Page MenuHomeHEPForge

No OneTemporary

Size
5 MB
Referenced Files
None
Subscribers
None
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -1,103 +1,104 @@
Makefile$
Makefile\.in$
\.deps$
\.libs$
\.l[ao]$
\.so$
\.so\.
\.o$
~$
\.pyc$
\.codereplace$
\.orig$
\.tar\.(gz|bz2)$
^autom4te.cache$
^config.herwig$
^config.log$
^config.status$
^configure$
^include/Herwig$
^Config/config.guess$
^Config/config.h$
^Config/config.h.in$
^Config/config.sub$
^Config/depcomp$
^Config/compile$
^Config/install-sh$
^Config/missing$
^Config/stamp-h1$
^Config/ar-lib$
^Contrib/make_makefiles.sh$
^Contrib/.*/.*\.(log|out|tex|run)$
^Utilities/hgstamp.inc$
^Doc/HerwigDefaults.in$
^Doc/refman-html$
^Doc/fixinterfaces.pl$
^Doc/refman.conf$
^Doc/refman.h$
^Doc/AllInterfaces.h$
^Doc/HerwigDefaults.rpo$
^Doc/Herwig-refman.tag$
^Doc/tagfileThePEG.tag$
^Doc/.*\.log$
^INSTALL$
^aclocal.m4$
^confdefs.h$
^conftest.c$
^conftest.err$
^include/done-all-links$
^libtool$
\.dirstamp$
^src/hgstamp.inc$
^src/herwigopts.h$
^src/herwigopts.c$
^src/defaults/Analysis.in$
^src/defaults/Decays.in$
^src/defaults/decayers.in$
^src/herwig-config$
^src/.*\.(run|tex|out|log|rpo|spc|top|dump|dot|aux|pdf|ps|png|svg|hepmc|dvi)$
^src/Makefile-UserModules$
^lib/done-all-links$
^lib/apple-fixes$
^src/defaults/PDF.in$
^src/defaults/done-all-links$
^src/tune$
^src/Herwig$
^src/Herwig-scratch$
^src/tests/.*\.(time|mult|Bmult|chisq)$
^Tests/.*/.*\.(top|ps|pyc|info|dat|pdf|png)$
^Tests/.*\.(top|ps|pyc|info|dat|pdf|png|log|out)$
^Tests/.*\.(top|run|tex|mult|Bmult|aida|yoda)$
^Tests/Rivet-.*$
^Tests/Rivet/(LEP|DIS|LHC|TVT|Star|BFactory|ISR|SppS)-.*\.in$
^Tests/plots$
^Tests/Herwig$
^Tests/.*index.html$
^Herwig\-
^Models/Feynrules/python/Makefile-FR$
^MatrixElement/Matchbox/External/MadGraph/mg2herwig.py$
^MatrixElement/Matchbox/Scales/MatchboxScale.cc$
^Utilities/Statistics/herwig-combinedistributions$
^Utilities/Statistics/herwig-combineruns$
^Utilities/Statistics/herwig-makedistributions$
^src/defaults/MatchboxDefaults.in$
^src/defaults/setup.gosam.in$
^src/Matchbox/LO-DefaultShower.in$
^src/Matchbox/LO-DipoleShower.in$
^src/Matchbox/LO-NoShower.in$
^src/Matchbox/MCatLO-DefaultShower.in$
^src/Matchbox/MCatLO-DipoleShower.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/Matchbox/done-all-links$
^src/snippets/done-all-links$
^Utilities/XML/xml_test$
^Utilities/utilities_test$
^Utilities/versionstring.h$
test\.(log|trs)$
test-suite\.log$
^Config/test-driver$
param_card\.dat$
+__all.cc$
diff --git a/API/HerwigAPI.cc b/API/HerwigAPI.cc
new file mode 100644
--- /dev/null
+++ b/API/HerwigAPI.cc
@@ -0,0 +1,316 @@
+// -*- C++ -*-
+//
+// 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 "HerwigAPI.h"
+#include "HerwigUI.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/Handlers/StandardEventHandler.h"
+
+#include <iostream>
+#include <sstream>
+
+#include <unistd.h>
+#include <sys/wait.h>
+
+#include <boost/filesystem.hpp>
+
+#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);
+
+ void HerwigGenericRead(const Herwig::HerwigUI & ui);
+ ThePEG::EGPtr HerwigGenericRun(const Herwig::HerwigUI & ui,
+ bool prepareOnly = false);
+}
+
+namespace Herwig {
+ namespace API {
+
+ void init(const HerwigUI & ui) {
+ setSearchPaths(ui, false);
+ SamplerBase::setRunLevel(SamplerBase::InitMode);
+
+ string infile = ui.inputfile();
+
+ // If status is INIT, we need an infile name / runname
+ if (infile.empty())
+ infile = "HerwigDefaults.in";
+
+ breakThePEG();
+ {
+# ifdef HERWIG_PKGLIBDIR
+ DynamicLoader::appendPath(HERWIG_PKGLIBDIR);
+# endif
+# ifdef THEPEG_PKGLIBDIR
+ DynamicLoader::appendPath(THEPEG_PKGLIBDIR);
+# endif
+ 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 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 mergegrids(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() ) 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> ");
+ }
+ }
+
+ 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();
+ }
+
+ if ( ui.integrationJob() && ui.jobs() > 1 ) {
+ ui.errStream() << "parallel event generation is not applicable to integrate\n";
+ ui.quit();
+ }
+
+ 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();
+ 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() ) 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() ) 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() ) ui.outStream() << "PID " << child
+ << " killed by signal " << WTERMSIG(status)
+ << std::endl;
+ }
+ }
+ if (! cleanrun) {
+ ui.quit();
+ }
+ }
+
+ return eg;
+
+ }
+}
+
+
diff --git a/API/HerwigAPI.h b/API/HerwigAPI.h
new file mode 100644
--- /dev/null
+++ b/API/HerwigAPI.h
@@ -0,0 +1,77 @@
+// -*- C++ -*-
+//
+// 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. 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 integrate mode
+ */
+ void integrate(const HerwigUI &);
+
+ /**
+ * Herwig mergegrids mode
+ */
+ void mergegrids(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 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/API/HerwigUI.h b/API/HerwigUI.h
new file mode 100644
--- /dev/null
+++ b/API/HerwigUI.h
@@ -0,0 +1,107 @@
+// -*- C++ -*-
+//
+// 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;
+
+ /// Repository name to operate on
+ virtual std::string repository() const = 0;
+
+ /// Name of the file to be read
+ virtual std::string inputfile() const = 0;
+
+ /// Name of the setup file to be read, to modify the repository
+ virtual std::string setupfile() const = 0;
+
+ /// Try to resume execution from an earlier interrupted run.
+ virtual bool resume() const = 0;
+
+ /// Require verbose progress markers
+ virtual bool tics() const = 0;
+
+ /// A user-defined tag to append to the run name.
+ virtual std::string tag() 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 prepended to the search path.
+ virtual const std::vector<std::string> & prependReadDirectories() 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;
+
+ /// The number of events to generate
+ virtual long N() const = 0;
+
+ /// The seed to use
+ virtual int seed() const = 0;
+
+ /// The number of jobs to fork
+ virtual int jobs() const = 0;
+
+ /// 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,12 @@
+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
+libHerwigAPI_la_CPPFLAGS = $(AM_CPPFLAGS) \
+-DHERWIG_PKGDATADIR="\"$(pkgdatadir)\"" \
+-DHERWIG_PKGLIBDIR="\"$(pkglibdir)\"" \
+-DTHEPEG_PKGLIBDIR="\"$(THEPEGLIBPATH)\""
\ No newline at end of file
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/Analysis/BasicConsistency.cc b/Analysis/BasicConsistency.cc
--- a/Analysis/BasicConsistency.cc
+++ b/Analysis/BasicConsistency.cc
@@ -1,323 +1,322 @@
// -*- C++ -*-
//
// BasicConsistency.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 BasicConsistency class.
//
#include "BasicConsistency.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/EventRecord/Event.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig/Utilities/EnumParticles.h"
#include "ThePEG/PDT/DecayMode.h"
using namespace Herwig;
using namespace ThePEG;
BasicConsistency::BasicConsistency()
: _epsmom(ZERO),_checkquark(true), _checkcharge(true),
_checkcluster(true), _checkBR(true),
_absolutemomentumtolerance(1*MeV), _relativemomentumtolerance(1e-5)
{}
IBPtr BasicConsistency::clone() const {
return new_ptr(*this);
}
IBPtr BasicConsistency::fullclone() const {
return new_ptr(*this);
}
void BasicConsistency::analyze(tEventPtr event, long, int, int) {
bool writeEvent=false;
set<tcPPtr> particles;
event->selectFinalState(inserter(particles));
int charge(-event->incoming().first->dataPtr()->iCharge()
-event->incoming().second->dataPtr()->iCharge());
Lorentz5Momentum
ptotal(-event->incoming().first->momentum()
-event->incoming().second->momentum());
const Energy beamenergy = ptotal.m();
for(set<tcPPtr>::const_iterator it = particles.begin();
it != particles.end(); ++it) {
if (_checkquark && (*it)->coloured()) {
cerr << "Had quarks in final state in event "
<< event->number()
<< '\n';
generator()->log() << "Had quarks in final state in event "
<< event->number() << '\n';
writeEvent = true;
}
else if( _checkcluster && (**it).id()==ParticleID::Cluster) {
cerr << "Had clusters in final state in event "
<< event->number()
<< '\n';
generator()->log() << "Had clusters in final state in event "
<< event->number() << '\n';
writeEvent = true;
}
charge += (*it)->dataPtr()->iCharge();
ptotal += (*it)->momentum();
bool problem=false;
LorentzDistance test;
for(unsigned int ix=0;ix<5;++ix) {
switch (ix) {
case 0:
test = (*it)->vertex();
break;
case 1:
test = (*it)->labVertex();
break;
case 2:
test = (*it)->decayVertex();
break;
case 3:
test = (*it)->labDecayVertex();
break;
case 4:
test = (*it)->lifeLength();
break;
}
- problem |=
- isnan(test.x()/mm) || isnan(test.y()/mm) ||
- isnan(test.z()/mm) || isnan(test.t()/mm) ||
- isinf(test.x()/mm) || isinf(test.y()/mm) ||
- isinf(test.z()/mm) || isinf(test.t()/mm);
+ problem |= ! ( isfinite(double(test.x()/mm)) &&
+ isfinite(double(test.y()/mm)) &&
+ isfinite(double(test.z()/mm)) &&
+ isfinite(double(test.t()/mm)) );
}
if(problem) {
generator()->log() << "Problem with position of " << **it << "\n"
<< (*it)->vertex()/mm << "\n"
<< (*it)->labVertex()/mm << "\n"
<< (*it)->decayVertex()/mm << "\n"
<< (*it)->labDecayVertex()/mm << "\n"
<< (*it)->lifeLength()/mm << "\n";
}
}
if ( _checkcharge && charge != 0 ) {
cerr << "\nCharge imbalance by "
<< charge
<< "in event "
<< event->number()
<< '\n';
generator()->log() << "Charge imbalance by "
<< charge
<< "in event "
<< event->number() << '\n';
writeEvent = true;
}
Energy mag = ptotal.m();
Energy ee = ptotal.e();
- if (isnan(mag/MeV)) {
+ if (std::isnan(double(mag/MeV))) {
cerr << "\nMomentum is 'nan'; " << ptotal/MeV
<< " MeV in event " << event->number() << '\n';
generator()->log() <<"\nMomentum is 'nan'; " << ptotal/MeV
<< " MeV in event " << event->number() << '\n';
writeEvent = true;
}
const Energy epsilonmax = max( _absolutemomentumtolerance,
_relativemomentumtolerance * beamenergy );
if (abs(mag) > epsilonmax || abs(ee) > epsilonmax) {
cerr << "\nMomentum imbalance by " << ptotal/MeV
<< " MeV in event " << event->number() << '\n';
generator()->log() <<"\nMomentum imbalance by " << ptotal/MeV
<< " MeV in event " << event->number() << '\n';
writeEvent = true;
}
if (abs(mag) > _epsmom)
_epsmom = abs(mag);
if (abs(ee) > _epsmom)
_epsmom = abs(ee);
if (abs(ptotal.x()) > _epsmom)
_epsmom = abs(ptotal.x());
if (abs(ptotal.y()) > _epsmom)
_epsmom = abs(ptotal.y());
if (abs(ptotal.z()) > _epsmom)
_epsmom = abs(ptotal.z());
particles.clear();
event->select(inserter(particles), ThePEG::AllSelector());
for(set<tcPPtr>::const_iterator it = particles.begin();
it != particles.end(); ++it) {
bool problem=false;
LorentzDistance test;
for(unsigned int ix=0;ix<5;++ix) {
switch (ix) {
case 0:
test = (*it)->vertex();
break;
case 1:
test = (*it)->labVertex();
break;
case 2:
test = (*it)->decayVertex();
break;
case 3:
test = (*it)->labDecayVertex();
break;
case 4:
test = (*it)->lifeLength();
break;
}
- problem |= isnan(test.m2()/mm/mm) || isinf(test.m2()/mm/mm);
+ problem |= ( ! isfinite(double(test.m2()/mm/mm)) );
}
if(problem) {
generator()->log() << "Problem with position of " << **it << "\n"
<< (*it)->vertex()/mm << "\n"
<< (*it)->labVertex()/mm << "\n"
<< (*it)->decayVertex()/mm << "\n"
<< (*it)->labDecayVertex()/mm << "\n"
<< (*it)->lifeLength()/mm << "\n";
writeEvent=true;
}
}
if(writeEvent) generator()->log() << *event;
}
void BasicConsistency::persistentOutput(PersistentOStream & os) const {
os << _checkquark << _checkcharge << _checkcluster << _checkBR
<< ounit(_absolutemomentumtolerance,MeV) << _relativemomentumtolerance;
}
void BasicConsistency::persistentInput(PersistentIStream & is, int) {
is >> _checkquark >> _checkcharge >> _checkcluster >> _checkBR
>> iunit(_absolutemomentumtolerance,MeV) >> _relativemomentumtolerance;
}
ClassDescription<BasicConsistency> BasicConsistency::initBasicConsistency;
// Definition of the static class description member.
void BasicConsistency::Init() {
static ClassDocumentation<BasicConsistency> documentation
("The BasicConsistency analysis handler checks for"
" momentum and charge conservation.");
static Switch<BasicConsistency,bool> interfaceCheckQuark
("CheckQuark",
"Check whether there are quarks in the final state",
&BasicConsistency::_checkquark, true, false, false);
static SwitchOption interfaceCheckQuarkCheck
(interfaceCheckQuark,
"Yes",
"Check for quarks",
true);
static SwitchOption interfaceCheckQuarkNoCheck
(interfaceCheckQuark,
"No",
"Don't check for quarks",
false);
static Switch<BasicConsistency,bool> interfaceCheckCharge
("CheckCharge",
"Check whether charge is conserved",
&BasicConsistency::_checkcharge, true, false, false);
static SwitchOption interfaceCheckChargeCheck
(interfaceCheckCharge,
"Yes",
"Check charge conservation",
true);
static SwitchOption interfaceCheckChargeNoCheck
(interfaceCheckCharge,
"No",
"Don't check charge conservation",
false);
static Switch<BasicConsistency,bool> interfaceCheckCluster
("CheckCluster",
"Check whether there are clusters in the final state",
&BasicConsistency::_checkcluster, true, false, false);
static SwitchOption interfaceCheckClusterCheck
(interfaceCheckCluster,
"Yes",
"Check for clusters",
true);
static SwitchOption interfaceCheckClusterNoCheck
(interfaceCheckCluster,
"No",
"Don't check for clusters",
false);
static Switch<BasicConsistency,bool> interfaceCheckBranchingRatios
("CheckBranchingRatios",
"Check whether the branching ratios of the particles add up to one.",
&BasicConsistency::_checkBR, true, false, false);
static SwitchOption interfaceCheckBranchingRatiosYes
(interfaceCheckBranchingRatios,
"Yes",
"Perform the check",
true);
static SwitchOption interfaceCheckBranchingRatiosNo
(interfaceCheckBranchingRatios,
"No",
"Don't perform the check",
false);
static Parameter<BasicConsistency,Energy> interfaceAbsoluteMomentumTolerance
("AbsoluteMomentumTolerance",
"The value of the momentum imbalance above which warnings are issued/MeV.\n"
"Final tolerance is the larger of AbsoluteMomentumTolerance and\n"
"RelativeMomentumTolerance*beam energy.",
&BasicConsistency::_absolutemomentumtolerance, MeV, 1*MeV, ZERO, 1e10*GeV,
false, false, true);
static Parameter<BasicConsistency,double> interfaceRelativeMomentumTolerance
("RelativeMomentumTolerance",
"The value of the momentum imbalance as a fraction of the beam energy\n"
"above which warnings are issued.\n"
"Final tolerance is the larger of AbsoluteMomentumTolerance and\n"
"RelativeMomentumTolerance*beam energy.",
&BasicConsistency::_relativemomentumtolerance, 1e-5, 0.0, 1.0,
false, false, true);
}
void BasicConsistency::dofinish() {
AnalysisHandler::dofinish();
cout << "\nBasicConsistency: maximum 4-momentum violation: "
<< _epsmom/MeV << " MeV\n";
}
void BasicConsistency::doinitrun() {
AnalysisHandler::doinitrun();
static double eps=1e-12;
for(ParticleMap::const_iterator it=generator()->particles().begin();
it!=generator()->particles().end();++it) {
if(it->second->stable()) continue;
double total(0.);
for(DecaySet::const_iterator dit=it->second->decayModes().begin();
dit!=it->second->decayModes().end();++dit) {
if((**dit).on()) total +=(**dit).brat();
}
if(abs(total-1.)>eps) {
cerr << "Warning: Total BR for "
<< it->second->PDGName()
<< " does not add up to 1. sum = " << total << "\n";
}
}
}
diff --git a/Analysis/JetsPlusAnalysis.cc b/Analysis/JetsPlusAnalysis.cc
--- a/Analysis/JetsPlusAnalysis.cc
+++ b/Analysis/JetsPlusAnalysis.cc
@@ -1,363 +1,363 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the JetsPlusAnalysis class.
//
#include "JetsPlusAnalysis.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/EventRecord/SubProcess.h"
#include "ThePEG/EventRecord/SubProcessGroup.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Handlers/EventHandler.h"
#include "ThePEG/Handlers/StandardEventHandler.h"
#include "Herwig/Sampling/GeneralSampler.h"
#include "Herwig/Utilities/XML/ElementIO.h"
using namespace Herwig;
JetsPlusAnalysis::JetsPlusAnalysis()
: theIsShowered(false) {}
JetsPlusAnalysis::~JetsPlusAnalysis() {}
#ifndef LWH_AIAnalysisFactory_H
#ifndef LWH
#define LWH ThePEGLWH
#endif
#include "ThePEG/Analysis/LWH/AnalysisFactory.h"
#endif
struct SortPt {
inline bool operator()(const LorentzMomentum& a,
const LorentzMomentum& b) const {
return a.perp() > b.perp();
}
};
void JetsPlusAnalysis::reconstructJets(const ParticleVector& parts) {
tcPDVector outType;
vector<LorentzMomentum> outMomenta;
for ( ParticleVector::const_iterator p = parts.begin();
p != parts.end(); ++p ) {
outType.push_back((**p).dataPtr());
outMomenta.push_back((**p).momentum());
}
jetFinder()->cluster(outType, outMomenta,
tcCutsPtr(), tcPDPtr(),tcPDPtr());
sort(outMomenta.begin(),outMomenta.end(),SortPt());
for ( vector<Ptr<JetRegion>::ptr>::iterator j =
theJetRegions.begin(); j != theJetRegions.end(); ++j )
(**j).reset();
for ( size_t k = 0; k < outMomenta.size(); ++k ) {
for ( vector<Ptr<JetRegion>::ptr>::const_iterator r = jetRegions().begin();
r != jetRegions().end(); ++r ) {
if ( (**r).matches(tCutsPtr(),k+1,outMomenta[k])) {
jetMomentum(k+1) = outMomenta[k];
break;
}
}
}
}
void JetsPlusAnalysis::analyze(ParticleVector& parts, long id, double weight) {
clear();
reconstructHardObjects(parts);
reconstructJets(parts);
for ( map<string,LorentzMomentum>::const_iterator h = theHardObjects.begin();
h != theHardObjects.end(); ++h ) {
hardObjectProperties(h->first).count(h->second,weight,id);
map<string,LorentzMomentum>::const_iterator g = h; ++g;
for ( ; g != theHardObjects.end(); ++g ) {
hardPairProperties(h->first,g->first).count(h->second,g->second,weight,id);
}
}
unsigned int njets = 0;
Energy jetSummedPerp = ZERO;
double jetSummedRapidity = 0.0;
double jetSummedPhi = 0.0;
Energy jetSummedM = ZERO;
nJetsInclusive().count(Statistics::EventContribution(njets,weight,0.0),id);
if ( njets == theJets.size() )
nJetsExclusive().count(Statistics::EventContribution(njets,weight,0.0),id);
for ( map<unsigned int,LorentzMomentum>::const_iterator h = theJets.begin();
h != theJets.end(); ++h ) {
njets += 1;
jetProperties(h->first).count(h->second,weight,id);
jetInclusiveProperties().count(h->second,weight,id);
nJetsInclusive().count(Statistics::EventContribution(njets,weight,0.0),id);
if ( njets == theJets.size() ) {
exclusiveJetProperties(h->first).count(h->second,weight,id);
nJetsExclusive().count(Statistics::EventContribution(njets,weight,0.0),id);
}
jetSummedPerp += h->second.perp();
jetSummedRapidity += h->second.rapidity();
jetSummedPhi += h->second.phi();
jetSummedM += h->second.m();
map<unsigned int,LorentzMomentum>::const_iterator g = h; ++g;
for ( ; g != theJets.end(); ++g ) {
jetPairProperties(h->first,g->first).count(h->second,g->second,weight,id);
map<unsigned int,LorentzMomentum>::const_iterator g1 = g; ++g1;
for ( ; g1 != theJets.end(); ++g1 ) {
LorentzMomentum p123 =
h->second + g->second + g1->second;
threeJetProperties(h->first,g->first,g1->first).count(p123,weight,id);
map<unsigned int,LorentzMomentum>::const_iterator g2 = g1; ++g2;
for ( ; g2 != theJets.end(); ++g2 ) {
LorentzMomentum p1234 =
h->second + g->second + g1->second + g2->second;
fourJetProperties(h->first,g->first,g1->first,g2->first).count(p1234,weight,id);
}
}
}
}
if ( njets > 0 )
jetSummedProperties().count(jetSummedPerp,jetSummedRapidity,
jetSummedPhi,jetSummedM,
weight,id);
if ( njets > 0 )
jetAverageProperties().count(jetSummedPerp/njets,jetSummedRapidity/njets,
jetSummedPhi/njets,jetSummedM/njets,
weight,id);
for ( map<string,LorentzMomentum>::const_iterator h = theHardObjects.begin();
h != theHardObjects.end(); ++h ) {
for ( map<unsigned int,LorentzMomentum>::const_iterator g = theJets.begin();
g != theJets.end(); ++g ) {
jetHardPairProperties(g->first,h->first).count(g->second,h->second,weight,id);
}
}
analyzeSpecial(id,weight);
}
void JetsPlusAnalysis::analyze(tEventPtr event, long ieve, int, int) {
// doing nothing
// AnalysisHandler::analyze(event, ieve, loop, state);
Ptr<StandardEventHandler>::tptr seh =
dynamic_ptr_cast<Ptr<StandardEventHandler>::tptr>(generator()->eventHandler());
Ptr<GeneralSampler>::tptr sampler =
dynamic_ptr_cast<Ptr<GeneralSampler>::tptr>(seh->sampler());
double norm = sampler->maxXSec()/picobarn;
if ( !theIsShowered ) {
tSubProPtr sub = event->primarySubProcess();
Ptr<SubProcessGroup>::tptr grp =
dynamic_ptr_cast<Ptr<SubProcessGroup>::tptr>(sub);
ParticleVector hfs = sub->outgoing();
analyze(hfs,ieve,norm*event->weight()*sub->groupWeight());
if ( grp ) {
for ( SubProcessVector::const_iterator s = grp->dependent().begin();
s != grp->dependent().end(); ++s ) {
ParticleVector fs = (**s).outgoing();
analyze(fs,ieve,norm*event->weight()*(**s).groupWeight());
}
}
} else {
ParticleVector fs;
event->getFinalState(fs);
analyze(fs,ieve,norm*event->weight());
}
}
void JetsPlusAnalysis::dofinish() {
AnalysisHandler::dofinish();
Ptr<StandardEventHandler>::tptr seh =
dynamic_ptr_cast<Ptr<StandardEventHandler>::tptr>(generator()->eventHandler());
Ptr<GeneralSampler>::tptr sampler =
dynamic_ptr_cast<Ptr<GeneralSampler>::tptr>(seh->sampler());
unsigned long attemptedPoints = sampler->attempts();
double sumOfWeights = sampler->sumWeights();
double sumOfSquaredWeights = sampler->sumWeights2();
CrossSection maxXSection = sampler->maxXSec();
XML::Element elem(XML::ElementTypes::Element,"Run");
elem.appendAttribute("name",generator()->runName());
elem.appendAttribute("attemptedPoints",attemptedPoints);
elem.appendAttribute("sumOfWeights",sumOfWeights*maxXSection/picobarn);
elem.appendAttribute("sumOfSquaredWeights",sumOfSquaredWeights*sqr(maxXSection/picobarn));
XML::Element xhistos(XML::ElementTypes::Element,"Histograms");
for ( map<string,ObjectProperties>::iterator h = theHardObjectProperties.begin();
h != theHardObjectProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
for ( map<unsigned int,ObjectProperties>::iterator h = theJetProperties.begin();
h != theJetProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
for ( map<unsigned int,ObjectProperties>::iterator h = theExclusiveJetProperties.begin();
h != theExclusiveJetProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
if ( !theJetInclusiveProperties.pt.bins().empty() ) {
theJetInclusiveProperties.finalize(xhistos);
}
if ( !theJetSummedProperties.pt.bins().empty() ) {
theJetSummedProperties.finalize(xhistos);
}
if ( !theJetAverageProperties.pt.bins().empty() ) {
theJetAverageProperties.finalize(xhistos);
}
if ( !theNJetsInclusive.bins().empty() ) {
theNJetsInclusive.finalize();
xhistos.append(theNJetsInclusive.toXML());
}
if ( !theNJetsExclusive.bins().empty() ) {
theNJetsExclusive.finalize();
xhistos.append(theNJetsExclusive.toXML());
}
for ( map<pair<string,string>,PairProperties>::iterator h = theHardPairProperties.begin();
h != theHardPairProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
for ( map<pair<unsigned int,unsigned int>,PairProperties>::iterator h = theJetPairProperties.begin();
h != theJetPairProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
for ( map<pair<unsigned int,string>,PairProperties>::iterator h = theJetHardPairProperties.begin();
h != theJetHardPairProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
- for ( map<boost::tuple<unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator h =
+ for ( map<std::tuple<unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator h =
theThreeJetProperties.begin(); h != theThreeJetProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
- for ( map<boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator h =
+ for ( map<std::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator h =
theFourJetProperties.begin(); h != theFourJetProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
finalize(xhistos);
elem.append(xhistos);
string fname = name() + ".xml";
ofstream runXML(fname.c_str());
runXML << setprecision(16);
XML::ElementIO::put(elem,runXML);
}
IBPtr JetsPlusAnalysis::clone() const {
return new_ptr(*this);
}
IBPtr JetsPlusAnalysis::fullclone() const {
return new_ptr(*this);
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void JetsPlusAnalysis::persistentOutput(PersistentOStream & os) const {
os << theIsShowered << theJetFinder << theJetRegions;
}
void JetsPlusAnalysis::persistentInput(PersistentIStream & is, int) {
is >> theIsShowered >> theJetFinder >> theJetRegions;
}
// *** 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<JetsPlusAnalysis,AnalysisHandler>
describeHerwigJetsPlusAnalysis("Herwig::JetsPlusAnalysis", "JetCuts.so HwJetsAnalysis.so");
void JetsPlusAnalysis::Init() {
static ClassDocumentation<JetsPlusAnalysis> documentation
("There is no documentation for the JetsPlusAnalysis class");
static Reference<JetsPlusAnalysis,JetFinder> interfaceJetFinder
("JetFinder",
"",
&JetsPlusAnalysis::theJetFinder, false, false, true, false, false);
static RefVector<JetsPlusAnalysis,JetRegion> interfaceJetRegions
("JetRegions",
"",
&JetsPlusAnalysis::theJetRegions, -1, false, false, true, false, false);
static Switch<JetsPlusAnalysis,bool> interfaceIsShowered
("IsShowered",
"",
&JetsPlusAnalysis::theIsShowered, false, false, false);
static SwitchOption interfaceIsShoweredYes
(interfaceIsShowered,
"Yes",
"",
true);
static SwitchOption interfaceIsShoweredNo
(interfaceIsShowered,
"No",
"",
false);
}
diff --git a/Analysis/JetsPlusAnalysis.h b/Analysis/JetsPlusAnalysis.h
--- a/Analysis/JetsPlusAnalysis.h
+++ b/Analysis/JetsPlusAnalysis.h
@@ -1,662 +1,659 @@
// -*- C++ -*-
#ifndef Herwig_JetsPlusAnalysis_H
#define Herwig_JetsPlusAnalysis_H
//
// This is the declaration of the JetsPlusAnalysis class.
//
#include "ThePEG/Handlers/AnalysisHandler.h"
#include "ThePEG/Cuts/JetFinder.h"
#include "ThePEG/Cuts/JetRegion.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "Herwig/Utilities/Statistics/Histogram.h"
-#include <boost/tuple/tuple.hpp>
-#include <boost/tuple/tuple_comparison.hpp>
-
namespace Herwig {
using namespace ThePEG;
/**
* Here is the documentation of the JetsPlusAnalysis class.
*
* @see \ref JetsPlusAnalysisInterfaces "The interfaces"
* defined for JetsPlusAnalysis.
*/
class JetsPlusAnalysis: public AnalysisHandler {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
JetsPlusAnalysis();
/**
* The destructor.
*/
virtual ~JetsPlusAnalysis();
//@}
public:
/** @name Virtual functions required by the AnalysisHandler class. */
//@{
/**
* Analyze a given Event. Note that a fully generated event
* may be presented several times, if it has been manipulated in
* between. The default version of this function will call transform
* to make a lorentz transformation of the whole event, then extract
* all final state particles and call analyze(tPVector) of this
* analysis object and those of all associated analysis objects. The
* default version will not, however, do anything on events which
* have not been fully generated, or have been manipulated in any
* way.
* @param event pointer to the Event to be analyzed.
* @param ieve the event number.
* @param loop the number of times this event has been presented.
* If negative the event is now fully generated.
* @param state a number different from zero if the event has been
* manipulated in some way since it was last presented.
*/
virtual void analyze(tEventPtr event, long ieve, int loop, int state);
//@}
protected:
/**
* Analyze one subprocess, given the event number it belongs to
*/
void analyze(ParticleVector&, long, double);
/**
* Clear the hard objects and jets for the next event
*/
void clear() {
theHardObjects.clear();
theJets.clear();
}
/**
* Reconstruct the desired electroweak objects and fill the
* respective momenta. Remove the reconstructed particles from the
* list.
*/
virtual void reconstructHardObjects(ParticleVector&) {}
/**
* Set the momentum of the indicated electroweak object.
*/
LorentzMomentum& hardObjectMomentum(const string& id) {
return theHardObjects[id];
}
/**
* Reconstruct the jets and fill the respective momenta.
*/
virtual void reconstructJets(const ParticleVector&);
/**
* The jet finder to use
*/
Ptr<JetFinder>::tptr jetFinder() const {
return theJetFinder;
}
/**
* The jet regions to match.
*/
const vector<Ptr<JetRegion>::ptr>& jetRegions() const { return theJetRegions; }
/**
* Return the number of matched jets
*/
unsigned int nJets() const { return theJets.size(); }
/**
* Set the momentum of the indicated jet.
*/
LorentzMomentum& jetMomentum(const unsigned int id) {
return theJets[id];
}
protected:
/**
* Finalize this object. Called in the run phase just after a
* run has ended. Used eg. to write out statistics.
*/
virtual void dofinish();
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).
protected:
/**
* Collection of object histograms; ranges are adjusted to the
* maximum, so range constraints and rebinning can be applied later.
*/
struct ObjectProperties {
/**
* Transverse momentum
*/
Statistics::Histogram pt;
Statistics::Histogram pt_logx;
/**
* Rapidity
*/
Statistics::Histogram y;
/**
* Azimuth
*/
Statistics::Histogram phi;
/**
* Mass
*/
Statistics::Histogram mass;
/**
* Default constructor
*/
ObjectProperties() {}
/**
* Construct given Ecm
*/
ObjectProperties(const string& name, Energy)
: pt(name + "Pt",Statistics::Histogram::regularBinEdges(0,1000,1000),true,false),
pt_logx(name + "PtLogX",Statistics::Histogram::logBinEdges(0.1,1000,1000),true,false),
y(name + "Y",Statistics::Histogram::regularBinEdges(-6,6,120),false,false),
phi(name + "Phi",Statistics::Histogram::regularBinEdges(-Constants::pi,Constants::pi,32),
make_pair(-Constants::pi,Constants::pi)),
mass(name + "Mass",Statistics::Histogram::regularBinEdges(0,1000,1000),true,false) {}
/**
* Count given momentum, weight and id
*/
void count(const LorentzMomentum& p, double weight, unsigned int id) {
pt.count(Statistics::EventContribution(p.perp()/GeV,weight,1.),id);
pt_logx.count(Statistics::EventContribution(p.perp()/GeV,weight,1.),id);
y.count(Statistics::EventContribution(p.rapidity(),weight,0.1),id);
phi.count(Statistics::EventContribution(p.phi(),weight,0.1),id);
mass.count(Statistics::EventContribution(p.m()/GeV,weight,1.),id);
}
/**
* Count given momentum components, weight and id
*/
void count(Energy perp, double rapidity,
double xphi, Energy m,
double weight, unsigned int id) {
pt.count(Statistics::EventContribution(perp/GeV,weight,1.),id);
pt_logx.count(Statistics::EventContribution(perp/GeV,weight,1.),id);
y.count(Statistics::EventContribution(rapidity,weight,0.1),id);
phi.count(Statistics::EventContribution(xphi,weight,0.1),id);
mass.count(Statistics::EventContribution(m/GeV,weight,1.),id);
}
/**
* Convert to XML
*/
void finalize(XML::Element& elem) {
pt.finalize(); elem.append(pt.toXML());
pt_logx.finalize(); elem.append(pt_logx.toXML());
y.finalize(); elem.append(y.toXML());
phi.finalize(); elem.append(phi.toXML());
mass.finalize(); elem.append(mass.toXML());
}
};
/**
* Collection of pair histograms; ranges are adjusted to the
* maximum, so range constraints and rebinning can be applied later.
*/
struct PairProperties
: public ObjectProperties {
/**
* Calculate deltaPhi
*/
static double dPhi(const LorentzMomentum& a,
const LorentzMomentum& b){
double phi1 = a.phi();
double phi2 = b.phi();
double diff=phi1-phi2;
if(diff<-Constants::pi){
diff+=(2.0*Constants::pi);
}
else if (diff>Constants::pi){
diff-=(2.0*Constants::pi);
}
return diff;
}
/**
* Calculate deltaY
*/
static double dY(const LorentzMomentum& a,
const LorentzMomentum& b){
return abs(a.rapidity()-b.rapidity());
}
/**
* Calculate deltaR
*/
static double dR(const LorentzMomentum& a,
const LorentzMomentum& b){
return sqrt(sqr(dPhi(a,b))+sqr(dY(a,b)));
}
/**
* Calculate ydoty
*/
static double yy(const LorentzMomentum& a,
const LorentzMomentum& b){
double ya = a.rapidity();
double yb = b.rapidity();
double yres = sqrt(abs(ya*yb));
return ya*yb < 0. ? -yres : yres;
}
/**
* Delta y
*/
Statistics::Histogram deltaY;
/**
* Delta phi
*/
Statistics::Histogram deltaPhi;
/**
* Delta phi
*/
Statistics::Histogram deltaR;
/**
* Product of the rapidities
*/
Statistics::Histogram yDotY;
/**
* Default constructor
*/
PairProperties()
: ObjectProperties() {}
/**
* Construct given Ecm
*/
PairProperties(const string& name, Energy ecm)
: ObjectProperties(name,ecm),
deltaY(name + "DeltaY",Statistics::Histogram::regularBinEdges(0,6,60),true,false),
deltaPhi(name + "DeltaPhi",Statistics::Histogram::regularBinEdges(-Constants::pi,Constants::pi,32),
make_pair(-Constants::pi,Constants::pi)),
deltaR(name + "DeltaR",Statistics::Histogram::regularBinEdges(0,10,100),true,false),
yDotY(name + "YDotY",Statistics::Histogram::regularBinEdges(-6,6,120),false,false) {}
/**
* Count given momentum, weight and id
*/
void count(const LorentzMomentum& p, const LorentzMomentum& q, double weight, unsigned int id) {
ObjectProperties::count(p+q,weight,id);
deltaY.count(Statistics::EventContribution(dY(p,q),weight,0.1),id);
deltaPhi.count(Statistics::EventContribution(dPhi(p,q),weight,0.1),id);
deltaR.count(Statistics::EventContribution(dR(p,q),weight,0.1),id);
yDotY.count(Statistics::EventContribution(yy(p,q),weight,0.1),id);
}
/**
* Convert to XML
*/
void finalize(XML::Element& elem) {
ObjectProperties::finalize(elem);
deltaY.finalize(); elem.append(deltaY.toXML());
deltaPhi.finalize(); elem.append(deltaPhi.toXML());
deltaR.finalize(); elem.append(deltaR.toXML());
yDotY.finalize(); elem.append(yDotY.toXML());
}
};
private:
/**
* Switch between fixed order and showered
*/
bool theIsShowered;
/**
* The jet finder to use
*/
Ptr<JetFinder>::ptr theJetFinder;
/**
* The jet regions to match.
*/
vector<Ptr<JetRegion>::ptr> theJetRegions;
/**
* The reconstructed hard objects.
*/
map<string,LorentzMomentum> theHardObjects;
/**
* The reconstructed jets
*/
map<unsigned int,LorentzMomentum> theJets;
/**
* Hard object properties
*/
map<string,ObjectProperties> theHardObjectProperties;
/**
* Jet properties
*/
map<unsigned int,ObjectProperties> theJetProperties;
/**
* Exclusive jet properties
*/
map<unsigned int,ObjectProperties> theExclusiveJetProperties;
/**
* Jet-inclusive properties
*/
ObjectProperties theJetInclusiveProperties;
/**
* Jet-summed properties
*/
ObjectProperties theJetSummedProperties;
/**
* Jet-average properties
*/
ObjectProperties theJetAverageProperties;
/**
* Inclusive jet multiplicities
*/
Statistics::Histogram theNJetsInclusive;
/**
* Exclusive jet multiplicities
*/
Statistics::Histogram theNJetsExclusive;
/**
* Hard object pair properties
*/
map<pair<string,string>,PairProperties> theHardPairProperties;
/**
* Jet pair properties
*/
map<pair<unsigned int,unsigned int>,PairProperties> theJetPairProperties;
/**
* Jet/hard pair properties
*/
map<pair<unsigned int,string>,PairProperties> theJetHardPairProperties;
/**
* Trijet properties
*/
- map<boost::tuple<unsigned int,unsigned int,unsigned int>,ObjectProperties> theThreeJetProperties;
+ map<std::tuple<unsigned int,unsigned int,unsigned int>,ObjectProperties> theThreeJetProperties;
/**
* Fourjet properties
*/
- map<boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties> theFourJetProperties;
+ map<std::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties> theFourJetProperties;
protected:
/**
* Hard object properties
*/
ObjectProperties& hardObjectProperties(const string& id) {
map<string,ObjectProperties>::iterator h =
theHardObjectProperties.find(id);
if ( h != theHardObjectProperties.end() )
return h->second;
return
theHardObjectProperties[id] =
ObjectProperties(id,generator()->maximumCMEnergy());
}
/**
* Jet properties
*/
ObjectProperties& jetProperties(const unsigned int id) {
map<unsigned int,ObjectProperties>::iterator h =
theJetProperties.find(id);
if ( h != theJetProperties.end() )
return h->second;
ostringstream ids; ids << "Jet" << id;
return
theJetProperties[id] =
ObjectProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Exclusive jet properties
*/
ObjectProperties& exclusiveJetProperties(const unsigned int id) {
map<unsigned int,ObjectProperties>::iterator h =
theExclusiveJetProperties.find(id);
if ( h != theExclusiveJetProperties.end() )
return h->second;
ostringstream ids; ids << "ExclusiveJet" << id;
return
theExclusiveJetProperties[id] =
ObjectProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Jet-inclusive properties
*/
ObjectProperties& jetInclusiveProperties() {
if ( !theJetInclusiveProperties.pt.bins().empty() )
return theJetInclusiveProperties;
return
theJetInclusiveProperties =
ObjectProperties("JetInclusive",generator()->maximumCMEnergy());
}
/**
* Jet-summed properties
*/
ObjectProperties& jetSummedProperties() {
if ( !theJetSummedProperties.pt.bins().empty() )
return theJetSummedProperties;
return
theJetSummedProperties =
ObjectProperties("JetSummed",generator()->maximumCMEnergy());
}
/**
* Jet-average properties
*/
ObjectProperties& jetAverageProperties() {
if ( !theJetAverageProperties.pt.bins().empty() )
return theJetAverageProperties;
return
theJetAverageProperties =
ObjectProperties("JetAverage",generator()->maximumCMEnergy());
}
/**
* Inclusive jet multiplicities
*/
Statistics::Histogram& nJetsInclusive() {
if ( !theNJetsInclusive.bins().empty() )
return theNJetsInclusive;
return
theNJetsInclusive =
Statistics::Histogram("NJetsInclusive",
Statistics::Histogram::regularBinEdges(-0.5,theJetRegions.size()+0.5,
theJetRegions.size()+1),
true,true);
}
/**
* Exclusive jet multiplicities
*/
Statistics::Histogram& nJetsExclusive() {
if ( !theNJetsExclusive.bins().empty() )
return theNJetsExclusive;
return
theNJetsExclusive =
Statistics::Histogram("NJetsExclusive",
Statistics::Histogram::regularBinEdges(-0.5,theJetRegions.size()+0.5,
theJetRegions.size()+1),
true,true);
}
/**
* Hard object pair properties
*/
PairProperties& hardPairProperties(const string& id, const string& jd) {
map<pair<string,string>,PairProperties>::iterator h =
theHardPairProperties.find(make_pair(id,jd));
if ( h != theHardPairProperties.end() )
return h->second;
return theHardPairProperties[make_pair(id,jd)] =
PairProperties(id+jd,generator()->maximumCMEnergy());
}
/**
* Jet pair properties
*/
PairProperties& jetPairProperties(const unsigned int id, const unsigned int jd) {
map<pair<unsigned int,unsigned int>,PairProperties>::iterator h =
theJetPairProperties.find(make_pair(id,jd));
if ( h != theJetPairProperties.end() )
return h->second;
ostringstream ids; ids << "Jet" << id << jd;
return theJetPairProperties[make_pair(id,jd)] =
PairProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Jet/hard pair properties
*/
PairProperties& jetHardPairProperties(const unsigned int id, const string& jd) {
map<pair<unsigned int,string>,PairProperties>::iterator h =
theJetHardPairProperties.find(make_pair(id,jd));
if ( h != theJetHardPairProperties.end() )
return h->second;
ostringstream ids; ids << "Jet" << id << jd;
return theJetHardPairProperties[make_pair(id,jd)] =
PairProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Trijet properties
*/
ObjectProperties& threeJetProperties(const unsigned int id1, const unsigned int id2,
const unsigned int id3) {
- map<boost::tuple<unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator it =
- theThreeJetProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3));
+ map<std::tuple<unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator it =
+ theThreeJetProperties.find(std::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3));
if ( it != theThreeJetProperties.end() )
return it->second;
ostringstream ids;
ids << "Jet" << id1 << id2 << id3;
- return theThreeJetProperties[boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] =
+ return theThreeJetProperties[std::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] =
ObjectProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Fourjet properties
*/
ObjectProperties& fourJetProperties(const unsigned int id1, const unsigned int id2,
const unsigned int id3, const unsigned int id4) {
- map<boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator it =
- theFourJetProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4));
+ map<std::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator it =
+ theFourJetProperties.find(std::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4));
if ( it != theFourJetProperties.end() )
return it->second;
ostringstream ids;
ids << "Jet" << id1 << id2 << id3 << id4;
- return theFourJetProperties[boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4)] =
+ return theFourJetProperties[std::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4)] =
ObjectProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Perform any additional analysis required
*/
virtual void analyzeSpecial(long, double) {}
/**
* Append any additional histograms to the given histogram element
*/
virtual void finalize(XML::Element&) {}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
JetsPlusAnalysis & operator=(const JetsPlusAnalysis &);
};
}
#endif /* Herwig_JetsPlusAnalysis_H */
diff --git a/Analysis/LeptonsJetsAnalysis.cc b/Analysis/LeptonsJetsAnalysis.cc
--- a/Analysis/LeptonsJetsAnalysis.cc
+++ b/Analysis/LeptonsJetsAnalysis.cc
@@ -1,611 +1,611 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the LeptonsJetsAnalysis class.
//
#include "LeptonsJetsAnalysis.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/EventRecord/SubProcess.h"
#include "ThePEG/EventRecord/SubProcessGroup.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Handlers/EventHandler.h"
#include "ThePEG/Handlers/StandardEventHandler.h"
#include "Herwig/Sampling/GeneralSampler.h"
#include "Herwig/Utilities/XML/ElementIO.h"
using namespace Herwig;
LeptonsJetsAnalysis::LeptonsJetsAnalysis()
: theIsShowered(false), theApplyCuts(false) {}
LeptonsJetsAnalysis::~LeptonsJetsAnalysis() {}
#ifndef LWH_AIAnalysisFactory_H
#ifndef LWH
#define LWH ThePEGLWH
#endif
#include "ThePEG/Analysis/LWH/AnalysisFactory.h"
#endif
struct SortPt {
inline bool operator()(const LorentzMomentum& a,
const LorentzMomentum& b) const {
return a.perp() > b.perp();
}
};
struct SortId {
inline bool operator()(const pair<PID,LorentzMomentum>& a,
const pair<PID,LorentzMomentum>& b) const {
// sort by abs(pid); if equal, first particle, then antiparticle
// this puts pairs forming bosons next to each other
long p1 = a.first;
long p2 = b.first;
if (abs(p1)==abs(p2)) {
return p1 > p2;
} else {
return abs(p1) < abs(p2);
}
}
};
void LeptonsJetsAnalysis::reconstructJets(const ParticleVector& parts) {
tcPDVector outType;
vector<LorentzMomentum> outMomenta;
for ( ParticleVector::const_iterator p = parts.begin();
p != parts.end(); ++p ) {
outType.push_back((**p).dataPtr());
outMomenta.push_back((**p).momentum());
}
jetFinder()->cluster(outType, outMomenta,
tcCutsPtr(), tcPDPtr(),tcPDPtr());
sort(outMomenta.begin(),outMomenta.end(),SortPt());
for ( vector<Ptr<JetRegion>::ptr>::iterator j =
theJetRegions.begin(); j != theJetRegions.end(); ++j )
(**j).reset();
for ( size_t k = 0; k < outMomenta.size(); ++k ) {
for ( vector<Ptr<JetRegion>::ptr>::const_iterator r = jetRegions().begin();
r != jetRegions().end(); ++r ) {
if ( (**r).matches(tCutsPtr(),k+1,outMomenta[k])) {
jetMomentum(k+1) = outMomenta[k];
break;
}
}
}
}
void LeptonsJetsAnalysis::reconstructEWParticles(ParticleVector& parts) {
vector< pair<PID,LorentzMomentum> > partall;
vector<LorentzMomentum> partl, partnu, parth;
LorentzMomentum ptmiss = LorentzMomentum(ZERO,ZERO,ZERO,ZERO);
ParticleVector::iterator p = parts.begin();
while (p != parts.end()) {
PID pid = (**p).id();
if ( ( static_cast<long>(pid) == ParticleID::eminus ) ||
( static_cast<long>(pid) == ParticleID::eplus ) ||
( static_cast<long>(pid) == ParticleID::muminus ) ||
( static_cast<long>(pid) == ParticleID::muplus ) ||
( static_cast<long>(pid) == ParticleID::tauminus ) ||
( static_cast<long>(pid) == ParticleID::tauplus ) ) {
partall.push_back(pair<PID,LorentzMomentum>(pid,(**p).momentum()));
partl.push_back((**p).momentum());
p = parts.erase(p);
} else
if ( ( static_cast<long>(pid) == ParticleID::nu_e ) ||
( static_cast<long>(pid) == ParticleID::nu_ebar ) ||
( static_cast<long>(pid) == ParticleID::nu_mu ) ||
( static_cast<long>(pid) == ParticleID::nu_mubar ) ||
( static_cast<long>(pid) == ParticleID::nu_tau ) ||
( static_cast<long>(pid) == ParticleID::nu_taubar ) ) {
partall.push_back(pair<PID,LorentzMomentum>(pid,(**p).momentum()));
partnu.push_back((**p).momentum());
ptmiss += (**p).momentum();
p = parts.erase(p);
} else
if ( static_cast<long>(pid) == ParticleID::h0 ) {
partall.push_back(pair<PID,LorentzMomentum>(pid,(**p).momentum()));
parth.push_back((**p).momentum());
p = parts.erase(p);
} else
p++;
}
sort(partall.begin(),partall.end(),SortId());
sort(partl.begin(),partl.end(),SortPt());
sort(partnu.begin(),partnu.end(),SortPt());
sort(parth.begin(),parth.end(),SortPt());
// make missing transverse momentum transverse and also add as last entry in EWID
ptmiss.setE(ptmiss.perp());
ptmiss.setZ(0*GeV);
partall.push_back(pair<PID,LorentzMomentum>(ParticleID::nu_e,ptmiss));
for ( size_t k = 0; k < partall.size(); ++k )
eWIDMomentum(k+1) = partall[k].second;
for ( size_t k = 0; k < partl.size(); ++k )
chargedLeptonMomentum(k+1) = partl[k];
for ( size_t k = 0; k < partnu.size(); ++k )
neutrinoMomentum(k+1) = partnu[k];
for ( size_t k = 0; k < parth.size(); ++k )
higgsMomentum(k+1) = parth[k];
pTmissMomentum() = ptmiss;
}
void LeptonsJetsAnalysis::analyze(ParticleVector& parts, long id, double weight) {
clear();
reconstructEWParticles(parts);
reconstructJets(parts);
if ( theApplyCuts ) {
// VBF cuts
if ( nJets()<2 ) return;
if ( (jetMomentum(1)+jetMomentum(2)).m() < 600*GeV ) return;
if ( abs(jetMomentum(1).rapidity()-jetMomentum(2).rapidity()) < 3.6 ) return;
// if ( jetMomentum(1).rapidity()*jetMomentum(2).rapidity() > 0 ) return;
for ( map<unsigned int,LorentzMomentum>::const_iterator h = theChargedLeptons.begin();
h != theChargedLeptons.end(); ++h ) {
if ( h->second.perp() < 20*GeV ) return;
if ( abs(h->second.rapidity()) > 2.5 ) return;
}
}
unsigned int njets = 0;
Energy jetSummedPerp = ZERO;
double jetSummedRapidity = 0.0;
double jetSummedPhi = 0.0;
Energy jetSummedM = ZERO;
nJetsInclusive().count(Statistics::EventContribution(njets,weight,0.0),id);
if ( njets == theJets.size() )
nJetsExclusive().count(Statistics::EventContribution(njets,weight,0.0),id);
for ( map<unsigned int,LorentzMomentum>::const_iterator h = theJets.begin();
h != theJets.end(); ++h ) {
njets += 1;
jetProperties(h->first).count(h->second,weight,id);
jetInclusiveProperties().count(h->second,weight,id);
nJetsInclusive().count(Statistics::EventContribution(njets,weight,0.0),id);
if ( njets == theJets.size() ) {
exclusiveJetProperties(h->first).count(h->second,weight,id);
nJetsExclusive().count(Statistics::EventContribution(njets,weight,0.0),id);
}
jetSummedPerp += h->second.perp();
jetSummedRapidity += h->second.rapidity();
jetSummedPhi += h->second.phi();
jetSummedM += h->second.m();
map<unsigned int,LorentzMomentum>::const_iterator g = h; ++g;
for ( ; g != theJets.end(); ++g ) {
jetPairProperties(h->first,g->first).count(h->second,g->second,weight,id);
map<unsigned int,LorentzMomentum>::const_iterator g1 = g; ++g1;
for ( ; g1 != theJets.end(); ++g1 ) {
threeJetProperties(h->first,g->first,g1->first).count(h->second,g->second,g1->second,weight,id);
map<unsigned int,LorentzMomentum>::const_iterator g2 = g1; ++g2;
for ( ; g2 != theJets.end(); ++g2 ) {
LorentzMomentum p1234 =
h->second + g->second + g1->second + g2->second;
fourJetProperties(h->first,g->first,g1->first,g2->first).count(p1234,weight,id);
}
}
for ( map<unsigned int,LorentzMomentum>::const_iterator g1 = theEWIDs.begin();
g1 != theEWIDs.end(); ++g1 )
jetPairEWIDTripleProperties(h->first,g->first,g1->first).count(h->second,g->second,g1->second,weight,id);
for ( map<unsigned int,LorentzMomentum>::const_iterator g1 = theChargedLeptons.begin();
g1 != theChargedLeptons.end(); ++g1 )
jetPairChargedLeptonTripleProperties(h->first,g->first,g1->first).count(h->second,g->second,g1->second,weight,id);
for ( map<unsigned int,LorentzMomentum>::const_iterator g1 = theNeutrinos.begin();
g1 != theNeutrinos.end(); ++g1 )
jetPairNeutrinoTripleProperties(h->first,g->first,g1->first).count(h->second,g->second,g1->second,weight,id);
jetPairPTmissTripleProperties(h->first,g->first).count(h->second,g->second,pTmissMomentum(),weight,id);
for ( map<unsigned int,LorentzMomentum>::const_iterator g1 = theHiggs.begin();
g1 != theHiggs.end(); ++g1 )
jetPairHiggsTripleProperties(h->first,g->first,g1->first).count(h->second,g->second,g1->second,weight,id);
}
for ( map<unsigned int,LorentzMomentum>::const_iterator g = theEWIDs.begin();
g != theEWIDs.end(); ++g )
jetEWIDPairProperties(h->first,g->first).count(h->second,g->second,weight,id);
for ( map<unsigned int,LorentzMomentum>::const_iterator g = theChargedLeptons.begin();
g != theChargedLeptons.end(); ++g )
jetChargedLeptonPairProperties(h->first,g->first).count(h->second,g->second,weight,id);
for ( map<unsigned int,LorentzMomentum>::const_iterator g = theNeutrinos.begin();
g != theNeutrinos.end(); ++g )
jetNeutrinoPairProperties(h->first,g->first).count(h->second,g->second,weight,id);
jetPTmissPairProperties(h->first).count(h->second,pTmissMomentum(),weight,id);
for ( map<unsigned int,LorentzMomentum>::const_iterator g = theHiggs.begin();
g != theHiggs.end(); ++g )
jetHiggsPairProperties(h->first,g->first).count(h->second,g->second,weight,id);
}
if ( njets > 0 )
jetSummedProperties().count(jetSummedPerp,jetSummedRapidity,
jetSummedPhi,jetSummedM,
weight,id);
if ( njets > 0 )
jetAverageProperties().count(jetSummedPerp/njets,jetSummedRapidity/njets,
jetSummedPhi/njets,jetSummedM/njets,
weight,id);
for ( map<unsigned int,LorentzMomentum>::const_iterator h = theEWIDs.begin();
h != theEWIDs.end(); ++h ) {
eWIDProperties(h->first).count(h->second,weight,id);
map<unsigned int,LorentzMomentum>::const_iterator g = h; ++g;
for ( ; g != theEWIDs.end(); ++g ) {
eWIDPairProperties(h->first,g->first).count(h->second,g->second,weight,id);
map<unsigned int,LorentzMomentum>::const_iterator g1 = g; ++g1;
for ( ; g1 != theEWIDs.end(); ++g1 ) {
threeEWIDProperties(h->first,g->first,g1->first).count(h->second,g->second,g1->second,weight,id);
map<unsigned int,LorentzMomentum>::const_iterator g2 = g1; ++g2;
for ( ; g2 != theEWIDs.end(); ++g2 ) {
LorentzMomentum p1234 =
h->second + g->second + g1->second + g2->second;
fourEWIDProperties(h->first,g->first,g1->first,g2->first).count(p1234,weight,id);
}
}
}
}
for ( map<unsigned int,LorentzMomentum>::const_iterator h = theChargedLeptons.begin();
h != theChargedLeptons.end(); ++h ) {
chargedLeptonProperties(h->first).count(h->second,weight,id);
map<unsigned int,LorentzMomentum>::const_iterator g = h; ++g;
for ( ; g != theChargedLeptons.end(); ++g ) {
chargedLeptonPairProperties(h->first,g->first).count(h->second,g->second,weight,id);
map<unsigned int,LorentzMomentum>::const_iterator g1 = g; ++g1;
for ( ; g1 != theChargedLeptons.end(); ++g1 ) {
threeChargedLeptonProperties(h->first,g->first,g1->first).count(h->second,g->second,g1->second,weight,id);
map<unsigned int,LorentzMomentum>::const_iterator g2 = g1; ++g2;
for ( ; g2 != theChargedLeptons.end(); ++g2 ) {
LorentzMomentum p1234 =
h->second + g->second + g1->second + g2->second;
fourChargedLeptonProperties(h->first,g->first,g1->first,g2->first).count(p1234,weight,id);
}
}
}
}
for ( map<unsigned int,LorentzMomentum>::const_iterator h = theNeutrinos.begin();
h != theNeutrinos.end(); ++h ) {
neutrinoProperties(h->first).count(h->second,weight,id);
}
pTmissProperties().count(pTmissMomentum(),weight,id);
for ( map<unsigned int,LorentzMomentum>::const_iterator h = theHiggs.begin();
h != theHiggs.end(); ++h ) {
higgsProperties(h->first).count(h->second,weight,id);
}
analyzeSpecial(id,weight);
}
void LeptonsJetsAnalysis::analyze(tEventPtr event, long ieve, int loop, int state) {
AnalysisHandler::analyze(event, ieve, loop, state);
Ptr<StandardEventHandler>::tptr seh =
dynamic_ptr_cast<Ptr<StandardEventHandler>::tptr>(generator()->eventHandler());
Ptr<GeneralSampler>::tptr sampler =
dynamic_ptr_cast<Ptr<GeneralSampler>::tptr>(seh->sampler());
double norm = sampler->maxXSec()/picobarn;
if ( !theIsShowered ) {
tSubProPtr sub = event->primarySubProcess();
Ptr<SubProcessGroup>::tptr grp =
dynamic_ptr_cast<Ptr<SubProcessGroup>::tptr>(sub);
ParticleVector hfs = sub->outgoing();
analyze(hfs,ieve,norm*event->weight()*sub->groupWeight());
if ( grp ) {
for ( SubProcessVector::const_iterator s = grp->dependent().begin();
s != grp->dependent().end(); ++s ) {
ParticleVector fs = (**s).outgoing();
analyze(fs,ieve,norm*event->weight()*(**s).groupWeight());
}
}
} else {
ParticleVector fs;
event->getFinalState(fs);
analyze(fs,ieve,norm*event->weight());
}
}
void LeptonsJetsAnalysis::dofinish() {
AnalysisHandler::dofinish();
Ptr<StandardEventHandler>::tptr seh =
dynamic_ptr_cast<Ptr<StandardEventHandler>::tptr>(generator()->eventHandler());
Ptr<GeneralSampler>::tptr sampler =
dynamic_ptr_cast<Ptr<GeneralSampler>::tptr>(seh->sampler());
unsigned long attemptedPoints = sampler->attempts();
double sumOfWeights = sampler->sumWeights();
double sumOfSquaredWeights = sampler->sumWeights2();
CrossSection maxXSection = sampler->maxXSec();
XML::Element elem(XML::ElementTypes::Element,"Run");
elem.appendAttribute("name",generator()->runName());
elem.appendAttribute("attemptedPoints",attemptedPoints);
elem.appendAttribute("sumOfWeights",sumOfWeights*maxXSection/picobarn);
elem.appendAttribute("sumOfSquaredWeights",sumOfSquaredWeights*sqr(maxXSection/picobarn));
XML::Element xhistos(XML::ElementTypes::Element,"Histograms");
for ( map<unsigned int,ObjectProperties>::iterator h = theJetProperties.begin();
h != theJetProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
for ( map<unsigned int,ObjectProperties>::iterator h = theExclusiveJetProperties.begin();
h != theExclusiveJetProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
if ( !theJetInclusiveProperties.pt.bins().empty() ) {
theJetInclusiveProperties.finalize(xhistos);
}
if ( !theJetSummedProperties.pt.bins().empty() ) {
theJetSummedProperties.finalize(xhistos);
}
if ( !theJetAverageProperties.pt.bins().empty() ) {
theJetAverageProperties.finalize(xhistos);
}
if ( !theNJetsInclusive.bins().empty() ) {
theNJetsInclusive.finalize();
xhistos.append(theNJetsInclusive.toXML());
}
if ( !theNJetsExclusive.bins().empty() ) {
theNJetsExclusive.finalize();
xhistos.append(theNJetsExclusive.toXML());
}
for ( map<unsigned int,ObjectProperties>::iterator h = theEWIDProperties.begin();
h != theEWIDProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
for ( map<unsigned int,ObjectProperties>::iterator h = theChargedLeptonProperties.begin();
h != theChargedLeptonProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
for ( map<unsigned int,ObjectProperties>::iterator h = theNeutrinoProperties.begin();
h != theNeutrinoProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
thePTmissProperties.finalize(xhistos);
for ( map<unsigned int,ObjectProperties>::iterator h = theHiggsProperties.begin();
h != theHiggsProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
for ( map<pair<unsigned int,unsigned int>,PairProperties>::iterator h = theJetPairProperties.begin();
h != theJetPairProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
for ( map<pair<unsigned int,unsigned int>,PairProperties>::iterator h = theJetEWIDPairProperties.begin();
h != theJetEWIDPairProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
for ( map<pair<unsigned int,unsigned int>,PairProperties>::iterator h = theJetChargedLeptonPairProperties.begin();
h != theJetChargedLeptonPairProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
for ( map<pair<unsigned int,unsigned int>,PairProperties>::iterator h = theJetNeutrinoPairProperties.begin();
h != theJetNeutrinoPairProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
for ( map<unsigned int,PairProperties>::iterator h = theJetPTmissPairProperties.begin();
h != theJetPTmissPairProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
for ( map<pair<unsigned int,unsigned int>,PairProperties>::iterator h = theJetHiggsPairProperties.begin();
h != theJetHiggsPairProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
for ( map<pair<unsigned int,unsigned int>,PairProperties>::iterator h = theEWIDPairProperties.begin();
h != theEWIDPairProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
for ( map<pair<unsigned int,unsigned int>,PairProperties>::iterator h = theChargedLeptonPairProperties.begin();
h != theChargedLeptonPairProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
- for ( map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator h =
+ for ( map<std::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator h =
theThreeJetProperties.begin(); h != theThreeJetProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
- for ( map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator h =
+ for ( map<std::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator h =
theJetPairEWIDTripleProperties.begin(); h != theJetPairEWIDTripleProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
- for ( map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator h =
+ for ( map<std::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator h =
theJetPairChargedLeptonTripleProperties.begin(); h != theJetPairChargedLeptonTripleProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
- for ( map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator h =
+ for ( map<std::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator h =
theJetPairNeutrinoTripleProperties.begin(); h != theJetPairNeutrinoTripleProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
for ( map<pair<unsigned int,unsigned int>,TripleProperties>::iterator h =
theJetPairPTmissTripleProperties.begin(); h != theJetPairPTmissTripleProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
- for ( map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator h =
+ for ( map<std::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator h =
theJetPairHiggsTripleProperties.begin(); h != theJetPairHiggsTripleProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
- for ( map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator h =
+ for ( map<std::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator h =
theThreeEWIDProperties.begin(); h != theThreeEWIDProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
- for ( map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator h =
+ for ( map<std::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator h =
theThreeChargedLeptonProperties.begin(); h != theThreeChargedLeptonProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
- for ( map<boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator h =
+ for ( map<std::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator h =
theFourJetProperties.begin(); h != theFourJetProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
- for ( map<boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator h =
+ for ( map<std::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator h =
theFourEWIDProperties.begin(); h != theFourEWIDProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
- for ( map<boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator h =
+ for ( map<std::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator h =
theFourChargedLeptonProperties.begin(); h != theFourChargedLeptonProperties.end(); ++h ) {
h->second.finalize(xhistos);
}
finalize(xhistos);
elem.append(xhistos);
string fname = name() + ".xml";
ofstream runXML(fname.c_str());
runXML << setprecision(16);
XML::ElementIO::put(elem,runXML);
}
IBPtr LeptonsJetsAnalysis::clone() const {
return new_ptr(*this);
}
IBPtr LeptonsJetsAnalysis::fullclone() const {
return new_ptr(*this);
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void LeptonsJetsAnalysis::persistentOutput(PersistentOStream & os) const {
os << theIsShowered << theApplyCuts << theJetFinder << theJetRegions;
}
void LeptonsJetsAnalysis::persistentInput(PersistentIStream & is, int) {
is >> theIsShowered >> theApplyCuts >> theJetFinder >> theJetRegions;
}
// *** 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<LeptonsJetsAnalysis,AnalysisHandler>
describeHerwigLeptonsJetsAnalysis("Herwig::LeptonsJetsAnalysis", "JetCuts.so HwJetsAnalysis.so");
void LeptonsJetsAnalysis::Init() {
static ClassDocumentation<LeptonsJetsAnalysis> documentation
("There is no documentation for the LeptonsJetsAnalysis class");
static Reference<LeptonsJetsAnalysis,JetFinder> interfaceJetFinder
("JetFinder",
"",
&LeptonsJetsAnalysis::theJetFinder, false, false, true, false, false);
static RefVector<LeptonsJetsAnalysis,JetRegion> interfaceJetRegions
("JetRegions",
"",
&LeptonsJetsAnalysis::theJetRegions, -1, false, false, true, false, false);
static Switch<LeptonsJetsAnalysis,bool> interfaceIsShowered
("IsShowered",
"",
&LeptonsJetsAnalysis::theIsShowered, false, false, false);
static SwitchOption interfaceIsShoweredYes
(interfaceIsShowered,
"Yes",
"",
true);
static SwitchOption interfaceIsShoweredNo
(interfaceIsShowered,
"No",
"",
false);
static Switch<LeptonsJetsAnalysis,bool> interfaceApplyCuts
("ApplyCuts",
"",
&LeptonsJetsAnalysis::theApplyCuts, false, false, false);
static SwitchOption interfaceApplyCutsYes
(interfaceApplyCuts,
"Yes",
"",
true);
static SwitchOption interfaceApplyCutsNo
(interfaceApplyCuts,
"No",
"",
false);
}
diff --git a/Analysis/LeptonsJetsAnalysis.h b/Analysis/LeptonsJetsAnalysis.h
--- a/Analysis/LeptonsJetsAnalysis.h
+++ b/Analysis/LeptonsJetsAnalysis.h
@@ -1,1140 +1,1137 @@
// -*- C++ -*-
#ifndef Herwig_LeptonsJetsAnalysis_H
#define Herwig_LeptonsJetsAnalysis_H
//
// This is the declaration of the LeptonsJetsAnalysis class.
//
#include "ThePEG/Handlers/AnalysisHandler.h"
#include "ThePEG/Cuts/JetFinder.h"
#include "ThePEG/Cuts/JetRegion.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "Herwig/Utilities/Statistics/Histogram.h"
-#include <boost/tuple/tuple.hpp>
-#include <boost/tuple/tuple_comparison.hpp>
-
namespace Herwig {
using namespace ThePEG;
/**
* Here is the documentation of the LeptonsJetsAnalysis class.
*
* @see \ref LeptonsJetsAnalysisInterfaces "The interfaces"
* defined for LeptonsJetsAnalysis.
*/
class LeptonsJetsAnalysis: public AnalysisHandler {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
LeptonsJetsAnalysis();
/**
* The destructor.
*/
virtual ~LeptonsJetsAnalysis();
//@}
public:
/** @name Virtual functions required by the AnalysisHandler class. */
//@{
/**
* Analyze a given Event. Note that a fully generated event
* may be presented several times, if it has been manipulated in
* between. The default version of this function will call transform
* to make a lorentz transformation of the whole event, then extract
* all final state particles and call analyze(tPVector) of this
* analysis object and those of all associated analysis objects. The
* default version will not, however, do anything on events which
* have not been fully generated, or have been manipulated in any
* way.
* @param event pointer to the Event to be analyzed.
* @param ieve the event number.
* @param loop the number of times this event has been presented.
* If negative the event is now fully generated.
* @param state a number different from zero if the event has been
* manipulated in some way since it was last presented.
*/
virtual void analyze(tEventPtr event, long ieve, int loop, int state);
//@}
protected:
/**
* Analyze one subprocess, given the event number it belongs to
*/
void analyze(ParticleVector&, long, double);
/**
* Clear the electroweak objects and jets for the next event
*/
void clear() {
theJets.clear();
theEWIDs.clear();
theChargedLeptons.clear();
theNeutrinos.clear();
theHiggs.clear();
}
/**
* Reconstruct the jets and fill the respective momenta.
*/
virtual void reconstructJets(const ParticleVector&);
/**
* The jet finder to use
*/
Ptr<JetFinder>::tptr jetFinder() const {
return theJetFinder;
}
/**
* The jet regions to match.
*/
const vector<Ptr<JetRegion>::ptr>& jetRegions() const { return theJetRegions; }
/**
* Return the number of matched jets
*/
unsigned int nJets() const { return theJets.size(); }
/**
* Set the momentum of the indicated jet.
*/
LorentzMomentum& jetMomentum(const unsigned int id) {
return theJets[id];
}
/**
* Reconstruct all the variables for EW particles and fill the respective momenta.
*/
virtual void reconstructEWParticles(ParticleVector&);
/**
* Set the momentum of the indicated electroweak particle.
*/
LorentzMomentum& eWIDMomentum(const unsigned int id) {
return theEWIDs[id];
}
/**
* Set the momentum of the indicated charged lepton.
*/
LorentzMomentum& chargedLeptonMomentum(const unsigned int id) {
return theChargedLeptons[id];
}
/**
* Set the momentum of the indicated neutrino.
*/
LorentzMomentum& neutrinoMomentum(const unsigned int id) {
return theNeutrinos[id];
}
/**
* Set the missing pT momentum.
*/
LorentzMomentum& pTmissMomentum() {
return thePTmiss;
}
/**
* Set the momentum of the indicated Higgs.
*/
LorentzMomentum& higgsMomentum(const unsigned int id) {
return theHiggs[id];
}
protected:
/**
* Finalize this object. Called in the run phase just after a
* run has ended. Used eg. to write out statistics.
*/
virtual void dofinish();
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).
protected:
/**
* Collection of object histograms; ranges are adjusted to the
* maximum, so range constraints and rebinning can be applied later.
*/
struct ObjectProperties {
/**
* Transverse momentum
*/
Statistics::Histogram pt;
Statistics::Histogram ptlow;
Statistics::Histogram pt_logx;
/**
* Rapidity
*/
Statistics::Histogram y;
/**
* Azimuth
*/
Statistics::Histogram phi;
/**
* Mass
*/
Statistics::Histogram mass;
Statistics::Histogram masslow;
/**
* Default constructor
*/
ObjectProperties() {}
/**
* Construct given Ecm
*/
ObjectProperties(const string& name, Energy)
: pt(name + "Pt",Statistics::Histogram::regularBinEdges(0,1000,200),true,false),
ptlow(name + "Ptlow",Statistics::Histogram::regularBinEdges(0,200,100),true,false),
pt_logx(name + "PtLogX",Statistics::Histogram::logBinEdges(0.1,1000,100),true,false),
y(name + "Y",Statistics::Histogram::regularBinEdges(-6,6,120),false,false),
phi(name + "Phi",Statistics::Histogram::regularBinEdges(-Constants::pi,Constants::pi,62),
make_pair(-Constants::pi,Constants::pi)),
mass(name + "Mass",Statistics::Histogram::regularBinEdges(0,5000,500),true,false),
masslow(name + "Masslow",Statistics::Histogram::regularBinEdges(0,250,100),true,false) {}
/**
* Count given momentum, weight and id
*/
void count(const LorentzMomentum& p, double weight, unsigned int id) {
pt.count(Statistics::EventContribution(p.perp()/GeV,weight,5.),id);
ptlow.count(Statistics::EventContribution(p.perp()/GeV,weight,2.),id);
pt_logx.count(Statistics::EventContribution(p.perp()/GeV,weight,1.),id);
y.count(Statistics::EventContribution(p.rapidity(),weight,0.1),id);
phi.count(Statistics::EventContribution(p.phi(),weight,0.1),id);
mass.count(Statistics::EventContribution(p.m()/GeV,weight,10.),id);
masslow.count(Statistics::EventContribution(p.m()/GeV,weight,2.5),id);
}
/**
* Count given momentum components, weight and id
*/
void count(Energy perp, double rapidity,
double xphi, Energy m,
double weight, unsigned int id) {
pt.count(Statistics::EventContribution(perp/GeV,weight,5.),id);
ptlow.count(Statistics::EventContribution(perp/GeV,weight,1.),id);
pt_logx.count(Statistics::EventContribution(perp/GeV,weight,1.),id);
y.count(Statistics::EventContribution(rapidity,weight,0.1),id);
phi.count(Statistics::EventContribution(xphi,weight,0.1),id);
mass.count(Statistics::EventContribution(m/GeV,weight,5.),id);
masslow.count(Statistics::EventContribution(m/GeV,weight,1.25),id);
}
/**
* Convert to XML
*/
void finalize(XML::Element& elem) {
pt.finalize(); elem.append(pt.toXML());
ptlow.finalize(); elem.append(ptlow.toXML());
pt_logx.finalize(); elem.append(pt_logx.toXML());
y.finalize(); elem.append(y.toXML());
phi.finalize(); elem.append(phi.toXML());
mass.finalize(); elem.append(mass.toXML());
masslow.finalize(); elem.append(masslow.toXML());
}
};
/**
* Collection of pair histograms; ranges are adjusted to the
* maximum, so range constraints and rebinning can be applied later.
*/
struct PairProperties
: public ObjectProperties {
/**
* Calculate deltaPhi
*/
static double dPhi(const LorentzMomentum& a,
const LorentzMomentum& b){
double phi1 = a.phi();
double phi2 = b.phi();
double diff=phi1-phi2;
if(diff<-Constants::pi){
diff+=(2.0*Constants::pi);
}
else if (diff>Constants::pi){
diff-=(2.0*Constants::pi);
}
return diff;
}
/**
* Calculate deltaY
*/
static double dY(const LorentzMomentum& a,
const LorentzMomentum& b){
return abs(a.rapidity()-b.rapidity());
}
/**
* Calculate deltaR
*/
static double dR(const LorentzMomentum& a,
const LorentzMomentum& b){
return sqrt(sqr(dPhi(a,b))+sqr(dY(a,b)));
}
/**
* Calculate ydoty
*/
static double yy(const LorentzMomentum& a,
const LorentzMomentum& b){
double ya = a.rapidity();
double yb = b.rapidity();
double yres = sqrt(abs(ya*yb));
return ya*yb < 0. ? -yres : yres;
}
/**
* Delta y
*/
Statistics::Histogram deltaY;
/**
* Delta phi
*/
Statistics::Histogram deltaPhi;
/**
* Delta phi
*/
Statistics::Histogram deltaR;
/**
* Product of the rapidities
*/
Statistics::Histogram yDotY;
/**
* Default constructor
*/
PairProperties()
: ObjectProperties() {}
/**
* Construct given Ecm
*/
PairProperties(const string& name, Energy ecm)
: ObjectProperties(name,ecm),
deltaY(name + "DeltaY",Statistics::Histogram::regularBinEdges(0,6,60),true,false),
deltaPhi(name + "DeltaPhi",Statistics::Histogram::regularBinEdges(-Constants::pi,Constants::pi,32),
make_pair(-Constants::pi,Constants::pi)),
deltaR(name + "DeltaR",Statistics::Histogram::regularBinEdges(0,10,100),true,false),
yDotY(name + "YDotY",Statistics::Histogram::regularBinEdges(-6,6,120),false,false) {}
/**
* Count given momentum, weight and id
*/
void count(const LorentzMomentum& p, const LorentzMomentum& q, double weight, unsigned int id) {
ObjectProperties::count(p+q,weight,id);
deltaY.count(Statistics::EventContribution(dY(p,q),weight,0.1),id);
deltaPhi.count(Statistics::EventContribution(dPhi(p,q),weight,0.1),id);
deltaR.count(Statistics::EventContribution(dR(p,q),weight,0.1),id);
yDotY.count(Statistics::EventContribution(yy(p,q),weight,0.1),id);
}
/**
* Convert to XML
*/
void finalize(XML::Element& elem) {
ObjectProperties::finalize(elem);
deltaY.finalize(); elem.append(deltaY.toXML());
deltaPhi.finalize(); elem.append(deltaPhi.toXML());
deltaR.finalize(); elem.append(deltaR.toXML());
yDotY.finalize(); elem.append(yDotY.toXML());
}
};
/**
* Collection of triple histograms; ranges are adjusted to the
* maximum, so range constraints and rebinning can be applied later.
*/
struct TripleProperties
: public ObjectProperties {
/**
* Calculate deltaY^*
*/
static double dYstar(const LorentzMomentum& a,
const LorentzMomentum& b,
const LorentzMomentum& c){
return c.rapidity()-(a.rapidity()+b.rapidity())/2.;
}
/**
* Calculate deltaZ^* -- normalized deltaY^*
*/
static double dZstar(const LorentzMomentum& a,
const LorentzMomentum& b,
const LorentzMomentum& c){
return dYstar(a,b,c)*2./abs(a.rapidity()-b.rapidity());
}
/**
* Delta y^*
*/
Statistics::Histogram deltaYstar;
/**
* Delta z^*
*/
Statistics::Histogram deltaZstar;
/**
* Default constructor
*/
TripleProperties()
: ObjectProperties() {}
/**
* Construct given Ecm
*/
TripleProperties(const string& name, Energy ecm)
: ObjectProperties(name,ecm),
deltaYstar(name + "DeltaYstar",Statistics::Histogram::regularBinEdges(-6,6,120),true,false),
deltaZstar(name + "DeltaZstar",Statistics::Histogram::regularBinEdges(-3,3,120),true,false) {}
/**
* Count given momentum, weight and id
*/
void count(const LorentzMomentum& p, const LorentzMomentum& q, const LorentzMomentum& r,
double weight, unsigned int id) {
ObjectProperties::count(p+q+r,weight,id);
deltaYstar.count(Statistics::EventContribution(dYstar(p,q,r),weight,0.1),id);
deltaZstar.count(Statistics::EventContribution(dZstar(p,q,r),weight,0.05),id);
}
/**
* Convert to XML
*/
void finalize(XML::Element& elem) {
ObjectProperties::finalize(elem);
deltaYstar.finalize(); elem.append(deltaYstar.toXML());
deltaZstar.finalize(); elem.append(deltaZstar.toXML());
}
};
private:
/**
* Switch between fixed order and showered
*/
bool theIsShowered;
/**
* Switch whether to apply extra analysis cuts
*/
bool theApplyCuts;
/**
* The jet finder to use
*/
Ptr<JetFinder>::ptr theJetFinder;
/**
* The jet regions to match.
*/
vector<Ptr<JetRegion>::ptr> theJetRegions;
/**
* The reconstructed jets
*/
map<unsigned int,LorentzMomentum> theJets;
/**
* The reconstructed electroweak particles
*/
map<unsigned int,LorentzMomentum> theEWIDs;
/**
* The reconstructed charged leptons
*/
map<unsigned int,LorentzMomentum> theChargedLeptons;
/**
* The reconstructed neutrinos
*/
map<unsigned int,LorentzMomentum> theNeutrinos;
/**
* The reconstructed missing pT
*/
LorentzMomentum thePTmiss;
/**
* The reconstructed Higgs
*/
map<unsigned int,LorentzMomentum> theHiggs;
/**
* Jet properties
*/
map<unsigned int,ObjectProperties> theJetProperties;
/**
* Exclusive jet properties
*/
map<unsigned int,ObjectProperties> theExclusiveJetProperties;
/**
* Jet-inclusive properties
*/
ObjectProperties theJetInclusiveProperties;
/**
* Jet-summed properties
*/
ObjectProperties theJetSummedProperties;
/**
* Jet-average properties
*/
ObjectProperties theJetAverageProperties;
/**
* Inclusive jet multiplicities
*/
Statistics::Histogram theNJetsInclusive;
/**
* Exclusive jet multiplicities
*/
Statistics::Histogram theNJetsExclusive;
/**
* Electroweak properties
*/
map<unsigned int,ObjectProperties> theEWIDProperties;
/**
* Charged lepton properties
*/
map<unsigned int,ObjectProperties> theChargedLeptonProperties;
/**
* Neutrino properties
*/
map<unsigned int,ObjectProperties> theNeutrinoProperties;
/**
* missing pT properties
*/
ObjectProperties thePTmissProperties;
/**
* Higgs properties
*/
map<unsigned int,ObjectProperties> theHiggsProperties;
/**
* Jet pair properties
*/
map<pair<unsigned int,unsigned int>,PairProperties> theJetPairProperties;
/**
* Jet/electroweak pair properties
*/
map<pair<unsigned int,unsigned int>,PairProperties> theJetEWIDPairProperties;
/**
* Jet/charged lepton pair properties
*/
map<pair<unsigned int,unsigned int>,PairProperties> theJetChargedLeptonPairProperties;
/**
* Jet/neutrino pair properties
*/
map<pair<unsigned int,unsigned int>,PairProperties> theJetNeutrinoPairProperties;
/**
* Jet/missing pT pair properties
*/
map<unsigned int,PairProperties> theJetPTmissPairProperties;
/**
* Jet/Higgs pair properties
*/
map<pair<unsigned int,unsigned int>,PairProperties> theJetHiggsPairProperties;
/**
* Electroweak pair properties
*/
map<pair<unsigned int,unsigned int>,PairProperties> theEWIDPairProperties;
/**
* Charged lepton pair properties
*/
map<pair<unsigned int,unsigned int>,PairProperties> theChargedLeptonPairProperties;
/**
* Trijet properties
*/
- map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties> theThreeJetProperties;
+ map<std::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties> theThreeJetProperties;
/**
* Jet-pair/electroweak triple properties
*/
- map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties> theJetPairEWIDTripleProperties;
+ map<std::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties> theJetPairEWIDTripleProperties;
/**
* Jet-pair/charged lepton triple properties
*/
- map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties> theJetPairChargedLeptonTripleProperties;
+ map<std::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties> theJetPairChargedLeptonTripleProperties;
/**
* Jet-pair/neutrino triple properties
*/
- map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties> theJetPairNeutrinoTripleProperties;
+ map<std::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties> theJetPairNeutrinoTripleProperties;
/**
* Jet-pair/missing pT triple properties
*/
map<pair<unsigned int,unsigned int>,TripleProperties> theJetPairPTmissTripleProperties;
/**
* Jet-pair/Higgs triple properties
*/
- map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties> theJetPairHiggsTripleProperties;
+ map<std::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties> theJetPairHiggsTripleProperties;
/**
* Triple electroweak properties
*/
- map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties> theThreeEWIDProperties;
+ map<std::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties> theThreeEWIDProperties;
/**
* Triple charged lepton properties
*/
- map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties> theThreeChargedLeptonProperties;
+ map<std::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties> theThreeChargedLeptonProperties;
/**
* Fourjet properties
*/
- map<boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties> theFourJetProperties;
+ map<std::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties> theFourJetProperties;
/**
* Four electroweak properties
*/
- map<boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties> theFourEWIDProperties;
+ map<std::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties> theFourEWIDProperties;
/**
* Four charged lepton properties
*/
- map<boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties> theFourChargedLeptonProperties;
+ map<std::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties> theFourChargedLeptonProperties;
protected:
/**
* Jet properties
*/
ObjectProperties& jetProperties(const unsigned int id) {
map<unsigned int,ObjectProperties>::iterator h =
theJetProperties.find(id);
if ( h != theJetProperties.end() )
return h->second;
ostringstream ids; ids << "Jet" << id;
return
theJetProperties[id] =
ObjectProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Exclusive jet properties
*/
ObjectProperties& exclusiveJetProperties(const unsigned int id) {
map<unsigned int,ObjectProperties>::iterator h =
theExclusiveJetProperties.find(id);
if ( h != theExclusiveJetProperties.end() )
return h->second;
ostringstream ids; ids << "ExclusiveJet" << id;
return
theExclusiveJetProperties[id] =
ObjectProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Jet-inclusive properties
*/
ObjectProperties& jetInclusiveProperties() {
if ( !theJetInclusiveProperties.pt.bins().empty() )
return theJetInclusiveProperties;
return
theJetInclusiveProperties =
ObjectProperties("JetInclusive",generator()->maximumCMEnergy());
}
/**
* Jet-summed properties
*/
ObjectProperties& jetSummedProperties() {
if ( !theJetSummedProperties.pt.bins().empty() )
return theJetSummedProperties;
return
theJetSummedProperties =
ObjectProperties("JetSummed",generator()->maximumCMEnergy());
}
/**
* Jet-average properties
*/
ObjectProperties& jetAverageProperties() {
if ( !theJetAverageProperties.pt.bins().empty() )
return theJetAverageProperties;
return
theJetAverageProperties =
ObjectProperties("JetAverage",generator()->maximumCMEnergy());
}
/**
* Inclusive jet multiplicities
*/
Statistics::Histogram& nJetsInclusive() {
if ( !theNJetsInclusive.bins().empty() )
return theNJetsInclusive;
return
theNJetsInclusive =
Statistics::Histogram("NJetsInclusive",
Statistics::Histogram::regularBinEdges(-0.5,theJetRegions.size()+0.5,
theJetRegions.size()+1),
true,true);
}
/**
* Exclusive jet multiplicities
*/
Statistics::Histogram& nJetsExclusive() {
if ( !theNJetsExclusive.bins().empty() )
return theNJetsExclusive;
return
theNJetsExclusive =
Statistics::Histogram("NJetsExclusive",
Statistics::Histogram::regularBinEdges(-0.5,theJetRegions.size()+0.5,
theJetRegions.size()+1),
true,true);
}
/**
* Lepton properties -- all sorted by ID
*/
ObjectProperties& eWIDProperties(const unsigned int id) {
map<unsigned int,ObjectProperties>::iterator h =
theEWIDProperties.find(id);
if ( h != theEWIDProperties.end() )
return h->second;
ostringstream ids; ids << "EWID" << id;
return
theEWIDProperties[id] =
ObjectProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Charged lepton properties
*/
ObjectProperties& chargedLeptonProperties(const unsigned int id) {
map<unsigned int,ObjectProperties>::iterator h =
theChargedLeptonProperties.find(id);
if ( h != theChargedLeptonProperties.end() )
return h->second;
ostringstream ids; ids << "ChargedLepton" << id;
return
theChargedLeptonProperties[id] =
ObjectProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Neutrino properties
*/
ObjectProperties& neutrinoProperties(const unsigned int id) {
map<unsigned int,ObjectProperties>::iterator h =
theNeutrinoProperties.find(id);
if ( h != theNeutrinoProperties.end() )
return h->second;
ostringstream ids; ids << "Neutrino" << id;
return
theNeutrinoProperties[id] =
ObjectProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Missing pT properties
*/
ObjectProperties& pTmissProperties() {
if ( !thePTmissProperties.pt.bins().empty() )
return thePTmissProperties;
return
thePTmissProperties =
ObjectProperties("PTmiss",generator()->maximumCMEnergy());
}
/**
* Higgs properties
*/
ObjectProperties& higgsProperties(const unsigned int id) {
map<unsigned int,ObjectProperties>::iterator h =
theHiggsProperties.find(id);
if ( h != theHiggsProperties.end() )
return h->second;
ostringstream ids; ids << "Higgs" << id;
return
theHiggsProperties[id] =
ObjectProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Jet pair properties
*/
PairProperties& jetPairProperties(const unsigned int id, const unsigned int jd) {
map<pair<unsigned int,unsigned int>,PairProperties>::iterator h =
theJetPairProperties.find(make_pair(id,jd));
if ( h != theJetPairProperties.end() )
return h->second;
ostringstream ids; ids << "Jet" << id << jd;
return theJetPairProperties[make_pair(id,jd)] =
PairProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Jet/lepton(all sorted by ID) pair properties
*/
PairProperties& jetEWIDPairProperties(const unsigned int id, const unsigned int jd) {
map<pair<unsigned int,unsigned int>,PairProperties>::iterator h =
theJetEWIDPairProperties.find(make_pair(id,jd));
if ( h != theJetEWIDPairProperties.end() )
return h->second;
ostringstream ids; ids << "Jet" << id << "EWID" << jd;
return theJetEWIDPairProperties[make_pair(id,jd)] =
PairProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Jet/charged lepton pair properties
*/
PairProperties& jetChargedLeptonPairProperties(const unsigned int id, const unsigned int jd) {
map<pair<unsigned int,unsigned int>,PairProperties>::iterator h =
theJetChargedLeptonPairProperties.find(make_pair(id,jd));
if ( h != theJetChargedLeptonPairProperties.end() )
return h->second;
ostringstream ids; ids << "Jet" << id << "ChargedLepton" << jd;
return theJetChargedLeptonPairProperties[make_pair(id,jd)] =
PairProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Jet/neutrino pair properties
*/
PairProperties& jetNeutrinoPairProperties(const unsigned int id, const unsigned int jd) {
map<pair<unsigned int,unsigned int>,PairProperties>::iterator h =
theJetNeutrinoPairProperties.find(make_pair(id,jd));
if ( h != theJetNeutrinoPairProperties.end() )
return h->second;
ostringstream ids; ids << "Jet" << id << "Neutrino" << jd;
return theJetNeutrinoPairProperties[make_pair(id,jd)] =
PairProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Jet/missing pT pair properties
*/
PairProperties& jetPTmissPairProperties(const unsigned int id) {
map<unsigned int,PairProperties>::iterator h =
theJetPTmissPairProperties.find(id);
if ( h != theJetPTmissPairProperties.end() )
return h->second;
ostringstream ids; ids << "Jet" << id << "PTmiss";
return theJetPTmissPairProperties[id] =
PairProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Jet/Higgs pair properties
*/
PairProperties& jetHiggsPairProperties(const unsigned int id, const unsigned int jd) {
map<pair<unsigned int,unsigned int>,PairProperties>::iterator h =
theJetHiggsPairProperties.find(make_pair(id,jd));
if ( h != theJetHiggsPairProperties.end() )
return h->second;
ostringstream ids; ids << "Jet" << id << "Higgs" << jd;
return theJetHiggsPairProperties[make_pair(id,jd)] =
PairProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Electroweak pair properties
*/
PairProperties& eWIDPairProperties(const unsigned int id, const unsigned int jd) {
map<pair<unsigned int,unsigned int>,PairProperties>::iterator h =
theEWIDPairProperties.find(make_pair(id,jd));
if ( h != theEWIDPairProperties.end() )
return h->second;
ostringstream ids; ids << "EWID" << id << jd;
return theEWIDPairProperties[make_pair(id,jd)] =
PairProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Charged lepton pair properties
*/
PairProperties& chargedLeptonPairProperties(const unsigned int id, const unsigned int jd) {
map<pair<unsigned int,unsigned int>,PairProperties>::iterator h =
theChargedLeptonPairProperties.find(make_pair(id,jd));
if ( h != theChargedLeptonPairProperties.end() )
return h->second;
ostringstream ids; ids << "ChargedLepton" << id << jd;
return theChargedLeptonPairProperties[make_pair(id,jd)] =
PairProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Trijet properties
*/
TripleProperties& threeJetProperties(const unsigned int id1, const unsigned int id2,
const unsigned int id3) {
- map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator it =
- theThreeJetProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3));
+ map<std::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator it =
+ theThreeJetProperties.find(std::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3));
if ( it != theThreeJetProperties.end() )
return it->second;
ostringstream ids;
ids << "Jet" << id1 << id2 << id3;
- return theThreeJetProperties[boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] =
+ return theThreeJetProperties[std::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] =
TripleProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Jet-pair/electroweak triple properties
*/
TripleProperties& jetPairEWIDTripleProperties(const unsigned int id1, const unsigned int id2,
const unsigned int id3) {
- map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator it =
- theJetPairEWIDTripleProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3));
+ map<std::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator it =
+ theJetPairEWIDTripleProperties.find(std::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3));
if ( it != theJetPairEWIDTripleProperties.end() )
return it->second;
ostringstream ids;
ids << "Jet" << id1 << id2 << "EWID" << id3;
- return theJetPairEWIDTripleProperties[boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] =
+ return theJetPairEWIDTripleProperties[std::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] =
TripleProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Jet-pair/charged lepton triple properties
*/
TripleProperties& jetPairChargedLeptonTripleProperties(const unsigned int id1, const unsigned int id2,
const unsigned int id3) {
- map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator it =
- theJetPairChargedLeptonTripleProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3));
+ map<std::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator it =
+ theJetPairChargedLeptonTripleProperties.find(std::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3));
if ( it != theJetPairChargedLeptonTripleProperties.end() )
return it->second;
ostringstream ids;
ids << "Jet" << id1 << id2 << "ChargedLepton" << id3;
- return theJetPairChargedLeptonTripleProperties[boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] =
+ return theJetPairChargedLeptonTripleProperties[std::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] =
TripleProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Jet-pair/neutrino triple properties
*/
TripleProperties& jetPairNeutrinoTripleProperties(const unsigned int id1, const unsigned int id2,
const unsigned int id3) {
- map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator it =
- theJetPairNeutrinoTripleProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3));
+ map<std::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator it =
+ theJetPairNeutrinoTripleProperties.find(std::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3));
if ( it != theJetPairNeutrinoTripleProperties.end() )
return it->second;
ostringstream ids;
ids << "Jet" << id1 << id2 << "Neutrino" << id3;
- return theJetPairNeutrinoTripleProperties[boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] =
+ return theJetPairNeutrinoTripleProperties[std::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] =
TripleProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Jet-pair/missing pT triple properties
*/
TripleProperties& jetPairPTmissTripleProperties(const unsigned int id1, const unsigned int id2) {
map<pair<unsigned int,unsigned int>,TripleProperties>::iterator it =
theJetPairPTmissTripleProperties.find(pair<unsigned int,unsigned int>(id1,id2));
if ( it != theJetPairPTmissTripleProperties.end() )
return it->second;
ostringstream ids;
ids << "Jet" << id1 << id2 << "PTmiss";
return theJetPairPTmissTripleProperties[pair<unsigned int,unsigned int>(id1,id2)] =
TripleProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Jet-pair/Higgs triple properties
*/
TripleProperties& jetPairHiggsTripleProperties(const unsigned int id1, const unsigned int id2,
const unsigned int id3) {
- map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator it =
- theJetPairHiggsTripleProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3));
+ map<std::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator it =
+ theJetPairHiggsTripleProperties.find(std::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3));
if ( it != theJetPairHiggsTripleProperties.end() )
return it->second;
ostringstream ids;
ids << "Jet" << id1 << id2 << "Higgs" << id3;
- return theJetPairHiggsTripleProperties[boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] =
+ return theJetPairHiggsTripleProperties[std::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] =
TripleProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Triple electroweak properties -- all sorted by ID
*/
TripleProperties& threeEWIDProperties(const unsigned int id1, const unsigned int id2,
const unsigned int id3) {
- map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator it =
- theThreeEWIDProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3));
+ map<std::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator it =
+ theThreeEWIDProperties.find(std::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3));
if ( it != theThreeEWIDProperties.end() )
return it->second;
ostringstream ids;
ids << "EWID" << id1 << id2 << id3;
- return theThreeEWIDProperties[boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] =
+ return theThreeEWIDProperties[std::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] =
TripleProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Triple charged lepton properties
*/
TripleProperties& threeChargedLeptonProperties(const unsigned int id1, const unsigned int id2,
const unsigned int id3) {
- map<boost::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator it =
- theThreeChargedLeptonProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3));
+ map<std::tuple<unsigned int,unsigned int,unsigned int>,TripleProperties>::iterator it =
+ theThreeChargedLeptonProperties.find(std::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3));
if ( it != theThreeChargedLeptonProperties.end() )
return it->second;
ostringstream ids;
ids << "ChargedLepton" << id1 << id2 << id3;
- return theThreeChargedLeptonProperties[boost::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] =
+ return theThreeChargedLeptonProperties[std::tuple<unsigned int,unsigned int,unsigned int>(id1,id2,id3)] =
TripleProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Fourjet properties
*/
ObjectProperties& fourJetProperties(const unsigned int id1, const unsigned int id2,
const unsigned int id3, const unsigned int id4) {
- map<boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator it =
- theFourJetProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4));
+ map<std::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator it =
+ theFourJetProperties.find(std::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4));
if ( it != theFourJetProperties.end() )
return it->second;
ostringstream ids;
ids << "Jet" << id1 << id2 << id3 << id4;
- return theFourJetProperties[boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4)] =
+ return theFourJetProperties[std::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4)] =
ObjectProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Four electroweak properties
*/
ObjectProperties& fourEWIDProperties(const unsigned int id1, const unsigned int id2,
const unsigned int id3, const unsigned int id4) {
- map<boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator it =
- theFourEWIDProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4));
+ map<std::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator it =
+ theFourEWIDProperties.find(std::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4));
if ( it != theFourEWIDProperties.end() )
return it->second;
ostringstream ids;
ids << "EWID" << id1 << id2 << id3 << id4;
- return theFourEWIDProperties[boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4)] =
+ return theFourEWIDProperties[std::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4)] =
ObjectProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Four charged lepton properties
*/
ObjectProperties& fourChargedLeptonProperties(const unsigned int id1, const unsigned int id2,
const unsigned int id3, const unsigned int id4) {
- map<boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator it =
- theFourChargedLeptonProperties.find(boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4));
+ map<std::tuple<unsigned int,unsigned int,unsigned int,unsigned int>,ObjectProperties>::iterator it =
+ theFourChargedLeptonProperties.find(std::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4));
if ( it != theFourChargedLeptonProperties.end() )
return it->second;
ostringstream ids;
ids << "ChargedLepton" << id1 << id2 << id3 << id4;
- return theFourChargedLeptonProperties[boost::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4)] =
+ return theFourChargedLeptonProperties[std::tuple<unsigned int,unsigned int,unsigned int,unsigned int>(id1,id2,id3,id4)] =
ObjectProperties(ids.str(),generator()->maximumCMEnergy());
}
/**
* Perform any additional analysis required
*/
virtual void analyzeSpecial(long, double) {}
/**
* Append any additional histograms to the given histogram element
*/
virtual void finalize(XML::Element&) {}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
LeptonsJetsAnalysis & operator=(const LeptonsJetsAnalysis &);
};
}
#endif /* Herwig_LeptonsJetsAnalysis_H */
diff --git a/Analysis/ParallelRunAnalysis.cc b/Analysis/ParallelRunAnalysis.cc
--- a/Analysis/ParallelRunAnalysis.cc
+++ b/Analysis/ParallelRunAnalysis.cc
@@ -1,62 +1,71 @@
#include <fstream>
#include "ParallelRunAnalysis.h"
#include "ThePEG/Handlers/SamplerBase.h"
#include "ThePEG/Repository/Repository.h"
#include "ThePEG/Handlers/EventHandler.h"
#include "ThePEG/Handlers/StandardEventHandler.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/EventRecord/Event.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
-#include <boost/asio.hpp>
+#include <unistd.h>
using namespace Herwig;
ParallelRunAnalysis::ParallelRunAnalysis() {}
void ParallelRunAnalysis::doinitrun() {
string logfilename = generator()->runName() + ".parallel";
ofstream log(logfilename.c_str(),ofstream::app);
- log << "hostname> " << boost::asio::ip::host_name() << "\n" << flush;
+
+ string hostname;
+ {
+ char tmp[256];
+ const int err = gethostname(tmp, 256);
+ tmp[255] = '\0';
+ hostname =
+ ( err == 0 ) ? tmp : "[unknown host]";
+ }
+ log << "hostname> " << hostname << "\n" << flush;
log.close();
}
void ParallelRunAnalysis::dofinish() {
AnalysisHandler::dofinish();
}
void ParallelRunAnalysis::analyze(tEventPtr, long currev, int, int) {
long totev = generator()->N();
long i = currev;
bool skip = currev%(max(totev/100, 1L));
if ( i > totev/2 ) i = totev-i;
while ( skip && i >= 10 && !(i%10) ) i /= 10;
if ( i == 1 || i == 2 || i == 5 ) skip = false;
if ( skip && currev%5000!=0) return;
tEHPtr curEvtHandler = generator()->currentEventHandler();
long attempts = (dynamic_ptr_cast<StdEHPtr>(curEvtHandler))->sampler()->attempts();
char str[128];
sprintf(str,"event> %lu/%lu/%lu xs = %.10E pb +/- %.10E pb\n",
currev,attempts,totev,
double(curEvtHandler->integratedXSec()/picobarn),
double(curEvtHandler->integratedXSecErr()/picobarn));
string logfilename = generator()->runName() + ".parallel";
ofstream log(logfilename.c_str(),ofstream::app);
log << str << flush;
log.close();
}
NoPIOClassDescription<ParallelRunAnalysis> ParallelRunAnalysis::initParallelRunAnalysis;
// Definition of the static class description member.
void ParallelRunAnalysis::Init() {
static ClassDocumentation<ParallelRunAnalysis> documentation
("Analysis for combining parallel runs with Herwig.");
}
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/Contrib/AlpGen/AlpGenToLH.cc b/Contrib/AlpGen/AlpGenToLH.cc
--- a/Contrib/AlpGen/AlpGenToLH.cc
+++ b/Contrib/AlpGen/AlpGenToLH.cc
@@ -1,1402 +1,1533 @@
//A few standard headers
#include <iostream>
#include <sstream>
#include <cstring>
#include <fstream>
#include <cmath>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <iomanip>
using namespace std;
double sqr(double x);
inline int nInt(double x) {
int theCeiling=int(ceil(x));
int theFloor=int(floor(x));
if((theCeiling-theFloor!=1&&theCeiling!=theFloor)
||theCeiling-x>1.0||x-theFloor>1.0||x<theFloor||x>theCeiling) {
cout << "nInt:\n"
<< "Fatal double to integer conversion error.\n"
<< "input double = " << x << "\n"
<< "integer ceiling = " << theCeiling << "\n"
<< "integer floor = " << theFloor << "\n"
<< "Quitting ...";
exit(1);
}
return (theCeiling-x) < (x-theFloor) ? theCeiling : theFloor;
}
int ndnsToLHAPDF(int ndns);
+string ndnsToLHAPDF_str(int ndns);
+
+
double parstrToparval(string varName,
vector<string> * parstrPtr,
vector<double> * parvalPtr);
void doIndividualHardProcessAssignments(int ihrd , double * nup,
vector<double> * idup , vector<double> * istup,
vector<double> * mothup1, vector<double> * mothup2,
vector<double> * icolup1, vector<double> * icolup2,
vector<vector<double> > * pup,
vector<double> masses , int itopprc);
//*****************************//
//*****************************//
//*****************************//
// //
// ATTENTION!!!! //
// ATTENTION!!!! //
// ATTENTION!!!! //
// //
// Remember to uncomment all //
// of the currently commented //
// commands outputting to //
// the HW++ input file for //
// the variables not yet //
// declared and interfaced //
// in the AlpGenHandler!! //
// These should only be the //
// ones commented out by _4_ //
// consecutive forward slashes //
// '////' in the function //
// writeHWPPinFile(...) //
// //
// These are only commented //
// as the AlpGenHandler isn't //
// ready for them yet! //
// //
//*****************************//
//*****************************//
//*****************************//
void writeHWPPinFile(string prefix, int ihrd, int unwev,
int lhapdf, int idbmup0, int idbmup1, int idwtup,
double aqcdup, int nloop,
vector<double> * massesPtr,
vector<double> * parvalPtr,
vector<string> * parstrPtr);
string trim(string theString);
int main(int argc, char *argv[]) {
bool usePowhegBoxConventions(true); // Control
int debugging(3); // To validate
cout << "\n";
cout << "------------------------------------------------------------------\n";
cout << " AlpGenToLH: Convert Alpgen Les Houches to Herwig Les Houches \n";
cout << " v2.0-beta \n";
cout << "------------------------------------------------------------------\n";
cout << "\n";
char* prefix;
if(argv[1]) { prefix = argv[1]; } else {
cout << "Use: ./AlpGenToLH [input string] [number of events (optional)]\n"; exit(1);
cout << "Note: As of version 2, the .stat and _unw.par files are "
<< "required to read the generation parameters.\n";
}
int maxevents(0); int eventcount(0);
if(argc>2) { maxevents=(atoi(argv[2])); }
string lheFilename = string(prefix) + string(".lhe");
string unwFilename = string(prefix) + string(".unw");
string unwparFilename = string(prefix) + string("_unw.par");
string statFilename = string(prefix) + string(".stat");
cout << "Opening input files ...\n";
cout << "-----------------------\n";
cout << "Unweighted events in " << unwFilename << ".\n"
<< "Generation settings in "
<< unwparFilename << " and " << statFilename << ".\n\n";
ifstream unwStream;
ifstream unwparStream;
ifstream statStream;
ofstream lheStream;
unwStream.open(unwFilename.c_str());
unwparStream.open(unwparFilename.c_str());
statStream.open(statFilename.c_str());
lheStream.open(lheFilename.c_str());
if(!unwStream) {
cerr << "error: Failed to open input file " << unwFilename << "\n";
exit(1);
}
if(!unwparStream) {
cerr << "error: Failed to open input file " << unwparFilename << "\n";
exit(1);
}
if(!statStream) {
cerr << "error: Failed to open input file " << statFilename << "\n";
exit(1);
}
// ******************************************************************** //
// Dump the AlpGen *_unw.par file into the LH header (it's not so big). //
// ******************************************************************** //
string tmpString;
lheStream << "<LesHouchesEvents version =\"1.0\">\n";
lheStream << "<!--\n";
lheStream << "File generated using AlpGen and converted with AlpGenToLH \n";
while(unwparStream) {
getline(unwparStream,tmpString);
lheStream << tmpString << "\n";
}
lheStream << "\n\n\n" << "-->\n";
unwparStream.close();
// ***************************************** //
// Read in all relevant info from *_unw.par. //
// ***************************************** //
int ihrd; // AlpGen convention hard process code.
double mc,mb,mt,mw,mz,mh; // C, B, Top, W, Z & Higgs mass from *_unw.par
double avgwgt,errwgt; // Average weight and its error.
int unwev; // Number of unweighted events.
double totlum; // Effective luminosity.
vector<double> parval(200,-999.0); // AlpGen parameters.
vector<string> parstr(200,"----"); // AlpGen parameter (variable) names.
vector<double> alpgenParticleMasses;
unwparStream.open(unwparFilename.c_str());
while(unwparStream) {
getline(unwparStream,tmpString);
if(tmpString.find("hard process code") != string::npos) {
tmpString=tmpString.substr(0,tmpString.find("!"));
tmpString=trim(tmpString);
ihrd=atoi(tmpString.c_str());
}
if(tmpString.find("mc,mb,mt,mw,mz,mh") != string::npos) {
tmpString=trim(tmpString.substr(0,tmpString.find("!")));
mc=atof((tmpString.substr(0,tmpString.find_first_of(" "))).c_str());
alpgenParticleMasses.push_back(mc);
tmpString=trim(tmpString.substr(tmpString.find_first_of(" ")));
mb=atof((tmpString.substr(0,tmpString.find_first_of(" "))).c_str());
alpgenParticleMasses.push_back(mb);
tmpString=trim(tmpString.substr(tmpString.find_first_of(" ")));
mt=atof((tmpString.substr(0,tmpString.find_first_of(" "))).c_str());
alpgenParticleMasses.push_back(mt);
tmpString=trim(tmpString.substr(tmpString.find_first_of(" ")));
mw=atof((tmpString.substr(0,tmpString.find_first_of(" "))).c_str());
alpgenParticleMasses.push_back(mw);
tmpString=trim(tmpString.substr(tmpString.find_first_of(" ")));
mz=atof((tmpString.substr(0,tmpString.find_first_of(" "))).c_str());
alpgenParticleMasses.push_back(mz);
tmpString=trim(tmpString.substr(tmpString.find_first_of(" ")));
mh=atof((tmpString.substr(0,tmpString.find_first_of(" "))).c_str());
alpgenParticleMasses.push_back(mh);
}
if(tmpString.find("Crosssection +- error (pb)") != string::npos) {
tmpString=trim(tmpString.substr(0,tmpString.find("!")));
avgwgt=atof(trim(tmpString.substr(0,tmpString.find(" "))).c_str());
errwgt=atof(trim(tmpString.substr(tmpString.find(" "))).c_str());
}
if(tmpString.find("unwtd events, lum (pb-1)") != string::npos) {
tmpString=trim(tmpString.substr(0,tmpString.find("!")));
unwev=atoi(trim(tmpString.substr(0,tmpString.find(" "))).c_str());
totlum=atof(trim(tmpString.substr(tmpString.find(" "))).c_str());
}
}
if(maxevents > unwev) {
cout << "-------------------------------\n";
cout << "requested " << maxevents << " > " << unwev << " (contained in file), will use all events.\n"; maxevents = 0; }
if(debugging>=4) {
cout << "\nDebugging initial reading of *_unw.par:\n";
cout << "ihrd = " << ihrd << "\n";
cout << "mc,mb,mt,mw,mz,mh = "
<< mc << " " << mb << " "
<< mt << " " << mw << " "
<< mz << " " << mh << "\n";
cout << "Cross section +/- error = "
<< avgwgt << " +/- " << errwgt << "\n";
cout << "Number of unweighted events = " << unwev << "\n";
cout << "Effective luminosity = " << totlum << "\n";
}
unwparStream.close();
unwparStream.open(unwparFilename.c_str());
int index;
while(unwparStream) {
getline(unwparStream,tmpString);
if(tmpString.find("!")==string::npos||
tmpString.find("hard process code")!=string::npos||
tmpString.find("mc,mb,mt,mw,mz,mh")!=string::npos||
tmpString.find("Crosssection +- error (pb)")!=string::npos||
tmpString.find("unwtd events, lum (pb-1)")!=string::npos) continue;
tmpString=trim(tmpString);
if(debugging>=4) cout << "\nDebugging reading paramters in *_unw.par:\n";
if(debugging>=4) cout << "File says: " << tmpString << "\n";
index = atoi((tmpString.substr(0,tmpString.find_first_of(" "))).c_str());
tmpString=trim(tmpString.substr(tmpString.find_first_of(" ")));
parval[index]=atof((tmpString.substr(0,tmpString.find_first_of(" "))).c_str());
tmpString=trim(tmpString.substr(tmpString.find_first_of("!")+1));
parstr[index]=tmpString;
if(debugging>=4) cout << "We say: "
<< index << " "
<< parval[index] << " "
<< parstr[index] << "\n\n\n\n\n";
}
unwparStream.close();
// Variables defined in parval array read from *_unw.par:
// PDG codes for the beam particles.
int idbmup[2]={0,0};
if(parstrToparval("ih1",&parstr,&parval)==1) idbmup[0] = 2212;
else if(parstrToparval("ih1",&parstr,&parval)==-1) idbmup[0] = -2212;
else idbmup[0] = 2212;
if(parstrToparval("ih2",&parstr,&parval)==1) idbmup[1] = 2212;
else if(parstrToparval("ih2",&parstr,&parval)==-1) idbmup[1] = -2212;
else idbmup[1] = 2212;
// Energies of the beam particles --- implementation implicitly assumes
// these are equal!
double ebmup[2]={0,0};
ebmup[0]=parstrToparval("ebeam",&parstr,&parval);
ebmup[1]=ebmup[0];
// LH accord pdf info variables for <init> block:
int pdfgup[2];
pdfgup[0]=-1; // Simply set to 1 as in POWHEG-BOX.
pdfgup[1]=-1;
int pdfsup[2];
// LHAPDF index: (note in POWHEG-BOX it is set to just -1).
pdfsup[0]=ndnsToLHAPDF(int(parstrToparval("ndns",&parstr,&parval)));
pdfsup[1]=pdfsup[0];
// LH accord flag defining weight scheme:
// N.B. AlpGen alpsho.f UPINIT uses idwtup = 3 (this is likely better from the
// point of view of combining events of diff multiplicity together in real life
// i.e. in ATLAS - so we should probably use it!).
int idwtup( 3); // As in POWHEG-BOX withnegweights 0 mode: unit wgts +1 only.
// int idwtup(-4); // As in POWHEG-BOX withnegweights 1 mode: +/- |xsecup| wgts only.
// Number of processes in the file (assume all one process as
// with alpsho.f UPINIT).
int nprup(1);
// Cross section, it's error, the maximum weight in the file.
double xsecup,xerrup,xmaxup;
xsecup = avgwgt;
xerrup = errwgt;
xmaxup = xsecup;
// Process id code (to be augmented by jet multiplicity - see just below).
int lprup(ihrd*100);
// We augment the process code (for the LH file only) by the number of
// (light) jets, just in case we end up connecting many different files
// to the shower MC in parallel (otherwise it likely won't distinguish
// between X+0,1,2,3,...,n jet processes).
int njets(int(parstrToparval("njets",&parstr,&parval)));
lprup+=njets;
// Write out some bits of info to the screen.
cout << "No. of jets: " << njets << "\n";
cout << "Total xsec in pb (all processes): " << scientific
<< xsecup << " +/- " << xerrup << "\n\n";
// NOW write out <init> block:
lheStream << "<init>\n";
lheStream << setw(9) << idbmup[0];
lheStream << setw(9) << idbmup[1];
lheStream << scientific << setprecision(5) << setw(13) << ebmup[0];
lheStream << scientific << setprecision(5) << setw(13) << ebmup[1];
lheStream << setw(7) << pdfgup[0];
lheStream << setw(7) << pdfgup[1];
if(usePowhegBoxConventions) {
lheStream << setw(7) << -1;
lheStream << setw(7) << -1;
} else {
lheStream << setw(7) << pdfsup[0];
lheStream << setw(7) << pdfsup[1];
}
lheStream << setw(7) << idwtup;
lheStream << setw(7) << nprup << "\n";
lheStream << scientific << setprecision(5) << setw(13) << xsecup;
lheStream << scientific << setprecision(5) << setw(13) << xerrup;
if(usePowhegBoxConventions)
lheStream << scientific << setprecision(5) << setw(13) << 1.0;
else // else put in more info (xmaxup=xsecup).
lheStream << scientific << setprecision(5) << setw(13) << xmaxup;
lheStream << setw(7) << lprup << "\n";
lheStream << "</init>\n";
// ************************************************* //
// All done with the init section of the LH file! //
// ************************************************* //
// ***************************************************************** //
// To write the HW++ .in file we have everything we could possibly //
// want except maybe the QCD coupling and no. of loops for running. //
// These are the only numbers we get / use from *.stat now. //
// ***************************************************************** //
double aqedup(-999),aqedStat(-999);
double aqcdup(-999),aqcdStat(-999);
int nloop(-999);
// Fish around for the QCD and QED alphas in .stat.
while(statStream) {
getline(statStream,tmpString);
if(tmpString.find("as(MZ)") != string::npos) {
aqcdup=atof(trim(tmpString.substr(tmpString.find_last_of("=")+1,
tmpString.length())).c_str());
tmpString=trim(tmpString.substr(tmpString.find_first_of("nloop=")));
tmpString=trim(tmpString.substr(tmpString.find_first_of(" ")));
tmpString=trim(tmpString.substr(0,tmpString.find_first_of("]")));
nloop=atoi(tmpString.c_str());
}
if(tmpString.find("aem(mZ)") != string::npos) {
tmpString=tmpString.substr(tmpString.find("aem(mZ)="));
tmpString=tmpString.substr(tmpString.find_first_of(" "));
tmpString=trim(tmpString);
aqedup=atof(tmpString.c_str());
aqedup=1/aqedup;
}
}
statStream.close();
aqedStat=aqedup;
aqcdStat=aqcdup;
// Write out a couple more bits of info to the screen.
cout << "aqcdup [as(MZ)] from stat file: " << aqcdup << "\n";
cout << "nloop for as from stat file : " << nloop << "\n";
cout << "aqedup [inverse] from stat file: " << 1/aqedup << "\n";
cout << "\n";
writeHWPPinFile(prefix,ihrd,unwev,pdfsup[0], idbmup[0], idbmup[1], idwtup,
aqcdup,nloop,
&alpgenParticleMasses,
&parval,&parstr);
// *********************************************************** //
// All done writing the HW++ .in file! //
// *********************************************************** //
// *********************************************************** //
// Start reading AlpGen events and writing them as LH events: //
// *********************************************************** //
int nupMax(20);
// First line of an event contains:
double nup(0),idprup(0),xwgtup(0),scalup(0);
// Subsequent lines for particle content contain:
vector<double> idup,istup;
vector<double> mothup1,mothup2; // WARNING: not implemented ... YET!
vector<double> icolup1,icolup2;
vector<double> vtimup,spinup; // WARNING: not implemented (but safe).
vector<vector<double> > pup;
pup.resize(5);
for (int ixx = 0; ixx <= 4; ++ixx)
pup[ixx].resize(nupMax);
// Initialise pup matrix (not really necessary):
for(unsigned int jup=0; jup < nupMax; jup++)
for(unsigned int ixx=0; ixx<5; ixx++) pup[ixx][jup]=0;
// Control reading AlpGen file:
int iup(0);
int counter(0);
bool readInWholeEvent(false),beginNewEvent(true);
double stringdoub;
// Needed as input to doIndividualHardProcessAssignments only:
int itopprc(nInt(parstrToparval("itopprc",&parstr,&parval)));
while(unwStream && (eventcount < maxevents || maxevents==0)) { // So long as we haven't hit the EOF do ...
if(beginNewEvent) {
// Rest / set control variables:
beginNewEvent=false;
readInWholeEvent=false;
counter=0;
iup=0;
// Reset variables for first line of LH event:
nup=0; idprup=0; xwgtup=0; scalup=0; aqedup=0; aqcdup=0;
// Reset variables for all individual particles in LH event:
idup.clear() ; istup.clear();
mothup1.clear(); mothup2.clear();
icolup1.clear(); icolup2.clear();
vtimup.clear() ; spinup.clear();
for(unsigned int jup=0; jup < nupMax; jup++)
for(unsigned int ixx=0; ixx<5; ixx++) pup[ixx][jup]=0;
}
// Read in next thing starting from last position in
// the file (int/real) as a double
unwStream >> stringdoub;
// counter counts the number of numbers read-in for a given
// event. On starting to read a new event counter will be 0.
counter++;
switch (counter) {
case 1: if(int(stringdoub)!=0) {
// if(int(stringdoub)%100==0)
// cout << "Processed " << fixed << setprecision(0)
// << stringdoub/unwev*100
// << " % of events ..." << "\r" << flush;
}
break;
case 2: idprup = stringdoub; break;
case 3: nup = stringdoub; break;
case 4: xwgtup = stringdoub; break;
case 5: scalup = stringdoub; break;
// N.B. There are no aqedup / aqcdup variables from AlpGen.
// Initial state particle +z direction:
case 6: idup.push_back(stringdoub) ;
istup.push_back(-1); break;
case 7: icolup1.push_back(stringdoub);
mothup1.push_back(0); break; // ATTENTION: not given by AlpGen
case 8: icolup2.push_back(stringdoub);
mothup2.push_back(0); break; // ATTENTION: not given by AlpGen
case 9: pup[2][iup]=stringdoub ;
pup[3][iup]=fabs(stringdoub) ; iup++ ; break;
// Initial state particle -z direction:
case 10: idup.push_back(stringdoub) ;
istup.push_back(-1); break;
case 11: icolup1.push_back(stringdoub);
mothup1.push_back(0); break; // ATTENTION: not given by AlpGen
case 12: icolup2.push_back(stringdoub);
mothup2.push_back(0); break; // ATTENTION: not given by AlpGen
case 13: pup[2][iup]=stringdoub;
pup[3][iup]=fabs(stringdoub) ; iup++ ; break;
}
if(debugging<5) idprup=lprup;
if(counter<14) continue;
// Final state particles:
if(counter==0+7*iup) idup.push_back(stringdoub);
// istup gets assigned later on to just -1/+1 (I.S. / F.S.).
if(counter==1+7*iup) { icolup1.push_back(stringdoub);
mothup1.push_back(1.); } // ATTENTION: not given by AlpGen
if(counter==2+7*iup) { icolup2.push_back(stringdoub);
mothup2.push_back(2.); } // ATTENTION: not given by AlpGen
if(counter==3+7*iup) pup[0][iup] = stringdoub;
if(counter==4+7*iup) pup[1][iup] = stringdoub;
if(counter==5+7*iup) pup[2][iup] = stringdoub;
if(counter==6+7*iup) pup[4][iup] = stringdoub;
if(counter==6+7*iup) istup.push_back(1.);
if(counter==6+7*iup) iup+=1;
if(counter==7*nup-1) readInWholeEvent = true;
for(int jup = 0; jup < nup; jup++) {
pup[3][jup] = sqrt( sqr(pup[4][jup]) + sqr(pup[0][jup])
+ sqr(pup[1][jup]) + sqr(pup[2][jup]) );
vtimup.push_back(0.); // ATTENTION: not implemented - so taking
spinup.push_back(9.); // POWHEG-BOX default values (should be v.safe).
}
// ***************************************************************** //
// Now consider assignments specific to individual hard processes: //
// ***************************************************************** //
if(readInWholeEvent)
doIndividualHardProcessAssignments(ihrd, &nup, &idup, &istup,
&mothup1 , &mothup2,
&icolup1 , &icolup2,
&pup ,
alpgenParticleMasses, itopprc);
if(readInWholeEvent) {
lheStream << "<event>\n";
if(debugging>=5) {
lheStream << nup << "\t" << idprup << "\t" << xwgtup << "\t"
<< scalup << "\t" << "0.007297352" << "\t" << "0.118\n";
} else {
// Bit about signing of xwgtup here is redundant as
// AlpGen only gives +ve weight events ...
double signOfXwgtup = xwgtup >= 0 ? 1 : -1;
xwgtup = idwtup==3 ? 1 : xsecup*signOfXwgtup;
// N.B. There are no aqedup / aqcdup variables from AlpGen
// events only the stat file has related information.
aqedup=aqedStat;
aqcdup=aqcdStat;
if(usePowhegBoxConventions) aqedup=-1;
lheStream << setw(7) << int(nup);
lheStream << setw(7) << int(idprup);
lheStream << scientific << setprecision(5) << setw(13) << xwgtup;
lheStream << scientific << setprecision(5) << setw(13) << scalup;
lheStream << scientific << setprecision(5) << setw(13) << aqedup;
lheStream << scientific << setprecision(5) << setw(13) << aqcdup;
lheStream << "\n";
}
for(int jup = 0; jup < nup; jup++) {
if(debugging>=5) {
lheStream << idup[jup] << "\t" << istup[jup] << "\t"
<< mothup1[jup] << "\t" << mothup2[jup] << "\t"
<< icolup1[jup] << "\t" << icolup2[jup] << "\t";
lheStream << pup[0][jup] << "\t" << pup[1][jup] << "\t"
<< pup[2][jup] << "\t" << pup[3][jup] << "\t"
<< pup[4][jup] << "\t";
lheStream << "0" << "\t" << "1\n";
} else {
if(icolup1[jup]!=0) icolup1[jup]+=500;
if(icolup2[jup]!=0) icolup2[jup]+=500;
lheStream << setw(8) << int(idup[jup]);
lheStream << setw(6) << int(istup[jup])
<< setw(6) << int(mothup1[jup])
<< setw(6) << int(mothup2[jup])
<< setw(6) << int(icolup1[jup])
<< setw(6) << int(icolup2[jup]);
lheStream << scientific << setprecision(9) << setw(17) << pup[0][jup];
lheStream << scientific << setprecision(9) << setw(17) << pup[1][jup];
lheStream << scientific << setprecision(9) << setw(17) << pup[2][jup];
lheStream << scientific << setprecision(9) << setw(17) << pup[3][jup];
lheStream << scientific << setprecision(9) << setw(17) << pup[4][jup];
lheStream << scientific << setprecision(5) << setw(13) << vtimup[jup];
lheStream << scientific << setprecision(3) << setw(11) << vtimup[jup];
lheStream << "\n";
}
}
lheStream << "</event>\n";
eventcount++;
cout << "Processed " << eventcount << " events ..." << "\r" << flush;
beginNewEvent=true;
}
}
cout << "\n\n";
if( maxevents!=0 ) {
cout << "All done (" << maxevents << " out of " << unwev << " events).\n";
} else {
cout << "All done (" << eventcount << " events).\n";
}
cout << "\n\n"
<< "Wrote a LH event file " << lheFilename
<< " and a HW++ MLM merging input file "
<< prefix+string(".in") << ".\n\n";
return 0;
}
inline double sqr(double x) { return x*x; }
int ndnsToLHAPDF(int ndns) {
// The information in this function is based on
// subroutine PRNTSF from alplib/alppdf.f, LHAPDF's
// PDFsets.index and, finally, the .stat output that
// results when the relevant ndns value is entered
// in the input file.
string Set("no PDF set found");
double Lambda_4(0),Lambda_5_2loop(0);
string Scheme("no PDF scheme");
int LHAPDFindex(-999);
string tmpString("");
if(ndns==1) {
Set = "CTEQ4M" ; Lambda_4 = 0.298 ; Lambda_5_2loop = 0.202 ; Scheme = "MS" ;
LHAPDFindex = 19150;
} else if(ndns==2) {
Set = "CTEQ4L" ; Lambda_4 = 0.298 ; Lambda_5_2loop = 0.202 ; Scheme = "MS" ;
LHAPDFindex = 19170;
} else if(ndns==3) {
Set = "CTEQ4HJ" ; Lambda_4 = 0.298 ; Lambda_5_2loop = 0.202 ; Scheme = "MS" ;
LHAPDFindex = -99999;
} else if(ndns==4) {
Set = "CTEQ5M" ; Lambda_4 = 0.326 ; Lambda_5_2loop = 0.226 ; Scheme = "MS" ;
LHAPDFindex = 19050;
} else if(ndns==5) {
Set = "CTEQ5L" ; Lambda_4 = 0.192 ; Lambda_5_2loop = 0.144 ; Scheme = "MS" ;
LHAPDFindex = 19070;
} else if(ndns==6) {
Set = "CTEQ5HJ" ; Lambda_4 = 0.326 ; Lambda_5_2loop = 0.226 ; Scheme = "MS" ;
LHAPDFindex = -99999;
} else if(ndns==7) {
Set = "CTEQ6M" ; Lambda_4 = 0.326 ; Lambda_5_2loop = 0.226 ; Scheme = "MS" ;
LHAPDFindex= 10050;
} else if(ndns==8) {
Set = "CTEQ6L" ; Lambda_4 = 0.326 ; Lambda_5_2loop = 0.226 ; Scheme = "MS" ;
LHAPDFindex = 10041;
} else if(ndns==9) {
Set = "CTEQ6L1" ; Lambda_4 = 0.215 ; Lambda_5_2loop = 0.167 ; Scheme = "MS" ;
LHAPDFindex = 10042;
} else if(ndns>=10&&ndns<=50) {
Set = "CTEQ6xx" ; Lambda_4 = 0.326 ; Lambda_5_2loop = 0.226 ; Scheme = "MS" ;
LHAPDFindex = 10150+(ndns-10);
} else if(ndns==101) {
Set = "MRST99" ; Lambda_4 = 0.321 ; Lambda_5_2loop = 0.220 ; Scheme = "MS" ;
LHAPDFindex = -99999;
} else if(ndns==102) {
Set = "MRST01" ; Lambda_4 = 0.342 ; Lambda_5_2loop = 0.239 ; Scheme = "MS" ;
LHAPDFindex = -99999;
} else if(ndns==103) {
Set = "MRST01" ; Lambda_4 = 0.310 ; Lambda_5_2loop = 0.214 ; Scheme = "MS" ;
LHAPDFindex = -99999;
} else if(ndns==104) {
Set = "MRST01" ; Lambda_4 = 0.378 ; Lambda_5_2loop = 0.267 ; Scheme = "MS" ;
LHAPDFindex = -99999;
} else if(ndns==105) {
Set = "MRST01J" ; Lambda_4 = 0.378 ; Lambda_5_2loop = 0.267 ; Scheme = "MS" ;
LHAPDFindex = -99999;
} else if(ndns==106) {
Set = "MRST02LO" ; Lambda_4 = 0.215 ; Lambda_5_2loop = 0.167 ; Scheme = "MS" ;
LHAPDFindex = -99999;
} else if(ndns==201) {
Set = "MSTW2008lo" ; Lambda_4 = 0.322 ; Lambda_5_2loop = 0.255 ; Scheme = "MS" ;
LHAPDFindex = 21000;
} else if(ndns==202) {
Set = "MSTW2008nlo" ; Lambda_4 = 0.365 ; Lambda_5_2loop = 0.255 ; Scheme = "MS" ;
LHAPDFindex = 21100;
} else if(ndns>=203&&ndns<=242) {
Set = "MSTW2008lo68cl"; Lambda_4 = 0.322 ; Lambda_5_2loop = 0.255 ; Scheme = "MS" ;
LHAPDFindex = 21000+(ndns-202);
} else if(ndns==243) {
Set = "MRST LO*" ; Lambda_4 = 0.365 ; Lambda_5_2loop = 0.255 ; Scheme = "MS" ;
LHAPDFindex = 20650;
} else if(ndns==244) {
Set = "MRST LO**" ; Lambda_4 = 0.280 ; Lambda_5_2loop = 0.190 ; Scheme = "MS" ;
LHAPDFindex = 20651;
} else if(ndns==301 ) {
Set = "CTQ6.6" ; Lambda_4 = 0.326 ; Lambda_5_2loop = 0.226 ; Scheme = "MS" ;
LHAPDFindex = 10550;
} else if(ndns>=302&&ndns<=345) {
Set = "CTQ66" ; Lambda_4 = 0.326 ; Lambda_5_2loop = 0.226 ; Scheme = "MS" ;
LHAPDFindex = 10550+(ndns-301);
} else if(ndns==346) {
Set = "CT09MC1" ; Lambda_4 = 0.215 ; Lambda_5_2loop = 0.167 ; Scheme = "MS" ;
LHAPDFindex = 10771;
} else if(ndns==347) {
Set = "CT09MC2" ; Lambda_4 = 0.326 ; Lambda_5_2loop = 0.226 ; Scheme = "MS" ;
LHAPDFindex = 10772;
}
cout << "-------------------------------\n";
cout << "ndnsToLHAPDF found: \n";
cout << "PDF set = " << Set << "\n";
cout << "ndns index = " << ndns << "\n";
cout << "LHAPDF index = " << LHAPDFindex << "\n";
cout << "-------------------------------\n\n";
return LHAPDFindex;
}
+string ndnsToLHAPDF_str(int ndns) {
+ // The information in this function is based on
+ // subroutine PRNTSF from alplib/alppdf.f, LHAPDF's
+ // PDFsets.index and, finally, the .stat output that
+ // results when the relevant ndns value is entered
+ // in the input file.
+ string Set("no PDF set found");
+ double Lambda_4(0),Lambda_5_2loop(0);
+ string Scheme("no PDF scheme");
+ int LHAPDFindex(-999);
+ string tmpString("");
+ string lhastring("");
+
+ if(ndns==1) {
+ Set = "CTEQ4M" ; Lambda_4 = 0.298 ; Lambda_5_2loop = 0.202 ; Scheme = "MS" ;
+ LHAPDFindex = 19150;
+ lhastring = "cteq6m";
+ } else if(ndns==2) {
+ Set = "CTEQ4L" ; Lambda_4 = 0.298 ; Lambda_5_2loop = 0.202 ; Scheme = "MS" ;
+ LHAPDFindex = 19170;
+ lhastring = "cteq4l";
+ } else if(ndns==3) {
+ Set = "CTEQ4HJ" ; Lambda_4 = 0.298 ; Lambda_5_2loop = 0.202 ; Scheme = "MS" ;
+ LHAPDFindex = -99999;
+ lhastring = "cteq4hj";
+ } else if(ndns==4) {
+ Set = "CTEQ5M" ; Lambda_4 = 0.326 ; Lambda_5_2loop = 0.226 ; Scheme = "MS" ;
+ LHAPDFindex = 19050;
+ lhastring = "cteq5m";
+ } else if(ndns==5) {
+ Set = "CTEQ5L" ; Lambda_4 = 0.192 ; Lambda_5_2loop = 0.144 ; Scheme = "MS" ;
+ LHAPDFindex = 19070;
+ lhastring = "cteq5l";
+
+ } else if(ndns==6) {
+ Set = "CTEQ5HJ" ; Lambda_4 = 0.326 ; Lambda_5_2loop = 0.226 ; Scheme = "MS" ;
+ LHAPDFindex = -99999;
+ lhastring = "cteq5hj";
+ } else if(ndns==7) {
+ Set = "CTEQ6M" ; Lambda_4 = 0.326 ; Lambda_5_2loop = 0.226 ; Scheme = "MS" ;
+ LHAPDFindex= 10050;
+ lhastring = "cteq6m";
+ } else if(ndns==8) {
+ Set = "CTEQ6L" ; Lambda_4 = 0.326 ; Lambda_5_2loop = 0.226 ; Scheme = "MS" ;
+ LHAPDFindex = 10041;
+ lhastring = "cteq6l";
+ } else if(ndns==9) {
+ Set = "CTEQ6L1" ; Lambda_4 = 0.215 ; Lambda_5_2loop = 0.167 ; Scheme = "MS" ;
+ LHAPDFindex = 10042;
+ lhastring = "cteq6l1";
+ } else if(ndns>=10&&ndns<=50) {
+ Set = "CTEQ6xx" ; Lambda_4 = 0.326 ; Lambda_5_2loop = 0.226 ; Scheme = "MS" ;
+ LHAPDFindex = 10150+(ndns-10);
+ lhastring = "cteq6xx";
+ } else if(ndns==101) {
+ Set = "MRST99" ; Lambda_4 = 0.321 ; Lambda_5_2loop = 0.220 ; Scheme = "MS" ;
+ LHAPDFindex = -99999;
+ lhastring = "mrst99";
+ } else if(ndns==102) {
+ Set = "MRST01" ; Lambda_4 = 0.342 ; Lambda_5_2loop = 0.239 ; Scheme = "MS" ;
+ LHAPDFindex = -99999;
+ lhastring = "mrst01";
+ } else if(ndns==103) {
+ Set = "MRST01" ; Lambda_4 = 0.310 ; Lambda_5_2loop = 0.214 ; Scheme = "MS" ;
+ LHAPDFindex = -99999;
+ } else if(ndns==104) {
+ Set = "MRST01" ; Lambda_4 = 0.378 ; Lambda_5_2loop = 0.267 ; Scheme = "MS" ;
+ LHAPDFindex = -99999;
+ lhastring = "mrst01";
+ } else if(ndns==105) {
+ Set = "MRST01J" ; Lambda_4 = 0.378 ; Lambda_5_2loop = 0.267 ; Scheme = "MS" ;
+ LHAPDFindex = -99999;
+ lhastring = "mrst01j";
+ } else if(ndns==106) {
+ Set = "MRST02LO" ; Lambda_4 = 0.215 ; Lambda_5_2loop = 0.167 ; Scheme = "MS" ;
+ LHAPDFindex = -99999;
+ lhastring = "mrst02lo";
+ } else if(ndns==201) {
+ Set = "MSTW2008lo" ; Lambda_4 = 0.322 ; Lambda_5_2loop = 0.255 ; Scheme = "MS" ;
+ LHAPDFindex = 21000;
+ } else if(ndns==202) {
+ Set = "MSTW2008nlo" ; Lambda_4 = 0.365 ; Lambda_5_2loop = 0.255 ; Scheme = "MS" ;
+ LHAPDFindex = 21100;
+ lhastring = "mstw2008nlo";
+ } else if(ndns>=203&&ndns<=242) {
+ Set = "MSTW2008lo68cl"; Lambda_4 = 0.322 ; Lambda_5_2loop = 0.255 ; Scheme = "MS" ;
+ LHAPDFindex = 21000+(ndns-202);
+ lhastring = "mstw2008lo68cl";
+ } else if(ndns==243) {
+ Set = "MRST LO*" ; Lambda_4 = 0.365 ; Lambda_5_2loop = 0.255 ; Scheme = "MS" ;
+ LHAPDFindex = 20650;
+ lhastring = "MRST2007lomod";
+ } else if(ndns==244) {
+ Set = "MRST LO**" ; Lambda_4 = 0.280 ; Lambda_5_2loop = 0.190 ; Scheme = "MS" ;
+ LHAPDFindex = 20651;
+ lhastring = "MRSTMCal";
+
+ } else if(ndns==301 ) {
+ Set = "CTQ6.6" ; Lambda_4 = 0.326 ; Lambda_5_2loop = 0.226 ; Scheme = "MS" ;
+ LHAPDFindex = 10550;
+ lhastring = "cteq66";
+ } else if(ndns>=302&&ndns<=345) {
+ Set = "CTQ66" ; Lambda_4 = 0.326 ; Lambda_5_2loop = 0.226 ; Scheme = "MS" ;
+ LHAPDFindex = 10550+(ndns-301);
+ lhastring = "cteq66";
+ } else if(ndns==346) {
+ Set = "CT09MC1" ; Lambda_4 = 0.215 ; Lambda_5_2loop = 0.167 ; Scheme = "MS" ;
+ LHAPDFindex = 10771;
+ lhastring = "CT09MC1";
+ } else if(ndns==347) {
+ Set = "CT09MC2" ; Lambda_4 = 0.326 ; Lambda_5_2loop = 0.226 ; Scheme = "MS" ;
+ LHAPDFindex = 10772;
+ lhastring = "CT09MC2";
+ }
+
+ cout << "-------------------------------\n";
+ cout << "ndnsToLHAPDF found: \n";
+ cout << "PDF set = " << Set << "\n";
+ cout << "ndns index = " << ndns << "\n";
+ cout << "LHAPDF index = " << LHAPDFindex << "\n";
+ cout << "-------------------------------\n\n";
+ return lhastring;
+
+}
+
+
double parstrToparval(string varName,
vector<string> * parstrPtr,
vector<double> * parvalPtr) {
for(unsigned int index=0; index<parvalPtr->size(); index++)
if(varName==parstrPtr->at(index))
return parvalPtr->at(index);
return -999.0;
}
string trim(string theString) {
int endStr = theString.find_last_not_of(" ");
int beginStr = theString.find_first_not_of(" ");
if(beginStr==0&&endStr==theString.length()-1) return theString; // No lead / trail spaces.
theString = theString.substr(beginStr,endStr-beginStr+1);
return theString;
}
void writeHWPPinFile(string prefix, int ihrd, int unwev,
int lhapdf, int idbmup0, int idbmup1, int idwtup,
double aqcdup, int nloop,
vector<double> * massesPtr,
vector<double> * parvalPtr,
vector<string> * parstrPtr) {
ofstream hwpp;
hwpp.open(string(prefix+".in").c_str());
hwpp << "#############################################################\n";
hwpp << "# Create an event generator taking the default LHCGenerator #\n";
hwpp << "# as the starting point ... #\n";
hwpp << "#############################################################\n";
hwpp << "cd /Herwig/Generators\n";
hwpp << "# Copy the default LHCGenerator with its settings to a new \n";
hwpp << "# which will be the basis of the one we use for showering: \n";
hwpp << "cp LHCGenerator theGenerator\n";
hwpp << "\n";
hwpp << "#############################################################\n";
hwpp << "# Create a LH event handler (set up & assigned below) ... #\n";
hwpp << "#############################################################\n";
hwpp << "cd /Herwig/EventHandlers\n";
hwpp << "library LesHouches.so\n";
hwpp << "create ThePEG::LesHouchesEventHandler theLesHouchesHandler\n";
hwpp << "\n";
hwpp << "#############################################################\n";
hwpp << "# Create a LH reader (set up & assigned below) ... #\n";
hwpp << "#############################################################\n";
hwpp << "cd /Herwig/EventHandlers\n";
hwpp << "#library BasicLesHouchesFileReader.so\n";
hwpp << "#create Herwig::BasicLesHouchesFileReader theLHReader\n";
hwpp << "library LesHouches.so\n";
hwpp << "create ThePEG::LesHouchesFileReader theLHReader\n";
hwpp << "\n";
hwpp << "#############################################################\n";
hwpp << "# Create an AlpGenHandler (set up & assigned below) ... #\n";
hwpp << "#############################################################\n";
hwpp << "cd /Herwig/Shower\n";
hwpp << "library AlpGenHandler.so\n";
hwpp << "create Herwig::AlpGenHandler AlpGenHandler\n";
hwpp << "\n";
hwpp << "#############################################################\n";
hwpp << "# Create an LHAPDF (set up & assigned below) ... #\n";
hwpp << "#############################################################\n";
hwpp << "cd /Herwig/Partons\n";
hwpp << "create ThePEG::LHAPDF thePDFset ThePEGLHAPDF.so\n";
hwpp << "\n";
hwpp << "############################################################\n";
hwpp << "# Create a cuts object ... #\n";
hwpp << "############################################################\n";
hwpp << "cd /Herwig/EventHandlers\n";
hwpp << "create ThePEG::Cuts /Herwig/Cuts/NoCuts\n";
hwpp << "\n";
hwpp << "#############################################################\n";
hwpp << "# Setup the LH event handler ... #\n";
hwpp << "#############################################################\n";
hwpp << "cd /Herwig/EventHandlers\n";
hwpp << "insert theLesHouchesHandler:LesHouchesReaders 0 theLHReader\n";
if(idwtup==3) {
hwpp << "set theLesHouchesHandler:WeightOption UnitWeight\n";
} else if(idwtup==-3) {
hwpp << "set theLesHouchesHandler:WeightOption NegUnitWeight\n";
} else if(idwtup==4) {
hwpp << "set theLesHouchesHandler:WeightOption VarWeight\n";
} else {
hwpp << "set theLesHouchesHandler:WeightOption VarNegWeight\n";
}
hwpp << "set theLesHouchesHandler:PartonExtractor "
<< "/Herwig/Partons/QCDExtractor\n";
hwpp << "set theLesHouchesHandler:CascadeHandler "
<< "/Herwig/Shower/AlpGenHandler\n";
hwpp << "set theLesHouchesHandler:HadronizationHandler "
<< "/Herwig/Hadronization/ClusterHadHandler\n";
hwpp << "set theLesHouchesHandler:DecayHandler "
<< "/Herwig/Decays/DecayHandler\n";
hwpp << "\n";
hwpp << "#############################################################\n";
hwpp << "# Set up the Evolver to veto hard emissions > scalup ... #\n";
hwpp << "#############################################################\n";
hwpp << "cd /Herwig/Shower\n";
hwpp << "# MaxTry 100 sets the maximum number of times to try \n";
hwpp << "# showering a given shower tree to 100. \n";
hwpp << "# HardVetoMode Yes to veto emissions with pT greater than pT_max.\n";
hwpp << "# HardVetoScaleSource Read means pT_max comes from hepeup.SCALUP.\n";
hwpp << "# This is what you need to set _along_with_ HardVetoMode Yes in \n";
hwpp << "# the case of Powheg external events _AND_ mc@nlo (we know this \n";
hwpp << "# from looking at the *MCinput file that mc@nlo generates). \n";
hwpp << "# MeCorrMode No turns off ME corrs. IntrinsicPtGaussian 2.2*GeV \n";
hwpp << "# is the RMS of intrinsic pT of Gaussian distribution: \n";
hwpp << "# 2*(1-Beta)*exp(-sqr(intrinsicpT/RMS))/sqr(RMS) \n";
hwpp << "set Evolver:MaxTry 100\n";
hwpp << "set Evolver:HardVetoMode Yes\n";
hwpp << "set Evolver:HardVetoScaleSource Read\n";
hwpp << "set Evolver:HardVetoReadOption PrimaryCollision\n";
hwpp << "set Evolver:MECorrMode No\n";
hwpp << "# Intrinsic pT etc should be set as part of a tune i.e. it \n";
hwpp << "# should either be left alone (default) or set by reading in \n";
hwpp << "# one of the tunes before theGenerator is created by copying \n";
hwpp << "# LHCGenerator (second line of this file). The following \n";
hwpp << "# settings were extracted from LHC-UE-EE-3-CTEQ6L1.in - In \n";
hwpp << "# light of some bad experience with MPI we prefer to set \n";
hwpp << "# these here manually rather than read try to read that .in. \n";
if(idbmup0 == 2212 && idbmup1 == -2212) {
- hwpp << "set /Herwig/UnderlyingEvent/KtCut:MinKT 2.26 \n";
- hwpp << "set /Herwig/UnderlyingEvent/UECuts:MHatMin 4.52 \n";
- hwpp << "set /Herwig/Shower/Evolver:IntrinsicPtGaussian 1.9*GeV \n";
+ hwpp << "#set /Herwig/UnderlyingEvent/KtCut:MinKT 2.26 \n";
+ hwpp << "#set /Herwig/UnderlyingEvent/UECuts:MHatMin 4.52 \n";
+ hwpp << "#set /Herwig/Shower/Evolver:IntrinsicPtGaussian 1.9*GeV \n";
} else {
- hwpp << "set /Herwig/UnderlyingEvent/KtCut:MinKT 2.752 \n";
- hwpp << "set /Herwig/UnderlyingEvent/UECuts:MHatMin 5.504 \n";
- hwpp << "set /Herwig/Shower/Evolver:IntrinsicPtGaussian 2.34*GeV \n";
+ hwpp << "#set /Herwig/UnderlyingEvent/KtCut:MinKT 2.752 \n";
+ hwpp << "#set /Herwig/UnderlyingEvent/UECuts:MHatMin 5.504 \n";
+ hwpp << "#set /Herwig/Shower/Evolver:IntrinsicPtGaussian 2.34*GeV \n";
}
hwpp << "# Colour reconnection (re)settings \n";
- hwpp << "set /Herwig/Hadronization/ColourReconnector:ColourReconnection Yes \n";
- hwpp << "set /Herwig/Hadronization/ColourReconnector:ReconnectionProbability 0.61\n";
+ hwpp << "#set /Herwig/Hadronization/ColourReconnector:ColourReconnection Yes \n";
+ hwpp << "#set /Herwig/Hadronization/ColourReconnector:ReconnectionProbability 0.61\n";
hwpp << "# Colour Disrupt settings \n";
- hwpp << "set /Herwig/Partons/RemnantDecayer:colourDisrupt 0.75 \n";
+ hwpp << "#set /Herwig/Partons/RemnantDecayer:colourDisrupt 0.75 \n";
hwpp << "# Inverse hadron radius \n";
- hwpp << "set /Herwig/UnderlyingEvent/MPIHandler:InvRadius 1.35 \n";
- hwpp << "set /Herwig/UnderlyingEvent/MPIHandler:softInt Yes \n";
- hwpp << "set /Herwig/UnderlyingEvent/MPIHandler:twoComp Yes \n";
- hwpp << "set /Herwig/UnderlyingEvent/MPIHandler:DLmode 2 \n";
+ hwpp << "#set /Herwig/UnderlyingEvent/MPIHandler:InvRadius 1.35 \n";
+ hwpp << "#set /Herwig/UnderlyingEvent/MPIHandler:softInt Yes \n";
+ hwpp << "#set /Herwig/UnderlyingEvent/MPIHandler:twoComp Yes \n";
+ hwpp << "#set /Herwig/UnderlyingEvent/MPIHandler:DLmode 2 \n";
hwpp << "\n";
hwpp << "#############################################################\n";
hwpp << "# Set up kinematics reconstructor (relevant only to mc@nlo) #\n";
hwpp << "#############################################################\n";
hwpp << "# Options for QTildeReconstructor - not needed for Powheg but\n";
hwpp << "# critical for mc@nlo. If using Powheg you may either leave \n";
hwpp << "# the next two settings as they are or comment them out as \n";
hwpp << "# you wish, for mc@nlo though you must leave them as they \n";
hwpp << "# are! ReconstructionOption General was the old default, it \n";
hwpp << "# ignores the colour structure for all processes - mc@nlo \n";
hwpp << "# will give you garbage unless you set this! \n";
hwpp << "# ReconstructionOption Colour is the new default - use the \n";
hwpp << "# colour structure of the process to determine the \n";
hwpp << "# reconstruction procedure. InitialInitialBoostOption \n";
hwpp << "# determines how the boost from the system before ISR to that\n";
hwpp << "# after ISR is applied. mc@nlo requires the old kinematics \n";
hwpp << "# reconstruction method: \n";
hwpp << "# InitialInitialBoostOption LongTransBoost - first apply a \n";
hwpp << "# longitudinal and then a transverse boost. Whereas the \n";
hwpp << "# default method now is InitialInitialBoostOption OneBoost - \n";
hwpp << "# apply one boost from old CMS to new CMS. Both options \n";
hwpp << "# should work with Powheg but probably it's best to use the \n";
hwpp << "# defaults in that case by simply commenting this setting. \n";
- hwpp << "set KinematicsReconstructor:ReconstructionOption General \n";
- hwpp << "set KinematicsReconstructor:InitialInitialBoostOption LongTransBoost\n";
+ hwpp << "#set KinematicsReconstructor:ReconstructionOption General \n";
+ hwpp << "#set KinematicsReconstructor:InitialInitialBoostOption LongTransBoost\n";
hwpp << "\n";
hwpp << "#############################################################\n";
hwpp << "# Set up the AlpGenHandler ... #\n";
hwpp << "#############################################################\n";
hwpp << "cd /Herwig/Shower\n";
hwpp << "set AlpGenHandler:MPIHandler /Herwig/UnderlyingEvent/MPIHandler\n";
hwpp << "set AlpGenHandler:RemDecayer /Herwig/Partons/RemnantDecayer\n";
hwpp << "set AlpGenHandler:Evolver Evolver\n";
hwpp << "set AlphaQCD:AlphaMZ " << aqcdup << "\n";
hwpp << "set AlphaQCD:NumberOfLoops " << nloop << "\n";
hwpp << "set AlpGenHandler:ShowerAlpha AlphaQCD\n";
hwpp << "# Calorimeter granularity settings used by GetJet algorithm\n";
hwpp << "set AlpGenHandler:NoCellsInRapidity 100\n";
hwpp << "set AlpGenHandler:NoCellsInPhi 60\n";
// AlpGen hard process code.
hwpp << "# AlpGen hard process code.\n";
hwpp << "set AlpGenHandler:ihrd " << ihrd << "\n";
// Number of (light) jets.
int njets(int(parstrToparval("njets",parstrPtr,parvalPtr)));
hwpp << "# No. of light jets in AlpGen process (the \"extra\" ones).\n";
hwpp << "set AlpGenHandler:njets " << njets << "\n";
// Mimimum jet pT use for generation.
double ptjmin(parstrToparval("ptjmin",parstrPtr,parvalPtr));
//// hwpp << "set AlpGenHandler:ptjmin " << ptjmin << "*GeV\n";
// Mimimum parton-parton R-sep used for generation.
double drjmin(parstrToparval("drjmin",parstrPtr,parvalPtr));
hwpp << "# Mimimum parton-parton R-sep used for generation.\n";
hwpp << "set AlpGenHandler:drjmin " << drjmin << "\n";
// Max |eta| for partons in generation.
double etajmax(parstrToparval("etajmax",parstrPtr,parvalPtr));
//// hwpp << "set AlpGenHandler:etajmax " << etajmax << "\n";
// Also probably want these variables fed to AlpGenHandler too ---
// they get set in the alpsho.f AHspar routine (note the list below
// does not include some variables from AHspar because they are already
// included in the above eg the PDFs are already handled so I removed
// ndns and also ptjmin drjmin are written out for the AlpGenHandler above).
int ickkw(int(parstrToparval("ickkw",parstrPtr,parvalPtr)));
//// hwpp << "set AlpGenHandler:ickkw " << ickkw << "\n";
int ihvy(int(parstrToparval("ihvy",parstrPtr,parvalPtr)));
hwpp << "# heavy flavour in WQQ,ZQQ,2Q etc (4=c, 5=b, 6=t):\n";
hwpp << "set AlpGenHandler:ihvy " << ihvy << "\n";
int ihvy2(int(parstrToparval("ihvy2",parstrPtr,parvalPtr)));
//// hwpp << "set AlpGenHandler:ihvy2 " << ihvy2 << "\n";
int itopprc(nInt(parstrToparval("itopprc",parstrPtr,parvalPtr)));
//// hwpp << "set AlpGenHandler:itopprc " << itopprc << "\n";
int nw(int(parstrToparval("nw",parstrPtr,parvalPtr)));
if(ihrd==13) {
nw=1; // N.B. nw is reassigned in this way
if(itopprc>=3) nw=2; // by UPEVNT (after UPINIT).
}
//// hwpp << "set AlpGenHandler:nw " << nw << "\n";
int nz(int(parstrToparval("nz",parstrPtr,parvalPtr)));
//// hwpp << "set AlpGenHandler:nz " << nz << "\n";
int nh(int(parstrToparval("nh",parstrPtr,parvalPtr)));
hwpp << "# Number of Higgses in the AlpGen process:\n";
hwpp << "set AlpGenHandler:nh " << nh << "\n";
int nph(int(parstrToparval("nph",parstrPtr,parvalPtr)));
hwpp << "# Number of photons in the AlpGen process:\n";
hwpp << "set AlpGenHandler:nph " << nph << "\n";
double ptbmin(parstrToparval("ptbmin",parstrPtr,parvalPtr));
//// hwpp << "set AlpGenHandler:ptbmin " << ptbmin << "\n";
double ptcmin(parstrToparval("ptcmin",parstrPtr,parvalPtr));
//// hwpp << "set AlpGenHandler:ptcmin " << ptcmin << "\n";
double ptlmin(parstrToparval("ptlmin",parstrPtr,parvalPtr));
//// hwpp << "set AlpGenHandler:ptlmin " << ptlmin << "\n";
double metmin(parstrToparval("metmin",parstrPtr,parvalPtr));
//// hwpp << "set AlpGenHandler:metmin " << metmin << "\n";
double ptphmin(parstrToparval("ptphmin",parstrPtr,parvalPtr));
//// hwpp << "set AlpGenHandler:ptphmin " << ptphmin << "\n";
double etabmax(parstrToparval("etabmax",parstrPtr,parvalPtr));
//// hwpp << "set AlpGenHandler:etabmax " << etabmax << "\n";
double etacmax(parstrToparval("etacmax",parstrPtr,parvalPtr));
//// hwpp << "set AlpGenHandler:etacmax " << etacmax << "\n";
double etalmax(parstrToparval("etalmax",parstrPtr,parvalPtr));
//// hwpp << "set AlpGenHandler:etalmax " << etalmax << "\n";
double etaphmax(parstrToparval("etaphmax",parstrPtr,parvalPtr));
//// hwpp << "set AlpGenHandler:etaphmax " << etaphmax << "\n";
double drbmin(parstrToparval("drbmin",parstrPtr,parvalPtr));
//// hwpp << "set AlpGenHandler:drbmin " << drbmin << "\n";
double drcmin(parstrToparval("drcmin",parstrPtr,parvalPtr));
//// hwpp << "set AlpGenHandler:drcmin " << drcmin << "\n";
double drlmin(parstrToparval("drlmin",parstrPtr,parvalPtr));
//// hwpp << "set AlpGenHandler:drlmin " << drlmin << "\n";
double drphjmin(parstrToparval("drphjmin",parstrPtr,parvalPtr));
//// hwpp << "set AlpGenHandler:drphjmin " << drphjmin << "\n";
double drphlmin(parstrToparval("drphlmin",parstrPtr,parvalPtr));
//// hwpp << "set AlpGenHandler:drphlmin " << drphlmin << "\n";
double drphmin(parstrToparval("drphmin",parstrPtr,parvalPtr));
//// hwpp << "set AlpGenHandler:drphmin " << drphmin << "\n";
double mllmin(parstrToparval("mllmin",parstrPtr,parvalPtr));
//// hwpp << "set AlpGenHandler:mllmin " << mllmin << "\n";
double mllmax(parstrToparval("mllmax",parstrPtr,parvalPtr));
//// hwpp << "set AlpGenHandler:mllmax " << mllmax << "\n";
hwpp << "\n";
hwpp << "#############################################################\n";
hwpp << "# Set up the LH reader ... #\n";
hwpp << "#############################################################\n";
hwpp << "cd /Herwig/EventHandlers\n";
hwpp << "set theLHReader:WeightWarnings false\n";
hwpp << "# Input event file name:\n";
hwpp << "set theLHReader:FileName " << prefix << ".lhe\n";
hwpp << "set theLHReader:MomentumTreatment RescaleEnergy\n";
hwpp << "# set theLHReader:IgnoreIDPRUP Yes\n";
hwpp << "set theLHReader:Cuts /Herwig/Cuts/NoCuts\n";
hwpp << "#set theLHReader:OverSampling ForbidOverSampling\n";
hwpp << "\n";
hwpp << "#############################################################\n";
hwpp << "# Set up the LHAPDF ... #\n";
hwpp << "#############################################################\n";
hwpp << "cd /Herwig/Partons\n";
hwpp << "# Don't try and find PDF index out from the LH file ...\n";
hwpp << "set /Herwig/EventHandlers/theLHReader:InitPDFs false\n";
hwpp << "# Instead set them explicitly here:\n";
+ // hwpp << "set thePDFset:PDFNumber " << lhapdf << "\n";
hwpp << "set thePDFset:PDFNumber " << lhapdf << "\n";
+
hwpp << "set thePDFset:RemnantHandler HadronRemnants\n";
hwpp << "set /Herwig/EventHandlers/theLHReader:PDFA thePDFset\n";
hwpp << "set /Herwig/EventHandlers/theLHReader:PDFB thePDFset\n";
hwpp << "set /Herwig/Particles/p+:PDF thePDFset\n";
hwpp << "set /Herwig/Particles/pbar-:PDF thePDFset\n";
hwpp << "# The PDF for beam particles A/B - overrides particle's own "
<< "PDF above\n";
hwpp << "set /Herwig/Shower/AlpGenHandler:PDFA thePDFset\n";
hwpp << "set /Herwig/Shower/AlpGenHandler:PDFB thePDFset\n";
hwpp << "set /Herwig/Shower/ShowerHandler:PDFA thePDFset\n";
hwpp << "set /Herwig/Shower/ShowerHandler:PDFB thePDFset\n";
hwpp << "\n";
hwpp << "####################################################\n";
hwpp << "# Set up the generator ... #\n";
hwpp << "####################################################\n";
hwpp << "cd /Herwig/Generators\n";
hwpp << "set theGenerator:EventHandler "
<< "/Herwig/EventHandlers/theLesHouchesHandler\n";
hwpp << "set theGenerator:NumberOfEvents " << unwev << "\n";
hwpp << "set theGenerator:RandomNumberGenerator:Seed 31122001\n";
hwpp << "set theGenerator:PrintEvent 10\n";
hwpp << "set theGenerator:MaxErrors 10000\n";
hwpp << "\n";
hwpp << "###################################################################\n";
hwpp << "# ReDefine particle data like it is in the AlpGen parameter file. #\n";
hwpp << "###################################################################\n";
hwpp << "\ncd /Herwig/Particles/ \n";
// 'if' statements needed here to protect against mc<ms (i.e. if AlpGen has mc=0
// for example). If this occurs then the QCD coupling can't initialise and the
// HW++ read step fails (due to matching at flavour thresholds etc).
if(massesPtr->at(0)>1.0) {
hwpp << "set c:NominalMass " << massesPtr->at(0) << "*GeV\n";
hwpp << "set cbar:NominalMass " << massesPtr->at(0) << "*GeV\n";
}
// Ditto.
if(massesPtr->at(0)>4.0) {
hwpp << "set b:NominalMass " << massesPtr->at(1) << "*GeV\n";
hwpp << "set bbar:NominalMass " << massesPtr->at(1) << "*GeV\n";
}
hwpp << "set t:NominalMass " << massesPtr->at(2) << "*GeV\n";
hwpp << "set tbar:NominalMass " << massesPtr->at(2) << "*GeV\n";
hwpp << "set W+:NominalMass " << massesPtr->at(3) << "*GeV\n";
hwpp << "set W-:NominalMass " << massesPtr->at(3) << "*GeV\n";
hwpp << "set Z0:NominalMass " << massesPtr->at(4) << "*GeV\n";
hwpp << "set h0:NominalMass " << massesPtr->at(5) << "*GeV\n";
hwpp << "\n\n\n\n\n";
hwpp << "######################################################### \n";
hwpp << "######################################################### \n";
hwpp << "## # \n";
hwpp << "## --- USER SERVICEABLE PART BELOW HERE ONLY ! --- # \n";
hwpp << "## # \n";
hwpp << "######################################################### \n";
hwpp << "######################################################### \n";
hwpp << "\n\n\n\n\n";
hwpp << "######################################################### \n";
hwpp << "# Option to off shower / hadronization / decays / MPI. # \n";
hwpp << "######################################################### \n";
hwpp << "cd /Herwig/EventHandlers \n";
hwpp << "# set theLesHouchesHandler:CascadeHandler NULL \n";
- hwpp << "set theLesHouchesHandler:HadronizationHandler NULL \n";
- hwpp << "set theLesHouchesHandler:DecayHandler NULL \n";
+ hwpp << "#set theLesHouchesHandler:HadronizationHandler NULL \n";
+ hwpp << "#set theLesHouchesHandler:DecayHandler NULL \n";
hwpp << "# The handler for multiple parton interactions \n";
- hwpp << "set /Herwig/Shower/AlpGenHandler:MPIHandler NULL \n";
+ hwpp << "#set /Herwig/Shower/AlpGenHandler:MPIHandler NULL \n";
hwpp << "\n\n";
hwpp << "######################################################### \n";
hwpp << "# Recommended key MLM merging parameters below - change # \n";
hwpp << "# for systematic error studies and / or at your peril. # \n";
hwpp << "######################################################### \n";
hwpp << "cd /Herwig/Shower\n";
hwpp << "# Is this the highest multiplicity ME in merging? \n";
hwpp << "# 0 = no, 1 = yes . \n";
hwpp << "set AlpGenHandler:highestMultiplicity 0 \n";
hwpp << "# Jet ET cut to apply in jet clustering in merging.\n";
double etclus(max(ptjmin+5,1.2*ptjmin));
hwpp << "set AlpGenHandler:ETClus " << etclus << "*GeV\n";
hwpp << "# Cone size used in clustering in merging.\n";
double rclus(drjmin);
hwpp << "set AlpGenHandler:RClus " << rclus << "\n";
hwpp << "# Max |eta| for jets in clustering in merging.\n";
double etaclmax(etajmax);
hwpp << "set AlpGenHandler:EtaClusMax " << etaclmax << "\n";
hwpp << "# Default 1.5 factor used to decide if a jet matches a parton\n";
hwpp << "# in merging: if DR(parton,jet)<rclusfactor*rclus the parton \n";
hwpp << "# and jet are said to have been matched.\n";
double rclusfactor(1.5);
hwpp << "set AlpGenHandler:RClusFactor " << rclusfactor << "\n";
hwpp << "\n\n";
hwpp << "################ \n";
hwpp << "# Save the run # \n";
hwpp << "################ \n";
hwpp << "cd /Herwig/Generators \n";
hwpp << "saverun " << prefix << " theGenerator\n";
}
// Now consider assignments specific to individual hard processes:
void doIndividualHardProcessAssignments(int ihrd , double * nup,
vector<double> * idup , vector<double> * istup,
vector<double> * mothup1, vector<double> * mothup2,
vector<double> * icolup1, vector<double> * icolup2,
vector<vector<double> > * pup,
vector<double> masses , int itopprc) {
int iwch(0);
// W/Z/gamma b bbar + jets ( wcjet*, ihrd=10 / wphjet*, ihrd=14 / wphqq*,
// ihrd=15 ), or W/Z + jets ( wjet*, ihrd=3 / zjet*, ihrd=4 ):
// In this case we add to the list of particles the single intermediate
// boson (at the end of the list) appropriately, and assign the relevant
// parent-daughter and colour flow indices.
if (ihrd<=4||ihrd==10||ihrd==14||ihrd==15) {
iwch=0; // <--- used to determine type: W/Z/gamma
for(int iup=int(*nup)-2; iup<int(*nup); iup++) {
(*mothup1)[iup]=*nup+1; // Assigning, to-be-added boson, as
(*mothup2)[iup]=0; // the parent of each decay prod.
if(ihrd!=2) iwch = iwch - (int((*idup)[iup])%2);
// electron+nubar -> 11 + (-12) => -(1)+0 = -1 => W-
// positron+nu -> -11+ 12 => -(-1)+0 = -1 => W+
// u dbar -> 2 -1 => 0 -(-1) = 1 => W+
// c dbar -> 4 -1 => W+
// etc.
}
// Now we start adding the intermediate boson entry:
int iup=nInt(*nup);
if(iwch>0) (*idup).push_back( 24);
else if(iwch<0) (*idup).push_back(-24);
else (*idup).push_back( 23);
(*istup).push_back(2);
(*mothup1).push_back(1);
(*mothup2).push_back(2);
(*pup).push_back(vector<double>(5));
double tmp = (*pup)[3][iup-2]+(*pup)[3][iup-1]; // Vector boson energy.
(*pup)[3][iup] = tmp;
tmp = sqr(tmp);
for(unsigned int ixx=0; ixx<=2; ixx++) {
(*pup)[ixx][iup] = (*pup)[ixx][iup-2]+(*pup)[ixx][iup-1];
tmp = tmp-sqr((*pup)[ixx][iup]); // Vector boson mass^2 when loop ends.
}
(*pup)[4][iup] = sqrt(tmp); // Set vector boson mass.
(*icolup1).push_back(0); // Set 1st colour line for vector boson.
(*icolup2).push_back(0); // Set 2nd colour line for vector boson.
(*nup) = (*nup)+1; // Increment number of particles to be read in the event.
}
// nW + mZ + kH + jets ( vbjet* / ihrd=5 ):
else if(ihrd==5) {
unsigned int ivstart(0),ivend(0);
// Identify the range of the Z and W bosons in the event (AlpGen conventions).
// Note the Z's and W's are the only things that decay - Higgs's and photons
// do not.
vector<unsigned int> bosonIndex;
for(unsigned int ixx=0; ixx<(*nup); ixx++)
if(abs((*idup)[ixx])==24||(*idup)[ixx]==23) {
(*istup)[ixx]=2; // Set the W/Z boson status to intermediate.
bosonIndex.push_back(ixx+1); // W/Z boson index in LH event record (1->nup).
}
unsigned int bosonCounter(nInt(*nup)-2*bosonIndex.size());
for(unsigned int ixx=0; ixx<bosonIndex.size(); ixx++) {
(*mothup1)[bosonCounter]=bosonIndex[ixx];
(*mothup2)[bosonCounter]=0;
bosonCounter++;
(*mothup1)[bosonCounter]=bosonIndex[ixx];
(*mothup2)[bosonCounter]=0;
bosonCounter++;
}
}
// t tbar + jets [ + photons ] ( 2Q*, ihrd=6 [ 2Qph*, ihrd=16 ] ):
else if ((ihrd==6||ihrd==16)&&abs((*idup)[2])==6) {
// Redefine the tops as intermediates in the event record.
(*istup)[2]=2;
(*istup)[3]=2;
unsigned int it(3),itb(4); // Index of t & tbar in evt.record (LH index).
if((*idup)[2]!=6) swap(it,itb);
// Reconstruct intermediate W's from the decay products.
for(unsigned int ixx=0; ixx<4;ixx++) {
(*idup).push_back(0);
(*istup).push_back(0);
(*mothup1).push_back(0);
(*mothup2).push_back(0);
(*icolup1).push_back(0);
(*icolup2).push_back(0);
(*pup).push_back(vector<double>(5));
}
for(unsigned int iw=1; iw<=2; iw++) {
int iwdec(nInt(*nup)-5+2*iw); // First of decay products for this W (iw).
int iwup(nInt(*nup)+iw); // Where the reco. W will go in evt.record (LH index).
int ibup(iwup+2); // Where the reco. b will go in evt.record (under the Ws).
int iwch(0);
for(unsigned int iup=iwdec; iup<=iwdec+1; iup++) {
(*mothup1)[iup-1]=iwup;
(*mothup2)[iup-1]=0;
iwch=iwch-int((*idup)[iup-1])%2; // iwch = charge of W boson.
// electron+nubar -> 11 + (-12) = -1 => W-
// d + ubar -> 1 + (-2) = -1 => W-
// positron+nu -> -11+ 12 = 1 => W+
// u + dbar -> 2 + (-1) = 1 => W+
}
// Make space for the b and W:
// Fill in b and W LH record entries:
if(iwch>0) {
(*idup)[iwup-1]=24;
(*idup)[ibup-1]=5;
(*mothup1)[iwup-1]=it;
(*mothup2)[iwup-1]=0;
(*mothup1)[ibup-1]=it;
(*mothup2)[ibup-1]=0;
} else if (iwch<0) {
(*idup)[iwup-1]=-24;
(*idup)[ibup-1]=-5;
(*mothup1)[iwup-1]=itb;
(*mothup2)[iwup-1]=0;
(*mothup1)[ibup-1]=itb;
(*mothup2)[ibup-1]=0;
}
(*istup)[iwup-1]=2; // The W is an intermediate and the
(*istup)[ibup-1]=1; // b is a final-state particle.
// Now reconstruct W boson momentum
double tmp=(*pup)[3][iwdec-1]+(*pup)[3][iwdec];
(*pup)[3][iwup-1]=tmp; // W energy.
tmp=sqr(tmp);
for(unsigned int ixx=0; ixx<=2; ixx++) {
(*pup)[ixx][iwup-1] = (*pup)[ixx][iwdec-1] // W's 3-mom.
+ (*pup)[ixx][iwdec];
tmp=tmp-sqr((*pup)[ixx][iwup-1]); // Equals m^2 at the end of the loop.
}
(*pup)[4][iwup-1]=sqrt(tmp); // W mass.
// Reconstruct b momentum
int itmp(nInt((*mothup1)[iwup-1]));
tmp=(*pup)[3][itmp-1]-(*pup)[3][iwup-1];
(*pup)[3][ibup-1]=tmp; // b energy.
tmp=sqr(tmp);
for(unsigned int ixx=0; ixx<=2; ixx++) {
(*pup)[ixx][ibup-1] = (*pup)[ixx][nInt((*mothup1)[iwup-1])-1] // b's 3mom.
- (*pup)[ixx][iwup-1];
tmp=tmp-sqr((*pup)[ixx][ibup-1]); // Equals m^2 at the end of the loop.
}
(*pup)[4][ibup-1]=sqrt(tmp); // b mass.
(*icolup1)[iwup-1]=0; // W has no colour
(*icolup2)[iwup-1]=0; // lines.
(*icolup1)[ibup-1]=(*icolup1)[nInt((*mothup1)[iwup-1])-1]; // b shares top
(*icolup2)[ibup-1]=(*icolup2)[nInt((*mothup1)[iwup-1])-1]; // colour line.
}
(*nup)+=4;
}
// H t tbar + jets ( QQh*, ihrd=8 ):
else if (ihrd==8&&abs((*idup)[3])==6) {
// Redefine the tops as intermediates in the event record.
(*istup)[3]=2;
(*istup)[4]=2;
unsigned int it(4),itb(5); // Index of t & tbar in evt.record (LH index).
if((*idup)[3]!=6) swap(it,itb);
// Reconstruct intermediate W's from the decay products.
for(unsigned int ixx=0; ixx<4;ixx++) {
(*idup).push_back(0);
(*istup).push_back(0);
(*mothup1).push_back(0);
(*mothup2).push_back(0);
(*icolup1).push_back(0);
(*icolup2).push_back(0);
(*pup).push_back(vector<double>(5));
}
for(unsigned int iw=1; iw<=2; iw++) {
int iwdec(nInt(*nup)-5+2*iw); // First of decay products for this W (iw).
int iwup(nInt(*nup)+iw); // Where the reco. W will go in evt.record (LH index).
int ibup(iwup+2); // Where the reco. b will go in evt.record (under the Ws).
int iwch(0);
for(unsigned int iup=iwdec; iup<=iwdec+1; iup++) {
(*mothup1)[iup-1]=iwup;
(*mothup2)[iup-1]=0;
iwch=iwch-int((*idup)[iup-1])%2; // iwch = charge of W boson.
// electron+nubar -> 11 + (-12) = -1 => W-
// d + ubar -> 1 + (-2) = -1 => W-
// positron+nu -> -11+ 12 = 1 => W+
// u + dbar -> 2 + (-1) = 1 => W+
}
if(iwch>0) {
(*idup)[iwup-1]=24;
(*idup)[ibup-1]=5;
(*mothup1)[iwup-1]=it;
(*mothup2)[iwup-1]=0;
(*mothup1)[ibup-1]=it;
(*mothup2)[ibup-1]=0;
} else if (iwch<0) {
(*idup)[iwup-1]=-24;
(*idup)[ibup-1]=-5;
(*mothup1)[iwup-1]=itb;
(*mothup2)[iwup-1]=0;
(*mothup1)[ibup-1]=itb;
(*mothup2)[ibup-1]=0;
}
(*istup)[iwup-1]=2; // The W is an intermediate and the
(*istup)[ibup-1]=1; // b is a final-state particle.
// Now reconstruct W boson momentum
double tmp=(*pup)[3][iwdec-1]+(*pup)[3][iwdec];
(*pup)[3][iwup-1]=tmp; // W energy.
tmp=sqr(tmp);
for(unsigned int ixx=0; ixx<=2; ixx++) {
(*pup)[ixx][iwup-1] = (*pup)[ixx][iwdec-1] // W's 3-mom.
+ (*pup)[ixx][iwdec];
tmp=tmp-sqr((*pup)[ixx][iwup-1]); // Equals m^2 at the end of the loop.
}
(*pup)[4][iwup-1]=sqrt(tmp); // W mass.
// Reconstruct b momentum
tmp=(*pup)[3][nInt((*mothup1)[iwup-1])-1]-(*pup)[3][iwup-1];
(*pup)[3][ibup-1]=tmp; // b energy.
tmp=sqr(tmp);
for(unsigned int ixx=0; ixx<=2; ixx++) {
(*pup)[ixx][ibup-1] = (*pup)[ixx][nInt((*mothup1)[iwup-1])-1] // b's 3mom.
- (*pup)[ixx][iwup-1];
tmp=tmp-sqr((*pup)[ixx][ibup-1]); // Equals m^2 at the end of the loop.
}
(*pup)[4][ibup-1]=sqrt(tmp); // b mass.
(*icolup1)[iwup-1]=0; // W has no colour
(*icolup2)[iwup-1]=0; // lines.
(*icolup1)[ibup-1]=(*icolup1)[nInt((*mothup1)[iwup-1])-1]; // b shares top
(*icolup2)[ibup-1]=(*icolup2)[nInt((*mothup1)[iwup-1])-1]; // colour line.
}
(*nup)+=4;
}
// Single top production ( top*, ihrd=13):
else if (ihrd==13) {
int nw=1;
if(itopprc>=3) nw=2;
// Assign a mass to the incoming bottom quark, if there is one,
// rescaling the energy to accommodate the mass.
for(unsigned int ixx=1; ixx<=2; ixx++) {
if(abs((*idup)[ixx-1])==5) {
(*pup)[4][ixx-1]=masses[1];
(*pup)[3][ixx-1]=sqrt(sqr((*pup)[2][ixx-1])+sqr((*pup)[4][ixx-1]));
}
}
// Set the top status to that of an intermediate.
(*istup)[2]=2;
// Get the index of the t / tbar in the evt. record (LH convention: 1->nup).
unsigned int it=0;
unsigned itb=0;
if((*idup)[2]==6) it=3;
else if((*idup)[2]==-6) itb=3;
else {
cout << "doIndividualHardProcessAssignments:\n"
<< "wrong assumption about top position.\n"
<< "Quitting ...";
exit(1);
}
// Reconstruct intermediate W's from the decay products.
// iwdec is the index of the first W decay product
unsigned int iwdec(nInt(*nup)-1); // LH conventions: 1->nup.
if(nw==2) iwdec=nInt(*nup)-3;
// The W and b will go at the end of the record.
unsigned int iwup(nInt(*nup)+1);
unsigned int ibup(nInt(*nup)+2);
int iwch(0);
for(unsigned int iup=iwdec; iup<=iwdec+1; iup++) {
(*mothup1)[iup-1]=iwup;
(*mothup2)[iup-1]=0;
iwch=iwch-int((*idup)[iup-1])%2; // iwch = charge of W boson.
// electron+nubar -> 11 + (-12) = -1 => W-
// d + ubar -> 1 + (-2) = -1 => W-
// positron+nu -> -11+ 12 = 1 => W+
// u + dbar -> 2 + (-1) = 1 => W+
}
for(unsigned int ixx=0; ixx<2;ixx++) {
(*idup).push_back(0);
(*istup).push_back(0);
(*mothup1).push_back(0);
(*mothup2).push_back(0);
(*icolup1).push_back(0);
(*icolup2).push_back(0);
(*pup).push_back(vector<double>(5));
}
if(iwch>0) {
(*idup)[iwup-1]=24;
(*idup)[ibup-1]=5;
(*mothup1)[iwup-1]=it;
(*mothup2)[iwup-1]=0;
(*mothup1)[ibup-1]=it;
(*mothup2)[ibup-1]=0;
} else if (iwch<0) {
(*idup)[iwup-1]=-24;
(*idup)[ibup-1]=-5;
(*mothup1)[iwup-1]=itb;
(*mothup2)[iwup-1]=0;
(*mothup1)[ibup-1]=itb;
(*mothup2)[ibup-1]=0;
}
(*istup)[iwup-1]=2;
(*istup)[ibup-1]=1;
// Now reconstruct W boson momentum
double tmp=(*pup)[3][iwdec-1]+(*pup)[3][iwdec];
(*pup)[3][iwup-1]=tmp; // W energy.
tmp=sqr(tmp);
for(unsigned int ixx=0; ixx<=2; ixx++) {
(*pup)[ixx][iwup-1] = (*pup)[ixx][iwdec-1] // W's 3-mom.
+ (*pup)[ixx][iwdec];
tmp=tmp-sqr((*pup)[ixx][iwup-1]); // Equals m^2 at the end of the loop.
}
(*pup)[4][iwup-1]=sqrt(tmp); // W mass.
// Reconstruct b momentum
tmp=(*pup)[3][nInt((*mothup1)[iwup-1])-1]-(*pup)[3][iwup-1];
(*pup)[3][ibup-1]=tmp; // b energy.
tmp=sqr(tmp);
for(unsigned int ixx=0; ixx<=2; ixx++) {
(*pup)[ixx][ibup-1] = (*pup)[ixx][nInt((*mothup1)[iwup-1])-1] // b's 3mom.
- (*pup)[ixx][iwup-1];
tmp=tmp-sqr((*pup)[ixx][ibup-1]); // Equals m^2 at the end of the loop.
}
(*pup)[4][ibup-1]=sqrt(tmp); // b mass.
(*icolup1)[iwup-1]=0;
(*icolup2)[iwup-1]=0;
(*icolup1)[ibup-1]=(*icolup1)[nInt((*mothup1)[iwup-1])-1];
(*icolup2)[ibup-1]=(*icolup2)[nInt((*mothup1)[iwup-1])-1];
(*nup)=(*nup)+2;
if(nw==2) {
// W DECAY
// iwdec is the index of the first W decay product.
iwdec=nInt(*nup)-3;
// iwup is the index of the W in the event record (LH conventions: 1->nup).
iwup=nInt(*nup)-6;
iwch=0;
int iwch(0);
for(unsigned int iup=iwdec; iup<=iwdec+1; iup++) {
(*mothup1)[iup-1]=iwup;
(*mothup2)[iup-1]=0;
iwch=iwch-int((*idup)[iup-1])%2; // iwch = charge of W boson.
// electron+nubar -> 11 + (-12) = -1 => W-
// d + ubar -> 1 + (-2) = -1 => W-
// positron+nu -> -11+ 12 = 1 => W+
// u + dbar -> 2 + (-1) = 1 => W+
}
(*istup)[iwup-1]=2;
(*icolup1)[iwup-1]=0;
(*icolup2)[iwup-1]=0;
}
}
return;
}
diff --git a/Contrib/AlpGen/BasicLesHouchesFileReader.cc b/Contrib/AlpGen/BasicLesHouchesFileReader.cc
--- a/Contrib/AlpGen/BasicLesHouchesFileReader.cc
+++ b/Contrib/AlpGen/BasicLesHouchesFileReader.cc
@@ -1,466 +1,466 @@
// -*- C++ -*-
//
// BasicLesHouchesFileReader.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 BasicLesHouchesFileReader class.
//
#include "BasicLesHouchesFileReader.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDF/PartonExtractor.h"
#include "ThePEG/PDF/NoPDF.h"
#include "ThePEG/Cuts/Cuts.h"
#include "ThePEG/EventRecord/TmpTransform.h"
#include "ThePEG/Utilities/UtilityBase.h"
using namespace Herwig;
BasicLesHouchesFileReader::
BasicLesHouchesFileReader(const BasicLesHouchesFileReader & x)
: LesHouchesReader(x), neve(x.neve), ieve(0),
LHFVersion(x.LHFVersion), outsideBlock(x.outsideBlock),
headerBlock(x.headerBlock), initComments(x.initComments),
initAttributes(x.initAttributes), eventComments(x.eventComments),
eventAttributes(x.eventAttributes),
theFileName(x.theFileName),overSampling_(x.overSampling_) {}
BasicLesHouchesFileReader::~BasicLesHouchesFileReader() {}
IBPtr BasicLesHouchesFileReader::clone() const {
return new_ptr(*this);
}
IBPtr BasicLesHouchesFileReader::fullclone() const {
return new_ptr(*this);
}
bool BasicLesHouchesFileReader::preInitialize() const {
return true;
}
void BasicLesHouchesFileReader::doinit() {
LesHouchesReader::doinit();
}
void BasicLesHouchesFileReader::initialize(LesHouchesEventHandler & eh) {
LesHouchesReader::initialize(eh);
if ( LHFVersion.empty() )
Throw<LesHouchesFileError>()
<< "The file associated with '" << name() << "' does not contain a "
<< "proper formatted Les Houches event file. The events may not be "
<< "properly sampled." << Exception::warning;
}
long BasicLesHouchesFileReader::scan() {
open();
// Shall we write the events to a cache file for fast reading? If so
// we write to a temporary file if the caches events should be
// randomized.
if ( cacheFileName().length() ) openWriteCacheFile();
// Keep track of the number of events scanned.
long neve = 0;
long cuteve = 0;
bool negw = false;
// If the open() has not already gotten information about subprocesses
// and cross sections we have to scan through the events.
if ( !heprup.NPRUP || cacheFile() || abs(heprup.IDWTUP) != 1 ) { // why scan if IDWTUP != 1?
HoldFlag<> isScanning(scanning);
double oldsum = 0.0;
vector<int> lprup;
vector<double> newmax;
vector<long> oldeve;
vector<long> neweve;
for ( int i = 0; ( maxScan() < 0 || i < maxScan() ) && readEvent(); ++i ) {
if ( !checkPartonBin() ) Throw<LesHouchesInitError>()
<< "Found event in LesHouchesReader '" << name()
<< "' which cannot be handeled by the assigned PartonExtractor '"
<< partonExtractor()->name() << "'." << Exception::runerror;
vector<int>::iterator idit =
find(lprup.begin(), lprup.end(), hepeup.IDPRUP);
int id = lprup.size();
if ( idit == lprup.end() ) {
lprup.push_back(hepeup.IDPRUP);
newmax.push_back(0.0);
neweve.push_back(0);
oldeve.push_back(0);
} else {
id = idit - lprup.begin();
}
++neve;
++oldeve[id];
oldsum += hepeup.XWGTUP;
if ( cacheFile() ) {
if ( eventWeight() == 0.0 ) {
++cuteve;
continue;
}
cacheEvent();
}
++neweve[id];
newmax[id] = max(newmax[id], abs(eventWeight()));
if ( eventWeight() < 0.0 ) negw = true;
}
xSecWeights.resize(oldeve.size(), 1.0);
for ( int i = 0, N = oldeve.size(); i < N; ++i )
if ( oldeve[i] ) xSecWeights[i] = double(neweve[i])/double(oldeve[i]);
if ( maxScan() < 0 || neve > NEvents() ) NEvents(neve - cuteve);
if ( lprup.size() == heprup.LPRUP.size() ) {
for ( int id = 0, N = lprup.size(); id < N; ++id ) {
vector<int>::iterator idit =
find(heprup.LPRUP.begin(), heprup.LPRUP.end(), hepeup.IDPRUP);
if ( idit == heprup.LPRUP.end() ) {
Throw<LesHouchesInitError>()
<< "When scanning events, the LesHouschesReader '" << name()
<< "' found undeclared processes." << Exception::warning;
heprup.NPRUP = 0;
break;
}
int idh = idit - heprup.LPRUP.begin();
heprup.XMAXUP[idh] = newmax[id];
}
}
if ( heprup.NPRUP == 0 ) {
// No heprup block was supplied or something went wrong.
heprup.NPRUP = lprup.size();
heprup.LPRUP.resize(lprup.size());
heprup.XMAXUP.resize(lprup.size());
for ( int id = 0, N = lprup.size(); id < N; ++id ) {
heprup.LPRUP[id] = lprup[id];
heprup.XMAXUP[id] = newmax[id];
}
} else if ( abs(heprup.IDWTUP) != 1 ) {
// Try to fix things if abs(heprup.IDWTUP) != 1.
double sumxsec = 0.0;
for ( int id = 0; id < heprup.NPRUP; ++id ) sumxsec += heprup.XSECUP[id];
weightScale = picobarn*neve*sumxsec/oldsum;
}
}
if ( cacheFile() ) closeCacheFile();
if ( negw ) heprup.IDWTUP = min(-abs(heprup.IDWTUP), -1);
return neve;
}
void BasicLesHouchesFileReader::open() {
if ( filename().empty() )
throw LesHouchesFileError()
<< "No Les Houches file name. "
<< "Use 'set " << name() << ":FileName'."
<< Exception::runerror;
cfile.open(filename());
if ( !cfile )
throw LesHouchesFileError()
<< "The BasicLesHouchesFileReader '" << name() << "' could not open the "
<< "event file called '" << theFileName << "'."
<< Exception::runerror;
cfile.readline();
if ( !cfile.find("<LesHouchesEvents") ) return;
map<string,string> attributes =
StringUtils::xmlAttributes("LesHouchesEvents", cfile.getline());
LHFVersion = attributes["version"];
if ( LHFVersion.empty() ) return;
bool readingHeader = false;
bool readingInit = false;
headerBlock = "";
// Loop over all lines until we hit the </init> tag.
while ( cfile.readline() && !cfile.find("</init>") ) {
if ( cfile.find("<header") ) {
// We have hit the header block, so we should dump this and all
// following lines to headerBlock until we hit the end of it.
readingHeader = true;
headerBlock = cfile.getline() + "\n";
}
else if ( cfile.find("<init") ) {
// We have hit the init block, so we should expect to find the
// standard information in the following. But first check for
// attributes.
initAttributes = StringUtils::xmlAttributes("init", cfile.getline());
readingInit = true;
cfile.readline();
if ( !( cfile >> heprup.IDBMUP.first >> heprup.IDBMUP.second
>> heprup.EBMUP.first >> heprup.EBMUP.second
>> heprup.PDFGUP.first >> heprup.PDFGUP.second
>> heprup.PDFSUP.first >> heprup.PDFSUP.second
>> heprup.IDWTUP >> heprup.NPRUP ) ) {
heprup.NPRUP = -42;
LHFVersion = "";
return;
}
heprup.resize();
for ( int i = 0; i < heprup.NPRUP; ++i ) {
cfile.readline();
if ( !( cfile >> heprup.XSECUP[i] >> heprup.XERRUP[i]
>> heprup.XMAXUP[i] >> heprup.LPRUP[i] ) ) {
heprup.NPRUP = -42;
LHFVersion = "";
return;
}
}
}
else if ( cfile.find("</header") ) {
readingHeader = false;
headerBlock += cfile.getline() + "\n";
}
else if ( readingHeader ) {
// We are in the process of reading the header block. Dump the
// line to headerBlock.
headerBlock += cfile.getline() + "\n";
}
else if ( readingInit ) {
// Here we found a comment line. Dump it to initComments.
initComments += cfile.getline() + "\n";
}
else {
// We found some other stuff outside the standard tags.
outsideBlock += cfile.getline() + "\n";
}
}
if ( !cfile ) {
heprup.NPRUP = -42;
LHFVersion = "";
return;
}
}
bool BasicLesHouchesFileReader::readEvent() {
reset();
if ( !doReadEvent() ) return false;
// If we are just skipping event we do not need to reweight or do
// anything fancy.
if ( skipping ) return true;
if ( cacheFile() && !scanning ) return true;
// Reweight according to the re- and pre-weights objects in the
// LesHouchesReader base class.
lastweight = reweight();
if ( !reweightPDF && !cutEarly() ) return true;
// We should try to reweight the PDFs or make early cuts here.
fillEvent();
double x1 = incoming().first->momentum().plus()/
beams().first->momentum().plus();
if ( reweightPDF &&
inPDF.first && outPDF.first && inPDF.first != outPDF.first ) {
if ( hepeup.XPDWUP.first <= 0.0 )
hepeup.XPDWUP.first =
inPDF.first->xfx(inData.first, incoming().first->dataPtr(),
sqr(hepeup.SCALUP*GeV), x1);
double xf = outPDF.first->xfx(inData.first, incoming().first->dataPtr(),
sqr(hepeup.SCALUP*GeV), x1);
lastweight *= xf/hepeup.XPDWUP.first;
hepeup.XPDWUP.first = xf;
}
double x2 = incoming().second->momentum().minus()/
beams().second->momentum().minus();
if ( reweightPDF &&
inPDF.second && outPDF.second && inPDF.second != outPDF.second ) {
if ( hepeup.XPDWUP.second <= 0.0 )
hepeup.XPDWUP.second =
inPDF.second->xfx(inData.second, incoming().second->dataPtr(),
sqr(hepeup.SCALUP*GeV), x2);
double xf =
outPDF.second->xfx(inData.second, incoming().second->dataPtr(),
sqr(hepeup.SCALUP*GeV), x2);
lastweight *= xf/hepeup.XPDWUP.second;
hepeup.XPDWUP.second = xf;
}
if ( cutEarly() ) {
if ( !cuts().initSubProcess((incoming().first->momentum() +
incoming().second->momentum()).m2(),
0.5*log(x1/x2)) ) lastweight = 0.0;
tSubProPtr sub = getSubProcess();
TmpTransform<tSubProPtr> tmp(sub, Utilities::getBoostToCM(sub->incoming()));
if ( !cuts().passCuts(*sub) ) lastweight = 0.0;
}
return true;
}
double BasicLesHouchesFileReader::getEvent() {
if ( cacheFile() ) {
if (overSampling_) {
if ( !uncacheEvent() ) reopen();
} else {
if ( !uncacheEvent() || stats.attempts()==NEvents() )
throw LesHouchesReopenWarning()
<< "More events requested than available in LesHouchesReader "
<< name() << Exception::runerror;
}
} else {
if (overSampling_) {
if ( !readEvent() ) reopen();
} else {
if ( !readEvent() || stats.attempts()==NEvents() )
throw LesHouchesReopenWarning()
<< "More events requested than available in LesHouchesReader "
<< name() << Exception::runerror;
}
}
++position;
double max = maxWeights[hepeup.IDPRUP]*maxFactor;
return max != 0.0? eventWeight()/max: 0.0;
}
void BasicLesHouchesFileReader::skip(long n) {
HoldFlag<> skipflag(skipping);
if(overSampling_) while ( n-- ) getEvent();
}
bool BasicLesHouchesFileReader::doReadEvent() {
if ( !cfile ) return false;
if ( LHFVersion.empty() ) return false;
if ( heprup.NPRUP < 0 ) return false;
eventComments = "";
outsideBlock = "";
hepeup.NUP = 0;
hepeup.XPDWUP.first = hepeup.XPDWUP.second = 0.0;
// Keep reading lines until we hit the next event or the end of
// the event block. Save any inbetween lines. Exit if we didn't
// find an event.
while ( cfile.readline() && !cfile.find("<event") )
outsideBlock += cfile.getline() + "\n";
// We found an event. First scan for attributes.
eventAttributes = StringUtils::xmlAttributes("event", cfile.getline());
if ( !cfile.readline() ) return false;
// The first line determines how many subsequent particle lines we
// have.
if ( !( cfile >> hepeup.NUP >> hepeup.IDPRUP >> hepeup.XWGTUP
>> hepeup.SCALUP >> hepeup.AQEDUP >> hepeup.AQCDUP ) )
return false;
hepeup.resize();
// Read all particle lines.
for ( int i = 0; i < hepeup.NUP; ++i ) {
if ( !cfile.readline() ) return false;
if ( !( cfile >> hepeup.IDUP[i] >> hepeup.ISTUP[i]
>> hepeup.MOTHUP[i].first >> hepeup.MOTHUP[i].second
>> hepeup.ICOLUP[i].first >> hepeup.ICOLUP[i].second
>> hepeup.PUP[i][0] >> hepeup.PUP[i][1] >> hepeup.PUP[i][2]
>> hepeup.PUP[i][3] >> hepeup.PUP[i][4]
>> hepeup.VTIMUP[i] >> hepeup.SPINUP[i] ) )
return false;
- if(isnan(hepeup.PUP[i][0])||isnan(hepeup.PUP[i][1])||
- isnan(hepeup.PUP[i][2])||isnan(hepeup.PUP[i][3])||
- isnan(hepeup.PUP[i][4]))
+ if(std::isnan(hepeup.PUP[i][0])||std::isnan(hepeup.PUP[i][1])||
+ std::isnan(hepeup.PUP[i][2])||std::isnan(hepeup.PUP[i][3])||
+ std::isnan(hepeup.PUP[i][4]))
throw Exception()
<< "nan's as momenta in Les Houches file "
<< Exception::eventerror;
}
// Now read any additional comments.
while ( cfile.readline() && !cfile.find("</event>") )
eventComments += cfile.getline() + "\n";
if ( !cfile ) return false;
return true;
}
void BasicLesHouchesFileReader::close() {
cfile.close();
}
void BasicLesHouchesFileReader::persistentOutput(PersistentOStream & os) const {
os << neve << LHFVersion << outsideBlock << headerBlock << initComments
<< initAttributes << eventComments << eventAttributes << theFileName
<< overSampling_;
}
void BasicLesHouchesFileReader::persistentInput(PersistentIStream & is, int) {
is >> neve >> LHFVersion >> outsideBlock >> headerBlock >> initComments
>> initAttributes >> eventComments >> eventAttributes >> theFileName
>> overSampling_;
ieve = 0;
}
ClassDescription<BasicLesHouchesFileReader>
BasicLesHouchesFileReader::initBasicLesHouchesFileReader;
// Definition of the static class description member.
void BasicLesHouchesFileReader::Init() {
static ClassDocumentation<BasicLesHouchesFileReader> documentation
("Herwig::BasicLesHouchesFileReader is an base class to be used for objects "
"which reads event files from matrix element generators. This class is "
"able to read plain event files conforming to the Les Houches Event File "
"accord.");
static Parameter<BasicLesHouchesFileReader,string> interfaceFileName
("FileName",
"The name of a file containing events conforming to the Les Houches "
"protocol to be read into ThePEG. A file name ending in "
"<code>.gz</code> will be read from a pipe which uses "
"<code>zcat</code>. If a file name ends in <code>|</code> the "
"preceeding string is interpreted as a command, the output of which "
"will be read through a pipe.",
&BasicLesHouchesFileReader::theFileName, "", false, false);
static Switch<BasicLesHouchesFileReader,bool> interfaceOverSampling
("OverSampling",
"Allow / Forbid reading of LH events more than once by the "
"LH reader, allowing / protecting against statistical problems.",
&BasicLesHouchesFileReader::overSampling_, true, false, false);
static SwitchOption AllowOverSampling
(interfaceOverSampling,
"AllowOverSampling",
"The reader will read events in the file more than once if more "
"events are needed to generate the requested number than that in "
"the LH file.",
true);
static SwitchOption ForbidOverSampling
(interfaceOverSampling,
"ForbidOverSampling",
"The reader will NOT read events in the file more than once if more "
"events are needed to generate the requested number than that in "
"the LH file - instead it will stop when all have been read.",
false);
interfaceFileName.fileType();
interfaceFileName.rank(11);
}
diff --git a/Contrib/Analysis2/Histogram2/Histogram2.cc b/Contrib/Analysis2/Histogram2/Histogram2.cc
--- a/Contrib/Analysis2/Histogram2/Histogram2.cc
+++ b/Contrib/Analysis2/Histogram2/Histogram2.cc
@@ -1,717 +1,717 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the Histogram2 class.
//
#include "Histogram2.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#ifdef ThePEG_TEMPLATES_IN_CC_FILE
// #include "Histogram2.tcc"
#endif
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Utilities/Throw.h"
using namespace Analysis2;
void HistogramChannel::persistentOutput(PersistentOStream & os) const {
os << _isCountingChannel << _bins << _binEntries << _outOfRange << _visible
<< _total << _nanEvents << _nanWeights << _finished;
}
void HistogramChannel::persistentInput(PersistentIStream & is) {
is >> _isCountingChannel >> _bins >> _binEntries >> _outOfRange >> _visible
>> _total >> _nanEvents >> _nanWeights >> _finished;
}
HistogramChannel& HistogramChannel::operator += (const HistogramChannel& c) {
if (!c.isCountingChannel()) _isCountingChannel = false;
for (unsigned int i = 0; i < _bins.size(); ++i) {
_bins[i].first += c.bin(i).first;
_bins[i].second += c.bin(i).second;
}
// uppon addition of a counting channel it remains a counting channel
if (_isCountingChannel) {
for (unsigned int i = 0; i < _bins.size(); ++i) {
_binEntries[i] += c.binEntries()[i];
_nanWeights[i] += c.nanWeights()[i];
}
_outOfRange.first += c.outOfRange().first;
_outOfRange.second += c.outOfRange().second;
_total += c.total();
_visible += c.visible();
_nanEvents += c.nanEvents();
}
return *this;
}
HistogramChannel& HistogramChannel::operator -= (const HistogramChannel& c) {
for (unsigned int i = 0; i < _bins.size(); ++i) {
_bins[i].first -= c.bin(i).first;
_bins[i].second += c.bin(i).second;
}
_isCountingChannel = false;
return *this;
}
HistogramChannel& HistogramChannel::operator *= (const HistogramChannel& c) {
for (unsigned int i = 0; i < _bins.size(); ++i) {
_bins[i].first *= c.bin(i).first;
_bins[i].second =
_bins[i].second*sqr(c.bin(i).first)+c.bin(i).second*sqr(_bins[i].first);
}
_isCountingChannel = false;
return *this;
}
HistogramChannel& HistogramChannel::operator *= (double factor) {
for (vector<pair<double,double> >::iterator b = _bins.begin();
b != _bins.end(); ++b) {
b->first *= factor;
b->second *= sqr(factor);
}
_isCountingChannel = false;
return *this;
}
HistogramChannel& HistogramChannel::operator += (double off) {
for (vector<pair<double,double> >::iterator b = _bins.begin();
b != _bins.end(); ++b) {
b->first += off;
}
_isCountingChannel = false;
return *this;
}
HistogramChannel& HistogramChannel::operator *= (pair<double,double> factor) {
for (vector<pair<double,double> >::iterator b = _bins.begin();
b != _bins.end(); ++b) {
b->first *= factor.first;
b->second = b->first*factor.second + b->second*sqr(factor.first);
}
_isCountingChannel = false;
return *this;
}
HistogramChannel& HistogramChannel::operator /= (pair<double,double> factor) {
for (vector<pair<double,double> >::iterator b = _bins.begin();
b != _bins.end(); ++b) {
if (factor.first != 0.) {
b->first /= factor.first;
if (b->first != 0.)
b->second = sqr(b->first/factor.first)*(b->second/sqr(b->first) + factor.second/sqr(factor.first));
else
b->second = 0.;
} else {
b->first = 0.;
b->second = 0.;
}
}
_isCountingChannel = false;
return *this;
}
HistogramChannel& HistogramChannel::operator /= (const HistogramChannel& c) {
for (unsigned int i = 0; i < _bins.size(); ++i) {
if (c.bin(i).first != 0. && _bins[i].first != 0.) {
_bins[i].first /= c.bin(i).first;
_bins[i].second = sqr(_bins[i].first/c.bin(i).first)*
(_bins[i].second/sqr(_bins[i].first)+c.bin(i).second/sqr(c.bin(i).first));
} else {
_bins[i].first = 0.;
_bins[i].second = 0.;
}
}
_isCountingChannel = false;
return *this;
}
unsigned long HistogramChannel::nanWeightEvents () const {
unsigned long all = 0;
for (vector<unsigned long>::const_iterator n = _nanWeights.begin();
n != _nanWeights.end(); ++n)
all += *n;
return all;
}
void HistogramChannel::differential (const vector<pair<double,double> >& binning) {
for (unsigned int i=0; i<binning.size(); ++i) {
_bins[i].first /= (binning[i].second-binning[i].first);
_bins[i].second /= (binning[i].second-binning[i].first);
}
}
pair<double,double> HistogramChannel::binSum () const {
pair<double,double> s = make_pair(0.,0.);
for (vector<pair<double,double> >::const_iterator b = _bins.begin();
b != _bins.end(); ++b) {
s.first += b->first;
s.second += b->second;
}
return s;
}
pair<double,double> HistogramChannel::integrate (const vector<pair<double,double> >& binning) const {
pair<double,double> integral = make_pair(0.,0.);
for (unsigned int i = 0; i< _bins.size(); ++i) {
integral.first += (binning[i].second-binning[i].first)*_bins[i].first;
integral.second += sqr(binning[i].second-binning[i].first)*_bins[i].second;
}
return integral;
}
pair<double,double> HistogramChannel::average (const vector<pair<double,double> >& binning) const {
pair<double,double> integral = make_pair(0.,0.);
double volume = 0.;
for (unsigned int i = 0; i< _bins.size(); ++i) {
volume += (binning[i].second-binning[i].first);
integral.first += (binning[i].second-binning[i].first)*_bins[i].first;
integral.second += sqr(binning[i].second-binning[i].first)*_bins[i].second;
}
integral.first /= volume;
integral.second /= sqr(volume);
return integral;
}
HistogramChannel HistogramChannel::delta (const HistogramChannel& channel) const {
HistogramChannel c(*this);
c /= channel; c += -1.;
return c;
}
HistogramChannel HistogramChannel::chi2 (const HistogramChannel& channel, double minfrac) const {
HistogramChannel chi2 (*this);
chi2 -= channel;
chi2 *= chi2;
for (unsigned int i = 0; i<_bins.size(); ++i) {
double var = 0.;
if (channel.bin(i).second/sqr(channel.bin(i).first) < minfrac)
var = sqr(minfrac*channel.bin(i).first);
else var = channel.bin(i).second;
if (var != 0)
chi2.bin(i,make_pair(chi2.bin(i).first/var,chi2.bin(i).second/var));
else
chi2.bin(i,make_pair(0,0));
}
return chi2;
}
Histogram2::Histogram2 (double low, double high,
unsigned int bins,
const string& name) {
// get the bin length
double length = (high-low)/(double)(bins);
_range = make_pair(low,high);
for (unsigned int i = 0; i<bins; ++i) {
_binning.push_back(make_pair(low+i*length,low+(i+1)*length));
_binhash.insert(make_pair(low+(i+1)*length,i));
}
if (!name.empty()) insertChannel(name);
}
Histogram2::Histogram2 (const vector<pair<double,double> >& binning, const string& name) {
_range = make_pair(binning.begin()->first,binning.end()->second);
_binning = binning;
for (unsigned int i = 0; i<_binning.size(); ++i) {
_binhash.insert(make_pair(_binning[i].second,i));
}
_range = make_pair(_binning.front().first,_binning.back().second);
if (!name.empty()) insertChannel(name);
}
Histogram2::Histogram2 (const string& dataFile, const string& dataName) {
ifstream data (dataFile.c_str());
if (!data) {
Throw<InitException>() << "Histogram2::Histogram2 : Building from datafile, but cannot open "
<< dataFile;
}
vector<pair<double,double> > dataCache;
double low, high, dataval, errstat, errsys;
double sigma2;
string in;
while (getline(data,in)) {
in = StringUtils::stripws(in);
if (in[0] == '#') continue;
if (in == "") continue;
istringstream theIn (in);
theIn >> low >> high >> dataval >> errstat >> errsys;
_binning.push_back(make_pair(low,high));
sigma2 = sqr(errstat) + sqr(errsys);
dataCache.push_back(make_pair(dataval,sigma2));
}
for (unsigned int i = 0; i<_binning.size(); ++i) {
_binhash.insert(make_pair(_binning[i].second,i));
}
_range = make_pair(_binning.front().first,_binning.back().second);
HistogramChannel theData (dataCache);
insertChannel(dataName,theData);
}
void Histogram2::book (const string& name, double event, double weight) {
map<string,HistogramChannel>::iterator c = _channels.find(name);
if (c != _channels.end()) {
- if (isnan(event) || isinf(event)) c->second.nanEvent();
+ if (!isfinite(event)) c->second.nanEvent();
else {
if (event < range().first) {
c->second.bookUnderflow(weight);
return;
}
if (event > range().second) {
c->second.bookOverflow(weight);
return;
}
unsigned int bin = _binhash.upper_bound(event)->second;
c->second.book(bin,weight);
}
}
}
vector<string> Histogram2::channels () const {
vector<string> all;
for (map<string,HistogramChannel>::const_iterator c = _channels.begin();
c != _channels.end(); ++c)
all.push_back(c->first);
return all;
}
void Histogram2::output (ostream& os, const string& name,
unsigned int flags, char comment) const {
bool bincenters = (flags & ChannelOutput::Bincenters) == ChannelOutput::Bincenters;
bool noerrorbars = (flags & ChannelOutput::NoErrorbars) == ChannelOutput::NoErrorbars;
bool nanevents = (flags & ChannelOutput::NanEvents) == ChannelOutput::NanEvents;
bool statistics = (flags & ChannelOutput::Statistics) == ChannelOutput::Statistics;
map<string,HistogramChannel>::const_iterator c = _channels.find(name);
if (c == _channels.end()) return;
os << comment << " channel = " << name << endl;
if(statistics) {
os << comment << " total entries = " << c->second.total()
<< " , visible entries = " << c->second.visible() << endl;
if (c->second.isCountingChannel())
os << comment << " underflow = " << c->second.outOfRange().first
<< " , overflow = " << c->second.outOfRange().second << endl;
if (c->second.nanEvents() > 0)
os << comment << " nan events = " << c->second.nanEvents();
if (c->second.nanWeightEvents() > 0)
os << " , nan weight events = " << c->second.nanWeightEvents() << endl;
}
for (unsigned int i = 0; i<_binning.size(); ++i) {
if (bincenters) {
os << (_binning[i].first+_binning[i].second)/2. << "\t";
} else {
os << _binning[i].first << "\t" << _binning[i].second << "\t";
}
os << c->second.bin(i).first;
if (!noerrorbars) {
os << "\t" << sqrt(c->second.bin(i).second);
}
if (nanevents) {
os << "\t" << c->second.nanWeights()[i];
}
os << endl;
}
}
HistogramChannel HistogramChannel::profile () const {
HistogramChannel temp (_bins.size(),false);
for (unsigned int i = 0; i< _bins.size(); ++i) {
pair<double,double> prof;
// mean of weights
prof.first = weightMean(i);
// varaince of mean
prof.second = binEntries(i) > 0 ? weightVariance(i)/binEntries(i) : 0;
temp.bin(i,prof,binEntries(i));
}
return temp;
}
void HistogramChannel::write (ostream& os, const string& name) {
finish();
os << "<channel"
<< " name=\"" << name << "\""
<< " counting=\"" << _isCountingChannel << "\"";
if (_isCountingChannel) {
os << " underflow=\"" << _outOfRange.first << "\""
<< " overflow=\"" << _outOfRange.second << "\""
<< " visible=\"" << _visible << "\""
<< " total=\"" << _total << "\"";
}
if (_nanEvents != 0) os << " nanevents=\"" << _nanEvents << "\"";
os << ">" << endl;
os << "<bins>" << endl;
for (unsigned int b = 0; b < _bins.size(); ++b) {
os << "<bincontent sumweights=\"" << _bins[b].first
<< "\" sumsquaredweights=\"" << _bins[b].second
<< "\" entries=\"" << _binEntries[b]
<< "\"/>" << endl;
}
os << "</bins>" << endl;
os << "<nanweights>" << endl;
// only write out, if at least happend for one event
if (nanWeightEvents() > 0)
for (vector<unsigned long>::const_iterator n = _nanWeights.begin();
n != _nanWeights.end(); ++n)
os << "<bincontent entries=\"" << *n << "\"/>" << endl;
os << "</nanweights>" << endl;
os << "</channel>" << endl;
}
string HistogramChannel::read (istream& is) {
_finished = true;
string tag;
string name;
map<string,string> attributes;
map<string,string>::iterator atit;
if (!is) return "";
// parse the channel tag
tag = getNextTag(is);
if (tag.find("<channel") == string::npos) return "";
attributes = StringUtils::xmlAttributes("channel",tag);
atit = attributes.find("name"); if (atit == attributes.end()) return "";
name = atit->second;
atit = attributes.find("counting"); if (atit == attributes.end()) return "";
fromString(atit->second,_isCountingChannel);
atit = attributes.find("underflow"); if (atit == attributes.end() && _isCountingChannel) return "";
if (_isCountingChannel) fromString(atit->second,_outOfRange.first);
atit = attributes.find("overflow"); if (atit == attributes.end() && _isCountingChannel) return "";
if (_isCountingChannel) fromString(atit->second,_outOfRange.second);
atit = attributes.find("visible"); if (atit == attributes.end() && _isCountingChannel) return "";
if (_isCountingChannel) fromString(atit->second,_visible);
atit = attributes.find("total"); if (atit == attributes.end() && _isCountingChannel) return "";
if (_isCountingChannel) fromString(atit->second,_total);
atit = attributes.find("nanevents");
if (atit != attributes.end()) fromString(atit->second,_nanEvents);
// read in the bin contents
tag = getNextTag(is);
if (tag != "<bins>") return "";
for (unsigned int i = 0; i < _bins.size(); ++i) {
tag = getNextTag(is);
if (tag.find("<bincontent") == string::npos) return "";
attributes = StringUtils::xmlAttributes("bincontent",tag);
atit = attributes.find("sumweights"); if (atit == attributes.end()) return "";
fromString(atit->second,_bins[i].first);
atit = attributes.find("sumsquaredweights"); if (atit == attributes.end()) return "";
fromString(atit->second,_bins[i].second);
atit = attributes.find("entries"); if (atit == attributes.end()) return "";
fromString(atit->second,_binEntries[i]);
}
tag = getNextTag(is);
if (tag != "</bins>") return "";
// read in the nan weight histogram
tag = getNextTag(is);
if (tag != "<nanweights>") return "";
bool nanweights = true;
for (unsigned int i = 0; i < _bins.size(); ++i) {
tag = getNextTag(is);
if (tag == "</nanweights>") {
nanweights = false;
break;
}
if (tag.find("<bincontent") == string::npos) return "";
attributes = StringUtils::xmlAttributes("bincontent",tag);
atit = attributes.find("entries"); if (atit == attributes.end()) return "";
fromString(atit->second,_nanWeights[i]);
}
if (nanweights) tag = getNextTag(is); if (tag != "</nanweights>") return "";
tag = getNextTag(is);
if (tag != "</channel>") return "";
return name;
}
void Histogram2::store (const string& name) {
ofstream os ((name+".h2").c_str());
if (!os) return;
os << "<?xml version=\"1.0\"?>" << endl;
os << "<Analysis2Histogram version=\"1.0\"" << " AnalysisName=\"" << Named::name() << "\">" << endl;
os << "<!--" << endl
<< " WARNING" << endl
<< " Though this is valid XML, the Histogram2 class will" << endl
<< " not be able to parse arbitraty, XML-valid changes" << endl
<< " to this file!" << endl
<< "-->" << endl;
os << "<xsec unit=\"nanobarn\" value=\"" << _xSec/nanobarn << "\"/>" << endl;
os << "<binning>" << endl;
for (vector<pair<double,double> >::const_iterator b = _binning.begin();
b != _binning.end(); ++b) {
os << "<bin lower=\"" << b->first << "\" upper=\"" << b->second << "\"/>" << endl;
}
os << "</binning>" << endl;
os << "<channels size=\"" << _channels.size() << "\">" << endl;
for(map<string,HistogramChannel>::iterator c = _channels.begin();
c != _channels.end(); ++c) {
c->second.write(os,c->first);
}
os << "</channels>" << endl;
os << "</Analysis2Histogram>" << endl;
}
bool Histogram2::load (const string& fname) {
ifstream is ((fname+".h2").c_str());
if (!is) return false;
string tag = getNextTag(is);
if (tag.find("<Analysis2Histogram") == string::npos) return false;
string name;
map<string,string> attributes = StringUtils::xmlAttributes("Analysis2Histogram",tag);
map<string,string>::iterator atit = attributes.find("name"); if (atit == attributes.end()) return false;
Named::name(atit->second);
// get the cross section
tag = getNextTag(is);
if (tag.find("<xsec") == string::npos) return false;
attributes = StringUtils::xmlAttributes("xsec",tag);
atit = attributes.find("unit"); if (atit == attributes.end()) return false;
if (atit->second != "nanobarn") return false; // switch units in a future version
atit = attributes.find("value"); if (atit == attributes.end()) return false;
double theXsec; fromString(atit->second,theXsec);
_xSec = theXsec * nanobarn;
// get the binning
tag = getNextTag(is);
if (tag != "<binning>") return false;
tag = getNextTag(is);
double binlower, binupper;
while (tag != "</binning>") {
if (tag.find("<bin") == string::npos && tag != "</binning>") return false;
attributes = StringUtils::xmlAttributes("bin",tag);
atit = attributes.find("lower"); if (atit == attributes.end()) return false;
fromString(atit->second,binlower);
atit = attributes.find("upper"); if (atit == attributes.end()) return false;
fromString(atit->second,binupper);
_binning.push_back(make_pair(binlower,binupper));
tag = getNextTag(is);
}
if (!_binning.size()) return false;
for (unsigned int i = 0; i<_binning.size(); ++i) {
_binhash.insert(make_pair(_binning[i].second,i));
}
_range = make_pair(_binning.front().first,_binning.back().second);
// get the channels
tag = getNextTag(is);
if (tag.find("<channels") == string::npos) return false;
attributes = StringUtils::xmlAttributes("channels",tag);
atit = attributes.find("size"); if (atit == attributes.end()) return false;
unsigned int numchannels;
fromString(atit->second,numchannels);
for (unsigned int i = 0; i<numchannels; ++i) {
HistogramChannel ch (_binning.size());
name = ch.read(is);
if (name != "") _channels.insert(make_pair(name,ch));
}
// there has to be at least one channel
if (!_channels.size()) return false;
tag = getNextTag(is);
if (tag != "</channels>") return false;
tag = getNextTag(is);
if (tag != "</Analysis2Histogram>") return false;
return true;
}
Histogram2Ptr Histogram2::loadToHistogram (const string& name) const {
Histogram2Ptr histo = new_ptr(Histogram2());
bool ok = histo->load(name);
if (!ok) histo = Histogram2Ptr();
return histo;
}
void Histogram2::combine (const string& prefix, const string& name,
unsigned int numRuns, const string& dataChannel,
const string& mcChannel) {
vector<Histogram2Ptr> inHistos;
for (unsigned int i = 0; i<numRuns; ++i) {
ostringstream fname ("");
fname << prefix << "." << i << "/" << name;
Histogram2Ptr in = loadToHistogram (fname.str());
if (in) {
inHistos.push_back(in);
}
}
// get the total cross section
CrossSection all = 0.*nanobarn;
unsigned long allEvents = 0;
for(vector<Histogram2Ptr>::iterator h = inHistos.begin();
h != inHistos.end(); ++h) {
if ((**h).haveChannel(mcChannel)) {
all += (**h).xSec() * (**h).channel(mcChannel).total();
allEvents += (**h).channel(mcChannel).total();
}
}
all /= allEvents;
xSec (all);
if (!inHistos.size()) return;
vector<string> channels = inHistos[0]->channels();
_binning = inHistos[0]->binning();
_range = inHistos[0]->range();
_binhash = inHistos[0]->binhash();
unsigned int numBins = _binning.size();
for (vector<string>::iterator c = channels.begin();
c != channels.end(); ++c) {
if (*c == dataChannel && inHistos[0]->haveChannel(dataChannel)) {
_channels.insert(make_pair(dataChannel,HistogramChannel(inHistos[0]->channel(dataChannel))));
continue;
}
HistogramChannel ch (numBins);
for (vector<Histogram2Ptr>::iterator h = inHistos.begin();
h != inHistos.end(); ++h) {
if ((**h).haveChannel(*c)) {
ch += (**h).channel(*c);
}
}
_channels.insert(make_pair(*c,ch));
}
}
Histogram2::Histogram2 (vector<double> limits) {
for (unsigned int i = 0; i < limits.size()-1; ++i)
_binning.push_back(make_pair(limits[i],limits[i+1]));
for (unsigned int i = 0; i<_binning.size(); ++i) {
_binhash.insert(make_pair(_binning[i].second,i));
}
_range = make_pair(_binning.front().first,_binning.back().second);
insertChannel("mc");
}
Histogram2::Histogram2 (vector<double> limits,
vector<double> data,
vector<double> dataerror) {
vector<pair<double,double> > dataCache;
for (unsigned int i = 0; i < limits.size(); ++i) {
if (i<limits.size()-1)
_binning.push_back(make_pair(limits[i],limits[i+1]));
dataCache.push_back(make_pair(data[i],sqr(dataerror[i])));
}
for (unsigned int i = 0; i<_binning.size(); ++i) {
_binhash.insert(make_pair(_binning[i].second,i));
}
_range = make_pair(_binning.front().first,_binning.back().second);
insertChannel("mc");
insertChannel("data",HistogramChannel(dataCache));
}
Histogram2 Histogram2::ratioWith(const Histogram2& h2) const {
Histogram2 tmp (*this);
tmp.channel("mc") /= h2.channel("mc");
return tmp;
}
Histogram2::~Histogram2() {}
void Histogram2::persistentOutput(PersistentOStream & os) const {
// *** ATTENTION *** os << ; // Add all member variable which should be written persistently here.
os << _binning << _range << _binhash << _channels << ounit(_xSec,nanobarn);
}
void Histogram2::persistentInput(PersistentIStream & is, int) {
// *** ATTENTION *** is >> ; // Add all member variable which should be read persistently here.
is >> _binning >> _range >> _binhash >> _channels >> iunit(_xSec,nanobarn);
}
ClassDescription<Histogram2> Histogram2::initHistogram2;
// Definition of the static class description member.
void Histogram2::Init() {
static ClassDocumentation<Histogram2> documentation
("Histogram2 provides advanced histogramming.");
}
diff --git a/Contrib/Analysis2/Histogram2/Histogram2.icc b/Contrib/Analysis2/Histogram2/Histogram2.icc
--- a/Contrib/Analysis2/Histogram2/Histogram2.icc
+++ b/Contrib/Analysis2/Histogram2/Histogram2.icc
@@ -1,353 +1,348 @@
// -*- C++ -*-
// (C) 2007-2009 Simon Plaetzer -- sp@particle.uni-karlsruhe.de
-// workaround for OS X bug where isnan() and isinf() are hidden
-// when <iostream> is included
-extern "C" int isnan(double) throw();
-extern "C" int isinf(double) throw();
-
namespace Analysis2 {
inline PersistentOStream& operator << (PersistentOStream& os, const HistogramChannel& h) {
h.persistentOutput(os);
return os;
}
inline PersistentIStream& operator >> (PersistentIStream& is, HistogramChannel& h) {
h.persistentInput(is);
return is;
}
inline string getNextTag (istream& is) {
string line = "";
while (line == "") {
if (!is) return "";
getline(is,line);
line = StringUtils::stripws(line);
if (line.length() && line[0] != '<') {
line = ""; continue;
}
if (line.length() && line[0] == '<') {
string::size_type a =
line.find_first_of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/");
if (a != 1) {
line = "";
continue;
}
}
}
return line;
}
inline HistogramChannel::HistogramChannel ()
: _isCountingChannel(true),
_bins(vector<pair<double,double> >()),
_binEntries(vector<unsigned long>()),
_outOfRange(make_pair(0.,0.)),
_visible(0), _total(0), _nanEvents(0),
_nanWeights(vector<unsigned long>()),
_finished(false)
{}
inline HistogramChannel::HistogramChannel (unsigned int bins, bool counting)
: _isCountingChannel(counting),
_bins(bins,make_pair(0.,0.)),
_binEntries(bins,0),
_outOfRange(make_pair(0.,0.)),
_visible(0), _total(0), _nanEvents(0),
_nanWeights(bins,0),
_finished(false)
{}
inline HistogramChannel::HistogramChannel (const vector<pair<double,double> >& bins,
double underflow, double overflow)
: _isCountingChannel(false),
_bins(bins),
_binEntries(bins.size(),0),
_outOfRange(make_pair(underflow,overflow)),
_visible(0), _total(0), _nanEvents(0),
_nanWeights(bins.size(),0),
_finished(false)
{}
inline void HistogramChannel::book (unsigned int bin, double weight) {
- if (isnan(weight) || isinf(weight)) {
+ if (!isfinite(weight)) {
++_nanWeights[bin];
return;
}
_bins[bin].first += weight;
_bins[bin].second += sqr(weight);
++_binEntries[bin];
++_visible; ++_total;
}
inline void HistogramChannel::bookUnderflow (double weight) {
_outOfRange.first += weight;
++_total;
}
inline void HistogramChannel::bookOverflow (double weight) {
_outOfRange.second += weight;
++_total;
}
inline void HistogramChannel::nanEvent () {
++_nanEvents;
}
inline HistogramChannel& HistogramChannel::operator /= (double a) {
return this->operator *= (1/a);
}
inline bool HistogramChannel::isCountingChannel () const {
return _isCountingChannel;
}
inline vector<pair<double,double> > HistogramChannel::bins () const {
return _bins;
}
inline pair<double,double> HistogramChannel::bin (unsigned int bin) const {
return _bins[bin];
}
inline void HistogramChannel::bin (unsigned int bin,
pair<double,double> val,
unsigned long entries) {
_bins[bin] = val;
if (entries > 0) {
_visible = _visible - _binEntries[bin] + entries;
_binEntries[bin] = entries;
}
}
inline vector<unsigned long> HistogramChannel::binEntries () const {
return _binEntries;
}
inline unsigned long HistogramChannel::binEntries (unsigned int bin) const {
return _binEntries[bin];
}
inline pair<double,double> HistogramChannel::outOfRange () const {
return _outOfRange;
}
inline unsigned long HistogramChannel::visible () const {
return _visible;
}
inline unsigned long HistogramChannel::total () const {
return _total;
}
inline vector<unsigned long> HistogramChannel::nanWeights () const {
return _nanWeights;
}
inline unsigned long HistogramChannel::nanEvents () const {
return _nanEvents;
}
inline void HistogramChannel::finish () {
if (_finished) return;
_finished = true;
}
inline double HistogramChannel::binVariance (unsigned int bin) const {
return _bins[bin].second;
}
inline double HistogramChannel::weightMean (unsigned int bin) const {
return _binEntries[bin] > 0 ? _bins[bin].first/_binEntries[bin] : 0.;
}
inline double HistogramChannel::weightVariance (unsigned int bin) const {
return _binEntries[bin] > 1 ?
(_bins[bin].second-sqr(_bins[bin].first)/_binEntries[bin])/(_binEntries[bin] - 1) : 0.;
}
inline pair<double,double> HistogramChannel::binAverage () const {
return make_pair(binSum().first/_bins.size(),binSum().second/(_bins.size()*_bins.size()));
}
inline HistogramChannel operator + (const HistogramChannel& a, const HistogramChannel& b) {
HistogramChannel c(a); c += b; return c;
}
inline HistogramChannel operator - (const HistogramChannel& a, const HistogramChannel& b) {
HistogramChannel c(a); c -= b; return c;
}
inline HistogramChannel operator * (const HistogramChannel& a, const HistogramChannel& b) {
HistogramChannel c(a); c *= b; return c;
}
inline HistogramChannel operator / (const HistogramChannel& a, const HistogramChannel& b) {
HistogramChannel c(a); c /= b; return c;
}
inline Histogram2::Histogram2 ()
: _binning(), _binhash(), _channels(), _xSec(0.*nanobarn) { }
inline void Histogram2::setName (const string& name) {
Named::name(name);
}
inline bool Histogram2::haveChannel (const string& name) const {
return _channels.find(name) != _channels.end();
}
inline HistogramChannel& Histogram2::channel (const string& name) {
return _channels.find(name)->second;
}
inline HistogramChannel Histogram2::channel (const string& name) const {
map<string,HistogramChannel>::const_iterator c = _channels.find(name);
if (c != _channels.end()) return c->second;
return HistogramChannel (0);
}
inline void Histogram2::insertChannel (const string& name, const HistogramChannel& c) {
_channels.insert(make_pair(name,c));
}
inline void Histogram2::insertChannel (const string& name) {
_channels.insert(make_pair(name,HistogramChannel(_binning.size())));
}
inline HistogramChannel Histogram2::removeChannel (const string& name) {
map<string,HistogramChannel>::iterator c = _channels.find(name);
if (c != _channels.end()) {
HistogramChannel rem (c->second);
_channels.erase(c);
return rem;
}
return HistogramChannel(0);
}
inline const vector<pair<double,double> >& Histogram2::binning () const {
return _binning;
}
inline const map<double,unsigned int>& Histogram2::binhash () const {
return _binhash;
}
inline pair<double,double> Histogram2::range () const {
return _range;
}
inline CrossSection Histogram2::xSec () const {
return _xSec;
}
inline void Histogram2::xSec (CrossSection xs) {
_xSec = xs;
}
inline void Histogram2::finish (const string& name) {
map<string,HistogramChannel>::iterator c = _channels.find(name);
if (c != _channels.end()) {
c->second.finish();
}
}
inline void Histogram2::differential (const string& name) {
map<string,HistogramChannel>::iterator c = _channels.find(name);
if (c != _channels.end()) {
c->second.differential(_binning);
}
}
inline pair<double,double> Histogram2::integrate (const string& name) const {
pair<double,double> integral = make_pair(0.,0.);
map<string,HistogramChannel>::const_iterator c = _channels.find(name);
if (c != _channels.end()) {
integral = c->second.integrate(_binning);
}
return integral;
}
inline void Histogram2::normalise (const string& name) {
map<string,HistogramChannel>::iterator c = _channels.find(name);
if (c != _channels.end()) {
c->second /= integrate(name);
}
}
inline void Histogram2::rescale (const string& name, double x) {
map<string,HistogramChannel>::iterator c = _channels.find(name);
if (c != _channels.end()) {
c->second *= x;
}
}
inline void Histogram2::rescale (double x) {
for (map<string,HistogramChannel>::iterator c = _channels.begin();
c != _channels.end(); ++c) {
c->second *= x;
}
}
inline void Histogram2::normalise (const string& name, const string& data) {
pair<double,double> norm = integrate(data);
map<string,HistogramChannel>::iterator c = _channels.find(name);
if (norm.first == 0. || c == _channels.end()) return;
c->second /= c->second.integrate(_binning);
c->second *= norm;
}
inline pair<double,double> Histogram2::chi2perDOF (const string& hyp, const string& dat, double minfrac) const {
map<string,HistogramChannel>::const_iterator hypothesis = _channels.find(hyp);
map<string,HistogramChannel>::const_iterator data = _channels.find(dat);
pair<double,double> chi2 = make_pair(0.,0.);
if (hypothesis != _channels.end() && data != _channels.end()) {
chi2 = hypothesis->second.chi2(data->second,minfrac).average(_binning);
}
return chi2;
}
inline void Histogram2::operator+=(double event) {
book("mc",event);
}
inline void Histogram2::addWeighted(double event, double weight) {
book("mc",event,weight);
}
inline unsigned int Histogram2::numberOfBins() const {
return _binning.size();
}
inline void Histogram2::normaliseToData() {
normalise("mc","data");
}
inline void Histogram2::normaliseToCrossSection(const string& name) {
normalise(name);
channel(name) *= _xSec/nanobarn;
}
inline void Histogram2::chiSquared(double & chisq,
unsigned int & ndegrees,
double minfrac) const {
ndegrees = _binning.size();
chisq = chi2perDOF("mc","data",minfrac).first;
}
inline IBPtr Histogram2::clone() const {
return new_ptr(*this);
}
inline IBPtr Histogram2::fullclone() const {
return new_ptr(*this);
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
}
diff --git a/Contrib/FxFx/FxFxAnalysis.cc b/Contrib/FxFx/FxFxAnalysis.cc
--- a/Contrib/FxFx/FxFxAnalysis.cc
+++ b/Contrib/FxFx/FxFxAnalysis.cc
@@ -1,358 +1,381 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the FxFxAnalysis class.
//
#include "FxFxAnalysis.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Vectors/HepMCConverter.h"
#include "ThePEG/Config/HepMCHelper.h"
#include "ThePEG/EventRecord/Event.h"
#include "ThePEG/EventRecord/SubProcess.h"
#include "ThePEG/EventRecord/SubProcessGroup.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "HepMC/GenEvent.h"
#include "Rivet/AnalysisHandler.hh"
#include "Rivet/Tools/Logging.hh"
#include "HepMC/IO_AsciiParticles.h"
#include "HepMC/IO_GenEvent.h"
#include "ThePEG/Utilities/XSecStat.h"
-//#include <config.h>
using namespace ThePEG;
FxFxAnalysis::FxFxAnalysis()
: _remnantId(82), _format(1),_unitchoice(),
- _geneventPrecision(16), debug(false), _rivet(), _nevent(0), useoptweights(false) {}
+ _geneventPrecision(16), debug(false), _rivet(), _nevent(0), useoptweights(false), normoptweights(false) {}
HepMC::GenEvent * FxFxAnalysis::makeEvent(tEventPtr event, tSubProPtr sub, long no,
Energy eUnit, Length lUnit,
CrossSection xsec, CrossSection xsecErr) const {
//convert the event from the Herwig format to the HepMC format and write it to the common block
HepMC::GenEvent * ev = HepMCConverter<HepMC::GenEvent>::convert(*event, false,eUnit, lUnit);
//reset the event
HepMCTraits<HepMC::GenEvent>::resetEvent(ev, no, event->weight()*sub->groupWeight(), event->optionalWeights());
+
//set the cross section
HepMCTraits<HepMC::GenEvent>::setCrossSection(*ev,xsec/picobarn,
xsecErr/picobarn);
return ev;
}
HepMC::GenEvent * FxFxAnalysis::makeEventW(tEventPtr event, tSubProPtr sub, long no,
Energy eUnit, Length lUnit,
- CrossSection xsec, CrossSection xsecErr, double evoptweight) const {
+ CrossSection xsec, CrossSection xsecErr, double evoptweight, double centralweight) const {
//convert the event from the Herwig format to the HepMC format and write it to the common block
HepMC::GenEvent * ev = HepMCConverter<HepMC::GenEvent>::convert(*event, false,eUnit, lUnit);
-
+
+ if(normoptweights) { evoptweight /= centralweight; }
+
//reset the event
HepMCTraits<HepMC::GenEvent>::resetEvent(ev, no, evoptweight, event->optionalWeights());
//set the cross section
HepMCTraits<HepMC::GenEvent>::setCrossSection(*ev,xsec/picobarn,
xsecErr/picobarn);
return ev;
}
void FxFxAnalysis::analyze(ThePEG::tEventPtr event, long ieve, int loop, int state) {
Energy eUnit;
Length lUnit;
switch (_unitchoice) {
default: eUnit = GeV; lUnit = millimeter; break;
case 1: eUnit = MeV; lUnit = millimeter; break;
case 2: eUnit = GeV; lUnit = centimeter; break;
case 3: eUnit = MeV; lUnit = centimeter; break;
}
tcFxFxEventHandlerPtr eh = dynamic_ptr_cast<tcFxFxEventHandlerPtr>(event->primaryCollision()->handler());
assert(eh);
CrossSection xsec = eh->integratedXSec();
CrossSection xsecErr = eh->integratedXSecErr();
optxsec = eh->optintegratedXSecMap();
int ii = 0;
if(useoptweights) {
for (map<string,CrossSection>::const_iterator it= optxsec.begin(); it!=optxsec.end(); ++it){
OptXS[ii] = it->second/picobarn;
ii++;
}
}
tSubProPtr sub = event->primarySubProcess();
Ptr<SubProcessGroup>::tptr grp =
dynamic_ptr_cast<Ptr<SubProcessGroup>::tptr>(sub);
AnalysisHandler::analyze(event, ieve, loop, state);
// Rotate to CMS, extract final state particles and call analyze(particles).
// convert to hepmc
HepMC::GenEvent * hepmc =
makeEvent(event,sub,_nevent,eUnit,lUnit,xsec,xsecErr);
//count weights here
std::vector<std::string> strs;
if(_numweights == -999) {
_numweights = 0;
for (map<string,double>::const_iterator it= event->optionalWeights().begin(); it!=event->optionalWeights().end(); ++it){
string first_piece = it->first;
string word;
istringstream iss(first_piece, istringstream::in);
while( iss >> word ) strs.push_back(word);
if(strs[0] == "PDF" || strs[0] == "SC") { _numweights++; }
strs.clear();
}
}
+ double CentralWeight = 1.;
if(useoptweights) {
//find the weights
_i = 0;//counter
OptWeights.clear();
for (map<string,double>::const_iterator it= event->optionalWeights().begin(); it!=event->optionalWeights().end(); ++it){
// std::cout << it->first << " => " << it->second << '\n';
string first_piece = it->first;
string word;
istringstream iss(first_piece, istringstream::in);
while( iss >> word ) {
strs.push_back(word);
}
std::pair<int,double> OptWeightsTemp;
if(strs[0] == "PDF") {
OptWeightsTemp.first = atoi(strs[2].c_str());
OptWeightsTemp.second= it->second;
OptWeights.push_back(OptWeightsTemp);
_i++;
}
if(strs[0] == "SC") {
OptWeightsTemp.first = atoi(strs[3].c_str());
OptWeightsTemp.second = it->second;
+ // cout << "OptWeightsTemp.first = " << OptWeightsTemp.first << " OptWeightsTemp.second = " << OptWeightsTemp.second << endl;
+ if(OptWeightsTemp.first == 1001) { /*cout << "OptWeightsTemp.second = " << OptWeightsTemp.second << endl;*/ CentralWeight = OptWeightsTemp.second; }
OptWeights.push_back(OptWeightsTemp);
_i++;
}
strs.clear();
}
}
/* multiple hepmcs for scale/pdf variations
*/
vector<HepMC::GenEvent*> hepmcMULTI;// = new HepMC::GenEvent[_numweights];
HepMC::GenEvent * hepmcMULTIi;
if(useoptweights) {
for(int rr = 0; rr < _numweights; rr++) {
- double xsrr = optxsec[boost::lexical_cast<string>(OptWeights[rr].first)]/picobarn;
- // cout << "xsec = " << xsec/picobarn << endl;
- // cout << "OptWeights[rr].second = " << OptWeights[rr].second << endl;
- hepmcMULTIi = makeEventW(event,sub,_nevent,eUnit,lUnit,xsrr*picobarn,xsecErr,OptWeights[rr].second);
+ double xsrr = optxsec[std::to_string(OptWeights[rr].first)]/picobarn;
+ //cout << "xsec = " << xsec/picobarn << endl;
+ //cout << "OptWeights[rr].second = " << OptWeights[rr].second << endl;
+ //cout << "xsrr = " << xsrr << endl;
+ hepmcMULTIi = makeEventW(event,sub,_nevent,eUnit,lUnit,xsrr*picobarn,xsecErr,OptWeights[rr].second, CentralWeight);
hepmcMULTI.push_back(hepmcMULTIi);
}
}
CurrentGenerator::Redirect stdout(cout);
if ( _rivet ) _rivet->analyze(*hepmc);
if(useoptweights) {
for(int rr = 0; rr < _numweights; rr++) {
if ( _rivetMULTI[rr] ) _rivetMULTI[rr]->analyze(*hepmcMULTI[rr]);
}
}
// delete hepmc events
delete hepmc;
if(useoptweights) {
for(int rr = 0; rr < _numweights; rr++) {
delete hepmcMULTI[rr];
}
}
if ( grp ) {
for ( SubProcessVector::const_iterator s = grp->dependent().begin();
s != grp->dependent().end(); ++s ) {
hepmc = makeEvent(event,*s,_nevent,eUnit,lUnit,xsec,xsecErr);
if ( _rivet ) _rivet->analyze(*hepmc);
// delete hepmc event
delete hepmc;
}
}
++_nevent;
}
ThePEG::IBPtr FxFxAnalysis::clone() const {
return new_ptr(*this);
}
ThePEG::IBPtr FxFxAnalysis::fullclone() const {
return new_ptr(*this);
}
void FxFxAnalysis::persistentOutput(ThePEG::PersistentOStream & os) const {
- os << _analyses << filename << debug << useoptweights;
+ os << _analyses << filename << debug << useoptweights << normoptweights;
}
void FxFxAnalysis::persistentInput(ThePEG::PersistentIStream & is, int) {
- is >> _analyses >> filename >> debug >> useoptweights;
+ is >> _analyses >> filename >> debug >> useoptweights >> normoptweights;
}
ThePEG::ClassDescription<FxFxAnalysis> FxFxAnalysis::initFxFxAnalysis;
// Definition of the static class description member.
void FxFxAnalysis::Init() {
static ThePEG::ClassDocumentation<FxFxAnalysis> documentation
("The FxFxAnalysis class is a simple class to allow analyses"
" from the Rivet library to be called from ThePEG");
static ThePEG::ParVector<FxFxAnalysis,string> interfaceAnalyses
("Analyses",
"The names of the Rivet analyses to use",
&FxFxAnalysis::_analyses, -1, "", "","" "",
false, false, ThePEG::Interface::nolimits);
static Parameter<FxFxAnalysis,long> interfaceRemnantId
("RemnantId",
"Set the PDG id to be used for remnants.",
&FxFxAnalysis::_remnantId, 82, 0, 0,
false, false, Interface::nolimits);
static Parameter<FxFxAnalysis,string> interfaceFilename
("Filename",
"The name of the file where the YODA histograms are put. If empty, "
"the run name will be used instead. '.yoda' will in any case be "
"appended to the file name.",
&FxFxAnalysis::filename, "", true, false);
static Switch<FxFxAnalysis,bool> interfaceDebug
("Debug",
"Enable debug information from Rivet",
&FxFxAnalysis::debug, false, true, false);
static SwitchOption interfaceDebugNo
(interfaceDebug,
"No",
"Disable debug information.",
false);
static SwitchOption interfaceDebugYes
(interfaceDebug,
"Yes",
"Enable debug information from Rivet.",
true);
static Switch<FxFxAnalysis,bool> interfaceUseOptWeights
("UseOptWeights",
"Enable debug information from Rivet",
&FxFxAnalysis::useoptweights, false, true, false);
static SwitchOption interfaceUseOptWeightsNo
(interfaceUseOptWeights,
"No",
"Disable optional weights",
false);
static SwitchOption interfaceUseOptWeightsYes
(interfaceUseOptWeights,
"Yes",
"Enable debug information from Rivet.",
true);
+ static Switch<FxFxAnalysis,bool> interfaceNormOptWeights
+ ("NormOptWeights",
+ "Enable debug information from Rivet",
+ &FxFxAnalysis::normoptweights, false, true, false);
+ static SwitchOption interfaceNormOptWeightsNo
+ (interfaceNormOptWeights,
+ "No",
+ "Do not normalize optional weights",
+ false);
+ static SwitchOption interfacedNormOptWeightsYes
+ (interfaceNormOptWeights,
+ "Yes",
+ "Normalize optional weights.",
+ true);
+
+
+
interfaceAnalyses.rank(10);
}
void FxFxAnalysis::dofinish() {
AnalysisHandler::dofinish();
if( _nevent > 0 && _rivet ) {
CurrentGenerator::Redirect stdout(cout);
_rivet->setCrossSection(generator()->integratedXSec()/picobarn);
_rivet->finalize();
string fname = filename;
fname = generator()->runName() + ".yoda";
_rivet->writeData(fname);
}
delete _rivet;
_rivet = 0;
if(useoptweights) {
for(int rr = 0; rr < _numweights; rr++) {
cout << (OptWeights[rr].first) << ", cross section = " << OptXS[rr] << endl;
if( _nevent > 0 && _rivetMULTI[rr] ) {
- double xsrr = optxsec[boost::lexical_cast<string>(OptWeights[rr].first)]/picobarn;
+ double xsrr = optxsec[std::to_string(OptWeights[rr].first)]/picobarn;
// _rivetMULTI[rr]->setCrossSection(OptXS[rr]);
_rivetMULTI[rr]->setCrossSection(xsrr);
_rivetMULTI[rr]->finalize();
string fname = filename;
- fname = generator()->runName() + "_" + boost::lexical_cast<string>(OptWeights[rr].first) + ".yoda";
+ fname = generator()->runName() + "_" + std::to_string(OptWeights[rr].first) + ".yoda";
_rivetMULTI[rr]->writeData(fname);
}
delete _rivetMULTI[rr];
_rivetMULTI[rr] = 0;
}
}
}
void FxFxAnalysis::doinit() {
_numweights = -999;
for(int rr = 0; rr < 120; rr++) {
OptXS.push_back(0.);
}
AnalysisHandler::doinit();
if(_analyses.empty())
throw ThePEG::Exception() << "Must have at least one analysis loaded in "
<< "FxFxAnalysis::doinitrun()"
<< ThePEG::Exception::runerror;
// check that analysis list is available
_rivet = new Rivet::AnalysisHandler; //(fname);
_rivet->addAnalyses(_analyses);
if ( _rivet->analysisNames().size() != _analyses.size() ) {
throw ThePEG::Exception()
<< "Rivet could not find all requested analyses.\n"
<< "Use 'rivet --list-analyses' to check availability.\n"
<< ThePEG::Exception::runerror;
}
delete _rivet;
_rivet = 0;
}
void FxFxAnalysis::doinitrun() {
_numweights = -999;
AnalysisHandler::doinitrun();
// create FxFx analysis handler
CurrentGenerator::Redirect stdout(cout);
_rivet = new Rivet::AnalysisHandler; //(fname);
_rivet->addAnalyses(_analyses);
if(useoptweights) {
for(int rr = 0; rr < 110; rr++) {
OptXS.push_back(0.);
_rivetMULTI[rr] = new Rivet::AnalysisHandler; //(fname);
_rivetMULTI[rr]->addAnalyses(_analyses);
}
}
// check that analysis list is still available
if ( _rivet->analysisNames().size() != _analyses.size() ) {
throw ThePEG::Exception()
<< "Rivet could not find all requested analyses.\n"
<< "Use 'rivet --list-analyses' to check availability.\n"
<< ThePEG::Exception::runerror;
}
if ( debug )
Rivet::Log::setLevel("Rivet",Rivet::Log::DEBUG);
}
diff --git a/Contrib/FxFx/FxFxAnalysis.h b/Contrib/FxFx/FxFxAnalysis.h
--- a/Contrib/FxFx/FxFxAnalysis.h
+++ b/Contrib/FxFx/FxFxAnalysis.h
@@ -1,256 +1,262 @@
// -*- C++ -*-
#ifndef THEPEG_FxFxAnalysis_H
#define THEPEG_FxFxAnalysis_H
//
// This is the declaration of the FxFxAnalysis class.
//
#include "ThePEG/Handlers/AnalysisHandler.h"
#include "Rivet/AnalysisHandler.hh"
#include "FxFxReader.h"
#include "FxFxEventHandler.h"
namespace ThePEG {
/**
* Here is the documentation of the FxFxAnalysis class.
*
* @see \ref FxFxAnalysisInterfaces "The interfaces"
* defined for FxFxAnalysis.
*/
class FxFxAnalysis: public ThePEG::AnalysisHandler {
public:
/**
* The default constructor.
*/
FxFxAnalysis();
public:
/** @name Virtual functions required by the AnalysisHandler class. */
//@{
/**
* Analyze a given Event. Note that a fully generated event
* may be presented several times, if it has been manipulated in
* between. The default version of this function will call transform
* to make a lorentz transformation of the whole event, then extract
* all final state particles and call analyze(tPVector) of this
* analysis object and those of all associated analysis objects. The
* default version will not, however, do anything on events which
* have not been fully generated, or have been manipulated in any
* way.
* @param event pointer to the Event to be analyzed.
* @param ieve the event number.
* @param loop the number of times this event has been presented.
* If negative the event is now fully generated.
* @param state a number different from zero if the event has been
* manipulated in some way since it was last presented.
*/
virtual void analyze(ThePEG::tEventPtr event, long ieve, int loop, int state);
/**
* Produca a HepMC event for the given subprocess
*/
HepMC::GenEvent * makeEvent(tEventPtr event, tSubProPtr sub, long no,
Energy eUnit, Length lUnit,
CrossSection xsec, CrossSection xsecErr) const;
/**
* Produca a HepMC event for the given subprocess
*/
HepMC::GenEvent * makeEventW(tEventPtr event, tSubProPtr sub, long no,
- Energy eUnit, Length lUnit,
- CrossSection xsec, CrossSection xsecErr, double weighttest) const;
+ Energy eUnit, Length lUnit,
+ CrossSection xsec, CrossSection xsecErr, double evoptweight, double centralweight) const;
int _i;
int _numweights;
//@}
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(ThePEG::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(ThePEG::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 ThePEG::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 ThePEG::IBPtr fullclone() const;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Initialize this object. Called in the read phase.
*/
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 static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ThePEG::ClassDescription<FxFxAnalysis> initFxFxAnalysis;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
FxFxAnalysis & operator=(const FxFxAnalysis &);
private:
/**
* The PDG ID to be used for remnants
*/
long _remnantId;
/**
* The HepMC format
*/
int _format;
/**
* Selector for the choice of units
*/
int _unitchoice;
/**
* Choice of output precision in GenEvent format
*/
unsigned int _geneventPrecision;
/**
* The Analyses to use
*/
vector<string> _analyses;
/**
* The base name of the output file.
*/
string filename;
/**
* Enable debugging information from FxFx
*/
bool debug;
/**
* Enable use of optional weights in analysis
*/
bool useoptweights;
+
+ /**
+ * normalize optional weights to the central weight
+ */
+
+ bool normoptweights;
/**
* The FxFxAnalysisHandler
*/
Rivet::AnalysisHandler * _rivet;
/**
* The FxFxAnalysisHandlers for multiple weights
*/
Rivet::AnalysisHandler * _rivetMULTI[120];
/**
* holders of weights and cross section
*/
std::vector< std::pair<int,double> > OptWeights;
std::vector<double> OptXS;
map<string,CrossSection> optxsec;
/**
* Event count
*/
unsigned long _nevent;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of FxFxAnalysis. */
template <>
struct BaseClassTrait<FxFxAnalysis,1> {
/** Typedef of the first base class of FxFxAnalysis. */
typedef AnalysisHandler NthBase;
};
/** This template specialization informs ThePEG about the name of
* the FxFxAnalysis class and the shared object where it is defined. */
template <>
struct ClassTraits<FxFxAnalysis>
: public ClassTraitsBase<FxFxAnalysis> {
/** Return a platform-independent class name */
static string className() { return "ThePEG::FxFxAnalysis"; }
/**
* The name of a file containing the dynamic library where the class
* FxFxAnalysis is implemented. It may also include several, space-separated,
* libraries if the class FxFxAnalysis depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "FxFxAnalysis.so"; }
};
/** @endcond */
}
#endif /* THEPEG_FxFxAnalysis_H */
diff --git a/Contrib/FxFx/FxFxEventHandler.cc b/Contrib/FxFx/FxFxEventHandler.cc
--- a/Contrib/FxFx/FxFxEventHandler.cc
+++ b/Contrib/FxFx/FxFxEventHandler.cc
@@ -1,612 +1,615 @@
// -*- C++ -*-
//
// FxFxEventHandler.cc is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2011 Leif Lonnblad
//
// ThePEG 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 FxFxEventHandler class.
//
#include "FxFxEventHandler.h"
#include "FxFxReader.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Repository/Repository.h"
#include "ThePEG/Handlers/LuminosityFunction.h"
#include "ThePEG/Handlers/XComb.h"
#include "ThePEG/Handlers/CascadeHandler.h"
#include "ThePEG/Cuts/Cuts.h"
#include "ThePEG/PDF/PartonExtractor.h"
#include "ThePEG/Utilities/LoopGuard.h"
#include "ThePEG/EventRecord/Event.h"
#include "ThePEG/EventRecord/Collision.h"
#include "ThePEG/EventRecord/Step.h"
#include "ThePEG/EventRecord/SubProcess.h"
#include "ThePEG/Utilities/EnumIO.h"
#include "ThePEG/Utilities/Maths.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Utilities/Debug.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace ThePEG;
FxFxEventHandler::~FxFxEventHandler() {}
IBPtr FxFxEventHandler::clone() const {
return new_ptr(*this);
}
IBPtr FxFxEventHandler::fullclone() const {
return new_ptr(*this);
}
void FxFxEventHandler::doinit() {
EventHandler::doinit();
for ( int i = 0, N = readers().size(); i < N; ++i ) {
readers()[i]->init();
//FxFxReader & reader = *readers()[i];
//reader.initialize(*this);
//weightnames = reader.optWeightsNamesFunc();
}
/*
XSecStat* initxsecs = new XSecStat[weightnames.size()];
for(int ww = 0; ww < weightnames.size(); ww++){
initxsecs[ww].reset();
optstats.insert(std::make_pair<string,XSecStat>(weightnames[ww], initxsecs[ww]));
opthistStats.insert(std::make_pair<string,XSecStat>(weightnames[ww], initxsecs[ww]));
CrossSection initxs = 0.*picobarn;
optxs.insert(std::make_pair<string,CrossSection>(weightnames[ww], initxs));
}*/
ntries = 0;
}
void FxFxEventHandler::initialize() {
if ( lumiFnPtr() ) Repository::clog()
<< "The LuminosityFunction '" << lumiFnPtr()->name()
<< "' assigned to the FxFxEventHandler '" << name()
<< "' will not be active in this run. Instead the incoming "
<< "particles will be determined by the used FxFxReader objects.\n"
<< Exception::warning;
if ( readers().empty() )
throw FxFxInitError()
<< "No readers were defined for the FxFxEventHandler '"
<< name() << "'" << Exception::warning;
// Go through all the readers and collect information about cross
// sections and processes.
typedef map<int,tFxFxReaderPtr> ProcessMap;
ProcessMap processes;
PDPair incoming;
Energy MaxEA = ZERO;
Energy MaxEB = ZERO;
for ( int i = 0, N = readers().size(); i < N; ++i ) {
FxFxReader & reader = *readers()[i];
reader.initialize(*this);
weightnames = reader.optWeightsNamesFunc();
// Check that the incoming particles are consistent between the
// readers.
if ( !incoming.first ) {
incoming.first = getParticleData(reader.heprup.IDBMUP.first);
if ( !incoming.first )
Throw<FxFxInitError>()
<< "Unknown beam PID " << reader.heprup.IDBMUP.first
<< ". Have you created a matching BeamParticle object?"
<< Exception::runerror;
}
if ( !incoming.second ) {
incoming.second = getParticleData(reader.heprup.IDBMUP.second);
if ( !incoming.second )
Throw<FxFxInitError>()
<< "Unknown beam PID " << reader.heprup.IDBMUP.first
<< ". Have you created a matching BeamParticle object?"
<< Exception::runerror;
}
if ( incoming.first->id() != reader.heprup.IDBMUP.first ||
incoming.second->id() != reader.heprup.IDBMUP.second )
Repository::clog()
<< "The different FxFxReader objects in the "
<< "FxFxEventHandler '" << name() << "' have different "
<< "types of colliding particles." << Exception::warning;
MaxEA = max(MaxEA, reader.heprup.EBMUP.first*GeV);
MaxEB = max(MaxEB, reader.heprup.EBMUP.second*GeV);
// Check that the weighting of the events in the different readers
// is consistent with the ones requested for this event
// handler. Also collect the sum of the maximum weights.
if ( reader.negativeWeights() && weightOption() > 0 )
throw FxFxInitError()
<< "The reader '" << reader.name()
<< "' contains negatively weighted events, "
<< "which is not allowed for the FxFxEventHandler '"
<< name() << "'." << Exception::warning;
// Check that we do not have the same process numbers in different
// readers.
for ( int ip = 0; ip < reader.heprup.NPRUP; ++ip ) {
if ( reader.heprup.LPRUP[ip] ) {
ProcessMap::iterator pit = processes.find(reader.heprup.LPRUP[ip]);
if ( pit == processes.end() )
processes[reader.heprup.LPRUP[ip]] = readers()[i];
else if ( warnPNum ) {
Throw<FxFxPNumException>()
<< "In the FxFxEventHandler '"
<< name() << "', both the '" << pit->second->name() << "' and '"
<< reader.name() << "' contains sub-process number " << pit->first
<< ". This process may be double-counted in this run."
<< Exception::warning;
}
}
}
selector().insert(reader.stats.maxXSec(), i);
}
stats.maxXSec(selector().sum());
histStats.maxXSec(selector().sum());
for (map<string,XSecStat>::iterator it= optstats.begin(); it!=optstats.end(); ++it){
(it->second).maxXSec(selector().sum());
}
// Check that we have any cross section at all.
if ( stats.maxXSec() <= ZERO )
throw FxFxInitError()
<< "The sum of the cross sections of the readers in the "
<< "FxFxEventHandler '" << name()
<< "' was zero." << Exception::warning;
// We now create a LuminosityFunction object to inform others about
// the energy of the beam.
theIncoming = incoming;
lumiFn(new_ptr(LuminosityFunction(MaxEA, MaxEB)));
}
void FxFxEventHandler::doinitrun() {
EventHandler::doinitrun();
stats.reset();
histStats.reset();
for ( int i = 0, N = readers().size(); i < N; ++i ) {
readers()[i]->init();
FxFxReader & reader = *readers()[i];
reader.initialize(*this);
weightnames = reader.optWeightsNamesFunc();
}
// XSecStat initxsecs;
XSecStat* initxsecs = new XSecStat[weightnames.size()];
for(int ww = 0; ww < weightnames.size(); ww++){
initxsecs[ww].reset();
- optstats.insert(std::make_pair<string,XSecStat>(weightnames[ww], initxsecs[ww]));
- opthistStats.insert(std::make_pair<string,XSecStat>(weightnames[ww], initxsecs[ww]));
+ // optstats.insert(std::make_pair<string,XSecStat>(weightnames[ww], initxsecs[ww]));
+ // opthistStats.insert(std::make_pair<string,XSecStat>(weightnames[ww], initxsecs[ww]));
CrossSection initxs = 0.*picobarn;
- optxs.insert(std::make_pair<string,CrossSection>(weightnames[ww], initxs));
+ //optxs.insert(std::make_pair<string,CrossSection>(weightnames[ww], initxs));
+ optstats.insert(std::make_pair(weightnames[ww], initxsecs[ww]));
+ opthistStats.insert(std::make_pair(weightnames[ww], initxsecs[ww]));
+ optxs.insert(std::make_pair(weightnames[ww], initxs));
}
ntries = 0;
}
EventPtr FxFxEventHandler::generateEvent() {
LoopGuard<EventLoopException,FxFxEventHandler>
loopGuard(*this, maxLoop());
while ( true ) {
loopGuard();
currentReader(readers()[selector().select(UseRandom::current())]);
skipEvents();
currentReader()->reset();
double weight = currentReader()->getEvent();
if ( weightOption() == unitweight && weight < 0.0 ) weight = 0.0;
if ( weightOption() == unitweight || weightOption() == unitnegweight ) {
CrossSection newmax = selector().reweight(weight);
if ( newmax > CrossSection() )
increaseMaxXSec(newmax);
}
select(weight/currentReader()->preweight);
histStats.select(weight);
if ( !weighted() ) {
if ( weightOption() == unitweight || weightOption() == unitnegweight ) {
if ( !rndbool(abs(weight)) ) continue;
weight = Math::sign(1.0, weight);
}
else if ( weight == 0.0 ) continue;
} else if ( weight == 0.0 ) continue;
accept();
// Divide by the bias introduced by the preweights in the reader.
weight /= currentReader()->preweight;
try {
theLastXComb = currentReader()->getXComb();
currentEvent(new_ptr(Event(lastParticles(), this, generator()->runName(),
generator()->currentEventNumber(), weight)));
currentEvent()->optionalWeights() = currentReader()->optionalEventWeights();
//print optional weights here
/* for (map<string,double>::const_iterator it= currentReader()->optionalEventWeights().begin(); it!=currentReader()->optionalEventWeights().end(); ++it){
std::cout << it->first << " => " << it->second << '\n';
}
cout << endl;*/
//print npLO and npNLO
// cout << currentReader()->optionalEventnpLO() << "\t" << currentReader()->optionalEventnpNLO() << endl;
performCollision();
if ( !currentCollision() ) throw Veto();
return currentEvent();
}
catch (Veto) {
reject(weight);
}
catch (Stop) {
}
catch (Exception &) {
reject(weight);
throw;
}
}
}
void FxFxEventHandler::skipEvents() {
// Don't do this for readers which seem to generate events on the fly.
if ( currentReader()->active() || currentReader()->NEvents() <= 0 ) return;
// Estimate the fration of the total events available from
// currentReader() which will be requested.
double frac = currentReader()->stats.maxXSec()/stats.maxXSec();
if ( stats.accepted() > 0 )
frac *= double(stats.attempts())/double(stats.accepted());
else
frac *= double(stats.attempts() + 1);
double xscan = generator()->N()*frac/currentReader()->NEvents();
// Estimate the number of times we need to go through the events for
// the currentReader(), and how many events on average we need to
// skip for each attempted event to go through the file an integer
// number of times.
double nscan = ceil(xscan);
double meanskip = nscan/xscan - 1.0;
// Skip an average numer of steps with a Poissonian distribution.
currentReader()->
skip(UseRandom::rndPoisson(meanskip)%currentReader()->NEvents());
}
void FxFxEventHandler::select(double weight) {
stats.select(weight);
currentReader()->select(weight);
vector<double> w;
for (map<string,double>::const_iterator it= currentReader()->optionalEventWeights().begin(); it!=currentReader()->optionalEventWeights().end(); ++it){
w.push_back(it->second);
}
int ii = 0;
for (map<string,XSecStat>::iterator it= opthistStats.begin(); it!=opthistStats.end(); ++it){
(it->second).select(w[ii]);
ii++;
}
ii = 0;
for (map<string,XSecStat>::iterator it= optstats.begin(); it!=optstats.end(); ++it){
(it->second).select(w[ii]);
ii++;
}
}
tCollPtr FxFxEventHandler::performCollision() {
lastExtractor()->select(lastXCombPtr());
if ( CKKWHandler() ) CKKWHandler()->setXComb(lastXCombPtr());
currentCollision(new_ptr(Collision(lastParticles(), currentEvent(), this)));
if ( currentEvent() ) currentEvent()->addCollision(currentCollision());
currentStep(new_ptr(Step(currentCollision(), this)));
currentCollision()->addStep(currentStep());
currentStep()->addSubProcess(currentReader()->getSubProcess());
lastExtractor()->constructRemnants(lastXCombPtr()->partonBinInstances(),
subProcess(), currentStep());
if ( !currentReader()->cuts().passCuts(*currentCollision()) ) throw Veto();
initGroups();
if ( ThePEG_DEBUG_ITEM(1) ) {
if ( currentEvent() )
generator()->logfile() << *currentEvent();
else
generator()->logfile() << *currentCollision();
}
return continueCollision();
}
EventPtr FxFxEventHandler::continueEvent() {
try {
continueCollision();
}
catch (Veto) {
reject(currentEvent()->weight());
}
catch (Stop) {
}
catch (Exception &) {
reject(currentEvent()->weight());
throw;
}
return currentEvent();
}
void FxFxEventHandler::dofinish() {
EventHandler::dofinish();
if ( selector().compensating() ) generator()->log()
<< "Warning: The run was ended while the FxFxEventHandler '"
<< name() << "' was still trying to compensate for weights larger than 1. "
<< "The cross section estimates may therefore be statistically "
<< "inaccurate." << endl;
}
void FxFxEventHandler::statistics(ostream & os) const {
if ( statLevel() == 0 ) return;
string line = "======================================="
"=======================================\n";
if ( stats.accepted() <= 0 ) {
os << line << "No events generated by event handler '" << name() << "'."
<< endl;
return;
}
os << line << "Statistics for Les Houches event handler \'" << name() << "\':\n"
<< " "
<< "generated number of Cross-section\n"
<< " "
<< " events attempts (nb)\n";
os << line << "Total:" << setw(42) << stats.accepted() << setw(13)
<< stats.attempts() << setw(17)
<< ouniterr(stats.xSec(), stats.xSecErr(), nanobarn) << endl
<< line;
if ( statLevel() == 1 ) return;
if ( statLevel() == 2 ) {
os << "Per Les Houches Reader breakdown:\n";
for ( int i = 0, N = readers().size(); i < N; ++i ) {
FxFxReader & reader = *readers()[i];
string n = reader.name();
n.resize(37, ' ');
os << n << setw(11) << reader.stats.accepted() << setw(13)
<< reader.stats.attempts() << setw(17)
<< ouniterr(reader.stats.xSec(), reader.stats.xSecErr(), nanobarn)
<< endl;
}
os << line;
} else {
os << "Per Les Houches Reader (and process #) breakdown:\n";
for ( int i = 0, N = readers().size(); i < N; ++i ) {
FxFxReader & reader = *readers()[i];
string n = reader.name() + " (all)";
n.resize(37, ' ');
os << n << setw(11) << reader.stats.accepted() << setw(13)
<< reader.stats.attempts() << setw(17)
<< ouniterr(reader.stats.xSec(), reader.stats.xSecErr(), nanobarn)
<< endl;
CrossSection xsectot = reader.stats.xSec();
if ( xsectot != ZERO ) xsectot /= reader.stats.sumWeights();
typedef FxFxReader::StatMap::const_iterator const_iterator;
for ( const_iterator i = reader.statmap.begin();
i != reader.statmap.end(); ++i ) {
ostringstream ss;
ss << reader.name() << " (" << i->first << ")";
string n = ss.str();
n.resize(37, ' ');
os << n << setw(11) << i->second.accepted() << setw(13)
<< i->second.attempts() << setw(17)
<< ouniterr(i->second.sumWeights()*xsectot,
sqrt(i->second.sumWeights2())*xsectot, nanobarn) << endl;
}
os << line;
}
}
string warn = "Warning: Result may be statistically incorrect since\n"
" the following FxFxReaders were oversampled:\n";
for ( int i = 0, N = readers().size(); i < N; ++i ) {
FxFxReader & reader = *readers()[i];
if ( reader.NEvents() > 0 && reader.stats.attempts() > reader.NEvents() ) {
os << warn;
warn = "";
os << "'" << reader.name() << "' (by a factor "
<< double(reader.stats.attempts())/double(reader.NEvents())
<< ")" << endl;
}
}
}
void FxFxEventHandler::increaseMaxXSec(CrossSection maxxsec) {
stats.maxXSec(selector().sum());
histStats.maxXSec(selector().sum());
currentReader()->increaseMaxXSec(maxxsec);
}
void FxFxEventHandler::accept() {
ntries++;
stats.accept();
histStats.accept();
currentReader()->accept();
for (map<string,XSecStat>::iterator it= opthistStats.begin(); it!=opthistStats.end(); ++it){
(it->second).accept();
}
for (map<string,XSecStat>::iterator it= optstats.begin(); it!=optstats.end(); ++it){
(it->second).accept();
}
}
void FxFxEventHandler::reject(double w) {
ntries++;
stats.reject(w);
histStats.reject(w);
currentReader()->reject(w);
vector<double> wv;
for (map<string,double>::const_iterator it= currentReader()->optionalEventWeights().begin(); it!=currentReader()->optionalEventWeights().end(); ++it){
wv.push_back(it->second);
}
int ii = 0;
for (map<string,XSecStat>::iterator it= opthistStats.begin(); it!=opthistStats.end(); ++it){
(it->second).reject(wv[ii]);
ii++;
}
ii = 0;
for (map<string,XSecStat>::iterator it= optstats.begin(); it!=optstats.end(); ++it){
(it->second).reject(wv[ii]);
ii++;
}
}
map<string,CrossSection> FxFxEventHandler::optintegratedXSecMap() const {
map<string,CrossSection> result;
for (map<string,XSecStat>::const_iterator it= optstats.begin(); it!=optstats.end(); ++it){
result[it->first] = (it->second.sumWeights()/it->second.attempts()) * picobarn;
}
return result;
}
CrossSection FxFxEventHandler::histogramScale() const {
return histStats.xSec()/histStats.sumWeights();
}
CrossSection FxFxEventHandler::integratedXSec() const {
return histStats.xSec();
}
CrossSection FxFxEventHandler::integratedXSecErr() const {
return histStats.xSecErr();
}
int FxFxEventHandler::ntriesinternal() const {
return stats.attempts();
}
void FxFxEventHandler::persistentOutput(PersistentOStream & os) const {
os << stats << histStats << theReaders << theSelector
<< oenum(theWeightOption) << theUnitTolerance << theCurrentReader << warnPNum;
}
void FxFxEventHandler::persistentInput(PersistentIStream & is, int) {
is >> stats >> histStats >> theReaders >> theSelector
>> ienum(theWeightOption) >> theUnitTolerance >> theCurrentReader >> warnPNum;
}
ClassDescription<FxFxEventHandler>
FxFxEventHandler::initFxFxEventHandler;
// Definition of the static class description member.
void FxFxEventHandler::setUnitTolerance(double x) {
theUnitTolerance = x;
selector().tolerance(unitTolerance());
}
void FxFxEventHandler::Init() {
static ClassDocumentation<FxFxEventHandler> documentation
("This is the main class administrating the selection of hard "
"subprocesses from a set of ThePEG::FxFxReader objects.");
static RefVector<FxFxEventHandler,FxFxReader>
interfaceFxFxReaders
("FxFxReaders",
"Objects capable of reading events from an event file or an "
"external matrix element generator.",
&FxFxEventHandler::theReaders, -1, false, false, true, false, false);
static Switch<FxFxEventHandler,WeightOpt> interfaceWeightOption
("WeightOption",
"The different ways to weight events in the Les Houches event handler. "
"Whether weighted or not and whether or not negative weights are allowed.",
&FxFxEventHandler::theWeightOption, unitweight, true, false);
static SwitchOption interfaceWeightOptionUnitWeight
(interfaceWeightOption,
"UnitWeight",
"All events have unit weight.",
unitweight);
static SwitchOption interfaceWeightOptionNegUnitWeight
(interfaceWeightOption,
"NegUnitWeight",
"All events have weight +1 or maybe -1.",
unitnegweight);
static SwitchOption interfaceWeightOptionVarWeight
(interfaceWeightOption,
"VarWeight",
"Events may have varying but positive weights.",
varweight);
static SwitchOption interfaceWeightOptionVarNegWeight
(interfaceWeightOption,
"VarNegWeight",
"Events may have varying weights, both positive and negative.",
varnegweight);
static Switch<FxFxEventHandler,bool> interfaceWarnPNum
("WarnPNum",
"Warn if the same process number is used in more than one "
"FxFxReader.",
&FxFxEventHandler::warnPNum, true, true, false);
static SwitchOption interfaceWarnPNumWarning
(interfaceWarnPNum,
"Warning",
"Give a warning message.",
true);
static SwitchOption interfaceWarnPNumNoWarning
(interfaceWarnPNum,
"NoWarning",
"Don't give a warning message.",
false);
static Parameter<FxFxEventHandler,double> interfaceUnitTolerance
("UnitTolerance",
"If the <interface>WeightOption</interface> is set to unit weight, do not start compensating unless the a weight is found to be this much larger than unity.",
&FxFxEventHandler::theUnitTolerance, 1.0e-6, 0.0, 0,
true, false, Interface::lowerlim,
&FxFxEventHandler::setUnitTolerance,
(double(FxFxEventHandler::*)()const)(0),
(double(FxFxEventHandler::*)()const)(0),
(double(FxFxEventHandler::*)()const)(0),
(double(FxFxEventHandler::*)()const)(0));
interfaceFxFxReaders.rank(10);
interfaceWeightOption.rank(9);
}
diff --git a/Contrib/FxFx/FxFxFileReader.cc b/Contrib/FxFx/FxFxFileReader.cc
--- a/Contrib/FxFx/FxFxFileReader.cc
+++ b/Contrib/FxFx/FxFxFileReader.cc
@@ -1,793 +1,792 @@
// -*- C++ -*-
//
// FxFxFileReader.cc is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2011 Leif Lonnblad
//
// ThePEG 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 FxFxFileReader class.
//
#include "FxFxFileReader.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include <boost/algorithm/string.hpp>
-#include <boost/lexical_cast.hpp>
#include <sstream>
#include <iostream>
using namespace ThePEG;
FxFxFileReader::
FxFxFileReader(const FxFxFileReader & x)
: FxFxReader(x), neve(x.neve), ieve(0),
LHFVersion(x.LHFVersion), outsideBlock(x.outsideBlock),
headerBlock(x.headerBlock), initComments(x.initComments),
initAttributes(x.initAttributes), eventComments(x.eventComments),
eventAttributes(x.eventAttributes),
theFileName(x.theFileName), theQNumbers(x.theQNumbers),
theDecayer(x.theDecayer) {}
FxFxFileReader::~FxFxFileReader() {}
IBPtr FxFxFileReader::clone() const {
return new_ptr(*this);
}
IBPtr FxFxFileReader::fullclone() const {
return new_ptr(*this);
}
bool FxFxFileReader::preInitialize() const {
return true;
}
void FxFxFileReader::doinit() {
FxFxReader::doinit();
// are we using QNUMBERS
if(!theQNumbers) return;
// parse the header block and create
// any new particles needed in QNUMBERS blocks
string block = headerBlock;
string line = "";
bool readingSLHA = false;
int (*pf)(int) = tolower;
unsigned int newNumber(0);
do {
line = StringUtils::car(block,"\r\n");
block = StringUtils::cdr(block,"\r\n");
if(line[0]=='#') continue;
// are we reading the SLHA block
if(readingSLHA) {
// reached the end of slha block ?
if(line.find("</slha") != string::npos) {
readingSLHA = false;
break;
}
// remove trailing comment from line
vector<string> split = StringUtils::split(line,"#");
// check for a qnumbers block
transform(split[0].begin(), split[0].end(), split[0].begin(), pf);
// if not contine
if(split[0].find("block qnumbers")==string::npos)
continue;
// get name from comment
string name;
if(split.size()>=2) {
name = StringUtils::stripws(split[1]);
}
else {
++newNumber;
ostringstream tname;
tname << "NP" << newNumber;
name = tname.str();
}
// extract the PDG code
split = StringUtils::split(split[0]," ");
istringstream is(split[2]);
long PDGCode(0);
is >> PDGCode;
// get the charge, spin, colour and whether an antiparticle
int charge(0),spin(0),colour(0),anti(0);
for(unsigned int ix=0;ix<4;++ix) {
line = StringUtils::car(block,"\r\n");
block = StringUtils::cdr(block,"\r\n");
int dummy[2];
istringstream is(line);
is >> dummy[0] >> dummy[1];
switch (dummy[0]) {
case 1:
charge = dummy[1];
break;
case 2:
spin = dummy[1];
break;
case 3:
colour = dummy[1];
break;
case 4:
anti = dummy[1];
break;
default:
assert(false);
}
}
// check if particles already exist
PDPair newParticle;
newParticle.first = getParticleData(PDGCode);
if(newParticle.first) Throw<SetupException>()
<< "Particle with PDG code " << PDGCode
<< " whose creation was requested in a QNUMBERS Block"
<< " already exists. Retaining the original particle"
<< Exception::warning;
if(anti) {
newParticle.second = getParticleData(-PDGCode);
if(newParticle.second) Throw<SetupException>()
<< "Anti-particle with PDG code " << -PDGCode
<< " whose creation was requested in a QNUMBERS Block"
<< " already exists. Retaining the original particle"
<< Exception::warning;
if(( newParticle.first && !newParticle.second ) ||
( newParticle.second && !newParticle.first ) )
Throw<SetupException>()
<< "Either particle or anti-particle with PDG code " << PDGCode
<< " whose creation was requested in a QNUMBERS Block"
<< " already exists, but not both the particle and antiparticle. "
<< " Something dodgy here stopping"
<< Exception::runerror;
}
// already exists continue
if(newParticle.first) continue;
// create the particles
// particle with no anti particle
if( anti == 0 ) {
// construct the name
if(name=="") {
ostringstream temp;
temp << PDGCode;
name = temp.str();
}
// create the ParticleData object
newParticle.first = ParticleData::Create(PDGCode,name);
}
// particle anti-particle pair
else {
// construct the names
string nameAnti;
if(name=="") {
ostringstream temp;
temp << PDGCode;
name = temp.str();
ostringstream temp2;
temp << -PDGCode;
nameAnti = temp2.str();
}
else {
nameAnti=name;
for(string::iterator it=nameAnti.begin();it!=nameAnti.end();++it) {
if(*it=='+') nameAnti.replace(it,it+1,"-");
else if(*it=='-') nameAnti.replace(it,it+1,"+");
}
if(nameAnti==name) nameAnti += "bar";
}
// create the ParticleData objects
newParticle = ParticleData::Create(PDGCode,name,nameAnti);
}
// set the particle properties
if(colour==1) colour = 0;
newParticle.first->iColour(PDT::Colour(colour));
newParticle.first->iSpin (PDT::Spin (spin ));
newParticle.first->iCharge(PDT::Charge(charge));
// register it
generator()->preinitRegister(newParticle.first,
"/Herwig/Particles/"+newParticle.first->PDGName());
// set the antiparticle properties
if(newParticle.second) {
if(colour==3||colour==6) colour *= -1;
charge = -charge;
newParticle.second->iColour(PDT::Colour(colour));
newParticle.second->iSpin (PDT::Spin (spin ));
newParticle.second->iCharge(PDT::Charge(charge));
// register it
generator()->preinitRegister(newParticle.second,
"/Herwig/Particles/"+newParticle.second->PDGName());
}
}
// start of SLHA block ?
else if(line.find("<slha") != string::npos) {
readingSLHA = true;
}
}
while(line!="");
// now set any masses/decay modes
block = headerBlock;
line="";
readingSLHA=false;
bool ok=true;
do {
line = StringUtils::car(block,"\r\n");
block = StringUtils::cdr(block,"\r\n");
// are we reading the SLHA block
if(readingSLHA) {
// reached the end?
if(line.find("</slha") == 0 ) {
readingSLHA = false;
break;
}
// make lower case
transform(line.begin(),line.end(),line.begin(), pf);
// found the mass block ?
if(line.find("block mass")!=string::npos) {
// read it
line = StringUtils::car(block,"\r\n");
// check not at end
while(line[0] != 'D' && line[0] != 'B' &&
line[0] != 'd' && line[0] != 'b' &&
line != "") {
// skip comment lines
if(line[0] == '#') {
block = StringUtils::cdr(block,"\r\n");
line = StringUtils::car(block,"\r\n");
continue;
}
// get the mass and PGD code
istringstream temp(line);
long id;
double mass;
temp >> id >> mass;
// skip resetting masses on SM particles
// as it can cause problems later on in event generation
if(abs(id)<=6 || (abs(id)>=11 && abs(id)<=16) ||
abs(id)==23 || abs(id)==24) {
// Throw<SetupException>() << "Standard model mass for PID "
// << id
// << " will not be changed."
// << Exception::warning;
block = StringUtils::cdr(block,"\r\n");
line = StringUtils::car(block,"\r\n");
continue;
}
// magnitude of mass for susy models
mass = abs(mass);
// set the mass
tPDPtr particle = getParticleData(id);
if(!particle) throw SetupException()
<< "FxFxFileReader::doinit() - Particle with PDG code not"
<< id << " not found." << Exception::runerror;
const InterfaceBase * ifb = BaseRepository::FindInterface(particle,
"NominalMass");
ostringstream os;
os << mass;
ifb->exec(*particle, "set", os.str());
// read the next line
block = StringUtils::cdr(block,"\r\n");
line = StringUtils::car(block,"\r\n");
};
}
// found a decay block
else if(line.find("decay") == 0) {
// get PGD code and width
istringstream iss(line);
string dummy;
long parent(0);
Energy width(ZERO);
iss >> dummy >> parent >> iunit(width, GeV);
// get the ParticleData object
PDPtr inpart = getParticleData(parent);
if(!inpart) {
throw SetupException()
<< "FxFxFileReader::doinit() - A ParticleData object with the PDG code "
<< parent << " does not exist. " << Exception::runerror;
return;
}
if ( abs(inpart->id()) == 6 ||
abs(inpart->id()) == 15 ||
abs(inpart->id()) == 23 ||
abs(inpart->id()) == 24 ||
abs(inpart->id()) == 25 ) {
Throw<SetupException>() << "\n"
"************************************************************************\n"
"* Your LHE file changes the width of " << inpart->PDGName() << ".\n"
"* This can cause serious problems in the event generation!\n"
"************************************************************************\n"
"\n" << Exception::warning;
}
else if (inpart->width() > ZERO && width <= ZERO) {
Throw<SetupException>() << "\n"
"************************************************************************\n"
"* Your LHE file zeroes the non-zero width of " << inpart->PDGName() << ".\n"
"* If " << inpart->PDGName() << " is a decaying SM particle,\n"
"* this can cause serious problems in the event generation!\n"
"************************************************************************\n"
"\n" << Exception::warning;
}
// set the width
inpart->width(width);
if( width > ZERO ) {
inpart->cTau(hbarc/width);
inpart->widthCut(5.*width);
inpart->stable(false);
}
// construct prefix for DecayModes
string prefix(inpart->name() + "->"), tag(prefix),line("");
unsigned int nmode(0);
// read any decay modes
line = StringUtils::car(block,"\r\n");
while(line[0] != 'D' && line[0] != 'B' &&
line[0] != 'd' && line[0] != 'b' &&
line[0] != '<' && line != "") {
// skip comments
if(line[0] == '#') {
block = StringUtils::cdr(block,"\r\n");
line = StringUtils::car(block,"\r\n");
continue;
}
// read decay mode and construct the tag
istringstream is(line);
double brat(0.);
unsigned int nda(0),npr(0);
is >> brat >> nda;
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 in FxFxFileReader::doinit()."
<< " Please check the Les Houches file.\n"
<< Exception::runerror;
tcPDPtr p = getParticleData(t);
if( !p )
throw SetupException()
<< "FxFxFileReader::doinit() -"
<< " An unknown PDG code has been encounterd "
<< "while reading a decay mode. ID: " << t
<< Exception::runerror;
++npr;
tag += p->name() + ",";
}
if( npr != nda )
throw SetupException()
<< "FxFxFileReader::doinit() - 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;
// create the DecayMode
if( npr > 1 ) {
if( nmode==0 ) {
generator()->preinitInterface(inpart, "VariableRatio" , "set","false");
if(inpart->massGenerator()) {
ok = false;
Throw<SetupException>()
<< inpart->PDGName() << " already has a MassGenerator set"
<< " this is incompatible with using QNUMBERS "
<< "Use\n"
<< "set " << inpart->fullName() << ":Mass_generator NULL\n"
<< "to fix this." << Exception::warning;
}
if(inpart->widthGenerator()) {
ok = false;
Throw<SetupException>()
<< inpart->PDGName() << " already has a WidthGenerator set"
<< " this is incompatible with using QNUMBERS "
<< "Use\n"
<< "set " << inpart->fullName() << ":Width_generator NULL\n"
<< "to fix this." << Exception::warning;
}
unsigned int ntemp=0;
for(DecaySet::const_iterator dit = inpart->decayModes().begin();
dit != inpart->decayModes().end(); ++dit ) {
if((**dit).on()) ++ntemp;
}
if(ntemp!=0) {
ok = false;
Throw<SetupException>()
<< inpart->PDGName() << " already has DecayModes"
<< " this is incompatible with using QNUMBERS "
<< "Use\n"
<< "do " << inpart->fullName() << ":SelectDecayModes none\n"
<< " to fix this." << Exception::warning;
}
}
inpart->stable(false);
tag.replace(tag.size() - 1, 1, ";");
DMPtr dm = generator()->findDecayMode(tag);
if(!theDecayer) Throw<SetupException>()
<< "FxFxFileReader::doinit() Decayer must be set using the "
<< "FxFxFileReader:Decayer"
<< " must be set to allow the creation of new"
<< " decay modes."
<< Exception::runerror;
if(!dm) {
dm = generator()->preinitCreateDecayMode(tag);
if(!dm)
Throw<SetupException>()
<< "FxFxFileReader::doinit() - Needed to create "
<< "new decaymode but one could not be created for the tag "
<< tag << Exception::warning;
}
generator()->preinitInterface(dm, "Decayer", "set",
theDecayer->fullName());
ostringstream br;
br << setprecision(13) << brat;
generator()->preinitInterface(dm, "BranchingRatio", "set", br.str());
generator()->preinitInterface(dm, "OnOff", "set", "On");
if(dm->CC()) {
generator()->preinitInterface(dm->CC(), "BranchingRatio", "set", br.str());
generator()->preinitInterface(dm->CC(), "OnOff", "set", "On");
}
++nmode;
}
tag=prefix;
// read the next line
block = StringUtils::cdr(block,"\r\n");
line = StringUtils::car(block,"\r\n");
};
if(nmode>0) {
inpart->update();
if(inpart->CC())
inpart->CC()->update();
}
}
}
// start of SLHA block ?
else if(line.find("<slha") != string::npos) {
readingSLHA = true;
}
}
while(line!="");
if(!ok)
throw SetupException() << "Problem reading QNUMBERS blocks in FxFxFileReader::doinit()"
<< Exception::runerror;
}
void FxFxFileReader::initialize(FxFxEventHandler & eh) {
FxFxReader::initialize(eh);
if ( LHFVersion.empty() )
Throw<FxFxFileError>()
<< "The file associated with '" << name() << "' does not contain a "
<< "proper formatted Les Houches event file. The events may not be "
<< "properly sampled." << Exception::warning;
}
//vector<string> FxFxFileReader::optWeightNamesFunc() { return optionalWeightsNames; }
vector<string> FxFxFileReader::optWeightsNamesFunc() { return optionalWeightsNames; }
void FxFxFileReader::open() {
if ( filename().empty() )
throw FxFxFileError()
<< "No Les Houches file name. "
<< "Use 'set " << name() << ":FileName'."
<< Exception::runerror;
cfile.open(filename());
if ( !cfile )
throw FxFxFileError()
<< "The FxFxFileReader '" << name() << "' could not open the "
<< "event file called '" << theFileName << "'."
<< Exception::runerror;
cfile.readline();
if ( !cfile.find("<LesHouchesEvents") ) return;
map<string,string> attributes =
StringUtils::xmlAttributes("LesHouchesEvents", cfile.getline());
LHFVersion = attributes["version"];
//cout << LHFVersion << endl;
if ( LHFVersion.empty() ) return;
bool readingHeader = false;
bool readingInit = false;
headerBlock = "";
char (cwgtinfo_weights_info[250][15]);
string hs;
int cwgtinfo_nn(0);
while ( cfile.readline() ) {
if(cfile.find("<initrwgt>")) { break; }
}
cfile.readline();
string scalename = "";
if(cfile.find("<weightgroup type='scale_variation'")) {
while ( cfile.readline() && !cfile.find("</weightgroup>") ) {
hs = cfile.getline();
std::string xmuR = hs.substr(hs.find("muR")+4,hs.length());
xmuR = xmuR.substr(0,xmuR.find("muF")-1);
std::string xmuF = hs.substr(hs.find("muF")+4,hs.length());
xmuF = xmuF.substr(0,xmuF.find("</w")-1);
double muR = atof(xmuR.c_str());
double muF = atof(xmuF.c_str());
istringstream isc(hs);
int ws = 0;
do {
string sub; isc >> sub;
if(ws==1) { boost::erase_all(sub, ">"); scalename = sub; }
++ws;
} while (isc);
// cout << scaleinfo.first << "\t" << scaleinfo.second << endl;
- std::string xmuRs = boost::lexical_cast<std::string>(muR);
- std::string xmuFs = boost::lexical_cast<std::string>(muF);
+ std::string xmuRs = std::to_string(muR);
+ std::string xmuFs = std::to_string(muF);
string scinfo = "SC " + xmuRs + " " + xmuFs;
scalemap[scalename] = scinfo.c_str();
boost::erase_all(scalename, "id=");
boost::erase_all(scalename, "'");
optionalWeightsNames.push_back(scalename);
}
}
cfile.readline();
// cout << cfile.getline() << endl;
string pdfname = "";
if(cfile.find("<weightgroup type='PDF_variation'")) {
while ( cfile.readline() && !cfile.find("</weightgroup>") ) {
hs = cfile.getline();
std::string PDF = hs.substr(hs.find("pdfset")+8,hs.length());
PDF = PDF.substr(0,PDF.find("</w")-1);
double iPDF = atof(PDF.c_str());
//store the plot label
istringstream isp(hs);
int wp = 0;
do {
string sub; isp >> sub;
if(wp==1) { boost::erase_all(sub, ">"); pdfname = sub; }
++wp;
} while (isp);
// cout << pdfinfo.first << "\t" << pdfinfo.second << endl;
string scinfo = "PDF " + PDF;
scalename = pdfname;
scalemap[scalename] = scinfo.c_str();
boost::erase_all(pdfname, "id=");
boost::erase_all(pdfname, "'");
optionalWeightsNames.push_back(pdfname);
}
}
/* for(int f = 0; f < optionalWeightsNames.size(); f++) {
cout << "optionalWeightsNames = " << optionalWeightsNames[f] << endl;
}*/
// Loop over all lines until we hit the </init> tag.
while ( cfile.readline() && !cfile.find("</init>") ) {
if ( cfile.find("<header") ) {
// We have hit the header block, so we should dump this and all
// following lines to headerBlock until we hit the end of it.
readingHeader = true;
headerBlock = cfile.getline() + "\n";
}
else if ( cfile.find("<init ") || cfile.find("<init>") ) {
// We have hit the init block, so we should expect to find the
// standard information in the following. But first check for
// attributes.
initAttributes = StringUtils::xmlAttributes("init", cfile.getline());
readingInit = true;
cfile.readline();
if ( !( cfile >> heprup.IDBMUP.first >> heprup.IDBMUP.second
>> heprup.EBMUP.first >> heprup.EBMUP.second
>> heprup.PDFGUP.first >> heprup.PDFGUP.second
>> heprup.PDFSUP.first >> heprup.PDFSUP.second
>> heprup.IDWTUP >> heprup.NPRUP ) ) {
heprup.NPRUP = -42;
LHFVersion = "";
return;
}
heprup.resize();
for ( int i = 0; i < heprup.NPRUP; ++i ) {
cfile.readline();
if ( !( cfile >> heprup.XSECUP[i] >> heprup.XERRUP[i]
>> heprup.XMAXUP[i] >> heprup.LPRUP[i] ) ) {
heprup.NPRUP = -42;
LHFVersion = "";
return;
}
}
}
else if ( cfile.find("</header") ) {
readingHeader = false;
headerBlock += cfile.getline() + "\n";
}
else if ( readingHeader ) {
// We are in the process of reading the header block. Dump the
// line to headerBlock.
headerBlock += cfile.getline() + "\n";
}
else if ( readingInit ) {
// Here we found a comment line. Dump it to initComments.
initComments += cfile.getline() + "\n";
}
else {
// We found some other stuff outside the standard tags.
outsideBlock += cfile.getline() + "\n";
}
}
if ( !cfile ) {
heprup.NPRUP = -42;
LHFVersion = "";
return;
}
}
bool FxFxFileReader::doReadEvent() {
if ( !cfile ) return false;
if ( LHFVersion.empty() ) return false;
if ( heprup.NPRUP < 0 ) return false;
eventComments = "";
outsideBlock = "";
hepeup.NUP = 0;
hepeup.XPDWUP.first = hepeup.XPDWUP.second = 0.0;
optionalWeights.clear();
optionalWeightsTemp.clear();
// Keep reading lines until we hit the next event or the end of
// the event block. Save any inbetween lines. Exit if we didn't
// find an event.
while ( cfile.readline() && !cfile.find("<event") )
outsideBlock += cfile.getline() + "\n";
// We found an event. First scan for attributes.
eventAttributes = StringUtils::xmlAttributes("event", cfile.getline());
istringstream ievat(cfile.getline());
int we(0), npLO(-10), npNLO(-10);
do {
string sub; ievat >> sub;
if(we==2) { npLO = atoi(sub.c_str()); }
if(we==5) { npNLO = atoi(sub.c_str()); }
++we;
} while (ievat);
//cout << "npLO, npNLO = " << npLO << ", " << npNLO << endl;
optionalnpLO = npLO;
optionalnpNLO = npNLO;
std::stringstream npstringstream;
npstringstream << "np " << npLO << " " << npNLO;
std::string npstrings = npstringstream.str();
// cout << npstrings.c_str() << endl;
optionalWeights[npstrings.c_str()] = -999;
if ( !cfile.readline() ) return false;
// The first line determines how many subsequent particle lines we
// have.
if ( !( cfile >> hepeup.NUP >> hepeup.IDPRUP >> hepeup.XWGTUP
>> hepeup.SCALUP >> hepeup.AQEDUP >> hepeup.AQCDUP ) )
return false;
hepeup.resize();
// Read all particle lines.
for ( int i = 0; i < hepeup.NUP; ++i ) {
if ( !cfile.readline() ) return false;
if ( !( cfile >> hepeup.IDUP[i] >> hepeup.ISTUP[i]
>> hepeup.MOTHUP[i].first >> hepeup.MOTHUP[i].second
>> hepeup.ICOLUP[i].first >> hepeup.ICOLUP[i].second
>> hepeup.PUP[i][0] >> hepeup.PUP[i][1] >> hepeup.PUP[i][2]
>> hepeup.PUP[i][3] >> hepeup.PUP[i][4]
>> hepeup.VTIMUP[i] >> hepeup.SPINUP[i] ) )
return false;
- if(isnan(hepeup.PUP[i][0])||isnan(hepeup.PUP[i][1])||
- isnan(hepeup.PUP[i][2])||isnan(hepeup.PUP[i][3])||
- isnan(hepeup.PUP[i][4]))
+ if(std::isnan(hepeup.PUP[i][0])||std::isnan(hepeup.PUP[i][1])||
+ std::isnan(hepeup.PUP[i][2])||std::isnan(hepeup.PUP[i][3])||
+ std::isnan(hepeup.PUP[i][4]))
throw Exception()
<< "nan's as momenta in Les Houches file "
<< Exception::eventerror;
if(hepeup.MOTHUP[i].first -1==i ||
hepeup.MOTHUP[i].second-1==i) {
throw Exception()
<< "Particle has itself as a mother in Les Houches "
<< "file, this is not allowed\n"
<< Exception::eventerror;
}
}
// Now read any additional comments and named weights.
// read until the end of rwgt is found
while ( cfile.readline() && !cfile.find("</rwgt>")) {
if(!cfile.find("<wgt")) { continue; }
istringstream iss(cfile.getline());
int wi = 0;
double weightValue(0);
string weightName = "";
do {
string sub; iss >> sub;
if(wi==1) { boost::erase_all(sub, ">"); weightName = sub; }
if(wi==2) weightValue = atof(sub.c_str());
++wi;
} while (iss);
// store the optional weights found in the temporary map
optionalWeightsTemp[weightName] = weightValue;
}
// loop over the optional weights and add the extra information (pdf or scale)
for (map<string,double>::const_iterator it=optionalWeightsTemp.begin(); it!=optionalWeightsTemp.end(); ++it){
//std::cout << it->first << " => " << it->second << '\n';
for (map<string,string>::const_iterator it2=scalemap.begin(); it2!=scalemap.end(); ++it2){
//find the scale id in the scale information and add this information
if(it->first==it2->first) {
string info = it2->second + " " + it->first;
boost::erase_all(info, "'");
boost::erase_all(info, "id=");
//set the optional weights
optionalWeights[info] = it->second;
}
}
}
if ( !cfile ) return false;
return true;
}
void FxFxFileReader::close() {
cfile.close();
}
void FxFxFileReader::persistentOutput(PersistentOStream & os) const {
os << neve << LHFVersion << outsideBlock << headerBlock << initComments
<< initAttributes << eventComments << eventAttributes << theFileName
<< theQNumbers << theDecayer;
}
void FxFxFileReader::persistentInput(PersistentIStream & is, int) {
is >> neve >> LHFVersion >> outsideBlock >> headerBlock >> initComments
>> initAttributes >> eventComments >> eventAttributes >> theFileName
>> theQNumbers >> theDecayer;
ieve = 0;
}
ClassDescription<FxFxFileReader>
FxFxFileReader::initFxFxFileReader;
// Definition of the static class description member.
void FxFxFileReader::Init() {
static ClassDocumentation<FxFxFileReader> documentation
("ThePEG::FxFxFileReader is an base class to be used for objects "
"which reads event files from matrix element generators. This class is "
"able to read plain event files conforming to the Les Houches Event File "
"accord.");
static Parameter<FxFxFileReader,string> interfaceFileName
("FileName",
"The name of a file containing events conforming to the Les Houches "
"protocol to be read into ThePEG. A file name ending in "
"<code>.gz</code> will be read from a pipe which uses "
"<code>zcat</code>. If a file name ends in <code>|</code> the "
"preceeding string is interpreted as a command, the output of which "
"will be read through a pipe.",
&FxFxFileReader::theFileName, "", false, false);
interfaceFileName.fileType();
interfaceFileName.rank(11);
static Switch<FxFxFileReader,bool> interfaceQNumbers
("QNumbers",
"Whether or not to read search for and read a QNUMBERS"
" block in the header of the file.",
&FxFxFileReader::theQNumbers, false, false, false);
static SwitchOption interfaceQNumbersYes
(interfaceQNumbers,
"Yes",
"Use QNUMBERS",
true);
static SwitchOption interfaceQNumbersNo
(interfaceQNumbers,
"No",
"Don't use QNUMBERS",
false);
static Reference<FxFxFileReader,Decayer> interfaceDecayer
("Decayer",
"Decayer to use for any decays read from the QNUMBERS Blocks",
&FxFxFileReader::theDecayer, false, false, true, true, false);
}
diff --git a/Contrib/FxFx/FxFxHandler.cc b/Contrib/FxFx/FxFxHandler.cc
--- a/Contrib/FxFx/FxFxHandler.cc
+++ b/Contrib/FxFx/FxFxHandler.cc
@@ -1,1435 +1,1458 @@
#include "FxFxHandler.h"
#include "FxFxReader.h"
#include "FxFxReader.fh"
#include "FxFxEventHandler.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"
#include <boost/algorithm/string.hpp>
using namespace Herwig;
using namespace ThePEG;
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);
}
FxFxHandler::FxFxHandler()
: 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_(1),vetoIsTurnedOff_(false),vetoSoftThanMatched_(false), etclusfixed_(true),epsetclus_(2.5*GeV)
+ ycmax_(5.4),ycmin_(-5.4),jetAlgorithm_(1),vetoIsTurnedOff_(false),vetoSoftThanMatched_(false), etclusfixed_(true),epsetclus_(2.5*GeV), vetoHeavyQ_(true)
{}
void FxFxHandler::doinitrun() {
- ShowerHandler::doinitrun();
+ QTildeShowerHandler::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 FxFxHandler::clone() const {
return new_ptr(*this);
}
IBPtr FxFxHandler::fullclone() const {
return new_ptr(*this);
}
void FxFxHandler::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_ << vetoSoftThanMatched_ << etclusfixed_
- << cphcal_ << sphcal_ << cthcal_ << sthcal_ << ounit(epsetclus_,GeV);
+ << cphcal_ << sphcal_ << cthcal_ << sthcal_ << ounit(epsetclus_,GeV) << vetoHeavyQ_;
}
void FxFxHandler::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_ >> vetoSoftThanMatched_ >> etclusfixed_
- >> cphcal_ >> sphcal_ >> cthcal_ >> sthcal_ >> iunit(epsetclus_,GeV);
+ >> cphcal_ >> sphcal_ >> cthcal_ >> sthcal_ >> iunit(epsetclus_,GeV) >> vetoHeavyQ_;
}
ClassDescription<FxFxHandler> FxFxHandler::initFxFxHandler;
// Definition of the static class description member.
void FxFxHandler::Init() {
static ClassDocumentation<FxFxHandler> documentation
("The FxFxHandler class performs MEPS merging "
"using the MLM procedure.");
static Reference<FxFxHandler,ShowerAlpha> interfaceShowerAlpha
("ShowerAlpha",
"The object calculating the strong coupling constant",
&FxFxHandler::alphaS_, false, false, true, false, false);
static Parameter<FxFxHandler,int> interfaceihvy
("ihvy",
"heavy flavour in WQQ,ZQQ,2Q etc (4=c, 5=b, 6=t)",
&FxFxHandler::ihvy_, -999, -999, 7,
false, false, Interface::limited);
static Parameter<FxFxHandler,int> interfacenph
("nph",
"Number of photons in the AlpGen process",
&FxFxHandler::nph_, -999, -999, 7,
false, false, Interface::limited);
static Parameter<FxFxHandler,int> interfacenh
("nh",
"Number of higgses in the AlpGen process",
&FxFxHandler::nph_, -999, -999, 7,
false, false, Interface::limited);
static Parameter<FxFxHandler,Energy> interfaceETClus
("ETClus",
"The ET threshold defining a jet in the merging procedure",
&FxFxHandler::etclusmean_, GeV, 20*GeV, 0*GeV, 14000*GeV,
false, false, Interface::limited);
static Parameter<FxFxHandler,double> interfaceRClus
("RClus",
"The cone size used to define a jet in the merging procedure",
&FxFxHandler::rclus_, 0.4, 0.0, 4.0,
false, false, Interface::limited);
static Parameter<FxFxHandler,double> interfaceEtaClusMax
("EtaClusMax",
"The maximum |eta| used to define a jet in the merging procedure",
&FxFxHandler::etaclmax_, 5.0, 0.0, 15.0,
false, false, Interface::limited);
static Parameter<FxFxHandler,double> interfaceRClusFactor
("RClusFactor",
"The prefactor for RClus used to define the jet-parton matching "
"distance",
&FxFxHandler::rclusfactor_, 1.5, 0.0, 4.0,
false, false, Interface::limited);
static Parameter<FxFxHandler,int> interfaceihrd
("ihrd",
"The AlpGen hard process code",
&FxFxHandler::ihrd_, -999, 0, 10000,
false, false, Interface::limited);
static Parameter<FxFxHandler,int> interfacenjetsmax
("njetsmax",
"The number of light jets in the maximum-multiplicity process",
&FxFxHandler::njets_, -999, 0, 10000,
false, false, Interface::limited);
static Parameter<FxFxHandler,double> interfacedrjmin
("drjmin",
"Mimimum parton-parton R-sep used for generation.",
&FxFxHandler::drjmin_, 0.7, 0.0, 4.0,
false, false, Interface::limited);
static Parameter<FxFxHandler,bool> interfacehighestMultiplicity
("highestMultiplicity",
"If true it indicates that this is the highest multiplicity input "
"ME-level configuration to be processed.",
&FxFxHandler::highestMultiplicity_, 0, 0, 1,
false, false, Interface::limited);
static Parameter<FxFxHandler,bool> interfaceETClusFixed
("ETClusFixed",
"If false, indicates that the jet merging scale, etclus_ is allowed to vary"
"according to epsetclus_",
&FxFxHandler::etclusfixed_, 1, 0, 1,
false, false, Interface::limited);
static Parameter<FxFxHandler,Energy> interfaceEpsilonETClus
("EpsilonETClus",
"The ET threshold defining a jet in the merging procedure",
&FxFxHandler::epsetclus_, GeV, 2.5*GeV, 0*GeV, 100.0*GeV,
false, false, Interface::limited);
static Switch<FxFxHandler,int> interfaceJetAlgorithm
("JetAlgorithm",
"Determines the jet algorithm for finding jets in parton-jet "
"matching in the MLM procedure.",
&FxFxHandler::jetAlgorithm_, 1, 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 Switch<FxFxHandler,bool> interfaceVetoIsTurnedOff
("VetoIsTurnedOff",
"Allows the vetoing mechanism to be switched off.",
&FxFxHandler::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<FxFxHandler,bool> interfaceHeavyQVeto
+ ("HeavyQVeto",
+ "Allows the vetoing mechanism on the heavy quark products to be switched off.",
+ &FxFxHandler::vetoHeavyQ_, false, false, false);
+ static SwitchOption HQVetoingIsOn
+ (interfaceHeavyQVeto,
+ "On",
+ "The MLM merging veto on Heavy quark decay produts mechanism is switched ON.",
+ true);
+ static SwitchOption HQVetoingIsOff
+ (interfaceHeavyQVeto,
+ "Off",
+ "The MLM merging veto on Heavy quark decay products mechanism is switched OFF.",
+ false);
+
static Switch<FxFxHandler,bool> interfaceVetoSoftThanMatched
("VetoSoftThanMatched",
"Allows the vetoing mechanism to be switched off.",
&FxFxHandler::vetoSoftThanMatched_, false, false, false);
static SwitchOption VetoSoftIsOn
(interfaceVetoSoftThanMatched,
"VetoSoftIsOn",
"The vetoing of highest-mult. events with jets softer than matched ones is ON",
true);
static SwitchOption VetoSoftIsOff
(interfaceVetoSoftThanMatched,
"VetoSoftIsOff",
"The vetoing of highest-mult. events with jets softer than matched ones is OFF.",
false);
}
void FxFxHandler::dofinish() {
- ShowerHandler::dofinish();
+ QTildeShowerHandler::dofinish();
}
void FxFxHandler::doinit() {
//print error if HardProcID is not set in input file
if(ihrd_ == -999) { cout << "Error: FxFxHandler:ihrd not set!" << endl; exit(1); }
- ShowerHandler::doinit();
+ QTildeShowerHandler::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 FxFxHandler::showerHardProcessVeto() {
+ int debug_mode = 0;
if(vetoIsTurnedOff_) return false;
+ //if(debug_mode) { cout << "debug_mode = " << 5 << endl; }
+
// Skip veto for processes in which merging is not implemented:
if(ihrd_==7||ihrd_==8||ihrd_==13) {
ostringstream wstring;
wstring << "FxFxHandler::showerHardProcessVeto() - warning."
<< "MLM merging not implemented "
<< "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();
// Get npLO_ and npNLO_ for FxFx matching
getnpFxFx();
// print the npXLO_ values obtained
// cout << "HANDLER:\t\t\t\t" << npLO_ << "\t\t" << npNLO_ << endl;
// Turn on some screen output debugging: 0 = none ---> 5 = very verbose.
- int debug_mode = 0;
doSanityChecks(debug_mode);
// 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_ ;
// 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);
}
// Cluster particlesToCluster_ into jets with FastJet.
getFastJets(rclus_,etclus_,etaclmax_);
//FxFx modifications start here.
// Sort partonsToMatch_ from high to low pT.
sort(partonsToMatch_.begin(),partonsToMatch_.end(),pTsortFunction);
// Count the number of jets.
int njets_found(pjet_.size());
// If the number of jets found is not equal to the number of partons in the Born
// (i.e., the number of partons in the S-event, or one less than the number of partons in an H-event),
// the jets cannot be matched and the event has to be rejected. The number of partons in the Born is written in the event file with a name “npNLO”
// if there are no jets to match and no jets have been found, do not veto.
if(njets_found == 0 && npNLO_ == 0) { /*cout << "njets_found = " << njets_found << " and npNLO = " << npNLO_ << ", accepting" << endl;*/ return false; }
//if the number of jets is smaller than npNLO -> reject the event.
if(njets_found < npNLO_) { /*cout << "njets_found = " << njets_found << " and npNLO = " << npNLO_ << ", rejecting" << endl;*/ return true; }
// For the maximum-multiplicity sample, the number of jets obtained does not have to be exactly equal to npNLO, it may also be larger;
if(njets_found > npNLO_ && npNLO_ != njets_) { /*cout << "njets_found = " << njets_found << " and npNLO = " << npNLO_ << ", rejecting" << endl;*/ return true; }
// Create the matrix-element jets.
// Cluster also the partons at the hard-matrix element level into jets with the same algorithm as above,
// but without the requirement of a minimal pT on the jets (or set it very small).
// By construction, for S-events you should find exactly npNLO jets, while for the H-events it is either npNLO or npNLO+1.
// Cluster partonsToMatch_ into jets with FastJet.
getFastJetsToMatch(rclus_,0*GeV,etaclmax_);
int me_njets_found(pjetME_.size());
// cout << "number of ME jets found = " << me_njets_found << "partons to match: " << partonsToMatch_.size() << endl;
// Match light progenitors to jets.
vector<int> jetToPartonMap(pjetME_.size(),-999);
Energy etmin(777e100*GeV);
// Match the jets.
// Try to match the “npNLO” hardest jets created post-shower with any of the jets pre-shower. Two jets are matched if the distance between them is smaller than 1.5*DeltaR.
// If not all the npNLO hardest shower jets are matched the event has to be rejected.
// Note that if the current event does not belong to the maximum multiplicity sample, this means that all the shower jets need to be matched, because the requirement above already rejects
// events that do not have npNLO shower jets.
// For those events, at the level of the matrix elements there can either be npNLO or npNLO+1 matrix-element jets, depending on S- or H-events and the kinematics of those partons.
// Still only the shower jets need to be matched, so an event should not be rejected if a matrix-element jet cannot be matched.
// For each parton, starting with the hardest one ...
for(unsigned int ixx=0; ixx<npNLO_; ixx++) {
// ... loop over all jets not already matched.
double DRmin(777e100);
int jetIndexForDRmin(-999);
for(unsigned int jxx=0; jxx<pjetME_.size(); jxx++) {
// ... and tag closest of the remaining ones
double DRpartonJet(partonJetDeltaR(pjetME_[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 where matched jets are softer than non-matched ones,
// in the inclusive (highestMultiplicity_ = true) mode, unless we
// are dealing with NLO input events.
if(npNLO_ == njets_ && vetoSoftThanMatched_) {
//cout << "highest mult. event being tested for softer jets than matched..." << endl;
for(unsigned int iyy=0; iyy<pjet_.size(); iyy++) {
//cout << "etjet_[iyy] = " << etjet_[iyy]/GeV << endl;
if(jetToPartonMap[iyy]<0&&etmin<etjet_[iyy]) { /*cout << "VETO!" << endl;*/ return true; }
}
}
+
+ if(!vetoHeavyQ_) {
+ //cout << "no heavy quark decay product veto!" << endl;
+ return false;
+ }
+
//end of FxFx part
// **************************************************************** //
// * 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();
// 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 FxFxHandler::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;
}
double FxFxHandler::partonJetDeltaR(LorentzMomentum jetmom1, LorentzMomentum jetmom2) {
// Calculate DY, DPhi and then DR
double DY(jetmom1.eta()-jetmom2.eta());
double DPhi(jetmom1.phi()-jetmom2.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 FxFxHandler::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 FxFxHandler::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;
}
// Get FastJets from partonsToMatch_
void FxFxHandler::getFastJetsToMatch(double rjet, Energy ejcut, double etajcut) {
vector<fastjet::PseudoJet> particlesToCluster;
for(unsigned int ipar=0; ipar<partonsToMatch_.size(); ipar++) {
double y(partonsToMatch_[ipar]->momentum().eta());
if(y>=ycmin_&&y<=ycmax_) {
int absId(abs(partonsToMatch_[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(partonsToMatch_[ipar]->momentum().x()/GeV,
partonsToMatch_[ipar]->momentum().y()/GeV,
partonsToMatch_[ipar]->momentum().z()/GeV,
partonsToMatch_[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.
pjetME_.clear();
pjetME_.resize(inclusiveJets.size());
for(unsigned int ffj=0; ffj<pjetME_.size();ffj++) {
pjetME_[ffj] = Lorentz5Momentum(inclusiveJets[ffj].px()*GeV,
inclusiveJets[ffj].py()*GeV,
inclusiveJets[ffj].pz()*GeV,
inclusiveJets[ffj].e()*GeV);
pjetME_[ffj].rescaleMass();
}
return;
}
// Simple calorimeter simulation - assume uniform Y and phi bins.
void FxFxHandler::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 FxFxHandler::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 << "FxFxHandler::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 FxFxHandler::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 FxFxHandler::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()
<< "FxFxHandler::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()
<< "FxFxHandler::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()
<< "FxFxHandler::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()
<< "FxFxHandler::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()
<< "FxFxHandler::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()
<< "FxFxHandler::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()
<< "FxFxHandler::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()
<< "FxFxHandler::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()
<< "FxFxHandler::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()
<< "FxFxHandler::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()
<< "FxFxHandler::caldel_m() - ERROR!\n"
<< "wphjet process should have " << 2+nph_ << " particles to omit from"
<< "jet-parton matching for ihvy=" << ihvy_ << "." << Exception::eventerror;
}
}
}
}
// cout << "partonsToMatch_.size()= " << partonsToMatch_.size() << " preshowerFSPsToDelete_.size() = " << preshowerFSPsToDelete_.size() << endl;
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;
}
}
}
//cout << "partonsToMatch_.size() (AFTER) = " << partonsToMatch_.size() << endl;
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()
<< "FxFxHandler::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;
}
// cout << "partonsToMatch_.size() (AFTER2) = " << partonsToMatch_.size() << endl;
// 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()
<< "FxFxHandler::caldel_m() - ERROR!\n"
<< "Found a parton to match to which is not a quark or gluon!"
<< *partonsToMatch_[ixx] << "\n"
<< Exception::eventerror;
}
throw Exception()
<< "FxFxHandler::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;
} */
//cout << "partonsToMatch_.size() (AFTER3) = " << partonsToMatch_.size() << endl;
return;
}
// This looks for all descendents of a top up to but not including
// the W and b children.
void FxFxHandler::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 FxFxHandler::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;
}
// get npLO_ and npNLO_
void FxFxHandler::getnpFxFx() {
split_vector_type SplitVec;
// pull the optional weights from the current event
map<string,double> optionalEventWeights = eventHandler()->currentEvent()->optionalWeights();
// loop over the optional weights and find np values
for (map<string,double>::const_iterator it=optionalEventWeights.begin(); it!=optionalEventWeights.end(); ++it){
// split the line
boost::split( SplitVec, it->first, boost::is_any_of(" ") );
// if np is found, store the information
if(SplitVec[0] == "np") {
npLO_ = atof(SplitVec[1].c_str());
npNLO_ = atof(SplitVec[2].c_str());
}
}
return;
}
void FxFxHandler::getPreshowerParticles() {
// LH file initial-state partons:
preshowerISPs_ = lastXCombPtr()->subProcess()->incoming();
// LH file final-state partICLEs:
preshowerFSPs_ = lastXCombPtr()->subProcess()->outgoing();
return;
}
void FxFxHandler::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 FxFxHandler::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 << "FxFxHandler::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 << "FxFxHandler::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 FxFxHandler::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 FxFxHandler::etclusran_(double petc) {
return (((2 * epsetclus_)/M_PI) * asin(2 * petc - 1) + etclusmean_);
}
diff --git a/Contrib/FxFx/FxFxHandler.h b/Contrib/FxFx/FxFxHandler.h
--- a/Contrib/FxFx/FxFxHandler.h
+++ b/Contrib/FxFx/FxFxHandler.h
@@ -1,603 +1,610 @@
// -*- C++ -*-
#ifndef HERWIG_FxFxHandler_H
#define HERWIG_FxFxHandler_H
//
// This is the declaration of the FxFxHandler class.
//
+#include "Herwig/Shower/QTilde/QTildeShowerHandler.h"
#include "Herwig/Shower/ShowerHandler.h"
-#include "Herwig/Shower/QTilde/Base/Evolver.h"
#include "ThePEG/Config/Pointers.h"
-#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h"
+#include "Herwig/Shower/Couplings/ShowerAlpha.h"
#include "fastjet/PseudoJet.hh"
#include "fastjet/ClusterSequence.hh"
#include "ThePEG/Utilities/CompSelector.h"
#include "ThePEG/Utilities/XSecStat.h"
namespace Herwig {
class FxFxHandler;
}
//declaration of thepeg ptr
namespace ThePEG {
ThePEG_DECLARE_POINTERS(Herwig::FxFxHandler,FxFxHandlerPtr);
}
namespace Herwig {
using namespace ThePEG;
typedef vector< string > split_vector_type;
/**
* Here is the documentation of the FxFxHandler class.
*
* @see \ref FxFxHandlerInterfaces "The interfaces"
* defined for FxFxHandler.
*/
-class FxFxHandler: public ShowerHandler {
+class FxFxHandler: public QTildeShowerHandler {
/**
* FxFxHandler should have access to our private parts.
*/
friend class FxFxEventHandler;
friend class FxFxReader;
public:
/**
* The default constructor.
*/
FxFxHandler();
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. */
//@{
/**
* Finalize the object
*/
virtual void dofinish();
/**
* 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();
//@}
public:
/**
* Hook to allow vetoing of event after showering hard sub-process
* as in e.g. MLM merging.
*/
virtual bool showerHardProcessVeto();
/**
* information for FxFx merging
*/
int npLO_;
int npNLO_;
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;
//@}
private:
/*
* Run MLM jet-parton matching on the 'extra' jets.
*/
bool lightJetPartonVeto();
/*
* Function that calculates deltaR between a parton and a jet
*/
double partonJetDeltaR(ThePEG::tPPtr partonptr, LorentzMomentum jetmom);
double partonJetDeltaR(LorentzMomentum jetmom1, LorentzMomentum jetmom2);
/**
* c++ translation of subroutine of same name from alpsho.f.
* 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 calini_m();
/**
* c++ translation of subroutine of same name from alpsho.f.
* Simple calorimeter simulation - assume uniform Y and phi bins.
*/
void calsim_m();
/**
* Find jets using the FastJet package on particlesToCluster_.
*/
void getFastJets(double rjet, Energy ejcut, double etajcut);
/**
* Find jets using the FastJet package on particlesToCluster_.
*/
void getFastJetsToMatch(double rjet, Energy ejcut, double etajcut);
/**
* c++ translation of subroutine of same name from alpsho.f.
* Simple jet-finding algorithm (similar to UA1). 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. The UA1
* parameters are RJET=1.0 and EJCUT=5.0.
*/
void getjet_m(double rjet, Energy ejcut, double etajcut);
/**
* 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 caldel_m();
/**
* c++ translation of subroutine of same name from alpsho.f.
* Label all particles with status between ISTLO and ISTHI
* (until a particle with status ISTOP is found) as final-state,
* call calsim_m and then put labels back to normal. This
* version keeps only all IST=1 particles rejected by caldel as
* daughters of vetoed heavy-quark mothers: jets complementary
* to those reconstructed by caldel.
*/
void caldel_hvq();
/**
* get the information required for FxFx merging
*/
void getnpFxFx();
/**
* Get the particles from lastXCombPtr filling the pair
* preshowerISPs_ and particle pointer vector preshowerFSPs_.
*/
void getPreshowerParticles();
/**
* Get the particles from eventHandler()->currentEvent()->...
* filling the particle pairs showeredISHs_, showeredISPs_,
* showeredRems_ and the particle pointer vector showeredFSPs_.
*/
void getShoweredParticles();
/**
* Allows printing of debug output and sanity checks like
* total momentum consrvation to be carried out.
* debugLevel = -1, 0, ...5
* = no debugging, minimal debugging, ... verbose.
*/
void doSanityChecks(int debugLevel);
/**
* Given a pointer to a particle this finds all its final state
* descendents.
*/
void getDescendents(PPtr theParticle);
/**
* Accumulates all descendents of tops down to the b and W
* but not including them.
*/
void getTopRadiation(PPtr theParticle);
/**
* Sorts a given vector of particles by descending pT or ETJET
*/
ParticleVector pTsort(ParticleVector unsortedVec);
pair< vector<Energy>, vector<Lorentz5Momentum> > ETsort(vector<Energy> unsortedetjet, vector<Lorentz5Momentum> unsortedVec);
/*
* A function that prints a vector of Lorentz5Momenta in a fancy way
*/
void printMomVec(vector<Lorentz5Momentum> momVec);
/*
* A probability function for varying etclus_ about the mean value
*/
Energy etclusran_(double petc);
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<FxFxHandler> initFxFxHandler;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
FxFxHandler & operator=(const FxFxHandler &);
private:
/**
* Initial-state incoming partons prior to showering
* (i.e. from lastXCombPtr).
*/
PPair preshowerISPs_;
/**
* Final-state outgoing partICLEs prior to showering
* (i.e. from lastXCombPtr).
*/
ParticleVector preshowerFSPs_;
/**
* Final-state outgoing partICLEs prior to showering _to_be_removed_
* from preShowerFSPs_ prior to the light-parton-light-jet matching
* step. This same list is the starting point for determining
* partonsToMatch_ for the case of merging in heavy quark production.
*/
ParticleVector preshowerFSPsToDelete_;
/**
* Initial-state incoming hadrons after shower of hard process
* (eventHandler()->currentEvent()->incoming()).
*/
PPair showeredISHs_;
/**
* Initial-state incoming partons after shower of hard process
* (look for partonic children of showeredISHs_).
*/
PPair showeredISPs_;
/**
* Final-state outgoing partICLEs after shower of hard process
* (eventHandler()->currentEvent()->getFinalState()).
*/
tPVector showeredFSPs_;
/**
* Final-state outgoing partICLEs after shower of hard process
* _to_be_removed_ from showeredFSPs_ prior to the
* light-parton-light-jet matching step. This same list is the
* starting point for determining particlesToCluster_ for the
* case of merging in heavy quark production.
*/
ParticleVector showeredFSPsToDelete_;
/**
* ONLY the final-state partons from preshowerFSPs_ that are
* supposed to enter the jet-parton matching.
*/
ParticleVector partonsToMatch_;
/*
* The shower progenitors
*/
PPtr theProgenitor;
PPtr theLastProgenitor;
/**
* ONLY the final-state particles from showeredFSPs_ (and maybe
* also showeredRems_) that are supposed to go for jet clustering.
*/
tPVector particlesToCluster_;
/**
* Final-state remnants after shower of hard process
* (look for remnants initially in showeredFSPs_).
*/
PPair showeredRems_;
/**
* Pointer to the object calculating the strong coupling
*/
ShowerAlphaPtr alphaS_;
/**
* Information extracted from the XComb object
*/
//@{
/**
* The fixed factorization scale used in the MEs.
*/
Energy pdfScale_;
/**
* Centre of mass energy
*/
Energy2 sHat_;
/**
* Constant alphaS used to generate LH events - if not already
* using CKKW scale (ickkw = 1 in AlpGen for example).
*/
double alphaSME_;
//@}
/*
* Number of rapidity segments of the calorimeter.
*/
unsigned int ncy_;
/*
* Number of phi segments of the calorimeter.
*/
unsigned int ncphi_;
/*
* Heavy flavour in WQQ,ZQQ,2Q etc (4=c, 5=b, 6=t).
*/
int ihvy_;
/*
* Number of photons in the AlpGen process.
*/
int nph_;
/*
* Number of higgses in the AlpGen process.
*/
int nh_;
/*
* Jet ET cut to apply in jet clustering (in merging).
*/
Energy etclus_;
/*
* Mean Jet ET cut to apply in jet clustering (in merging).
*/
Energy etclusmean_;
/*
* maximum deviation from mean Jet ET cut to apply in jet clustering (in merging).
*/
Energy epsetclus_;
/*
* Cone size used in jet clustering (in merging).
*/
double rclus_;
/*
* Max |eta| for jets in clustering (in merging).
*/
double etaclmax_;
/*
* Default 1.5 factor used to decide if a jet matches a parton
* in merging: if DR(parton,jet)<rclusfactor*rclus the parton
* and jet are said to have been matched.
*/
double rclusfactor_;
/*
* The AlpGen hard process code. Relation to the AlpGen process names:
* 1: wqq, 2: zqq, 3: wjet, 4: zjet, 5: vbjet, 6: 2Q, 8: QQh, 9: Njet,
* 10: wcjet, 11: phjet, 12: hjet, 13: top, 14: wphjet, 15: wphqq,
* 16: 2Qph.
*/
int ihrd_;
/*
* The number of light jets in the AlpGen process (i.e. the 'extra' ones).
*/
int njets_;
/*
* Mimimum parton-parton R-sep used for generation (used for hvq merging).
*/
double drjmin_;
/*
* This flags that the highest multiplicity ME-level process is
* being processed.
*/
bool highestMultiplicity_;
/*
* This flags whether the etclus_ (merging scale) should be fixed or variable according to a prob. distribution around the mean
*/
bool etclusfixed_;
/*
* The forwards rapidity span of the calorimeter.
*/
double ycmax_;
/*
* The backwards rapidity span of the calorimeter.
*/
double ycmin_;
/*
* The jet algorithm used for parton-jet matching in the MLM procedure.
*/
int jetAlgorithm_;
/*
* Allows the vetoing to be turned off completely - just for convenience.
*/
bool vetoIsTurnedOff_;
+
+ /*
+ * Allows the vetoing on heavy quark decay products to be turned off.
+ */
+ bool vetoHeavyQ_;
+
+
/*
* Veto if there exist softer unmatched jets than matched
*/
bool vetoSoftThanMatched_;
/*
* Cosine of phi values of calorimeter cell centres.
* Goes phi~=0 to phi~=2*pi (index = 0 ---> ncphi).
* ==> Cosine goes from +1 ---> +1 (index = 0 ---> ncphi).
*/
vector<double> cphcal_;
/*
* Sine of phi values of calorimeter cell centres.
* Goes phi~=0 to phi~=2*pi (index = 0 ---> ncphi).
* ==> Sine goes 0 -> 1 -> 0 -> -1 -> 0 (index = 0 ---> ncphi).
*/
vector<double> sphcal_;
/*
* Cosine of theta values of calorimeter cell centres in Y.
* Goes bwds th~=pi to fwds th~=0 (index = 0 ---> ncy).
* ==> Cosine goes from -1 ---> +1 (index = 0 ---> ncy).
*/
vector<double> cthcal_;
/*
* Sine of theta values of calorimeter cell centres in Y.
* Goes bwds th~=pi to fwds th~=0 (index = 0 ---> ncy).
* ==> Sine goes from 0 ---> +1 ---> 0 (index = 0 ---> ncy).
*/
vector<double> sthcal_;
/*
* Transverse energy deposit in a given calorimeter cell.
* First array index corresponds to rapidity index of cell,
* second array index corresponds to phi cell index.
*/
vector<vector<Energy> > et_;
/*
* For a given calorimeter cell this holds the index of the jet
* that the cell was clustered into.
*/
vector<vector<int> > jetIdx_;
/*
* Vector holding the Lorentz 5 momenta of each jet.
*/
vector<Lorentz5Momentum> pjet_;
/*
* Vector holding the Lorentz 5 momenta of each jet from ME partons
*/
vector<Lorentz5Momentum> pjetME_;
/*
* Vector holding the list of FS particles resulting from
* the particle input to getDescendents.
*/
ParticleVector tmpList_;
/*
* Variables for the C++ translation of the calini_m(), calsim_m(),
* getjet_m(...) and caldel_m() functions
*/
vector<Energy> etjet_;
vector<Energy> etjetME_;
double dely_, delphi_;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of FxFxHandler. */
template <>
struct BaseClassTrait<Herwig::FxFxHandler,1> {
/** Typedef of the first base class of FxFxHandler. */
- typedef Herwig::ShowerHandler NthBase;
+ typedef Herwig::QTildeShowerHandler NthBase;
};
/** This template specialization informs ThePEG about the name of
* the FxFxHandler class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::FxFxHandler>
: public ClassTraitsBase<Herwig::FxFxHandler> {
/** Return a platform-independent class name */
static string className() { return "Herwig::FxFxHandler"; }
/**
* The name of a file containing the dynamic library where the class
* FxFxHandler is implemented. It may also include several, space-separated,
* libraries if the class FxFxHandler depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "FxFxHandler.so"; }
};
/** @endcond */
}
#endif /* HERWIG_FxFxHandler_H */
diff --git a/Contrib/FxFx/FxFxLHReader.cc b/Contrib/FxFx/FxFxLHReader.cc
--- a/Contrib/FxFx/FxFxLHReader.cc
+++ b/Contrib/FxFx/FxFxLHReader.cc
@@ -1,466 +1,466 @@
// -*- C++ -*-
//
// FxFxLHReader.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 FxFxLHReader class.
//
#include "FxFxLHReader.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDF/PartonExtractor.h"
#include "ThePEG/PDF/NoPDF.h"
#include "ThePEG/Cuts/Cuts.h"
#include "ThePEG/EventRecord/TmpTransform.h"
#include "ThePEG/Utilities/UtilityBase.h"
using namespace Herwig;
FxFxLHReader::
FxFxLHReader(const FxFxLHReader & x)
: LesHouchesReader(x), neve(x.neve), ieve(0),
LHFVersion(x.LHFVersion), outsideBlock(x.outsideBlock),
headerBlock(x.headerBlock), initComments(x.initComments),
initAttributes(x.initAttributes), eventComments(x.eventComments),
eventAttributes(x.eventAttributes),
theFileName(x.theFileName),overSampling_(x.overSampling_) {}
FxFxLHReader::~FxFxLHReader() {}
IBPtr FxFxLHReader::clone() const {
return new_ptr(*this);
}
IBPtr FxFxLHReader::fullclone() const {
return new_ptr(*this);
}
bool FxFxLHReader::preInitialize() const {
return true;
}
void FxFxLHReader::doinit() {
LesHouchesReader::doinit();
}
void FxFxLHReader::initialize(LesHouchesEventHandler & eh) {
LesHouchesReader::initialize(eh);
if ( LHFVersion.empty() )
Throw<LesHouchesFileError>()
<< "The file associated with '" << name() << "' does not contain a "
<< "proper formatted Les Houches event file. The events may not be "
<< "properly sampled." << Exception::warning;
}
long FxFxLHReader::scan() {
open();
// Shall we write the events to a cache file for fast reading? If so
// we write to a temporary file if the caches events should be
// randomized.
if ( cacheFileName().length() ) openWriteCacheFile();
// Keep track of the number of events scanned.
long neve = 0;
long cuteve = 0;
bool negw = false;
// If the open() has not already gotten information about subprocesses
// and cross sections we have to scan through the events.
if ( !heprup.NPRUP || cacheFile() || abs(heprup.IDWTUP) != 1 ) { // why scan if IDWTUP != 1?
HoldFlag<> isScanning(scanning);
double oldsum = 0.0;
vector<int> lprup;
vector<double> newmax;
vector<long> oldeve;
vector<long> neweve;
for ( int i = 0; ( maxScan() < 0 || i < maxScan() ) && readEvent(); ++i ) {
if ( !checkPartonBin() ) Throw<LesHouchesInitError>()
<< "Found event in LesHouchesReader '" << name()
<< "' which cannot be handeled by the assigned PartonExtractor '"
<< partonExtractor()->name() << "'." << Exception::runerror;
vector<int>::iterator idit =
find(lprup.begin(), lprup.end(), hepeup.IDPRUP);
int id = lprup.size();
if ( idit == lprup.end() ) {
lprup.push_back(hepeup.IDPRUP);
newmax.push_back(0.0);
neweve.push_back(0);
oldeve.push_back(0);
} else {
id = idit - lprup.begin();
}
++neve;
++oldeve[id];
oldsum += hepeup.XWGTUP;
if ( cacheFile() ) {
if ( eventWeight() == 0.0 ) {
++cuteve;
continue;
}
cacheEvent();
}
++neweve[id];
newmax[id] = max(newmax[id], abs(eventWeight()));
if ( eventWeight() < 0.0 ) negw = true;
}
xSecWeights.resize(oldeve.size(), 1.0);
for ( int i = 0, N = oldeve.size(); i < N; ++i )
if ( oldeve[i] ) xSecWeights[i] = double(neweve[i])/double(oldeve[i]);
if ( maxScan() < 0 || neve > NEvents() ) NEvents(neve - cuteve);
if ( lprup.size() == heprup.LPRUP.size() ) {
for ( int id = 0, N = lprup.size(); id < N; ++id ) {
vector<int>::iterator idit =
find(heprup.LPRUP.begin(), heprup.LPRUP.end(), hepeup.IDPRUP);
if ( idit == heprup.LPRUP.end() ) {
Throw<LesHouchesInitError>()
<< "When scanning events, the LesHouschesReader '" << name()
<< "' found undeclared processes." << Exception::warning;
heprup.NPRUP = 0;
break;
}
int idh = idit - heprup.LPRUP.begin();
heprup.XMAXUP[idh] = newmax[id];
}
}
if ( heprup.NPRUP == 0 ) {
// No heprup block was supplied or something went wrong.
heprup.NPRUP = lprup.size();
heprup.LPRUP.resize(lprup.size());
heprup.XMAXUP.resize(lprup.size());
for ( int id = 0, N = lprup.size(); id < N; ++id ) {
heprup.LPRUP[id] = lprup[id];
heprup.XMAXUP[id] = newmax[id];
}
} else if ( abs(heprup.IDWTUP) != 1 ) {
// Try to fix things if abs(heprup.IDWTUP) != 1.
double sumxsec = 0.0;
for ( int id = 0; id < heprup.NPRUP; ++id ) sumxsec += heprup.XSECUP[id];
weightScale = picobarn*neve*sumxsec/oldsum;
}
}
if ( cacheFile() ) closeCacheFile();
if ( negw ) heprup.IDWTUP = min(-abs(heprup.IDWTUP), -1);
return neve;
}
void FxFxLHReader::open() {
if ( filename().empty() )
throw LesHouchesFileError()
<< "No Les Houches file name. "
<< "Use 'set " << name() << ":FileName'."
<< Exception::runerror;
cfile.open(filename());
if ( !cfile )
throw LesHouchesFileError()
<< "The FxFxLHReader '" << name() << "' could not open the "
<< "event file called '" << theFileName << "'."
<< Exception::runerror;
cfile.readline();
if ( !cfile.find("<LesHouchesEvents") ) return;
map<string,string> attributes =
StringUtils::xmlAttributes("LesHouchesEvents", cfile.getline());
LHFVersion = attributes["version"];
if ( LHFVersion.empty() ) return;
bool readingHeader = false;
bool readingInit = false;
headerBlock = "";
// Loop over all lines until we hit the </init> tag.
while ( cfile.readline() && !cfile.find("</init>") ) {
if ( cfile.find("<header") ) {
// We have hit the header block, so we should dump this and all
// following lines to headerBlock until we hit the end of it.
readingHeader = true;
headerBlock = cfile.getline() + "\n";
}
else if ( cfile.find("<init") ) {
// We have hit the init block, so we should expect to find the
// standard information in the following. But first check for
// attributes.
initAttributes = StringUtils::xmlAttributes("init", cfile.getline());
readingInit = true;
cfile.readline();
if ( !( cfile >> heprup.IDBMUP.first >> heprup.IDBMUP.second
>> heprup.EBMUP.first >> heprup.EBMUP.second
>> heprup.PDFGUP.first >> heprup.PDFGUP.second
>> heprup.PDFSUP.first >> heprup.PDFSUP.second
>> heprup.IDWTUP >> heprup.NPRUP ) ) {
heprup.NPRUP = -42;
LHFVersion = "";
return;
}
heprup.resize();
for ( int i = 0; i < heprup.NPRUP; ++i ) {
cfile.readline();
if ( !( cfile >> heprup.XSECUP[i] >> heprup.XERRUP[i]
>> heprup.XMAXUP[i] >> heprup.LPRUP[i] ) ) {
heprup.NPRUP = -42;
LHFVersion = "";
return;
}
}
}
else if ( cfile.find("</header") ) {
readingHeader = false;
headerBlock += cfile.getline() + "\n";
}
else if ( readingHeader ) {
// We are in the process of reading the header block. Dump the
// line to headerBlock.
headerBlock += cfile.getline() + "\n";
}
else if ( readingInit ) {
// Here we found a comment line. Dump it to initComments.
initComments += cfile.getline() + "\n";
}
else {
// We found some other stuff outside the standard tags.
outsideBlock += cfile.getline() + "\n";
}
}
if ( !cfile ) {
heprup.NPRUP = -42;
LHFVersion = "";
return;
}
}
bool FxFxLHReader::readEvent() {
reset();
if ( !doReadEvent() ) return false;
// If we are just skipping event we do not need to reweight or do
// anything fancy.
if ( skipping ) return true;
if ( cacheFile() && !scanning ) return true;
// Reweight according to the re- and pre-weights objects in the
// LesHouchesReader base class.
lastweight = reweight();
if ( !reweightPDF && !cutEarly() ) return true;
// We should try to reweight the PDFs or make early cuts here.
fillEvent();
double x1 = incoming().first->momentum().plus()/
beams().first->momentum().plus();
if ( reweightPDF &&
inPDF.first && outPDF.first && inPDF.first != outPDF.first ) {
if ( hepeup.XPDWUP.first <= 0.0 )
hepeup.XPDWUP.first =
inPDF.first->xfx(inData.first, incoming().first->dataPtr(),
sqr(hepeup.SCALUP*GeV), x1);
double xf = outPDF.first->xfx(inData.first, incoming().first->dataPtr(),
sqr(hepeup.SCALUP*GeV), x1);
lastweight *= xf/hepeup.XPDWUP.first;
hepeup.XPDWUP.first = xf;
}
double x2 = incoming().second->momentum().minus()/
beams().second->momentum().minus();
if ( reweightPDF &&
inPDF.second && outPDF.second && inPDF.second != outPDF.second ) {
if ( hepeup.XPDWUP.second <= 0.0 )
hepeup.XPDWUP.second =
inPDF.second->xfx(inData.second, incoming().second->dataPtr(),
sqr(hepeup.SCALUP*GeV), x2);
double xf =
outPDF.second->xfx(inData.second, incoming().second->dataPtr(),
sqr(hepeup.SCALUP*GeV), x2);
lastweight *= xf/hepeup.XPDWUP.second;
hepeup.XPDWUP.second = xf;
}
if ( cutEarly() ) {
if ( !cuts().initSubProcess((incoming().first->momentum() +
incoming().second->momentum()).m2(),
0.5*log(x1/x2)) ) lastweight = 0.0;
tSubProPtr sub = getSubProcess();
TmpTransform<tSubProPtr> tmp(sub, Utilities::getBoostToCM(sub->incoming()));
if ( !cuts().passCuts(*sub) ) lastweight = 0.0;
}
return true;
}
double FxFxLHReader::getEvent() {
if ( cacheFile() ) {
if (overSampling_) {
if ( !uncacheEvent() ) reopen();
} else {
if ( !uncacheEvent() || stats.attempts()==NEvents() )
throw LesHouchesReopenWarning()
<< "More events requested than available in LesHouchesReader "
<< name() << Exception::runerror;
}
} else {
if (overSampling_) {
if ( !readEvent() ) reopen();
} else {
if ( !readEvent() || stats.attempts()==NEvents() )
throw LesHouchesReopenWarning()
<< "More events requested than available in LesHouchesReader "
<< name() << Exception::runerror;
}
}
++position;
double max = maxWeights[hepeup.IDPRUP]*maxFactor;
return max != 0.0? eventWeight()/max: 0.0;
}
void FxFxLHReader::skip(long n) {
HoldFlag<> skipflag(skipping);
if(overSampling_) while ( n-- ) getEvent();
}
bool FxFxLHReader::doReadEvent() {
if ( !cfile ) return false;
if ( LHFVersion.empty() ) return false;
if ( heprup.NPRUP < 0 ) return false;
eventComments = "";
outsideBlock = "";
hepeup.NUP = 0;
hepeup.XPDWUP.first = hepeup.XPDWUP.second = 0.0;
// Keep reading lines until we hit the next event or the end of
// the event block. Save any inbetween lines. Exit if we didn't
// find an event.
while ( cfile.readline() && !cfile.find("<event") )
outsideBlock += cfile.getline() + "\n";
// We found an event. First scan for attributes.
eventAttributes = StringUtils::xmlAttributes("event", cfile.getline());
if ( !cfile.readline() ) return false;
// The first line determines how many subsequent particle lines we
// have.
if ( !( cfile >> hepeup.NUP >> hepeup.IDPRUP >> hepeup.XWGTUP
>> hepeup.SCALUP >> hepeup.AQEDUP >> hepeup.AQCDUP ) )
return false;
hepeup.resize();
// Read all particle lines.
for ( int i = 0; i < hepeup.NUP; ++i ) {
if ( !cfile.readline() ) return false;
if ( !( cfile >> hepeup.IDUP[i] >> hepeup.ISTUP[i]
>> hepeup.MOTHUP[i].first >> hepeup.MOTHUP[i].second
>> hepeup.ICOLUP[i].first >> hepeup.ICOLUP[i].second
>> hepeup.PUP[i][0] >> hepeup.PUP[i][1] >> hepeup.PUP[i][2]
>> hepeup.PUP[i][3] >> hepeup.PUP[i][4]
>> hepeup.VTIMUP[i] >> hepeup.SPINUP[i] ) )
return false;
- if(isnan(hepeup.PUP[i][0])||isnan(hepeup.PUP[i][1])||
- isnan(hepeup.PUP[i][2])||isnan(hepeup.PUP[i][3])||
- isnan(hepeup.PUP[i][4]))
+ if(std::isnan(hepeup.PUP[i][0])||std::isnan(hepeup.PUP[i][1])||
+ std::isnan(hepeup.PUP[i][2])||std::isnan(hepeup.PUP[i][3])||
+ std::isnan(hepeup.PUP[i][4]))
throw Exception()
<< "nan's as momenta in Les Houches file "
<< Exception::eventerror;
}
// Now read any additional comments.
while ( cfile.readline() && !cfile.find("</event>") )
eventComments += cfile.getline() + "\n";
if ( !cfile ) return false;
return true;
}
void FxFxLHReader::close() {
cfile.close();
}
void FxFxLHReader::persistentOutput(PersistentOStream & os) const {
os << neve << LHFVersion << outsideBlock << headerBlock << initComments
<< initAttributes << eventComments << eventAttributes << theFileName
<< overSampling_;
}
void FxFxLHReader::persistentInput(PersistentIStream & is, int) {
is >> neve >> LHFVersion >> outsideBlock >> headerBlock >> initComments
>> initAttributes >> eventComments >> eventAttributes >> theFileName
>> overSampling_;
ieve = 0;
}
ClassDescription<FxFxLHReader>
FxFxLHReader::initFxFxLHReader;
// Definition of the static class description member.
void FxFxLHReader::Init() {
static ClassDocumentation<FxFxLHReader> documentation
("Herwig::FxFxLHReader is an base class to be used for objects "
"which reads event files from matrix element generators. This class is "
"able to read plain event files conforming to the Les Houches Event File "
"accord.");
static Parameter<FxFxLHReader,string> interfaceFileName
("FileName",
"The name of a file containing events conforming to the Les Houches "
"protocol to be read into ThePEG. A file name ending in "
"<code>.gz</code> will be read from a pipe which uses "
"<code>zcat</code>. If a file name ends in <code>|</code> the "
"preceeding string is interpreted as a command, the output of which "
"will be read through a pipe.",
&FxFxLHReader::theFileName, "", false, false);
static Switch<FxFxLHReader,bool> interfaceOverSampling
("OverSampling",
"Allow / Forbid reading of LH events more than once by the "
"LH reader, allowing / protecting against statistical problems.",
&FxFxLHReader::overSampling_, true, false, false);
static SwitchOption AllowOverSampling
(interfaceOverSampling,
"AllowOverSampling",
"The reader will read events in the file more than once if more "
"events are needed to generate the requested number than that in "
"the LH file.",
true);
static SwitchOption ForbidOverSampling
(interfaceOverSampling,
"ForbidOverSampling",
"The reader will NOT read events in the file more than once if more "
"events are needed to generate the requested number than that in "
"the LH file - instead it will stop when all have been read.",
false);
interfaceFileName.fileType();
interfaceFileName.rank(11);
}
diff --git a/Contrib/FxFx/Makefile.in b/Contrib/FxFx/Makefile.in
--- a/Contrib/FxFx/Makefile.in
+++ b/Contrib/FxFx/Makefile.in
@@ -1,51 +1,51 @@
# -*- Makefile -*- (for emacs)
#
# This Makefile is intended for compiling Herwig++ plugins
#
# This Makefile received very little testing,
# any bug reports are very welcome!
#
# Location of include files
THEPEGINCLUDE =
HERWIGINCLUDE =
GSLINCLUDE =
FASTJETINCLUDE =
RIVETINCLUDE = -I$(shell rivet-config --includedir --cppflags)
HEPMCINCLUDE =
# Messy hack, not guaranteed to work:
FASTJETLIB = `echo $(FASTJETINCLUDE) | sed "s/-I//" | sed "s/ //"`/../lib/
LDFLAGS = -L$(FASTJETLIB) -lfastjet $(shell rivet-config --ldflags --libs)
SHARED_FLAG =
INCLUDE = $(THEPEGINCLUDE) $(HERWIGINCLUDE) $(GSLINCLUDE) $(FASTJETINCLUDE) $(RIVETINCLUDE) $(HEPMCINCLUDE)
# C++ flags
CXX =
CXXFLAGS =
ALLCCFILES=$(shell echo *.cc)
default : FxFx.so FxFxHandler.so FxFxAnalysis.so
%.o : %.cc %.h
$(CXX) -fPIC $(CPPFLAGS) $(INCLUDE) $(CXXFLAGS) -c -shared $< -o $@
FxFx.so : FxFxFileReader.o FxFxEventHandler.o FxFxReader.o
$(CXX) -fPIC $(CPPFLAGS) $(INCLUDE) $(CXXFLAGS) $(SHARED_FLAG) $(LDFLAGS) \
-Wl,-undefined -Wl,dynamic_lookup \
FxFxFileReader.o FxFxEventHandler.o FxFxReader.o -o FxFx.so
FxFxHandler.so : FxFxHandler.o
$(CXX) -fPIC $(CPPFLAGS) $(INCLUDE) $(CXXFLAGS) $(SHARED_FLAG) $(LDFLAGS) \
-Wl,-undefined -Wl,dynamic_lookup \
FxFxHandler.o -o FxFxHandler.so
FxFxAnalysis.so : FxFxAnalysis.o
$(CXX) -fPIC $(CPPFLAGS) $(INCLUDE) $(CXXFLAGS) $(SHARED_FLAG) $(LDFLAGS) \
-Wl,-undefined -Wl,dynamic_lookup \
FxFxAnalysis.o -o FxFxAnalysis.so
clean:
rm -f $(ALLCCFILES:.cc=.o) \
FxFx.so FxFxHandler.so FxFxAnalysis.so
install:
- cp *.so $(HERWIGINSTALL)/lib/Herwig
\ No newline at end of file
+ cp *.so $(HERWIGINSTALL)/lib/Herwig
\ No newline at end of file
diff --git a/Contrib/FxFx/NLORivetAnalysis.cc b/Contrib/FxFx/NLORivetAnalysis.cc
--- a/Contrib/FxFx/NLORivetAnalysis.cc
+++ b/Contrib/FxFx/NLORivetAnalysis.cc
@@ -1,451 +1,451 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the NLORivetAnalysis class.
//
#include "NLORivetAnalysis.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Vectors/HepMCConverter.h"
#include "ThePEG/Config/HepMCHelper.h"
#include "ThePEG/EventRecord/Event.h"
#include "ThePEG/EventRecord/SubProcess.h"
#include "ThePEG/EventRecord/SubProcessGroup.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "HepMC/GenEvent.h"
#include "Rivet/AnalysisHandler.hh"
#include "Rivet/Tools/Logging.hh"
#include "HepMC/IO_AsciiParticles.h"
#include "HepMC/IO_GenEvent.h"
#include <config.h>
using namespace ThePEG;
NLORivetAnalysis::NLORivetAnalysis()
: _remnantId(82), _format(1),_unitchoice(),
_geneventPrecision(16), debug(false), _rivet(), _nevent(0) {}
HepMC::GenEvent * NLORivetAnalysis::makeEvent(tEventPtr event, tSubProPtr sub, long no,
Energy eUnit, Length lUnit,
CrossSection xsec, CrossSection xsecErr) const {
// generate beam particles
const PPair& beam = event->incoming();
HepMC::GenParticle * b1 =
HepMCTraits<HepMC::GenEvent>::newParticle(beam.first->momentum(),beam.first->id(),
1,eUnit);
HepMC::GenParticle * b2 =
HepMCTraits<HepMC::GenEvent>::newParticle(beam.second->momentum(),beam.second->id(),
1,eUnit);
// generate remnants
HepMC::GenParticle * r1 =
HepMCTraits<HepMC::GenEvent>::newParticle(beam.first->momentum() -
sub->incoming().first->momentum(),
_remnantId,1,eUnit);
HepMC::GenParticle * r2 =
HepMCTraits<HepMC::GenEvent>::newParticle(beam.second->momentum() -
sub->incoming().second->momentum(),
_remnantId,1,eUnit);
// generate outgoing particles
vector<HepMC::GenParticle*> outgoing;
for ( ParticleVector::const_iterator p = sub->outgoing().begin();
p != sub->outgoing().end(); ++p ) {
outgoing.push_back(HepMCTraits<HepMC::GenEvent>::newParticle((**p).momentum(),(**p).id(),
1,eUnit));
}
// generate one blob vertex
HepMC::GenVertex * vertex = HepMCTraits<HepMC::GenEvent>::newVertex();
HepMCTraits<HepMC::GenEvent>::addIncoming(*vertex,b1);
HepMCTraits<HepMC::GenEvent>::addIncoming(*vertex,b2);
HepMCTraits<HepMC::GenEvent>::addOutgoing(*vertex,r1);
HepMCTraits<HepMC::GenEvent>::addOutgoing(*vertex,r2);
for ( vector<HepMC::GenParticle*>::const_iterator p = outgoing.begin();
p != outgoing.end(); ++p )
HepMCTraits<HepMC::GenEvent>::addOutgoing(*vertex,*p);
HepMC::GenEvent * ev =
HepMCTraits<HepMC::GenEvent>::newEvent(no,event->weight()*sub->groupWeight(),
event->optionalWeights());
// cout << "event->weight()*sub->groupWeight()" << event->weight()*sub->groupWeight() << endl;
/*print optional weights here
for (map<string,double>::const_iterator it= event->optionalWeights().begin(); it!=event->optionalWeights().end(); ++it){
std::cout << it->first << " => " << it->second << '\n';
}
cout << endl;*/
HepMCTraits<HepMC::GenEvent>::setUnits(*ev,eUnit,lUnit);
HepMCTraits<HepMC::GenEvent>::setBeamParticles(*ev,b1,b2);
HepMCTraits<HepMC::GenEvent>::addVertex(*ev,vertex);
HepMCTraits<HepMC::GenEvent>::setCrossSection(*ev,xsec/picobarn,
xsecErr/picobarn);
return ev;
}
HepMC::GenEvent * NLORivetAnalysis::makeEventW(tEventPtr event, tSubProPtr sub, long no,
Energy eUnit, Length lUnit,
CrossSection xsec, CrossSection xsecErr, double weighttest) const {
// generate beam particles
const PPair& beam = event->incoming();
HepMC::GenParticle * b1 =
HepMCTraits<HepMC::GenEvent>::newParticle(beam.first->momentum(),beam.first->id(),
1,eUnit);
HepMC::GenParticle * b2 =
HepMCTraits<HepMC::GenEvent>::newParticle(beam.second->momentum(),beam.second->id(),
1,eUnit);
// generate remnants
HepMC::GenParticle * r1 =
HepMCTraits<HepMC::GenEvent>::newParticle(beam.first->momentum() -
sub->incoming().first->momentum(),
_remnantId,1,eUnit);
HepMC::GenParticle * r2 =
HepMCTraits<HepMC::GenEvent>::newParticle(beam.second->momentum() -
sub->incoming().second->momentum(),
_remnantId,1,eUnit);
// generate outgoing particles
vector<HepMC::GenParticle*> outgoing;
for ( ParticleVector::const_iterator p = sub->outgoing().begin();
p != sub->outgoing().end(); ++p ) {
outgoing.push_back(HepMCTraits<HepMC::GenEvent>::newParticle((**p).momentum(),(**p).id(),
1,eUnit));
}
// generate one blob vertex
HepMC::GenVertex * vertex = HepMCTraits<HepMC::GenEvent>::newVertex();
HepMCTraits<HepMC::GenEvent>::addIncoming(*vertex,b1);
HepMCTraits<HepMC::GenEvent>::addIncoming(*vertex,b2);
HepMCTraits<HepMC::GenEvent>::addOutgoing(*vertex,r1);
HepMCTraits<HepMC::GenEvent>::addOutgoing(*vertex,r2);
for ( vector<HepMC::GenParticle*>::const_iterator p = outgoing.begin();
p != outgoing.end(); ++p )
HepMCTraits<HepMC::GenEvent>::addOutgoing(*vertex,*p);
HepMC::GenEvent * ev =
HepMCTraits<HepMC::GenEvent>::newEvent(no,event->weight()*sub->groupWeight()*weighttest,
event->optionalWeights());
// cout << "event->weight()*sub->groupWeight()" << event->weight()*sub->groupWeight() << endl;
/*print optional weights here
for (map<string,double>::const_iterator it= event->optionalWeights().begin(); it!=event->optionalWeights().end(); ++it){
std::cout << it->first << " => " << it->second << '\n';
}
cout << endl;*/
HepMCTraits<HepMC::GenEvent>::setUnits(*ev,eUnit,lUnit);
HepMCTraits<HepMC::GenEvent>::setBeamParticles(*ev,b1,b2);
HepMCTraits<HepMC::GenEvent>::addVertex(*ev,vertex);
HepMCTraits<HepMC::GenEvent>::setCrossSection(*ev,xsec/picobarn,
xsecErr/picobarn);
return ev;
}
void NLORivetAnalysis::analyze(ThePEG::tEventPtr event, long ieve, int loop, int state) {
Energy eUnit;
Length lUnit;
switch (_unitchoice) {
default: eUnit = GeV; lUnit = millimeter; break;
case 1: eUnit = MeV; lUnit = millimeter; break;
case 2: eUnit = GeV; lUnit = centimeter; break;
case 3: eUnit = MeV; lUnit = centimeter; break;
}
tcEHPtr eh = dynamic_ptr_cast<tcEHPtr>(event->primaryCollision()->handler());
assert(eh);
CrossSection xsec = eh->integratedXSec();
CrossSection xsecErr = eh->integratedXSecErr();
tSubProPtr sub = event->primarySubProcess();
Ptr<SubProcessGroup>::tptr grp =
dynamic_ptr_cast<Ptr<SubProcessGroup>::tptr>(sub);
AnalysisHandler::analyze(event, ieve, loop, state);
// Rotate to CMS, extract final state particles and call analyze(particles).
// convert to hepmc
HepMC::GenEvent * hepmc =
makeEvent(event,sub,_nevent,eUnit,lUnit,xsec,xsecErr);
//count weights here
std::vector<std::string> strs;
if(_numweights == -999) {
_numweights = 0;
for (map<string,double>::const_iterator it= event->optionalWeights().begin(); it!=event->optionalWeights().end(); ++it){
//std::cout << it->first << " => " << it->second << '\n';
string first_piece = it->first;
string word;
istringstream iss(first_piece, istringstream::in);
while( iss >> word ) strs.push_back(word);
if(strs[0] == "PDF" || strs[0] == "SC") { _numweights++; }
}
strs.clear();
}
//find the weights
_i = 0;//counter
for (map<string,double>::const_iterator it= event->optionalWeights().begin(); it!=event->optionalWeights().end(); ++it){
// std::cout << it->first << " => " << it->second << '\n';
string first_piece = it->first;
string word;
istringstream iss(first_piece, istringstream::in);
while( iss >> word ) {
strs.push_back(word);
}
std::pair<int,double> OptWeightsTemp;
if(strs[0] == "PDF") {
OptWeightsTemp.first = atoi(strs[2].c_str());
OptWeightsTemp.second= it->second;
OptWeights.push_back(OptWeightsTemp);
OptXS[_i] += it->second;
_i++;
}
if(strs[0] == "SC") {
OptWeightsTemp.first = atoi(strs[3].c_str());
OptWeightsTemp.second = it->second;
OptWeights.push_back(OptWeightsTemp);
OptXS[_i] += it->second;
_i++;
}
strs.clear();
}
/* multiple hepmcs for scale/pdf variations
*/
vector<HepMC::GenEvent*> hepmcMULTI;// = new HepMC::GenEvent[_numweights];
HepMC::GenEvent * hepmcMULTIi;
for(int rr = 0; rr < _numweights; rr++) {
hepmcMULTIi = makeEventW(event,sub,_nevent,eUnit,lUnit,xsec,xsecErr,OptWeights[rr].second);
hepmcMULTI.push_back(hepmcMULTIi);
}
CurrentGenerator::Redirect stdout(cout);
if ( _rivet ) _rivet->analyze(*hepmc);
for(int rr = 0; rr < _numweights; rr++) {
if ( _rivetMULTI[rr] ) _rivetMULTI[rr]->analyze(*hepmcMULTI[rr]);
}
// delete hepmc events
delete hepmc;
for(int rr = 0; rr < _numweights; rr++) {
delete hepmcMULTI[rr];
}
if ( grp ) {
std::cout << "grp is true" << endl;
std::cout << endl;
for ( SubProcessVector::const_iterator s = grp->dependent().begin();
s != grp->dependent().end(); ++s ) {
hepmc = makeEvent(event,*s,_nevent,eUnit,lUnit,xsec,xsecErr);
if ( _rivet ) _rivet->analyze(*hepmc);
// delete hepmc event
delete hepmc;
}
}
++_nevent;
}
ThePEG::IBPtr NLORivetAnalysis::clone() const {
return new_ptr(*this);
}
ThePEG::IBPtr NLORivetAnalysis::fullclone() const {
return new_ptr(*this);
}
void NLORivetAnalysis::persistentOutput(ThePEG::PersistentOStream & os) const {
os << _analyses << filename << debug;
}
void NLORivetAnalysis::persistentInput(ThePEG::PersistentIStream & is, int) {
is >> _analyses >> filename >> debug;
}
ThePEG::ClassDescription<NLORivetAnalysis> NLORivetAnalysis::initNLORivetAnalysis;
// Definition of the static class description member.
void NLORivetAnalysis::Init() {
static ThePEG::ClassDocumentation<NLORivetAnalysis> documentation
("The NLORivetAnalysis class is a simple class to allow analyses"
" from the Rivet library to be called from ThePEG");
static ThePEG::ParVector<NLORivetAnalysis,string> interfaceAnalyses
("Analyses",
"The names of the Rivet analyses to use",
&NLORivetAnalysis::_analyses, -1, "", "","" "",
false, false, ThePEG::Interface::nolimits);
static Parameter<NLORivetAnalysis,long> interfaceRemnantId
("RemnantId",
"Set the PDG id to be used for remnants.",
&NLORivetAnalysis::_remnantId, 82, 0, 0,
false, false, Interface::nolimits);
static Parameter<NLORivetAnalysis,string> interfaceFilename
("Filename",
#if ThePEG_RIVET_VERSION == 1
"The name of the file where the AIDA histograms are put. If empty, "
"the run name will be used instead. '.aida' will in any case be "
"appended to the file name.",
#elif ThePEG_RIVET_VERSION > 1
"The name of the file where the YODA histograms are put. If empty, "
"the run name will be used instead. '.yoda' will in any case be "
"appended to the file name.",
#else
#error "Unknown ThePEG_RIVET_VERSION"
#endif
&NLORivetAnalysis::filename, "", true, false);
static Switch<NLORivetAnalysis,bool> interfaceDebug
("Debug",
"Enable debug information from Rivet",
&NLORivetAnalysis::debug, false, true, false);
static SwitchOption interfaceDebugNo
(interfaceDebug,
"No",
"Disable debug information.",
false);
static SwitchOption interfaceDebugYes
(interfaceDebug,
"Yes",
"Enable debug information from Rivet.",
true);
interfaceAnalyses.rank(10);
}
void NLORivetAnalysis::dofinish() {
AnalysisHandler::dofinish();
if( _nevent > 0 && _rivet ) {
CurrentGenerator::Redirect stdout(cout);
_rivet->setCrossSection(generator()->integratedXSec()/picobarn);
_rivet->finalize();
string fname = filename;
#if ThePEG_RIVET_VERSION == 1
if ( fname.empty() ) fname = generator()->runName() + ".aida";
#elif ThePEG_RIVET_VERSION > 1
if ( fname.empty() ) fname = generator()->runName() + ".yoda";
#else
#error "Unknown ThePEG_RIVET_VERSION"
#endif
_rivet->writeData(fname);
}
delete _rivet;
_rivet = 0;
cout << "finalizing with numweights = " << _numweights << endl;
for(int rr = 0; rr < _numweights; rr++) {
OptXS[rr] = OptXS[rr]/_nevent;
}
for(int rr = 0; rr < _numweights; rr++) {
cout << "cross section = " << OptXS[rr] << endl;
if( _nevent > 0 && _rivetMULTI[rr] ) {
_rivetMULTI[rr]->setCrossSection(OptXS[rr]);
_rivetMULTI[rr]->finalize();
string fname = filename;
#if ThePEG_RIVET_VERSION == 1
- if ( fname.empty() ) fname = generator()->runName() + "_" + boost::lexical_cast<string>(OptWeights[rr].first) + ".aida";
+ if ( fname.empty() ) fname = generator()->runName() + "_" + std::to_string(OptWeights[rr].first) + ".aida";
#elif ThePEG_RIVET_VERSION > 1
- if ( fname.empty() ) fname = generator()->runName() + "_" + boost::lexical_cast<string>(OptWeights[rr].first) + ".yoda";
+ if ( fname.empty() ) fname = generator()->runName() + "_" + std::to_string(OptWeights[rr].first) + ".yoda";
#else
#error "Unknown ThePEG_RIVET_VERSION"
#endif
_rivetMULTI[rr]->writeData(fname);
}
delete _rivetMULTI[rr];
_rivetMULTI[rr] = 0;
}
}
void NLORivetAnalysis::doinit() {
_numweights = -999;
for(int rr = 0; rr < 120; rr++) {
OptXS.push_back(0.);
}
AnalysisHandler::doinit();
if(_analyses.empty())
throw ThePEG::Exception() << "Must have at least one analysis loaded in "
<< "NLORivetAnalysis::doinitrun()"
<< ThePEG::Exception::runerror;
// check that analysis list is available
_rivet = new Rivet::AnalysisHandler; //(fname);
_rivet->addAnalyses(_analyses);
if ( _rivet->analysisNames().size() != _analyses.size() ) {
throw ThePEG::Exception()
<< "Rivet could not find all requested analyses.\n"
<< "Use 'rivet --list-analyses' to check availability.\n"
<< ThePEG::Exception::runerror;
}
delete _rivet;
_rivet = 0;
}
void NLORivetAnalysis::doinitrun() {
_numweights = -999;
AnalysisHandler::doinitrun();
// create NLORivet analysis handler
CurrentGenerator::Redirect stdout(cout);
_rivet = new Rivet::AnalysisHandler; //(fname);
_rivet->addAnalyses(_analyses);
for(int rr = 0; rr < 120; rr++) {
OptXS.push_back(0.);
_rivetMULTI[rr] = new Rivet::AnalysisHandler; //(fname);
_rivetMULTI[rr]->addAnalyses(_analyses);
}
// check that analysis list is still available
if ( _rivet->analysisNames().size() != _analyses.size() ) {
throw ThePEG::Exception()
<< "Rivet could not find all requested analyses.\n"
<< "Use 'rivet --list-analyses' to check availability.\n"
<< ThePEG::Exception::runerror;
}
if ( debug )
Rivet::Log::setLevel("Rivet",Rivet::Log::DEBUG);
}
diff --git a/Contrib/HiggsPair/MEHiggsPair.cc b/Contrib/HiggsPair/MEHiggsPair.cc
--- a/Contrib/HiggsPair/MEHiggsPair.cc
+++ b/Contrib/HiggsPair/MEHiggsPair.cc
@@ -1,718 +1,747 @@
// -*- C++ -*-
//
// MEHiggsPair.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2009-2011 The Herwig Collaboration
//
// Herwig is licenaaaced 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 MEHiggsPair class.
//
#include "MEHiggsPair.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "Herwig/Models/StandardModel/StandardModel.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/Cuts/Cuts.h"
#include "Herwig/Utilities/Maths.h"
#include <fstream>
#include <cmath>
namespace Herwig {
}
using namespace Herwig;
MEHiggsPair::MEHiggsPair()
- : _selfcoupling(1.0),_hhHcoupling(1.0), _process(0), _mh(), _wh(), _cH(0.0), _c6(0.0), _ct1(0.0), _cb1(0.0), _ct2(0.0), _cb2(0.0), _cg1(0.0), _cg2(0.0), _EFTScale(1000*GeV), _fixedalphaS(0), _alphasfixedvalue(0.1), _alphascale(90.0*GeV), _basescale(125.0*GeV), _fixedscale(0), _scalemultiplier(1.0) {
+ : _selfcoupling(1.0),_hhHcoupling(1.0), _process(0), _mh(), _wh(), _cH(0.0), _c6(0.0), _ct1(0.0), _cb1(0.0), _ct2(0.0), _cb2(0.0), _cg1(0.0), _cg2(0.0), _EFTScale(1000*GeV), _fixedalphaS(0), _alphasfixedvalue(0.1), _alphascale(90.0*GeV), _basescale(125.0*GeV), _fixedscale(0), _scalemultiplier(1.0), _yH(1.0), _yh(1.0), _ybH(1.0), _ybh(1.0) {
massOption(vector<unsigned int>(2,0));
}
int MEHiggsPair::nDim() const {
return 5;
}
void MEHiggsPair::doinit() {
if(_process == 5 || _process == 6) { cerr << "HH and hH production not implemented yet, please choose an hh production subprocess" << endl; exit(1); }
if(_process == 4) { cerr << "WARNING: In the EFT, the option SelfCoupling is not used." << endl; }
higgs(getParticleData(ParticleID::h0));
PDPtr wboson = getParticleData(ParticleID::Wplus);
_Wmass = wboson->mass();
PDPtr top = getParticleData(ParticleID::t);
_topmass = top->mass();
PDPtr zboson = getParticleData(ParticleID::Z0);
_zmass = zboson->mass();
PDPtr bottom = getParticleData(ParticleID::b);
_bottommass = bottom->mass();
PDPtr heavyH = getParticleData(35);
_heavyHmass = heavyH->mass();
_heavyHwidth = heavyH->width();
// higgs stuff
_mh = _higgs->mass();
_m1 = _higgs->mass();
_m2 = _higgs->mass();
_wh = _higgs->width();
if(_higgs->massGenerator()) {
_hmass=dynamic_ptr_cast<GenericMassGeneratorPtr>(_higgs->massGenerator());
}
HwMEBase::doinit();
}
void MEHiggsPair::rebind(const TranslationMap & trans) {
HwMEBase::rebind(trans);
}
IVector MEHiggsPair::getReferences() {
IVector ret = HwMEBase::getReferences();
return ret;
}
IBPtr MEHiggsPair::clone() const {
return new_ptr(*this);
}
IBPtr MEHiggsPair::fullclone() const {
return new_ptr(*this);
}
void MEHiggsPair::persistentOutput(PersistentOStream & os) const {
- os << _selfcoupling << _hhHcoupling << _process << _higgs << ounit(_topmass,GeV) << ounit(_bottommass,GeV) << ounit(_zmass,GeV) << ounit(_m1,GeV) << ounit(_m2,GeV) << ounit(_mh,GeV) << ounit(_wh,GeV) << _hmass << _cH << _c6 << _ct1 << _cb1 << _ct2 << _cb2 << _cg1 << _cg2 << ounit(_EFTScale,GeV) << _fixedalphaS << _alphasfixedvalue << ounit(_heavyHmass,GeV) << ounit(_heavyHwidth,GeV) << ounit(_basescale,GeV) << ounit(_alphascale,GeV) << _fixedscale << _scalemultiplier;
+ os << _selfcoupling << _hhHcoupling << _process << _higgs << ounit(_topmass,GeV) << ounit(_bottommass,GeV) << ounit(_zmass,GeV) << ounit(_m1,GeV) << ounit(_m2,GeV) << ounit(_mh,GeV) << ounit(_wh,GeV) << _hmass << _cH << _c6 << _ct1 << _cb1 << _ct2 << _cb2 << _cg1 << _cg2 << ounit(_EFTScale,GeV) << _fixedalphaS << _alphasfixedvalue << ounit(_heavyHmass,GeV) << ounit(_heavyHwidth,GeV) << ounit(_basescale,GeV) << ounit(_alphascale,GeV) << _fixedscale << _scalemultiplier << _yH << _yh << _ybH << _ybh;
}
void MEHiggsPair::persistentInput(PersistentIStream & is, int) {
- is >> _selfcoupling >> _hhHcoupling >> _process >> _higgs >> iunit(_topmass,GeV) >> iunit(_bottommass,GeV) >> iunit(_zmass,GeV) >> iunit(_m1,GeV) >> iunit(_m2,GeV) >> iunit(_mh,GeV) >> iunit(_wh,GeV) >> _hmass >> _cH >> _c6 >> _ct1 >> _cb1 >> _ct2 >> _cb2 >> _cg1 >> _cg2 >> iunit(_EFTScale,GeV) >> _fixedalphaS >> _alphasfixedvalue >> iunit(_heavyHmass,GeV) >> iunit(_heavyHwidth,GeV) >> iunit(_basescale,GeV) >> iunit(_alphascale,GeV) >> _fixedscale >> _scalemultiplier;
+ is >> _selfcoupling >> _hhHcoupling >> _process >> _higgs >> iunit(_topmass,GeV) >> iunit(_bottommass,GeV) >> iunit(_zmass,GeV) >> iunit(_m1,GeV) >> iunit(_m2,GeV) >> iunit(_mh,GeV) >> iunit(_wh,GeV) >> _hmass >> _cH >> _c6 >> _ct1 >> _cb1 >> _ct2 >> _cb2 >> _cg1 >> _cg2 >> iunit(_EFTScale,GeV) >> _fixedalphaS >> _alphasfixedvalue >> iunit(_heavyHmass,GeV) >> iunit(_heavyHwidth,GeV) >> iunit(_basescale,GeV) >> iunit(_alphascale,GeV) >> _fixedscale >> _scalemultiplier >> _yH >> _yh >> _ybH >> _ybh;
}
Energy2 MEHiggsPair::scale() const {
if(_fixedscale==0 || _fixedscale==5 ) { return sqr(_scalemultiplier)*sHat(); }
else if (_fixedscale==1 || _fixedscale==2 || _fixedscale==3) { return (sqr(_scalemultiplier)*sqr(_basescale)); }
}
// Definition of the static class description member.
ClassDescription<MEHiggsPair> MEHiggsPair::initMEHiggsPair;
void MEHiggsPair::Init() {
static ClassDocumentation<MEHiggsPair> documentation
("The MEHiggsPair class implements the gg -> hh processes in hadron-hadron"
" collisions");
static Parameter<MEHiggsPair, double> interfaceSelfCoupling
("SelfCoupling",
"Multiplier for the SM Higgs triple coupling",
&MEHiggsPair::_selfcoupling, 1.0, -1000000.0, 1000000.0,
false, false, Interface::limited);
static Parameter<MEHiggsPair, double> interfacecH
("cH",
"Effective theory coefficient cH",
&MEHiggsPair::_cH, 0.0, -1000000.0, 1000000.0,
false, false, Interface::limited);
static Parameter<MEHiggsPair, double> interfacec6
("c6",
"Effective theory coefficient c6",
&MEHiggsPair::_c6, 0.0, -1000000.0, 1000000.0,
false, false, Interface::limited);
static Parameter<MEHiggsPair, double> interfacect1
("ct1",
"Effective theory coefficient ct1",
&MEHiggsPair::_ct1, 0.0, -1000000.0, 1000000.0,
false, false, Interface::limited);
static Parameter<MEHiggsPair, double> interfacecb1
("cb1",
"Effective theory coefficient fb1",
&MEHiggsPair::_cb1, 0.0, -1000000.0, 1000000.0,
false, false, Interface::limited);
static Parameter<MEHiggsPair, double> interfacect2
("ct2",
"Effective theory coefficient ft2",
&MEHiggsPair::_ct2, 0.0, -1000000.0, 1000000.0,
false, false, Interface::limited);
static Parameter<MEHiggsPair, double> interfacecb2
("cb2",
"Effective theory coefficient cb2",
&MEHiggsPair::_cb2, 0.0, -1000000.0, 1000000.0,
false, false, Interface::limited);
static Parameter<MEHiggsPair, double> interfacecg1
("cg1",
"Effective theory coefficient cg1",
&MEHiggsPair::_cg1, 0.0, -1000000.0, 1000000.0,
false, false, Interface::limited);
static Parameter<MEHiggsPair, double> interfacecg2
("cg2",
"Effective theory coefficient cg2",
&MEHiggsPair::_cg2, 0.0, -1000000.0, 1000000.0,
false, false, Interface::limited);
+ static Parameter<MEHiggsPair, double> interfacecyytHeavy
+ ("ytH",
+ "Multiplier for Heavy Higgs-top Yukawa",
+ &MEHiggsPair::_yH, 1.0, -1000000.0, 1000000.0,
+ false, false, Interface::limited);
+
+ static Parameter<MEHiggsPair, double> interfacecyytLight
+ ("yth",
+ "Multiplier for Light Higgs-top Yukawa",
+ &MEHiggsPair::_yh, 1.0, -1000000.0, 1000000.0,
+ false, false, Interface::limited);
+
+ static Parameter<MEHiggsPair, double> interfacecyybHeavy
+ ("ybH",
+ "Multiplier for Heavy Higgs-top Yukawa",
+ &MEHiggsPair::_ybH, 1.0, -1000000.0, 1000000.0,
+ false, false, Interface::limited);
+
+ static Parameter<MEHiggsPair, double> interfacecyybLight
+ ("ybh",
+ "Multiplier for Light Higgs-top Yukawa",
+ &MEHiggsPair::_ybh, 1.0, -1000000.0, 1000000.0,
+ false, false, Interface::limited);
+
+
static Parameter<MEHiggsPair, Energy> interfaceEFTScale
("EFTScale",
"Effective theory coefficient f1",
&MEHiggsPair::_EFTScale, GeV, 1000.0*GeV, 1.0*GeV, 10000000*GeV,
false, false, Interface::limited);
static Switch<MEHiggsPair,unsigned int> interfaceFixedAlphaS
("FixedAlphaS",
"Which implementation to use",
&MEHiggsPair::_fixedalphaS, 0, false, false);
static SwitchOption interfaceFixedAlphaSNo
(interfaceFixedAlphaS,
"No",
"Don't fix the scale of alphaS.",
0);
static SwitchOption interfaceFixedAlphaSScale
(interfaceFixedAlphaS,
"Scale",
"Fix the scale of alphaS.",
1);
static SwitchOption interfaceFixedAlphaSAlphaS
(interfaceFixedAlphaS,
"AlphaS",
"Fix alphaS directly via the AlphaS interface.",
2);
static Parameter<MEHiggsPair, Energy> interfaceBaseScale
("BaseScale",
"Base scale if fixed",
&MEHiggsPair::_basescale, GeV, 125.0*GeV, 0.0*GeV, 10000000.0*GeV,
false, false, Interface::limited);
static Switch<MEHiggsPair,unsigned int> interfaceFixedScale
("FixedScale",
"Whether to use fixed base scale or not",
&MEHiggsPair::_fixedscale, 0, false, false);
static SwitchOption interfaceFixedScaleNo
(interfaceFixedScale,
"sHat",
"Don't fix the base scale, use sHat().",
0);
static SwitchOption interfaceFixedScaleFixed
(interfaceFixedScale,
"Fixed",
"Fix the scale of the process to chosen (base scale)^2.",
2);
static SwitchOption interfaceFixedScaleBaseQuad
(interfaceFixedScale,
"FixedQuadPt",
"Fix the scale of the process to (base scale)^2 + pt^2.",
1);
static SwitchOption interfaceFixedScaleBaseLin
(interfaceFixedScale,
"FixedLinPt",
"Fix the scale of the process to (base scale + pt)^2.",
3);
static SwitchOption interfaceFixedScaleMHH
(interfaceFixedScale,
"MHH",
"Don't fix the base scale, use MHH.",
5);
static Parameter<MEHiggsPair, double> interfaceScaleMultiplier
("ScaleMultiplier",
"Multiplier scale",
&MEHiggsPair::_scalemultiplier, 1.0, 0.0, 100000.0,
false, false, Interface::limited);
static Parameter<MEHiggsPair, Energy> interfaceAlphaSScale
("AlphaSScale",
"Scale for alphaS if fixed",
&MEHiggsPair::_alphascale, GeV, 100.0*GeV, 0.0*GeV, 10000000.0*GeV,
false, false, Interface::limited);
static Parameter<MEHiggsPair, double> interfacehHHCoupling
("hhHCoupling",
"Multiplier for the hh-H triple coupling",
&MEHiggsPair::_hhHcoupling, 1.0, -10.0, 10.0,
false, false, Interface::limited);
//choose whether to include the triangle, box or both
static Switch<MEHiggsPair,unsigned int> interfaceProcess
("Process",
"Which subprocesses to include",
&MEHiggsPair::_process, 0, false, false);
static SwitchOption interfaceProcessAll
(interfaceProcess,
"All",
"Include all SM gg->hh subprocesses",
0);
static SwitchOption interfaceProcessTriangle
(interfaceProcess,
"ggToTriangleTohh",
"Include only SM gg->hh triangle subprocess",
1);
static SwitchOption interfaceProcessBox
(interfaceProcess,
"ggToBoxTohh",
"Include only SM gg->hh box subprocess",
2);
static SwitchOption interfaceProcessHhh
(interfaceProcess,
"ggToHTohh",
"Include all gg->hh subprocess, with heavy Higgs",
3);
static SwitchOption interfaceProcessEFT
(interfaceProcess,
"EFT",
"Include all SM gg->hh subprocesses in the EFT",
4);
static SwitchOption interfaceProcessHH
(interfaceProcess,
"ggToHH",
"Include all gg->HH subprocesses",
5);
static SwitchOption interfaceProcessHh
(interfaceProcess,
"ggToHh",
"Include only gg->hH subprocesses",
6);
static Parameter<MEHiggsPair, double> interfaceAlphaS
("AlphaS",
"The value of AlphaS if FixedAlphaS is AlphaS, option 1",
&MEHiggsPair::_alphasfixedvalue, 0.1, 0., 100000.0,
false, false, Interface::limited);
}
CrossSection MEHiggsPair::dSigHatDR() const {
using Constants::pi;
return me2()/(16.0*pi*sqr(sHat())/GeV/GeV)*sqr(hbarc);
}
Selector<MEBase::DiagramIndex>
MEHiggsPair::diagrams(const DiagramVector & diags) const {
// select the diagram, this is easy for us as we have already done it
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i ) {
sel.insert(1.0, i);
}
return sel;
}
//diagrams with box or triangle
void MEHiggsPair::getDiagrams() const {
// get the particle data objects
PDPtr gluon = getParticleData(ParticleID::g);
PDPtr boxon = getParticleData(99926);
PDPtr triangon = getParticleData(99927);
//cout<< _higgs->mass() << endl;
if(_process==0||_process==1||_process==3||_process==4) {
add(new_ptr((Tree2toNDiagram(2),gluon,gluon,
1,triangon,3,higgs(),higgs(),-1)));
}
if(_process==0||_process==2||_process==3||_process==4) {
add(new_ptr((Tree2toNDiagram(2),gluon,gluon,
1,boxon,3,higgs(),higgs(),-2)));
}
}
//both diagrams possess the same colour structure
Selector<const ColourLines *>
MEHiggsPair::colourGeometries(tcDiagPtr diag) const {
// colour lines for gg to hh
static const ColourLines cgghh("1 -2, -1 2");
Selector<const ColourLines *> sel;
switch(abs(diag->id())) {
case 1:
sel.insert(1.0, &cgghh);
break;
case 2:
sel.insert(1.0, &cgghh);
break;
}
return sel;
}
//the matrix element squared with the appropriate factors
double MEHiggsPair::me2() const {
using Constants::pi;
double mesq(0.);
//get the masses and Mandestam variables
Energy mh(_mh);
double Mc = _mh/GeV;
double Md = _mh/GeV;
double s = sHat()/GeV/GeV;
double t = tHat()/GeV/GeV;
double u = uHat()/GeV/GeV;
//calculate the matrix element from the form factors
mesq = MATRIX(s, t, u, Mc, Md);
//QCD factors
double ALPS=SM().alphaS(scale());
if(_fixedalphaS==1) { ALPS = _alphasfixedvalue; }
double QCD=sqr(ALPS);
//XLAM = beta*S
double XLAM=sqrt(sqr(s+sqr(Mc)-sqr(Md))-4.*s*sqr(Mc));
//the jacobian is jacobian()*XLAM
mesq *= jacobian()*XLAM;
mesq *= QCD / (2048.*sqr(pi));
return mesq;
}
bool MEHiggsPair::generateKinematics(const double * r) {
//C--FUNCTION FOR PARTONIC CROSS SECTION
using Constants::pi;
//the form factors
Complex A1,A2,H1,H2,Z1,Z2,AA1,AA2,HH1,HH2,AH1,AH2;
//phase space cut, masses, and Mandelstam variables
double EPS=1E-8;
double S = sHat()/GeV/GeV;
double T = tHat()/GeV/GeV;
double U = uHat()/GeV/GeV;
double M1 = _m1/GeV;
double M2 = _m2/GeV;
double mh = M1;
double WHAT = sqrt(S);
//generate the random variables
vector<double> Y;
int N=2;
Y.resize(N);
for(int I=0; I < N; I++) {
Y[I]=EPS+(1.-2.*EPS)*r[I];
}
jacobian(1.);
double DJAC = 1-2*EPS;
double V=Y[0]/2.;
double XLAM=sqrt(sqr(S+sqr(M1)-sqr(M2))-4.*S*sqr(M1));
double BET=XLAM/(S+sqr(M1)-sqr(M2));
//sample T1 and U1
double T1=-(S+sqr(M1)-sqr(M2))*((1.+BET)/2.-BET*V);
double U1=-(S+sqr(M1)-sqr(M2))*((1.-BET)/2.+BET*V);
T=T1+sqr(M1);
U=U1+sqr(M1);
//calculate the pT squared
double PT2=(T1*U1-S*sqr(M1))/S;
//if identical particles, divide by two
DJAC=DJAC/2.;
jacobian(DJAC*jacobian());
meMomenta()[2].setMass(mh*GeV);
meMomenta()[3].setMass(mh*GeV);
if(WHAT<2*mh) {
jacobian(0.);
return false;
}
Energy q = ZERO;
Energy pt = sqrt(PT2)*GeV;
//calculate the energy/theta/phi given the sqrt(S) = WHAT and pT
q = sqrt(sqr(WHAT)/4 - sqr(mh)) * GeV;
double cth = sqrt( 1 - sqr(pt)/sqr(q) );
double phi = UseRandom::rnd()*2.0*pi;
//set up the momenta in the COM
meMomenta()[2].setX(pt*sin(phi));
meMomenta()[2].setY(pt*cos(phi));
meMomenta()[2].setZ(q*cth);
meMomenta()[3].setX(-pt*sin(phi));
meMomenta()[3].setY(-pt*cos(phi));
meMomenta()[3].setZ(-q*cth);
meMomenta()[2].rescaleEnergy();
meMomenta()[3].rescaleEnergy();
return true;
}
void MEHiggsPair::setKinematics() {
HwMEBase::setKinematics();
}
vector<Complex> MEHiggsPair::iniscal(double AMQ, double S, double T,double U, double M1, double M2) const {
//INITIALIZATION OF SCALAR INTEGRALS
//taken from hpair
Complex C0AB,C0AC,C0AD,C0BC,C0BD,C0CD,D0ABC,D0BAC,D0ACB;
double EPM = 1.E-6;
double c12[1] = {EPM};
double c3[1] = {S};
double c456[1] = {AMQ};
double zerod[1] = {0.};
double sqrm1[1] = {sqr(M1)};
double sqrm2[1] = {sqr(M2)};
double ss[1] = {S};
double tt[1] = {T};
double uu[1] = {U};
Complex DQ2=Complex(sqr(AMQ),0.);
//get the scalar integrals using the associated hpair fortran functions
C0AB = c03_(c12, c12, c3, c456, c456, c456)*DQ2;
C0AC = c03_(c12,sqrm1,tt, c456,c456,c456)*DQ2;
C0AD = c03_(c12,sqrm2,uu,c456,c456,c456)*DQ2;
C0BC = c03_(c12,sqrm1,uu,c456,c456,c456)*DQ2;
C0BD = c03_(c12,sqrm2,tt,c456,c456,c456)*DQ2;
C0CD = c03_(sqrm1,sqrm2,ss,c456,c456,c456)*DQ2;
D0ABC = sqr(DQ2)*d04_(zerod,zerod,sqrm1,sqrm2,ss,uu,c456,c456,c456,c456);
D0BAC = sqr(DQ2)*d04_(zerod,zerod,sqrm1,sqrm2,ss,tt,c456,c456,c456,c456);
D0ACB = sqr(DQ2)*d04_(zerod,sqrm1,zerod,sqrm2,tt,uu,c456,c456,c456,c456);
//push them back into a vector
vector<Complex> FormRes;
FormRes.push_back(C0AB);
FormRes.push_back(C0AC);
FormRes.push_back(C0AD);
FormRes.push_back(C0BC);
FormRes.push_back(C0BD);
FormRes.push_back(C0CD);
FormRes.push_back(D0ABC);
FormRes.push_back(D0BAC);
FormRes.push_back(D0ACB);
return FormRes;
}
//calculate the LO matrix element squared as given by hpair, constants are taken care of by me2()
//both top and bottom loops are considered.
double MEHiggsPair::MATRIX(double S, double T,double U, double M1, double M2) const {
//C--LO MATRIX ELEMENT FOR GG -> HH
using Constants::pi;
Complex A1,A2,H1,H2,Z1,Z2,AA1,AA2,HH1,HH2,AH1,AH2;
Complex F1,F2,PROH, PROHEAVY;
//bottom and top masses
double AMT = _topmass/GeV;
double AMB = _bottommass/GeV;
//W mass
double MW = _Wmass/GeV;
//higgs width and mass
double FACH=1;
double GAMH= _wh/GeV;
double AMH = _mh/GeV;
//vacuum expectation value, self-coupling, top and bottom Yukawas
double V = 1./sqrt(sqrt(2) * SM().fermiConstant()*GeV*GeV);
double GHHH = _selfcoupling * 3.*sqr(AMH) / V;
- double GHT=AMT/V;
- double GHB=AMB/V;
+ double GHT=_yh*AMT/V;
+ double GHB=_ybh*AMB/V;
double ALPS=SM().alphaS(scale());
if(_fixedalphaS==1) { ALPS = _alphasfixedvalue; }
double eftscale = _EFTScale/GeV;
//Higgs propagator
PROH = Complex(S-sqr(AMH),AMH*GAMH*FACH);
//EFT-modified self-coupling
double GHHH_EFT = 0;
if(_process == 4) {
GHHH_EFT = (3.*sqr(AMH) / V) * ( - (3./2.) * _cH + _c6 ) ;
}
//EFT-modified top/bottom Yukawas
double GHT_EFT = 0, GHB_EFT = 0;
if(_process == 4) {
GHT_EFT = AMT/V * ( _ct1 - 0.5 * _cH );
GHB_EFT = AMB/V * ( _cb1 - 0.5 * _cH );
}
//Heavy Higgs
double AMHEAVY = _heavyHmass/GeV;
- double GAMHEAVY = _heavyHwidth/GeV;
+ double GAMHEAVY = _heavyHwidth/GeV;
+ double GHTHEAVY=_yH*AMT/V;
+ double GHBHEAVY=_ybH*AMB/V;
+
+
double FACHEAVY = 1.;
PROHEAVY = Complex(S-sqr(AMHEAVY),AMHEAVY*GAMHEAVY*FACHEAVY);
double GHhh = _hhHcoupling * 3.*sqr(AMHEAVY) / V; // Hhh coupling (for _process == 3)
//calculation of scalar integrals C_ij and D_ijk
vector<Complex> ScalFacs;
ScalFacs = iniscal(AMT, S, T, U, M1, M2);
double amq[1] = {AMT};
double m1[1] = {M1};
double m2[1] = {M2};
double ss[1] = {S};
double tt[1] = {T};
double uu[1] = {U};
Complex C0AB[1] = {ScalFacs[0]};
Complex C0AC[1] = {ScalFacs[1]};
Complex C0AD[1] = {ScalFacs[2]};
Complex C0BC[1] = {ScalFacs[3]};
Complex C0BD[1] = {ScalFacs[4]};
Complex C0CD[1] = {ScalFacs[5]};
Complex D0ABC[1] = {ScalFacs[6]};
Complex D0BAC[1] = {ScalFacs[7]};
Complex D0ACB[1] = {ScalFacs[8]};
//form factors for top quark contributions
formfac_(amq, ss, tt, uu, m1, m2, C0AB, C0AC, C0AD, C0BC, C0BD, C0CD, D0ABC, D0BAC, D0ACB);
// this factor needs to be divided out to go from SM EFT to DIM-6 EFT
double CH = ALPS / (8. * pi);
F1 = Complex(0.,0.);
F2 = Complex(0.,0.);
//triangle
if(_process==0||_process==1||_process==3||_process==4) {
F1 = F1 + (form_.H1*(GHT*GHHH/PROH)); //(1)
}
//triangle: EFT
if(_process==4) {
F1 = F1 + (form_.H1*(GHT*GHHH_EFT+GHT_EFT*GHHH)/PROH);
}
//box
if(_process==0||_process==2||_process==3||_process==4) {
F1 = F1 + (form_.HH1*GHT*GHT); //(2)
F2 = F2 + (form_.HH2*GHT*GHT);
}
//box: EFT
if(_process==4) {
F1 = F1 + 2. * (form_.HH1*GHT_EFT*GHT);
F2 = F2 + 2. * (form_.HH2*GHT_EFT*GHT);
}
//additional EFT from gg -> h -> hh diagram:
if(_process==4) {
F1 = F1 + _cg1 * (2.*S/V)*2*(GHHH/PROH);
/* divide (1) by form_.H1*AMT/(2*S) to remove F_triangle
* multiply by 2
* and multiply by cg1
*/
}
//additional EFT from gg -> hh diagram:
if(_process==4) {
F1 = F1 + _cg2 * (2.*S/sqr(V))*2.;
/* divide (2) by form_.HH1*sqr(AMT)/(2*S) to remove F_box
* multiply by 2
* and multiply by cg2
*/
}
//EFT: new t-tbar-h-h diagram
if(_process==4) {
double GttHH = (3.*_ct2 - _cH) *AMT/(2.*sqr(V)); // we have already replaced yf/sqrt(2) = mf/V
F1 = F1 + (form_.H1*2.*GttHH); //factor of 2 from tthh feynman rule
}
//TESTING BELOW
/* cout << "form_.H1 = " << form_.H1 << " form_.HH1 = " << form_.HH1 << endl;
cout << "Ftri = " << real(form_.H1)*AMT/(2*S) << endl;
cout << "Fbox = " << real(form_.HH1)*sqr(AMT)/(2*S) << endl; */
//form factors for bottom quark contributions
ScalFacs = iniscal(AMB, S, T, U, M1, M2);
amq[0] = AMB;
C0AB[0] = ScalFacs[0];
C0AC[0] = ScalFacs[1];
C0AD[0] = ScalFacs[2];
C0BC[0] = ScalFacs[3];
C0BD[0] = ScalFacs[4];
C0CD[0] = ScalFacs[5];
D0ABC[0] = ScalFacs[6];
D0BAC[0] = ScalFacs[7];
D0ACB[0] = ScalFacs[8];
formfac_(amq, ss, tt, uu, m1, m2, C0AB, C0AC, C0AD, C0BC, C0BD, C0CD, D0ABC, D0BAC, D0ACB);
//triangle
if(_process==0||_process==1||_process==3||_process==4) {
F1 = F1 + (form_.H1*(GHB*GHHH/PROH));
}
//triangle: EFT
if(_process==4) {
F1 = F1 + (form_.H1*(GHB*GHHH_EFT+GHB_EFT*GHHH)/PROH);
}
//box
if(_process==0||_process==2||_process==3||_process==4) {
F1 = F1 + (form_.HH1*GHB*GHB);
F2 = F2 + (form_.HH2*GHB*GHB);
}
//box: EFT
if(_process==4) {
F1 = F1 + 2. * (form_.HH1*GHB_EFT*GHB);
F2 = F2 + 2. * (form_.HH2*GHB_EFT*GHB);
}
//EFT: new b-bbar-h-h diagram
if(_process==4) {
double GbbHH = (3.*_cb2 - _cH) *AMB/(2.*sqr(V));// we have already replaced yf/sqrt(2) = mf/V
F1 = F1 + (form_.H1*2.*GbbHH);
}
if(_process==3) {
m1[0] = AMH;
m2[0] = AMHEAVY;
ScalFacs = iniscal(AMT, S, T, U, M1, M2);
amq[0] = AMT;
C0AB[0] = ScalFacs[0];
C0AC[0] = ScalFacs[1];
C0AD[0] = ScalFacs[2];
C0BC[0] = ScalFacs[3];
C0BD[0] = ScalFacs[4];
C0CD[0] = ScalFacs[5];
D0ABC[0] = ScalFacs[6];
D0BAC[0] = ScalFacs[7];
D0ACB[0] = ScalFacs[8];
formfac_(amq, ss, tt, uu, m1, m2, C0AB, C0AC, C0AD, C0BC, C0BD, C0CD, D0ABC, D0BAC, D0ACB);
- F1 = F1 + (form_.H1*(GHT*GHhh/PROHEAVY));
+ F1 = F1 + (form_.H1*(GHTHEAVY*GHhh/PROHEAVY));
ScalFacs = iniscal(AMB, S, T, U, M1, M2);
amq[0] = AMB;
C0AB[0] = ScalFacs[0];
C0AC[0] = ScalFacs[1];
C0AD[0] = ScalFacs[2];
C0BC[0] = ScalFacs[3];
C0BD[0] = ScalFacs[4];
C0CD[0] = ScalFacs[5];
D0ABC[0] = ScalFacs[6];
D0BAC[0] = ScalFacs[7];
D0ACB[0] = ScalFacs[8];
formfac_(amq, ss, tt, uu, m1, m2, C0AB, C0AC, C0AD, C0BC, C0BD, C0CD, D0ABC, D0BAC, D0ACB);
- F1 = F1 + (form_.H1*(GHB*GHhh/PROHEAVY));
+ F1 = F1 + (form_.H1*(GHBHEAVY*GHhh/PROHEAVY));
}
//square
double DMAT = 2. * (norm(F1) + norm(F2));
return DMAT;
}
diff --git a/Contrib/HiggsPair/MEHiggsPair.h b/Contrib/HiggsPair/MEHiggsPair.h
--- a/Contrib/HiggsPair/MEHiggsPair.h
+++ b/Contrib/HiggsPair/MEHiggsPair.h
@@ -1,489 +1,507 @@
// -*- C++ -*-
//
// MEHiggsPair.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2009-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_MEHiggsPair_H
#define HERWIG_MEHiggsPair_H
//
// This is the declaration of the MEHiggsPair class.
//
#include "Herwig/MatrixElement/HwMEBase.h"
#include "ThePEG/Repository/UseRandom.h"
#include "Herwig/PDT/GenericMassGenerator.h"
#include "Herwig/Utilities/Kinematics.h"
#include "Herwig/MatrixElement/ProductionMatrixElement.h"
namespace Herwig {
using namespace ThePEG;
/*
* Interface to external FORTRAN hpair functions (T.Plehn, M.Spira & P.Zerwas, arXiv:hep-ph/9603205)
* original Program found at http://people.web.psi.ch/spira/hpair/
*/
extern "C" {
complex<double> eta_(complex<double>* C1, complex<double>* C2);
complex<double> d04_(double* P1, double* P2, double* P3, double* P4, double* P12,double* P23, double* M1, double* M2, double* M3, double* M4);
complex<double> c03_(double* P1,double* P2,double* P3,double* M1,double* M2,double* M3);
complex<double> cspen_(double* Z);
complex<double> sqe_(double* A, double* B, double* C);
complex<double> etas_(complex<double>*Y,complex<double>* R,complex<double>*RS);
void formfac_(double* AMQ, double* S, double* T, double* U, double* M1, double* M2, complex<double>* C0AB,complex<double>* C0AC,complex<double>* C0AD,complex<double>* C0BC,complex<double>* C0BD,complex<double>* C0CD,complex<double>* D0ABC,complex<double>* D0BAC,complex<double>* D0ACB);
}
extern "C" {
extern struct{
complex<double> A1;
complex<double> A2;
complex<double> H1;
complex<double> H2;
complex<double> Z1;
complex<double> Z2;
complex<double> AA1;
complex<double> AA2;
complex<double> HH1;
complex<double> HH2;
complex<double> AH1;
complex<double> AH2;
} form_;
}
/**
* The MEHiggsPair class implements the matrix elements for
* HiggsPairian \f$2\to2\f$ scattering process
*/
class MEHiggsPair: public HwMEBase {
public:
/**
* The default constructor.
*/
MEHiggsPair();
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const { return 0; }
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const { return 0; }
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Generate internal degrees of freedom
*/
virtual bool generateKinematics(const double * r);
/**
* Return the matrix element squared differential in the variables
* given by the last call to generateKinematics().
*/
virtual CrossSection dSigHatDR() const;
/*
* Fix alphaS
*/
unsigned int fixedalphaS() const { return _fixedalphaS; }
/*
* Fixed alphaS value if AlphaS is chosen (option 2 above)
*/
double alphasfixedvalue() const { return _alphasfixedvalue; }
/**
* Return multiplier for scale
*/
double scalemultiplier() const {return _scalemultiplier;}
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
//@}
virtual void setKinematics();
/**
* The number of internal degrees of freedom used in the matrix
* element.
*/
virtual int nDim() 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();
/**
* Rebind pointer to other Interfaced objects. Called in the setup phase
* after all objects used in an EventGenerator has been cloned so that
* the pointers will refer to the cloned objects afterwards.
* @param trans a TranslationMap relating the original objects to
* their respective clones.
* @throws RebindException if no cloned object was found for a given
* pointer.
*/
virtual void rebind(const TranslationMap & trans);
/**
* Return a vector of all pointers to Interfaced objects used in this
* object.
* @return a vector of pointers.
*/
virtual IVector getReferences();
//@}
/**
* Access to the higgs data
*/
PDPtr higgs() const { return _higgs; }
/**
* Set the higgs data
*/
void higgs(PDPtr in) {_higgs =in;}
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;
//@}
protected:
/** @name Helper functions for me2. */
//@{
/**
*/
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEHiggsPair> initMEHiggsPair;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEHiggsPair & operator=(const MEHiggsPair &);
/**
* The higgs boson
*/
PDPtr _higgs;
/*
* The W mass
*/
Energy _Wmass;
/*
* The top mass
*/
Energy _topmass;
/*
* The bottom mass
*/
Energy _bottommass;
/*
* The Z boson mass
*/
Energy _zmass;
/*
* Higgs boson mass(es)
*/
Energy _m1, _m2;
/*
* Heavy H mass
*/
Energy _heavyHmass;
/*
* Heavy H width
*/
Energy _heavyHwidth;
+ /*
+ * top yukawa multiplier, Heavy
+ */
+ double _yH;
+ /*
+ * top yukawa multiplier, light
+ */
+ double _yh;
+
+ /*
+ * bottom yukawa multiplier, Heavy
+ */
+ double _ybH;
+
+ /*
+ * bottom yukawa multiplier, light
+ */
+ double _ybh;
private:
/**
* The mass generator for the Higgs
*/
GenericMassGeneratorPtr _hmass;
/**
* multiplier for the SM triple-coupling
*/
double _selfcoupling;
/**
* multiplier for the hhH triple-coupling
*/
double _hhHcoupling;
/**
* Processes to include
*/
unsigned int _process;
/*
* Fix alphaS
*/
unsigned int _fixedalphaS;
/*
* Scale to use for alpha_S if fixed
*/
Energy _alphascale;
/*
* Value of AlphaS if fixed using option 2 above
*/
double _alphasfixedvalue;
/*
* Base scale to use if chosen to be fixed
*/
Energy _basescale;
/*
* scale multiplier
*/
double _scalemultiplier;
/*
* Fix scale of whole process
*/
unsigned int _fixedscale;
/**
* On-shell mass for the higgs
*/
Energy _mh;
/**
* On-shell width for the higgs
*/
Energy _wh;
/**
* On-shell mass for the W
*/
Energy _mW;
/*
* _cH, effective theory coefficient
*/
double _cH;
/* _c6, effective theory coefficient
*
*/
double _c6;
/*
* _cg1, effective theory coefficient
*/
double _cg1;
/* _cg2, effective theory coefficient
*
*/
double _cg2;
/*
* _ct1, effective theory coefficient
*/
double _ct1;
/*
* _ct2, effective theory coefficient
*/
double _ct2;
/* _ct2, effective theory coefficient
*
*/
double _cb1;
/* f_b2, effective theory coefficient
*
*/
double _cb2;
/* effective theory scale
*
*/
Energy _EFTScale;
/* Scalar integral initialization from hpair.f (T.Plehn, M.Spira & P.Zerwas, arXiv:hep-ph/9603205)
Program found at http://people.web.psi.ch/spira/hpair/ */
virtual vector<Complex> iniscal(double AMQ, double S, double T,double U, double M1, double M2) const;
/* Matrix element calculation from hpair */
virtual double MATRIX(double S, double T,double U, double M1, double M2) const;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEHiggsPair. */
template <>
struct BaseClassTrait<Herwig::MEHiggsPair,1> {
/** Typedef of the first base class of MEHiggsPair. */
typedef Herwig::HwMEBase NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEHiggsPair class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEHiggsPair>
: public ClassTraitsBase<Herwig::MEHiggsPair> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEHiggsPair"; }
/**
* The name of a file containing the dynamic library where the class
* MEHiggsPair is implemented. It may also include several, space-separated,
* libraries if the class MEQCD2to2Fast depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "MEHiggsPair.so"; }
};
/** @endcond */
}
#endif /* HERWIG_MEHiggsPair_H */
diff --git a/Contrib/LeptonME/Makefile.in b/Contrib/LeptonME/Makefile.in
--- a/Contrib/LeptonME/Makefile.in
+++ b/Contrib/LeptonME/Makefile.in
@@ -1,36 +1,36 @@
# -*- Makefile -*- (for emacs)
#
# This Makefile is intended for compiling Herwig++ plugins
# You can find plugins here: INSERT URL
#
# This Makefile received very little testing,
# any bug reports are very welcome!
#
# location of include files
THEPEGINCLUDE=
HERWIGINCLUDE=
GSLINCLUDE=
LDFLAGS =
SHARED_FLAG =
INCLUDE = $(THEPEGINCLUDE) $(HERWIGINCLUDE) $(GSLINCLUDE)
#
# C++ flags
#
CXX =
CXXFLAGS =
ALLCCFILES=$(shell echo *.cc)
default : LeptonME.so
%.o : %.cc %.h
$(CXX) -fPIC $(CPPFLAGS) $(INCLUDE) $(CXXFLAGS) -c -shared $< -o $@
LeptonME.so: MEee2Higgs2SM.o MEee2Z.o
$(CXX) -fPIC $(CPPFLAGS) $(INCLUDE) $(CXXFLAGS) \
- MEee2Higgs2SM.o MEee2Z.o $(SHARED_FLAG) $(LDFLAGS) -o LeptonME.so
+ MEee2Z.o $(SHARED_FLAG) $(LDFLAGS) -o LeptonME.so
clean:
rm -f $(ALLCCFILES:.cc=.o) LeptonME.so
diff --git a/Decay/Baryon/Makefile.am b/Decay/Baryon/Makefile.am
--- a/Decay/Baryon/Makefile.am
+++ b/Decay/Baryon/Makefile.am
@@ -1,23 +1,46 @@
-pkglib_LTLIBRARIES = HwBaryonDecay.la
+BUILT_SOURCES = BaryonDecayer__all.cc
+DISTCLEANFILES = BaryonDecayer__all.cc
-HwBaryonDecay_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 8:0:0
-HwBaryonDecay_la_LIBADD = $(top_builddir)/PDT/libHwBaryonWidth.la
-HwBaryonDecay_la_SOURCES = \
-Baryon1MesonDecayerBase.cc Baryon1MesonDecayerBase.h \
-Baryon1MesonDecayerBase.fh\
-BaryonFactorizedDecayer.cc BaryonFactorizedDecayer.h \
-KornerKramerCharmDecayer.cc KornerKramerCharmDecayer.h \
-NonLeptonicHyperonDecayer.cc NonLeptonicHyperonDecayer.h \
-RadiativeHyperonDecayer.cc RadiativeHyperonDecayer.h \
-NonLeptonicOmegaDecayer.cc NonLeptonicOmegaDecayer.h \
-OmegaXiStarPionDecayer.cc OmegaXiStarPionDecayer.h \
-SemiLeptonicBaryonDecayer.cc SemiLeptonicBaryonDecayer.h \
-StrongHeavyBaryonDecayer.cc StrongHeavyBaryonDecayer.h \
-SU3BaryonDecupletOctetPhotonDecayer.cc SU3BaryonDecupletOctetPhotonDecayer.h\
-SU3BaryonDecupletOctetScalarDecayer.cc SU3BaryonDecupletOctetScalarDecayer.h\
-SU3BaryonOctetDecupletScalarDecayer.cc SU3BaryonOctetDecupletScalarDecayer.h\
-SU3BaryonOctetOctetPhotonDecayer.cc SU3BaryonOctetOctetPhotonDecayer.h \
-SU3BaryonOctetOctetScalarDecayer.cc SU3BaryonOctetOctetScalarDecayer.h \
-SU3BaryonSingletOctetPhotonDecayer.cc SU3BaryonSingletOctetPhotonDecayer.h \
-SU3BaryonSingletOctetScalarDecayer.cc SU3BaryonSingletOctetScalarDecayer.h \
-RadiativeHeavyBaryonDecayer.cc RadiativeHeavyBaryonDecayer.h
+BaryonDecayer__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+Baryon1MesonDecayerBase.h \
+Baryon1MesonDecayerBase.fh \
+BaryonFactorizedDecayer.h \
+KornerKramerCharmDecayer.h \
+OmegaXiStarPionDecayer.h \
+SemiLeptonicBaryonDecayer.h \
+StrongHeavyBaryonDecayer.h \
+NonLeptonicHyperonDecayer.h \
+NonLeptonicOmegaDecayer.h \
+RadiativeHyperonDecayer.h \
+RadiativeHeavyBaryonDecayer.h \
+SU3BaryonDecupletOctetPhotonDecayer.h\
+SU3BaryonDecupletOctetScalarDecayer.h\
+SU3BaryonOctetDecupletScalarDecayer.h\
+SU3BaryonOctetOctetPhotonDecayer.h \
+SU3BaryonOctetOctetScalarDecayer.h \
+SU3BaryonSingletOctetPhotonDecayer.h \
+SU3BaryonSingletOctetScalarDecayer.h
+
+ALL_CC_FILES = \
+Baryon1MesonDecayerBase.cc \
+BaryonFactorizedDecayer.cc \
+KornerKramerCharmDecayer.cc \
+OmegaXiStarPionDecayer.cc \
+SemiLeptonicBaryonDecayer.cc \
+StrongHeavyBaryonDecayer.cc \
+NonLeptonicHyperonDecayer.cc \
+NonLeptonicOmegaDecayer.cc \
+RadiativeHyperonDecayer.cc \
+RadiativeHeavyBaryonDecayer.cc \
+SU3BaryonDecupletOctetPhotonDecayer.cc \
+SU3BaryonDecupletOctetScalarDecayer.cc \
+SU3BaryonOctetDecupletScalarDecayer.cc \
+SU3BaryonOctetOctetPhotonDecayer.cc \
+SU3BaryonOctetOctetScalarDecayer.cc \
+SU3BaryonSingletOctetPhotonDecayer.cc \
+SU3BaryonSingletOctetScalarDecayer.cc
diff --git a/Decay/FormFactors/Makefile.am b/Decay/FormFactors/Makefile.am
--- a/Decay/FormFactors/Makefile.am
+++ b/Decay/FormFactors/Makefile.am
@@ -1,31 +1,57 @@
noinst_LTLIBRARIES = libHwFormFactor.la
-pkglib_LTLIBRARIES = HwFormFactors.la
-
libHwFormFactor_la_SOURCES = \
BaryonFormFactor.cc BaryonFormFactor.fh \
BaryonFormFactor.h \
ScalarFormFactor.cc ScalarFormFactor.fh \
ScalarFormFactor.h \
BtoSGammaHadronicMass.h \
BtoSGammaHadronicMass.cc BtoSGammaHadronicMass.fh
-HwFormFactors_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 9:1:0
-HwFormFactors_la_SOURCES = \
-BallZwickyScalarFormFactor.cc BallZwickyScalarFormFactor.h \
-BallZwickyVectorFormFactor.cc BallZwickyVectorFormFactor.h \
-BaryonSimpleFormFactor.cc BaryonSimpleFormFactor.h \
-BaryonThreeQuarkModelFormFactor.cc BaryonThreeQuarkModelFormFactor.h \
-ChengHeavyBaryonFormFactor.cc ChengHeavyBaryonFormFactor.h \
-ISGW2FormFactor.cc ISGW2FormFactor.h \
-ISGWFormFactor.cc ISGWFormFactor.h \
+
+
+
+BUILT_SOURCES = Formfactor__all.cc
+DISTCLEANFILES = Formfactor__all.cc
+
+Formfactor__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+BallZwickyScalarFormFactor.h \
+BallZwickyVectorFormFactor.h \
+BaryonSimpleFormFactor.h \
+BaryonThreeQuarkModelFormFactor.h \
+ChengHeavyBaryonFormFactor.h \
+ISGW2FormFactor.h \
+ISGWFormFactor.h \
+LambdabExcitedLambdacSumRuleFormFactor.h \
+LightBaryonQuarkModelFormFactor.h \
+SingletonFormFactor.h \
+WSBFormFactor.h \
+KiselevBcFormFactor.h \
+MelikhovFormFactor.h \
+MelikhovStechFormFactor.h \
+BtoSGammaFlatEnergy.h \
+BtoSGammaKagan.h \
+HQETFormFactor.h
+
+ALL_CC_FILES = \
+BallZwickyScalarFormFactor.cc \
+BallZwickyVectorFormFactor.cc \
+BaryonSimpleFormFactor.cc \
+BaryonThreeQuarkModelFormFactor.cc \
+ChengHeavyBaryonFormFactor.cc \
+ISGW2FormFactor.cc \
+ISGWFormFactor.cc \
LambdabExcitedLambdacSumRuleFormFactor.cc \
-LambdabExcitedLambdacSumRuleFormFactor.h \
-LightBaryonQuarkModelFormFactor.cc LightBaryonQuarkModelFormFactor.h \
-SingletonFormFactor.cc SingletonFormFactor.h\
-WSBFormFactor.cc WSBFormFactor.h\
-KiselevBcFormFactor.cc KiselevBcFormFactor.h\
-MelikhovFormFactor.cc MelikhovFormFactor.h \
-MelikhovStechFormFactor.cc MelikhovStechFormFactor.h \
-BtoSGammaFlatEnergy.h BtoSGammaFlatEnergy.cc \
-BtoSGammaKagan.h BtoSGammaKagan.cc\
-HQETFormFactor.h HQETFormFactor.cc
+LightBaryonQuarkModelFormFactor.cc \
+SingletonFormFactor.cc \
+WSBFormFactor.cc \
+KiselevBcFormFactor.cc \
+MelikhovFormFactor.cc \
+MelikhovStechFormFactor.cc \
+BtoSGammaFlatEnergy.cc \
+BtoSGammaKagan.cc \
+HQETFormFactor.cc
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/Makefile.am b/Decay/General/Makefile.am
--- a/Decay/General/Makefile.am
+++ b/Decay/General/Makefile.am
@@ -1,31 +1,66 @@
noinst_LTLIBRARIES = libHwGeneralDecay.la
libHwGeneralDecay_la_SOURCES = \
GeneralTwoBodyDecayer.h GeneralTwoBodyDecayer.fh GeneralTwoBodyDecayer.cc \
-FFSDecayer.h FFSDecayer.cc \
-FFVDecayer.h FFVDecayer.cc \
-SFFDecayer.h SFFDecayer.cc \
-SSSDecayer.h SSSDecayer.cc \
-SSVDecayer.h SSVDecayer.cc \
-SVVDecayer.h SVVDecayer.cc \
-TFFDecayer.h TFFDecayer.cc \
-TSSDecayer.h TSSDecayer.cc \
-TVVDecayer.h TVVDecayer.cc \
-VFFDecayer.h VFFDecayer.cc \
-VSSDecayer.h VSSDecayer.cc \
-VVSDecayer.h VVSDecayer.cc \
-VVVDecayer.h VVVDecayer.cc \
-SRFDecayer.h SRFDecayer.cc \
-FRSDecayer.h FRSDecayer.cc \
-FRVDecayer.h FRVDecayer.cc \
GeneralThreeBodyDecayer.h GeneralThreeBodyDecayer.fh \
GeneralThreeBodyDecayer.cc \
-FtoFFFDecayer.h FtoFFFDecayer.cc \
-StoSFFDecayer.h StoSFFDecayer.cc \
-StoFFVDecayer.h StoFFVDecayer.cc \
-VtoFFVDecayer.h VtoFFVDecayer.cc \
-FtoFVVDecayer.h FtoFVVDecayer.cc \
GeneralCurrentDecayer.h GeneralCurrentDecayer.fh GeneralCurrentDecayer.cc \
-FFVCurrentDecayer.h FFVCurrentDecayer.cc \
GeneralFourBodyDecayer.h GeneralFourBodyDecayer.fh \
GeneralFourBodyDecayer.cc \
-StoFFFFDecayer.h StoFFFFDecayer.cc
+StoFFFFDecayer.h StoFFFFDecayer.cc \
+GeneralDecayer__all.cc $(ALL_H_FILES)
+
+BUILT_SOURCES = GeneralDecayer__all.cc
+DISTCLEANFILES = GeneralDecayer__all.cc
+
+GeneralDecayer__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+FFSDecayer.h \
+FFVDecayer.h \
+SFFDecayer.h \
+SSSDecayer.h \
+SSVDecayer.h \
+SVVDecayer.h \
+TFFDecayer.h \
+TSSDecayer.h \
+TVVDecayer.h \
+VFFDecayer.h \
+VSSDecayer.h \
+VVSDecayer.h \
+VVVDecayer.h \
+SRFDecayer.h \
+FRSDecayer.h \
+FRVDecayer.h \
+FtoFFFDecayer.h \
+StoSFFDecayer.h \
+StoFFVDecayer.h \
+VtoFFVDecayer.h \
+FtoFVVDecayer.h \
+FFVCurrentDecayer.h
+
+ALL_CC_FILES = \
+FFSDecayer.cc \
+FFVDecayer.cc \
+SFFDecayer.cc \
+SSSDecayer.cc \
+SSVDecayer.cc \
+SVVDecayer.cc \
+TFFDecayer.cc \
+TSSDecayer.cc \
+TVVDecayer.cc \
+VFFDecayer.cc \
+VSSDecayer.cc \
+VVSDecayer.cc \
+VVVDecayer.cc \
+SRFDecayer.cc \
+FRSDecayer.cc \
+FRVDecayer.cc \
+FtoFFFDecayer.cc \
+StoSFFDecayer.cc \
+StoFFVDecayer.cc \
+VtoFFVDecayer.cc \
+FtoFVVDecayer.cc \
+FFVCurrentDecayer.cc
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/Decay/Makefile.am b/Decay/Makefile.am
--- a/Decay/Makefile.am
+++ b/Decay/Makefile.am
@@ -1,30 +1,183 @@
SUBDIRS = FormFactors Tau Baryon VectorMeson Perturbative \
WeakCurrents ScalarMeson TensorMeson Partonic General Radiation
if HAVE_EVTGEN
SUBDIRS += EvtGen
endif
noinst_LTLIBRARIES = libHwDecay.la
-pkglib_LTLIBRARIES = Hw64Decay.la HwMamboDecay.la
-Hw64Decay_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 8:0:0
-Hw64Decay_la_SOURCES = Hw64Decayer.h Hw64Decayer.cc
+libHwDecay_la_LIBADD = \
+$(top_builddir)/PDT/libHwPDT.la
-HwMamboDecay_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 9:0:0
-HwMamboDecay_la_SOURCES = MamboDecayer.h MamboDecayer.cc
+libHwDecay_la_SOURCES = \
+hwdecay__all.cc
-libHwDecay_la_LIBADD = $(top_builddir)/PDT/libHwPDT.la
-libHwDecay_la_SOURCES = \
-DecayIntegrator.cc DecayIntegrator.fh DecayIntegrator.h \
-DecayPhaseSpaceChannel.cc DecayPhaseSpaceChannel.fh \
-DecayPhaseSpaceChannel.h \
-DecayPhaseSpaceMode.cc DecayPhaseSpaceMode.fh \
-DecayPhaseSpaceMode.h \
-HwDecayerBase.cc HwDecayerBase.fh HwDecayerBase.h \
-HwDecayHandler.cc HwDecayHandler.h\
-DecayVertex.fh DecayVertex.h DecayVertex.cc \
-DecayMatrixElement.h DecayMatrixElement.cc DecayMatrixElement.fh \
-TwoBodyDecayMatrixElement.h TwoBodyDecayMatrixElement.cc \
-GeneralDecayMatrixElement.h GeneralDecayMatrixElement.cc GeneralDecayMatrixElement.fh \
-BranchingRatioReweighter.h BranchingRatioReweighter.cc
+BUILT_SOURCES = hwdecay__all.cc
+DISTCLEANFILES = hwdecay__all.cc
+
+hwdecay__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+DecayIntegrator.fh DecayIntegrator.h \
+DecayPhaseSpaceChannel.fh DecayPhaseSpaceChannel.h \
+DecayPhaseSpaceMode.fh DecayPhaseSpaceMode.h \
+HwDecayerBase.fh HwDecayerBase.h \
+HwDecayHandler.h \
+DecayVertex.fh DecayVertex.h \
+DecayMatrixElement.fh DecayMatrixElement.h \
+TwoBodyDecayMatrixElement.h \
+GeneralDecayMatrixElement.fh GeneralDecayMatrixElement.h \
+BranchingRatioReweighter.h
+
+ALL_CC_FILES = \
+DecayIntegrator.cc \
+DecayPhaseSpaceChannel.cc \
+DecayPhaseSpaceMode.cc \
+HwDecayerBase.cc \
+HwDecayHandler.cc \
+DecayVertex.cc \
+DecayMatrixElement.cc \
+TwoBodyDecayMatrixElement.cc \
+GeneralDecayMatrixElement.cc \
+BranchingRatioReweighter.cc
+
+
+
+##################
+
+pkglib_LTLIBRARIES = Hw64Decay.la
+
+Hw64Decay_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 8:0:0
+
+Hw64Decay_la_SOURCES = \
+Hw64Decayer.h Hw64Decayer.cc
+
+##################
+
+pkglib_LTLIBRARIES += HwMamboDecay.la
+
+HwMamboDecay_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 9:0:0
+
+HwMamboDecay_la_SOURCES = \
+MamboDecayer.h MamboDecayer.cc
+
+##################
+
+pkglib_LTLIBRARIES += HwFormFactors.la
+
+HwFormFactors_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 9:1:0
+
+HwFormFactors_la_SOURCES = \
+FormFactors/Formfactor__all.cc
+
+##################
+
+pkglib_LTLIBRARIES += HwTauDecay.la
+
+HwTauDecay_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 9:0:0
+
+HwTauDecay_la_SOURCES = \
+Tau/TauDecayer.cc
+
+##################
+
+pkglib_LTLIBRARIES += HwBaryonDecay.la
+
+HwBaryonDecay_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 8:0:0
+
+HwBaryonDecay_la_LIBADD = \
+$(top_builddir)/PDT/libHwBaryonWidth.la
+
+HwBaryonDecay_la_SOURCES = \
+Baryon/BaryonDecayer__all.cc
+
+##################
+
+pkglib_LTLIBRARIES += HwVMDecay.la
+
+HwVMDecay_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 8:0:0
+
+HwVMDecay_la_SOURCES = \
+VectorMeson/VMDecayer__all.cc
+
+##################
+
+pkglib_LTLIBRARIES += HwPerturbativeDecay.la
+
+HwPerturbativeDecay_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 9:0:0
+
+HwPerturbativeDecay_la_SOURCES = \
+Perturbative/Perturbative__all.cc
+
+##################
+
+pkglib_LTLIBRARIES += HwPerturbativeHiggsDecay.la
+
+HwPerturbativeHiggsDecay_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 9:0:0
+
+HwPerturbativeHiggsDecay_la_SOURCES = \
+Perturbative/PerturbativeHiggs__all.cc
+
+##################
+
+pkglib_LTLIBRARIES += HwWeakCurrents.la
+
+HwWeakCurrents_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 9:0:0
+
+HwWeakCurrents_la_SOURCES = \
+WeakCurrents/WeakCurrents__all.cc
+
+##################
+
+pkglib_LTLIBRARIES += HwSMDecay.la
+
+HwSMDecay_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 10:0:0
+
+HwSMDecay_la_SOURCES = \
+ScalarMeson/SMDecayer__all.cc
+
+##################
+
+pkglib_LTLIBRARIES += HwTMDecay.la
+
+HwTMDecay_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 8:0:0
+
+HwTMDecay_la_SOURCES = \
+TensorMeson/TMDecayer__all.cc
+
+##################
+
+pkglib_LTLIBRARIES += HwPartonicDecay.la
+
+HwPartonicDecay_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 9:0:0
+
+HwPartonicDecay_la_SOURCES = \
+Partonic/Partonic__all.cc
+
+##################
+
+pkglib_LTLIBRARIES += HwSOPHTY.la
+
+HwSOPHTY_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 3:0:0
+
+HwSOPHTY_la_SOURCES = \
+Radiation/Sophty__all.cc
+
+##################
diff --git a/Decay/Partonic/HeavyDecayer.h b/Decay/Partonic/HeavyDecayer.h
--- a/Decay/Partonic/HeavyDecayer.h
+++ b/Decay/Partonic/HeavyDecayer.h
@@ -1,179 +1,179 @@
// -*- C++ -*-
//
// HeavyDecayer.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_HeavyDecayer_H
#define HERWIG_HeavyDecayer_H
// This is the declaration of the HeavyDecayer class.
-#include <PartonicDecayerBase.h>
+#include "PartonicDecayerBase.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Decay
*
* This class is designed for the partonic decay of a bottom or charm mesons
* and baryons and is intended to be the same as that in HERWIG6.4.
* Only four body partonic decays are supported.
*
* Two types of matrix element are supported for this decay
*
* - MECode=0 flat phase space
* - MECode=100 V-A matrix element for the heavy quark decay in the spectator model.
*
* The class decays a particle based on the DecayMode given.
* The basic idea is that the heavy parton in the heavy meson will decay
* weakly while the other parton will be more or less unchanged. This produces
* 4 partons, the spectator plus the result of the weak decay. The W then
* decays again into two more partons,
* e.g. a decay of \f$B^0\to d,\bar{c},\bar{d}, u \f$.
*
* \f$\bar{b}\to\bar{c}\f$ (colour connected to spectator)
* and \f$W^+\to\bar{d}u\f$ (the W decay products are colour connected)
*
* The resulting partons then need to be hadronized and decayed again.
*
* @see QuarkoniumDecayer
* @see Hw64Decayer
* @see Decayer
*
*/
class HeavyDecayer: public PartonicDecayerBase {
public:
/**
* Default constructor
*/
HeavyDecayer();
/**
* Check if this decayer can perfom the decay for a particular mode
* @param parent The decaying particle
* @param children The decay products
* @return true If this decayer can handle the given mode, otherwise false.
*/
virtual bool accept(tcPDPtr parent, const tPDVector & children) const;
/**
* Perform the decay of the particle to the specified decay products
* @param parent The decaying particle
* @param children The decay products
* @return a ParticleVector containing the decay products.
*/
virtual ParticleVector decay(const Particle & parent,
const tPDVector & children) const;
/**
* Output the setup information for the particle database
* @param os The stream to output the information to
* @param header Whether or not to output the information for MySQL
*/
virtual void dataBaseOutput(ofstream & os,bool header) const;
public:
/**
* Standard Init function used to initialize the interface.
*/
static void Init();
/** @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);
//@}
/** @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;
//@}
private:
/**
* Weighting of phase space for V-A matrix elements
*/
static double VAWt(Energy2, Energy2, Energy2, InvEnergy4);
private:
/**
* Describe a concrete class with persistent data.
*/
static ClassDescription<HeavyDecayer> initHeavyDecayer;
/**
* Private and non-existent assignment operator.
*/
const HeavyDecayer & operator=(const HeavyDecayer &);
private:
/**
* The code for the matrix element being used.
*/
int MECode;
};
}
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/**
* This template specialization informs ThePEG about the base class of
* HeavyDecayer.
*/
template <>
struct BaseClassTrait<Herwig::HeavyDecayer,1> {
/** Typedef of the base class of HeavyDecayer. */
typedef Herwig::PartonicDecayerBase NthBase;
};
/**
* This template specialization informs ThePEG about the name of the
* HeavyDecayer class.
*/
template <>
struct ClassTraits<Herwig::HeavyDecayer>: public ClassTraitsBase<Herwig::HeavyDecayer> {
/** Return the class name. */
static string className() { return "Herwig::HeavyDecayer"; }
/** Return the name of the shared library to be loaded to get
* access to this class and every other class it uses
* (except the base class).
*/
static string library() { return "HwPartonicDecay.so"; }
};
/** @endcond */
}
#endif /* HERWIG_HeavyDecayer_H */
diff --git a/Decay/Partonic/Makefile.am b/Decay/Partonic/Makefile.am
--- a/Decay/Partonic/Makefile.am
+++ b/Decay/Partonic/Makefile.am
@@ -1,9 +1,21 @@
-pkglib_LTLIBRARIES = HwPartonicDecay.la
-HwPartonicDecay_la_SOURCES = \
-QuarkoniumDecayer.h QuarkoniumDecayer.cc \
-HeavyDecayer.h HeavyDecayer.cc \
-WeakPartonicDecayer.h WeakPartonicDecayer.cc\
-BtoSGammaDecayer.h BtoSGammaDecayer.cc\
-PartonicDecayerBase.h PartonicDecayerBase.cc
+BUILT_SOURCES = Partonic__all.cc
+DISTCLEANFILES = Partonic__all.cc
-HwPartonicDecay_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 9:0:0
+Partonic__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+QuarkoniumDecayer.h \
+HeavyDecayer.h \
+WeakPartonicDecayer.h \
+BtoSGammaDecayer.h \
+PartonicDecayerBase.h
+
+ALL_CC_FILES = \
+QuarkoniumDecayer.cc \
+HeavyDecayer.cc \
+WeakPartonicDecayer.cc\
+BtoSGammaDecayer.cc\
+PartonicDecayerBase.cc
diff --git a/Decay/Partonic/QuarkoniumDecayer.h b/Decay/Partonic/QuarkoniumDecayer.h
--- a/Decay/Partonic/QuarkoniumDecayer.h
+++ b/Decay/Partonic/QuarkoniumDecayer.h
@@ -1,172 +1,172 @@
// -*- C++ -*-
//
// QuarkoniumDecayer.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_QuarkoniumDecayer_H
#define HERWIG_QuarkoniumDecayer_H
//
// This is the declaration of the QuarkoniumDecayer class.
//
-#include <PartonicDecayerBase.h>
+#include "PartonicDecayerBase.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Decay
*
* The QuarkoniumDecayer class is designed for the partonic decay of bottom and charmonium
* resonances. In general it is used for decays of the type:
* - \f$q,\bar{q}\f$ decay to a quark-antiquark pair generally using phase space,
* \e i.e. MECode=0.
*
* - \f$g,g\f$ decay to two gluons normally using phase space,
* \e i.e. MECode=0.
*
* - \f$g,g,g\f$ decay to three gluons, this will normally use the Ore-Powell
* matrix element, \e i.e. MECode=130.
*
* - \f$g,g,\gamma\f$ decay to two gluons and a photon, this will normally use
* the Ore-Powell matrix element, \e i.e. MECode=130.
*
*
* This class supports two values of the MECode variable which can be set using
* the interface
*
* - MECode=0 flat-phase space
* - MECode=130 The Ore-Powell onium matrix element.
*
* This is designed to be the same as the FORTRAN HERWIG routine.
*
* @see HeavyDecayer
* @see Hw64Decayer
* @see Decayer
*
*/
class QuarkoniumDecayer: public PartonicDecayerBase {
public:
/**
* Standard ctors and dtor
*/
QuarkoniumDecayer();
/**
* Check if this decayer can perfom the decay for a particular mode
* @param parent The decaying particle
* @param children The decay products
* @return true If this decayer can handle the given mode, otherwise false.
*/
virtual bool accept(tcPDPtr parent, const tPDVector & children) const;
/**
* Perform the decay of the particle to the specified decay products
* @param parent The decaying particle
* @param children The decay products
* @return a ParticleVector containing the decay products.
*/
virtual ParticleVector decay(const Particle & parent,
const tPDVector & children) const;
/**
* Output the setup information for the particle database
* @param os The stream to output the information to
* @param header Whether or not to output the information for MySQL
*/
virtual void dataBaseOutput(ofstream & os,bool header) const;
public:
/**
* Standard Init function used to initialize the interface.
*/
static void Init();
/**
* Standard Persistent stream methods
*/
void persistentOutput(PersistentOStream &) const;
/**
* Standard Persistent stream methods
*/
void persistentInput(PersistentIStream &, int);
/**
* Standard clone methods
*/
protected:
/**
* Standard clone methods
*/
virtual IBPtr clone() const;
/**
* Standard clone methods
*/
virtual IBPtr fullclone() const;
private:
/**
* Describe a concrete class with persistant decay
*/
static ClassDescription<QuarkoniumDecayer> initQuarkoniumDecayer;
/**
* Private and non-existent assignment operator.
*/
const QuarkoniumDecayer & operator=(const QuarkoniumDecayer &);
private:
/**
* The code for the type of matrix element being used.
*/
int MECode;
};
}
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/**
* This template specialization informs ThePEG about the base class of
* QuarkoniumDecayer.
*/
template <>
struct BaseClassTrait<Herwig::QuarkoniumDecayer,1> {
/** Typedef of the base class of QuarkoniumDecayer. */
typedef Herwig::PartonicDecayerBase NthBase;
};
/**
* This template specialization informs ThePEG about the name of the
* QuarkoniumDecayer class.
*/
template <>
struct ClassTraits<Herwig::QuarkoniumDecayer>:
public ClassTraitsBase<Herwig::QuarkoniumDecayer> {
/** Return the class name. */
static string className() { return "Herwig::QuarkoniumDecayer"; }
/** Return the name of the shared library to be loaded to get
* access to this class and every other class it uses
* (except the base class).
*/
static string library() { return "HwPartonicDecay.so"; }
};
/** @endcond */
}
#endif /* HERWIG_QuarkoniumDecayer_H */
diff --git a/Decay/Perturbative/Makefile.am b/Decay/Perturbative/Makefile.am
--- a/Decay/Perturbative/Makefile.am
+++ b/Decay/Perturbative/Makefile.am
@@ -1,17 +1,48 @@
-pkglib_LTLIBRARIES = HwPerturbativeDecay.la HwPerturbativeHiggsDecay.la
+BUILT_SOURCES = Perturbative__all.cc
+DISTCLEANFILES = Perturbative__all.cc
-HwPerturbativeDecay_la_SOURCES = \
- SMWDecayer.cc SMWDecayer.h\
- SMZDecayer.cc SMZDecayer.h\
- SMTopDecayer.cc SMTopDecayer.h\
- SMTopPOWHEGDecayer.cc SMTopPOWHEGDecayer.h\
- SMZFermionsPOWHEGDecayer.cc SMZFermionsPOWHEGDecayer.h\
- SMWFermionsPOWHEGDecayer.cc SMWFermionsPOWHEGDecayer.h
-HwPerturbativeDecay_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 9:0:0
+Perturbative__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
-HwPerturbativeHiggsDecay_la_SOURCES = \
- SMHiggsFermionsDecayer.cc SMHiggsFermionsDecayer.h \
- SMHiggsFermionsPOWHEGDecayer.cc SMHiggsFermionsPOWHEGDecayer.h \
- SMHiggsGGHiggsPPDecayer.cc SMHiggsGGHiggsPPDecayer.h\
- SMHiggsWWDecayer.cc SMHiggsWWDecayer.h
-HwPerturbativeHiggsDecay_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 9:0:0
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+ SMWDecayer.h\
+ SMZDecayer.h\
+ SMTopDecayer.h\
+ SMTopPOWHEGDecayer.h\
+ SMZFermionsPOWHEGDecayer.h\
+ SMWFermionsPOWHEGDecayer.h
+
+
+ALL_CC_FILES = \
+ SMWDecayer.cc \
+ SMZDecayer.cc \
+ SMTopDecayer.cc \
+ SMTopPOWHEGDecayer.cc \
+ SMZFermionsPOWHEGDecayer.cc \
+ SMWFermionsPOWHEGDecayer.cc
+
+
+
+
+
+BUILT_SOURCES += PerturbativeHiggs__all.cc
+DISTCLEANFILES += PerturbativeHiggs__all.cc
+
+PerturbativeHiggs__all.cc : $(ALL_CC_FILES_2)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST += $(ALL_H_FILES_2) $(ALL_CC_FILES_2)
+
+ALL_H_FILES_2 = \
+ SMHiggsFermionsDecayer.h \
+ SMHiggsFermionsPOWHEGDecayer.h \
+ SMHiggsGGHiggsPPDecayer.h\
+ SMHiggsWWDecayer.h
+
+ALL_CC_FILES_2 = \
+ SMHiggsFermionsDecayer.cc \
+ SMHiggsFermionsPOWHEGDecayer.cc \
+ SMHiggsGGHiggsPPDecayer.cc \
+ SMHiggsWWDecayer.cc
diff --git a/Decay/Perturbative/SMTopDecayer.cc b/Decay/Perturbative/SMTopDecayer.cc
--- a/Decay/Perturbative/SMTopDecayer.cc
+++ b/Decay/Perturbative/SMTopDecayer.cc
@@ -1,1141 +1,1141 @@
// -*- C++ -*-
//
// SMTopDecayer.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 SMTopDecayer class.
//
#include "SMTopDecayer.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/DecayMode.h"
#include "Herwig/Decay/DecayVertex.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "Herwig/PDT/ThreeBodyAllOn1IntegralCalculator.h"
#include "Herwig/Shower/RealEmissionProcess.h"
#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h"
#include "Herwig/Shower/QTilde/Base/ShowerParticle.h"
#include "Herwig/Shower/QTilde/Base/Branching.h"
#include "Herwig/Decay/GeneralDecayMatrixElement.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
SMTopDecayer::SMTopDecayer()
: _wquarkwgt(6,0.),_wleptonwgt(3,0.), _xg_sampling(1.5),
_initialenhance(1.), _finalenhance(2.3), _useMEforT2(true) {
_wleptonwgt[0] = 0.302583;
_wleptonwgt[1] = 0.301024;
_wleptonwgt[2] = 0.299548;
_wquarkwgt[0] = 0.851719;
_wquarkwgt[1] = 0.0450162;
_wquarkwgt[2] = 0.0456962;
_wquarkwgt[3] = 0.859839;
_wquarkwgt[4] = 3.9704e-06;
_wquarkwgt[5] = 0.000489657;
generateIntermediates(true);
}
bool SMTopDecayer::accept(tcPDPtr parent, const tPDVector & children) const {
if(abs(parent->id()) != ParticleID::t) return false;
int id0(0),id1(0),id2(0);
for(tPDVector::const_iterator it = children.begin();
it != children.end();++it) {
int id=(**it).id(),absid(abs(id));
if(absid==ParticleID::b&&double(id)/double(parent->id())>0) {
id0=id;
}
else {
switch (absid) {
case ParticleID::nu_e:
case ParticleID::nu_mu:
case ParticleID::nu_tau:
id1 = id;
break;
case ParticleID::eminus:
case ParticleID::muminus:
case ParticleID::tauminus:
id2 = id;
break;
case ParticleID::b:
case ParticleID::d:
case ParticleID::s:
id1 = id;
break;
case ParticleID::u:
case ParticleID::c:
id2=id;
break;
default :
break;
}
}
}
if(id0==0||id1==0||id2==0) return false;
if(double(id1)/double(id2)>0) return false;
return true;
}
ParticleVector SMTopDecayer::decay(const Particle & parent,
const tPDVector & children) const {
int id1(0),id2(0);
for(tPDVector::const_iterator it = children.begin();
it != children.end();++it) {
int id=(**it).id(),absid=abs(id);
if(absid == ParticleID::b && double(id)/double(parent.id())>0) continue;
//leptons
if(absid > 10 && absid%2==0) id1=absid;
if(absid > 10 && absid%2==1) id2=absid;
//quarks
if(absid < 10 && absid%2==0) id2=absid;
if(absid < 10 && absid%2==1) id1=absid;
}
unsigned int imode(0);
if(id2 >=11 && id2<=16) imode = (id1-12)/2;
else imode = id1+1+id2/2;
bool cc = parent.id() == ParticleID::tbar;
ParticleVector out(generate(true,cc,imode,parent));
//arrange colour flow
PPtr pparent=const_ptr_cast<PPtr>(&parent);
out[1]->incomingColour(pparent,out[1]->id()<0);
ParticleVector products = out[0]->children();
if(products[0]->hasColour())
products[0]->colourNeighbour(products[1],true);
else if(products[0]->hasAntiColour())
products[0]->colourNeighbour(products[1],false);
return out;
}
void SMTopDecayer::persistentOutput(PersistentOStream & os) const {
os << _wvertex << _wquarkwgt << _wleptonwgt << _wplus << _alpha
<< _initialenhance << _finalenhance << _xg_sampling << _useMEforT2;
}
void SMTopDecayer::persistentInput(PersistentIStream & is, int) {
is >> _wvertex >> _wquarkwgt >> _wleptonwgt >> _wplus >> _alpha
>> _initialenhance >> _finalenhance >> _xg_sampling >> _useMEforT2;
}
ClassDescription<SMTopDecayer> SMTopDecayer::initSMTopDecayer;
// Definition of the static class description member.
void SMTopDecayer::Init() {
static ClassDocumentation<SMTopDecayer> documentation
("This is the implementation of the SMTopDecayer which "
"decays top quarks into bottom quarks and either leptons "
"or quark-antiquark pairs including the matrix element for top decay",
"The matrix element correction for top decay \\cite{Hamilton:2006ms}.",
"%\\cite{Hamilton:2006ms}\n"
"\\bibitem{Hamilton:2006ms}\n"
" K.~Hamilton and P.~Richardson,\n"
" ``A simulation of QCD radiation in top quark decays,''\n"
" JHEP {\\bf 0702}, 069 (2007)\n"
" [arXiv:hep-ph/0612236].\n"
" %%CITATION = JHEPA,0702,069;%%\n");
static ParVector<SMTopDecayer,double> interfaceQuarkWeights
("QuarkWeights",
"Maximum weights for the hadronic decays",
&SMTopDecayer::_wquarkwgt, 6, 1.0, 0.0, 10.0,
false, false, Interface::limited);
static ParVector<SMTopDecayer,double> interfaceLeptonWeights
("LeptonWeights",
"Maximum weights for the semi-leptonic decays",
&SMTopDecayer::_wleptonwgt, 3, 1.0, 0.0, 10.0,
false, false, Interface::limited);
static Parameter<SMTopDecayer,double> interfaceEnhancementFactor
("InitialEnhancementFactor",
"The enhancement factor for initial-state radiation in the shower to ensure"
" the weight for the matrix element correction is less than one.",
&SMTopDecayer::_initialenhance, 1.0, 1.0, 10000.0,
false, false, Interface::limited);
static Parameter<SMTopDecayer,double> interfaceFinalEnhancementFactor
("FinalEnhancementFactor",
"The enhancement factor for final-state radiation in the shower to ensure"
" the weight for the matrix element correction is less than one",
&SMTopDecayer::_finalenhance, 1.6, 1.0, 1000.0,
false, false, Interface::limited);
static Parameter<SMTopDecayer,double> interfaceSamplingTopHardMEC
("SamplingTopHardMEC",
"The importance sampling power for choosing an initial xg, "
"to sample xg according to xg^-_xg_sampling",
&SMTopDecayer::_xg_sampling, 1.5, 1.2, 2.0,
false, false, Interface::limited);
static Switch<SMTopDecayer,bool> interfaceUseMEForT2
("UseMEForT2",
"Use the matrix element correction, if available to fill the T2"
" region for the decay shower and don't fill using the shower",
&SMTopDecayer::_useMEforT2, true, false, false);
static SwitchOption interfaceUseMEForT2Shower
(interfaceUseMEForT2,
"Shower",
"Use the shower to fill the T2 region",
false);
static SwitchOption interfaceUseMEForT2ME
(interfaceUseMEForT2,
"ME",
"Use the Matrix element to fill the T2 region",
true);
static Reference<SMTopDecayer,ShowerAlpha> interfaceCoupling
("Coupling",
"Pointer to the object to calculate the coupling for the correction",
&SMTopDecayer::_alpha, false, false, true, false, false);
}
double SMTopDecayer::me2(const int, const Particle & inpart,
const ParticleVector & decay,
MEOption meopt) const {
if(!ME())
ME(new_ptr(GeneralDecayMatrixElement(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half)));
// spinors etc for the decaying particle
if(meopt==Initialize) {
// spinors and rho
if(inpart.id()>0)
SpinorWaveFunction ::calculateWaveFunctions(_inHalf,_rho,
const_ptr_cast<tPPtr>(&inpart),
incoming);
else
SpinorBarWaveFunction::calculateWaveFunctions(_inHalfBar,_rho,
const_ptr_cast<tPPtr>(&inpart),
incoming);
}
// setup spin info when needed
if(meopt==Terminate) {
// for the decaying particle
if(inpart.id()>0) {
SpinorWaveFunction::
constructSpinInfo(_inHalf,const_ptr_cast<tPPtr>(&inpart),incoming,true);
SpinorBarWaveFunction::constructSpinInfo(_inHalfBar,decay[0],outgoing,true);
SpinorWaveFunction ::constructSpinInfo(_outHalf ,decay[1],outgoing,true);
SpinorBarWaveFunction::constructSpinInfo(_outHalfBar,decay[2],outgoing,true);
}
else {
SpinorBarWaveFunction::
constructSpinInfo(_inHalfBar,const_ptr_cast<tPPtr>(&inpart),incoming,true);
SpinorWaveFunction::constructSpinInfo(_inHalf,decay[0],outgoing,true);
SpinorBarWaveFunction::constructSpinInfo(_outHalfBar,decay[1],outgoing,true);
SpinorWaveFunction ::constructSpinInfo(_outHalf ,decay[2],outgoing,true);
}
}
if ( ( decay[1]->momentum() + decay[2]->momentum() ).m()
< decay[1]->data().constituentMass() + decay[2]->data().constituentMass() )
return 0.0;
// spinors for the decay product
if(inpart.id()>0) {
SpinorBarWaveFunction::calculateWaveFunctions(_inHalfBar ,decay[0],outgoing);
SpinorWaveFunction ::calculateWaveFunctions(_outHalf ,decay[1],outgoing);
SpinorBarWaveFunction::calculateWaveFunctions(_outHalfBar,decay[2],outgoing);
}
else {
SpinorWaveFunction ::calculateWaveFunctions(_inHalf ,decay[0],outgoing);
SpinorBarWaveFunction::calculateWaveFunctions(_outHalfBar,decay[1],outgoing);
SpinorWaveFunction ::calculateWaveFunctions(_outHalf ,decay[2],outgoing);
}
Energy2 scale(sqr(inpart.mass()));
if(inpart.id() == ParticleID::t) {
//Define intermediate vector wave-function for Wplus
tcPDPtr Wplus(getParticleData(ParticleID::Wplus));
VectorWaveFunction inter;
unsigned int thel,bhel,fhel,afhel;
for(thel = 0;thel<2;++thel){
for(bhel = 0;bhel<2;++bhel){
inter = _wvertex->evaluate(scale,1,Wplus,_inHalf[thel],
_inHalfBar[bhel]);
for(afhel=0;afhel<2;++afhel){
for(fhel=0;fhel<2;++fhel){
(*ME())(thel,bhel,afhel,fhel) =
_wvertex->evaluate(scale,_outHalf[afhel],
_outHalfBar[fhel],inter);
}
}
}
}
}
else if(inpart.id() == ParticleID::tbar) {
VectorWaveFunction inter;
tcPDPtr Wminus(getParticleData(ParticleID::Wminus));
unsigned int tbhel,bbhel,afhel,fhel;
for(tbhel = 0;tbhel<2;++tbhel){
for(bbhel = 0;bbhel<2;++bbhel){
inter = _wvertex->
evaluate(scale,1,Wminus,_inHalf[bbhel],_inHalfBar[tbhel]);
for(afhel=0;afhel<2;++afhel){
for(fhel=0;fhel<2;++fhel){
(*ME())(tbhel,bbhel,fhel,afhel) =
_wvertex->evaluate(scale,_outHalf[afhel],
_outHalfBar[fhel],inter);
}
}
}
}
}
double output = (ME()->contract(_rho)).real();
if(abs(decay[1]->id())<=6) output *=3.;
return output;
}
void SMTopDecayer::doinit() {
DecayIntegrator::doinit();
//get vertices from SM object
tcHwSMPtr hwsm = dynamic_ptr_cast<tcHwSMPtr>(standardModel());
if(!hwsm) throw InitException() << "Must have Herwig::StandardModel in "
<< "SMTopDecayer::doinit()";
_wvertex = hwsm->vertexFFW();
//initialise
_wvertex->init();
//set up decay modes
_wplus = getParticleData(ParticleID::Wplus);
DecayPhaseSpaceModePtr mode;
DecayPhaseSpaceChannelPtr Wchannel;
tPDVector extpart(4);
vector<double> wgt(1,1.0);
extpart[0] = getParticleData(ParticleID::t);
extpart[1] = getParticleData(ParticleID::b);
//lepton modes
for(int i=11; i<17;i+=2) {
extpart[2] = getParticleData(-i);
extpart[3] = getParticleData(i+1);
mode = new_ptr(DecayPhaseSpaceMode(extpart,this));
Wchannel = new_ptr(DecayPhaseSpaceChannel(mode));
Wchannel->addIntermediate(extpart[0],0,0.0,-1,1);
Wchannel->addIntermediate(_wplus,0,0.0,2,3);
Wchannel->init();
mode->addChannel(Wchannel);
addMode(mode,_wleptonwgt[(i-11)/2],wgt);
}
//quark modes
unsigned int iz=0;
for(int ix=1;ix<6;ix+=2) {
for(int iy=2;iy<6;iy+=2) {
// check that the combination of particles is allowed
if(_wvertex->allowed(-ix,iy,ParticleID::Wminus)) {
extpart[2] = getParticleData(-ix);
extpart[3] = getParticleData( iy);
mode = new_ptr(DecayPhaseSpaceMode(extpart,this));
Wchannel = new_ptr(DecayPhaseSpaceChannel(mode));
Wchannel->addIntermediate(extpart[0],0,0.0,-1,1);
Wchannel->addIntermediate(_wplus,0,0.0,2,3);
Wchannel->init();
mode->addChannel(Wchannel);
addMode(mode,_wquarkwgt[iz],wgt);
++iz;
}
else {
throw InitException() << "SMTopDecayer::doinit() the W vertex"
<< "cannot handle all the quark modes"
<< Exception::abortnow;
}
}
}
}
void SMTopDecayer::dataBaseOutput(ofstream & os,bool header) const {
if(header) os << "update decayers set parameters=\"";
// parameters for the DecayIntegrator base class
for(unsigned int ix=0;ix<_wquarkwgt.size();++ix) {
os << "newdef " << name() << ":QuarkWeights " << ix << " "
<< _wquarkwgt[ix] << "\n";
}
for(unsigned int ix=0;ix<_wleptonwgt.size();++ix) {
os << "newdef " << name() << ":LeptonWeights " << ix << " "
<< _wleptonwgt[ix] << "\n";
}
DecayIntegrator::dataBaseOutput(os,false);
if(header) os << "\n\" where BINARY ThePEGName=\"" << fullName() << "\";" << endl;
}
void SMTopDecayer::doinitrun() {
DecayIntegrator::doinitrun();
if(initialize()) {
for(unsigned int ix=0;ix<numberModes();++ix) {
if(ix<3) _wleptonwgt[ix ] = mode(ix)->maxWeight();
else _wquarkwgt [ix-3] = mode(ix)->maxWeight();
}
}
}
WidthCalculatorBasePtr SMTopDecayer::threeBodyMEIntegrator(const DecayMode & dm) const {
// identify W decay products
int sign = dm.parent()->id() > 0 ? 1 : -1;
int iferm(0),ianti(0);
for(ParticleMSet::const_iterator pit=dm.products().begin();
pit!=dm.products().end();++pit) {
int id = (**pit).id();
if(id*sign != ParticleID::b) {
if (id*sign > 0 ) iferm = id*sign;
else ianti = id*sign;
}
}
assert(iferm!=0&&ianti!=0);
// work out which mode we are doing
int imode(-1);
for(unsigned int ix=0;ix<numberModes();++ix) {
if(mode(ix)->externalParticles(2)->id() == ianti &&
mode(ix)->externalParticles(3)->id() == iferm ) {
imode = ix;
break;
}
}
assert(imode>=0);
// get the masses we need
Energy m[3] = {mode(imode)->externalParticles(1)->mass(),
mode(imode)->externalParticles(3)->mass(),
mode(imode)->externalParticles(2)->mass()};
return
new_ptr(ThreeBodyAllOn1IntegralCalculator<SMTopDecayer>
(3,_wplus->mass(),_wplus->width(),0.0,*this,imode,m[0],m[1],m[2]));
}
InvEnergy SMTopDecayer::threeBodydGammads(const int imode, const Energy2 mt2,
const Energy2 mffb2, const Energy mb,
const Energy mf, const Energy mfb) const {
Energy mffb(sqrt(mffb2));
Energy mw(_wplus->mass());
Energy2 mw2(sqr(mw)),gw2(sqr(_wplus->width()));
Energy mt(sqrt(mt2));
Energy Eb = 0.5*(mt2-mffb2-sqr(mb))/mffb;
Energy Ef = 0.5*(mffb2-sqr(mfb)+sqr(mf))/mffb;
Energy Ebm = sqrt(sqr(Eb)-sqr(mb));
Energy Efm = sqrt(sqr(Ef)-sqr(mf));
Energy2 upp = sqr(Eb+Ef)-sqr(Ebm-Efm);
Energy2 low = sqr(Eb+Ef)-sqr(Ebm+Efm);
InvEnergy width=(dGammaIntegrand(mffb2,upp,mt,mb,mf,mfb,mw)-
dGammaIntegrand(mffb2,low,mt,mb,mf,mfb,mw))
/32./mt2/mt/8/pow(Constants::pi,3)/(sqr(mffb2-mw2)+mw2*gw2);
// couplings
width *= 0.25*sqr(4.*Constants::pi*generator()->standardModel()->alphaEM(mt2)/
generator()->standardModel()->sin2ThetaW());
width *= generator()->standardModel()->CKM(*mode(imode)->externalParticles(0),
*mode(imode)->externalParticles(1));
if(abs(mode(imode)->externalParticles(2)->id())<=6) {
width *=3.;
if(abs(mode(imode)->externalParticles(2)->id())%2==0)
width *=generator()->standardModel()->CKM(*mode(imode)->externalParticles(2),
*mode(imode)->externalParticles(3));
else
width *=generator()->standardModel()->CKM(*mode(imode)->externalParticles(3),
*mode(imode)->externalParticles(2));
}
// final spin average
- assert(!isnan(width*GeV));
+ assert(!std::isnan(double(width*MeV)));
return 0.5*width;
}
Energy6 SMTopDecayer::dGammaIntegrand(Energy2 mffb2, Energy2 mbf2, Energy mt,
Energy mb, Energy mf, Energy mfb, Energy mw) const {
Energy2 mt2(sqr(mt)) ,mb2(sqr(mb)) ,mf2(sqr(mf )),mfb2(sqr(mfb )),mw2(sqr(mw ));
Energy4 mt4(sqr(mt2)),mb4(sqr(mb2)),mf4(sqr(mf2)),mfb4(sqr(mfb2)),mw4(sqr(mw2));
return -mbf2 * ( + 6 * mb2 * mf2 * mfb2 * mffb2 + 6 * mb2 * mt2 * mfb2 * mffb2
+ 6 * mb2 * mt2 * mf2 * mffb2 + 12 * mb2 * mt2 * mf2 * mfb2
- 3 * mb2 * mfb4 * mffb2 + 3 * mb2 * mf2 * mffb2 * mffb2
- 3 * mb2 * mf4 * mffb2 - 6 * mb2 * mt2 * mfb4
- 6 * mb2 * mt2 * mf4 - 3 * mb4 * mfb2 * mffb2
- 3 * mb4 * mf2 * mffb2 - 6 * mb4 * mf2 * mfb2
+ 3 * mt4 * mf4 + 3 * mb4 * mfb4
+ 3 * mb4 * mf4 + 3 * mt4 * mfb4
+ 3 * mb2 * mfb2 * mffb2 * mffb2 + 3 * mt2 * mfb2 * mffb2 * mffb2
- 3 * mt2 * mfb4 * mffb2 + 3 * mt2 * mf2 * mffb2 * mffb2
- 3 * mt2 * mf4 * mffb2 - 3 * mt4 * mfb2 * mffb2
- 3 * mt4 * mf2 * mffb2 - 6 * mt4 * mf2 * mfb2
+ 6 * mt2 * mf2 * mfb2 * mffb2 + 12 * mt2 * mf2 * mw4
+ 12 * mb2 * mfb2 * mw4 + 12 * mb2 * mt2 * mw4
+ 6 * mw2 * mt2 * mfb2 * mbf2 - 12 * mw2 * mt2 * mf2 * mffb2
- 6 * mw2 * mt2 * mf2 * mbf2 - 12 * mw2 * mt2 * mf2 * mfb2
- 12 * mw2 * mb2 * mfb2 * mffb2 - 6 * mw2 * mb2 * mfb2 * mbf2
+ 6 * mw2 * mb2 * mf2 * mbf2 - 12 * mw2 * mb2 * mf2 * mfb2
- 12 * mw2 * mb2 * mt2 * mfb2 - 12 * mw2 * mb2 * mt2 * mf2
+ 12 * mf2 * mfb2 * mw4 + 4 * mbf2 * mbf2 * mw4
- 6 * mfb2 * mbf2 * mw4 - 6 * mf2 * mbf2 * mw4
- 6 * mt2 * mbf2 * mw4 - 6 * mb2 * mbf2 * mw4
+ 12 * mw2 * mt2 * mf4 + 12 * mw2 * mt4 * mf2
+ 12 * mw2 * mb2 * mfb4 + 12 * mw2 * mb4 * mfb2) /mw4 / 3.;
}
void SMTopDecayer::initializeMECorrection(RealEmissionProcessPtr born, double & initial,
double & final) {
// check the outgoing particles
PPtr part[2];
for(unsigned int ix=0;ix<born->bornOutgoing().size();++ix) {
part[ix]= born->bornOutgoing()[ix];
}
// check the final-state particles and get the masses
if(abs(part[0]->id())==ParticleID::Wplus&&abs(part[1]->id())==ParticleID::b) {
_ma=part[0]->mass();
_mc=part[1]->mass();
}
else if(abs(part[1]->id())==ParticleID::Wplus&&abs(part[0]->id())==ParticleID::b) {
_ma=part[1]->mass();
_mc=part[0]->mass();
}
else {
return;
}
// set the top mass
_mt=born->bornIncoming()[0]->mass();
// set the gluon mass
_mg=getParticleData(ParticleID::g)->constituentMass();
// set the radiation enhancement factors
initial = _initialenhance;
final = _finalenhance;
// reduced mass parameters
_a=sqr(_ma/_mt);
_g=sqr(_mg/_mt);
_c=sqr(_mc/_mt);
double lambda = sqrt(1.+sqr(_a)+sqr(_c)-2.*_a-2.*_c-2.*_a*_c);
_ktb = 0.5*(3.-_a+_c+lambda);
_ktc = 0.5*(1.-_a+3.*_c+lambda);
useMe();
}
RealEmissionProcessPtr SMTopDecayer::applyHardMatrixElementCorrection(RealEmissionProcessPtr born) {
// Get b and a and put them in particle vector ba in that order...
ParticleVector ba;
for(unsigned int ix=0;ix<born->bornOutgoing().size();++ix)
ba.push_back(born->bornOutgoing()[ix]);
if(abs(ba[0]->id())!=5) swap(ba[0],ba[1]);
assert(born->bornIncoming().size()==1);
// Now decide if we get an emission into the dead region.
// If there is an emission newfs stores momenta for a,c,g
// according to NLO decay matrix element.
vector<Lorentz5Momentum> newfs = applyHard(ba,_ktb,_ktc);
// If there was no gluon emitted return.
if(newfs.size()!=3) return RealEmissionProcessPtr();
// Sanity checks to ensure energy greater than mass etc :)
bool check = true;
tcPDPtr gluondata=getParticleData(ParticleID::g);
if (newfs[0].e()<ba[0]->data().constituentMass()) check = false;
if (newfs[1].e()<ba[1]->mass()) check = false;
if (newfs[2].e()<gluondata->constituentMass()) check = false;
// Return if insane:
if (!check) return RealEmissionProcessPtr();
// // Set masses in 5-vectors:
newfs[0].setMass(ba[0]->mass());
newfs[1].setMass(ba[1]->mass());
newfs[2].setMass(ZERO);
// The next part of this routine sets the colour structure.
// To do this for decays we assume that the gluon comes from c!
// First create new particle objects for c, a and gluon:
PPtr newg = gluondata->produceParticle(newfs[2]);
PPtr newc = ba[0]->data().produceParticle(newfs[0]);
PPtr newa = ba[1]->data().produceParticle(newfs[1]);
born->spectator(0);
born->emitted(3);
// decaying particle
born->incoming().push_back(born->bornIncoming()[0]->dataPtr()->
produceParticle(born->bornIncoming()[0]->momentum()));
// colour flow
newg->incomingColour(born->incoming()[0],ba[0]->id()<0);
newg->colourConnect(newc ,ba[0]->id()<0);
if(born->bornOutgoing()[0]->id()==newc->id()) {
born->outgoing().push_back(newc);
born->outgoing().push_back(newa);
born->emitter(1);
}
else {
born->outgoing().push_back(newa);
born->outgoing().push_back(newc);
born->emitter(2);
}
born->outgoing().push_back(newg);
// boost for the W
LorentzRotation trans(ba[1]->momentum().findBoostToCM());
trans.boost(newfs[1].boostVector());
born->transformation(trans);
if(!inTheDeadRegion(_xg,_xa,_ktb,_ktc)) {
generator()->log()
<< "SMTopDecayer::applyHardMatrixElementCorrection()\n"
<< "Just found a point that escaped from the dead region!\n"
<< " _xg: " << _xg << " _xa: " << _xa
<< " newfs.size(): " << newfs.size() << endl;
}
born->interaction(ShowerInteraction::QCD);
return born;
}
vector<Lorentz5Momentum> SMTopDecayer::
applyHard(const ParticleVector &p,double ktb, double ktc) {
// ********************************* //
// First we see if we get a dead //
// region event: _xa,_xg //
// ********************************* //
vector<Lorentz5Momentum> fs;
// Return if there is no (NLO) gluon emission:
double weight = getHard(ktb,ktc);
if(weight>1.) {
generator()->log() << "Weight greater than 1 for hard emission in "
<< "SMTopDecayer::applyHard xg = " << _xg
<< " xa = " << _xa << "\n";
weight=1.;
}
// Accept/Reject
if (weight<UseRandom::rnd()||p.size()!= 2) return fs;
// Drop events if getHard returned a negative weight
// as in events that, somehow have escaped from the dead region
// or, worse, the allowed region.
if(weight<0.) return fs;
// Calculate xc by momentum conservation:
_xc = 2.-_xa-_xg;
// ************************************ //
// Now we get the boosts & rotations to //
// go from lab to top rest frame with //
// a in the +z direction. //
// ************************************ //
Lorentz5Momentum pa_lab,pb_lab,pc_lab,pg_lab;
// Calculate momentum of b:
pb_lab = p[0]->momentum() + p[1]->momentum();
// Define/assign momenta of c,a and the gluon:
if(abs(p[0]->id())==5) {
pc_lab = p[0]->momentum();
pa_lab = p[1]->momentum();
} else {
pc_lab = p[1]->momentum();
pa_lab = p[0]->momentum();
}
// Calculate the boost to the b rest frame:
SpinOneLorentzRotation rot0(pb_lab.findBoostToCM());
// Calculate the rotation matrix to position a along the +z direction
// in the rest frame of b and does a random rotation about z:
SpinOneLorentzRotation rot1 = rotateToZ(rot0*pa_lab);
// Calculate the boost from the b rest frame back to the lab:
// and the inverse of the random rotation about the z-axis and the
// rotation required to align a with +z:
SpinOneLorentzRotation invrot = rot0.inverse()*rot1.inverse();
// ************************************ //
// Now we construct the momenta in the //
// b rest frame using _xa,_xg. //
// First we construct b, then c and g, //
// finally we generate a by momentum //
// conservation. //
// ************************************ //
Lorentz5Momentum pa_brf, pb_brf(_mt), pc_brf, pg_brf;
// First we set the top quark to being on-shell and at rest.
// Second we set the energies of c and g,
pc_brf.setE(0.5*_mt*(2.-_xa-_xg));
pg_brf.setE(0.5*_mt*_xg);
// then their masses,
pc_brf.setMass(_mc);
pg_brf.setMass(ZERO);
// Now set the z-component of c and g. For pg we simply start from
// _xa and _xg, while for pc we assume it is equal to minus the sum
// of the z-components of a (assumed to point in the +z direction) and g.
double root=sqrt(_xa*_xa-4.*_a);
pg_brf.setZ(_mt*(1.-_xa-_xg+0.5*_xa*_xg-_c+_a)/root);
pc_brf.setZ(-1.*( pg_brf.z()+_mt*0.5*root));
// Now set the y-component of c and g's momenta
pc_brf.setY(ZERO);
pg_brf.setY(ZERO);
// Now set the x-component of c and g's momenta
pg_brf.setX(sqrt(sqr(pg_brf.t())-sqr(pg_brf.z())));
pc_brf.setX(-pg_brf.x());
// Momenta b,c,g are now set. Now we obtain a from momentum conservation,
pa_brf = pb_brf-pc_brf-pg_brf;
pa_brf.setMass(pa_brf.m());
pa_brf.rescaleEnergy();
// ************************************ //
// Now we orient the momenta and boost //
// them back to the original lab frame. //
// ************************************ //
// As in herwig6507 we assume that, in the rest frame
// of b, we have aligned the W boson momentum in the
// +Z direction by rot1*rot0*pa_lab, therefore
// we obtain the new pa_lab by applying:
// invrot*pa_brf.
pa_lab = invrot*pa_brf;
pb_lab = invrot*pb_brf;
pc_lab = invrot*pc_brf;
pg_lab = invrot*pg_brf;
fs.push_back(pc_lab);
fs.push_back(pa_lab);
fs.push_back(pg_lab);
return fs;
}
double SMTopDecayer::getHard(double ktb, double ktc) {
// zero the variables
_xg = 0.;
_xa = 0.;
_xc = 0.;
// Get a phase space point in the dead region:
double volume_factor = deadRegionxgxa(ktb,ktc);
// if outside region return -1
if(volume_factor<0) return volume_factor;
// Compute the weight for this phase space point:
double weight = volume_factor*me(_xa,_xg)*(1.+_a-_c-_xa);
// Alpha_S and colour factors - this hard wired Alpha_S needs removing.
weight *= (4./3.)/Constants::pi
*(_alpha->value(_mt*_mt*_xg*(1.-_xa+_a-_c)
/(2.-_xg-_xa-_c)));
return weight;
}
bool SMTopDecayer::softMatrixElementVeto(ShowerProgenitorPtr initial,
ShowerParticlePtr parent,Branching br) {
// check if we need to apply the full correction
long id[2]={abs(initial->progenitor()->id()),abs(parent->id())};
// the initial-state correction
if(id[0]==ParticleID::t&&id[1]==ParticleID::t) {
Energy pt=br.kinematics->pT();
// check if hardest so far
// if not just need to remove effect of enhancement
bool veto(false);
// if not hardest so far
if(pt<initial->highestpT())
veto=!UseRandom::rndbool(1./_initialenhance);
// if hardest so far do calculation
else {
// values of kappa and z
double z(br.kinematics->z()),kappa(sqr(br.kinematics->scale()/_mt));
// parameters for the translation
double w(1.-(1.-z)*(kappa-1.)),u(1.+_a-_c-(1.-z)*kappa),v(sqr(u)-4.*_a*w*z);
// veto if outside phase space
if(v<0.)
veto=true;
// otherwise calculate the weight
else {
v = sqrt(v);
double xa((0.5*(u+v)/w+0.5*(u-v)/z)),xg((1.-z)*kappa);
double f(me(xa,xg)),
J(0.5*(u+v)/sqr(w)-0.5*(u-v)/sqr(z)+_a*sqr(w-z)/(v*w*z));
double wgt(f*J*2./kappa/(1.+sqr(z)-2.*z/kappa)/_initialenhance);
// This next `if' prevents the hardest emission from the
// top shower ever entering the so-called T2 region of the
// phase space if that region is to be populated by the hard MEC.
if(_useMEforT2&&xg>xgbcut(_ktb)) wgt = 0.;
if(wgt>1.) {
generator()->log() << "Violation of maximum for initial-state "
<< " soft veto in "
<< "SMTopDecayer::softMatrixElementVeto"
<< "xg = " << xg << " xa = " << xa
<< "weight = " << wgt << "\n";
wgt=1.;
}
// compute veto from weight
veto = !UseRandom::rndbool(wgt);
}
// if not vetoed reset max
if(!veto) initial->highestpT(pt);
}
// if vetoing reset the scale
if(veto) parent->vetoEmission(br.type,br.kinematics->scale());
// return the veto
return veto;
}
// final-state correction
else if(id[0]==ParticleID::b&&id[1]==ParticleID::b) {
Energy pt=br.kinematics->pT();
// check if hardest so far
// if not just need to remove effect of enhancement
bool veto(false);
// if not hardest so far
if(pt<initial->highestpT()) return !UseRandom::rndbool(1./_finalenhance);
// if hardest so far do calculation
// values of kappa and z
double z(br.kinematics->z()),kappa(sqr(br.kinematics->scale()/_mt));
// momentum fractions
double xa(1.+_a-_c-z*(1.-z)*kappa),r(0.5*(1.+_c/(1.+_a-xa))),root(sqr(xa)-4.*_a);
if(root<0.) {
generator()->log() << "Imaginary root for final-state veto in "
<< "SMTopDecayer::softMatrixElementVeto"
<< "\nz = " << z << "\nkappa = " << kappa
<< "\nxa = " << xa
<< "\nroot^2= " << root;
parent->vetoEmission(br.type,br.kinematics->scale());
return true;
}
root=sqrt(root);
double xg((2.-xa)*(1.-r)-(z-r)*root);
// xfact (below) is supposed to equal xg/(1-z).
double xfact(z*kappa/2./(z*(1.-z)*kappa+_c)*(2.-xa-root)+root);
// calculate the full result
double f(me(xa,xg));
// jacobian
double J(z*root);
double wgt(f*J*2.*kappa/(1.+sqr(z)-2.*_c/kappa/z)/sqr(xfact)/_finalenhance);
if(wgt>1.) {
generator()->log() << "Violation of maximum for final-state soft veto in "
<< "SMTopDecayer::softMatrixElementVeto"
<< "xg = " << xg << " xa = " << xa
<< "weight = " << wgt << "\n";
wgt=1.;
}
// compute veto from weight
veto = !UseRandom::rndbool(wgt);
// if vetoing reset the scale
if(veto) parent->vetoEmission(br.type,br.kinematics->scale());
// return the veto
return veto;
}
// otherwise don't veto
else return !UseRandom::rndbool(1./_finalenhance);
}
double SMTopDecayer::me(double xw,double xg) {
double prop(1.+_a-_c-xw),xg2(sqr(xg));
double lambda=sqrt(1.+_a*_a+_c*_c-2.*_a-2.*_c-2.*_a*_c);
double denom=(1.-2*_a*_a+_a+_c*_a+_c*_c-2.*_c);
double wgt=-_c*xg2/prop+(1.-_a+_c)*xg-(prop*(1 - xg)+xg2)
+(0.5*(1.+2.*_a+_c)*sqr(prop-xg)*xg+2.*_a*prop*xg2)/denom;
return wgt/(lambda*prop);
}
// This function is auxiliary to the xab function.
double SMTopDecayer::xgbr(int toggle) {
return 1.+toggle*sqrt(_a)-_c*(1.-toggle*sqrt(_a))/(1.-_a);
}
// This function is auxiliary to the xab function.
double SMTopDecayer::ktr(double xgb, int toggle) {
return 2.*xgb/
(xgb+toggle*sqrt((1.-1./_a)
*(xgb-xgbr( 1))
*(xgb-xgbr(-1))));
}
// Function xab determines xa (2*W energy fraction) for a given value
// of xg (2*gluon energy fraction) and kappa tilde (q tilde squared over
// m_top squared). Hence this function allows you to draw 1: the total
// phase space volume in the xa vs xg plane 2: for a given value of
// kappa tilde (i.e. starting evolution scale) the associated contour
// in the xa vs xg plane (and hence the regions that either shower can
// populate). This calculation is done assuming the emission came from
// the top quark i.e. kappa tilde here is the q tilde squared of the TOP
// quark divided by m_top squared.
double SMTopDecayer::xab(double xgb, double kt, int toggle) {
double xab;
if(toggle==2) {
// This applies for g==0.&&kt==ktr(a,c,0.,xgb,1).
xab = -2.*_a*(xgb-2.)/(1.+_a-_c-xgb);
} else if(toggle==1) {
// This applies for kt==1&&g==0.
double lambda = sqrt(sqr(xgb-1.+_a+_c)-4.*_a*_c);
xab = (0.5/(kt-xgb))*(kt*(1.+_a-_c-xgb)-lambda)
+ (0.5/(kt+xgb*(1.-kt)))*(kt*(1.+_a-_c-xgb)+lambda);
} else {
// This is the form of xab FOR _g=0.
double ktmktrpktmktrm = kt*kt - 4.*_a*(kt-1.)*xgb*xgb
/ (sqr(1.-_a-_c-xgb)-4.*_a*_c);
if(fabs(kt-(2.*xgb-2.*_g)/(xgb-sqrt(xgb*xgb-4.*_g)))/kt>1.e-6) {
double lambda = sqrt((sqr(1.-_a-_c-xgb)-4.*_a*_c)*ktmktrpktmktrm);
xab = (0.5/(kt-xgb))*(kt*(1.+_a-_c-xgb)-lambda)
+ (0.5/(kt+xgb*(1.-kt)))*(kt*(1.+_a-_c-xgb)+lambda);
}
else {
// This is the value of xa as a function of xb when kt->infinity.
// Where we take any kt > (2.*xgb-2.*_g)/(xgb-sqrt(xgb*xgb-4.*_g))
// as being effectively infinite. This kt value is actually the
// maximum allowed value kt can have if the phase space is calculated
// without the approximation of _g=0 (massless gluon). This formula
// for xab below is then valid for _g=0 AND kt=infinity only.
xab = ( 2.*_c+_a*(xgb-2.)
+ 3.*xgb
- xgb*(_c+xgb+sqrt(_a*_a-2.*(_c-xgb+1.)*_a+sqr(_c+xgb-1.)))
- 2.
)/2./(xgb-1.);
}
}
- if(isnan(xab)) {
+ if(std::isnan(xab)) {
double ktmktrpktmktrm = ( sqr(xgb*kt-2.*(xgb-_g))
-kt*kt*(1.-1./_a)*(xgb-xgbr( 1)-_g/(1.+sqrt(_a)))
*(xgb-xgbr(-1)-_g/(1.-sqrt(_a)))
)/
(xgb*xgb-(1.-1./_a)*(xgb-xgbr( 1)-_g/(1.+sqrt(_a)))
*(xgb-xgbr(-1)-_g/(1.-sqrt(_a)))
);
double lambda = sqrt((xgb-1.+sqr(sqrt(_a)+sqrt(_c-_g)))
*(xgb-1.+sqr(sqrt(_a)-sqrt(_c-_g)))*
ktmktrpktmktrm);
xab = (0.5/(kt-xgb+_g))*(kt*(1.+_a-_c+_g-xgb)-lambda)
+ (0.5/(kt+xgb*(1.-kt)-_g))*(kt*(1.+_a-_c+_g-xgb)+lambda);
- if(isnan(xab))
+ if(std::isnan(xab))
throw Exception() << "TopMECorrection::xab complex x_a value.\n"
<< " xgb = " << xgb << "\n"
<< " xab = " << xab << "\n"
<< " toggle = " << toggle << "\n"
<< " ktmktrpktmktrm = " << ktmktrpktmktrm
<< Exception::eventerror;
}
return xab;
}
// xgbcut is the point along the xg axis where the upper bound on the
// top quark (i.e. b) emission phase space goes back on itself in the
// xa vs xg plane i.e. roughly mid-way along the xg axis in
// the xa vs xg Dalitz plot.
double SMTopDecayer::xgbcut(double kt) {
double lambda2 = 1.+_a*_a+_c*_c-2.*_a-2.*_c-2.*_a*_c;
double num1 = kt*kt*(1.-_a-_c);
double num2 = 2.*kt*sqrt(_a*(kt*kt*_c+lambda2*(kt-1.)));
return (num1-num2)/(kt*kt-4.*_a*(kt-1.));
}
double SMTopDecayer::xaccut(double kt) {
return 1.+_a-_c-0.25*kt;
}
double SMTopDecayer::z(double xac, double kt,
int toggle1, int toggle2) {
double z = -1.0;
if(toggle2==0) {
z = (kt+toggle1*sqrt(kt*(kt-4.*(1.+_a-_c-xac))))/(2.*kt);
} else if(toggle2==1) {
z = ((1.+_a+_c-xac)+toggle1*(1.+_a-_c-xac))
/(2.*(1.+_a-xac));
} else if(toggle2==2) {
z = 0.5;
} else {
throw Exception() << "Cannot determine z in SMTopDecayer::z()"
<< Exception::eventerror;
}
return z;
}
double SMTopDecayer::xgc(double xac, double kt,
int toggle1, int toggle2) {
double tiny(1.e-6);
double xaToMinBoundary(xac*xac-4.*_a);
if(xaToMinBoundary<0) {
if(fabs(xaToMinBoundary/(1.-_a)/(1.-_a))<tiny)
xaToMinBoundary *= -1.;
else
throw Exception() << "SMTopDecayer::xgc xa not in phase space!"
<< Exception::eventerror;
}
return (2.-xac)*(1.-0.5*(1.+_c/(1.+_a-xac)))
-(z(xac,kt,toggle1,toggle2)-0.5*(1.+_c/(1.+_a-xac)))
*sqrt(xaToMinBoundary);
}
double SMTopDecayer::xginvc0(double xg , double kt) {
// The function xg(kappa_tilde_c,xa) surely, enough, draws a
// line of constant kappa_tilde_c in the xg, xa Dalitz plot.
// Such a function can therefore draw the upper and lower
// edges of the phase space for emission from c (the b-quark).
// However, to sample the soft part of the dead zone effectively
// we want to generate a value of xg first and THEN distribute
// xa in the associated allowed part of the dead zone. Hence, the
// function we want, to define the dead zone in xa for a given
// xg, is the inverse of xg(kappa_tilde_c,xa). The full expression
// for xg(kappa_tilde_c,xa) is complicated and, sure enough,
// does not invert. Therefore we try to overestimate the size
// of the dead zone initially, rejecting events which do not
// fall exactly inside it afterwards, with the immediate aim
// of getting an approximate version of xg(kappa_tilde_c,xa)
// that can be inverted. We do this by simply setting c=0 i.e.
// the b-quark mass to zero (and the gluon mass of course), in
// the full expression xg(...). The result of inverting this
// function is the output of this routine (a value of xa) hence
// the name xginvc0. xginvc0 is calculated to be,
// xginvc0 = (1./3.)*(1.+a+pow((U+sqrt(4.*V*V*V+U*U))/2.,1./3.)
// -V*pow(2./(U+sqrt(4.*V*V*V+U*U)),1./3.)
// )
// U = 2.*a*a*a - 66.*a*a + 9.*a*kt*xg + 18.*a*kt
// - 66.*a + 27.*kt*xg*xg - 45.*kt*xg +18.*kt +2. ;
// V = -1.-a*a-14.*a-3.kt*xg+3.*kt;
// This function, as with many functions in this ME correction,
// is plagued by cuts that have to handled carefully in numerical
// implementation. We have analysed the cuts and hence we implement
// it in the following way, with a series of 'if' statements.
//
// A useful -definition- to know in deriving the v<0 terms is
// that tanh^-1(z) = 0.5*(log(1.+z)-log(1.-z)).
double u,v,output;
u = 2.*_a*_a*_a-66.*_a*_a
+9.*xg*kt*_a+18.*kt*_a
-66.*_a+27.*xg*xg*kt
-45.*xg*kt+18.*kt+2.;
v = -_a*_a-14.*_a-3.*xg*kt+3.*kt-1.;
double u2=u*u,v3=v*v*v;
if(v<0.) {
if(u>0.&&(4.*v3+u2)<0.) output = cos( atan(sqrt(-4.*v3-u2)/u)/3.);
else if(u>0.&&(4.*v3+u2)>0.) output = cosh(atanh(sqrt( 4.*v3+u2)/u)/3.);
else output = cos(( atan(sqrt(-4.*v3-u2)/u)
+Constants::pi)/3.);
output *= 2.*sqrt(-v);
} else {
output = sinh(log((u+sqrt(4.*v3+u2))/(2.*sqrt(v3)))/3.);
output *= 2.*sqrt(v);
}
- if(isnan(output)||isinf(output)) {
+ if(!isfinite(output)) {
throw Exception() << "TopMECorrection::xginvc0:\n"
<< "possible numerical instability detected.\n"
<< "\n v = " << v << " u = " << u << "\n4.*v3+u2 = " << 4.*v3+u2
<< "\n_a = " << _a << " ma = " << sqrt(_a*_mt*_mt/GeV2)
<< "\n_c = " << _c << " mc = " << sqrt(_c*_mt*_mt/GeV2)
<< "\n_g = " << _g << " mg = " << sqrt(_g*_mt*_mt/GeV2)
<< Exception::eventerror;
}
return ( 1.+_a +output)/3.;
}
double SMTopDecayer::approxDeadMaxxa(double xg,double ktb,double ktc) {
double maxxa(0.);
double x = min(xginvc0(xg,ktc),
xab(xg,(2.*xg-2.*_g)/(xg-sqrt(xg*xg-4.*_g)),0));
double y(-9999999999.);
if(xg>2.*sqrt(_g)&&xg<=xgbcut(ktb)) {
y = max(xab(xg,ktb,0),xab(xg,1.,1));
} else if(xg>=xgbcut(ktb)&&xg<=1.-sqr(sqrt(_a)+sqrt(_c))) {
y = max(xab(xg,ktr(xg,1),2),xab(xg,1.,1));
}
if(xg>2.*sqrt(_g)&&xg<=1.-sqr(sqrt(_a)+sqrt(_c))) {
if(x>=y) { maxxa = x ; }
else { maxxa = -9999999.; }
} else {
maxxa = -9999999.;
}
return maxxa;
}
double SMTopDecayer::approxDeadMinxa(double xg,double ktb,double ktc) {
double minxa(0.);
double x = min(xginvc0(xg,ktc),
xab(xg,(2.*xg-2.*_g)/(xg-sqrt(xg*xg-4.*_g)),0));
double y(-9999999999.);
if(xg>2.*sqrt(_g)&&xg<=xgbcut(ktb)) {
y = max(xab(xg,ktb,0),xab(xg,1.,1));
} else if(xg>=xgbcut(ktb)&&xg<=1.-sqr(sqrt(_a)+sqrt(_c))) {
if(_useMEforT2) y = xab(xg,1.,1);
else y = max(xab(xg,ktr(xg,1),2),xab(xg,1.,1));
}
if(xg>2.*sqrt(_g)&&xg<=1.-sqr(sqrt(_a)+sqrt(_c))) {
if(x>=y) { minxa = y ; }
else { minxa = 9999999.; }
} else {
minxa = 9999999.;
}
return minxa;
}
// This function returns true if the phase space point (xg,xa) is in the
// kinematically allowed phase space.
bool SMTopDecayer::inTheAllowedRegion(double xg , double xa) {
bool output(true);
if(xg<2.*sqrt(_g)||xg>1.-sqr(sqrt(_a)+sqrt(_c))) output = false;
if(xa<xab(xg,1.,1)) output = false;
if(xa>xab(xg,(2.*xg-2.*_g)/(xg-sqrt(xg*xg-4.*_g)),0)) output = false;
return output;
}
// This function returns true if the phase space point (xg,xa) is in the
// approximate (overestimated) dead region.
bool SMTopDecayer::inTheApproxDeadRegion(double xg , double xa,
double ktb, double ktc) {
bool output(true);
if(!inTheAllowedRegion(xg,xa)) output = false;
if(xa<approxDeadMinxa(xg,ktb,ktc)) output = false;
if(xa>approxDeadMaxxa(xg,ktb,ktc)) output = false;
return output;
}
// This function returns true if the phase space point (xg,xa) is in the
// dead region.
bool SMTopDecayer::inTheDeadRegion(double xg , double xa,
double ktb, double ktc) {
bool output(true);
if(!inTheApproxDeadRegion(xg,xa,ktb,ktc)) output = false;
if(xa>xaccut(ktc)) {
if(xg<xgc(max(xaccut(ktc),2.*sqrt(_a)),ktc, 1,2)&&
xg>xgc(xa,ktc, 1,0)) { output = false; }
if(xg>xgc(max(xaccut(ktc),2.*sqrt(_a)),ktc,-1,2)&&
xg<xgc(xa,ktc,-1,0)) { output = false; }
}
return output;
}
// This function attempts to generate a phase space point in the dead
// region and returns the associated phase space volume factor needed for
// the associated event weight.
double SMTopDecayer::deadRegionxgxa(double ktb,double ktc) {
_xg=0.;
_xa=0.;
// Here we set limits on xg and generate a value inside the bounds.
double xgmin(2.*sqrt(_g)),xgmax(1.-sqr(sqrt(_a)+sqrt(_c)));
// Generate _xg.
if(_xg_sampling==2.) {
_xg=xgmin*xgmax/(xgmin+UseRandom::rnd()*(xgmax-xgmin));
} else {
_xg=xgmin*xgmax/pow(( pow(xgmin,_xg_sampling-1.)
+ UseRandom::rnd()*(pow(xgmax,_xg_sampling-1.)
-pow(xgmin,_xg_sampling-1.))
),1./(_xg_sampling-1.));
}
// Here we set the bounds on _xa for given _xg.
if(_xg<xgmin||xgmin>xgmax)
throw Exception() << "TopMECorrection::deadRegionxgxa:\n"
<< "upper xg bound is less than the lower xg bound.\n"
<< "\n_xg = " << _xg
<< "\n2.*sqrt(_g) = " << 2.*sqrt(_g)
<< "\n_a = " << _a << " ma = " << sqrt(_a*_mt*_mt/GeV2)
<< "\n_c = " << _c << " mc = " << sqrt(_c*_mt*_mt/GeV2)
<< "\n_g = " << _g << " mg = " << sqrt(_g*_mt*_mt/GeV2)
<< Exception::eventerror;
double xamin(approxDeadMinxa(_xg,ktb,ktc));
double xamax(approxDeadMaxxa(_xg,ktb,ktc));
// Are the bounds sensible? If not return.
if(xamax<=xamin) return -1.;
_xa=1.+_a-(1.+_a-xamax)*pow((1.+_a-xamin)/(1.+_a-xamax),UseRandom::rnd());
// If outside the allowed region return -1.
if(!inTheDeadRegion(_xg,_xa,ktb,ktc)) return -1.;
// The integration volume for the weight
double xg_vol,xa_vol;
if(_xg_sampling==2.) {
xg_vol = (xgmax-xgmin)
/ (xgmax*xgmin);
} else {
xg_vol = (pow(xgmax,_xg_sampling-1.)-pow(xgmin,_xg_sampling-1.))
/ ((_xg_sampling-1.)*pow(xgmax*xgmin,_xg_sampling-1.));
}
xa_vol = log((1.+_a-xamin)/(1.+_a-xamax));
// Here we return the integral volume factor multiplied by the part of the
// weight left over which is not included in the BRACES function, i.e.
// the part of _xg^-2 which is not absorbed in the integration measure.
return xg_vol*xa_vol*pow(_xg,_xg_sampling-2.);
}
LorentzRotation SMTopDecayer::rotateToZ(Lorentz5Momentum v) {
// compute the rotation matrix
LorentzRotation trans;
// rotate so in z-y plane
trans.rotateZ(-atan2(v.y(),v.x()));
// rotate so along Z
trans.rotateY(-acos(v.z()/v.vect().mag()));
// generate random rotation
double c,s,cs;
do
{
c = 2.*UseRandom::rnd()-1.;
s = 2.*UseRandom::rnd()-1.;
cs = c*c+s*s;
}
while(cs>1.||cs==0.);
double cost=(c*c-s*s)/cs,sint=2.*c*s/cs;
// apply random azimuthal rotation
trans.rotateZ(atan2(sint,cost));
return trans;
}
diff --git a/Decay/Radiation/FFDipole.cc b/Decay/Radiation/FFDipole.cc
--- a/Decay/Radiation/FFDipole.cc
+++ b/Decay/Radiation/FFDipole.cc
@@ -1,947 +1,947 @@
// -*- C++ -*-
//
// FFDipole.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 FFDipole class.
//
#include "FFDipole.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Utilities/Debug.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "YFSFormFactors.h"
#include "Herwig/Decay/DecayPhaseSpaceMode.h"
#include "Herwig/Decay/DecayIntegrator.h"
using namespace Herwig;
void FFDipole::persistentOutput(PersistentOStream & os) const {
os << ounit(_emin,GeV) << ounit(_eminrest,GeV) << ounit(_eminlab,GeV)
<< _maxwgt << _weightOutput
<< _mode << _maxtry << _energyopt << _betaopt << _dipoleopt;
}
void FFDipole::persistentInput(PersistentIStream & is, int) {
is >> iunit(_emin,GeV) >> iunit(_eminrest,GeV) >> iunit(_eminlab,GeV)
>> _maxwgt >> _weightOutput
>> _mode >> _maxtry >> _energyopt >> _betaopt >> _dipoleopt;
}
FFDipole::~FFDipole() {}
ClassDescription<FFDipole> FFDipole::initFFDipole;
// Definition of the static class description member.
void FFDipole::Init() {
static ClassDocumentation<FFDipole> documentation
("The FFDipole class implements the final-final dipole for the SOPTHY algorithm");
static Switch<FFDipole,unsigned int> interfaceUnWeight
("UnWeight",
"Control the type of unweighting to perform, only one should be used the"
" other options are for debugging purposes.",
&FFDipole::_mode, 1, false, false);
static SwitchOption interfaceUnWeightNoUnweighting
(interfaceUnWeight,
"NoUnweighting",
"Perform no unweighting",
0);
static SwitchOption interfaceUnWeightAllWeights
(interfaceUnWeight,
"AllWeights",
"Include all the weights",
1);
static SwitchOption interfaceUnWeightNoJacobian
(interfaceUnWeight,
"NoJacobian",
"Only include the dipole and YFS weights",
2);
static SwitchOption interfaceUnWeightDipole
(interfaceUnWeight,
"Dipole",
"Only include the dipole weight",
3);
static SwitchOption interfaceUnWeightYFS
(interfaceUnWeight,
"YFS",
"Only include the YFS weight",
4);
static SwitchOption interfaceUnWeightNLO
(interfaceUnWeight,
"NLO",
"Weight to get the stict NLO rate",
5);
static Parameter<FFDipole,unsigned int> interfaceMaximumTries
("MaximumTries",
"Maximum number of attempts to unweight",
&FFDipole::_maxtry, 500, 10, 100000,
false, false, Interface::limited);
static Parameter<FFDipole,Energy> interfaceMinimumEnergyBoosted
("MinimumEnergyBoosted",
"The minimum energy of the photons in the boosted frame in which"
" they are generated.",
&FFDipole::_emin, MeV, 1.e-6*MeV, ZERO, 100.0*MeV,
false, false, Interface::limited);
static Parameter<FFDipole,Energy> interfaceMinimumEnergyRest
("MinimumEnergyRest",
"The minimum energy of the photons in the rest frame of the decaying particle",
&FFDipole::_eminrest, MeV, 100.0*MeV, 1.0*MeV, 10000.0*MeV,
false, false, Interface::limited);
static Parameter<FFDipole,Energy> interfaceMinimumEnergyLab
("MinimumEnergyLab",
"The minimum energy of the photons in the lab frame",
&FFDipole::_eminlab, MeV, 100.0*MeV, 1.0*MeV, 10000.0*MeV,
false, false, Interface::limited);
static Parameter<FFDipole,double> interfaceMaximumWeight
("MaximumWeight",
"The maximum weight for unweighting",
&FFDipole::_maxwgt, 7.0, 0.0, 100.0,
false, false, Interface::limited);
static Switch<FFDipole,unsigned int> interfaceEnergyCutOff
("EnergyCutOff",
"The type of cut-off on the photon energy to apply",
&FFDipole::_energyopt, 1, false, false);
static SwitchOption interfaceEnergyCutOffBoostedFrame
(interfaceEnergyCutOff,
"BoostedFrame",
"Only apply cut-off in boosted frame",
0);
static SwitchOption interfaceEnergyCutOffRestFrame
(interfaceEnergyCutOff,
"RestFrame",
"Apply cut-off in rest frame",
1);
static SwitchOption interfaceEnergyCutOff2
(interfaceEnergyCutOff,
"LabFrame",
"Apply cut-off in lab frame",
2);
static Switch<FFDipole,unsigned int> interfaceBetaOption
("BetaOption",
"Option for the inclusive of the higher beta coefficients",
&FFDipole::_betaopt, 4, false, false);
static SwitchOption interfaceBetaOptionNone
(interfaceBetaOption,
"None",
"No higher betas included",
0);
static SwitchOption interfaceBetaOptionCollinear
(interfaceBetaOption,
"Collinear",
"Include the collinear approx",
1);
static SwitchOption interfaceBetaOptionCollinearVirtA
(interfaceBetaOption,
"CollinearVirtualA",
"Include the collinear approx with virtual corrections",
2);
static SwitchOption interfaceBetaOptionCollinearVirtB
(interfaceBetaOption,
"CollinearVirtualB",
"Include the collinear approx with virtual corrections",
3);
static SwitchOption interfaceBetaOptionExact
(interfaceBetaOption,
"Exact",
"Include the exact higher order terms if available",
4);
static Switch<FFDipole,unsigned int> interfaceDipoleOption
("DipoleOption",
"Option for generating the primary dipole distribution",
&FFDipole::_dipoleopt, 0, false, false);
static SwitchOption interfaceDipoleOptionNoMass
(interfaceDipoleOption,
"NoMass",
"Don't include the mass terms in the primary distribution",
0);
static SwitchOption interfaceDipoleOptionMass
(interfaceDipoleOption,
"Mass",
"Include the mass terms in the primary distribution",
1);
static Switch<FFDipole,bool> interfaceWeightOutput
("WeightOutput",
"Whether or not to output the average weight for testing",
&FFDipole::_weightOutput, false, false, false);
static SwitchOption interfaceWeightOutputNo
(interfaceWeightOutput,
"No",
"Don't output the average",
false);
static SwitchOption interfaceWeightOutputYes
(interfaceWeightOutput,
"Yes",
"Output the average",
true);
}
void FFDipole::printDebugInfo(const Particle & p,
const ParticleVector & children,
double wgt) const {
generator()->log() << "Input masses "
<< p.mass()/GeV << " -> "
<< children[0]->mass()/GeV << " "
<< children[1]->mass()/GeV << '\n';
generator()->log() << "Momenta\n";
generator()->log() << "parent " << p.momentum()/GeV << '\n';
for(unsigned int ix=0;ix<2;++ix)
generator()->log() << "charged " << ix << " "
<< _qnewlab[ix]/GeV << " "
<< children[ix]->momentum()/GeV << '\n';
for(unsigned int ix=0;ix<_multiplicity;++ix) {
generator()->log() << "photons " << ix << " "
<< "phocut " << _photcut[ix] << ' '
<< _llab[ix]/GeV << '\n';
}
generator()->log() << "wgt : " << wgt << '\n';
generator()->log() << "_mewgt : " << _mewgt << '\n';
generator()->log() << "_jacobianwgt: " << _jacobianwgt << '\n';
generator()->log() << "_yfswgt : " << _yfswgt << '\n';
generator()->log() << "_dipolewgt : " << _dipolewgt << '\n';
generator()->log() << "dipoleopt : " << _dipoleopt << '\n';
}
ParticleVector FFDipole::generatePhotons(const Particle & p,
ParticleVector children,
tDecayIntegratorPtr decayer) {
_parent = const_ptr_cast<tPPtr>(&p);
// set the decayer
_decayer=decayer;
// set parameters which won't change in the event loop
// masses of the particles
_m[0] = p.mass();
_m[1] = children[0]->mass();
_m[2] = children[1]->mass();
// set the maximum photon energy (exact - no approximations here).
_emax=(0.5*(_m[0]-sqr(_m[1]+_m[2])/_m[0]))*_m[0]/(_m[1]+_m[2]);
// check masses non-zero
for(unsigned int ix=0;ix<2;++ix) {
if(children[ix]->mass()<1e-4*GeV) {
ostringstream message;
message << "FFDipole::generatePhotons() trying to generate QED radiation from "
<< children[ix]->dataPtr()->PDGName() << "\n with mass " << children[ix]->mass()/GeV
<< "which is much smaller than the mass of the electron.\n"
<< "This is probably due to reading events from a LHEF,\nskipping radiation in this case.\n";
generator()->logWarning( Exception(message.str(), Exception::warning));
return children;
}
}
// momenta before radiation in lab
for(unsigned int ix=0;ix<2;++ix)
_qlab[ix]=children[ix]->momentum();
// get the charges of the particles in units of the positron charge
_charge=children[0]->dataPtr()->iCharge()*children[1]->dataPtr()->iCharge()/9.;
// boost the momenta to the rest frame
Boost boostv(-p.momentum().boostVector());
// boost the particles to the parent rest frame
// and set the initial momenta of the charged particles
// in the dipole rest frame: currently this is the same
// as the boson rest frame...
for(unsigned int ix=0;ix<2;++ix) {
children[ix]->deepBoost(boostv);
_qdrf[ix]=children[ix]->momentum();
_qprf[ix]=children[ix]->momentum();
}
_parent->boost(boostv);
// perform the unweighting
double wgt;
unsigned int ntry(0);
do {
++ntry;
wgt = makePhotons(-boostv,children);
// Error checks
- if ( isnan(wgt) ) {
+ if ( std::isnan(wgt) ) {
generator()->log() << "Infinite weight for decay "
<< p.PDGName() << " "
<< children[0]->PDGName()
<< " " << children[1]->PDGName()
<< '\n';
wgt = 0.0;
}
else if ( wgt < 0.0 && _mode != 5 ) {
generator()->log() << "Negative weight for decay "
<< p.PDGName() << " "
<< children[0]->PDGName()
<< " " << children[1]->PDGName()
<< "in FFDipole: Weight = " << wgt << '\n';
if ( Debug::level )
printDebugInfo(p,children,wgt);
}
else if ( wgt > _maxwgt ) {
generator()->log() << "Weight "<< wgt<<" exceeds maximum for decay "
<< p.PDGName() << ' '
<< children[0]->PDGName()
<< " " << children[1]->PDGName()
<< " in FFDipole:\nresetting maximum weight.\n"
<< "Old Maximum = " << _maxwgt;
_maxwgt = min(1.1 * wgt, 10.0);
generator()->log() << " New Maximum = " << wgt << '\n';
if ( Debug::level && _mode!=5 )
printDebugInfo(p,children,wgt);
}
// End of error checks
_wgtsum += wgt;
_wgtsq += sqr(wgt);
++_nweight;
}
while ( wgt<(_maxwgt*UseRandom::rnd()) && ntry<_maxtry );
if(ntry>=_maxtry) {
generator()->log() << "FFDipole failed to generate QED radiation for the decay "
<< p.PDGName() << " -> "
<< children[0]->PDGName() << " "
<< children[1]->PDGName() << '\n';
_parent->boost(-boostv);
for(unsigned int ix=0;ix<2;++ix)
children[ix]->deepBoost(-boostv);
return children;
}
// produce products after radiation if needed
if(_multiplicity>0) {
// change the momenta of the children, they are currently
// in original rest frame
for(unsigned int ix=0;ix<2;++ix) {
// unit vector along direction
Boost br = children[ix]->momentum().vect().unit();
// calculate the boost vector using expression accurate for beta->1
double beta(sqrt((_qdrf[ix].e()+_m[ix+1])*(_qdrf[ix].e()-_m[ix+1]))/
_qdrf[ix].e());
double ombeta(sqr(_m[ix+1]/_qdrf[ix].e())/(1.+beta));
double betap(sqrt((_qnewdrf[ix].e()+_m[ix+1])*(_qnewdrf[ix].e()-_m[ix+1]))
/_qnewdrf[ix].e());
double ombetap(sqr(_m[ix+1]/_qnewdrf[ix].e())/(1.+betap));
// boost to get correct momentum in dipole rest frame
double bv = -(ombetap-ombeta)/(beta*ombetap + ombeta);
br *= bv;
children[ix]->deepBoost(br);
// boost to the parent rest frame
Lorentz5Momentum pnew(_bigLdrf);
pnew.setMass(_m[0]);
pnew.rescaleEnergy();
br = pnew.findBoostToCM();
children[ix]->deepBoost(br);
// boost back to the lab
children[ix]->deepBoost(-boostv);
}
// add the photons to the event record
tcPDPtr photon=getParticleData(ParticleID::gamma);
for(unsigned int ix=0;ix<_multiplicity;++ix) {
// add if not removed because energy too low
if(!_photcut[ix]) {
PPtr newphoton=new_ptr(Particle(photon));
newphoton->set5Momentum(_llab[ix]);
children.push_back(newphoton);
}
}
_parent->boost(-boostv);
//printDebugInfo(p, children, wgt);
return children;
}
// otherwise just return the original particles
else {
for(unsigned int ix=0;ix<2;++ix)
children[ix]->deepBoost(-boostv);
_parent->boost(-boostv);
return children;
}
}
// member which generates the photons
double FFDipole::makePhotons(const Boost & boostv,
const ParticleVector & children) {
// set the initial parameters
// number of photons (zero)
_multiplicity=0;
// zero size of photon vectors
_ldrf.clear();
_lprf.clear();
_llab.clear();
// zero size of angle storage
_sinphot.clear();
_cosphot.clear();
_photcut.clear();
_photonwgt.clear();
// zero total momenta of the photons
_bigLdrf=Lorentz5Momentum();
_bigLprf=Lorentz5Momentum();
// set the initial values of the reweighting factors to one
_dipolewgt = 1.0;
_yfswgt = 1.0;
_jacobianwgt = 1.0;
_mewgt = 1.0;
// calculate the velocities of the charged particles (crude/overvalued)
double beta1(sqrt((_qdrf[0].e()+_m[1])*(_qdrf[0].e()-_m[1]))/_qdrf[0].e());
double beta2(sqrt((_qdrf[1].e()+_m[2])*(_qdrf[1].e()-_m[2]))/_qdrf[1].e());
// calculate 1-beta to avoid numerical problems
double ombeta1(sqr(_m[1]/_qdrf[0].e())/(1.+beta1));
double ombeta2(sqr(_m[2]/_qdrf[1].e())/(1.+beta2));
// calculate the average photon multiplicity
double aver(YFSFormFactors::nbarFF(beta1,ombeta1,beta2,ombeta2,_charge,
_emax,_emin,_dipoleopt==1));
// calculate the number of photons using the poisson
_multiplicity = _mode !=5 ? UseRandom::rndPoisson(aver) : 1;
// calculate the first part of the YFS factor
// (N.B. crude form factor is just exp(-aver) to get a poisson)
_yfswgt *= exp(aver);
// if photons produced
if(_multiplicity>0) {
_photonwgt.resize(_multiplicity);
// generate the photon momenta with respect to q1
// keeping track of the weight
for(unsigned int ix=0;ix<_multiplicity;++ix)
_photonwgt[ix] = photon(beta1,ombeta1,beta2,ombeta2);
// rotate the photons so in dipole rest frame rather
// than angle measured w.r.t q1 first work out the rotation
SpinOneLorentzRotation rotation;
rotation.setRotateZ(-_qdrf[0].phi());
rotation.rotateY(_qdrf[0].theta());
rotation.rotateZ(_qdrf[0].phi());
// rotate the total
_bigLdrf *= rotation;
// rotate the photons
for(unsigned int ix=0;ix<_multiplicity;++ix)
_ldrf[ix]*=rotation;
// boost the momenta without any removal of low energy photons
// resize arrays
_photcut.resize(_multiplicity,false);
_lprf.resize(_multiplicity);
_llab.resize(_multiplicity);
// perform the boost
if(!boostMomenta(boostv)){return 0.;}
// apply the cut on the photon energy if needed
unsigned int nremoved(removePhotons());
// redo the boost if we have removed photons
if(nremoved!=0){if(!boostMomenta(boostv)){return 0.;}}
// form factor part of the removal term to remove existing cut
if(_energyopt!=0) _dipolewgt *=
YFSFormFactors::exponentialYFSFF(beta1,ombeta1,beta2,ombeta2,
_qdrf[0].e(),_qdrf[1].e(),
_m[1],_m[2],_m[0]*_m[0],
_charge,_emin);
// calculate the new dipole weight
// calculate velocities and 1-velocites
beta1=sqrt((_qnewdrf[0].e()+_m[1])*(_qnewdrf[0].e()-_m[1]))/_qnewdrf[0].e();
beta2=sqrt((_qnewdrf[1].e()+_m[2])*(_qnewdrf[1].e()-_m[2]))/_qnewdrf[1].e();
ombeta1=sqr(_m[1]/_qnewdrf[0].e())/(1.+beta1);
ombeta2=sqr(_m[2]/_qnewdrf[1].e())/(1.+beta2);
for(unsigned int ix=0;ix<_multiplicity;++ix) {
if(!_photcut[ix])
_dipolewgt *= exactDipoleWeight(beta1,ombeta1,beta2,ombeta2,ix)/
_photonwgt[ix];
}
// calculate the weight for the photon removal
Energy2 s((_qnewdrf[0]+_qnewdrf[1]).m2());
// calculate the second part of the yfs form factor
// this is different for the different photon removal options
// option with no removal
if(_energyopt==0) {
_yfswgt *=
YFSFormFactors::exponentialYFSFF(beta1,ombeta1,beta2,ombeta2,
_qnewdrf[0].e(),_qnewdrf[1].e(),
_m[1],_m[2],s,_charge,_emin);
}
// weight for option with cut in the rest frame
else if(_energyopt==1) {
// yfs piece
double nbeta1(sqrt( (_qnewprf[0].e()+_m[1])*(_qnewprf[0].e()-_m[1]))
/_qnewprf[0].e());
double nbeta2(sqrt( (_qnewprf[1].e()+_m[2])*(_qnewprf[1].e()-_m[2]))
/_qnewprf[1].e());
double nomb1 (sqr(_m[1]/_qnewprf[0].e())/(1.+nbeta1));
double nomb2 (sqr(_m[2]/_qnewprf[1].e())/(1.+nbeta2));
_yfswgt *=
YFSFormFactors::exponentialYFSFF(nbeta1,nomb1,nbeta2,nomb2,
_qnewprf[0].e(),_qnewprf[1].e(),
_m[1],_m[2],s,_charge,_eminrest);
// dipole piece
// Find the momenta of the particles of original particles in new rest frame
Lorentz5Momentum pnew(_bigLdrf.x(),_bigLdrf.y(),
_bigLdrf.z(),_bigLdrf.e(),_m[0]);
pnew.rescaleEnergy();
SpinOneLorentzRotation boost(pnew.findBoostToCM());
Lorentz5Momentum q1=boost*_qdrf[0];
Lorentz5Momentum q2=boost*_qdrf[1];
// use this to calculate the form factor
nbeta1=sqrt( (q1.e()+_m[1])*(q1.e()-_m[1]))/q1.e();
nbeta2=sqrt( (q2.e()+_m[2])*(q2.e()-_m[2]))/q2.e();
nomb1 =sqr(_m[1]/q1.e())/(1.+nbeta1);
nomb2 =sqr(_m[2]/q2.e())/(1.+nbeta2);
_dipolewgt /=YFSFormFactors::exponentialYFSFF(nbeta1,nomb1,nbeta2,nomb2,
q1.e(),q2.e(),
_m[1],_m[2],_m[0]*_m[0],
_charge,_eminrest);
}
// weight for option with cut in the rest frame
else if(_energyopt==2) {
// yfs piece
double nbeta1(sqrt( (_qnewlab[0].e()+_m[1])*(_qnewlab[0].e()-_m[1]))
/_qnewlab[0].e());
double nbeta2(sqrt( (_qnewlab[1].e()+_m[2])*(_qnewlab[1].e()-_m[2]))
/_qnewlab[1].e());
double nomb1 (sqr(_m[1]/_qnewlab[0].e())/(1.+nbeta1));
double nomb2 (sqr(_m[2]/_qnewlab[1].e())/(1.+nbeta2));
_yfswgt *=
YFSFormFactors::exponentialYFSFF(nbeta1,nomb1,nbeta2,nomb2,
_qnewlab[0].e(),_qnewlab[1].e(),
_m[1],_m[2],s,_charge,_eminlab);
// dipole piece
// Find the momenta of the particles of original particles in new rest frame
Lorentz5Momentum pnew(_bigLdrf.x(),_bigLdrf.y(),
_bigLdrf.z(),_bigLdrf.e(),_m[0]);
pnew.rescaleEnergy();
SpinOneLorentzRotation boost(pnew.findBoostToCM());
Lorentz5Momentum q1=boost*_qdrf[0];
Lorentz5Momentum q2=boost*_qdrf[1];
// then boost to the lab
boost.setBoost(boostv);
q1 *=boost;
q2 *=boost;
// use this to calculate the form factor
nbeta1=sqrt( (q1.e()+_m[1])*(q1.e()-_m[1]))
/q1.e();
nbeta2=sqrt( (q2.e()+_m[2])*(q2.e()-_m[2]))
/q2.e();
nomb1 =sqr(_m[1]/q1.e())/(1.+nbeta1);
nomb2 =sqr(_m[2]/q2.e())/(1.+nbeta2);
_dipolewgt /=YFSFormFactors::exponentialYFSFF(nbeta1,nomb1,nbeta2,nomb2,
q1.e(),q2.e(),_m[1],_m[2],
_m[0]*_m[0],_charge,_eminlab);
}
// Calculating jacobian weight
_jacobianwgt = jacobianWeight();
// Calculate the weight for the corrections
_mewgt = meWeight(children);
}
// otherwise copy momenta
else {
for(unsigned int ix=0;ix<2;++ix) {
_qnewdrf[ix]=_qdrf[ix];
_qnewprf[ix]=_qprf[ix];
_qnewlab[ix]=_qlab[ix];
}
_jacobianwgt = 1.0;
_yfswgt*=YFSFormFactors::exponentialYFSFF(beta1,ombeta1,beta2,ombeta2,
_qdrf[0].e(),_qdrf[1].e(),
_m[1],_m[2],_m[0]*_m[0],
_charge,_emin);
_dipolewgt = 1.0;
}
double wgt;
if(_mode!=5) {
// virtual corrections
_mewgt += virtualWeight(children);
// calculate the weight depending on the option
if(_mode==0) wgt = _maxwgt;
else if(_mode==1) wgt = _mewgt*_yfswgt*_jacobianwgt*_dipolewgt;
else if(_mode==2) wgt = _jacobianwgt*_yfswgt*_dipolewgt;
else if(_mode==3) wgt = _yfswgt*_dipolewgt;
else wgt = _yfswgt;
}
// special to test NLO results
else {
double beta1 = sqrt((_qdrf[0].e()+_m[1])*(_qdrf[0].e()-_m[1]))/_qdrf[0].e();
double beta2 = sqrt((_qdrf[1].e()+_m[2])*(_qdrf[1].e()-_m[2]))/_qdrf[1].e();
double ombeta1 = sqr(_m[1]/_qdrf[0].e())/(1.+beta1);
double ombeta2 = sqr(_m[2]/_qdrf[1].e())/(1.+beta2);
double yfs = YFSFormFactors::YFSFF(beta1,ombeta1,beta2,ombeta2,
_qdrf[0].e(),_qdrf[1].e(),
_m[1],_m[2],_m[0]*_m[0],
_charge,_emin);
double nbar = YFSFormFactors::nbarFF(beta1,ombeta1,beta2,ombeta2,_charge,
_emax,_emin,_dipoleopt==1);
wgt = 1.+virtualWeight(children)+yfs+nbar*_dipolewgt*_mewgt*_jacobianwgt;
}
return wgt;
}
double FFDipole::photon(double beta1,double ombeta1,
double beta2,double ombeta2) {
// generate the polar angle
double r1,r2,costh,sinth,opbc,ombc;
// relative weights for the two terms
double Pp(log((1+beta2)/ombeta2));
double Pm(log((1+beta1)/ombeta1));
Pp/=(Pp+Pm);
// generate the angle
double wgt=1.;
do {
r1=UseRandom::rnd();
r2=UseRandom::rnd();
// 1/(1+bc) branch
if(r1<=Pp) {
opbc = pow(1.+beta2,r2)*pow(ombeta2,1.-r2);
costh = -1./beta2*(1.-opbc);
ombc = 1.-beta1*costh;
sinth = sqrt(opbc*(2.-opbc)-(1.+beta2)*ombeta2*sqr(costh));
}
// 1/(1-bc) branch
else {
ombc = pow(1.+beta1,1.-r2)*pow(ombeta1,r2);
costh = 1./beta1*(1.-ombc);
opbc = 1.+beta2*costh;
sinth = sqrt(ombc*(2.-ombc)-(1.+beta1)*ombeta1*sqr(costh));
}
// wgt for rejection
if(_dipoleopt==1)
wgt = 1.-0.5/(1.+beta1*beta2)*(ombeta1*(1.+beta1)*opbc/ombc+
ombeta2*(1.+beta2)*ombc/opbc);
}
while(UseRandom::rnd()>wgt);
// generate the polar angle randomly in -pi->+pi
double phi(-pi+UseRandom::rnd()*2.*pi);
// generate the ln(energy) uniformly in ln(_emin)->ln(_emax)
Energy en(pow(_emax/_emin,UseRandom::rnd())*_emin);
// calculate the weight (omit the pre and energy factors
// which would cancel later anyway)
if(_dipoleopt==0)
wgt = 0.5*(1.+beta1*beta2)/opbc/ombc;
else
wgt = 0.25*(2.*(1.+beta1*beta2)/opbc/ombc
-ombeta1*(1.+beta1)/sqr(ombc)
-ombeta2*(1.+beta2)/sqr(opbc));
// store the angles
_cosphot.push_back(costh);
_sinphot.push_back(sinth);
// store the four vector for the photon
_ldrf.push_back(Lorentz5Momentum(en*sinth*cos(phi),
en*sinth*sin(phi),
en*costh,en,
ZERO));
// add the photon momentum to the total
_bigLdrf+=_ldrf.back();
// return the weight
return wgt;
}
double FFDipole::meWeight(const ParticleVector & children) {
if(_multiplicity==0) return 1.;
// option which does nothing
if(_betaopt==0) {
return 1.;
}
// collinear approx
else if(_betaopt <= 3) {
return collinearWeight(children);
}
else if (_betaopt == 4 ) {
if(_decayer&&_decayer->hasRealEmissionME()) {
double outwgt=1.;
// values of beta etc to evaluate the dipole
double beta1(sqrt( (_qnewdrf[0].e()+_m[1])*(_qnewdrf[0].e()-_m[1]))/
_qnewdrf[0].e());
double beta2(sqrt( (_qnewdrf[1].e()+_m[2])*(_qnewdrf[1].e()-_m[2]))/
_qnewdrf[1].e());
double ombeta1(sqr(_m[1]/_qnewdrf[0].e())/(1.+beta1));
double ombeta2(sqr(_m[2]/_qnewdrf[1].e())/(1.+beta2));
// storage of the weights
ParticleVector ptemp;
for(unsigned int ix=0;ix<children.size();++ix)
ptemp.push_back(new_ptr(Particle(children[ix]->dataPtr())));
ptemp.push_back(new_ptr(Particle(getParticleData(ParticleID::gamma))));
for(unsigned int i=0;i<_multiplicity;++i) {
PPtr new_parent = new_ptr(Particle(*_parent));
if(_photcut[i]) continue;
// compute the angle terms
// if cos is greater than zero use result accurate as cos->1
double opbc,ombc;
if(_cosphot[i]>0) {
opbc=1.+beta2*_cosphot[i];
ombc=ombeta1+beta1*sqr(_sinphot[i])/(1.+_cosphot[i]);
}
// if cos is less than zero use result accurate as cos->-1
else {
opbc=ombeta2+beta2*sqr(_sinphot[i])/(1.-_cosphot[i]);
ombc=1.-beta1*_cosphot[i];
}
// dipole factor for denominator
double dipole = 2./opbc/ombc*(1.+beta1*beta2
-0.5*ombeta1*(1.+beta1)*opbc/ombc
-0.5*ombeta2*(1.+beta2)*ombc/opbc);
// energy and momentum of the photon
Energy L0(_ldrf[i].e()),modL(_ldrf[i].rho());
// 3-momenta of charged particles
Energy modq(_qdrf[0].rho());
// calculate the energy of the fermion pair
Energy newE12(-L0+sqrt(sqr(_m[0])+sqr(modL)));
// 3-momentum rescaling factor (NOT energy rescaling).
double kappa(Kinematics::pstarTwoBodyDecay(newE12,_m[1],_m[2])/modq);
// calculate the rescaled momenta
Lorentz5Momentum porig[3];
for(unsigned int ix=0;ix<2;++ix) {
porig[ix] = kappa*_qdrf[ix];
porig[ix].setMass(_m[ix+1]);
porig[ix].rescaleEnergy();
}
porig[2] = _ldrf[i];
// calculate the momentum of the decaying particle in dipole rest frame
Lorentz5Momentum pnew(_ldrf[i].x(),_ldrf[i].y(),
_ldrf[i].z(),_ldrf[i].e(),_m[0]);
pnew.rescaleEnergy();
// Find the momenta of the particles in the rest frame of the parent...
// First get the boost from the parent particle
Boost boost = pnew.findBoostToCM();
LorentzRotation rot1(-boost, pnew.e()/pnew.mass());
// check the photon energy
Lorentz5Momentum ptest = _ldrf[i];
ptest.boost(boost);
if(_energyopt==1&&ptest.e()<_eminrest) continue;
new_parent->transform(rot1);
// rotation to put the emitter along the z axis
// first particle emits
unsigned int iemit = _cosphot[i]>0. ? 0 : 1;
LorentzRotation rot2;
rot2.setRotateZ(-porig[iemit].phi());
rot2.rotateY(porig[iemit].theta());
rot2.rotateZ(porig[iemit].phi());
rot2.invert();
// Boost the momenta of the charged particles
for(unsigned int ix=0;ix<3;++ix) {
porig[ix].transform(rot2);
ptemp[ix]->set5Momentum(porig[ix]);
}
new_parent->transform(rot2);
if(_cosphot[i]>0.) {
outwgt -= _decayer->
realEmissionME(_decayer->imode(),*new_parent,ptemp,
0,_cosphot[i],_sinphot[i],rot1,rot2)/
(_charge/sqr(_ldrf[i].e())*dipole);
}
else {
outwgt -= _decayer->
realEmissionME(_decayer->imode(),*new_parent,ptemp,
1,-_cosphot[i],_sinphot[i],rot1,rot2)/
(_charge/sqr(_ldrf[i].e())*dipole);
}
rot1.invert();
rot2.invert();
new_parent->transform(rot2);
new_parent->transform(rot1);
}
return outwgt;
}
else
return collinearWeight(children);
}
return 1.;
}
double FFDipole::collinearWeight(const ParticleVector & children) {
double outwgt=1.;
// spins of the decay products
PDT::Spin spin1(children[0]->dataPtr()->iSpin());
PDT::Spin spin2(children[1]->dataPtr()->iSpin());
// values of beta etc to evaluate the dipole
double beta1(sqrt( (_qnewdrf[0].e()+_m[1])*(_qnewdrf[0].e()-_m[1]))/
_qnewdrf[0].e());
double beta2(sqrt( (_qnewdrf[1].e()+_m[2])*(_qnewdrf[1].e()-_m[2]))/
_qnewdrf[1].e());
double ombeta1(sqr(_m[1]/_qnewdrf[0].e())/(1.+beta1));
double ombeta2(sqr(_m[2]/_qnewdrf[1].e())/(1.+beta2));
// storage of the weights
double twgt,dipole;
double opbc,ombc;
// compute the collinear approx
for(unsigned int i=0;i<_multiplicity;++i) {
if(_photcut[i]) continue;
// compute the angle terms
// if cos is greater than zero use result accurate as cos->1
if(_cosphot[i]>0) {
opbc=1.+beta2*_cosphot[i];
ombc=ombeta1+beta1*sqr(_sinphot[i])/(1.+_cosphot[i]);
}
// if cos is less than zero use result accurate as cos->-1
else {
opbc=ombeta2+beta2*sqr(_sinphot[i])/(1.-_cosphot[i]);
ombc=1.-beta1*_cosphot[i];
}
// dipole factor for denominator
dipole = 2.*(1.+beta1*beta2
-0.5*ombeta1*(1.+beta1)*opbc/ombc
-0.5*ombeta2*(1.+beta2)*ombc/opbc);
twgt=0.;
// correction for the first particle
double ratio(_ldrf[i].e()/_qnewdrf[0].e());
if(spin1==PDT::Spin0) twgt += 0.;
else if(spin1==PDT::Spin1Half)
twgt += opbc*ratio/(1.+(1.+beta1*beta2)/ratio/opbc);
else
twgt += 2.*sqr(opbc*ratio) *
(+1./(1+beta1*beta2+_ldrf[i].e()/_qnewdrf[1].e()*ombc)
+(1.+beta1*beta2)/sqr(1.+beta1*beta2
+_ldrf[i].e()/_qnewdrf[0].e()*opbc));
// correction for the second particle
ratio =_ldrf[i].e()/_qnewdrf[1].e();
if(spin2==PDT::Spin0) twgt += 0.;
else if(spin2==PDT::Spin1Half)
twgt += ombc*ratio/(1.+(1.+beta1*beta2)/ratio/ombc);
else
twgt += 2.*sqr(ombc*ratio) *
(1./(1. + beta1*beta2 + _ldrf[i].e()/_qnewdrf[0].e()*opbc)
+ (1.+beta1*beta2) / sqr(1. + beta1*beta2
+ _ldrf[i].e()/_qnewdrf[1].e()*ombc));
twgt/=dipole;
outwgt+=twgt;
}
return outwgt;
}
bool FFDipole::boostMomenta(const Boost & boostv) {
// total energy and momentum of photons
Energy L0(_bigLdrf.e()),modL(_bigLdrf.rho());
// 3-momenta of charged particles
Energy modq(_qdrf[0].rho());
// calculate the energy of the fermion pair
Energy newE12(-L0+sqrt(_m[0]*_m[0]+modL*modL));
// check this is allowed
if(newE12<_m[1]+_m[2]){return false;}
// 3-momentum rescaling factor (NOT energy rescaling).
double kappa(Kinematics::pstarTwoBodyDecay(newE12,_m[1],_m[2])/modq);
// calculate the rescaled momenta
for(unsigned int ix=0;ix<2;++ix) {
_qnewdrf[ix] = kappa*_qdrf[ix];
_qnewdrf[ix].setMass(_m[ix+1]);
_qnewdrf[ix].rescaleEnergy();
}
// calculate the momentum of the decaying particle in dipole rest frame
Lorentz5Momentum pnew(_bigLdrf.x(),_bigLdrf.y(),
_bigLdrf.z(),_bigLdrf.e(),_m[0]);
pnew.rescaleEnergy();
// Find the momenta of the particles in the rest frame
// of the parent...
// First get the boost from the parent particle
SpinOneLorentzRotation boost(pnew.findBoostToCM());
// Boost the momenta of the charged particles
for(unsigned int ix=0;ix<2;++ix) _qnewprf[ix]=boost*_qnewdrf[ix];
// Boost the total photon momentum
_bigLprf=boost*_bigLdrf;
// Boost the individual photon momenta
for(unsigned int ix=0;ix<_multiplicity;++ix){_lprf[ix]=boost*_ldrf[ix];}
// Now boost from the parent rest frame to the lab frame
boost.setBoost(boostv);
// Boosting charged particles
for(unsigned int ix=0;ix<2;++ix){_qnewlab[ix]=boost*_qnewprf[ix];}
// Boosting total photon momentum
_bigLlab=boost*_bigLprf;
// Boosting individual photon momenta
for(unsigned int ix=0;ix<_multiplicity;++ix){_llab[ix]=boost*_lprf[ix];}
return true;
}
unsigned int FFDipole::removePhotons() {
unsigned int nremoved(0);
// apply the cut in the rest frame
if(_energyopt==1) {
for(unsigned int ix=0;ix<_multiplicity;++ix) {
if(_lprf[ix].e()<_eminrest) {
++nremoved;
_photcut[ix]=true;
_bigLdrf-=_ldrf[ix];
_ldrf[ix]=Lorentz5Momentum();
}
}
}
// apply the cut in the lab frame
else if(_energyopt==2) {
for(unsigned int ix=0;ix<_multiplicity;++ix) {
if(_llab[ix].e()<_eminlab) {
++nremoved;
_photcut[ix]=true;
_bigLdrf-=_ldrf[ix];
_ldrf[ix]=Lorentz5Momentum();
}
}
}
// correction factor for dipoles if needed
if(_dipoleopt==0&&nremoved!=0) {
// calculate the velocities of the charged particles (crude/overvalued)
double beta1(sqrt((_qdrf[0].e()+_m[1])*(_qdrf[0].e()-_m[1]))/_qdrf[0].e());
double beta2(sqrt((_qdrf[1].e()+_m[2])*(_qdrf[1].e()-_m[2]))/_qdrf[1].e());
// calculate 1-beta to avoid numerical problems
double ombeta1(sqr(_m[1]/_qdrf[0].e())/(1.+beta1));
double ombeta2(sqr(_m[2]/_qdrf[1].e())/(1.+beta2));
// calculate the weights
for(unsigned int ix=0;ix<_multiplicity;++ix) {
if(_photcut[ix]) _dipolewgt *=
exactDipoleWeight(beta1,ombeta1,beta2,ombeta2,ix)/_photonwgt[ix];
}
}
// return number of remove photons
return nremoved;
}
double FFDipole::virtualWeight(const ParticleVector & children) {
double output = 0.;
// Virtual corrections for beta_0:
// These should be zero for the scalar case as there is no
// collinear singularity going by the dipoles above...
// Use mass of decaying particle...
if(_betaopt==2) {
if((children[0]->dataPtr()->iSpin())==2&&
(children[1]->dataPtr()->iSpin())==2
) {
output += (1.0*YFSFormFactors::_alpha/pi)
* log(sqr(_m[0]/_m[1]));
}
}
// OR Use invariant mass of final state children...
else if(_betaopt==3) {
if((children[0]->dataPtr()->iSpin())==2&&
(children[1]->dataPtr()->iSpin())==2
) {
output += (1.0*YFSFormFactors::_alpha/pi)
* log((_qnewprf[0]+_qnewprf[1]).m2()/sqr(_m[1]));
}
}
else if (_betaopt==4) {
if(_decayer&&_decayer->hasOneLoopME()) {
output +=
_decayer->oneLoopVirtualME(_decayer->imode(),*_parent,
children);
}
else {
output += (1.0*YFSFormFactors::_alpha/pi)
* log(sqr(_m[0]/_m[1]));
}
}
return output;
}
void FFDipole::dofinish() {
Interfaced::dofinish();
if(_weightOutput) {
_wgtsum /= double(_nweight);
_wgtsq /= double(_nweight);
_wgtsq = max(_wgtsq - sqr(_wgtsum),0.);
_wgtsq /= double(_nweight);
_wgtsq = sqrt(_wgtsq);
generator()->log() << "The average weight for QED Radiation in " << fullName()
<< " was " << _wgtsum << " +/- " << _wgtsq << '\n';
}
}
diff --git a/Decay/Radiation/IFDipole.cc b/Decay/Radiation/IFDipole.cc
--- a/Decay/Radiation/IFDipole.cc
+++ b/Decay/Radiation/IFDipole.cc
@@ -1,706 +1,706 @@
// -*- C++ -*-
//
// IFDipole.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 IFDipole class.
//
#include "IFDipole.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
using namespace ThePEG::Helicity;
using namespace Herwig;
void IFDipole::persistentOutput(PersistentOStream & os) const {
os << _alpha << ounit(_emin,GeV) << _maxwgt
<< _mode << _maxtry << _energyopt << _betaopt;
}
void IFDipole::persistentInput(PersistentIStream & is, int) {
is >> _alpha >> iunit(_emin,GeV) >> _maxwgt
>> _mode >> _maxtry >> _energyopt >> _betaopt;
}
ClassDescription<IFDipole> IFDipole::initIFDipole;
// Definition of the static class description member.
void IFDipole::Init() {
static ClassDocumentation<IFDipole> documentation
("The IFDipole class implements the initial-final dipole for the SOPTHY algorithm");
static Switch<IFDipole,unsigned int> interfaceUnWeight
("UnWeight",
"Control the type of unweighting to perform, only one should be used the"
" other options are for debugging purposes.",
&IFDipole::_mode, 1, false, false);
static SwitchOption interfaceUnWeightNoUnweighting
(interfaceUnWeight,
"NoUnweighting",
"Perform no unweighting",
0);
static SwitchOption interfaceUnWeightAllWeights
(interfaceUnWeight,
"AllWeights",
"Include all the weights",
1);
static SwitchOption interfaceUnWeightNoJacobian
(interfaceUnWeight,
"NoJacobian",
"Only include the dipole and YFS weights",
2);
static SwitchOption interfaceUnWeightDipole
(interfaceUnWeight,
"Dipole",
"Only include the dipole weight",
3);
static SwitchOption interfaceUnWeightYFS
(interfaceUnWeight,
"YFS",
"Only include the YFS weight",
4);
static Parameter<IFDipole,unsigned int> interfaceMaximumTries
("MaximumTries",
"Maximum number of attempts to unweight",
&IFDipole::_maxtry, 500, 10, 100000,
false, false, Interface::limited);
static Parameter<IFDipole,Energy> interfaceMinimumEnergyRest
("MinimumEnergyRest",
"The minimum energy of the photons in the rest frame of the decaying particle",
&IFDipole::_emin, MeV, 1.*MeV, ZERO, 10000.0*MeV,
false, false, Interface::limited);
static Parameter<IFDipole,double> interfaceMaximumWeight
("MaximumWeight",
"The maximum weight for unweighting",
&IFDipole::_maxwgt, 2.0, 0.0, 100.0,
false, false, Interface::limited);
static Switch<IFDipole,unsigned int> interfaceEnergyCutOff
("EnergyCutOff",
"The type of cut-off on the photon energy to apply",
&IFDipole::_energyopt, 1, false, false);
static SwitchOption interfaceEnergyCutOffRestFrame
(interfaceEnergyCutOff,
"RestFrame",
"Apply cut-off in rest frame",
1);
static SwitchOption interfaceEnergyCutOff2
(interfaceEnergyCutOff,
"LabFrame",
"Apply cut-off in lab frame",
2);
static Switch<IFDipole,unsigned int> interfaceBetaOption
("BetaOption",
"Option for the inclusive of the higher beta coefficients",
&IFDipole::_betaopt, 1, false, false);
static SwitchOption interfaceBetaOptionNone
(interfaceBetaOption,
"None",
"No higher betas included",
0);
static SwitchOption interfaceBetaOptionCollinear
(interfaceBetaOption,
"Collinear",
"Include the collinear approx",
1);
static SwitchOption interfaceBetaOptionCollinearVirtA
(interfaceBetaOption,
"CollinearVirtualA",
"Include the collinear approx with virtual corrections",
2);
static SwitchOption interfaceBetaOptionCollinearVirtB
(interfaceBetaOption,
"CollinearVirtualB",
"Include the collinear approx with virtual corrections",
3);
static SwitchOption interfaceBetaOptionExact
(interfaceBetaOption,
"Exact",
"Include the exact higher order terms if available",
4);
}
ParticleVector IFDipole::generatePhotons(const Particle & p,ParticleVector children) {
// set parameters which won't change in the event loop
// masses of the particles
_m[0] = p.mass();
_m[1] = children[0]->mass();
_m[2] = children[1]->mass();
// momenta before radiation in lab
for(unsigned int ix=0;ix<2;++ix){_qlab[ix]=children[ix]->momentum();}
// get the charges of the particles in units of the positron charge
// chrg1 is the charge of the parent and chrg2 is the charge of the
// charged child. Also we create a map between the arguments of
// _q???[X] _m[X] etc so that
// _q???[_map[0]] and _m[_map[0]] are the momenta and masses of
// the charged child while
// _q???[_map[1]] and _m[_map[1]] are the momenta and masses of
// the neutral child.
_chrg1 = p.dataPtr()->iCharge()/3.0;
if(children[1]->dataPtr()->iCharge()/3.0==0.0) {
_chrg2 = children[0]->dataPtr()->iCharge()/3.0;
_map[0] = 0; _map[1] = 1;
}
else if(children[0]->dataPtr()->iCharge()/3.0==0.0) {
_chrg2 = children[1]->dataPtr()->iCharge()/3.0;
_map[0] = 1; _map[1] = 0;
}
// check the radiating particle is not massless
// if(children[1]->mass()<
if(children[_map[0]]->mass()<1e-4*GeV) {
ostringstream message;
message << "IFDipole::generatePhotons() trying to generate QED radiation from "
<< children[_map[0]]->dataPtr()->PDGName() << "\n with mass " << children[_map[0]]->mass()/GeV
<< "which is much smaller than the mass of the electron.\n"
<< "This is probably due to reading events from a LHEF,\nskipping radiation in this case.\n";
generator()->logWarning( Exception(message.str(), Exception::warning));
return children;
}
// boost the momenta to the rest frame
Boost boostv(p.momentum().boostVector());
// boost the particles to the parent rest frame
// and set the initial momenta of the charged particles
// in the dipole rest frame: currently this is the same
// as the boson rest frame...
for(unsigned int ix=0;ix<2;++ix) {
// KMH - 08/11/05 - This used to be boostv instead of -boostv
// -boostv is the boost from the lab to the parent rest frame
// whereas boostv goes the other way!!!
children[ix]->deepBoost(-boostv);
_qprf[ix]=children[ix]->momentum();
}
// perform the unweighting
double wgt;
unsigned int ntry(0);
do {
wgt =makePhotons(boostv,children);
++ntry;
// Record warnings about large and weird weights in the .log file.
- if(wgt>_maxwgt||wgt<0.0||isnan(wgt)) {
+ if(wgt>_maxwgt||wgt<0.0||std::isnan(wgt)) {
generator()->log() << "IFDipole.cc:\n";
if(wgt>_maxwgt) {
generator()->log() << "Weight exceeds maximum for decay!\n";
}
if(wgt<0.0) {
generator()->log() << "Weight is negative! \n";
}
- if(isnan(wgt)) {
+ if(std::isnan(wgt)) {
generator()->log() << "Weight is NAN! \n";
wgt = 0.;
}
generator()->log() << p.PDGName() << " "
<< children[0]->PDGName() << " "
<< children[1]->PDGName()
<< endl
<< " Current Maximum = " << _maxwgt
<< endl
<< " Current Weight = " << wgt
<< endl;
generator()->log() << "Photon Multiplicity : "
<< _multiplicity << endl
<< "Original Parent rest frame momenta: " << endl
<< "charged child: " << ounit(_qprf[_map[0]],GeV) << endl
<< "neutral child: " << ounit(_qprf[_map[1]],GeV) << endl
<< "Parent rest frame momenta: " << endl
<< "charged child: " << ounit(_qnewprf[_map[0]],GeV)<< endl
<< "neutral child: " << ounit(_qnewprf[_map[1]],GeV)<< endl
<< "photons : " << ounit(_bigLprf,GeV) << endl
<< "Weights : " << endl
<< "_dipolewgt : " << _dipolewgt << endl
<< "_yfswgt : " << _yfswgt << endl
<< "_jacobianwgt : " << _jacobianwgt << endl
<< "_mewgt : " << _mewgt << endl;
for(unsigned int ct=0;ct<_multiplicity;ct++) {
generator()->log() << "_cosphot[" << ct << "]: " << _cosphot[ct] << endl;
generator()->log() << "_sinphot[" << ct << "]: " << _sinphot[ct] << endl;
}
if(wgt>_maxwgt) {
if(wgt<15.0) {
generator()->log() << "Resetting maximum weight"
<< endl << " New Maximum = " << wgt << endl;
_maxwgt=wgt;
} else {
generator()->log() << "Maximum weight set to limit (15)" << endl;
_maxwgt=15.0;
}
}
}
} while (wgt<(_maxwgt*UseRandom::rnd()) && ntry<_maxtry);
if(ntry>=_maxtry) {
generator()->log() << "IFDipole Failed to generate QED radiation for the decay "
<< p.PDGName() << " -> "
<< children[0]->PDGName() << " "
<< children[1]->PDGName() << endl;
return children;
}
// produce products after radiation if needed
if(_multiplicity>0) {
// change the momenta of the children, they are currently
// in parent rest frame
for(unsigned int ix=0;ix<2;++ix) {
LorentzRotation boost(solveBoost(_qnewprf[ix],children[ix]->momentum()));
children[ix]->deepTransform(boost);
// boost back to the lab
// KMH - 08/11/05 - This used to be -boostv instead of boostv
// -boostv is the boost from the lab to the parent rest frame
// whereas boostv goes the other way!!!
children[ix]->deepBoost(boostv);
}
// add the photons to the event record
tcPDPtr photon=getParticleData(ParticleID::gamma);
for(unsigned int ix=0;ix<_multiplicity;++ix) {
PPtr newphoton=new_ptr(Particle(photon));
newphoton->set5Momentum(_llab[ix]);
children.push_back(newphoton);
}
return children;
}
// otherwise just return the orginial particles
// boosted back to lab
else {
for(unsigned int ix=0;ix<children.size();++ix)
children[ix]->deepBoost(boostv);
return children;
}
}
// member which generates the photons
double IFDipole::makePhotons(Boost boostv,ParticleVector children) {
// set the initial parameters
// number of photons (zero)
_multiplicity=0;
// zero size of photon vectors
_lprf.clear();
_llab.clear();
// zero size of angle storage
_sinphot.clear();
_cosphot.clear();
// zero total momenta of the photons
_bigLprf=Lorentz5Momentum();
// set the initial values of the reweighting factors to one
_dipolewgt = 1.0;
_yfswgt = 1.0;
_jacobianwgt = 1.0;
_mewgt = 1.0;
// set the maximum photon energy (exact - no approximations here).
double boost_factor = 1.0;
_emax=(0.5*(_m[0]-sqr(_m[1]+_m[2])/_m[0]))*boost_factor;
// calculate the velocities of the children (crude/overvalued)
double beta1(sqrt( (_qprf[_map[0]].e()+_m[_map[0]+1])
*(_qprf[_map[0]].e()-_m[_map[0]+1])
)
/_qprf[_map[0]].e());
double beta2(sqrt( (_qprf[_map[1]].e()+_m[_map[1]+1])
*(_qprf[_map[1]].e()-_m[_map[1]+1])
)
/_qprf[_map[1]].e());
// calculate 1-beta to avoid numerical problems
double ombeta1(sqr(_m[_map[0]+1]/_qprf[_map[0]].e())/(1.+beta1));
double ombeta2(sqr(_m[_map[1]+1]/_qprf[_map[1]].e())/(1.+beta2));
// calculate the average photon multiplicity
double aver(nbar(beta1,ombeta1));
// calculate the number of photons using the poisson
_multiplicity = UseRandom::rndPoisson(aver);
// calculate the first part of the YFS factor
_yfswgt/=crudeYFSFormFactor(beta1,ombeta1);
// generate the photon momenta with respect to q1
// keeping track of the weight
double dipoles(1.);
for(unsigned int ix=0;ix<_multiplicity;++ix)
{ dipoles *= photon(beta1,ombeta1); }
// calculate contributions to the dipole weights so far
_dipolewgt /=dipoles;
// now do the momentum reshuffling
Lorentz5Momentum pmom(ZERO,ZERO,ZERO,_m[0],_m[0]);
if(_multiplicity>0) {
// total energy and momentum of photons
Energy L0(_bigLprf.e()),modL(_bigLprf.rho());
// squared invariant mass of final state fermions...
Energy2 m122 = sqr(_m[0]-L0)-sqr(modL);
if(m122<sqr(_m[1]+_m[2])) return 0.;
// 3-momenta of charged particles
Energy modq(_qprf[_map[0]].rho());
// total photon momentum perpendicular to charged child...
Energy LT(_bigLprf.perp());
// kallen function...
Energy4 kallen = ( m122 - sqr(_m[1]+_m[2]) )
* ( m122 - sqr(_m[1]-_m[2]) );
// discriminant of rho...
Energy4 droot = kallen-4.*sqr(_m[_map[0]+1]*LT);
if(droot<ZERO) return 0.;
double disc = (_m[0]-L0) * sqrt(droot) / (2.*modq*(m122+LT*LT));
// calculate the energy rescaling factor
double rho = disc-_bigLprf.z()
* (m122+sqr(_m[_map[0]+1])-sqr(_m[_map[1]+1]))
/ (2.*modq*(m122+LT*LT));
// calculate the rescaled charged child momentum
_qnewprf[_map[0]]=rho*_qprf[_map[0]];
_qnewprf[_map[0]].setMass(_m[_map[0]+1]);
_qnewprf[_map[0]].rescaleEnergy();
// rotate the photons so in parent rest frame rather
// than angle measured w.r.t q1 first work out the rotation
SpinOneLorentzRotation rotation;
rotation.setRotateZ(-_qprf[_map[0]].phi());
rotation.rotateY(_qprf[_map[0]].theta());
rotation.rotateZ(_qprf[_map[0]].phi());
// rotate the total
_bigLprf*=rotation;
// rotate the photons
for(unsigned int ix=0;ix<_multiplicity;++ix){_lprf[ix]*=rotation;}
// calculate the rescaled neutral child momentum
_qnewprf[_map[1]]=pmom-_qnewprf[_map[0]]-_bigLprf;
_qnewprf[_map[1]].setMass(_m[_map[1]+1]);
_qnewprf[_map[1]].rescaleEnergy();
// calculate the new dipole weight
// Note this (weight) is Lorentz invariant
// calculate velocities and 1-velocites
beta1=sqrt( (_qnewprf[_map[0]].e()+_m[_map[0]+1])
*(_qnewprf[_map[0]].e()-_m[_map[0]+1]))
/_qnewprf[_map[0]].e();
beta2=sqrt( (_qnewprf[_map[1]].e()+_m[_map[1]+1])
*(_qnewprf[_map[1]].e()-_m[_map[1]+1]))
/_qnewprf[_map[1]].e();
ombeta1=sqr(_m[_map[0]+1]/_qnewprf[_map[0]].e())/(1.+beta1);
ombeta2=sqr(_m[_map[1]+1]/_qnewprf[_map[1]].e())/(1.+beta2);
for(unsigned int ix=0;ix<_multiplicity;++ix)
{_dipolewgt*=exactDipoleWeight(beta1,ombeta1,ix);}
// calculate the second part of the yfs form factor
_yfswgt*=exactYFSFormFactor(beta1,ombeta1,beta2,ombeta2);
// Now boost from the parent rest frame to the lab frame
SpinOneLorentzRotation boost(boostv);
// Boosting charged particles
for(unsigned int ix=0;ix<2;++ix){_qnewlab[ix]=boost*_qnewprf[ix];}
// Boosting total photon momentum
_bigLlab=boost*_bigLprf;
// Boosting individual photon momenta
for(unsigned int ix=0;ix<_multiplicity;++ix)
{_llab.push_back(boost*_lprf[ix]);}
// Calculating jacobian weight
_jacobianwgt = jacobianWeight();
// Calculating beta^1 weight
_mewgt = meWeight(children);
// Apply phase space vetos...
if(kallen<(4.*sqr(_m[_map[0]+1]*LT))||m122<sqr(_m[1]+_m[2])||rho<0.0) {
// generator()->log() << "Outside Phase Space" << endl;
// generator()->log() << "Photon Multiplicity: "
// << _multiplicity << endl
// << "Original Parent rest frame momenta: " << endl
// << "charged child: " << _qprf[_map[0]] << endl
// << "neutral child: " << _qprf[_map[1]] << endl
// << "rescaling : " << rho << endl
// << "Parent rest frame momenta: " << endl
// << "charged child: " << _qnewprf[_map[0]] << endl
// << "neutral child: " << _qnewprf[_map[1]] << endl
// << "photons : " << _bigLprf << endl
// << endl;
_dipolewgt = 0.0 ;
_yfswgt = 0.0 ;
_jacobianwgt = 0.0 ;
_mewgt = 0.0 ;
}
_qprf[_map[0]].rescaleEnergy();
_qprf[_map[1]].rescaleEnergy();
_qnewprf[_map[0]].rescaleEnergy();
_qnewprf[_map[1]].rescaleEnergy();
if( ((abs(_m[0]-_bigLprf.e()-_qnewprf[0].e()-_qnewprf[1].e())>0.00001*MeV)||
(abs( _bigLprf.x()+_qnewprf[0].x()+_qnewprf[1].x())>0.00001*MeV)||
(abs( _bigLprf.y()+_qnewprf[0].y()+_qnewprf[1].y())>0.00001*MeV)||
(abs( _bigLprf.z()+_qnewprf[0].z()+_qnewprf[1].z())>0.00001*MeV))
&&(_dipolewgt*_jacobianwgt*_yfswgt*_mewgt>0.0)) {
Lorentz5Momentum ptotal = _bigLprf+_qnewprf[0]+_qnewprf[1];
ptotal.setE(ptotal.e()-_m[0]);
generator()->log()
<< "Warning! Energy Not Conserved! tol = 0.00001 MeV"
<< "\nwgt = " << _dipolewgt*_yfswgt*_jacobianwgt*_mewgt
<< "\nrho = " << rho
<< "\nmultiplicity = " << _multiplicity
<< "\n_qprf[_map[0]] = " << _qprf[_map[0]]/GeV
<< "\n_qprf[_map[1]] = " << _qprf[_map[1]]/GeV
<< "\n_qnewprf[_map[0]] = " << _qnewprf[_map[0]]/GeV << " "
<< _qnewprf[_map[0]].m()/GeV << " " << _m[_map[0]+1]/GeV
<< "\n_qnewprf[_map[1]] = " << _qnewprf[_map[1]]/GeV << " "
<< _qnewprf[_map[1]].m()/GeV << " " << _m[_map[1]+1]/GeV
<< "\n_bigLprf = " << _bigLprf/GeV
<< "\n_bigLprf.m2() = " << _bigLprf.m2()/GeV2
<< "\n_total out -in = " << ptotal/GeV
<< "\nRejecting Event. " << "\n";
_dipolewgt = 0.0 ;
_yfswgt = 0.0 ;
_jacobianwgt = 0.0 ;
_mewgt = 0.0 ;
}
}
// otherwise copy momenta
else
{ for(unsigned int ix=0;ix<2;++ix) {
_qnewprf[ix]=_qprf[ix];
_qnewlab[ix]=_qlab[ix];
}
_jacobianwgt = 1.0;
// calculate the second part of the yfs form factor
_yfswgt*=exactYFSFormFactor(beta1,ombeta1,beta2,ombeta2);
_dipolewgt = 1.0;
}
// Virtual corrections for beta_0:
// These should be zero for the scalar case as there is no
// collinear singularity going by the dipoles above...
// Use mass of decaying particle...
if(_betaopt==2) {
if((children[_map[0]]->dataPtr()->iSpin())==2) {
_mewgt += (0.5*_alpha/pi)
* log(sqr(_m[0]
/_m[_map[0]+1])
);
}
}
// OR Use invariant mass of final state children...
if(_betaopt==3) {
if((children[_map[0]]->dataPtr()->iSpin())==2) {
_mewgt += (0.5*_alpha/pi)
* log((_qnewprf[0]+_qnewprf[1]).m2()
/sqr(_m[_map[0]+1])
);
}
}
// calculate the weight depending on the option
double wgt;
if(_mode==0){wgt=_maxwgt;}
else if(_mode==1){wgt=_mewgt*_jacobianwgt*_yfswgt*_dipolewgt;}
else if(_mode==2){wgt=_jacobianwgt*_yfswgt*_dipolewgt;}
else if(_mode==3){wgt=_yfswgt*_dipolewgt;}
else {wgt=_yfswgt;}
return wgt;
}
double IFDipole::photon(double beta1,double ombeta1)
{
// generate the azimuthal angle randomly in -pi->+pi
double phi(-pi+UseRandom::rnd()*2.*pi);
// generate the polar angle
double r(UseRandom::rnd());
double costh,sinth,ombc;
ombc = pow(1.+beta1,1.-r)*pow(ombeta1,r);
costh = 1./beta1*(1.-ombc);
sinth = sqrt(ombc*(2.-ombc)-(1.+beta1)*ombeta1*sqr(costh));
// generate the ln(energy) uniformly in ln(_emin)->ln(_emax)
Energy energy = pow(_emax/_emin,UseRandom::rnd())*_emin;
// calculate the weight (omit the pre and energy factors
// which would cancel later anyway)
double wgt = 2./ombc;
// store the angles
_cosphot.push_back(costh);
_sinphot.push_back(sinth);
// store the four vector for the photon
_lprf.push_back(Lorentz5Momentum(energy*sinth*cos(phi),energy*sinth*sin(phi),
energy*costh,energy,ZERO));
// add the photon momentum to the total
_bigLprf+=_lprf.back();
// return the weight
return wgt;
}
double IFDipole::meWeight(ParticleVector children)
{
unsigned int spin = children[_map[0]]->dataPtr()->iSpin();
double mewgt = 1.0;
double beta1=sqrt( (_qnewprf[_map[0]].e()+_m[_map[0]+1])
*(_qnewprf[_map[0]].e()-_m[_map[0]+1]))
/_qnewprf[_map[0]].e();
double ombeta1=sqr(_m[_map[0]+1]/_qnewprf[_map[0]].e())/(1.+beta1);
// option which does nothing
if(_betaopt==0){mewgt=1.;}
// collinear approx
else if(_betaopt==1||_betaopt==2||_betaopt==3)
{
double ombc;
InvEnergy2 dipole;
for(unsigned int i=0;i<_multiplicity;++i) {
double opbc;
if(_cosphot[i]<0.0)
{ opbc=ombeta1+beta1*sqr(_sinphot[i])/(1.-_cosphot[i]); }
// if cos is greater than zero use result accurate as cos->-1
else
{ opbc=1.+beta1*_cosphot[i]; }
// if cos is greater than zero use result accurate as cos->1
if(_cosphot[i]>0.0)
{ ombc=ombeta1+beta1*sqr(_sinphot[i])/(1.+_cosphot[i]); }
// if cos is less than zero use result accurate as cos->-1
else
{ ombc=1.-beta1*_cosphot[i]; }
if(((_qnewprf[_map[0]].z()>ZERO)&&(_qprf[_map[0]].z()<ZERO))||
((_qnewprf[_map[0]].z()<ZERO)&&(_qprf[_map[0]].z()>ZERO))) {
dipole = sqr(beta1*_sinphot[i]/(opbc*_lprf[i].e()));
} else {
dipole = sqr(beta1*_sinphot[i]/(ombc*_lprf[i].e()));
}
// here "dipole" is the exact dipole function divided by alpha/4pi^2.
if(spin==2) {
Energy magpi= sqrt( sqr(_qnewprf[_map[0]].x())
+ sqr(_qnewprf[_map[0]].y())
+ sqr(_qnewprf[_map[0]].z())
);
mewgt += sqr(_lprf[i].e())*_qnewprf[_map[0]].e()*ombc
/ (sqr(magpi*_sinphot[i])*(_qnewprf[_map[0]].e()+_lprf[i].e()));
}
else if(spin==3) {
Energy2 pik = _qnewprf[_map[0]].e()*_lprf[i].e()
- _qnewprf[_map[0]].x()*_lprf[i].x()
- _qnewprf[_map[0]].y()*_lprf[i].y()
- _qnewprf[_map[0]].z()*_lprf[i].z();
Energy2 pjk = _m[0]*_lprf[i].e();
Energy2 pipj = _m[0]*_qnewprf[_map[0]].e();
mewgt += (2.*pjk*pipj/(pik*sqr(pipj+pjk))
+2.*pjk/(pik*(pipj+pik))
)/dipole;
}
else {
mewgt = 1.0;
}
}
}
return mewgt;
}
double IFDipole::exactYFSFormFactor(double beta1,double ombeta1,
double beta2,double ombeta2) {
double Y = 0.0 ;
double b = beta1 ;
double omb = ombeta1;
double c = beta2 ;
double omc = ombeta2;
double arg1 = -omc/(2.*c);
double arg2 = -omb*omc/(2.*(b+c));
double arg3 = 2.*b/(1.+b);
if(_m[_map[1]+1]!=ZERO) {
Y = _chrg1*_chrg2*(_alpha/(2.*pi))*(
log(_m[0]*_m[_map[1]+1]/sqr(2.*_emin))
+log(_m[_map[0]+1]*_m[_map[1]+1]/sqr(2.*_emin))
-(1./b )*log((1.+b)/omb)*log(sqr(_m[_map[1]+1]/(2.*_emin)))
-(1./b )*log(omb/(1.+b))
-(0.5/b )*sqr(log(omb/(1.+b)))
+((b+c )/(b*omc))*log((b+c )/(b*omc))
-((c+b*c)/(b*omc))*log((c+b*c)/(b*omc))
+((b+c )/(b+b*c))*log((b+c )/(b+b*c))
-((c*omb)/(b+b*c))*log((c*omb)/(b+b*c))
+(0.5/b)*( sqr(log( (b+c)/(b*omc)))-sqr(log((c+b*c)/(b*omc)))
+ sqr(log((c*omb)/(b+b*c)))-sqr(log((b+ c)/(b+b*c)))
)
+(2./b )*( real(Math::Li2(arg1))
- real(Math::Li2(arg2))
- real(Math::Li2(arg3))
)
+(1./b )*log((b+c)/(b+b*c))*log((1.+c)/(2.*c))
-(1./b )*log((c*omb)/(b*(1.+c)))*log((1.+b)*(1.+c)/(2.*(b+c)))
-(1./b )*log((2.*c/b)*((b+c)/(omc*(1.+c))))*log((b+c)/(c*omb))
);
}
else if(_m[_map[1]+1]==ZERO) {
Y = _chrg1*_chrg2*(_alpha/(2.*pi))*(
log(sqr(_m[0]/(2.*_emin)))
+log(sqr(_m[_map[0]+1]/(2.*_emin)))
-(1./b )*log((1.+b)/omb)
*log((sqr(_m[0])-sqr(_m[_map[0]+1]))/sqr(2.*_emin))
-0.5*log(omb*(1.+b)/sqr(2.*b))
+((1.+b)/(2.*b))*log((1.+b)/(2.*b))
-( omb/(2.*b))*log( omb/(2.*b))
-(1./b )*log((1.-b)/(1.+b))
+1.
+(0.5/b)*sqr(log( omb/(2.*b)))
-(0.5/b)*sqr(log((1.+b)/(2.*b)))
-(0.5/b)*sqr(log((1.-b)/(1.+b)))
-(2. /b)*real(Math::Li2(arg3))
);
}
return exp(Y);
}
double IFDipole::jacobianWeight() {
// calculate the velocities of the children (crude/overvalued)
Energy mag1old = sqrt( (_qprf[_map[0]].e() +_m[_map[0]+1])
*(_qprf[_map[0]].e() -_m[_map[0]+1])
);
Energy mag1new = sqrt( (_qnewprf[_map[0]].e()+_m[_map[0]+1])
*(_qnewprf[_map[0]].e()-_m[_map[0]+1])
);
Energy magL = sqrt( sqr(_bigLprf.x())
+ sqr(_bigLprf.y())
+ sqr(_bigLprf.z())
);
// 14/12/05 - KMH - This was another mistake. This is supposed to be
// the angel between _qnewprf[_map[0]] and _bigLprf instead of
// between _qnewprf[0] and _bigLprf. Stupid. Hopefully this weight
// is correct now.
// double cos1L = (_qnewprf[0].x()*_bigLprf.x()
// +_qnewprf[0].y()*_bigLprf.y()
// +_qnewprf[0].z()*_bigLprf.z()
// )
// /(mag1new*magL);
double cos1L = (_qnewprf[_map[0]].x()*_bigLprf.x()
+_qnewprf[_map[0]].y()*_bigLprf.y()
+_qnewprf[_map[0]].z()*_bigLprf.z()
)
/(mag1new*magL);
return abs( (_m[0]*sqr(mag1new)/mag1old)
/ ( mag1new*(_m[0]-_bigLprf.e())
+_qnewprf[_map[0]].e()*magL*cos1L
)
);
}
LorentzRotation IFDipole::solveBoost(const Lorentz5Momentum & q,
const Lorentz5Momentum & p ) const {
Energy modp = p.vect().mag();
Energy modq = q.vect().mag();
double betam = (p.e()*modp-q.e()*modq)/(sqr(modq)+sqr(modp)+p.mass2());
Boost beta = -betam*q.vect().unit();
ThreeVector<Energy2> ax = p.vect().cross( q.vect() );
double delta = p.vect().angle( q.vect() );
LorentzRotation R;
using Constants::pi;
if ( ax.mag2()/GeV2/MeV2 > 1e-16 ) {
R.rotate( delta, unitVector(ax) ).boost( beta );
}
else {
if(p.mass()>ZERO) {
R.boost(p.findBoostToCM(),p.e()/p.mass());
R.boost(q.boostVector(),q.e()/q.mass());
}
else {
if(modp>modq) beta = -betam*p.vect().unit();
R.boost( beta );
}
}
return R;
}
void IFDipole::doinit() {
Interfaced::doinit();
// get the value fo alpha from the Standard Model object
_alpha=generator()->standardModel()->alphaEM();
}
diff --git a/Decay/Radiation/Makefile.am b/Decay/Radiation/Makefile.am
--- a/Decay/Radiation/Makefile.am
+++ b/Decay/Radiation/Makefile.am
@@ -1,15 +1,30 @@
noinst_LTLIBRARIES = libHwDecRad.la
-pkglib_LTLIBRARIES = HwSOPHTY.la
libHwDecRad_la_SOURCES = \
DecayRadiationGenerator.cc DecayRadiationGenerator.h \
DecayRadiationGenerator.fh \
QEDRadiationHandler.cc QEDRadiationHandler.fh\
QEDRadiationHandler.h
-HwSOPHTY_la_SOURCES = \
-SOPHTY.h SOPHTY.cc \
-FFDipole.cc FFDipole.fh FFDipole.h \
-IFDipole.cc IFDipole.fh IFDipole.h \
-YFSFormFactors.cc YFSFormFactors.h
-HwSOPHTY_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 3:0:0
+
+
+
+BUILT_SOURCES = Sophty__all.cc
+DISTCLEANFILES = Sophty__all.cc
+
+Sophty__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+SOPHTY.h \
+FFDipole.fh FFDipole.h \
+IFDipole.fh IFDipole.h \
+YFSFormFactors.h
+
+ALL_CC_FILES = \
+SOPHTY.cc \
+FFDipole.cc \
+IFDipole.cc \
+YFSFormFactors.cc
diff --git a/Decay/Radiation/YFSFormFactors.cc b/Decay/Radiation/YFSFormFactors.cc
--- a/Decay/Radiation/YFSFormFactors.cc
+++ b/Decay/Radiation/YFSFormFactors.cc
@@ -1,280 +1,280 @@
// -*- C++ -*-
//
// YFSFormFactors.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 YFSFormFactors class.
//
#include "YFSFormFactors.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include <cassert>
using namespace Herwig;
using Constants::pi;
using Herwig::Math::ReLi2;
const double YFSFormFactors::_alpha=1./137.03599911;
const Energy YFSFormFactors::_mgamma=1e-10*MeV;
const Energy2 YFSFormFactors::_tcut=1.e-11*GeV2;
const Energy YFSFormFactors::_ecut=1e-6*GeV;
double YFSFormFactors::ReBIF(Energy m0 ,Energy m1 , Energy2 t ,
double charge ,bool includegamma,
Energy mgamma) {
// mass squared for speed
Energy2 m02(m0*m0),m12(m1*m1),nu(0.5*(m02+m12-t)),mprod(m0*m1);
double Anu,vfinite;
double output;
// t>0
if(t>_tcut) {
// parameters
Energy2 lambda(sqrt((nu-mprod)*(nu+mprod)));
double eta(0.5*m12*t/lambda/(lambda+nu-m12)),zeta((lambda+nu)*eta/m12);
// simple A functions for virtual piece
InvEnergy2 A;
if(lambda>1e-6*GeV2){A=(log((lambda+nu)/mprod)/lambda);}
else{A=1./mprod;}
double A1((m02-m12)/t*log(m0/m1)-2.*sqr(lambda)/t*A-2.);
InvEnergy2 A3(A*log(2.*lambda/mprod)
+1./lambda*
(+0.25*(log((lambda+nu)/m02)+2.*log((lambda-nu+m02)/t ))*
log((lambda+nu)/m02)
+0.25*(log((lambda+nu)/m12)-2.*log((lambda+nu-m12)/m12))*
log((lambda+nu)/m12)
+0.5*(log(eta)*log(1.+eta)-log(zeta)*log(1.+zeta))
+ReLi2(-eta)-ReLi2(-zeta)));
Anu=nu*A;
vfinite=0.5*A1-nu*A3;
}
// t==0
else {
// virtual part of the dipole
Anu = (m02+m12)/(m02-m12)*log(m0/m1);
vfinite=0.5*(Anu-1.);
}
if(includegamma){output=-_alpha*charge/pi*((Anu-1.)*log(sqr(mgamma)/mprod)+vfinite);}
else {output=-_alpha*charge/pi*((Anu-1.)*log(MeV2/mprod)+vfinite);}
- // assert(!isnan(output) && !isinf(output));
+ // assert(isfinite(output));
return output;
}
double YFSFormFactors::ReBFF(Energy m1,Energy m2,Energy2 s,double charge,
bool includegamma,Energy mgamma) {
// masses etc
Energy2 m12(m1*m1),m22(m2*m2),mu(0.5*(s-m12-m22)),mprod(m1*m2);
// parameters
double ratio(m1*m2/mu),rho(sqrt((1.-ratio)*(1.+ratio)));
Energy2 prod(mu*(1.+rho));
// the finite piece
double vfinite(mu*rho/s*log(prod/mprod)+0.5*(m12-m22)/s*log(m1/m2)
+1./rho*(pi*pi-0.5*log(prod/m12)*log(prod/m22)
-0.5*sqr(log((m12+prod)/(m22+prod)))
-ReLi2(2.*mu*rho/(m12+prod))
-ReLi2(2.*mu*rho/(m22+prod)))-1.);
// the cut-off piece
double Anu(log(prod/mprod)/rho),output;
if(includegamma){output=-_alpha*charge/pi*((Anu-1.)*log(sqr(mgamma)/mprod)+vfinite);}
else {output=-_alpha*charge/pi*((Anu-1.)*log(MeV2/mprod)+vfinite);}
- // assert(!isnan(output) && !isinf(output));
+ // assert(isfinite(output));
return output;
}
double YFSFormFactors::BtildeIF(double beta0 ,double ombeta0 ,
double beta1 ,double ombeta1 ,
Energy en0 ,Energy en1 ,
Energy m0 ,Energy m1 ,
Energy2 t ,double charge ,
Energy emin ,bool includegamma,
Energy mgamma) {
// coefficient of the divergent piece
Energy2 mprod(m0*m1),nu(0.5*(m0*m0+m1*m1-t));
double Anu;
if(nu-mprod>1e-12*GeV2) {
Energy2 lambda(sqrt((nu-mprod)*(nu+mprod)));
Anu=nu/lambda*log((lambda+nu)/mprod);
}
else
{Anu=1.;}
// finite piece
double rfinite(-0.5*A4single(beta0,ombeta0)-0.5*A4single(beta1,ombeta1)
+nu*A4IF(beta0,ombeta0,beta1,ombeta1,en0,en1,m0,m1,t));
- // assert(!isnan(rfinite) && !isinf(rfinite));
+ // assert(isfinite(rfinite));
// return the answer
double output;
if(includegamma) {
output=-_alpha*charge/pi*((Anu-1.)*2.*log(2.*emin/mgamma)+rfinite);
}
else {
output=-_alpha*charge/pi*((Anu-1.)*2.*log(2.*emin/MeV)+rfinite);
}
- // assert(!isnan(output) && !isinf(output));
+ // assert(isfinite(output));
return output;
}
double YFSFormFactors::BtildeFF(double beta1 ,double ombeta1 ,
double beta2 ,double ombeta2 ,
Energy en1 ,Energy en2 ,
Energy m1 ,Energy m2 ,
Energy2 s ,double charge ,
Energy emin ,bool includegamma,
Energy mgamma) {
// masses etc
Energy2 m12(m1*m1),m22(m2*m2),mu(0.5*(s-m12-m22)),mprod(m1*m2);
// parameters
double ratio(m1*m2/mu),rho(sqrt((1.-ratio)*(1.+ratio)));
Energy2 prod(mu*(1.+rho));
// finite piece
double rfinite(-0.5*A4single(beta1,ombeta1)-0.5*A4single(beta2,ombeta2)
+mu*A4FFFull(en1,en2,beta1,beta2,m1,m2,s));
double Anu(log(prod/mprod)/rho);
// return the answer
double output;
if(includegamma){output=-_alpha*charge/pi*((Anu-1.)*2.*log(2.*emin/mgamma)+rfinite);}
else {output=-_alpha*charge/pi*((Anu-1.)*2.*log(2.*emin/MeV)+rfinite);}
- // assert(!isnan(output) && !isinf(output));
+ // assert(isfinite(output));
return output;
}
InvEnergy2 YFSFormFactors::A4FFFull(Energy inen1 ,Energy inen2,
double beta1,double beta2,
Energy inm1 ,Energy inm2,Energy2 s ) {
Energy en1(inen1),en2(inen2),m1(inm1),m2(inm2);
// order the particles so en1>en2
if(inen1*beta1<inen2*beta2) {
en1=inen2;
en2=inen1;
m1=inm2;
m2=inm1;
}
Energy Delta(en1-en2);
Energy Omega(en1+en2),delta(m1-m2),omega(m1+m2);
Energy2 Q2(s-2.*(m1*m1+m2*m2));
Energy root(sqrt(Delta*Delta+Q2));
Energy eta[2]={sqrt((en2-m2)*(en2+m2)),sqrt((en1-m1)*(en1+m1))+root};
if(0.5*(s-m1*m1-m2*m2)>en1*en2){eta[0]=-eta[0];}
Energy2 root2(sqrt((Q2+omega*omega)*(Q2+delta*delta)));
double Y[2];
// various limits
Energy y[4];
y[0]=0.5*(root-Omega+(omega*delta+root2)/(root+Delta));
y[1]=y[0]-root2/(root+Delta);
y[2]=0.5*(root+Omega+(omega*delta+root2)/(root-Delta));
y[3]=y[2]-root2/(root-Delta);
// the Y function at both limits
for(unsigned int ix=0;ix<2;++ix)
{Y[ix]=Zij(eta[ix],y[0],y[3])+Zij(eta[ix],y[1],y[0])
+Zij(eta[ix],y[2],y[1])-Zij(eta[ix],y[2],y[3])
+0.5*Xijkl(eta[ix],y[0],y[1],y[2],y[3])*Xijkl(eta[ix],y[1],y[2],y[0],y[3]);}
// the answer
// the Z function at both limits
double output(0.);
if(abs(Delta)>_ecut) {
output=log(abs((root-Delta)/(root+Delta)))*(+Xijkl(eta[1],y[0],y[3],y[1],y[2])
-Xijkl(eta[0],y[0],y[3],y[1],y[2]));
}
return 1./root2*(output+Y[1]-Y[0]);
}
InvEnergy2 YFSFormFactors::A4IF(double beta0 ,double ombeta0 ,
double beta1 ,double ombeta1 ,
Energy en0 ,Energy en1 , Energy m0 ,Energy m1 ,
Energy2 t) {
// this is the general function so pick the special case
if(t>_tcut){
// rest frame of decaying particle t!=0
if(abs(en0-m0)<_ecut){return A4IFRest(m0,m1,beta1,ombeta1,en1);}
// rest frame of decay product t!=0
else if(abs(en1-m1)<_ecut){return A4IFRest(m1,m0,beta0,ombeta0,en0);}
// general frame t!=0
else
{return A4IFFull(beta0,beta1,en0,en1,m0,m1,t);}
}
else {
// rest frame of decaying particle t=0
if(abs(en0-m0)<_ecut){return A4IFRestZero(m0,m1);}
// rest frame of decay products t=0
else if(abs(en1-m1)<_ecut){return A4IFRestZero(m1,m0);}
// general frame t=0
else{return A4IFZero(beta0,beta1,ombeta1,en0,en1,m0,m1);}
}
}
InvEnergy2 YFSFormFactors::A4IFZero(double beta0, double beta1, double ombeta1,
Energy en0,
Energy en1 , Energy m0 , Energy m1) {
Energy Delta = en0-en1;
Energy2 mu2 = (m0-m1)*(m0+m1);
long double z[2]={ beta1*en1/Delta, beta0*en0/Delta-1. };
long double y[3],xi[3];
y[0]=en1/Delta;
y[1]=y[0]-0.5*mu2/sqr(Delta);
y[2]=-y[0]+2.*m1*m1/mu2;
for(unsigned int ix = 0; ix < 3; ++ix) {
if ( ix == 0 ) xi[0] = -ombeta1*y[0] / (z[1] - y[0] );
else xi[ix] = (z[0] - y[ix]) / (z[1] - y[ix]);
}
long double U[2];
for(unsigned int ix=0;ix<2;++ix) {
// U[ix] = 0.5*sqr(log(abs((z[ix]-y[0])*(z[ix]-y[1])/(z[ix]-y[2]))))
// +log(abs(z[ix]-y[0]))*log(abs(z[ix]-y[0])/sqr(z[ix]-y[1]))
// +2.*ReLi2((y[1]-y[0])/(z[ix]-y[0]))
// +2.*ReLi2((y[2]-y[1])/(z[ix]-y[1]));
const long double a = ix==0 ? -ombeta1*y[0] : z[ix]-y[0];
const long double b = z[ix]-y[1];
const long double c = z[ix]-y[2];
const long double A = abs(a*b/c);
const long double B = abs(a);
const long double C = B/sqr(b);
const long double D = (y[1]-y[0])/a;
const long double E = (y[2]-y[1])/b;
U[ix] = 0.5*sqr(log(A)) + log(B)*log(C) + 2.*ReLi2(D) + 2.*ReLi2(E);
}
return 1./mu2*(log(2.*sqr(Delta)/mu2)*log(abs(xi[1]*xi[2]/xi[0]))+U[1]-U[0]);
}
InvEnergy2 YFSFormFactors::A4IFRest(Energy m0 ,Energy m1, double beta1,
double ombeta1, Energy E1) {
Energy Mfact0 = m0-E1*ombeta1;
Energy Mfact1 = m0-E1*(1.+beta1);
Energy2 Mfact2 = m0*E1*(1.+beta1)-m1*m1;
Energy2 Mfact3 = m0*E1*ombeta1-m1*m1;
Energy2 qprod(m0*E1*beta1);
return 0.5/qprod*(+log(abs(Mfact0/Mfact1))*log(E1*(1.+beta1)/m0)
-2.*log(abs(2.*beta1*E1*Mfact0/m0/m1))*log(E1*(1.+beta1)/m1)
+2.*ReLi2(E1/m0*ombeta1)-2.*ReLi2(E1/m0*(1.+beta1))
+ReLi2(-0.5*Mfact1/beta1/E1)-ReLi2( 0.5*Mfact0/beta1/E1)
+ReLi2( 0.5*Mfact2/qprod )-ReLi2(-0.5*Mfact3/qprod));
}
InvEnergy2 YFSFormFactors::A4IFFull(Velocity beta0,Velocity beta1,
Energy en0 ,Energy en1 ,
Energy m0 ,Energy m1 , Energy2 t) {
Energy Delta(en0-en1),Omega(en0+en1),delta(m0-m1),omega(m0+m1);
Energy T(sqrt(sqr(Delta)-t)),V(Delta+T);
Energy2 kappa(sqrt((sqr(omega)-t)*(sqr(delta)-t)));
long double y[4]={-0.5/T*(T+Omega-(omega*delta+kappa)*V/t),
-0.5/T*(T+Omega-(omega*delta-kappa)*V/t),
-0.5/T*(T-Omega+(omega*delta+kappa)/V),
-0.5/T*(T-Omega+(omega*delta-kappa)/V)};
long double z[2]={beta1*en1/T,beta0*en0/T-1.};
double Y[2],lfact(log(abs(V*V/t)));
for(unsigned int ix=0;ix<2;++ix) {
Y[ix] = lfact*Xijkl(z[ix],y[0],y[3],y[1],y[2])
+Zij(z[ix],y[0],y[3])
+Zij(z[ix],y[1],y[0])
+Zij(z[ix],y[2],y[1])
-Zij(z[ix],y[2],y[3])
+0.5*Xijkl(z[ix],y[0],y[1],y[2],y[3])*Xijkl(z[ix],y[1],y[2],y[0],y[3]);
}
return (Y[1]-Y[0])/kappa;
}
diff --git a/Decay/ScalarMeson/Makefile.am b/Decay/ScalarMeson/Makefile.am
--- a/Decay/ScalarMeson/Makefile.am
+++ b/Decay/ScalarMeson/Makefile.am
@@ -1,20 +1,43 @@
-pkglib_LTLIBRARIES = HwSMDecay.la
+BUILT_SOURCES = SMDecayer__all.cc
+DISTCLEANFILES = SMDecayer__all.cc
-HwSMDecay_la_SOURCES = \
-EtaPiGammaGammaDecayer.cc EtaPiGammaGammaDecayer.h\
-EtaPiPiGammaDecayer.cc EtaPiPiGammaDecayer.h \
-EtaPiPiPiDecayer.cc EtaPiPiPiDecayer.h \
-PScalar4FermionsDecayer.cc PScalar4FermionsDecayer.h\
-PScalarLeptonNeutrinoDecayer.cc PScalarLeptonNeutrinoDecayer.h\
-PScalarPScalarVectorDecayer.cc PScalarPScalarVectorDecayer.h \
-PScalarVectorFermionsDecayer.cc PScalarVectorFermionsDecayer.h\
-PScalarVectorVectorDecayer.cc PScalarVectorVectorDecayer.h\
-ScalarMesonTensorScalarDecayer.cc ScalarMesonTensorScalarDecayer.h\
-ScalarScalarScalarDecayer.cc ScalarScalarScalarDecayer.h \
-SemiLeptonicScalarDecayer.cc SemiLeptonicScalarDecayer.h \
-ScalarMesonFactorizedDecayer.cc ScalarMesonFactorizedDecayer.h \
-ScalarVectorVectorDecayer.h ScalarVectorVectorDecayer.cc \
-DtoKPiPiCLEO.h DtoKPiPiCLEO.cc \
-DtoKPiPiE691.h DtoKPiPiE691.cc\
-DtoKPiPiMarkIII.h DtoKPiPiMarkIII.cc
-HwSMDecay_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 10:0:0
+SMDecayer__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+EtaPiGammaGammaDecayer.h\
+EtaPiPiGammaDecayer.h \
+EtaPiPiPiDecayer.h \
+PScalar4FermionsDecayer.h\
+PScalarLeptonNeutrinoDecayer.h\
+PScalarPScalarVectorDecayer.h \
+PScalarVectorFermionsDecayer.h\
+PScalarVectorVectorDecayer.h\
+ScalarMesonTensorScalarDecayer.h\
+ScalarScalarScalarDecayer.h \
+SemiLeptonicScalarDecayer.h \
+ScalarMesonFactorizedDecayer.h \
+ScalarVectorVectorDecayer.h \
+DtoKPiPiCLEO.h \
+DtoKPiPiE691.h \
+DtoKPiPiMarkIII.h
+
+ALL_CC_FILES = \
+EtaPiGammaGammaDecayer.cc \
+EtaPiPiGammaDecayer.cc \
+EtaPiPiPiDecayer.cc \
+PScalar4FermionsDecayer.cc \
+PScalarLeptonNeutrinoDecayer.cc \
+PScalarPScalarVectorDecayer.cc \
+PScalarVectorFermionsDecayer.cc \
+PScalarVectorVectorDecayer.cc \
+ScalarMesonTensorScalarDecayer.cc \
+ScalarScalarScalarDecayer.cc \
+SemiLeptonicScalarDecayer.cc \
+ScalarMesonFactorizedDecayer.cc \
+ScalarVectorVectorDecayer.cc \
+DtoKPiPiCLEO.cc \
+DtoKPiPiE691.cc\
+DtoKPiPiMarkIII.cc
diff --git a/Decay/Tau/Makefile.am b/Decay/Tau/Makefile.am
--- a/Decay/Tau/Makefile.am
+++ b/Decay/Tau/Makefile.am
@@ -1,4 +1,1 @@
-pkglib_LTLIBRARIES = HwTauDecay.la
-
-HwTauDecay_la_SOURCES = TauDecayer.cc TauDecayer.h
-HwTauDecay_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 9:0:0
+EXTRA_DIST = TauDecayer.cc TauDecayer.h
diff --git a/Decay/TensorMeson/Makefile.am b/Decay/TensorMeson/Makefile.am
--- a/Decay/TensorMeson/Makefile.am
+++ b/Decay/TensorMeson/Makefile.am
@@ -1,7 +1,17 @@
-pkglib_LTLIBRARIES = HwTMDecay.la
+BUILT_SOURCES = TMDecayer__all.cc
+DISTCLEANFILES = TMDecayer__all.cc
-HwTMDecay_la_SOURCES = \
-TensorMeson2PScalarDecayer.cc TensorMeson2PScalarDecayer.h\
-TensorMesonVectorPScalarDecayer.cc TensorMesonVectorPScalarDecayer.h \
-TensorMesonVectorVectorDecayer.cc TensorMesonVectorVectorDecayer.h
-HwTMDecay_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 8:0:0
+TMDecayer__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+TensorMeson2PScalarDecayer.h\
+TensorMesonVectorPScalarDecayer.h \
+TensorMesonVectorVectorDecayer.h
+
+ALL_CC_FILES = \
+TensorMeson2PScalarDecayer.cc \
+TensorMesonVectorPScalarDecayer.cc \
+TensorMesonVectorVectorDecayer.cc
diff --git a/Decay/VectorMeson/Makefile.am b/Decay/VectorMeson/Makefile.am
--- a/Decay/VectorMeson/Makefile.am
+++ b/Decay/VectorMeson/Makefile.am
@@ -1,17 +1,37 @@
-pkglib_LTLIBRARIES = HwVMDecay.la
+BUILT_SOURCES = VMDecayer__all.cc
+DISTCLEANFILES = VMDecayer__all.cc
-HwVMDecay_la_SOURCES = \
-a1ThreePionCLEODecayer.cc a1ThreePionCLEODecayer.h \
-a1SimpleDecayer.cc a1SimpleDecayer.h\
-a1ThreePionDecayer.cc a1ThreePionDecayer.h \
-PVectorMesonVectorPScalarDecayer.cc PVectorMesonVectorPScalarDecayer.h \
-VectorMeson2FermionDecayer.cc VectorMeson2FermionDecayer.h \
-VectorMeson2MesonDecayer.cc VectorMeson2MesonDecayer.h \
-VectorMeson3PionDecayer.cc VectorMeson3PionDecayer.h \
-VectorMesonPScalarFermionsDecayer.cc VectorMesonPScalarFermionsDecayer.h \
-VectorMesonPVectorPScalarDecayer.cc VectorMesonPVectorPScalarDecayer.h \
-VectorMesonVectorPScalarDecayer.cc VectorMesonVectorPScalarDecayer.h \
-VectorMesonVectorScalarDecayer.cc VectorMesonVectorScalarDecayer.h \
-VectorMesonVectorVectorDecayer.cc VectorMesonVectorVectorDecayer.h \
-OniumToOniumPiPiDecayer.cc OniumToOniumPiPiDecayer.h
-HwVMDecay_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 8:0:0
+VMDecayer__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+a1ThreePionCLEODecayer.h \
+a1SimpleDecayer.h\
+a1ThreePionDecayer.h \
+PVectorMesonVectorPScalarDecayer.h \
+VectorMeson2FermionDecayer.h \
+VectorMeson2MesonDecayer.h \
+VectorMeson3PionDecayer.h \
+VectorMesonPScalarFermionsDecayer.h \
+VectorMesonPVectorPScalarDecayer.h \
+VectorMesonVectorPScalarDecayer.h \
+VectorMesonVectorScalarDecayer.h \
+VectorMesonVectorVectorDecayer.h \
+OniumToOniumPiPiDecayer.h
+
+ALL_CC_FILES = \
+a1ThreePionCLEODecayer.cc \
+a1SimpleDecayer.cc \
+a1ThreePionDecayer.cc \
+PVectorMesonVectorPScalarDecayer.cc \
+VectorMeson2FermionDecayer.cc \
+VectorMeson2MesonDecayer.cc \
+VectorMeson3PionDecayer.cc \
+VectorMesonPScalarFermionsDecayer.cc \
+VectorMesonPVectorPScalarDecayer.cc \
+VectorMesonVectorPScalarDecayer.cc \
+VectorMesonVectorScalarDecayer.cc \
+VectorMesonVectorVectorDecayer.cc \
+OniumToOniumPiPiDecayer.cc
diff --git a/Decay/WeakCurrents/FourPionNovosibirskCurrent.cc b/Decay/WeakCurrents/FourPionNovosibirskCurrent.cc
--- a/Decay/WeakCurrents/FourPionNovosibirskCurrent.cc
+++ b/Decay/WeakCurrents/FourPionNovosibirskCurrent.cc
@@ -1,1217 +1,1212 @@
// -*- C++ -*-
//
// FourPionNovosibirskCurrent.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 FourPionNovosibirskCurrent class.
//
#include "FourPionNovosibirskCurrent.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Helicity/ScalarSpinInfo.h"
#include "Herwig/PDT/ThreeBodyAllOnCalculator.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include <functional>
using namespace Herwig;
using namespace ThePEG;
using namespace ThePEG::Helicity;
DescribeClass<FourPionNovosibirskCurrent,WeakDecayCurrent>
describeHerwigFourPionNovosibirskCurrent("Herwig::FourPionNovosibirskCurrent",
"HwWeakCurrents.so");
HERWIG_INTERPOLATOR_CLASSDESC(FourPionNovosibirskCurrent1,Energy,Energy2)
HERWIG_INTERPOLATOR_CLASSDESC(FourPionNovosibirskCurrent2,double,Energy)
HERWIG_INTERPOLATOR_CLASSDESC(FourPionNovosibirskCurrent3,double,Energy2)
-namespace {
- inline Energy timesGeV (double x) { return x * GeV; }
- inline Energy2 timesGeV2(double x) { return x * GeV2; }
-}
-
IBPtr FourPionNovosibirskCurrent::clone() const {
return new_ptr(*this);
}
IBPtr FourPionNovosibirskCurrent::fullclone() const {
return new_ptr(*this);
}
void FourPionNovosibirskCurrent::doupdate() {
WeakDecayCurrent::doupdate();
// update running width if needed
if ( !touched() ) return;
if(_maxmass!=_maxcalc) inita1width(-1);
}
FourPionNovosibirskCurrent::FourPionNovosibirskCurrent() : _mpic(), _mpi0(),
_mpic2(), _mpi02(), _prho()
{
// set the number of modes
addDecayMode(2,-1);
addDecayMode(2,-1);
setInitialModes(2);
// masses of the particles used in the current
_rhomass = 0.7761*GeV;
_a1mass = 1.2300*GeV;
_omegamass = 0.7820*GeV;
_sigmamass = 0.8000*GeV;
// widths of the particles used in the current
_rhowidth = 0.14450*GeV;
_a1width = 0.45000*GeV;
_omegawidth = 0.00841*GeV;
_sigmawidth = 0.80000*GeV;
// parameters for the resonance used in the integration
_intmass = 1.4*GeV;
_intwidth = 0.5*GeV;
// relative coupling of the sigma and rho in the a_1 decay
_zmag = 1.3998721;
_zphase = 0.43585036;
_zsigma=0.;
// parameter for f_a1
_lambda2 = 1.2*GeV2;
_onedlam2 = 1./_lambda2;
_a1massolam2 = _a1mass*_a1mass*_onedlam2;
_hm2=ZERO;
_rhoD=ZERO;
_dhdq2m2=0.;
// use local values of the parameters
_localparameters=true;
// magic numbers from TAUOLA (N.B. conversion from GeV to MeV)
_athreec = 76.565/GeV;
_bthreec = 0.71709;
_cthreec = 0.27505;
_aomega = 886.84/GeV;
_bomega = 0.70983;
_comega = 0.26689;
_aonec = 96.867/GeV;
_bonec = 0.70907;
_conec = 0.26413;
//parameters for the running omega width
_omegaparam.resize(10);
_omegaparam[0] = 17.560;
_omegaparam[1] = 141.110;
_omegaparam[2] = 894.884;
_omegaparam[3] = 4977.35;
_omegaparam[4] = 7610.66;
_omegaparam[5] =-42524.4;
_omegaparam[6] =-1333.26;
_omegaparam[7] = 4860.19;
_omegaparam[8] =-6000.81;
_omegaparam[9] = 2504.97;
// values of the g omega function from hep-ph/0201149
double Fomegainit[98]={ 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000,
0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000,
0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000,
0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000,
0.0000000, 0.0000000, 0.0000000, 0.0000000, 2.2867811,
2.9710648, 2.9344304, 2.6913538, 2.5471206, 2.3557470,
2.2448280, 2.1074708, 2.0504866, 1.9270257, 1.8669430,
1.7907301, 1.7184515, 1.6535717, 1.6039416, 1.5535343,
1.5065620, 1.4608675, 1.4215596, 1.3849826, 1.3480113,
1.3147917, 1.2793381, 1.2487282, 1.2184237, 1.1952927,
1.1683835, 1.1458827, 1.1145806, 1.0935820, 1.0608720,
1.0390474, 1.0164336, 0.9908721, 0.9585276, 0.9307971,
0.9017274, 0.8731154, 0.8452763, 0.8145532, 0.7817339,
0.7493086, 0.7199919, 0.6887290, 0.6568120, 0.6255773,
0.5944664, 0.5661956, 0.5391204, 0.5102391, 0.4786543,
0.4546428, 0.4316779, 0.4063754, 0.3769831, 0.3561141,
0.3333555, 0.3139160, 0.2949214, 0.2814728, 0.2602444,
0.2349602, 0.2269845, 0.2192318, 0.2286938, 0.2839763,
0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000,
0.0000000, 0.0000000, 0.0000000};
// values of the three charged pion G function from hep-ph/0201149
double Fthreeinit[98]={ 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000,
0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000,
0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000,
13.1664906,10.7234087, 8.8219614,10.7989664, 9.1883001,
7.8526378, 7.7481031, 8.2633696, 5.5042820, 4.9029269,
4.4794345, 3.9654009, 4.5254011, 3.6509495, 3.5005512,
3.2274280, 3.1808922, 2.9925177, 2.6886659, 2.5195024,
2.4678771, 2.3540580, 2.2123868, 2.1103525, 2.0106986,
1.8792295, 1.8250662, 1.7068460, 1.6442842, 1.5503920,
1.4814349, 1.4225838, 1.3627135, 1.3205355, 1.2784383,
1.2387408, 1.1975995, 1.1633024, 1.1318133, 1.1114354,
1.0951439, 1.0691465, 1.0602311, 1.0392803, 1.0220672,
1.0154786, 1.0010130, 0.9908018, 0.9710845, 0.9602382,
0.9488459, 0.9316537, 0.9118049, 0.8920435, 0.8719332,
0.8520256, 0.8280582, 0.8064085, 0.7767881, 0.7570597,
0.7382626, 0.7100251, 0.6846500, 0.6666913, 0.6372250,
0.6162248, 0.6007728, 0.5799103, 0.5674670, 0.5446148,
0.5352115, 0.5128809, 0.4932536, 0.5310397, 0.8566489,
0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000,
0.0000000, 0.0000000, 0.0000000};
double Foneinit[98]={ 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000,
0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000,
0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000,
1.4819183, 1.7086354, 1.6958492, 1.6172935, 1.6301320,
1.5719706, 1.5459771, 1.5377471, 1.5008864, 1.4924121,
1.4720882, 1.4371741, 1.3990080, 1.3879193, 1.4030601,
1.3768673, 1.3493533, 1.3547127, 1.3275831, 1.3167892,
1.3035913, 1.2968298, 1.2801558, 1.2650299, 1.2557997,
1.2325822, 1.2210644, 1.1935984, 1.1746194, 1.1510350,
1.1358515, 1.1205584, 1.1010553, 1.0903869, 1.0731295,
1.0578678, 1.0438409, 1.0377911, 1.0253277, 1.0103551,
1.0042409, 0.9937978, 0.9858117, 0.9770346, 0.9724492,
0.9656686, 0.9606671, 0.9525813, 0.9488522, 0.9417335,
0.9399430, 0.9323438, 0.9281269, 0.9244171, 0.9237418,
0.9174354, 0.9177181, 0.9120840, 0.9047825, 0.9065579,
0.9034142, 0.8992961, 0.9011586, 0.9036470, 0.8954964,
0.8898208, 0.8911991, 0.8854824, 0.8888282, 0.8868449,
0.9004632, 0.8981572, 0.9096183, 0.9046990, 1.7454215,
0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000,
0.0000000, 0.0000000, 0.0000000};
// eninit in GeV
double eninit[98]={ 0.6000000, 0.6131313, 0.6262626, 0.6393939, 0.6525252,
0.6656566, 0.6787879, 0.6919192, 0.7050505, 0.7181818,
0.7313131, 0.7444444, 0.7575758, 0.7707071, 0.7838384,
0.7969697, 0.8101010, 0.8232324, 0.8363636, 0.8494949,
0.8626263, 0.8757576, 0.8888889, 0.9020202, 0.9151515,
0.9282829, 0.9414141, 0.9545454, 0.9676768, 0.9808081,
0.9939394, 1.0070707, 1.0202020, 1.0333333, 1.0464647,
1.0595959, 1.0727273, 1.0858586, 1.0989898, 1.1121212,
1.1252525, 1.1383839, 1.1515151, 1.1646465, 1.1777778,
1.1909091, 1.2040404, 1.2171717, 1.2303030, 1.2434343,
1.2565657, 1.2696970, 1.2828283, 1.2959596, 1.3090909,
1.3222222, 1.3353535, 1.3484849, 1.3616161, 1.3747475,
1.3878788, 1.4010102, 1.4141414, 1.4272727, 1.4404041,
1.4535353, 1.4666667, 1.4797980, 1.4929293, 1.5060606,
1.5191919, 1.5323232, 1.5454545, 1.5585859, 1.5717171,
1.5848485, 1.5979798, 1.6111112, 1.6242424, 1.6373737,
1.6505051, 1.6636363, 1.6767677, 1.6898990, 1.7030303,
1.7161616, 1.7292930, 1.7424242, 1.7555555, 1.7686869,
1.7818182, 1.7949495, 1.8080808, 1.8212122, 1.8343434,
1.8474747, 1.8606061, 1.8737373};
// ensigma in GeV2
double ensigma[100]={ 0.2916000, 0.3206586, 0.3497172, 0.3787757, 0.4078344,
0.4368929, 0.4659515, 0.4950101, 0.5240687, 0.5531273,
0.5821859, 0.6112444, 0.6403030, 0.6693616, 0.6984202,
0.7274788, 0.7565374, 0.7855960, 0.8146545, 0.8437131,
0.8727717, 0.9018303, 0.9308889, 0.9599475, 0.9890060,
1.0180646, 1.0471232, 1.0761818, 1.1052403, 1.1342990,
1.1633576, 1.1924162, 1.2214748, 1.2505333, 1.2795919,
1.3086505, 1.3377091, 1.3667676, 1.3958262, 1.4248848,
1.4539435, 1.4830021, 1.5120606, 1.5411192, 1.5701778,
1.5992364, 1.6282949, 1.6573535, 1.6864121, 1.7154707,
1.7445292, 1.7735878, 1.8026465, 1.8317051, 1.8607637,
1.8898222, 1.9188808, 1.9479394, 1.9769980, 2.0060565,
2.0351152, 2.0641737, 2.0932324, 2.1222908, 2.1513495,
2.1804080, 2.2094667, 2.2385252, 2.2675838, 2.2966425,
2.3257010, 2.3547597, 2.3838181, 2.4128768, 2.4419353,
2.4709940, 2.5000525, 2.5291111, 2.5581696, 2.5872283,
2.6162868, 2.6453454, 2.6744041, 2.7034626, 2.7325213,
2.7615798, 2.7906384, 2.8196969, 2.8487556, 2.8778141,
2.9068727, 2.9359312, 2.9649899, 2.9940486, 3.0231071,
3.0521657, 3.0812242, 3.1102829, 3.1393414, 3.1684000};
double Fsigma[100]={ 2.0261996, 2.2349865, 2.4839740, 2.7840748, 3.1488798,
3.5936222, 4.1301847, 4.7517977, 5.3984838, 5.9147439,
6.0864558, 5.8283591, 5.2841811, 4.6615186, 4.0839195,
3.5914702, 3.1841860, 2.8494759, 2.5732665, 2.3434010,
2.1502059, 1.9862038, 1.8456544, 1.7241427, 1.6182493,
1.5253036, 1.4432002, 1.3702650, 1.3051554, 1.2467849,
1.1942677, 1.1468738, 1.1039963, 1.0651271, 1.0298390,
0.9977714, 0.9686196, 0.9421255, 0.9180685, 0.8962603,
0.8765374, 0.8587573, 0.8427927, 0.8285285, 0.8158574,
0.8046767, 0.7948853, 0.7863811, 0.7790571, 0.7728010,
0.7674922, 0.7630011, 0.7591889, 0.7559078, 0.7530031,
0.7503147, 0.7476809, 0.7449428, 0.7419487, 0.7385587,
0.7346500, 0.7301207, 0.7248930, 0.7189151, 0.7121620,
0.7046344, 0.6963565, 0.6873729, 0.6777444, 0.6675445,
0.6568548, 0.6457604, 0.6343476, 0.6227004, 0.6108983,
0.5990148, 0.5871165, 0.5752623, 0.5635037, 0.5518846,
0.5404415, 0.5292045, 0.5181981, 0.5074410, 0.4969472,
0.4867267, 0.4767860, 0.4671288, 0.4577557, 0.4486661,
0.4398569, 0.4313242, 0.4230627, 0.4150662, 0.4073282,
0.3998415, 0.3925985, 0.3855914, 0.3788125, 0.3722538};
// set up the interpolators
_Fomega = make_InterpolatorPtr( 98,Fomegainit,1.0,eninit, GeV, 1);
_Fthreec = make_InterpolatorPtr( 98,Fthreeinit,1.0,eninit, GeV, 1);
_Fonec = make_InterpolatorPtr( 98,Foneinit ,1.0,eninit, GeV, 1);
_Fsigma = make_InterpolatorPtr(100,Fsigma ,1.0,ensigma,GeV2,1);
// initialise the calculation of the a_1 width
_initializea1=false;
// in GeV2
double a1q2in[200]={0,15788.6,31577.3,47365.9,63154.6,78943.2,94731.9,110521,
126309,142098,157886,173675,189464,205252,221041,236830,252618,
268407,284196,299984,315773,331562,347350,363139,378927,394716,
410505,426293,442082,457871,473659,489448,505237,521025,536814,
552603,568391,584180,599969,615757,631546,647334,663123,678912,
694700,710489,726278,742066,757855,773644,789432,805221,821010,
836798,852587,868375,884164,899953,915741,931530,947319,963107,
978896,994685,1.01047e+06,1.02626e+06,1.04205e+06,1.05784e+06,
1.07363e+06,1.08942e+06,1.10521e+06,1.12099e+06,1.13678e+06,
1.15257e+06,1.16836e+06,1.18415e+06,1.19994e+06,1.21573e+06,
1.23151e+06,1.2473e+06,1.26309e+06,1.27888e+06,1.29467e+06,
1.31046e+06,1.32625e+06,1.34203e+06,1.35782e+06,1.37361e+06,
1.3894e+06,1.40519e+06,1.42098e+06,1.43677e+06,1.45256e+06,
1.46834e+06,1.48413e+06,1.49992e+06,1.51571e+06,1.5315e+06,
1.54729e+06,1.56308e+06,1.57886e+06,1.59465e+06,1.61044e+06,
1.62623e+06,1.64202e+06,1.65781e+06,1.6736e+06,1.68939e+06,
1.70517e+06,1.72096e+06,1.73675e+06,1.75254e+06,1.76833e+06,
1.78412e+06,1.79991e+06,1.81569e+06,1.83148e+06,1.84727e+06,
1.86306e+06,1.87885e+06,1.89464e+06,1.91043e+06,1.92621e+06,
1.942e+06,1.95779e+06,1.97358e+06,1.98937e+06,2.00516e+06,
2.02095e+06,2.03674e+06,2.05252e+06,2.06831e+06,2.0841e+06,
2.09989e+06,2.11568e+06,2.13147e+06,2.14726e+06,2.16304e+06,
2.17883e+06,2.19462e+06,2.21041e+06,2.2262e+06,2.24199e+06,
2.25778e+06,2.27356e+06,2.28935e+06,2.30514e+06,2.32093e+06,
2.33672e+06,2.35251e+06,2.3683e+06,2.38409e+06,2.39987e+06,
2.41566e+06,2.43145e+06,2.44724e+06,2.46303e+06,2.47882e+06,
2.49461e+06,2.51039e+06,2.52618e+06,2.54197e+06,2.55776e+06,
2.57355e+06,2.58934e+06,2.60513e+06,2.62092e+06,2.6367e+06,
2.65249e+06,2.66828e+06,2.68407e+06,2.69986e+06,2.71565e+06,
2.73144e+06,2.74722e+06,2.76301e+06,2.7788e+06,2.79459e+06,
2.81038e+06,2.82617e+06,2.84196e+06,2.85774e+06,2.87353e+06,
2.88932e+06,2.90511e+06,2.9209e+06,2.93669e+06,2.95248e+06,
2.96827e+06,2.98405e+06,2.99984e+06,3.01563e+06,3.03142e+06,
3.04721e+06,3.063e+06,3.07879e+06,3.09457e+06,3.11036e+06,
3.12615e+06,3.14194e+06};
// in GeV
double a1widthin[200]={0,0,0,0,0,0,0,0,
0,0,0,0,0.000634625,0.00686721,0.026178,0.066329,
0.134996,0.239698,0.387813,0.586641,0.843471,1.16567,
1.56076,2.03654,2.60115,3.26324,4.03202,4.91749,
5.93053,7.08313,8.38858,9.86176,11.5194,13.3805,
15.4667,17.8029,20.4175,23.3438,26.6202,30.2917,
34.4108,39.0384,44.2457,50.1143,56.7369,64.2147,
72.6566,82.1666,92.8329,104.708,117.786,131.981,
147.124,162.974,179.244,195.64,211.904,227.818,
243.223,257.991,272.06,285.392,297.971,309.8,
320.894,331.278,340.979,350.03,358.463,366.31,
373.608,380.386,386.677,392.511,397.945,402.935,
407.563,411.841,415.79,419.433,422.766,425.853,
428.695,431.302,433.715,435.883,437.887,439.716,
441.426,442.947,444.326,445.575,446.65,447.666,
448.578,449.395,450.123,450.821,451.343,451.847,
452.283,452.859,452.987,453.266,453.496,453.686,
453.839,453.958,454.05,454.113,454.149,454.16,
454.154,454.13,454.091,454.037,453.966,453.9,
453.814,453.724,453.628,453.528,453.417,453.314,
453.206,453.1,452.995,452.891,452.79,452.697,
452.598,452.509,452.423,452.343,452.269,452.201,
452.141,452.086,452.039,452.004,451.966,451.941,
451.926,451.888,451.919,451.928,451.945,451.971,
452.006,452.05,452.102,452.163,452.234,452.421,
452.401,452.498,452.605,452.718,452.84,452.971,
453.111,453.261,453.417,453.583,453.756,453.937,
454.126,454.324,454.529,455.023,454.964,455.719,
455.428,455.671,455.921,456.179,456.444,456.695,
456.996,457.276,457.57,457.867,458.171,458.478,
458.793,459.115,459.442,459.777,460.115,460.458,
460.809,461.161,461.52,461.884,462.253,462.626,
463.004,463.832,463.778,464.166};
vector<double> tmp1(a1widthin,a1widthin+200);
_a1runwidth.clear();
std::transform(tmp1.begin(), tmp1.end(),
back_inserter(_a1runwidth),
- timesGeV);
+ [](double x){return x*GeV;});
vector<double> tmp2(a1q2in,a1q2in+200);
_a1runq2.clear();
std::transform(tmp2.begin(), tmp2.end(),
back_inserter(_a1runq2),
- timesGeV2);
+ [](double x){return x*GeV2;});
_maxmass=ZERO;
_maxcalc=ZERO;
}
void FourPionNovosibirskCurrent::doinit() {
WeakDecayCurrent::doinit();
// pion masses
_mpic=getParticleData(ParticleID::piplus)->mass();
_mpic2=sqr(_mpic);
_mpi0=getParticleData(ParticleID::pi0)->mass();
_mpi02=sqr(_mpi0);
if(!_localparameters) {
_rhomass = getParticleData(ParticleID::rhominus)->mass();
_rhowidth = getParticleData(ParticleID::rhominus)->width();
_omegamass = getParticleData(ParticleID::omega)->mass();
_omegawidth = getParticleData(ParticleID::omega)->width();
_sigmamass = getParticleData(9000221)->mass();
_sigmawidth = getParticleData(9000221)->width();
_a1mass = getParticleData(ParticleID::a_1minus)->mass();
_a1width = getParticleData(ParticleID::a_1minus)->width();
}
// calculate the constants for the a_1 form factor
_onedlam2 = 1./_lambda2;
_a1massolam2 = _a1mass*_a1mass*_onedlam2;
// parameter for the sigma breit-wigner
_psigma.push_back(Kinematics::pstarTwoBodyDecay(_sigmamass,_mpi0,_mpi0));
_psigma.push_back(Kinematics::pstarTwoBodyDecay(_sigmamass,_mpic,_mpic));
// parameters for the rho breit wigner
_prho=Kinematics::pstarTwoBodyDecay(_rhomass,_mpic,_mpic);
_hm2 = hFunction(_rhomass);
_dhdq2m2=dhdq2Parameter();
_rhoD=DParameter();
// convert the magnitude and phase of z into a phase
_zsigma = _zmag*(cos(_zphase)+Complex(0.,1.)*sin(_zphase));
// initialize the a_1 width
inita1width(-1);
}
void FourPionNovosibirskCurrent::doinitrun() {
// set up the running a_1 width
inita1width(0);
WeakDecayCurrent::doinitrun();
}
void FourPionNovosibirskCurrent::persistentOutput(PersistentOStream & os) const {
os << _a1runinter << _Fomega << _Fthreec << _Fonec << _Fsigma
<< ounit(_rhomass,GeV) << ounit(_a1mass,GeV) << ounit(_omegamass,GeV)
<< ounit(_sigmamass,GeV) << ounit(_rhowidth,GeV) << ounit(_a1width,GeV)
<< ounit(_omegawidth,GeV) << ounit(_sigmawidth,GeV)
<< _zsigma << ounit(_lambda2,GeV2)
<< _initializea1 << _localparameters
<< ounit(_a1runwidth,GeV) << ounit(_a1runq2,GeV2) << ounit(_onedlam2,1/GeV2)
<< _a1massolam2 << ounit(_psigma,GeV) << ounit(_mpic,GeV) << ounit(_mpi0,GeV)
<< ounit(_aomega,1/GeV) << ounit(_athreec,1/GeV) << ounit(_aonec,1/GeV)
<< _bomega << _bthreec << _bonec
<< _comega << _cthreec <<_conec << _omegaparam
<< ounit(_intwidth,GeV) << ounit(_intmass,GeV)
<< ounit(_mpic2,GeV2) << ounit(_mpi02,GeV2) << ounit(_hm2,GeV2) << _dhdq2m2
<< ounit(_prho,GeV) << ounit(_rhoD,GeV2) << _zmag << _zphase
<< ounit(_maxmass,GeV) << ounit(_maxcalc,GeV);
}
void FourPionNovosibirskCurrent::persistentInput(PersistentIStream & is, int) {
is >> _a1runinter >> _Fomega >> _Fthreec >> _Fonec >> _Fsigma
>> iunit(_rhomass,GeV) >> iunit(_a1mass,GeV) >> iunit(_omegamass,GeV)
>> iunit(_sigmamass,GeV) >> iunit(_rhowidth,GeV) >> iunit(_a1width,GeV)
>> iunit(_omegawidth,GeV) >> iunit(_sigmawidth,GeV)
>> _zsigma >> iunit(_lambda2,GeV2)
>> _initializea1 >> _localparameters
>> iunit(_a1runwidth,GeV) >> iunit(_a1runq2,GeV2) >> iunit(_onedlam2,1/GeV2)
>> _a1massolam2 >> iunit(_psigma,GeV) >> iunit(_mpic,GeV) >> iunit(_mpi0,GeV)
>> iunit(_aomega,1/GeV) >> iunit(_athreec,1/GeV) >> iunit(_aonec,1/GeV)
>> _bomega >> _bthreec >> _bonec
>> _comega >> _cthreec >>_conec >> _omegaparam
>> iunit(_intwidth,GeV) >> iunit(_intmass,GeV)
>> iunit(_mpic2,GeV2) >> iunit(_mpi02,GeV2)>> iunit(_hm2,GeV2) >> _dhdq2m2
>> iunit(_prho,GeV) >> iunit(_rhoD,GeV2) >> _zmag >> _zphase
>> iunit(_maxmass,GeV) >> iunit(_maxcalc,GeV);
}
// Definition of the static class description member.
void FourPionNovosibirskCurrent::Init() {
static ClassDocumentation<FourPionNovosibirskCurrent> documentation
("The FourPionNovosibirskCurrent class performs the decay"
" of the tau to four pions using currents based on the the"
" Novosibirsk e+e- data",
"The decay of the tau to four pions uses currents based on \\cite{Bondar:2002mw}.",
"%\\cite{Bondar:2002mw}\n"
"\\bibitem{Bondar:2002mw}\n"
" A.~E.~Bondar, S.~I.~Eidelman, A.~I.~Milstein, T.~Pierzchala, N.~I.~Root, Z.~Was and M.~Worek,\n"
" ``Novosibirsk hadronic currents for tau --> 4pi channels of tau decay\n"
" %library TAUOLA,''\n"
" Comput.\\ Phys.\\ Commun.\\ {\\bf 146}, 139 (2002)\n"
" [arXiv:hep-ph/0201149].\n"
" %%CITATION = CPHCB,146,139;%%\n"
);
static Parameter<FourPionNovosibirskCurrent,Energy> interfacerhoMass
("rhoMass",
"The local value of the rho mass",
&FourPionNovosibirskCurrent::_rhomass, GeV,0.7761*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<FourPionNovosibirskCurrent,Energy> interfacea1mass
("a1Mass",
"The local value of the square of the a_1 mass",
&FourPionNovosibirskCurrent::_a1mass, GeV, 1.2300*GeV, 0.5*GeV, 10.0*GeV,
false, false, true);
static Parameter<FourPionNovosibirskCurrent,Energy> interfaceSigmaMass
("sigmaMass",
"The local value of the sigma mass",
&FourPionNovosibirskCurrent::_sigmamass, GeV, 0.8*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<FourPionNovosibirskCurrent,Energy> interfaceOmegaMass
("omegaMass",
"The local value of the omega mass",
&FourPionNovosibirskCurrent::_omegamass, GeV, 0.7820*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<FourPionNovosibirskCurrent,Energy> interfacerhoWidth
("rhoWidth",
"The local value of the rho width",
&FourPionNovosibirskCurrent::_rhowidth, GeV,0.1445*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<FourPionNovosibirskCurrent,Energy> interfacea1width
("a1Width",
"The local value of the square of the a_1 width",
&FourPionNovosibirskCurrent::_a1width, GeV, 0.45*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<FourPionNovosibirskCurrent,Energy> interfaceSigmaWidth
("sigmaWidth",
"The local value of the sigma width",
&FourPionNovosibirskCurrent::_sigmawidth, GeV, 0.8*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<FourPionNovosibirskCurrent,Energy> interfaceOmegaWidth
("omegaWidth",
"The local value of the omega width",
&FourPionNovosibirskCurrent::_omegawidth, GeV, 0.00841*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<FourPionNovosibirskCurrent,Energy> interfaceIntegrationMass
("IntegrationMass",
"Mass of the pseudoresonance used to improve integration effciency",
&FourPionNovosibirskCurrent::_intmass, GeV, 1.4*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<FourPionNovosibirskCurrent,Energy> interfaceIntegrationWidth
("IntegrationWidth",
"Width of the pseudoresonance used to improve integration effciency",
&FourPionNovosibirskCurrent::_intwidth, GeV, 0.5*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<FourPionNovosibirskCurrent,double> interfaceSigmaMagnitude
("SigmaMagnitude",
"magnitude of the relative sigma coupling",
&FourPionNovosibirskCurrent::_zmag, 1.3998721, 0.0, 10.0e20,
false, false, true);
static Parameter<FourPionNovosibirskCurrent,double> interfaceSigmaPhase
("SigmaPhase",
"phase of the relative sigma coupling",
&FourPionNovosibirskCurrent::_zphase, 0.43585036, 0.0, Constants::twopi,
false, false, true);
static Parameter<FourPionNovosibirskCurrent,Energy2> interfaceLambda2
("Lambda2",
"The value of the mass scale squared to use in the form-factor",
&FourPionNovosibirskCurrent::_lambda2, GeV2, 1.2*GeV2, 0.0001*GeV2, 10.0*GeV2,
false, false, true);
static Switch<FourPionNovosibirskCurrent,bool> interfaceLocalParameters
("LocalParameters",
"Use local values of the intermediate resonances masses and widths",
&FourPionNovosibirskCurrent::_localparameters, true, false, false);
static SwitchOption interfaceLocalParametersLocal
(interfaceLocalParameters,
"Local",
"Use the local values",
true);
static SwitchOption interfaceLocalParametersDefault
(interfaceLocalParameters,
"ParticleData",
"Use the values from the particleData objects",
false);
static Switch<FourPionNovosibirskCurrent,bool> interfaceInitializea1
("Initializea1",
"Initialise the calculation of the a_1 running width",
&FourPionNovosibirskCurrent::_initializea1, false, false, false);
static SwitchOption interfaceInitializea1Initialization
(interfaceInitializea1,
"Yes",
"Initialize the calculation",
true);
static SwitchOption interfaceInitializea1NoInitialization
(interfaceInitializea1,
"No",
"Use the default values",
false);
static ParVector<FourPionNovosibirskCurrent,Energy> interfacea1RunningWidth
("a1RunningWidth",
"The values of the a_1 width for interpolation to giving the running width.",
&FourPionNovosibirskCurrent::_a1runwidth, GeV, -1, 1.0*GeV, ZERO, 10.0*GeV,
false, false, true);
static ParVector<FourPionNovosibirskCurrent,Energy2> interfacea1RunningQ2
("a1RunningQ2",
"The values of the q^2 for interpolation to giving the running width.",
&FourPionNovosibirskCurrent::_a1runq2, GeV2, -1, 1.0*GeV2, ZERO, 10.0*GeV2,
false, false, true);
}
// initialisation of the a_1 running width
void FourPionNovosibirskCurrent::inita1width(int iopt) {
// set up the interpolator
if(iopt==0||!_initializea1) {
_a1runinter = make_InterpolatorPtr(_a1runwidth,_a1runq2,3);
return;
}
_maxcalc=_maxmass;
if(_maxmass==ZERO) return;
// parameters for the table of values
Energy2 step(sqr(_maxmass)/200.);
// function to be integrated to give the matrix element
// integrator to perform the integral
// weights for the integration channels
vector<double> inweights;
inweights.push_back(0.3);inweights.push_back(0.3);inweights.push_back(0.3);
vector<double> inpower(3, 0.0);
// types of integration channels
vector<int> intype;
intype.push_back(2);intype.push_back(3);intype.push_back(1);
// masses for the integration channels
vector<Energy> inmass(2,_rhomass);inmass.push_back(_sigmamass);
// widths for the integration channels
vector<Energy> inwidth(2,_rhowidth);inwidth.push_back(_sigmawidth);
ThreeBodyAllOnCalculator<FourPionNovosibirskCurrent>
widthgen1(inweights,intype,inmass,inwidth,inpower,*this,0,_mpi0,_mpic,_mpic);
ThreeBodyAllOnCalculator<FourPionNovosibirskCurrent>
widthgen2(inweights,intype,inmass,inwidth,inpower,*this,1,_mpi0,_mpi0,_mpi0);
// normalisation constant to give physical width if on shell
double a1const(_a1width/(widthgen1.partialWidth(sqr(_a1mass))+
widthgen2.partialWidth(sqr(_a1mass))));
// loop to give the values
Energy2 moff2(ZERO);
_a1runwidth.clear();_a1runq2.clear();
for(;moff2<=sqr(_maxmass);moff2+=step) {
Energy total = a1const*(widthgen1.partialWidth(moff2)+widthgen2.partialWidth(moff2));
_a1runwidth.push_back(total);
_a1runq2.push_back(moff2);
}
}
// complete the construction of the decay mode for integration
bool FourPionNovosibirskCurrent::createMode(int icharge, unsigned int imode,
DecayPhaseSpaceModePtr mode,
unsigned int iloc,unsigned int ires,
DecayPhaseSpaceChannelPtr phase,Energy upp)
{
// check the charge
if(abs(icharge)!=3) return false;
// check that the modes are kinematical allowed
Energy min(ZERO);
if(imode==0) {
min= getParticleData(ParticleID::piplus)->mass()
+3.*getParticleData(ParticleID::pi0)->mass();
}
else {
min=3.*getParticleData(ParticleID::piplus)->mass()
+getParticleData(ParticleID::pi0)->mass();
}
if(min>upp) return false;
_maxmass=max(upp,_maxmass);
// intermediates for the channels
tPDPtr omega(getParticleData(ParticleID::omega)),rhop,rhom,
rho0(getParticleData(ParticleID::rho0)),a1m,a10(getParticleData(ParticleID::a_10)),
sigma(getParticleData(9000221)),rhot;
if(icharge==3) {
rhop = getParticleData(ParticleID::rhominus);
rhom = getParticleData(ParticleID::rhoplus);
a1m = getParticleData(ParticleID::a_1plus);
rhot = getParticleData(24);
}
else {
rhop = getParticleData(ParticleID::rhoplus);
rhom = getParticleData(ParticleID::rhominus);
a1m = getParticleData(ParticleID::a_1minus);
rhot = getParticleData(-24);
}
DecayPhaseSpaceChannelPtr newchannel;
// the omega channels for the three charged pion mode
// first channel two channels with rho0
if(imode==1) {
newchannel=new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(omega ,0,0.0,-ires-2,iloc+3);
newchannel->addIntermediate(rho0 ,0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(omega ,0,0.0,-ires-2,iloc+3);
newchannel->addIntermediate(rho0 ,0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
// second two channels with rho -
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(omega ,0,0.0,-ires-2,iloc+2);
newchannel->addIntermediate(rhom ,0,0.0, iloc+1,iloc+3);
mode->addChannel(newchannel);
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(omega ,0,0.0,-ires-2,iloc+2);
newchannel->addIntermediate(rhom ,0,0.0, iloc,iloc+3);
mode->addChannel(newchannel);
// third two channels with rho +
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(omega ,0,0.0,-ires-2,iloc+1);
newchannel->addIntermediate(rhop ,0,0.0, iloc+2,iloc+3);
mode->addChannel(newchannel);
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(omega ,0,0.0,-ires-2,iloc);
newchannel->addIntermediate(rhop ,0,0.0, iloc+2,iloc+3);
mode->addChannel(newchannel);
// a_1 channels with rhos
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc+3);
newchannel->addIntermediate(a1m ,0,0.0,-ires-2,iloc);
newchannel->addIntermediate(rho0 ,0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc+3);
newchannel->addIntermediate(a1m ,0,0.0,-ires-2,iloc+1);
newchannel->addIntermediate(rho0 ,0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
// neutral a_1 channels with rhos
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(a10 ,0,0.0,-ires-2,iloc+2);
newchannel->addIntermediate(rhom ,0,0.0, iloc+1,iloc+3);
mode->addChannel(newchannel);
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(a10 ,0,0.0,-ires-2,iloc+2);
newchannel->addIntermediate(rhom ,0,0.0, iloc,iloc+3);
mode->addChannel(newchannel);
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(a10 ,0,0.0,-ires-2,iloc+1);
newchannel->addIntermediate(rhop ,0,0.0, iloc+2,iloc+3);
mode->addChannel(newchannel);
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(a10 ,0,0.0,-ires-2,iloc);
newchannel->addIntermediate(rhop ,0,0.0, iloc+2,iloc+3);
mode->addChannel(newchannel);
// a_1 channels with sigmas
if(sigma) {
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc+3);
newchannel->addIntermediate(a1m ,0,0.0,-ires-2,iloc);
newchannel->addIntermediate(sigma ,0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc+3);
newchannel->addIntermediate(a1m ,0,0.0,-ires-2,iloc+1);
newchannel->addIntermediate(sigma ,0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
// neutral a_1 channels with sigma
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(a10 ,0,0.0,-ires-2,iloc+3);
newchannel->addIntermediate(sigma ,0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(a10 ,0,0.0,-ires-2,iloc+3);
newchannel->addIntermediate(sigma ,0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
}
}
else {
// channels with an a1- and a rho -
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(a1m ,0,0.0,-ires-2,iloc+2);
newchannel->addIntermediate(rhom ,0,0.0, iloc+3,iloc);
mode->addChannel(newchannel);
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(a1m ,0,0.0,-ires-2,iloc+3);
newchannel->addIntermediate(rhom ,0,0.0, iloc+2,iloc);
mode->addChannel(newchannel);
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc+2);
newchannel->addIntermediate(a1m ,0,0.0,-ires-2,iloc+1);
newchannel->addIntermediate(rhom ,0,0.0, iloc+3,iloc);
mode->addChannel(newchannel);
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc+2);
newchannel->addIntermediate(a1m ,0,0.0,-ires-2,iloc+3);
newchannel->addIntermediate(rhom ,0,0.0, iloc+1,iloc);
mode->addChannel(newchannel);
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc+3);
newchannel->addIntermediate(a1m ,0,0.0,-ires-2,iloc+1);
newchannel->addIntermediate(rhom ,0,0.0, iloc+2,iloc);
mode->addChannel(newchannel);
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc+3);
newchannel->addIntermediate(a1m ,0,0.0,-ires-2,iloc+2);
newchannel->addIntermediate(rhom ,0,0.0, iloc+1,iloc);
mode->addChannel(newchannel);
// channels with a sigma and a10
if(sigma ) {
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(a10 ,0,0.0,-ires-2,iloc+1);
newchannel->addIntermediate(sigma ,0,0.0, iloc+2,iloc+3);
mode->addChannel(newchannel);
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(a10 ,0,0.0,-ires-2,iloc+2);
newchannel->addIntermediate(sigma ,0,0.0, iloc+1,iloc+3);
mode->addChannel(newchannel);
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(a10 ,0,0.0,-ires-2,iloc+3);
newchannel->addIntermediate(sigma ,0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
// channels with a1- and sigma
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(a1m ,0,0.0,-ires-2,iloc);
newchannel->addIntermediate(sigma ,0,0.0, iloc+2,iloc+3);
mode->addChannel(newchannel);
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc+2);
newchannel->addIntermediate(a1m ,0,0.0,-ires-2,iloc);
newchannel->addIntermediate(sigma ,0,0.0, iloc+1,iloc+3);
mode->addChannel(newchannel);
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhot ,0,0.0,-ires-1,iloc+3);
newchannel->addIntermediate(a1m ,0,0.0,-ires-2,iloc);
newchannel->addIntermediate(sigma ,0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
}
}
// reset the parameters of the dummy resonance used for integration
mode->resetIntermediate(rhot,_intmass,_intwidth);
// reset the parameters of the resonances if using local values
if(_localparameters) {
mode->resetIntermediate(rhom,_rhomass,_rhowidth);
mode->resetIntermediate(rhop,_rhomass,_rhowidth);
mode->resetIntermediate(rho0,_rhomass,_rhowidth);
mode->resetIntermediate(omega,_omegamass,_omegawidth);
if(sigma) mode->resetIntermediate(sigma,_sigmamass,_sigmawidth);
}
// return if successful
return true;
}
// the particles produced by the current
tPDVector FourPionNovosibirskCurrent::particles(int icharge, unsigned int imode,int,int) {
if(abs(icharge)!=3) return tPDVector();
tPDVector output(4);
if(imode==1) {
output[0]=getParticleData(ParticleID::piplus);
output[1]=getParticleData(ParticleID::piplus);
output[2]=getParticleData(ParticleID::piminus);
}
else {
output[0]=getParticleData(ParticleID::piplus);
output[1]=getParticleData(ParticleID::pi0);
output[2]=getParticleData(ParticleID::pi0);
}
output[3]=getParticleData(ParticleID::pi0);
if(icharge==-3) {
for(unsigned int ix=0;ix<output.size();++ix) {
if(output[ix]->CC()) output[ix]=output[ix]->CC();
}
}
return output;
}
// the hadronic currents
vector<LorentzPolarizationVectorE>
FourPionNovosibirskCurrent::current(const int imode, const int ichan,
Energy & scale,const ParticleVector & decay,
DecayIntegrator::MEOption meopt) const {
useMe();
if(meopt==DecayIntegrator::Terminate) {
for(unsigned int ix=0;ix<4;++ix)
ScalarWaveFunction::constructSpinInfo(decay[ix],outgoing,true);
return vector<LorentzPolarizationVectorE>(1,LorentzPolarizationVectorE());
}
LorentzVector<complex<InvEnergy> > output;
double fact(1.);
// the momenta of the particles
Lorentz5Momentum q1(decay[0]->momentum()),q2(decay[2]->momentum()),
q3(decay[1]->momentum()),q4(decay[3]->momentum());
Lorentz5Momentum Q(q1+q2+q3+q4);Q.rescaleMass();
scale = Q.mass();
// decide which decay mode
// three charged pions
if(imode==1) {
// momenta of the particles
LorentzVector<complex<Energy5> > veca1rho,vecomega,veca1sig;
if(ichan<0) {
// a_1 rho current
veca1rho =
t1(q1,q2,q3,q4)+t1(q3,q2,q1,q4)+t1(q1,q3,q2,q4)
+t1(q3,q1,q2,q4)+t1(q4,q3,q1,q2)+t1(q4,q1,q3,q2);
// a_1 sigma current
veca1sig =
t2(q4,q3,q1,q2,1)+t2(q4,q1,q3,q2,1)
-t2(q1,q4,q3,q2,1)-t2(q3,q4,q1,q2,1);
// omega current
vecomega =
t3(q1,q2,q3,q4)+t3(q3,q2,q1,q4)-t3(q1,q3,q2,q4)
-t3(q3,q1,q2,q4)-t3(q1,q4,q3,q2)-t3(q3,q4,q1,q2);
}
else if(ichan== 0) vecomega = t3(q1,q4,q3,q2);
else if(ichan== 1) vecomega = t3(q3,q4,q1,q2);
else if(ichan== 2) vecomega = t3(q1,q2,q3,q4);
else if(ichan== 3) vecomega = t3(q3,q2,q1,q4);
else if(ichan== 4) vecomega = t3(q1,q3,q2,q4);
else if(ichan== 5) vecomega = t3(q3,q1,q2,q4);
else if(ichan== 6) veca1rho = t1(q4,q1,q3,q2);
else if(ichan== 7) veca1rho = t1(q4,q3,q1,q2);
else if(ichan== 8) veca1rho = t1(q1,q2,q3,q4);
else if(ichan== 9) veca1rho = t1(q3,q2,q1,q4);
else if(ichan==10) veca1rho = t1(q1,q3,q2,q4);
else if(ichan==11) veca1rho = t1(q3,q1,q2,q4);
else if(ichan==12) veca1sig = t2(q4,q1,q3,q2,1);
else if(ichan==13) veca1sig = t2(q4,q3,q1,q2,1);
else if(ichan==14) veca1sig = t2(q1,q4,q3,q2,1);
else if(ichan==15) veca1sig = t2(q3,q4,q1,q2,1);
// final manipulations
veca1rho += veca1sig;
LorentzVector<complex<InvEnergy> >
veca1rho1 = veca1rho * gFunction(Q.mass2(),1);
LorentzVector<complex<InvEnergy> >
vecomega1 = vecomega * gFunction(Q.mass2(),2);
output = vecomega1 + veca1rho1;
// this is 1/sqrt(2) for identical particles
fact *= 1./sqrt(2.);
}
else if(imode==0) {
// momenta of the particles
LorentzVector<complex<Energy5> > veca1rho,veca1sig;
if(ichan<0) {
// a_1 rho current
veca1rho= t1(q2,q3,q1,q4)+t1(q2,q4,q1,q3)+t1(q3,q2,q1,q4)
+t1(q3,q4,q1,q2)+t1(q4,q2,q1,q3)+t1(q4,q3,q1,q2);
// a_1 sigma current
veca1sig=
t2(q2,q1,q3,q4,0)+t2(q3,q1,q2,q4,0)+t2(q4,q1,q3,q2,0)
-t2(q1,q2,q3,q4,0)-t2(q1,q3,q2,q4,0)-t2(q1,q4,q3,q2,0);
}
else if(ichan== 0) veca1rho = t1(q2,q3,q1,q4);
else if(ichan== 1) veca1rho = t1(q2,q4,q1,q3);
else if(ichan== 2) veca1rho = t1(q3,q2,q1,q4);
else if(ichan== 3) veca1rho = t1(q3,q4,q1,q2);
else if(ichan== 4) veca1rho = t1(q4,q2,q1,q3);
else if(ichan== 5) veca1rho = t1(q4,q3,q1,q2);
else if(ichan== 6) veca1sig = t2(q2,q1,q3,q4,0);
else if(ichan== 7) veca1sig = t2(q3,q1,q2,q4,0);
else if(ichan== 8) veca1sig = t2(q4,q1,q3,q2,0);
else if(ichan== 9) veca1sig = t2(q1,q2,q3,q4,0);
else if(ichan==10) veca1sig = t2(q1,q3,q2,q4,0);
else if(ichan==11) veca1sig = t2(q1,q4,q3,q2,0);
// add them up
output = (veca1rho + veca1sig) * gFunction(Q.mass2(),0);
// this is sqrt(1/3!) for identical particles
fact *= 1./sqrt(6.);
}
else {
throw DecayIntegratorError() << "Unknown decay mode in the "
<< "FourPionNovosibirskCurrent::"
<< "hadronCurrent()" << Exception::abortnow;
}
vector<LorentzPolarizationVectorE> temp(1, output * fact * Q.mass2());
return temp;
}
bool FourPionNovosibirskCurrent::accept(vector<int> id) {
bool allowed(false);
// check four products
if(id.size()!=4){return false;}
int npiminus=0,npiplus=0,npi0=0;
for(unsigned int ix=0;ix<id.size();++ix) {
if(id[ix]==ParticleID:: piplus) ++npiplus;
else if(id[ix]==ParticleID::piminus) ++npiminus;
else if(id[ix]==ParticleID::pi0) ++npi0;
}
if(npiminus==2&&npiplus==1&&npi0==1) allowed=true;
else if(npiminus==1&&npi0==3) allowed=true;
else if(npiplus==2&&npiminus==1&&npi0==1) allowed=true;
else if(npiplus==1&&npi0==3) allowed=true;
return allowed;
}
// the decay mode
unsigned int FourPionNovosibirskCurrent::decayMode(vector<int> idout) {
unsigned int npi(0);
for(unsigned int ix=0;ix<idout.size();++ix) {
if(abs(idout[ix])==ParticleID::piplus) ++npi;
}
if(npi==3) return 1;
return 0;
}
// output the information for the database
void FourPionNovosibirskCurrent::dataBaseOutput(ofstream & output,bool header,
bool create) const {
if(header) output << "update decayers set parameters=\"";
if(create) output << "create Herwig::FourPionNovosibirskCurrent "
<< name() << " HwWeakCurrents.so\n";
output << "newdef " << name() << ":rhoMass " << _rhomass/GeV << "\n";
output << "newdef " << name() << ":a1Mass " << _a1mass/GeV << "\n";
output << "newdef " << name() << ":sigmaMass " << _sigmamass/GeV << "\n";
output << "newdef " << name() << ":omegaMass " << _omegamass/GeV << "\n";
output << "newdef " << name() << ":rhoWidth " << _rhowidth/GeV << "\n";
output << "newdef " << name() << ":a1Width " << _a1width/GeV << "\n";
output << "newdef " << name() << ":sigmaWidth " << _sigmawidth/GeV << "\n";
output << "newdef " << name() << ":omegaWidth " << _omegawidth/GeV << "\n";
output << "newdef " << name() << ":IntegrationMass " << _intmass/GeV << "\n";
output << "newdef " << name() << ":IntegrationWidth " << _intwidth/GeV << "\n";
output << "newdef " << name() << ":SigmaMagnitude " << _zmag << "\n";
output << "newdef " << name() << ":SigmaPhase " << _zphase << "\n";
output << "newdef " << name() << ":Lambda2 " << _lambda2/GeV2 << "\n";
output << "newdef " << name() << ":LocalParameters " << _localparameters << "\n";
output << "newdef " << name() << ":Initializea1 " << _initializea1 << "\n";
for(unsigned int ix=0;ix<_a1runwidth.size();++ix) {
if(ix<200) output << "newdef ";
else output << "insert ";
output << name() << ":a1RunningWidth " << ix << " "
<< _a1runwidth[ix]/GeV << "\n";
}
for(unsigned int ix=0;ix<_a1runq2.size();++ix) {
if(ix<200) output << "newdef ";
else output << "insert ";
output << name() << ":a1RunningQ2 " << ix << " " << _a1runq2[ix]/GeV2 << "\n";
}
WeakDecayCurrent::dataBaseOutput(output,false,false);
if(header) output << "\n\" where BINARY ThePEGName=\""
<< fullName() << "\";" << endl;
}
double FourPionNovosibirskCurrent::
threeBodyMatrixElement(const int iopt, const Energy2 q2,
const Energy2 s3, const Energy2 s2,
const Energy2 s1, const Energy,
const Energy, const Energy) const {
unsigned int ix;
// construct the momenta of the decay products
Energy p1[5],p2[5],p3[5];
Energy2 p1sq, p2sq, p3sq;
Energy q(sqrt(q2));
if(iopt==0) {
p1[0] = 0.5*(q2+_mpi02-s1)/q; p1sq=p1[0]*p1[0]; p1[4]=sqrt(p1sq-_mpi02);
p2[0] = 0.5*(q2+_mpic2-s2)/q; p2sq=p2[0]*p2[0]; p2[4]=sqrt(p2sq-_mpic2);
p3[0] = 0.5*(q2+_mpic2-s3)/q; p3sq=p3[0]*p3[0]; p3[4]=sqrt(p3sq-_mpic2);
}
else {
p1[0] = 0.5*(q2+_mpi02-s1)/q; p1sq=p1[0]*p1[0]; p1[4]=sqrt(p1sq-_mpi02);
p2[0] = 0.5*(q2+_mpi02-s2)/q; p2sq=p2[0]*p2[0]; p2[4]=sqrt(p2sq-_mpi02);
p3[0] = 0.5*(q2+_mpi02-s3)/q; p3sq=p3[0]*p3[0]; p3[4]=sqrt(p3sq-_mpi02);
}
// take momentum of 1 parallel to z axis
p1[1]=ZERO;p1[2]=ZERO;p1[3]=p1[4];
// construct 2
double cos2(0.5*(sqr(p1[4])+sqr(p2[4])-sqr(p3[4]))/p1[4]/p2[4]);
p2[1] = p2[4]*sqrt(1.-sqr(cos2)); p2[2]=ZERO; p2[3]=-p2[4]*cos2;
// construct 3
double cos3(0.5*(sqr(p1[4])-sqr(p2[4])+sqr(p3[4]))/p1[4]/p3[4]);
p3[1] =-p3[4]*sqrt(1.-sqr(cos3)); p3[2]=ZERO; p3[3]=-p3[4]*cos3;
// pi+pi-pi0 term
complex<Energy4> output(0.*sqr(MeV2));
if(iopt==0) {
// values for the different Breit-Wigner terms
Complex rho1(2.365*rhoBreitWigner(s2)),
rho2(2.365*rhoBreitWigner(s3)),
sig1(sigmaBreitWigner(s1,1));
// compute the vector
complex<Energy2> term;
for(ix=1;ix<4;++ix) {
term = (p1[0]*p2[ix]-p2[0]*p1[ix])*rho2+(p1[0]*p3[ix]-p3[0]*p1[ix])*rho1
+_zsigma*q*p1[ix]*sig1;
output+=term*conj(term);
}
}
// pi0pi0pi0 term
else if(iopt==1) {
// values for the different Breit-Wigner terms
Complex sig1(sigmaBreitWigner(s1,0)),
sig2(sigmaBreitWigner(s2,0)),
sig3(sigmaBreitWigner(s3,0));
// compute the vector
complex<Energy2> term;
for(ix=1;ix<4;++ix) {
term = _zsigma * q * (p1[ix]*sig1 + p2[ix]*sig2 + p3[ix]*sig3);
output += term*conj(term);
}
output/=6.;
}
output *= a1FormFactor(q2);
return output.real() / pow<4,1>(_rhomass);
}
Complex FourPionNovosibirskCurrent::sigmaBreitWigner(Energy2 q2,
unsigned int iopt) const {
Energy q(sqrt(q2));
Energy pcm = iopt==0 ?
Kinematics::pstarTwoBodyDecay(q,_mpi0,_mpi0) :
Kinematics::pstarTwoBodyDecay(q,_mpic,_mpic);
if(pcm<ZERO) pcm=ZERO;
Energy width(_sigmawidth*pcm/_psigma[iopt]);
Energy2 msigma2 = sqr(_sigmamass);
return msigma2/(q2-msigma2+Complex(0.,1.)*msigma2*width/q);
}
Complex FourPionNovosibirskCurrent::a1BreitWigner(Energy2 q2) const {
Complex ii(0.,1.);
Energy2 m2 = sqr(_a1mass);
Energy q = sqrt(q2);
return (m2/complex<Energy2>(q2 - m2 + ii*q*a1width(q2)));
}
Complex FourPionNovosibirskCurrent::omegaBreitWigner(Energy2 q2) const {
Energy q(sqrt(q2));
// calcluate the running width
double diff((q-_omegamass)/GeV),temp(diff);
double gomega(1.);
Complex ii(0.,1.);
if(q<=1.*GeV) {
for(unsigned int ix=0;ix<6;++ix) {
gomega +=temp*_omegaparam[ix];
temp*=diff;
}
}
else {
gomega=_omegaparam[6]+q/GeV*(_omegaparam[7]+q/GeV*_omegaparam[8]
+q2/GeV2*_omegaparam[9]);
}
if(gomega<0.){gomega=0.;}
Energy2 numer=_omegamass*_omegamass;
complex<Energy2> denom=q2-_omegamass*_omegamass+ii*_omegamass*_omegawidth*gomega;
return numer/denom;
}
Complex FourPionNovosibirskCurrent::rhoBreitWigner(Energy2 q2) const {
Energy q(sqrt(q2));
Energy2 grhom(8.*_prho*_prho*_prho/_rhomass);
complex<Energy2> denom;
Complex ii(0.,1.);
if(q2<4.*_mpic2) {
denom=q2-_rhomass*_rhomass
-_rhowidth*_rhomass*(hFunction(q)-_hm2-(q2-_rhomass*_rhomass)*_dhdq2m2)/grhom;
}
else {
Energy pcm(2.*Kinematics::pstarTwoBodyDecay(q,_mpic,_mpic));
Energy2 grho(pcm*pcm*pcm/q);
denom=q2-_rhomass*_rhomass
-_rhowidth*_rhomass*(hFunction(q)-_hm2-(q2-_rhomass*_rhomass)*_dhdq2m2)/grhom
+ii*_rhomass*_rhowidth*grho/grhom;
}
return _rhoD/denom;
}
LorentzVector<complex<Energy5> >
FourPionNovosibirskCurrent::t1(Lorentz5Momentum & q1,Lorentz5Momentum & q2,
Lorentz5Momentum & q3,Lorentz5Momentum & q4) const {
// momentum of the whole sysytem
Lorentz5Momentum Q(q1+q2+q3+q4);Q.rescaleMass();
// compute the virtuality of the a_1
Lorentz5Momentum a1(q2+q3+q4);a1.rescaleMass();
// compute the virtuality of the rho
Lorentz5Momentum rho(q3+q4);rho.rescaleMass();
// compute the prefactor
Complex pre(-a1FormFactor(a1.mass2())*a1BreitWigner(a1.mass2())*
rhoBreitWigner(rho.mass2()));
// dot products we need
Energy2 QdQmq1(Q*a1);
complex<Energy4> consta(QdQmq1*(a1*q3)), constb(QdQmq1*(a1*q4)),
constc(((Q*q4)*(q1*q3)-(Q*q3)*(q1*q4)));
// compute the current
return pre*(consta*q4-constb*q3+constc*a1);
}
LorentzVector<complex<Energy5> >
FourPionNovosibirskCurrent::t2(Lorentz5Momentum & q1,Lorentz5Momentum & q2,
Lorentz5Momentum & q3,Lorentz5Momentum & q4,
unsigned int iopt) const {
// momentum of the whole system
Lorentz5Momentum Q(q1+q2+q3+q4);Q.rescaleMass();
// compute the virtuality of the a_1
Lorentz5Momentum a1(q2+q3+q4);a1.rescaleMass();
// compute the virtuality of the sigma
Lorentz5Momentum sigma(q3+q4);sigma.rescaleMass();
// compute the prefactor
Complex pre(_zsigma*a1FormFactor(a1.mass2())
*a1BreitWigner(a1.mass2())*
sigmaBreitWigner(sigma.mass2(),iopt));
// dot products we need
complex<Energy4> consta((Q*a1)*a1.mass2()),constb((Q*q2)*a1.mass2());
// compute the current
return pre*(consta*q2-constb*a1);
}
LorentzVector<complex<Energy5> >
FourPionNovosibirskCurrent::t3(Lorentz5Momentum & q1,Lorentz5Momentum & q2,
Lorentz5Momentum & q3,Lorentz5Momentum & q4) const {
// momentum of the whole sysytem
Lorentz5Momentum Q(q1+q2+q3+q4);Q.rescaleMass();
// compute the virtuality of the omega
Lorentz5Momentum omega(q2+q3+q4);omega.rescaleMass();
// compute the virtuality of the rho
Lorentz5Momentum rho(q3+q4);rho.rescaleMass();
// compute the prefactor
Complex pre(omegaBreitWigner(omega.mass2())*rhoBreitWigner(rho.mass2()));
// dot products we need
complex<Energy4> consta((Q*q3)*(q1*q4)-(Q*q4)*(q1*q3)),
constb(-(Q*q2)*(q1*q4)+(q1*q2)*(Q*q4)),
constc((Q*q2)*(q1*q3)-(q1*q2)*(Q*q3));
// compute the current
return pre*(consta*q2+constb*q3+constc*q4);
}
InvEnergy6 FourPionNovosibirskCurrent::gFunction(Energy2 q2, int ichan) const {
Energy q(sqrt(q2));
InvEnergy4 invmrho4 = 1/sqr(sqr(_rhomass));
// the one charged pion G function
if(ichan==0) {
return (*_Fonec)(q) * _aonec * (*_Fsigma)(q2) * sqrt(_bonec*q/GeV-_conec) *
invmrho4/q;
}
// the three charged pion G function
else if(ichan==1) {
return (*_Fthreec)(q)*_athreec*sqrt(_bthreec*q/GeV-_cthreec)*invmrho4/q;
}
// the omega G function
else if(ichan==2) {
return(*_Fomega)(q)*_aomega*sqrt(_bomega*q/GeV-_comega)*invmrho4/q;
}
assert(false);
return InvEnergy6();
}
Energy2 FourPionNovosibirskCurrent::DParameter() const {
Energy2 grhom(8.*_prho*_prho*_prho/_rhomass);
return _rhomass*_rhomass+_rhowidth*_rhomass*
(hFunction(ZERO)-_hm2+_rhomass*_rhomass*_dhdq2m2)/grhom;
}
double FourPionNovosibirskCurrent::dhdq2Parameter() const {
Energy2 mrho2(_rhomass*_rhomass);
double root(sqrt(1.-4.*_mpic2/mrho2));
return root/Constants::pi*(root+(1.+2*_mpic2/mrho2)*log((1+root)/(1-root)));
}
Energy2 FourPionNovosibirskCurrent::hFunction(const Energy q) const {
using Constants::pi;
static const Energy2 eps(0.01*MeV2);
Energy2 q2(q*q), output;
if (q2 > 4*_mpic2) {
double root = sqrt(1.-4.*_mpic2/q2);
output = root*log((1.+root)/(1.-root))*(q2-4*_mpic2)/pi;
}
else if (q2 > eps) output = ZERO;
else output = -8.*_mpic2/pi;
return output;
}
diff --git a/Decay/WeakCurrents/KaonThreeMesonCurrent.cc b/Decay/WeakCurrents/KaonThreeMesonCurrent.cc
--- a/Decay/WeakCurrents/KaonThreeMesonCurrent.cc
+++ b/Decay/WeakCurrents/KaonThreeMesonCurrent.cc
@@ -1,1524 +1,1519 @@
// -*- C++ -*-
//
// KaonThreeMesonCurrent.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 KaonThreeMesonCurrent class.
//
#include "KaonThreeMesonCurrent.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig/PDT/ThreeBodyAllOnCalculator.h"
#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
DescribeClass<KaonThreeMesonCurrent,ThreeMesonCurrentBase>
describeHerwigKaonThreeMesonCurrent("Herwig::KaonThreeMesonCurrent",
"HwWeakCurrents.so");
HERWIG_INTERPOLATOR_CLASSDESC(KaonThreeMesonCurrent,Energy,Energy2)
-namespace {
- inline Energy timesGeV (double x) { return x * GeV; }
- inline Energy2 timesGeV2(double x) { return x * GeV2; }
-}
-
IBPtr KaonThreeMesonCurrent::clone() const {
return new_ptr(*this);
}
IBPtr KaonThreeMesonCurrent::fullclone() const {
return new_ptr(*this);
}
KaonThreeMesonCurrent::KaonThreeMesonCurrent() {
// rho parameters
// use local values
_rhoparameters=true;
// rho parameters for axial-vector pieces
_rho1wgts.push_back( 1.0 ); _rho1wgts.push_back(-0.145);
_rho1wgts.push_back(0.);
_rho1mass.push_back(0.773*GeV);_rho1mass.push_back(1.370*GeV);
_rho1mass.push_back(1.750*GeV);
_rho1width.push_back(0.145*GeV);_rho1width.push_back(0.510*GeV);
_rho1width.push_back(0.120*GeV);
// rho parameters for vector pieces
_rho2wgts.push_back( 1.0 ); _rho2wgts.push_back(-0.25 );
_rho2wgts.push_back(-0.038);
_rho2mass.push_back(0.773*GeV);_rho2mass.push_back(1.500*GeV);
_rho2mass.push_back(1.750*GeV);
_rho2width.push_back(0.145*GeV);_rho2width.push_back(0.220*GeV);
_rho2width.push_back(0.120*GeV);
// K* parameters
_kstarparameters=true;
// K* parameters for the axial-vector pieces
_kstar1wgts.push_back( 1.0 ); _kstar1wgts.push_back(-0.135);
_kstar1wgts.push_back(0.);
_kstar1mass.push_back(0.892*GeV);_kstar1mass.push_back(1.412*GeV);
_kstar1mass.push_back(1.714*GeV);
_kstar1width.push_back(0.050*GeV);_kstar1width.push_back(0.227*GeV);
_kstar1width.push_back(0.323*GeV);
// K* parameters for vector pieces
_kstar2wgts.push_back( 1.0 ); _kstar2wgts.push_back(-0.25 );
_kstar2wgts.push_back(-0.038);
_kstar2mass.push_back(0.892*GeV);_kstar2mass.push_back(1.412*GeV);
_kstar2mass.push_back(1.714*GeV);
_kstar2width.push_back(0.050*GeV);_kstar2width.push_back(0.227*GeV);
_kstar2width.push_back(0.323*GeV);
// a_1 parameters
_a1parameters = true;
_initializea1 = false;
_a1opt = true;
_a1mass = 1.251*GeV;
_a1width = 0.475*GeV;
double a1q2in[200]={0,15788.6,31577.3,47365.9,63154.6,78943.2,94731.9,110521,
126309,142098,157886,173675,189464,205252,221041,236830,
252618,268407,284196,299984,315773,331562,347350,363139,
378927,394716,410505,426293,442082,457871,473659,489448,
505237,521025,536814,552603,568391,584180,599969,615757,
631546,647334,663123,678912,694700,710489,726278,742066,
757855,773644,789432,805221,821010,836798,852587,868375,
884164,899953,915741,931530,947319,963107,978896,994685,
1.01047e+06,1.02626e+06,1.04205e+06,1.05784e+06,1.07363e+06,
1.08942e+06,1.10521e+06,1.12099e+06,1.13678e+06,1.15257e+06,
1.16836e+06,1.18415e+06,1.19994e+06,1.21573e+06,1.23151e+06,
1.2473e+06,1.26309e+06,1.27888e+06,1.29467e+06,1.31046e+06,
1.32625e+06,1.34203e+06,1.35782e+06,1.37361e+06,1.3894e+06,
1.40519e+06,1.42098e+06,1.43677e+06,1.45256e+06,1.46834e+06
,1.48413e+06,1.49992e+06,1.51571e+06,1.5315e+06,1.54729e+06,
1.56308e+06,1.57886e+06,1.59465e+06,1.61044e+06,1.62623e+06,
1.64202e+06,1.65781e+06,1.6736e+06,1.68939e+06,1.70517e+06,
1.72096e+06,1.73675e+06,1.75254e+06,1.76833e+06,1.78412e+06,
1.79991e+06,1.81569e+06,1.83148e+06,1.84727e+06,1.86306e+06,
1.87885e+06,1.89464e+06,1.91043e+06,1.92621e+06,1.942e+06,
1.95779e+06,1.97358e+06,1.98937e+06,2.00516e+06,2.02095e+06,
2.03674e+06,2.05252e+06,2.06831e+06,2.0841e+06,2.09989e+06,
2.11568e+06,2.13147e+06,2.14726e+06,2.16304e+06,2.17883e+06,
2.19462e+06,2.21041e+06,2.2262e+06,2.24199e+06,2.25778e+06,
2.27356e+06,2.28935e+06,2.30514e+06,2.32093e+06,2.33672e+06,
2.35251e+06,2.3683e+06,2.38409e+06,2.39987e+06,2.41566e+06,
2.43145e+06,2.44724e+06,2.46303e+06,2.47882e+06,2.49461e+06,
2.51039e+06,2.52618e+06,2.54197e+06,2.55776e+06,2.57355e+06,
2.58934e+06,2.60513e+06,2.62092e+06,2.6367e+06,2.65249e+06,
2.66828e+06,2.68407e+06,2.69986e+06,2.71565e+06,2.73144e+06,
2.74722e+06,2.76301e+06,2.7788e+06,2.79459e+06,2.81038e+06,
2.82617e+06,2.84196e+06,2.85774e+06,2.87353e+06,2.88932e+06,
2.90511e+06,2.9209e+06,2.93669e+06,2.95248e+06,2.96827e+06,
2.98405e+06,2.99984e+06,3.01563e+06,3.03142e+06,3.04721e+06,
3.063e+06,3.07879e+06,3.09457e+06,3.11036e+06,3.12615e+06,
3.14194e+06};
double a1widthin[200]={0,0,0,0,0,0,0,0,0,0,0,0,0.00153933,0.0136382,0.0457614,
0.105567,0.199612,0.333825,0.513831,0.745192,1.0336,1.38501,
1.80581,2.30295,2.88403,3.5575,4.33278,5.22045,6.23243,
7.38223,8.68521,10.1589,11.8234,13.7018,15.8206,18.2107,
20.9078,23.9533,27.3954,31.2905,35.7038,40.7106,46.3984,
52.8654,60.2207,68.581,78.0637,88.7754,100.794,114.145,
128.783,144.574,161.299,178.683,196.426,214.248,231.908,
249.221,266.059,282.336,298.006,313.048,327.46,341.254,
354.448,367.066,379.133,390.677,401.726,412.304,422.439,
432.155,441.474,450.419,459.01,467.267,475.207,482.847,
490.203,497.29,504.121,510.71,517.068,523.207,529.138,
534.869,540.411,545.776,550.961,556.663,560.851,565.566,
570.137,574.569,578.869,583.041,587.091,591.023,594.843,
598.553,602.16,605.664,609.072,612.396,615.626,618.754,
621.796,624.766,627.656,630.47,633.21,635.878,638.5,
641.006,643.471,645.873,648.213,650.493,652.715,654.88,
656.99,659.047,661.052,663.007,664.963,666.771,668.6,
670.351,672.075,673.828,675.397,676.996,678.567,680.083,
681.589,683.023,684.457,685.825,687.18,688.499,689.789,
691.058,692.284,693.501,694.667,695.82,696.947,698.05,
699.129,700.186,701.221,702.234,703.226,704.198,705.158,
706.085,707.001,707.899,708.78,709.644,710.474,711.334,
712.145,712.943,713.727,714.505,715.266,716.015,716.751,
717.474,718.183,718.88,719.645,720.243,720.91,721.565,
722.211,722.851,723.473,724.094,724.697,725.296,725.886,
726.468,727.041,727.608,728.166,728.718,729.262,729.808,
730.337,730.856,731.374,731.883,732.386,732.884,733.373,
733.859,734.339,734.813};
vector<double> tmp1(a1widthin,a1widthin+200);
_a1runwidth.clear();
std::transform(tmp1.begin(), tmp1.end(),
back_inserter(_a1runwidth),
- timesGeV);
+ [](double x){return x*GeV;});
vector<double> tmp2(a1q2in,a1q2in+200);
_a1runq2.clear();
std::transform(tmp2.begin(), tmp2.end(),
back_inserter(_a1runq2),
- timesGeV2);
+ [](double x){return x*GeV2;});
// K_1 parameters
_k1parameters=true;
_k1mass.push_back(1.270*GeV);_k1width.push_back(0.090*GeV);
_k1mass.push_back(1.402*GeV);_k1width.push_back(0.174*GeV);
_k1wgta.push_back(0.33);_k1wgta.push_back(1.);
_k1wgtb.push_back(1.00);_k1wgtb.push_back(0.);
// parameters for the T_omega function
_omegaopt=true;
_epsomega=0.05;
_omegamass = 0.782*GeV;
_omegawidth = 0.00843*GeV;
_phimass = 1.020*GeV;
_phiwidth = 0.00443*GeV;
_omegaKstarwgt=1./sqrt(2.);
// the pion decay constant
_fpi=130.7*MeV/sqrt(2.);
_mpi=ZERO;_mK=ZERO;
_maxmass=ZERO;
_maxcalc=ZERO;
}
void KaonThreeMesonCurrent::persistentOutput(PersistentOStream & os) const {
os << _a1runinter
<< _rho1wgts << ounit(_rho1mass,GeV) << ounit(_rho1width,GeV)
<< _rho2wgts << ounit(_rho2mass,GeV) << ounit(_rho2width,GeV)
<< _kstar1wgts << ounit(_kstar1mass,GeV) << ounit(_kstar1width,GeV)
<< _kstar2wgts << ounit(_kstar2mass,GeV) << ounit(_kstar2width,GeV)
<< ounit(_a1mass,GeV) << ounit(_a1width,GeV) << ounit(_k1mass,GeV)
<< ounit(_k1width,GeV) << _k1wgta << _k1wgtb
<< ounit(_a1runwidth,GeV) << ounit(_a1runq2,GeV2) << _epsomega
<< ounit(_omegamass,GeV) << ounit(_omegawidth,GeV)
<< ounit(_phimass,GeV) << ounit(_phiwidth,GeV) << _omegaKstarwgt
<< ounit(_fpi,GeV) << ounit(_mpi,GeV) << ounit(_mK,GeV)
<< _initializea1 << _rhoparameters << _kstarparameters << _a1parameters
<< _k1parameters << _a1opt << _omegaopt
<< ounit(_maxmass,GeV) << ounit(_maxcalc,GeV);
}
void KaonThreeMesonCurrent::persistentInput(PersistentIStream & is, int) {
is >> _a1runinter
>> _rho1wgts >> iunit(_rho1mass,GeV) >> iunit(_rho1width,GeV)
>> _rho2wgts >> iunit(_rho2mass,GeV) >> iunit(_rho2width,GeV)
>> _kstar1wgts >> iunit(_kstar1mass,GeV) >> iunit(_kstar1width,GeV)
>> _kstar2wgts >> iunit(_kstar2mass,GeV) >> iunit(_kstar2width,GeV)
>> iunit(_a1mass,GeV) >> iunit(_a1width,GeV) >> iunit(_k1mass,GeV)
>> iunit(_k1width,GeV) >> _k1wgta >> _k1wgtb
>> iunit(_a1runwidth,GeV) >> iunit(_a1runq2,GeV2) >> _epsomega
>> iunit(_omegamass,GeV) >> iunit(_omegawidth,GeV)
>> iunit(_phimass,GeV) >> iunit(_phiwidth,GeV) >> _omegaKstarwgt
>> iunit(_fpi,GeV) >> iunit(_mpi,GeV) >> iunit(_mK,GeV)
>> _initializea1 >> _rhoparameters >> _kstarparameters >> _a1parameters
>> _k1parameters >> _a1opt >> _omegaopt
>> iunit(_maxmass,GeV) >> iunit(_maxcalc,GeV);
}
void KaonThreeMesonCurrent::Init() {
static ClassDocumentation<KaonThreeMesonCurrent> documentation
("The KaonThreeMesonCurrent class implements the model of "
"Z. Phys. C 69 (1996) 243 [arXiv:hep-ph/9503474]"
" for the weak current with three "
"mesons, at least one of which is a kaon",
"The KaonThreeMesonCurrent class implements the model of "
"\\cite{Finkemeier:1995sr} for the weak current with three "
"mesons, at least one of which is a kaon.",
"\\bibitem{Finkemeier:1995sr}\n"
"M.~Finkemeier and E.~Mirkes,\n"
"Z.\\ Phys.\\ C {\\bf 69} (1996) 243 [arXiv:hep-ph/9503474].\n"
" %%CITATION = ZEPYA,C69,243;%%\n"
);
static Switch<KaonThreeMesonCurrent,bool> interfaceInitializea1
("Initializea1",
"Initialise the calculation of the a_1 running width",
&KaonThreeMesonCurrent::_initializea1, false, false, false);
static SwitchOption interfaceInitializea1Initialization
(interfaceInitializea1,
"Yes",
"Initialize the calculation",
true);
static SwitchOption interfaceInitializea1NoInitialization
(interfaceInitializea1,
"No",
"Use the default values",
false);
static Parameter<KaonThreeMesonCurrent,Energy> interfaceA1Width
("A1Width",
"The a_1 width if using local values.",
&KaonThreeMesonCurrent::_a1width, GeV, 0.599*GeV, ZERO, 10.0*GeV,
false, false, false);
static Parameter<KaonThreeMesonCurrent,Energy> interfaceA1Mass
("A1Mass",
"The a_1 mass if using local values.",
&KaonThreeMesonCurrent::_a1mass, GeV, 1.251*GeV, ZERO, 10.0*GeV,
false, false, false);
static Parameter<KaonThreeMesonCurrent,Energy> interfaceFPi
("FPi",
"The pion decay constant",
&KaonThreeMesonCurrent::_fpi, MeV, 92.4*MeV, ZERO, 200.0*MeV,
false, false, true);
static ParVector<KaonThreeMesonCurrent,Energy> interfaceRhoAxialMasses
("RhoAxialMasses",
"The masses for the rho resonances if used local values",
&KaonThreeMesonCurrent::_rho1mass, GeV, -1, 1.0*GeV, ZERO, 10.0*GeV,
false, false, true);
static ParVector<KaonThreeMesonCurrent,Energy> interfaceRhoAxialWidths
("RhoAxialWidths",
"The widths for the rho resonances if used local values",
&KaonThreeMesonCurrent::_rho1width, GeV, -1, 1.0*GeV, ZERO, 10.0*GeV,
false, false, true);
static ParVector<KaonThreeMesonCurrent,Energy> interfaceRhoVectorMasses
("RhoVectorMasses",
"The masses for the rho resonances if used local values",
&KaonThreeMesonCurrent::_rho2mass, GeV, -1, 1.0*GeV, ZERO, 10.0*GeV,
false, false, true);
static ParVector<KaonThreeMesonCurrent,Energy> interfaceRhoVectorWidths
("RhoVectorWidths",
"The widths for the rho resonances if used local values",
&KaonThreeMesonCurrent::_rho2width, GeV, -1, 1.0*GeV, ZERO, 10.0*GeV,
false, false, true);
static ParVector<KaonThreeMesonCurrent,Energy> interfaceKstarAxialMasses
("KstarAxialMasses",
"The masses for the Kstar resonances if used local values",
&KaonThreeMesonCurrent::_kstar1mass, GeV, -1, 1.0*GeV, ZERO, 10.0*GeV,
false, false, true);
static ParVector<KaonThreeMesonCurrent,Energy> interfaceKstarAxialWidths
("KstarAxialWidths",
"The widths for the Kstar resonances if used local values",
&KaonThreeMesonCurrent::_kstar1width, GeV, -1, 1.0*GeV, ZERO, 10.0*GeV,
false, false, true);
static ParVector<KaonThreeMesonCurrent,Energy> interfaceKstarVectorMasses
("KstarVectorMasses",
"The masses for the Kstar resonances if used local values",
&KaonThreeMesonCurrent::_kstar2mass, GeV, -1, 1.0*GeV, ZERO, 10.0*GeV,
false, false, true);
static ParVector<KaonThreeMesonCurrent,Energy> interfaceKstarVectorWidths
("KstarVectorWidths",
"The widths for the Kstar resonances if used local values",
&KaonThreeMesonCurrent::_kstar2width, GeV, -1, 1.0*GeV, ZERO, 10.0*GeV,
false, false, true);
static ParVector<KaonThreeMesonCurrent,double> interfaceAxialRhoWeight
("AxialRhoWeight",
"The weights of the different rho resonances in the F1,2,3 form factor",
&KaonThreeMesonCurrent::_rho1wgts,
0, 0, 0, -1000, 1000, false, false, true);
static ParVector<KaonThreeMesonCurrent,double> interfaceAxialKStarWeight
("AxialKStarWeight",
"The weights of the different Kstar resonances in the F1,2,3 form factor",
&KaonThreeMesonCurrent::_kstar1wgts,
0, 0, 0, -1000, 1000, false, false, true);
static ParVector<KaonThreeMesonCurrent,double> interfaceVectorRhoWeight
("VectorRhoWeight",
"The weights of the different rho resonances in the F1,2,3 form factor",
&KaonThreeMesonCurrent::_rho2wgts,
0, 0, 0, -1000, 1000, false, false, true);
static ParVector<KaonThreeMesonCurrent,double> interfaceVectorKStarWeight
("VectorKStarWeight",
"The weights of the different Kstar resonances in the F1,2,3 form factor",
&KaonThreeMesonCurrent::_kstar2wgts,
0, 0, 0, -1000, 1000, false, false, true);
static Switch<KaonThreeMesonCurrent,bool> interfaceRhoParameters
("RhoParameters",
"Use local values of the rho meson masses and widths",
&KaonThreeMesonCurrent::_rhoparameters, true, false, false);
static SwitchOption interfaceRhoParameterstrue
(interfaceRhoParameters,
"Local",
"Use local values of the parameters",
true);
static SwitchOption interfaceRhoParametersParticleData
(interfaceRhoParameters,
"ParticleData",
"Use the masses and widths from the particle data objects",
false);
static Switch<KaonThreeMesonCurrent,bool> interfaceKstarParameters
("KstarParameters",
"Use local values of the rho meson masses and widths",
&KaonThreeMesonCurrent::_kstarparameters, true, false, false);
static SwitchOption interfaceKstarParameterstrue
(interfaceKstarParameters,
"Local",
"Use local values of the parameters",
true);
static SwitchOption interfaceKstarParametersParticleData
(interfaceKstarParameters,
"ParticleData",
"Use the masses and widths from the particle data objects",
false);
static Switch<KaonThreeMesonCurrent,bool> interfacea1Parameters
("a1Parameters",
"Use local values of the rho meson masses and widths",
&KaonThreeMesonCurrent::_a1parameters, true, false, false);
static SwitchOption interfacea1Parameterstrue
(interfacea1Parameters,
"Local",
"Use local values of the parameters",
true);
static SwitchOption interfacea1ParametersParticleData
(interfacea1Parameters,
"ParticleData",
"Use the masses and widths from the particle data objects",
false);
static Switch<KaonThreeMesonCurrent,bool> interfaceK1Parameters
("K1Parameters",
"Use local values of the rho meson masses and widths",
&KaonThreeMesonCurrent::_k1parameters, true, false, false);
static SwitchOption interfaceK1Parameterstrue
(interfaceK1Parameters,
"Local",
"Use local values of the parameters",
true);
static SwitchOption interfaceK1ParametersParticleData
(interfaceK1Parameters,
"ParticleData",
"Use the masses and widths from the particle data objects",
false);
static Switch<KaonThreeMesonCurrent,bool> interfacea1WidthOption
("a1WidthOption",
"Option for the treatment of the a1 width",
&KaonThreeMesonCurrent::_a1opt, true, false, false);
static SwitchOption interfacea1WidthOptionLocal
(interfacea1WidthOption,
"Local",
"Use a calculation of the running width based on the parameters as"
" interpolation table.",
true);
static SwitchOption interfacea1WidthOptionParam
(interfacea1WidthOption,
"Kuhn",
"Use the parameterization of Kuhn and Santamaria for default parameters."
" This should only be used for testing vs TAUOLA",
false);
static ParVector<KaonThreeMesonCurrent,Energy> interfacea1RunningWidth
("a1RunningWidth",
"The values of the a_1 width for interpolation to giving the running width.",
&KaonThreeMesonCurrent::_a1runwidth, GeV, -1, 1.0*GeV, ZERO, 10.0*GeV,
false, false, true);
static ParVector<KaonThreeMesonCurrent,Energy2> interfacea1RunningQ2
("a1RunningQ2",
"The values of the q^2 for interpolation to giving the running width.",
&KaonThreeMesonCurrent::_a1runq2, GeV2, -1, 1.0*GeV2, ZERO, 10.0*GeV2,
false, false, true);
static ParVector<KaonThreeMesonCurrent,Energy> interfaceK1Masses
("K1Masses",
"Masses of the K_1 mesons",
&KaonThreeMesonCurrent::_k1mass, GeV, -1, 1.0*GeV, ZERO, 10.0*GeV,
false, false, Interface::limited);
static ParVector<KaonThreeMesonCurrent,Energy> interfaceK1Widths
("K1Widths",
"Widths of the K_1 mesons",
&KaonThreeMesonCurrent::_k1width, GeV, -1, 1.0*GeV, ZERO, 10.0*GeV,
false, false, Interface::limited);
static ParVector<KaonThreeMesonCurrent,double> interfaceK1WeightKStarPi
("K1WeightKStarPi",
"The relative weights for the K_1 resonances in the K* pi final-state",
&KaonThreeMesonCurrent::_k1wgta, -1, 1.0, 0, 10.0,
false, false, Interface::limited);
static ParVector<KaonThreeMesonCurrent,double> interfaceK1WeightRhoK
("K1WeightRhoK",
"The relative weights for the K_1 resonances in the rho K final-state",
&KaonThreeMesonCurrent::_k1wgtb, -1, 1.0, 0, 10.0,
false, false, Interface::limited);
static Parameter<KaonThreeMesonCurrent,double> interfaceEpsOmega
("EpsOmega",
"The omega-phi mixing ",
&KaonThreeMesonCurrent::_epsomega, 0.05, 0.0, 1.0,
false, false, Interface::limited);
static Parameter<KaonThreeMesonCurrent,Energy> interfaceOmegaMass
("OmegaMass",
"The mass of the omega meson",
&KaonThreeMesonCurrent::_omegamass, GeV, 0.782*GeV, ZERO, 10.0*GeV,
false, false, Interface::limited);
static Parameter<KaonThreeMesonCurrent,Energy> interfaceOmegaWidth
("OmegaWidth",
"The width of the omega meson",
&KaonThreeMesonCurrent::_omegawidth, GeV, 0.00843*GeV, ZERO, 10.0*GeV,
false, false, Interface::limited);
static Parameter<KaonThreeMesonCurrent,Energy> interfacePhiMass
("PhiMass",
"The mass of the phi meson",
&KaonThreeMesonCurrent::_phimass, GeV, 1.020*GeV, ZERO, 10.0*GeV,
false, false, Interface::limited);
static Parameter<KaonThreeMesonCurrent,Energy> interfacePhiWidth
("PhiWidth",
"The width of the phi meson",
&KaonThreeMesonCurrent::_phiwidth, GeV, 0.00443*GeV, ZERO, 10.0*GeV,
false, false, Interface::limited);
static Parameter<KaonThreeMesonCurrent,double> interfaceOmegaKStarWeight
("OmegaKStarWeight",
"The relative weight of the omega-phi and K* terms",
&KaonThreeMesonCurrent::_omegaKstarwgt, 1./sqrt(2.), 0.0, 100.0,
false, false, Interface::limited);
static Switch<KaonThreeMesonCurrent,bool> interfaceOmegaParameters
("OmegaParameters",
"Use local values of the omega/phi meson masses and widths",
&KaonThreeMesonCurrent::_omegaopt, true, false, false);
static SwitchOption interfaceOmegaParameterstrue
(interfaceOmegaParameters,
"Local",
"Use local values of the parameters",
true);
static SwitchOption interfaceOmegaParametersParticleData
(interfaceOmegaParameters,
"ParticleData",
"Use the masses and widths from the particle data objects",
false);
}
void KaonThreeMesonCurrent::inita1Width(int iopt) {
if(iopt==-1) {
_maxcalc=_maxmass;
if(!_initializea1||_maxmass==ZERO) return;
// parameters for the table of values
Energy2 step(sqr(_maxmass)/199.);
// integrator to perform the integral
vector<double> inweights;inweights.push_back(0.5);inweights.push_back(0.5);
vector<int> intype;intype.push_back(2);intype.push_back(3);
Energy mrho(getParticleData(ParticleID::rhoplus)->mass()),
wrho(getParticleData(ParticleID::rhoplus)->width());
vector<Energy> inmass(2,mrho),inwidth(2,wrho);
vector<double> inpow(2,0.0);
ThreeBodyAllOnCalculator<KaonThreeMesonCurrent>
widthgen(inweights,intype,inmass,inwidth,inpow,*this,0,_mpi,_mpi,_mpi);
// normalisation constant to give physical width if on shell
double a1const(_a1width/(widthgen.partialWidth(sqr(_a1mass))));
// loop to give the values
_a1runq2.clear();_a1runwidth.clear();
for(Energy2 moff2 = ZERO; moff2<=sqr(_maxmass); moff2+=step) {
_a1runwidth.push_back(widthgen.partialWidth(moff2)*a1const);
_a1runq2.push_back(moff2);
}
}
// set up the interpolator
else if(iopt==0) {
_a1runinter = make_InterpolatorPtr(_a1runwidth,_a1runq2,3);
}
}
// modes handled by this class
bool KaonThreeMesonCurrent::acceptMode(int imode) const {
return imode>=2&&imode<=11&&imode!=8;
}
// complete the construction of the decay mode for integration
bool KaonThreeMesonCurrent::createMode(int icharge, unsigned int imode,
DecayPhaseSpaceModePtr mode,
unsigned int iloc,unsigned int ires,
DecayPhaseSpaceChannelPtr phase,Energy upp) {
int iq(0),ia(0);
if(!acceptMode(imode)) return false;
tPDVector extpart(particles(1,imode,iq,ia));
Energy min(ZERO);
for(unsigned int ix=0;ix<extpart.size();++ix) min+=extpart[ix]->massMin();
if(min>upp) return false;
// the particles we will use a lot
tPDPtr a1,k1[2];
if(icharge==-3) {
a1 = getParticleData(ParticleID::a_1minus);
k1[0] = getParticleData(ParticleID::K_1minus);
k1[1] = getParticleData(ParticleID::Kstar_1minus);
}
else if(icharge==3) {
a1 = getParticleData(ParticleID::a_1plus);
k1[0] = getParticleData(ParticleID::K_1plus);
k1[1] = getParticleData(ParticleID::Kstar_1plus);
}
else {
return false;
}
_maxmass=max(_maxmass,upp);
// the rho0 resonances
tPDPtr rho0[3] ={getParticleData( 113),getParticleData( 100113),
getParticleData( 30113)};
// the charged rho resonances
tPDPtr rhoc[3] ={getParticleData(-213),getParticleData(-100213),
getParticleData(-30213)};
// the K*0 resonances
tPDPtr Kstar0[3]={getParticleData( 313),getParticleData( 100313),
getParticleData( 30313)};
// the charged K* resonances
tPDPtr Kstarc[3]={getParticleData(-323),getParticleData(-100323),
getParticleData(-30323)};
if(icharge==3) {
for(unsigned int ix=0;ix<3;++ix) {
if(rhoc[ix]) rhoc[ix]=rhoc[ix]->CC();
if(Kstar0[ix]) Kstar0[ix]=Kstar0[ix]->CC();
if(Kstarc[ix]) Kstarc[ix]=Kstarc[ix]->CC();
}
}
DecayPhaseSpaceChannelPtr newchannel;
if(imode==2) {
// channels for K- pi- K+
for(unsigned int ix=0;ix<3;++ix) {
if(Kstar0[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1 ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(Kstar0[ix],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
}
if(rho0[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1 ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(rho0[ix],0,0.0,iloc,iloc+2);
mode->addChannel(newchannel);
}
for(unsigned int iy=0;iy<3;++iy) {
if(!rhoc[ix]) continue;
if(Kstar0[iy]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhoc[ix] ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(Kstar0[iy],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
}
}
}
}
else if(imode==3) {
// channels for K0 pi- K0bar
for(unsigned int ix=0;ix<3;++ix) {
if(Kstarc[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1 ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(Kstarc[ix],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
}
if(rho0[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1 ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(rho0[ix],0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
}
for(unsigned int iy=0;iy<3;++iy) {
if(!rhoc[ix]) continue;
if(Kstarc[iy]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhoc[ix] ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(Kstarc[iy],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
}
}
}
}
else if(imode==4) {
// channels for K- pi0 K0
for(unsigned int ix=0;ix<3;++ix) {
if(Kstar0[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1 ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(Kstar0[ix],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
}
if(Kstarc[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1 ,0,0.0,-ires-1,iloc+2);
newchannel->addIntermediate(Kstarc[ix],0,0.0, iloc ,iloc+1);
mode->addChannel(newchannel);
}
if(rhoc[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1 ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(rhoc[ix],0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
}
for(unsigned int iy=0;iy<3;++iy) {
if(!rhoc[ix]) continue;
if(Kstar0[iy]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhoc[ix] ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(Kstar0[iy],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
}
if(Kstarc[iy]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhoc[ix] ,0,0.0,-ires-1,iloc+2);
newchannel->addIntermediate(Kstarc[iy],0,0.0, iloc ,iloc+1);
mode->addChannel(newchannel);
}
}
}
}
else if(imode==5) {
// channels for pi0 pi0 K-
for(unsigned int ix=0;ix<3;++ix) {
if(!Kstarc[ix]) continue;
for(unsigned int ik=0;ik<2;++ik) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(k1[ik] ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(Kstarc[ix],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(k1[ik] ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(Kstarc[ix],0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
}
for(unsigned int iy=0;iy<3;++iy) {
if(!Kstarc[iy]) continue;
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(Kstarc[ix],0,0.0,-ires-1,iloc );
newchannel->addIntermediate(Kstarc[iy],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(Kstarc[ix],0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(Kstarc[iy],0,0.0, iloc ,iloc+2);
mode->addChannel(newchannel);
}
}
}
else if(imode==6) {
// channels for K- pi- pi+
for(unsigned int ix=0;ix<3;++ix) {
for(unsigned int ik=0;ik<2;++ik) {
if(rho0[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(k1[ik] ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(rho0[ix],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
}
if(Kstar0[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(k1[ik] ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(Kstar0[ix],0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
}
}
for(unsigned int iy=0;iy<3;++iy) {
if(!Kstarc[ix]) continue;
if(rho0[iy]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(Kstarc[ix],0,0.0,-ires-1,iloc);
newchannel->addIntermediate(rho0[iy] ,0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
}
if(Kstar0[iy]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(Kstarc[ix],0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(Kstar0[iy],0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
}
}
}
}
else if(imode==7) {
// channels for pi- kbar0 pi0
for(unsigned int ix=0;ix<3;++ix) {
for(unsigned int ik=0;ik<2;++ik) {
if(rhoc[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(k1[ik] ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(rhoc[ix],0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
}
if(Kstar0[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(k1[ik] ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(Kstar0[ix],0,0.0,iloc+1,iloc+2);
mode->addChannel(newchannel);
}
if(Kstarc[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(k1[ik] ,0,0.0,-ires-1,iloc+2);
newchannel->addIntermediate(Kstarc[ix],0,0.0, iloc,iloc+1);
mode->addChannel(newchannel);
}
}
for(unsigned int iy=0;iy<3;++iy) {
if(!Kstarc[ix]) continue;
if(Kstar0[iy]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(Kstarc[ix],0,0.0,-ires-1,iloc);
newchannel->addIntermediate(Kstar0[iy],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
}
if(rhoc[iy]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(Kstarc[ix],0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(rhoc[iy] ,0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
}
if(Kstarc[iy]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(Kstarc[ix],0,0.0,-ires-1,iloc+2);
newchannel->addIntermediate(Kstarc[iy],0,0.0, iloc ,iloc+1);
mode->addChannel(newchannel);
}
}
}
}
else if(imode==9||imode==10) {
// channels for K_S0 pi- K_S0 and K_L0 pi- K_L0
for(unsigned int ix=0;ix<3;++ix) {
if(Kstarc[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1 ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(Kstarc[ix],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1 ,0,0.0,-ires-1,iloc+2);
newchannel->addIntermediate(Kstarc[ix],0,0.0, iloc ,iloc+1);
mode->addChannel(newchannel);
}
for(unsigned int iy=0;iy<3;++iy) {
if(!rhoc[ix]) continue;
if(Kstarc[iy]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhoc[ix] ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(Kstarc[iy],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhoc[ix] ,0,0.0,-ires-1,iloc+2);
newchannel->addIntermediate(Kstarc[iy],0,0.0, iloc ,iloc+1);
mode->addChannel(newchannel);
}
}
}
}
else if(imode==11) {
// channels for K_S0 pi- K_L0
for(unsigned int ix=0;ix<3;++ix) {
if(Kstarc[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1 ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(Kstarc[ix],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1 ,0,0.0,-ires-1,iloc+2);
newchannel->addIntermediate(Kstarc[ix],0,0.0, iloc ,iloc+1);
mode->addChannel(newchannel);
}
if(rho0[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1 ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(rho0[ix],0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
}
for(unsigned int iy=0;iy<3;++iy) {
if(!rhoc[ix]) continue;
if(Kstarc[iy]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhoc[ix] ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(Kstarc[iy],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhoc[ix] ,0,0.0,-ires-1,iloc+2);
newchannel->addIntermediate(Kstarc[iy],0,0.0, iloc ,iloc+1);
mode->addChannel(newchannel);
}
}
}
}
if(_rhoparameters) {
for(unsigned int ix=0;ix<_rho1mass.size();++ix) {
if(rhoc[ix]) mode->resetIntermediate(rhoc[ix],_rho1mass[ix],
_rho1width[ix]);
if(rho0[ix]) mode->resetIntermediate(rho0[ix],_rho1mass[ix],
_rho1width[ix]);
}
}
// K star parameters in the base class
if(_kstarparameters) {
for(unsigned int ix=0;ix<_kstar1mass.size();++ix) {
if(Kstarc[ix]) mode->resetIntermediate(Kstarc[ix],_kstar1mass[ix],
_kstar1width[ix]);
if(Kstar0[ix]) mode->resetIntermediate(Kstar0[ix],_kstar1mass[ix],
_kstar1width[ix]);
}
}
return true;
}
void KaonThreeMesonCurrent::dataBaseOutput(ofstream & os,
bool header,bool create) const {
if(header) os << "update decayers set parameters=\"";
if(create) os << "create Herwig::KaonThreeMesonCurrent "
<< name() << " HwWeakCurrents.so\n";
for(unsigned int ix=0;ix<_rho1wgts.size();++ix) {
if(ix<3) {
os << "newdef " << name() << ":AxialRhoWeight " << ix
<< " " << _rho1wgts[ix] << "\n";
}
else {
os << "insert " << name() << ":AxialRhoWeight " << ix
<< " " << _rho1wgts[ix] << "\n";
}
}
for(unsigned int ix=0;ix<_kstar1wgts.size();++ix) {
if(ix<3) {
os << "newdef " << name() << ":AxialKStarWeight " << ix
<< " " << _kstar1wgts[ix] << "\n";}
else {
os << "insert " << name() << ":AxialKStarWeight " << ix
<< " " << _kstar1wgts[ix] << "\n";
}
}
for(unsigned int ix=0;ix<_rho2wgts.size();++ix) {
if(ix<3) {
os << "newdef " << name() << ":VectorRhoWeight " << ix
<< " " << _rho2wgts[ix] << "\n";
}
else {
os << "insert " << name() << ":VectorRhoWeight " << ix
<< " " << _rho2wgts[ix] << "\n";
}
}
for(unsigned int ix=0;ix<_kstar2wgts.size();++ix) {
if(ix<3) {
os << "newdef " << name() << ":VectorKStarWeight " << ix
<< " " << _kstar2wgts[ix] << "\n";}
else {
os << "insert " << name() << ":VectorKStarWeight " << ix
<< " " << _kstar2wgts[ix] << "\n";
}
}
os << "newdef " << name() << ":OmegaKStarWeight " << _omegaKstarwgt << "\n";
os << "newdef " << name() << ":EpsOmega " << _epsomega << "\n";
os << "newdef " << name() << ":Initializea1 " << _initializea1 << "\n";
os << "newdef " << name() << ":RhoParameters " << _rhoparameters << "\n";
os << "newdef " << name() << ":KstarParameters " << _kstarparameters << "\n";
os << "newdef " << name() << ":a1Parameters " << _a1parameters << "\n";
os << "newdef " << name() << ":K1Parameters " << _k1parameters << "\n";
os << "newdef " << name() << ":OmegaParameters " << _omegaopt << "\n";
os << "newdef " << name() << ":a1WidthOption " << _a1opt << "\n";
for(unsigned int ix=0;ix<_a1runwidth.size();++ix) {
os << "newdef " << name() << ":a1RunningWidth " << ix
<< " " << _a1runwidth[ix]/GeV << "\n";
}
for(unsigned int ix=0;ix<_a1runq2.size();++ix) {
os << "newdef " << name() << ":a1RunningQ2 " << ix
<< " " << _a1runq2[ix]/GeV2 << "\n";
}
os << "newdef " << name() << ":A1Width " << _a1width/GeV << "\n";
os << "newdef " << name() << ":A1Mass " << _a1mass/GeV << "\n";
os << "newdef " << name() << ":OmegaWidth " << _omegawidth/GeV << "\n";
os << "newdef " << name() << ":OmegaMass " << _omegamass/GeV << "\n";
os << "newdef " << name() << ":PhiWidth " << _phiwidth/GeV << "\n";
os << "newdef " << name() << ":PhiMass " << _phimass/GeV << "\n";
os << "newdef " << name() << ":FPi " << _fpi/MeV << "\n";
for(unsigned int ix=0;ix<_k1mass.size();++ix) {
if(ix<2) {
os << "newdef " << name() << ":K1Masses " << ix
<< " " << _k1mass[ix]/GeV << "\n";
}
else {
os << "insert " << name() << ":K1Masses " << ix
<< " " << _k1mass[ix]/GeV << "\n";
}
}
for(unsigned int ix=0;ix<_k1width.size();++ix) {
if(ix<2) {
os << "newdef " << name() << ":K1Widths " << ix
<< " " << _k1width[ix]/GeV << "\n";
}
else {
os << "insert " << name() << ":K1Widths " << ix
<< " " << _k1width[ix]/GeV << "\n";
}
}
for(unsigned int ix=0;ix<_rho1mass.size();++ix) {
if(ix<3) os << "newdef " << name() << ":RhoAxialMasses " << ix
<< " " << _rho1mass[ix]/GeV << "\n";
else os << "insert " << name() << ": RhoAxialMasses" << ix
<< " " << _rho1mass[ix]/GeV << "\n";
}
for(unsigned int ix=0;ix<_rho1width.size();++ix) {
if(ix<3) os << "newdef " << name() << ":RhoAxialWidths " << ix
<< " " << _rho1width[ix]/GeV << "\n";
else os << "insert " << name() << ":RhoAxialWidths " << ix
<< " " << _rho1width[ix]/GeV << "\n";
}
for(unsigned int ix=0;ix<_rho2mass.size();++ix) {
if(ix<3) os << "newdef " << name() << ":RhoVectorMasses " << ix
<< " " << _rho2mass[ix]/GeV << "\n";
else os << "insert " << name() << ": RhoVectorMasses" << ix
<< " " << _rho2mass[ix]/GeV << "\n";
}
for(unsigned int ix=0;ix<_rho2width.size();++ix) {
if(ix<3) os << "newdef " << name() << ":RhoVectorWidths " << ix
<< " " << _rho2width[ix]/GeV << "\n";
else os << "insert " << name() << ":RhoVectorWidths " << ix
<< " " << _rho2width[ix]/GeV << "\n";
}
for(unsigned int ix=0;ix<_kstar1mass.size();++ix) {
if(ix<3) os << "newdef " << name() << ":KstarAxialMasses " << ix
<< " " << _kstar1mass[ix]/GeV << "\n";
else os << "insert " << name() << ": KstarAxialMasses" << ix
<< " " << _kstar1mass[ix]/GeV << "\n";
}
for(unsigned int ix=0;ix<_kstar1width.size();++ix) {
if(ix<3) os << "newdef " << name() << ":KstarAxialWidths " << ix
<< " " << _kstar1width[ix]/GeV << "\n";
else os << "insert " << name() << ":KstarAxialWidths " << ix
<< " " << _kstar1width[ix]/GeV << "\n";
}
for(unsigned int ix=0;ix<_kstar2mass.size();++ix) {
if(ix<3) os << "newdef " << name() << ":KstarVectorMasses " << ix
<< " " << _kstar2mass[ix]/GeV << "\n";
else os << "insert " << name() << ": KstarVectorMasses" << ix
<< " " << _kstar2mass[ix]/GeV << "\n";
}
for(unsigned int ix=0;ix<_kstar2width.size();++ix) {
if(ix<3) os << "newdef " << name() << ":KstarVectorWidths " << ix
<< " " << _kstar2width[ix]/GeV << "\n";
else os << "insert " << name() << ":KstarVectorWidths " << ix
<< " " << _kstar2width[ix]/GeV << "\n";
}
for(unsigned int ix=0;ix<_k1wgta.size();++ix) {
if(ix<2) os << "newdef " << name() << ":K1WeightKStarPi " << ix
<< " " << _k1wgta[ix] << "\n";
else os << "insert " << name() << ":K1WeightKStarPi " << ix
<< " " << _k1wgta[ix] << "\n";
}
for(unsigned int ix=0;ix<_k1wgtb.size();++ix) {
if(ix<2) os << "newdef " << name() << ":K1WeightRhoK " << ix
<< " " << _k1wgtb[ix] << "\n";
else os << "insert " << name() << ":K1WeightRhoK " << ix
<< " " << _k1wgtb[ix] << "\n";
}
ThreeMesonCurrentBase::dataBaseOutput(os,false,false);
if(header) os << "\n\" where BINARY ThePEGName=\""
<< fullName() << "\";" << endl;
}
void KaonThreeMesonCurrent::doinit() {
ThreeMesonCurrentBase::doinit();
// the particles we will use a lot
tPDPtr a1(getParticleData(ParticleID::a_1minus)),
pi0(getParticleData(ParticleID::pi0)),
piplus(getParticleData(ParticleID::piplus)),
piminus(getParticleData(ParticleID::piminus));
tPDPtr k1[2]={getParticleData(ParticleID::K_1minus),
getParticleData(ParticleID::Kstar_1minus)};
// masses for the running widths
_mpi=piplus->mass();
_mK=getParticleData(ParticleID::K0)->mass();
// the charged rho resonances
tPDPtr rhoc[3]={getParticleData(-213),getParticleData(-100213),
getParticleData(-30213)};
// the charged K* resonances
tPDPtr Kstarc[3]={getParticleData(-323),getParticleData(-100323),
getParticleData(-30323)};
if(!_a1parameters) {
_a1mass=a1->mass();
_a1width=a1->width();
}
// mass and width of the k_1
if(!_k1parameters) {
for(unsigned int ix=0;ix<2;++ix) {
_k1mass[ix] = k1[ix]->mass();
_k1width[ix] = k1[ix]->width();
}
}
// initialise the a_1 running width calculation
inita1Width(-1);
// rho parameters in the base classs
tcPDPtr temp;
unsigned int ix;
if(_rhoparameters&&_rho1mass.size()<3) {
ix = _rho1mass.size();
_rho1mass.resize(3);
_rho1width.resize(3);
for(;ix<3;++ix) {
if(rhoc[ix]) {
_rho1mass [ix]=rhoc[ix]->mass();
_rho1width[ix]=rhoc[ix]->width();
}
}
}
else if(!_rhoparameters) {
_rho1mass.resize(3);_rho1width.resize(3);
for(ix=0;ix<3;++ix) {
if(rhoc[ix]) {
_rho1mass[ix]=rhoc[ix]->mass();
_rho1width[ix]=rhoc[ix]->width();
}
}
}
// K star parameters in the base class
if(_kstarparameters&&_kstar1mass.size()<3) {
ix = _kstar1mass.size();
_kstar1mass.resize(3);_kstar1width.resize(3);
for(;ix<3;++ix) {
if(Kstarc[ix]) {
_kstar1mass[ix]=Kstarc[ix]->mass();
_kstar1width[ix]=Kstarc[ix]->width();
}
}
}
else if(!_kstarparameters) {
_kstar1mass.resize(3);_kstar1width.resize(3);
for(ix=0;ix<3;++ix) {
if(Kstarc[ix]) {
_kstar1mass[ix]=Kstarc[ix]->mass();
_kstar1width[ix]=Kstarc[ix]->width();
}
}
}
// rho parameters here
if(_rhoparameters&&_rho2mass.size()<3) {
ix = _rho2mass.size();
_rho2mass.resize(3);_rho2width.resize(3);
for(;ix<3;++ix) {
if(rhoc[ix]) {
_rho2mass[ix]=rhoc[ix]->mass();
_rho2width[ix]=rhoc[ix]->width();
}
}
}
else if(!_rhoparameters) {
_rho2mass.resize(3);_rho2width.resize(3);
for(ix=0;ix<3;++ix) {
if(rhoc[ix]) {
_rho2mass[ix]=rhoc[ix]->mass();
_rho2width[ix]=rhoc[ix]->width();
}
}
}
// Kstar parameters here
if(_kstarparameters&&_kstar2width.size()<3) {
ix = _kstar2mass.size();
_kstar2mass.resize(3);_kstar2width.resize(3);
for(;ix<3;++ix) {
if(Kstarc[ix]) {
_kstar2mass[ix]=Kstarc[ix]->mass();
_kstar2width[ix]=Kstarc[ix]->width();
}
}
}
else if(!_kstarparameters) {
_kstar2mass.resize(3);_kstar2width.resize(3);
for(ix=0;ix<3;++ix) {
if(Kstarc[ix]) {
_kstar2mass[ix]=Kstarc[ix]->mass();
_kstar2width[ix]=Kstarc[ix]->width();
}
}
}
inita1Width(0);
}
KaonThreeMesonCurrent::FormFactors
KaonThreeMesonCurrent::calculateFormFactors(const int ichan,const int imode,
Energy2 q2,Energy2 s1,
Energy2 s2,Energy2 s3) const {
useMe();
Complex F1, F2, F5;
// calculate the K- pi - K+ factor
if(imode==2) {
Complex a1fact(a1BreitWigner(q2)*sqrt(2.)/3.);
if(ichan<0) {
F1 = -a1fact*TKstar1(s1,-1);
F2 = a1fact*Trho1(s2,-1);
F5 = Trho2(q2,-1)*TOmegaKStar(s1,s2,-1)*sqrt(2.);
}
else if(ichan%5==0) F1 = -a1fact*TKstar1(s1, ichan/5);
else if(ichan%5==1) F2 = a1fact*Trho1( s2,(ichan-1)/5);
else if(ichan%5>=2) F5 = Trho2(q2,ichan/5)*TOmegaKStar(s1,s2,2*((ichan-2)%5))
*sqrt(2.);
}
// calculate the K0 pi- K0bar
else if(imode==3) {
Complex a1fact(a1BreitWigner(q2)*sqrt(2.)/3.);
if(ichan<0) {
F1 =-a1fact*TKstar1(s1,-1);
F2 = a1fact*Trho1 (s2,-1);
F5 =-Trho2(q2,-1)*TOmegaKStar(s1,s2,-1)*sqrt(2.);
}
else if(ichan%5==0) F1 = -a1fact*TKstar1(s1, ichan/5);
else if(ichan%5==1) F2 = a1fact*Trho1 (s2,(ichan-1)/5);
else if(ichan%5>=2) F5 = -Trho2(q2,ichan/5)*TOmegaKStar(s1,s2,2*((ichan-2)%5))
*sqrt(2.);
}
// calculate the K- pi0 k0
else if(imode==4) {
Complex a1fact(a1BreitWigner(q2)/3.);
if(ichan<0) {
F1 = a1fact*( TKstar1(s1,-1)-TKstar1(s3,-1));
F2 = -a1fact*(2.*Trho1(s2,-1)+TKstar1(s3,-1));
F5 = Trho2(q2,-1)*(TKstar1(s3,-1)-TKstar1(s1,-1))/(1.+_omegaKstarwgt)/sqrt(2.);
}
else if(ichan%9==0) F1 = a1fact*TKstar1(s1,ichan/9)/3.;
else if(ichan%9==1) {
F1 = +a1fact*TKstar1(s3,(ichan-1)/9)/3.;
F2 = -a1fact*TKstar1(s3,(ichan-1)/9)/3.;
}
else if(ichan%9==2) F2 = -a1fact*2.*Trho1(s2,(ichan-2)/9)/3.;
else if(ichan%9<6) F5 =-Trho2(q2,ichan/9)*TKstar1(s1,(ichan-3)%9)
/(1.+_omegaKstarwgt)/sqrt(2.);
else F5 = Trho2(q2,ichan/9)*TKstar1(s3,(ichan-6)%9)
/(1.+_omegaKstarwgt)/sqrt(2.);
}
// calculate the pi0 pi0 K-
else if(imode==5) {
if(ichan<0) {
Complex K1fact(TK1(q2,0,-1)/6.);
F1 = K1fact*TKstar1(s1,-1);
F2 =-K1fact*TKstar1(s2,-1);
F5 =-0.25*TKstar2(q2,-1)*(TKstar1(s1,-1)-TKstar1(s2,-1));
}
else if(ichan%10==0) F1= TK1(q2,0,0)/6.*TKstar1(s1,ichan/10);
else if(ichan%10==1) F2= -TK1(q2,0,0)/6.*TKstar1(s2,ichan/10);
else if(ichan%10==2) F1= TK1(q2,0,1)/6.*TKstar1(s1,ichan/10);
else if(ichan%10==3) F2= -TK1(q2,0,1)/6.*TKstar1(s2,ichan/10);
else if(ichan%10<7 ) F5 =-sqrt(2.)/4*TKstar2(q2,ichan/10)*TKstar1(s1,(ichan-4)%10);
else F5 = sqrt(2.)/4*TKstar2(q2,ichan/10)*TKstar1(s2,(ichan-7)%10);
}
// calculate the K- pi- pi+
else if(imode==6) {
double fact=sqrt(2.)/3.;
if(ichan<0) {
F1 = -fact*TK1(q2,1,-1)*Trho1(s1,-1);
F2 = fact*TK1(q2,0,-1)*TKstar1(s2,-1);
F5 = -sqrt(0.5)*TKstar2(q2,-1)*(Trho1(s1,-1)+TKstar1(s2,-1));
}
else if(ichan%10==0) F1 = -fact*TK1(q2,1,0)*Trho1 (s1,ichan/10);
else if(ichan%10==1) F2 = fact*TK1(q2,0,0)*TKstar1(s2,ichan/10);
else if(ichan%10==2) F1 = -fact*TK1(q2,1,1)*Trho1( s1,ichan/10);
else if(ichan%10==3) F2 = fact*TK1(q2,0,1)*TKstar1(s2,ichan/10);
else if(ichan%10<7) F5 = -sqrt(0.5)*TKstar2(q2,ichan/10)*Trho1( s1,(ichan-4)%10);
else F5 = -sqrt(0.5)*TKstar2(q2,ichan/10)*TKstar1(s2,(ichan-7)%10);
}
// calculate the pi- K0bar pi0
else if(imode==7) {
if(ichan<0) {
Complex K1facta(TK1(q2,0,-1)),K1factb(TK1(q2,1,-1));
F1 = K1facta*(TKstar1(s1,-1)-TKstar1(s3,-1))/3.;
F2 =-(2.*K1factb*Trho1(s2,-1)+K1facta*TKstar1(s3,-1))/3.;
F5 = -0.5*TKstar2(q2,-1)*(2.*Trho1(s2,-1)+TKstar1(s1,-1)+TKstar1(s3,-1));
}
else if(ichan%15==0) F2 =-2.*TK1(q2,0,0)*Trho1 (s2,ichan/15)/3.;
else if(ichan%15==1) F1 = TK1(q2,1,0)*TKstar1(s1,ichan/15)/3.;
else if(ichan%15==2) {
F1 =-TK1(q2,1,0)*TKstar1(s3,ichan/15)/3.;
F2 =-TK1(q2,1,0)*TKstar1(s3,ichan/15)/3.;
}
else if(ichan%15==3) F2 =-2.*TK1(q2,0,1)*Trho1 (s2,ichan/15)/3.;
else if(ichan%15==4) F1 = TK1(q2,1,1)*TKstar1(s1,ichan/15)/3.;
else if(ichan%15==5) {
F1 =-TK1(q2,1,1)*TKstar1(s3,ichan/15)/3.;
F2 =-TK1(q2,1,1)*TKstar1(s3,ichan/15)/3.;
}
else if(ichan%15<9 ) F5 = -0.5*TKstar2(q2,ichan/15)*TKstar1(s1,(ichan- 6)%15);
else if(ichan%15<12) F5 = - TKstar2(q2,ichan/15)*Trho1 (s2,(ichan- 9)%15);
else F5 = -0.5*TKstar2(q2,ichan/15)*TKstar1(s3,(ichan-12)%15);
}
// calculate the K_S0 pi- K_S0 or K_L0 pi- K_L0
else if(imode==9||imode==10) {
Complex a1fact(a1BreitWigner(q2)/6.);
if(ichan<0) {
F1 = a1fact*(TKstar1(s1,-1)+TKstar1(s3,-1));
F2 = a1fact*TKstar1(s3,-1);
F5 = 0.5*Trho2(q2,-1)*(TOmegaKStar(s1,s2,-1)-TOmegaKStar(s3,s2,-1));
}
else if(ichan%8==0) F1=a1fact*TKstar1(s1,ichan/8);
else if(ichan%8==1) {
F1 = a1fact*TKstar1(s3,ichan/8);
F2 = a1fact*TKstar1(s3,ichan/8);
}
else if(ichan%8<5 ) F5 = -Trho2(q2,ichan/8)*TKstar1(s1,(ichan-2)%8)
/(1.+_omegaKstarwgt)/2.;
else F5 = Trho2(q2,ichan/8)*TKstar1(s3,(ichan-5)%8)
/(1.+_omegaKstarwgt)/2.;
}
else if(imode==11) {
Complex a1fact(a1BreitWigner(q2)/3./sqrt(2.));
if(ichan<0) {
F1 = -a1fact*(TKstar1(s1,-1)-TKstar1(s3,-1));
F2 = a1fact*(2.*Trho1(s2,-1)+TKstar1(s3,-1));
F5 = -Trho2(q2,-1)*(TOmegaKStar(s1,s2,-1)+TOmegaKStar(s3,s2,-1))/sqrt(2.);
}
else if(ichan%9==0) F1 =- a1fact*TKstar1(s1,ichan/9);
else if(ichan%9==1) {
F1 = a1fact*TKstar1(s3,ichan/9);
F2 = a1fact*TKstar1(s3,ichan/9);
}
else if(ichan%9==2) F2 = 2.*a1fact*Trho1( s2,ichan/9);
else if(ichan%9<6 ) F5 = -sqrt(0.5)*TKstar2(q2,ichan/9)*
TOmegaKStar(s1,s2,2*((ichan-3)%9))/sqrt(2.);
else F5 = -sqrt(0.5)*TKstar2(q2,ichan/9)*
TOmegaKStar(s3,s2,2*((ichan-6)%9))/sqrt(2.);
}
return FormFactors(F1 / _fpi,
F2 / _fpi,
InvEnergy(),
InvEnergy(),
-F5 / sqr(Constants::twopi) / pow<3,1>(_fpi));
}
void KaonThreeMesonCurrent::doinitrun() {
// set up the running a_1 width
inita1Width(0);
ThreeMesonCurrentBase::doinitrun();
}
void KaonThreeMesonCurrent::doupdate() {
ThreeMesonCurrentBase::doupdate();
// update running width if needed
if ( !touched() ) return;
if(_maxmass!=_maxcalc) inita1Width(-1);
}
double KaonThreeMesonCurrent::
threeBodyMatrixElement(const int , const Energy2 q2,
const Energy2 s3, const Energy2 s2,
const Energy2 s1, const Energy ,
const Energy , const Energy ) const {
Energy2 mpi2(sqr(_mpi));
Complex propb(Trho1(s1,-1)),propa(Trho1(s2,-1));
// the matrix element
Energy2 output(ZERO);
// first resonance
output+= ((s1-4.*mpi2)+0.25*(s3-s2)*(s3-s2)/q2)*real(propb*conj(propb));
// second resonance
output+= ((s2-4.*mpi2)+0.25*(s3-s1)*(s3-s1)/q2)*real(propa*conj(propa));
// the interference term
output+= (0.5*q2-s3-0.5*mpi2+0.25*(s3-s2)*(s3-s1)/q2)*real(propa*conj(propb)+
propb*conj(propa));
return output / sqr(_rho1mass[0]);
}
Complex KaonThreeMesonCurrent::Trho1(Energy2 q2,int ires) const {
Complex output(0.);
double norm(0.);
for(unsigned int ix=0,N=_rho1wgts.size();ix<N;++ix) norm+=_rho1wgts[ix];
if(ires<0) {
for(unsigned int ix=0,N=_rho1wgts.size();ix<N;++ix) {
output+=_rho1wgts[ix]*BWrho1(q2,ix);
}
}
else {
unsigned int temp(ires);
if(temp<_rho1wgts.size()) output=_rho1wgts[temp]*BWrho1(q2,temp);
}
return output/norm;
}
Complex KaonThreeMesonCurrent::Trho2(Energy2 q2,int ires) const {
Complex output(0.);
double norm(0.);
for(unsigned int ix=0,N=_rho2wgts.size();ix<N;++ix) norm+=_rho2wgts[ix];
if(ires<0) {
for(unsigned int ix=0,N=_rho2wgts.size();ix<N;++ix) {
output+=_rho2wgts[ix]*BWrho2(q2,ix);
}
}
else {
unsigned int temp(ires);
if(temp<_rho2wgts.size()) output=_rho2wgts[temp]*BWrho2(q2,temp);
}
return output/norm;
}
Complex KaonThreeMesonCurrent::TKstar1(Energy2 q2,int ires) const {
Complex output(0.);
double norm(0.);
for(unsigned int ix=0,N=_kstar1wgts.size();ix<N;++ix) norm+=_kstar1wgts[ix];
if(ires<0) {
for(unsigned int ix=0,N=_kstar1wgts.size();ix<N;++ix) {
output+=_kstar1wgts[ix]*BWKstar1(q2,ix);
}
}
else {
unsigned int temp(ires);
if(temp<_kstar1wgts.size()) output=_kstar1wgts[temp]*BWKstar1(q2,temp);
}
return output/norm;
}
Complex KaonThreeMesonCurrent::TKstar2(Energy2 q2,int ires) const {
Complex output(0.);
double norm(0.);
for(unsigned int ix=0,N=_kstar2wgts.size();ix<N;++ix) norm+=_kstar2wgts[ix];
if(ires<0) {
for(unsigned int ix=0,N=_kstar2wgts.size();ix<N;++ix) {
output+=_kstar2wgts[ix]*BWKstar2(q2,ix);
}
}
else {
unsigned int temp(ires);
if(temp<_kstar2wgts.size()) output=_kstar2wgts[temp]*BWKstar2(q2,temp);
}
return output/norm;
}
Complex KaonThreeMesonCurrent::BWrho1(Energy2 q2, unsigned int ires) const {
if(ires>=_rho1mass.size()) return 0.;
Energy mass = _rho1mass [ires];
Energy width = _rho1width[ires];
Energy q=sqrt(q2);
Energy pcm0 = Kinematics::pstarTwoBodyDecay(mass,_mpi,_mpi);
Energy pcm = q<=2.*_mpi ? ZERO : Kinematics::pstarTwoBodyDecay(q,_mpi,_mpi);
double ratio = Math::powi(pcm/pcm0, 3);
Energy gam(width*mass*ratio/q);
return sqr(mass)/(sqr(mass)-q2-Complex(0.,1.)*mass*gam);
}
Complex KaonThreeMesonCurrent::BWrho2(Energy2 q2, unsigned int ires) const {
if(ires>=_rho2mass.size()) return 0.;
Energy mass = _rho2mass [ires];
Energy width = _rho2width[ires];
Energy q=sqrt(q2);
Energy pcm0 = Kinematics::pstarTwoBodyDecay(mass,_mpi,_mpi);
Energy pcm = q<=2.*_mpi ? ZERO : Kinematics::pstarTwoBodyDecay(q,_mpi,_mpi);
double ratio(pcm/pcm0);ratio*=ratio*ratio;
Energy gam(width*mass*ratio/q);
return sqr(mass)/(sqr(mass)-q2-Complex(0.,1.)*mass*gam);
}
Complex KaonThreeMesonCurrent::BWKstar1(Energy2 q2, unsigned int ires) const {
if(ires>=_kstar1mass.size()) return 0.;
Energy mass = _kstar1mass [ires];
Energy width = _kstar1width[ires];
Energy q=sqrt(q2);
Energy pcm0 = Kinematics::pstarTwoBodyDecay(mass,_mK,_mpi);
Energy pcm = q<=_mpi+_mK ? ZERO : Kinematics::pstarTwoBodyDecay(q,_mK,_mpi);
double ratio(pcm/pcm0);ratio*=ratio*ratio;
Energy gam(width*mass*ratio/q);
return sqr(mass)/(sqr(mass)-q2-Complex(0.,1.)*mass*gam);
}
Complex KaonThreeMesonCurrent::BWKstar2(Energy2 q2, unsigned int ires) const {
if(ires>=_kstar2mass.size()) return 0.;
Energy mass = _kstar2mass [ires];
Energy width = _kstar2width[ires];
Energy q=sqrt(q2);
Energy pcm0 = Kinematics::pstarTwoBodyDecay(mass,_mK,_mpi);
Energy pcm = q<=_mpi+_mK ? ZERO : Kinematics::pstarTwoBodyDecay(q,_mK,_mpi);
double ratio(pcm/pcm0);ratio*=ratio*ratio;
Energy gam(width*mass*ratio/q);
return sqr(mass)/(sqr(mass)-q2-Complex(0.,1.)*mass*gam);
}
Complex KaonThreeMesonCurrent::a1BreitWigner(Energy2 q2) const {
Complex ii(0.,1.);
Energy2 m2(_a1mass*_a1mass);
Energy q(sqrt(q2));
return m2/(m2-q2-ii*q*a1Width(q2));
}
Complex KaonThreeMesonCurrent::TK1(Energy2 q2,unsigned int iopt,int ires) const {
Complex denom(0),num(0.);
if(iopt==0) {
for(unsigned int ix=0;ix<_k1wgta.size();++ix) denom+=_k1wgta[ix];
if(ires==-1) {
for(unsigned int ix=0;ix<_k1wgta.size();++ix)
num+=_k1wgta[ix]*K1BreitWigner(q2,ix);
}
else {
num+=_k1wgta[ires]*K1BreitWigner(q2,ires);
}
}
else if(iopt==1) {
for(unsigned int ix=0;ix<_k1wgtb.size();++ix) denom+=_k1wgtb[ix];
if(ires==-1) {
for(unsigned int ix=0;ix<_k1wgtb.size();++ix)
num+=_k1wgtb[ix]*K1BreitWigner(q2,ix);
}
else {
num+=_k1wgtb[ires]*K1BreitWigner(q2,ires);
}
}
else {
return 0.;
}
return num/denom;
}
Complex KaonThreeMesonCurrent::K1BreitWigner(Energy2 q2,unsigned int ires) const {
if(ires>=_k1mass.size()) return 0.;
Energy2 m2=sqr(_k1mass[ires]),mg=_k1mass[ires]*_k1width[ires];
return (-m2+Complex(0.,1.)*mg)/(q2-m2+Complex(0.,1.)*mg);
}
Energy KaonThreeMesonCurrent::a1Width(Energy2 q2) const {
if(!_a1opt) return _a1mass*_a1width*g(q2)/g(_a1mass*_a1mass)/sqrt(q2);
else return (*_a1runinter)(q2);
}
double KaonThreeMesonCurrent::g(Energy2 q2) const {
double output;
if(q2<9.*_mpi*_mpi) {
output=0.;
}
else if(q2<sqr(_rho1mass[0]+_mpi)) {
double diff=(q2-9.*_mpi*_mpi)/GeV2;
output=4.1*sqr(diff)*diff*(1.-3.3*diff+5.8*sqr(diff));
}
else {
double ratio = q2/GeV2;
output = ratio*(1.623+10.38/ratio-9.32/sqr(ratio)+0.65/(ratio*sqr(ratio)));
}
return output;
}
Complex KaonThreeMesonCurrent::Tomega(Energy2 q2, int ires) const {
double denom=(1.+_epsomega);
Complex num(0.);
if(ires<0) num=OmegaPhiBreitWigner(q2,0)+_epsomega*OmegaPhiBreitWigner(q2,1);
else if(ires==0) num=OmegaPhiBreitWigner(q2,0);
else num=OmegaPhiBreitWigner(q2,1);
return num/denom;
}
Complex KaonThreeMesonCurrent::OmegaPhiBreitWigner(Energy2 q2, unsigned int ires) const {
Energy2 m2,mg;
if(ires==0) {
m2=sqr(_omegamass);
mg=_omegamass*_omegawidth;
}
else {
m2=sqr(_phimass);
mg=_phimass*_phiwidth;
}
return (-m2+Complex(0.,1.)*mg)/(q2-m2+Complex(0.,1.)*mg);
}
Complex KaonThreeMesonCurrent::TOmegaKStar(Energy2 s1,Energy2 s2,int ires) const {
Complex output;
if(ires<0) output = _omegaKstarwgt*TKstar1(s1,-1)+Tomega(s2,-1);
else if(ires%2==0) output = _omegaKstarwgt*TKstar1(s1,ires/2);
else if(ires%2==1) output = Tomega(s2,ires/2);
return output/(1.+_omegaKstarwgt);
}
diff --git a/Decay/WeakCurrents/Makefile.am b/Decay/WeakCurrents/Makefile.am
--- a/Decay/WeakCurrents/Makefile.am
+++ b/Decay/WeakCurrents/Makefile.am
@@ -1,20 +1,41 @@
-pkglib_LTLIBRARIES = HwWeakCurrents.la
+
noinst_LTLIBRARIES = libHwWeakCurrent.la
libHwWeakCurrent_la_SOURCES = \
WeakDecayCurrent.cc WeakDecayCurrent.fh WeakDecayCurrent.h\
LeptonNeutrinoCurrent.cc LeptonNeutrinoCurrent.fh \
LeptonNeutrinoCurrent.h
-HwWeakCurrents_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 9:0:0
-HwWeakCurrents_la_SOURCES = \
-FourPionNovosibirskCurrent.cc FourPionNovosibirskCurrent.h \
-ScalarMesonCurrent.cc ScalarMesonCurrent.h\
-ThreeMesonCurrentBase.cc ThreeMesonCurrentBase.h \
-ThreeMesonDefaultCurrent.cc ThreeMesonDefaultCurrent.h\
-ThreePionCLEOCurrent.cc ThreePionCLEOCurrent.h\
-TwoMesonRhoKStarCurrent.cc TwoMesonRhoKStarCurrent.h\
-TwoPionPhotonCurrent.cc TwoPionPhotonCurrent.h\
-VectorMesonCurrent.cc VectorMesonCurrent.h\
-FivePionCurrent.cc FivePionCurrent.h \
-KPiCurrent.cc KPiCurrent.h\
-KaonThreeMesonCurrent.cc KaonThreeMesonCurrent.h
+BUILT_SOURCES = WeakCurrents__all.cc
+DISTCLEANFILES = WeakCurrents__all.cc
+
+WeakCurrents__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+FourPionNovosibirskCurrent.h \
+ScalarMesonCurrent.h\
+ThreeMesonCurrentBase.h \
+ThreeMesonDefaultCurrent.h\
+ThreePionCLEOCurrent.h\
+TwoMesonRhoKStarCurrent.h\
+TwoPionPhotonCurrent.h\
+VectorMesonCurrent.h\
+FivePionCurrent.h \
+KPiCurrent.h\
+KaonThreeMesonCurrent.h
+
+
+ALL_CC_FILES = \
+FourPionNovosibirskCurrent.cc \
+ScalarMesonCurrent.cc \
+ThreeMesonCurrentBase.cc \
+ThreeMesonDefaultCurrent.cc \
+ThreePionCLEOCurrent.cc \
+TwoMesonRhoKStarCurrent.cc \
+TwoPionPhotonCurrent.cc \
+VectorMesonCurrent.cc \
+FivePionCurrent.cc \
+KPiCurrent.cc \
+KaonThreeMesonCurrent.cc
diff --git a/Decay/WeakCurrents/ThreeMesonDefaultCurrent.cc b/Decay/WeakCurrents/ThreeMesonDefaultCurrent.cc
--- a/Decay/WeakCurrents/ThreeMesonDefaultCurrent.cc
+++ b/Decay/WeakCurrents/ThreeMesonDefaultCurrent.cc
@@ -1,1123 +1,1118 @@
// -*- C++ -*-
//
// ThreeMesonDefaultCurrent.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 ThreeMesonDefaultCurrent class.
//
#include "ThreeMesonDefaultCurrent.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig/PDT/ThreeBodyAllOnCalculator.h"
#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
using namespace ThePEG;
-namespace {
- inline Energy timesGeV (double x) { return x * GeV; }
- inline Energy2 timesGeV2(double x) { return x * GeV2; }
-}
-
DescribeClass<ThreeMesonDefaultCurrent,ThreeMesonCurrentBase>
describeHerwigThreeMesonDefaultCurrent("Herwig::ThreeMesonDefaultCurrent",
"HwWeakCurrents.so");
HERWIG_INTERPOLATOR_CLASSDESC(ThreeMesonDefaultCurrent,Energy,Energy2)
ThreeMesonDefaultCurrent::ThreeMesonDefaultCurrent() {
// the pion decay constant
_fpi=130.7*MeV/sqrt(2.);
_mpi=ZERO;_mK=ZERO;
// set the initial weights for the resonances
// the rho weights
_rhoF123wgts.push_back(1.0);_rhoF123wgts.push_back(-0.145);
_rhoF123wgts.push_back(0.);
_rhoF5wgts.push_back(-26.);_rhoF5wgts.push_back(6.5);
_rhoF5wgts.push_back(1.);
// the Kstar weights
_kstarF123wgts.push_back(1.);
_kstarF5wgts.push_back(1.);
// relative rho/Kstar weights
_rhoKstarwgt=-0.2;
// local values of the a_1 parameters
_a1parameters=true;_a1mass=1.251*GeV;_a1width=0.599*GeV;
_a1opt=true;
// local values of the K_1 parameters
_k1parameters=true;_k1mass=1.402*GeV,_k1width=0.174*GeV;
// local values of the rho parameters
_rhoparameters=true;
_rhoF123masses.push_back(0.773*GeV);_rhoF123masses.push_back(1.370*GeV);
_rhoF123masses.push_back(1.750*GeV);
_rhoF123widths.push_back(0.145*GeV);_rhoF123widths.push_back(0.510*GeV);
_rhoF123widths.push_back(0.120*GeV);
_rhoF5masses.push_back(0.773*GeV);_rhoF5masses.push_back(1.500*GeV);
_rhoF5masses.push_back(1.750*GeV);
_rhoF5widths.push_back(0.145*GeV);_rhoF5widths.push_back(0.220*GeV);
_rhoF5widths.push_back(0.120*GeV);
// local values for the Kstar parameters
_kstarparameters=true;
_kstarF123masses.push_back(0.8921*GeV);
_kstarF123widths.push_back(0.0513*GeV);
_kstarF5masses.push_back(0.8921*GeV);
_kstarF5widths.push_back(0.0513*GeV);
// initialization of the a_1 running width
_initializea1=false;
double a1q2in[200]={0,15788.6,31577.3,47365.9,63154.6,78943.2,94731.9,110521,
126309,142098,157886,173675,189464,205252,221041,236830,
252618,268407,284196,299984,315773,331562,347350,363139,
378927,394716,410505,426293,442082,457871,473659,489448,
505237,521025,536814,552603,568391,584180,599969,615757,
631546,647334,663123,678912,694700,710489,726278,742066,
757855,773644,789432,805221,821010,836798,852587,868375,
884164,899953,915741,931530,947319,963107,978896,994685,
1.01047e+06,1.02626e+06,1.04205e+06,1.05784e+06,1.07363e+06,
1.08942e+06,1.10521e+06,1.12099e+06,1.13678e+06,1.15257e+06,
1.16836e+06,1.18415e+06,1.19994e+06,1.21573e+06,1.23151e+06,
1.2473e+06,1.26309e+06,1.27888e+06,1.29467e+06,1.31046e+06,
1.32625e+06,1.34203e+06,1.35782e+06,1.37361e+06,1.3894e+06,
1.40519e+06,1.42098e+06,1.43677e+06,1.45256e+06,1.46834e+06
,1.48413e+06,1.49992e+06,1.51571e+06,1.5315e+06,1.54729e+06,
1.56308e+06,1.57886e+06,1.59465e+06,1.61044e+06,1.62623e+06,
1.64202e+06,1.65781e+06,1.6736e+06,1.68939e+06,1.70517e+06,
1.72096e+06,1.73675e+06,1.75254e+06,1.76833e+06,1.78412e+06,
1.79991e+06,1.81569e+06,1.83148e+06,1.84727e+06,1.86306e+06,
1.87885e+06,1.89464e+06,1.91043e+06,1.92621e+06,1.942e+06,
1.95779e+06,1.97358e+06,1.98937e+06,2.00516e+06,2.02095e+06,
2.03674e+06,2.05252e+06,2.06831e+06,2.0841e+06,2.09989e+06,
2.11568e+06,2.13147e+06,2.14726e+06,2.16304e+06,2.17883e+06,
2.19462e+06,2.21041e+06,2.2262e+06,2.24199e+06,2.25778e+06,
2.27356e+06,2.28935e+06,2.30514e+06,2.32093e+06,2.33672e+06,
2.35251e+06,2.3683e+06,2.38409e+06,2.39987e+06,2.41566e+06,
2.43145e+06,2.44724e+06,2.46303e+06,2.47882e+06,2.49461e+06,
2.51039e+06,2.52618e+06,2.54197e+06,2.55776e+06,2.57355e+06,
2.58934e+06,2.60513e+06,2.62092e+06,2.6367e+06,2.65249e+06,
2.66828e+06,2.68407e+06,2.69986e+06,2.71565e+06,2.73144e+06,
2.74722e+06,2.76301e+06,2.7788e+06,2.79459e+06,2.81038e+06,
2.82617e+06,2.84196e+06,2.85774e+06,2.87353e+06,2.88932e+06,
2.90511e+06,2.9209e+06,2.93669e+06,2.95248e+06,2.96827e+06,
2.98405e+06,2.99984e+06,3.01563e+06,3.03142e+06,3.04721e+06,
3.063e+06,3.07879e+06,3.09457e+06,3.11036e+06,3.12615e+06,
3.14194e+06};
double a1widthin[200]={0,0,0,0,0,0,0,0,0,0,0,0,0.00153933,0.0136382,0.0457614,
0.105567,0.199612,0.333825,0.513831,0.745192,1.0336,1.38501,
1.80581,2.30295,2.88403,3.5575,4.33278,5.22045,6.23243,
7.38223,8.68521,10.1589,11.8234,13.7018,15.8206,18.2107,
20.9078,23.9533,27.3954,31.2905,35.7038,40.7106,46.3984,
52.8654,60.2207,68.581,78.0637,88.7754,100.794,114.145,
128.783,144.574,161.299,178.683,196.426,214.248,231.908,
249.221,266.059,282.336,298.006,313.048,327.46,341.254,
354.448,367.066,379.133,390.677,401.726,412.304,422.439,
432.155,441.474,450.419,459.01,467.267,475.207,482.847,
490.203,497.29,504.121,510.71,517.068,523.207,529.138,
534.869,540.411,545.776,550.961,556.663,560.851,565.566,
570.137,574.569,578.869,583.041,587.091,591.023,594.843,
598.553,602.16,605.664,609.072,612.396,615.626,618.754,
621.796,624.766,627.656,630.47,633.21,635.878,638.5,
641.006,643.471,645.873,648.213,650.493,652.715,654.88,
656.99,659.047,661.052,663.007,664.963,666.771,668.6,
670.351,672.075,673.828,675.397,676.996,678.567,680.083,
681.589,683.023,684.457,685.825,687.18,688.499,689.789,
691.058,692.284,693.501,694.667,695.82,696.947,698.05,
699.129,700.186,701.221,702.234,703.226,704.198,705.158,
706.085,707.001,707.899,708.78,709.644,710.474,711.334,
712.145,712.943,713.727,714.505,715.266,716.015,716.751,
717.474,718.183,718.88,719.645,720.243,720.91,721.565,
722.211,722.851,723.473,724.094,724.697,725.296,725.886,
726.468,727.041,727.608,728.166,728.718,729.262,729.808,
730.337,730.856,731.374,731.883,732.386,732.884,733.373,
733.859,734.339,734.813};
vector<double> tmp1(a1widthin,a1widthin+200);
_a1runwidth.clear();
std::transform(tmp1.begin(), tmp1.end(),
back_inserter(_a1runwidth),
- timesGeV);
+ [](double x){return x*GeV;});
vector<double> tmp2(a1q2in,a1q2in+200);
_a1runq2.clear();
std::transform(tmp2.begin(), tmp2.end(),
back_inserter(_a1runq2),
- timesGeV2);
+ [](double x){return x*GeV2;});
_maxmass=ZERO;
_maxcalc=ZERO;
}
void ThreeMesonDefaultCurrent::doinit() {
ThreeMesonCurrentBase::doinit();
// the particles we will use a lot
tPDPtr a1(getParticleData(ParticleID::a_1minus)),
k1(getParticleData(ParticleID::Kstar_1minus)),pi0(getParticleData(ParticleID::pi0)),
piplus(getParticleData(ParticleID::piplus)),
piminus(getParticleData(ParticleID::piminus));
// masses for the running widths
_mpi=piplus->mass();
_mK=getParticleData(ParticleID::Kminus)->mass();
// the charged rho resonances
tPDPtr rhoc[3]={getParticleData(-213),getParticleData(-100213),
getParticleData(-30213)};
// the charged K* resonances
tPDPtr Kstarc[3]={getParticleData(-323),getParticleData(-100323),
getParticleData(-30323)};
if(!_a1parameters) {
_a1mass=a1->mass();
_a1width=a1->width();
}
// mass and width of the k_1
if(!_k1parameters) {
_k1mass=k1->mass();
_k1width=k1->width();
}
// initialise the a_1 running width calculation
inita1Width(-1);
// rho parameters in the base classs
tcPDPtr temp;
unsigned int ix;
if(_rhoparameters&&_rhoF123masses.size()<3) {
ix = _rhoF123masses.size();
_rhoF123masses.resize(3);_rhoF123widths.resize(3);
for(;ix<3;++ix) {
if(rhoc[ix]) {
_rhoF123masses[ix]=rhoc[ix]->mass();
_rhoF123widths[ix]=rhoc[ix]->width();
}
}
}
else if(!_rhoparameters) {
_rhoF123masses.resize(3);_rhoF123widths.resize(3);
for(ix=0;ix<3;++ix) {
if(rhoc[ix]) {
_rhoF123masses[ix]=rhoc[ix]->mass();
_rhoF123widths[ix]=rhoc[ix]->width();
}
}
}
// K star parameters in the base class
if(_kstarparameters&&_kstarF123masses.size()<3) {
ix = _kstarF123masses.size();
_kstarF123masses.resize(3);_kstarF123widths.resize(3);
for(;ix<3;++ix) {
if(Kstarc[ix]) {
_kstarF123masses[ix]=Kstarc[ix]->mass();
_kstarF123widths[ix]=Kstarc[ix]->width();
}
}
}
else if(!_kstarparameters) {
_kstarF123masses.resize(3);_kstarF123widths.resize(3);
for(ix=0;ix<3;++ix) {
if(Kstarc[ix]) {
_kstarF123masses[ix]=Kstarc[ix]->mass();
_kstarF123widths[ix]=Kstarc[ix]->width();
}
}
}
// rho parameters here
if(_rhoparameters&&_rhoF5masses.size()<3) {
ix = _rhoF5masses.size();
_rhoF5masses.resize(3);_rhoF5widths.resize(3);
for(;ix<3;++ix) {
if(rhoc[ix]) {
_rhoF5masses[ix]=rhoc[ix]->mass();
_rhoF5widths[ix]=rhoc[ix]->width();
}
}
}
else if(!_rhoparameters) {
_rhoF5masses.resize(3);_rhoF5widths.resize(3);
for(ix=0;ix<3;++ix) {
if(rhoc[ix]) {
_rhoF5masses[ix]=rhoc[ix]->mass();
_rhoF5widths[ix]=rhoc[ix]->width();
}
}
}
// Kstar parameters here
if(_kstarparameters&&_kstarF5widths.size()<3) {
ix = _kstarF5masses.size();
_kstarF5masses.resize(3);_kstarF5widths.resize(3);
for(;ix<3;++ix) {
if(Kstarc[ix]) {
_kstarF5masses[ix]=Kstarc[ix]->mass();
_kstarF5widths[ix]=Kstarc[ix]->width();
}
}
}
else if(!_kstarparameters) {
_kstarF5masses.resize(3);_kstarF5widths.resize(3);
for(ix=0;ix<3;++ix) {
if(Kstarc[ix]) {
_kstarF5masses[ix]=Kstarc[ix]->mass();
_kstarF5widths[ix]=Kstarc[ix]->width();
}
}
}
}
void ThreeMesonDefaultCurrent::persistentOutput(PersistentOStream & os) const {
os << _rhoF123wgts << _kstarF123wgts << _rhoF5wgts << _kstarF5wgts
<< _rhoKstarwgt << ounit(_a1runwidth,GeV)<< ounit(_a1runq2,GeV2)
<< _initializea1
<< ounit(_a1mass,GeV)<< ounit(_a1width,GeV)<< ounit(_k1mass,GeV)
<< ounit(_k1width,GeV)<< ounit(_fpi,GeV) << ounit(_mpi,GeV)<< ounit(_mK,GeV)
<<_rhoparameters << ounit(_rhoF123masses,GeV) << ounit(_rhoF5masses,GeV)
<< ounit(_rhoF123widths,GeV)
<< ounit(_rhoF5widths,GeV) << _kstarparameters << ounit(_kstarF123masses,GeV)
<<ounit(_kstarF5masses,GeV)
<< ounit(_kstarF123widths,GeV) << ounit(_kstarF5widths,GeV) << _a1parameters
<< _k1parameters
<< _a1opt << ounit(_maxmass,GeV) << ounit(_maxcalc,GeV) << _a1runinter;
}
void ThreeMesonDefaultCurrent::persistentInput(PersistentIStream & is, int) {
is >> _rhoF123wgts >> _kstarF123wgts >> _rhoF5wgts >> _kstarF5wgts
>> _rhoKstarwgt >> iunit(_a1runwidth,GeV) >> iunit(_a1runq2,GeV2)
>> _initializea1
>> iunit(_a1mass,GeV) >> iunit(_a1width,GeV) >> iunit(_k1mass,GeV)
>> iunit(_k1width,GeV) >> iunit(_fpi,GeV) >> iunit(_mpi,GeV) >> iunit(_mK,GeV)
>>_rhoparameters >> iunit(_rhoF123masses,GeV) >> iunit(_rhoF5masses,GeV)
>> iunit(_rhoF123widths,GeV)
>> iunit(_rhoF5widths,GeV) >> _kstarparameters >> iunit(_kstarF123masses,GeV)
>>iunit(_kstarF5masses,GeV)
>> iunit(_kstarF123widths,GeV) >> iunit(_kstarF5widths,GeV) >> _a1parameters
>> _k1parameters
>> _a1opt >> iunit(_maxmass,GeV) >> iunit(_maxcalc,GeV) >> _a1runinter;
}
void ThreeMesonDefaultCurrent::Init() {
static ClassDocumentation<ThreeMesonDefaultCurrent> documentation
("The ThreeMesonDefaultCurrent class is designed to implement "
"the three meson decays of the tau, ie pi- pi- pi+, pi0 pi0 pi-, "
"K- pi- K+, K0 pi- Kbar0, K- pi0 K0,pi0 pi0 K-, K- pi- pi+, "
"pi- Kbar0 pi0, pi- pi0 eta. It uses the same currents as those in TAUOLA.",
"The three meson decays of the tau, ie pi- pi- pi+, pi0 pi0 pi-, "
"K- pi- K+, K0 pi- Kbar0, K- pi0 K0,pi0 pi0 K-, K- pi- pi+, "
"and pi- Kbar0 pi0, pi- pi0 eta "
"use the same currents as \\cite{Jadach:1993hs,Kuhn:1990ad,Decker:1992kj}.",
"%\\cite{Jadach:1993hs}\n"
"\\bibitem{Jadach:1993hs}\n"
" S.~Jadach, Z.~Was, R.~Decker and J.~H.~Kuhn,\n"
" %``The Tau Decay Library Tauola: Version 2.4,''\n"
" Comput.\\ Phys.\\ Commun.\\ {\\bf 76}, 361 (1993).\n"
" %%CITATION = CPHCB,76,361;%%\n"
"%\\cite{Kuhn:1990ad}\n"
"\\bibitem{Kuhn:1990ad}\n"
" J.~H.~Kuhn and A.~Santamaria,\n"
" %``Tau decays to pions,''\n"
" Z.\\ Phys.\\ C {\\bf 48}, 445 (1990).\n"
" %%CITATION = ZEPYA,C48,445;%%\n"
"%\\cite{Decker:1992kj}\n"
"\\bibitem{Decker:1992kj}\n"
" R.~Decker, E.~Mirkes, R.~Sauer and Z.~Was,\n"
" %``Tau decays into three pseudoscalar mesons,''\n"
" Z.\\ Phys.\\ C {\\bf 58}, 445 (1993).\n"
" %%CITATION = ZEPYA,C58,445;%%\n"
);
static ParVector<ThreeMesonDefaultCurrent,double> interfaceF123RhoWgt
("F123RhoWeight",
"The weights of the different rho resonances in the F1,2,3 form factor",
&ThreeMesonDefaultCurrent::_rhoF123wgts,
0, 0, 0, -1000, 1000, false, false, true);
static ParVector<ThreeMesonDefaultCurrent,double> interfaceF123KstarWgt
("F123KstarWeight",
"The weights of the different Kstar resonances in the F1,2,3 form factor",
&ThreeMesonDefaultCurrent::_kstarF123wgts,
0, 0, 0, -1000, 1000, false, false, true);
static ParVector<ThreeMesonDefaultCurrent,double> interfaceF5RhoWgt
("F5RhoWeight",
"The weights of the different rho resonances in the F1,2,3 form factor",
&ThreeMesonDefaultCurrent::_rhoF5wgts,
0, 0, 0, -1000, 1000, false, false, true);
static ParVector<ThreeMesonDefaultCurrent,double> interfaceF5KstarWgt
("F5KstarWeight",
"The weights of the different Kstar resonances in the F1,2,3 form factor",
&ThreeMesonDefaultCurrent::_kstarF5wgts,
0, 0, 0, -1000, 1000, false, false, true);
static Parameter<ThreeMesonDefaultCurrent,double> interfaceRhoKstarWgt
("RhoKstarWgt",
"The relative weights of the rho and K* in the F5 form factor",
&ThreeMesonDefaultCurrent::_rhoKstarwgt, -0.2, -10., 10.,
false, false, false);
static Switch<ThreeMesonDefaultCurrent,bool> interfaceInitializea1
("Initializea1",
"Initialise the calculation of the a_1 running width",
&ThreeMesonDefaultCurrent::_initializea1, false, false, false);
static SwitchOption interfaceInitializea1Initialization
(interfaceInitializea1,
"Yes",
"Initialize the calculation",
true);
static SwitchOption interfaceInitializea1NoInitialization
(interfaceInitializea1,
"No",
"Use the default values",
false);
static Switch<ThreeMesonDefaultCurrent,bool> interfaceRhoParameters
("RhoParameters",
"Use local values of the rho meson masses and widths",
&ThreeMesonDefaultCurrent::_rhoparameters, true, false, false);
static SwitchOption interfaceRhoParameterstrue
(interfaceRhoParameters,
"Local",
"Use local values of the parameters",
true);
static SwitchOption interfaceRhoParametersParticleData
(interfaceRhoParameters,
"ParticleData",
"Use the masses and wdiths from the particle data objects",
false);
static Switch<ThreeMesonDefaultCurrent,bool> interfaceKstarParameters
("KstarParameters",
"Use local values of the rho meson masses and widths",
&ThreeMesonDefaultCurrent::_kstarparameters, true, false, false);
static SwitchOption interfaceKstarParameterstrue
(interfaceKstarParameters,
"Local",
"Use local values of the parameters",
true);
static SwitchOption interfaceKstarParametersParticleData
(interfaceKstarParameters,
"ParticleData",
"Use the masses and wdiths from the particle data objects",
false);
static Switch<ThreeMesonDefaultCurrent,bool> interfacea1Parameters
("a1Parameters",
"Use local values of the rho meson masses and widths",
&ThreeMesonDefaultCurrent::_a1parameters, true, false, false);
static SwitchOption interfacea1Parameterstrue
(interfacea1Parameters,
"Local",
"Use local values of the parameters",
true);
static SwitchOption interfacea1ParametersParticleData
(interfacea1Parameters,
"ParticleData",
"Use the masses and wdiths from the particle data objects",
false);
static Switch<ThreeMesonDefaultCurrent,bool> interfaceK1Parameters
("K1Parameters",
"Use local values of the rho meson masses and widths",
&ThreeMesonDefaultCurrent::_k1parameters, true, false, false);
static SwitchOption interfaceK1Parameterstrue
(interfaceK1Parameters,
"Local",
"Use local values of the parameters",
true);
static SwitchOption interfaceK1ParametersParticleData
(interfaceK1Parameters,
"ParticleData",
"Use the masses and wdiths from the particle data objects",
false);
static Switch<ThreeMesonDefaultCurrent,bool> interfacea1WidthOption
("a1WidthOption",
"Option for the treatment of the a1 width",
&ThreeMesonDefaultCurrent::_a1opt, true, false, false);
static SwitchOption interfacea1WidthOptionLocal
(interfacea1WidthOption,
"Local",
"Use a calculation of the running width based on the parameters as"
" interpolation table.",
true);
static SwitchOption interfacea1WidthOptionParam
(interfacea1WidthOption,
"Kuhn",
"Use the parameterization of Kuhn and Santamaria for default parameters."
" This should only be used for testing vs TAUOLA",
false);
static ParVector<ThreeMesonDefaultCurrent,Energy> interfacea1RunningWidth
("a1RunningWidth",
"The values of the a_1 width for interpolation to giving the running width.",
&ThreeMesonDefaultCurrent::_a1runwidth, GeV, -1, 1.0*GeV, ZERO, 10.0*GeV,
false, false, true);
static ParVector<ThreeMesonDefaultCurrent,Energy2> interfacea1RunningQ2
("a1RunningQ2",
"The values of the q^2 for interpolation to giving the running width.",
&ThreeMesonDefaultCurrent::_a1runq2, GeV2, -1, 1.0*GeV2, ZERO, 10.0*GeV2,
false, false, true);
static Parameter<ThreeMesonDefaultCurrent,Energy> interfaceA1Width
("A1Width",
"The a_1 width if using local values.",
&ThreeMesonDefaultCurrent::_a1width, GeV, 0.599*GeV, ZERO, 10.0*GeV,
false, false, false);
static Parameter<ThreeMesonDefaultCurrent,Energy> interfaceA1Mass
("A1Mass",
"The a_1 mass if using local values.",
&ThreeMesonDefaultCurrent::_a1mass, GeV, 1.251*GeV, ZERO, 10.0*GeV,
false, false, false);
static Parameter<ThreeMesonDefaultCurrent,Energy> interfaceK1Width
("K1Width",
"The K_1 width if using local values.",
&ThreeMesonDefaultCurrent::_k1width, GeV, 0.174*GeV, ZERO, 10.0*GeV,
false, false, false);
static Parameter<ThreeMesonDefaultCurrent,Energy> interfaceK1Mass
("K1Mass",
"The K_1 mass if using local values.",
&ThreeMesonDefaultCurrent::_k1mass, GeV, 1.402*GeV, ZERO, 10.0*GeV,
false, false, false);
static ParVector<ThreeMesonDefaultCurrent,Energy> interfacerhoF123masses
("rhoF123masses",
"The masses for the rho resonances if used local values",
&ThreeMesonDefaultCurrent::_rhoF123masses, GeV, -1, 1.0*GeV, ZERO, 10.0*GeV,
false, false, true);
static ParVector<ThreeMesonDefaultCurrent,Energy> interfacerhoF123widths
("rhoF123widths",
"The widths for the rho resonances if used local values",
&ThreeMesonDefaultCurrent::_rhoF123widths, GeV, -1, 1.0*GeV, ZERO, 10.0*GeV,
false, false, true);
static ParVector<ThreeMesonDefaultCurrent,Energy> interfacerhoF5masses
("rhoF5masses",
"The masses for the rho resonances if used local values",
&ThreeMesonDefaultCurrent::_rhoF5masses, GeV, -1, 1.0*GeV, ZERO, 10.0*GeV,
false, false, true);
static ParVector<ThreeMesonDefaultCurrent,Energy> interfacerhoF5widths
("rhoF5widths",
"The widths for the rho resonances if used local values",
&ThreeMesonDefaultCurrent::_rhoF5widths, GeV, -1, 1.0*GeV, ZERO, 10.0*GeV,
false, false, true);
static ParVector<ThreeMesonDefaultCurrent,Energy> interfaceKstarF123masses
("KstarF123masses",
"The masses for the Kstar resonances if used local values",
&ThreeMesonDefaultCurrent::_kstarF123masses, GeV, -1, 1.0*GeV, ZERO, 10.0*GeV,
false, false, true);
static ParVector<ThreeMesonDefaultCurrent,Energy> interfaceKstarF123widths
("KstarF123widths",
"The widths for the Kstar resonances if used local values",
&ThreeMesonDefaultCurrent::_kstarF123widths, GeV, -1, 1.0*GeV, ZERO, 10.0*GeV,
false, false, true);
static ParVector<ThreeMesonDefaultCurrent,Energy> interfaceKstarF5masses
("KstarF5masses",
"The masses for the Kstar resonances if used local values",
&ThreeMesonDefaultCurrent::_kstarF5masses, GeV, -1, 1.0*GeV, ZERO, 10.0*GeV,
false, false, true);
static ParVector<ThreeMesonDefaultCurrent,Energy> interfaceKstarF5widths
("KstarF5widths",
"The widths for the Kstar resonances if used local values",
&ThreeMesonDefaultCurrent::_kstarF5widths, GeV, -1, 1.0*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<ThreeMesonDefaultCurrent,Energy> interfaceFPi
("FPi",
"The pion decay constant",
&ThreeMesonDefaultCurrent::_fpi, MeV, 92.4*MeV, ZERO, 200.0*MeV,
false, false, true);
}
// modes handled by this class
bool ThreeMesonDefaultCurrent::acceptMode(int imode) const {
return imode>=0&&imode<=8;
}
// calculate the form-factors
ThreeMesonDefaultCurrent::FormFactors
ThreeMesonDefaultCurrent::calculateFormFactors(const int ichan, const int imode,
Energy2 q2, Energy2 s1,
Energy2 s2, Energy2 s3) const {
useMe();
Complex F1, F2, F3, F4, F5;
F1 = F2 = F3 = F4 = F5 = 0.0;
// calculate the pi- pi- pi+ factor
if(imode==0) {
Complex a1fact(a1BreitWigner(q2)*2./3.);
if(ichan<0) {
F1= a1fact*BrhoF123(s1,-1);
F2 =-a1fact*BrhoF123(s2,-1);
}
else if(ichan%2==0) F1 = a1fact*BrhoF123(s1, ichan/2);
else if(ichan%2==1) F2 =-a1fact*BrhoF123(s2,(ichan-1)/2);
}
// calculate the pi0 pi0 pi- factor
else if(imode==1) {
Complex a1fact(a1BreitWigner(q2)*2./3.);
if(ichan<0) {
F1 = a1fact*BrhoF123(s1,-1);
F2 =-a1fact*BrhoF123(s2,-1);
}
else if(ichan%2==0) F1 = a1fact*BrhoF123(s1, ichan/2);
else if(ichan%2==1) F2 =-a1fact*BrhoF123(s2,(ichan-1)/2);
}
// calculate the K- pi - K+ factor
else if(imode==2) {
Complex a1fact(a1BreitWigner(q2)*sqrt(2.)/3.);
if(ichan<0) {
F1 =-a1fact*BKstarF123(s1,-1);
F2 = a1fact*BrhoF123(s2,-1);
F5 = BrhoF5(q2,-1)*FKrho(s1,s2,-1)*sqrt(2.);
}
else if(ichan%8==0) F1 =-a1fact*BKstarF123(s1,ichan/8);
else if(ichan%8==1) F2 = a1fact*BrhoF123(s2,(ichan-1)/8);
else if(ichan%8>=2) F5 = BrhoF5(q2,ichan/8)*FKrho(s1,s2,(ichan-2)%8)*sqrt(2.);
}
// calculate the K0 pi- K0bar
else if(imode==3) {
Complex a1fact(a1BreitWigner(q2)*sqrt(2.)/3.);
if(ichan<0) {
F1 =-a1fact*BKstarF123(s1,-1);
F2 = a1fact*BrhoF123(s2,-1);
F5 =-BrhoF5(q2,-1)*FKrho(s1,s2,-1)*sqrt(2.);
}
else if(ichan%8==0) F1 = -a1fact*BKstarF123(s1,ichan/8);
else if(ichan%8==1) F2 = a1fact*BrhoF123(s2,(ichan-1)/8);
else if(ichan%8>=2) F5 = -BrhoF5(q2,ichan/8)*FKrho(s1,s2,(ichan-2)%8)*sqrt(2.);
}
// calculate the K- pi0 k0
else if(imode==4) {
Complex a1fact(a1BreitWigner(q2));
if(ichan<0){F2 =-a1fact*BrhoF123(s2,-1);}
else{F2 =-a1fact*BrhoF123(s2,ichan);}
}
// calculate the pi0 pi0 K-
else if(imode==5) {
Complex K1fact(K1BreitWigner(q2)/6.);
if(ichan<0) {
F1 = K1fact*BKstarF123(s1,-1);
F2 =-K1fact*BKstarF123(s2,-1);
}
else if(ichan%2==0) F1 = K1fact*BKstarF123(s1,ichan/2);
else F2 =-K1fact*BKstarF123(s2,(ichan-1)/2);
}
// calculate the K- pi- pi+
else if(imode==6) {
Complex K1fact(K1BreitWigner(q2)*sqrt(2.)/3.);
if(ichan<0) {
F1 =-K1fact*BrhoF123(s1,-1);
F2 = K1fact*BKstarF123(s2,-1);
F5 =-BKstarF123(q2,-1)*FKrho(s2,s1,-1)*sqrt(2.);
}
else if(ichan%8==0) F1 =-K1fact*BrhoF123(s1,ichan/8);
else if(ichan%8==1) F2 = K1fact*BKstarF123(s2,(ichan-1)/8);
else F5 = -BKstarF123(q2,ichan/8)*FKrho(s2,s1,(ichan-2)%8)*sqrt(2.);
}
// calculate the pi- K0bar pi0
else if(imode==7) {
Complex K1fact(K1BreitWigner(q2));
if(ichan<0) {
F2 =-K1fact*BrhoF123(s2,-1);
F5 =-2.*BKstarF123(q2,-1)*FKrho(s1,s2,-1);
}
else if(ichan%7==0) F2 =-K1fact*BrhoF123(s2,ichan/7);
else F5 =-2.*BKstarF123(q2,ichan/7)*FKrho(s1,s2,(ichan-1)%7);
}
// calculate the pi- pi0 eta
else if(imode==8) {
if(ichan<0) F5 = BrhoF5(q2, -1)*BrhoF123(s3, -1)*sqrt(2./3.);
else F5 = BrhoF5(q2,ichan/3)*BrhoF123(s3,ichan%3)*sqrt(2./3.);
}
// multiply by the prefactors
using Constants::twopi;
return FormFactors(F1/_fpi,
F2/_fpi,
F3/_fpi,
F4/_fpi,
-F5/sqr(twopi)/pow<3,1>(_fpi)
);
}
// complete the construction of the decay mode for integration
bool ThreeMesonDefaultCurrent::createMode(int icharge, unsigned int imode,
DecayPhaseSpaceModePtr mode,
unsigned int iloc,unsigned int ires,
DecayPhaseSpaceChannelPtr phase,Energy upp) {
int iq(0),ia(0);
if(!acceptMode(imode)) return false;
tPDVector extpart(particles(1,imode,iq,ia));
Energy min(ZERO);
for(unsigned int ix=0;ix<extpart.size();++ix) min+=extpart[ix]->massMin();
if(min>upp) return false;
// the particles we will use a lot
tPDPtr a1,k1;
if(icharge==-3) {
a1=getParticleData(ParticleID::a_1minus);
k1=getParticleData(ParticleID::Kstar_1minus);
}
else if(icharge==3) {
a1=getParticleData(ParticleID::a_1plus);
k1=getParticleData(ParticleID::Kstar_1plus);
}
else {
return false;
}
_maxmass=max(_maxmass,upp);
// the rho0 resonances
tPDPtr rho0[3]={getParticleData(113),getParticleData(100113),getParticleData(30113)};
tPDPtr rhoc[3],Kstar0[3],Kstarc[3];
if(icharge==-3) {
// the charged rho resonances
rhoc[0] = getParticleData(-213);
rhoc[1] = getParticleData(-100213);
rhoc[2] = getParticleData(-30213);
// the K*0 resonances
Kstar0[0] = getParticleData(313);
Kstar0[1] = getParticleData(100313);
Kstar0[2] = getParticleData(30313);
// the charged K* resonances
Kstarc[0] = getParticleData(-323);
Kstarc[1] = getParticleData(-100323);
Kstarc[2] = getParticleData(-30323);
}
else {
// the charged rho resonances
rhoc[0] = getParticleData(213);
rhoc[1] = getParticleData(100213);
rhoc[2] = getParticleData(30213);
// the K*0 resonances
Kstar0[0] = getParticleData(-313);
Kstar0[1] = getParticleData(-100313);
Kstar0[2] = getParticleData(-30313);
// the charged K* resonances
Kstarc[0] = getParticleData(323);
Kstarc[1] = getParticleData(100323);
Kstarc[2] = getParticleData(30323);
}
DecayPhaseSpaceChannelPtr newchannel;
if(imode==0) {
// channels for pi- pi- pi+
for(unsigned int ix=0;ix<3;++ix) {
if(!rho0[ix]) continue;
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1 ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(rho0[ix],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1 ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(rho0[ix],0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
}
}
else if(imode==1) {
// channels for pi0 pi0 pi-
for(unsigned int ix=0;ix<3;++ix) {
if(!rhoc[ix]) continue;
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1 ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(rhoc[ix],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1 ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(rhoc[ix],0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
}
}
else if(imode==2) {
// channels for K- pi- K+
for(unsigned int ix=0;ix<3;++ix) {
if(Kstar0[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1 ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(Kstar0[ix],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
}
if(rho0[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1 ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(rho0[ix],0,0.0,iloc,iloc+2);
mode->addChannel(newchannel);
}
for(unsigned int iy=0;iy<3;++iy) {
if(!rhoc[ix]) continue;
if(Kstar0[iy]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhoc[ix] ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(Kstar0[iy],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
}
if(rho0[iy]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhoc[ix],0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(rho0[iy],0,0.0,iloc,iloc+2);
mode->addChannel(newchannel);
}
}
}
}
else if(imode==3) {
// channels for K0 pi- K0bar
for(unsigned int ix=0;ix<3;++ix) {
if(Kstarc[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1 ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(Kstarc[ix],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
}
if(rho0[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1 ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(rho0[ix],0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
}
for(unsigned int iy=0;iy<3;++iy) {
if(!rhoc[ix]) continue;
if(Kstarc[iy]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhoc[ix] ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(Kstarc[iy],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
}
if(rho0[iy]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhoc[ix],0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(rho0[iy],0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
}
}
}
}
else if(imode==4) {
// channels for K- pi0 K0
for(unsigned int ix=0;ix<3;++ix) {
if(!rhoc[ix]) continue;
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1 ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(rhoc[ix],0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
}
}
else if(imode==5) {
// channels for pi0 pi0 K-
for(unsigned int ix=0;ix<3;++ix) {
if(!Kstarc[ix]) continue;
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(k1 ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(Kstarc[ix],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(k1 ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(Kstarc[ix],0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
}
}
else if(imode==6) {
// channels for K- pi- pi+
for(unsigned int ix=0;ix<3;++ix) {
if(rho0[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(k1 ,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(rho0[ix],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
}
if(Kstar0[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(k1 ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(Kstar0[ix],0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
}
for(unsigned int iy=0;iy<3;++iy) {
if(!Kstarc[ix]) continue;
if(rho0[iy]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(Kstarc[ix],0,0.0,-ires-1,iloc);
newchannel->addIntermediate(rho0[iy] ,0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
}
if(Kstar0[iy]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(Kstarc[ix],0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(Kstar0[iy],0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
}
}
}
}
else if(imode==7) {
// channels for pi- kbar0 pi0
for(unsigned int ix=0;ix<3;++ix) {
if(rhoc[ix]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(k1 ,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(rhoc[ix],0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
}
for(unsigned int iy=0;iy<3;++iy) {
if(!Kstarc[ix]) continue;
if(Kstar0[iy]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(Kstarc[ix],0,0.0,-ires-1,iloc);
newchannel->addIntermediate(Kstar0[iy],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
}
if(rhoc[iy]) {
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(Kstarc[ix],0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(rhoc[iy] ,0,0.0, iloc,iloc+2);
mode->addChannel(newchannel);
}
}
}
}
else if(imode==8) {
// channels for pi- pi0 eta
for(unsigned int ix=0;ix<3;++ix) {
if(!rhoc[ix]) continue;
for(unsigned int iy=0;iy<3;++iy) {
if(!rho0[iy]) continue;
newchannel= new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(rhoc[ix],0,0.0,-ires-1,iloc);
newchannel->addIntermediate(rho0[iy],0,0.0, iloc+1,iloc+2);
mode->addChannel(newchannel);
}
}
}
if(_rhoparameters) {
if(imode!=8) {
for(unsigned int ix=0;ix<_rhoF123masses.size();++ix) {
if(rhoc[ix]) mode->resetIntermediate(rhoc[ix],_rhoF123masses[ix],
_rhoF123widths[ix]);
if(rho0[ix]) mode->resetIntermediate(rho0[ix],_rhoF123masses[ix],
_rhoF123widths[ix]);
}
}
else {
for(unsigned int ix=0;ix<_rhoF5masses.size();++ix) {
if(rhoc[ix]) mode->resetIntermediate(rhoc[ix],_rhoF5masses[ix],
_rhoF5widths[ix]);
if(rho0[ix]) mode->resetIntermediate(rho0[ix],_rhoF5masses[ix],
_rhoF5widths[ix]);
}
}
}
// K star parameters in the base class
if(_kstarparameters) {
for(unsigned int ix=0;ix<_kstarF123masses.size();++ix) {
if(Kstarc[ix]) mode->resetIntermediate(Kstarc[ix],_kstarF123masses[ix],
_kstarF123widths[ix]);
if(Kstar0[ix]) mode->resetIntermediate(Kstar0[ix],_kstarF123masses[ix],
_kstarF123widths[ix]);
}
}
return true;
}
// initialisation of the a_1 width
// (iopt=-1 initialises, iopt=0 starts the interpolation)
void ThreeMesonDefaultCurrent::inita1Width(int iopt) {
if(iopt==-1) {
_maxcalc=_maxmass;
if(!_initializea1||_maxmass==ZERO) return;
// parameters for the table of values
Energy2 step(sqr(_maxcalc)/199.);
// integrator to perform the integral
vector<double> inweights;inweights.push_back(0.5);inweights.push_back(0.5);
vector<int> intype;intype.push_back(2);intype.push_back(3);
Energy mrho(getParticleData(ParticleID::rhoplus)->mass()),
wrho(getParticleData(ParticleID::rhoplus)->width());
vector<Energy> inmass(2,mrho),inwidth(2,wrho);
vector<double> inpow(2,0.0);
ThreeBodyAllOnCalculator<ThreeMesonDefaultCurrent>
widthgen(inweights,intype,inmass,inwidth,inpow,*this,0,_mpi,_mpi,_mpi);
// normalisation constant to give physical width if on shell
double a1const(_a1width/(widthgen.partialWidth(sqr(_a1mass))));
// loop to give the values
_a1runq2.clear(); _a1runwidth.clear();
for(Energy2 moff2(ZERO); moff2<=sqr(_maxcalc); moff2+=step) {
_a1runwidth.push_back(widthgen.partialWidth(moff2)*a1const);
_a1runq2.push_back(moff2);
}
}
// set up the interpolator
else if(iopt==0) {
_a1runinter = make_InterpolatorPtr(_a1runwidth,_a1runq2,3);
}
}
void ThreeMesonDefaultCurrent::dataBaseOutput(ofstream & output,bool header,
bool create) const {
if(header) output << "update decayers set parameters=\"";
if(create) output << "create Herwig::ThreeMesonDefaultCurrent "
<< name() << " HwWeakCurrents.so\n";
for(unsigned int ix=0;ix<_rhoF123wgts.size();++ix) {
if(ix<3) output << "newdef ";
else output << "insert ";
output << name() << ":F123RhoWeight " << ix << " " << _rhoF123wgts[ix] << "\n";
}
for(unsigned int ix=0;ix<_kstarF123wgts.size();++ix) {
if(ix<1) output << "newdef ";
else output << "insert ";
output << name() << ":F123KstarWeight " << ix << " "
<< _kstarF123wgts[ix] << "\n";
}
for(unsigned int ix=0;ix<_rhoF5wgts.size();++ix) {
if(ix<3) output << "newdef ";
else output << "insert ";
output << name() << ":F5RhoWeight " << ix << " " << _rhoF5wgts[ix] << "\n";
}
for(unsigned int ix=0;ix<_kstarF5wgts.size();++ix) {
if(ix<1) output << "newdef ";
else output << "insert ";
output << name() << ":F5KstarWeight " << ix << " " << _kstarF5wgts[ix] << "\n";
}
output << "newdef " << name() << ":RhoKstarWgt " << _rhoKstarwgt << "\n";
output << "newdef " << name() << ":Initializea1 " << _initializea1 << "\n";
output << "newdef " << name() << ":RhoParameters " << _rhoparameters << "\n";
output << "newdef " << name() << ":KstarParameters " << _kstarparameters << "\n";
output << "newdef " << name() << ":a1Parameters " << _a1parameters << "\n";
output << "newdef " << name() << ":K1Parameters " << _k1parameters << "\n";
output << "newdef " << name() << ":a1WidthOption " << _a1opt << "\n";
for(unsigned int ix=0;ix<_a1runwidth.size();++ix) {
output << "newdef " << name() << ":a1RunningWidth " << ix
<< " " << _a1runwidth[ix]/GeV << "\n";
}
for(unsigned int ix=0;ix<_a1runq2.size();++ix) {
output << "newdef " << name() << ":a1RunningQ2 " << ix
<< " " << _a1runq2[ix]/GeV2 << "\n";
}
output << "newdef " << name() << ":A1Width " << _a1width/GeV << "\n";
output << "newdef " << name() << ":A1Mass " << _a1mass/GeV << "\n";
output << "newdef " << name() << ":K1Width " << _k1width/GeV << "\n";
output << "newdef " << name() << ":K1Mass " << _k1mass/GeV << "\n";
output << "newdef " << name() << ":FPi " << _fpi/MeV << "\n";
for(unsigned int ix=0;ix<_rhoF123masses.size();++ix) {
if(ix<3) output << "newdef ";
else output << "insert ";
output << name() << ":rhoF123masses " << ix
<< " " << _rhoF123masses[ix]/GeV << "\n";
}
for(unsigned int ix=0;ix<_rhoF123widths.size();++ix) {
if(ix<3) output << "newdef ";
else output << "insert ";
output << name() << ":rhoF123widths " << ix << " "
<< _rhoF123widths[ix]/GeV << "\n";
}
for(unsigned int ix=0;ix<_rhoF5masses.size();++ix) {
if(ix<3) output << "newdef ";
else output << "insert ";
output << name() << ":rhoF5masses " << ix << " "
<< _rhoF5masses[ix]/GeV << "\n";
}
for(unsigned int ix=0;ix<_rhoF5widths.size();++ix) {
if(ix<3) output << "newdef ";
else output << "insert ";
output << name() << ":rhoF5widths " << ix << " "
<< _rhoF5widths[ix]/GeV << "\n";
}
for(unsigned int ix=0;ix<_kstarF123masses.size();++ix) {
if(ix<1) output << "newdef ";
else output << "insert ";
output << name() << ":KstarF123masses " << ix << " "
<< _kstarF123masses[ix]/GeV << "\n";
}
for(unsigned int ix=0;ix<_kstarF123widths.size();++ix) {
if(ix<1) output << "newdef ";
else output << "insert ";
output << name() << ":KstarF123widths " << ix << " "
<< _kstarF123widths[ix]/GeV << "\n";
}
for(unsigned int ix=0;ix<_kstarF5masses.size();++ix) {
if(ix<1) output << "newdef ";
else output << "insert ";
output << name() << ":KstarF5masses " << ix << " "
<< _kstarF5masses[ix]/GeV << "\n";
}
for(unsigned int ix=0;ix<_kstarF5widths.size();++ix) {
if(ix<1) output << "newdef ";
else output << "insert ";
output << name() << ":KstarF5widths " << ix << " "
<< _kstarF5widths[ix]/GeV << "\n";
}
ThreeMesonCurrentBase::dataBaseOutput(output,false,false);
if(header) output << "\n\" where BINARY ThePEGName=\""
<< fullName() << "\";" << endl;
}
void ThreeMesonDefaultCurrent::doinitrun() {
// set up the running a_1 width
inita1Width(0);
ThreeMesonCurrentBase::doinitrun();
}
void ThreeMesonDefaultCurrent::doupdate() {
ThreeMesonCurrentBase::doupdate();
// update running width if needed
if ( !touched() ) return;
if(_maxmass!=_maxcalc) inita1Width(-1);
}
Complex ThreeMesonDefaultCurrent::rhoKBreitWigner(Energy2 q2,unsigned int itype,
unsigned int ires) const {
Energy q(sqrt(q2)),mass,width,mout[2]={_mpi,_mpi};
// get the mass and width of the requested resonance
if(itype==0) {
mass=_rhoF123masses[ires];
width=_rhoF123widths[ires];
}
else if(itype==1) {
mass=_rhoF5masses[ires];
width=_rhoF5widths[ires];
}
else if(itype==2) {
mass=_kstarF123masses[ires];
width=_kstarF123widths[ires];
}
else if(itype==3) {
mass=_kstarF5masses[ires];
width=_kstarF5widths[ires];
}
else {
return 0.;
}
// calculate the momenta for the running widths
if(itype>1) mout[0]=_mK;
Energy pcm0(Kinematics::pstarTwoBodyDecay(mass,mout[0],mout[1]));
Energy pcm(ZERO);
if(mout[0]+mout[1]<q){pcm=Kinematics::pstarTwoBodyDecay(q,mout[0],mout[1]);}
double ratio = Math::Pow<3>(pcm/pcm0);
Energy gamrun(width*mass*ratio/q);
Complex ii(0.,1.);
complex<Energy2> denom(q2-mass*mass+ii*mass*gamrun), numer(-mass*mass);
return numer/denom;
}
double ThreeMesonDefaultCurrent::
threeBodyMatrixElement(const int , const Energy2 q2,
const Energy2 s3, const Energy2 s2,
const Energy2 s1, const Energy ,
const Energy , const Energy ) const {
Energy2 mpi2(sqr(_mpi));
Complex propb(BrhoF123(s1,-1)),propa(BrhoF123(s2,-1));
// the matrix element
Energy2 output(ZERO);
// first resonance
output += ((s1-4.*mpi2) + 0.25*(s3-s2)*(s3-s2)/q2) * real(propb*conj(propb));
// second resonance
output += ((s2-4.*mpi2) + 0.25*(s3-s1)*(s3-s1)/q2) * real(propa*conj(propa));
// the interference term
output += (0.5*q2-s3-0.5*mpi2+0.25*(s3-s2)*(s3-s1)/q2)*real(propa*conj(propb)+
propb*conj(propa));
return output/sqr(_rhoF123masses[0]);
}
diff --git a/Decay/WeakCurrents/ThreePionCLEOCurrent.cc b/Decay/WeakCurrents/ThreePionCLEOCurrent.cc
--- a/Decay/WeakCurrents/ThreePionCLEOCurrent.cc
+++ b/Decay/WeakCurrents/ThreePionCLEOCurrent.cc
@@ -1,1091 +1,1086 @@
// -*- C++ -*-
//
// ThreePionCLEOCurrent.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 ThreePionCLEOCurrent class.
//
#include "ThreePionCLEOCurrent.h"
#include "ThePEG/Interface/ClassDocumentation.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 "Herwig/PDT/ThreeBodyAllOnCalculator.h"
#include "ThePEG/Utilities/DescribeClass.h"
-namespace {
- inline Energy timesGeV (double x) { return x * GeV; }
- inline Energy2 timesGeV2(double x) { return x * GeV2; }
-}
-
using namespace Herwig;
DescribeClass<ThreePionCLEOCurrent,ThreeMesonCurrentBase>
describeHerwigThreePionCLEOCurrent("Herwig::ThreePionCLEOCurrent",
"HwWeakCurrents.so");
HERWIG_INTERPOLATOR_CLASSDESC(ThreePionCLEOCurrent,Energy,Energy2)
ThreePionCLEOCurrent::ThreePionCLEOCurrent() {
// local particle properties
_localparameters=true;
// rho masses and widths
if(_rhomass.size()==0) {
_rhomass.push_back(0.7743*GeV);_rhowidth.push_back(0.1491*GeV);
_rhomass.push_back(1.370*GeV);_rhowidth.push_back(0.386*GeV);
}
// f_2 mass and width
_f2mass=1.275*GeV;_f2width=0.185*GeV;
// f_0(1370) mass and width
_f0mass=1.186*GeV;_f0width=0.350*GeV;
// sigma mass and width
_sigmamass = 0.860*GeV;_sigmawidth =0.880*GeV;
// a1 mass and width
_a1mass = 1.331*GeV;_a1width=0.814*GeV;
// parameters for the K K* contribution to the a_1 running width
_mKstar = 894*MeV;
_mK=496*MeV;
_gammk=3.32;
// pion decay constant
_fpi = 130.7*MeV/sqrt(2.);
// couplings and phases for the different channels
// p-wave rho and rho prime
using Constants::pi;
if(_rhomagP.size()==0) {
_rhomagP.push_back(1.) ;_rhophaseP.push_back(0.);
_rhomagP.push_back(0.12);_rhophaseP.push_back(0.99*pi);
}
// d-wave rho and rho prime
if(_rhomagD.size()==0) {
_rhomagD.push_back(0.37/GeV2);_rhophaseD.push_back(-0.15*pi);
_rhomagD.push_back(0.87/GeV2);_rhophaseD.push_back( 0.53*pi);
}
// f_2
_f2mag=0.71/GeV2;_f2phase=0.56*pi;_f2coup=ZERO;
// sigma
_sigmamag=2.10;_sigmaphase=0.23*pi;_sigmacoup=0.;
// f_0
_f0mag=0.77;_f0phase=-0.54*pi;_f0coup=0.;
// initialize the a_1 width
_initializea1=false;
_a1opt=true;
double a1q2in[200]={0 ,15788.6,31577.3,47365.9,63154.6,78943.2,
94731.9,110521 ,126309 ,142098 ,157886 ,173675 ,
189464 ,205252 ,221041 ,236830 ,252618 ,268407 ,
284196 ,299984 ,315773 ,331562 ,347350 ,363139 ,
378927 ,394716 ,410505 ,426293 ,442082 ,457871 ,
473659 ,489448 ,505237 ,521025 ,536814 ,552603 ,
568391 ,584180 ,599969 ,615757 ,631546 ,647334 ,
663123 ,678912 ,694700 ,710489 ,726278 ,742066 ,
757855 ,773644 ,789432 ,805221 ,821010 ,836798 ,
852587 ,868375 ,884164 ,899953 ,915741 ,931530 ,
947319 ,963107 ,978896 ,994685 ,
1.01047e+06,1.02626e+06,1.04205e+06,1.05784e+06,
1.07363e+06,1.08942e+06,1.10521e+06,1.12099e+06,
1.13678e+06,1.15257e+06,1.16836e+06,1.18415e+06,
1.19994e+06,1.21573e+06,1.23151e+06,1.24730e+06,
1.26309e+06,1.27888e+06,1.29467e+06,1.31046e+06,
1.32625e+06,1.34203e+06,1.35782e+06,1.37361e+06,
1.38940e+06,1.40519e+06,1.42098e+06,1.43677e+06,
1.45256e+06,1.46834e+06,1.48413e+06,1.49992e+06,
1.51571e+06,1.53150e+06,1.54729e+06,1.56308e+06,
1.57886e+06,1.59465e+06,1.61044e+06,1.62623e+06,
1.64202e+06,1.65781e+06,1.67360e+06,1.68939e+06,
1.70517e+06,1.72096e+06,1.73675e+06,1.75254e+06,
1.76833e+06,1.78412e+06,1.79991e+06,1.81569e+06,
1.83148e+06,1.84727e+06,1.86306e+06,1.87885e+06,
1.89464e+06,1.91043e+06,1.92621e+06,1.94200e+06,
1.95779e+06,1.97358e+06,1.98937e+06,2.00516e+06,
2.02095e+06,2.03674e+06,2.05252e+06,2.06831e+06,
2.08410e+06,2.09989e+06,2.11568e+06,2.13147e+06,
2.14726e+06,2.16304e+06,2.17883e+06,2.19462e+06,
2.21041e+06,2.22620e+06,2.24199e+06,2.25778e+06,
2.27356e+06,2.28935e+06,2.30514e+06,2.32093e+06,
2.33672e+06,2.35251e+06,2.36830e+06,2.38409e+06,
2.39987e+06,2.41566e+06,2.43145e+06,2.44724e+06,
2.46303e+06,2.47882e+06,2.49461e+06,2.51039e+06,
2.52618e+06,2.54197e+06,2.55776e+06,2.57355e+06,
2.58934e+06,2.60513e+06,2.62092e+06,2.63670e+06,
2.65249e+06,2.66828e+06,2.68407e+06,2.69986e+06,
2.71565e+06,2.73144e+06,2.74722e+06,2.76301e+06,
2.77880e+06,2.79459e+06,2.81038e+06,2.82617e+06,
2.84196e+06,2.85774e+06,2.87353e+06,2.88932e+06,
2.90511e+06,2.92090e+06,2.93669e+06,2.95248e+06,
2.96827e+06,2.98405e+06,2.99984e+06,3.01563e+06,
3.03142e+06,3.04721e+06,3.06300e+06,3.07879e+06,
3.09457e+06,3.11036e+06,3.12615e+06,3.14194e+06};
double a1widthin[200]={0,0,0,0,0,0,0,0,
0,0,0,0.00021256,0.0107225,0.0554708,0.150142,0.303848,
0.522655,0.81121,1.1736,1.61381,2.13606,2.74499,3.44583,4.24454,
5.14795,6.16391,7.3014,8.57079,9.98398,11.5547,13.2987,15.2344,
17.3827,19.7683,22.4195,25.3695,28.6568,32.3264,36.4311,41.0322,
46.201,52.0203,58.5847,66.0011,74.3871,83.8666,94.5615,106.578,
119.989,134.807,150.968,168.315,186.615,205.576,224.893,244.28,
263.499,282.364,300.748,318.569,335.781,352.367,368.327,383.677,
398.438,412.638,426.306,439.472,452.167,464.421,476.263,487.719,
498.815,509.576,520.024,530.179,540.063,549.693,559.621,568.26,
577.229,586.005,594.604,603.035,611.314,619.447,627.446,635.321,
643.082,650.736,658.288,665.75,673.127,680.427,687.659,694.82,
701.926,708.977,715.983,722.944,729.862,736.752,743.619,750.452,
757.271,764.076,770.874,777.658,784.444,791.233,798.027,804.838,
811.649,818.485,825.342,832.224,839.139,846.082,853.059,860.079,
867.143,874.248,881.409,919.527,945.28,965.514,983.228,999.471,
1014.69,1029.15,1043.05,1056.49,1069.57,1082.36,1094.88,1107.2,
1120.89,1131.4,1143.33,1155.15,1166.92,1178.61,1190.27,1201.92,
1213.55,1225.18,1236.81,1250.06,1260.16,1271.86,1283.64,1295.46,
1307.36,1319.3,1331.34,1343.45,1355.64,1367.93,1380.31,1392.77,
1405.35,1418.03,1430.83,1443.75,1457.17,1469.94,1483.22,1496.64,
1510.18,1523.86,1537.67,1551.64,1565.72,1579.99,1594.38,1608.92,
1623.63,1642.08,1653.51,1668.69,1684.03,1699.53,1715.21,1731.04,
1747.05,1763.23,1779.59,1796.12,1812.83,1829.72,1846.79,1864.04,
1881.49,1899.11,1916.93,1934.93,1953.13,1971.52,1990.12,2008.89};
if(_a1runwidth.empty()) {
vector<double> tmp1(a1widthin,a1widthin+200);
std::transform(tmp1.begin(), tmp1.end(),
back_inserter(_a1runwidth),
- timesGeV);
+ [](double x){return x*GeV;});
vector<double> tmp2(a1q2in,a1q2in+200);
_a1runq2.clear();
std::transform(tmp2.begin(), tmp2.end(),
back_inserter(_a1runq2),
- timesGeV2);
+ [](double x){return x*GeV2;});
}
// zero parameters which will be calculated later to avoid problems
_pf2cc=ZERO;
_pf200=ZERO;
_pf0cc=ZERO;
_pf000=ZERO;
_psigmacc=ZERO;
_psigma00=ZERO;
_mpi0=ZERO;
_mpic=ZERO;
_fact=ZERO;
_maxmass=ZERO;
_maxcalc=ZERO;
}
void ThreePionCLEOCurrent::doinit() {
ThreeMesonCurrentBase::doinit();
// pointers to the particles we need
tPDPtr a1m = getParticleData(ParticleID::a_1minus);
// the different rho resonances
tPDPtr rhom[3];
rhom[0] = getParticleData(-213);
rhom[1] = getParticleData(-100213);
rhom[2] = getParticleData(-30213);
// the sigma
tPDPtr sigma = getParticleData(9000221);
// the f_2
tPDPtr f2=getParticleData(225);
// the f_0
tPDPtr f0=getParticleData(10221);
if(_localparameters) {
// make sure the rho array has enough masses
if(_rhomass.size()<3) {
for(unsigned int ix=_rhomass.size();ix<3;++ix) {
_rhomass.push_back(rhom[ix]->mass());
_rhowidth.push_back(rhom[ix]->width());
}
}
}
// set the local variables if needed
else {
// masses and widths for the particles
_rhomass.resize(3);_rhowidth.resize(3);
for(unsigned int ix=0;ix<3;++ix)
{_rhomass[ix]=rhom[ix]->mass();_rhowidth[ix]=rhom[ix]->width();}
_f2mass=f2->mass();_f2width=f2->width();
_f0mass=f0->mass();_f0width=f0->width();
_sigmamass=sigma->mass();_sigmawidth=sigma->width();
_a1mass=a1m->mass();_a1width=a1m->width();
_mKstar=getParticleData(ParticleID::Kstarplus)->mass();
_mK =getParticleData(ParticleID::Kplus)->mass();
}
// parameters for the breit-wigners
_mpic=getParticleData(ParticleID::piplus)->mass();
_mpi0=getParticleData(ParticleID::pi0)->mass();
// momenta of the decay products for on-shell particles
_psigmacc=Kinematics::pstarTwoBodyDecay(_sigmamass,_mpic,_mpic);
_psigma00=Kinematics::pstarTwoBodyDecay(_sigmamass,_mpi0,_mpi0);
_pf2cc=Kinematics::pstarTwoBodyDecay(_f2mass,_mpic,_mpic);
_pf200=Kinematics::pstarTwoBodyDecay(_f2mass,_mpi0,_mpi0);
_pf0cc=Kinematics::pstarTwoBodyDecay(_f0mass,_mpic,_mpic);
_pf000=Kinematics::pstarTwoBodyDecay(_f0mass,_mpi0,_mpi0);
_prhocc.resize(3);_prhoc0.resize(3);
for(unsigned int ix=0;ix<3;++ix) {
_prhocc[ix]=Kinematics::pstarTwoBodyDecay(_rhomass[ix],_mpic,_mpic);
_prhoc0[ix]=Kinematics::pstarTwoBodyDecay(_rhomass[ix],_mpic,_mpi0);
}
// couplings for the different modes
Complex ii(0.,1.);
_rhocoupP.resize(_rhomagP.size());
for(unsigned int ix=0;ix<_rhomagP.size();++ix)
{_rhocoupP[ix]=_rhomagP[ix]*(cos(_rhophaseP[ix])+ii*sin(_rhophaseP[ix]));}
_rhocoupD.resize(_rhomagD.size());
for(unsigned int ix=0;ix<_rhomagD.size();++ix)
{_rhocoupD[ix]=_rhomagD[ix]*(cos(_rhophaseD[ix])+ii*sin(_rhophaseD[ix]));}
_f0coup=_f0mag*(cos(_f0phase)+ii*sin(_f0phase));
_f2coup=_f2mag*(cos(_f2phase)+ii*sin(_f2phase));
_sigmacoup=_sigmamag*(cos(_sigmaphase)+ii*sin(_sigmaphase));
// overall coupling
_fact = 2.*sqrt(2.)/_fpi/3.;
// initialise the a_1 running width calculation
inita1Width(-1);
}
void ThreePionCLEOCurrent::persistentOutput(PersistentOStream & os) const {
os << ounit(_rhomass,GeV) << ounit(_rhowidth,GeV) << ounit(_prhocc,GeV) << ounit(_prhoc0,GeV)
<< ounit(_f2mass,GeV) << ounit(_f2width,GeV) << ounit(_pf2cc,GeV)
<< ounit(_pf200,GeV) << ounit(_f0mass,GeV) << ounit(_f0width,GeV)
<< ounit(_pf0cc,GeV) << ounit(_pf000,GeV)
<< ounit(_sigmamass,GeV) << ounit(_sigmawidth,GeV)
<< ounit(_psigmacc,GeV) << ounit(_psigma00,GeV) << ounit(_mpi0,GeV) << ounit(_mpic,GeV)
<< ounit(_fpi,GeV) << ounit(_fact,1/GeV)
<< _rhomagP << _rhophaseP
<< _rhocoupP << ounit(_rhomagD,1/GeV2) << _rhophaseD
<< ounit(_rhocoupD,1/GeV2) <<ounit(_f2mag,1/GeV2) << _f2phase << ounit(_f2coup ,1/GeV2)
<< _f0mag << _f0phase << _f0coup << _sigmamag << _sigmaphase << _sigmacoup
<< _localparameters
<< ounit(_a1mass,GeV) << ounit(_a1width,GeV) << ounit(_a1runwidth,GeV)
<< ounit(_a1runq2,GeV2) << _initializea1
<< ounit(_mKstar,GeV) << ounit(_mK,GeV) << _gammk << _a1opt
<< ounit(_maxmass,GeV) << ounit(_maxcalc,GeV) << _a1runinter;
}
void ThreePionCLEOCurrent::persistentInput(PersistentIStream & is, int) {
is >> iunit(_rhomass,GeV) >> iunit(_rhowidth,GeV) >> iunit(_prhocc,GeV) >> iunit(_prhoc0,GeV)
>> iunit(_f2mass,GeV) >> iunit(_f2width,GeV) >> iunit(_pf2cc,GeV)
>> iunit(_pf200,GeV) >> iunit(_f0mass,GeV) >> iunit(_f0width,GeV)
>> iunit(_pf0cc,GeV) >> iunit(_pf000,GeV)
>> iunit(_sigmamass,GeV) >> iunit(_sigmawidth,GeV)
>> iunit(_psigmacc,GeV) >> iunit(_psigma00,GeV) >> iunit(_mpi0,GeV) >> iunit(_mpic,GeV)
>> iunit(_fpi,GeV) >> iunit(_fact,1/GeV)
>> _rhomagP >> _rhophaseP
>> _rhocoupP >> iunit(_rhomagD,1/GeV2) >> _rhophaseD >> iunit(_rhocoupD,1/GeV2)
>> iunit(_f2mag,1/GeV2) >> _f2phase >> iunit(_f2coup,1/GeV2)
>> _f0mag >> _f0phase >> _f0coup >> _sigmamag >> _sigmaphase >> _sigmacoup
>> _localparameters
>> iunit(_a1mass,GeV) >> iunit(_a1width,GeV) >> iunit(_a1runwidth,GeV)
>> iunit(_a1runq2,GeV2) >> _initializea1
>> iunit(_mKstar,GeV) >> iunit(_mK,GeV) >> _gammk >> _a1opt
>> iunit(_maxmass,GeV) >> iunit(_maxcalc,GeV) >> _a1runinter;
}
void ThreePionCLEOCurrent::Init() {
static ClassDocumentation<ThreePionCLEOCurrent> documentation
("The ThreePionCLEOCurrent class performs the decay of the"
" tau to three pions using the currents from CLEO",
"The decay of tau to three pions is modelled using the currents from "
"\\cite{Asner:1999kj}.",
" %\\cite{Asner:1999kj}\n"
"\\bibitem{Asner:1999kj}\n"
" D.~M.~Asner {\\it et al.} [CLEO Collaboration],\n"
" ``Hadronic structure in the decay tau- --> nu/tau pi- pi0 pi0 and the sign\n"
" %of the tau neutrino helicity,''\n"
" Phys.\\ Rev.\\ D {\\bf 61}, 012002 (2000)\n"
" [arXiv:hep-ex/9902022].\n"
" %%CITATION = PHRVA,D61,012002;%%\n"
);
static ParVector<ThreePionCLEOCurrent,Energy> interfacerhomass
("RhoMasses",
"The masses of the different rho resonnaces",
&ThreePionCLEOCurrent::_rhomass,
MeV, 0, ZERO, -10000*MeV, 10000*MeV, false, false, true);
static ParVector<ThreePionCLEOCurrent,Energy> interfacerhowidth
("RhoWidths",
"The widths of the different rho resonnaces",
&ThreePionCLEOCurrent::_rhowidth,
MeV, 0, ZERO, -10000*MeV, 10000*MeV, false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfacef_2Mass
("f_2Mass",
"The mass of the f_2 meson",
&ThreePionCLEOCurrent::_f2mass, GeV, 1.275*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfacef_2Width
("f_2Width",
"The width of the f_2 meson",
&ThreePionCLEOCurrent::_f2width, GeV, 0.185*GeV, ZERO, 1.0*GeV,
false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfacef_0Mass
("f_0Mass",
"The mass of the f_0 meson",
&ThreePionCLEOCurrent::_f0mass, GeV, 1.186*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfacef_0Width
("f_0Width",
"The width of the f_0 meson",
&ThreePionCLEOCurrent::_f0width, GeV, 0.350*GeV, ZERO, 1.0*GeV,
false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfacesigmaMass
("sigmaMass",
"The mass of the sigma meson",
&ThreePionCLEOCurrent::_sigmamass, GeV, 0.860*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfacesigmaWidth
("sigmaWidth",
"The width of the sigma meson",
&ThreePionCLEOCurrent::_sigmawidth, GeV, 0.880*GeV, ZERO, 2.0*GeV,
false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfacea1Mass
("a1Mass",
"The mass of the a_1 meson",
&ThreePionCLEOCurrent::_a1mass, GeV, 1.331*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfacea1Width
("a1Width",
"The width of the a_1 meson",
&ThreePionCLEOCurrent::_a1width, GeV, 0.814*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfaceKaonMass
("KaonMass",
"The mass of the kaon",
&ThreePionCLEOCurrent::_mK, GeV, 0.496*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfaceKStarMass
("KStarMass",
"The mass of the k* meson",
&ThreePionCLEOCurrent::_mKstar, GeV, 0.894*GeV, ZERO, 10.0*GeV,
false, false, true);
static Parameter<ThreePionCLEOCurrent,double> interfaceKaonCoupling
("KaonCoupling",
"The relative coupling for the kaon in the a_1 running width",
&ThreePionCLEOCurrent::_gammk, 3.32, 0.0, 10.0,
false, false, true);
static Parameter<ThreePionCLEOCurrent,Energy> interfaceFpi
("Fpi",
"The pion decay constant",
&ThreePionCLEOCurrent::_fpi, MeV, 130.7*MeV/sqrt(2.), ZERO, 500.0*MeV,
false, false, true);
static ParVector<ThreePionCLEOCurrent,double> interfacerhomagP
("RhoPWaveMagnitude",
"The magnitude of the couplings for the p-wave rho currents",
&ThreePionCLEOCurrent::_rhomagP,
0, 0, 0, 0, 10000, false, false, true);
static ParVector<ThreePionCLEOCurrent,double> interfacerhophaseP
("RhoPWavePhase",
"The phase of the couplings for the p-wave rho currents",
&ThreePionCLEOCurrent::_rhophaseP,
0, 0, 0, -Constants::twopi, Constants::twopi, false, false, true);
static ParVector<ThreePionCLEOCurrent,InvEnergy2> interfacerhomagD
("RhoDWaveMagnitude",
"The magnitude of the couplings for the d-wave rho currents",
&ThreePionCLEOCurrent::_rhomagD,
1/MeV2, 0, ZERO, ZERO, 10000/MeV2, false, false, true);
static ParVector<ThreePionCLEOCurrent,double> interfacerhophaseD
("RhoDWavePhase",
"The phase of the couplings for the d-wave rho currents",
&ThreePionCLEOCurrent::_rhophaseD,
0, 0, 0, -Constants::twopi, Constants::twopi, false, false, true);
static Parameter<ThreePionCLEOCurrent,double> interfacef0Phase
("f0Phase",
"The phase of the f_0 scalar current",
&ThreePionCLEOCurrent::_f0phase, 0.54*Constants::pi, -Constants::twopi, Constants::twopi,
false, false, true);
static Parameter<ThreePionCLEOCurrent,double> interfacef2Phase
("f2Phase",
"The phase of the f_2 tensor current",
&ThreePionCLEOCurrent::_f2phase, 0.56*Constants::pi,-Constants::twopi, Constants::twopi,
false, false, true);
static Parameter<ThreePionCLEOCurrent,double> interfacesigmaPhase
("sigmaPhase",
"The phase of the sigma scalar current",
&ThreePionCLEOCurrent::_sigmaphase, 0.23*Constants::pi, -Constants::twopi, Constants::twopi,
false, false, true);
static Parameter<ThreePionCLEOCurrent,double> interfacef0Magnitude
("f0Magnitude",
"The magnitude of the f_0 scalar current",
&ThreePionCLEOCurrent::_f0mag, 0.77, 0.0, 10,
false, false, true);
static Parameter<ThreePionCLEOCurrent,InvEnergy2> interfacef2Magnitude
("f2Magnitude",
"The magnitude of the f_2 tensor current",
&ThreePionCLEOCurrent::_f2mag, 1./GeV2, 0.71/GeV2, ZERO, 10./GeV2,
false, false, true);
static Parameter<ThreePionCLEOCurrent,double> interfacesigmaMagnitude
("sigmaMagnitude",
"The magnitude of the sigma scalar current",
&ThreePionCLEOCurrent::_sigmamag, 2.1, 0.0, 10,
false, false, true);
static Switch<ThreePionCLEOCurrent,bool> interfaceLocalParameters
("LocalParameters",
"Use local values of the intermediate resonances masses and widths",
&ThreePionCLEOCurrent::_localparameters, true, false, false);
static SwitchOption interfaceLocalParametersLocal
(interfaceLocalParameters,
"Local",
"Use the local values",
true);
static SwitchOption interfaceLocalParametersDefault
(interfaceLocalParameters,
"ParticleData",
"Use the values from the particleData objects",
false);
static ParVector<ThreePionCLEOCurrent,Energy> interfacea1RunningWidth
("a1RunningWidth",
"The values of the a_1 width for interpolation to giving the running width.",
&ThreePionCLEOCurrent::_a1runwidth,
MeV, 0, ZERO, ZERO, 10000000*MeV, false, false, true);
static ParVector<ThreePionCLEOCurrent,Energy2> interfacea1RunningQ2
("a1RunningQ2",
"The values of the q^2 for interpolation to giving the running width.",
&ThreePionCLEOCurrent::_a1runq2,
MeV2, 0, ZERO, ZERO, 10000000*MeV2, false, false, true);
static Switch<ThreePionCLEOCurrent,bool> interfaceInitializea1
("Initializea1",
"Initialise the calculation of the a_1 running width",
&ThreePionCLEOCurrent::_initializea1, false, false, false);
static SwitchOption interfaceInitializea1Initialization
(interfaceInitializea1,
"Yes",
"Initialize the calculation",
true);
static SwitchOption interfaceInitializea1NoInitialization
(interfaceInitializea1,
"No",
"Use the default values",
false);
static Switch<ThreePionCLEOCurrent,bool> interfacea1WidthOption
("a1WidthOption",
"Option for the treatment of the a1 width",
&ThreePionCLEOCurrent::_a1opt, true, false, false);
static SwitchOption interfacea1WidthOptionLocal
(interfacea1WidthOption,
"Local",
"Use a calculation of the running width based on the parameters as"
" interpolation table.",
true);
static SwitchOption interfacea1WidthOptionParam
(interfacea1WidthOption,
"Kuhn",
"Use the parameterization of Kuhn and Santamaria for default parameters."
" This should only be used for testing vs TAUOLA",
false);
}
// initialisation of the a_1 width
// (iopt=-1 initialises, iopt=0 starts the interpolation)
void ThreePionCLEOCurrent::inita1Width(int iopt) {
if(iopt==-1) {
_maxcalc=_maxmass;
if(!_initializea1||_maxmass==ZERO) return;
// parameters for the table of values
Energy2 step=sqr(_maxmass)/200.;
// function to be integrated to give the matrix element
// integrator to perform the integral
vector<double> inweights;inweights.push_back(0.5);inweights.push_back(0.5);
vector<int> intype;intype.push_back(2);intype.push_back(3);
Energy mrho=getParticleData(ParticleID::rhoplus)->mass();
Energy wrho=getParticleData(ParticleID::rhoplus)->width();
vector<Energy> inmass;inmass.push_back(mrho);inmass.push_back(mrho);
vector<Energy> inwidth;inwidth.push_back(wrho);inwidth.push_back(wrho);
vector<double> inpow(2,0.0);
ThreeBodyAllOnCalculator<ThreePionCLEOCurrent>
widthgenN(inweights,intype,inmass,inwidth,inpow,*this,0,_mpi0,_mpi0,_mpic);
ThreeBodyAllOnCalculator<ThreePionCLEOCurrent>
widthgenC(inweights,intype,inmass,inwidth,inpow,*this,1,_mpic,_mpic,_mpic);
// normalisation constant to give physical width if on shell
double a1const = _a1width/(widthgenN.partialWidth(sqr(_a1mass))+
widthgenC.partialWidth(sqr(_a1mass)));
// loop to give the values
_a1runq2.clear();_a1runwidth.clear();
for(Energy2 moff2=ZERO; moff2<=sqr(_maxmass); moff2+=step) {
Energy moff=sqrt(moff2);
_a1runq2.push_back(moff2);
Energy charged=a1const*widthgenC.partialWidth(moff2);
Energy neutral=a1const*widthgenN.partialWidth(moff2);
Energy kaon = moff<=_mK+_mKstar ? ZERO : 2.870*_gammk*_gammk/8./Constants::pi*
Kinematics::pstarTwoBodyDecay(moff,_mK,_mKstar)/moff2*GeV2;
Energy total = charged + neutral + kaon;
_a1runwidth.push_back(total);
}
}
// set up the interpolator
else if(iopt==0) {
_a1runinter = make_InterpolatorPtr(_a1runwidth,_a1runq2,3);
}
}
// modes handled by this class
bool ThreePionCLEOCurrent::acceptMode(int imode) const {
return imode>=0&&imode<=1;
}
ThreePionCLEOCurrent::FormFactors ThreePionCLEOCurrent::
calculateFormFactors(const int ichan, const int imode,
Energy2 q2, Energy2 s1, Energy2 s2, Energy2 s3) const {
Complex F1=0., F2=0., F3=0.;//F4=0.;F5=0.;
// calculate the form factors without the a_1 piece
CLEOFormFactor(imode,ichan,q2,s1,s2,s3,F1,F2,F3);
// change sign of the f_2 term
F2=-F2;
// multiply by the a_1 factor
complex<InvEnergy> a1fact = a1BreitWigner(q2) * _fact;
return FormFactors(F1*a1fact, F2*a1fact, F3*a1fact);
}
void ThreePionCLEOCurrent::CLEOFormFactor(int imode,int ichan,
Energy2 q2,Energy2 s1, Energy2 s2, Energy2 s3,
Complex & F1, Complex & F2,
Complex & F3) const {
useMe();
if(imode==0) {
// compute the breit wigners we need
Complex rhos1bw[3],rhos2bw[3],f0bws1,sigbws1,f2bws1,f0bws2,sigbws2,f2bws2;
for(unsigned int ix=0,N=max(_rhocoupP.size(),_rhocoupD.size());ix<N;++ix) {
rhos1bw[ix]=rhoBreitWigner(ix,s1,0);
rhos2bw[ix]=rhoBreitWigner(ix,s2,0);
}
f0bws1 =f0BreitWigner(s1,0);
sigbws1 =sigmaBreitWigner(s1,0);
f2bws1 =f2BreitWigner(s1,0);
f0bws2 =f0BreitWigner(s2,0);
sigbws2 =sigmaBreitWigner(s2,0);
f2bws2 =f2BreitWigner(s2,0);
if(ichan<0) {
// the p-wave rho terms
for(unsigned int ix=0;ix<_rhocoupP.size();++ix) {
F1-=_rhocoupP[ix]*rhos1bw[ix];
F2-=_rhocoupP[ix]*rhos2bw[ix];
}
// the D-wave rho terms
Energy2 Dfact1=1./3.*(s1-s3);
Energy2 Dfact2=1./3.*(s2-s3);
for(unsigned int ix=0;ix<_rhocoupD.size();++ix) {
F1-=Dfact1*_rhocoupD[ix]*rhos2bw[ix];
F2-=Dfact2*_rhocoupD[ix]*rhos1bw[ix];
F3-=_rhocoupD[ix]*(Dfact2*rhos1bw[ix]-Dfact1*rhos2bw[ix]);
}
// the scalar terms
F1-=2./3.*(_sigmacoup*sigbws2+_f0coup*f0bws2);
F2-=2./3.*(_sigmacoup*sigbws1+_f0coup*f0bws1);
F3+=-2./3.*(_sigmacoup*sigbws1+_f0coup*f0bws1)
+2./3.*(_sigmacoup*sigbws2+_f0coup*f0bws2);
// the tensor terms
complex<Energy2> sfact1 = 1./18.*(4.*_mpic*_mpic-s1)*(q2+s1-_mpic*_mpic)/s1*f2bws1;
complex<Energy2> sfact2 = 1./18.*(4.*_mpic*_mpic-s2)*(q2+s2-_mpic*_mpic)/s2*f2bws2;
F1+=_f2coup*(0.5*(s3-s2)*f2bws1-sfact2);
F2+=_f2coup*(0.5*(s3-s1)*f2bws2-sfact1);
F3+=_f2coup*(-sfact1+sfact2);
}
else if(ichan%2==0&&ichan<=4) {
unsigned int ires=ichan/2;
Energy2 Dfact2=1./3.*(s2-s3);
if(ires<_rhocoupP.size()) F1-=_rhocoupP[ires]*rhos1bw[ires];
if(ires<_rhocoupD.size()) {
F2-=Dfact2*_rhocoupD[ires]*rhos1bw[ires];
F3-=_rhocoupD[ires]*Dfact2*rhos1bw[ires];
}
}
else if(ichan%2==1&&ichan<=5) {
unsigned int ires=(ichan-1)/2;
Energy2 Dfact1=1./3.*(s1-s3);
if(ires<_rhocoupP.size()) {
F2-=_rhocoupP[ires]*rhos2bw[ires];
}
if(ires<_rhocoupD.size()) {
F1-=Dfact1*_rhocoupD[ires]*rhos2bw[ires];
F3+=_rhocoupD[ires]*Dfact1*rhos2bw[ires];
}
}
else if(ichan==6) {
F2-=2./3.*_sigmacoup*sigbws1;
F3-=2./3.*_sigmacoup*sigbws1;
}
else if(ichan==7) {
F1-=2./3.*_sigmacoup*sigbws2;
F3+=2./3.*_sigmacoup*sigbws2;
}
else if(ichan==8) {
complex<Energy2> sfact1 = 1./18.*(4.*_mpic*_mpic-s1)*(q2+s1-_mpic*_mpic)/s1*f2bws1;
F1+=_f2coup*0.5*(s3-s2)*f2bws1;
F2-=_f2coup*sfact1;
F3-=_f2coup*sfact1;
}
else if(ichan==9) {
complex<Energy2> sfact2 = 1./18.*(4.*_mpic*_mpic-s2)*(q2+s2-_mpic*_mpic)/s2*f2bws2;
F1-=_f2coup*sfact2;
F2+=_f2coup*0.5*(s3-s1)*f2bws2;
F3+=_f2coup*sfact2;
}
else if(ichan==10) {
F2-=2./3.*_f0coup*f0bws1;
F3-=2./3.*_f0coup*f0bws1;
}
else if(ichan==11) {
F1-=2./3.*_f0coup*f0bws2;
F3+=2./3.*_f0coup*f0bws2;
}
}
// calculate the pi0 pi0 pi+ factor
else if(imode==1) {
// compute the breit wigners we need
Complex rhos1bw[3],rhos2bw[3],f0bw,sigbw,f2bw;
for(unsigned int ix=0,N=max(_rhocoupP.size(),_rhocoupD.size());ix<N;++ix) {
rhos1bw[ix]=rhoBreitWigner(ix,s1,1);
rhos2bw[ix]=rhoBreitWigner(ix,s2,1);
}
f0bw =f0BreitWigner(s3,1);
sigbw =sigmaBreitWigner(s3,1);
f2bw =f2BreitWigner(s3,1);
if(ichan<0) {
// the p-wave rho terms
for(unsigned int ix=0;ix<_rhocoupP.size();++ix) {
F1+=_rhocoupP[ix]*rhos1bw[ix];
F2+=_rhocoupP[ix]*rhos2bw[ix];
}
// the D-wave rho terms
Energy2 Dfact1=-1./3.*((s3-_mpic*_mpic)-(s1-_mpi0*_mpi0));
Energy2 Dfact2=-1./3.*((s3-_mpic*_mpic)-(s2-_mpi0*_mpi0));
for(unsigned int ix=0;ix<_rhocoupD.size();++ix) {
F1+=Dfact1*_rhocoupD[ix]*rhos2bw[ix];
F2+=Dfact2*_rhocoupD[ix]*rhos1bw[ix];
F3+=_rhocoupD[ix]*(Dfact2*rhos1bw[ix]-Dfact1*rhos2bw[ix]);
}
// the scalar terms
Complex scalar=2./3.*(_sigmacoup*sigbw+_f0coup*f0bw);
F1+=scalar;F2+=scalar;
// the tensor terms
Complex Dfact3=1./18./s3*_f2coup*(q2-_mpic*_mpic+s3)*(4.*_mpi0*_mpi0-s3)*f2bw;
F1+=Dfact3;F2+=Dfact3;
F3-=0.5*_f2coup*(s1-s2)*f2bw;
}
else if(ichan%2==0&&ichan<=4) {
unsigned int ires=ichan/2;
if(ires<_rhocoupP.size()){F1+=_rhocoupP[ires]*rhos1bw[ires];}
Energy2 Dfact2=-1./3.*((s3-_mpic*_mpic)-(s2-_mpi0*_mpi0));
if(ires<_rhocoupD.size()) {
F2+=Dfact2*_rhocoupD[ires]*rhos1bw[ires];
F3+=_rhocoupD[ires]*Dfact2*rhos1bw[ires];
}
}
else if(ichan%2==1&&ichan<=5) {
unsigned int ires=(ichan-1)/2;
if(ires<_rhocoupP.size()){F2+=_rhocoupP[ires]*rhos2bw[ires];}
Energy2 Dfact1=-1./3.*((s3-_mpic*_mpic)-(s1-_mpi0*_mpi0));
if(ires<_rhocoupD.size()) {
F1+=Dfact1*_rhocoupD[ires]*rhos2bw[ires];
F3-=_rhocoupD[ires]*Dfact1*rhos2bw[ires];
}
}
else if(ichan==6) {
F1+=2./3.*_sigmacoup*sigbw;
F2+=2./3.*_sigmacoup*sigbw;
}
else if(ichan==7) {
Complex Dfact3=1./18./s3*_f2coup*(q2-_mpic*_mpic+s3)*(4.*_mpi0*_mpi0-s3)*f2bw;
F1+=Dfact3;F2+=Dfact3;
F3-=0.5*_f2coup*(s1-s2)*f2bw;
}
else if(ichan==8) {
F1+=2./3.*_f0coup*f0bw;
F2+=2./3.*_f0coup*f0bw;
}
}
else {
throw DecayIntegratorError() << "ThreePionCLEOCurrent Unknown Decay" << imode
<< Exception::abortnow;
}
// identical particle factors
double fact = 1./sqrt(2.);
F1*=fact;F2*=fact;F3*=fact;
}
// complete the construction of the decay mode for integration
bool ThreePionCLEOCurrent::createMode(int icharge, unsigned int imode,
DecayPhaseSpaceModePtr mode,
unsigned int iloc,unsigned int ires,
DecayPhaseSpaceChannelPtr phase,Energy upp) {
if(!acceptMode(imode)){return false;}
int iq(0),ia(0);
tPDVector extpart=particles(1,imode,iq,ia);
Energy min(ZERO);
for(unsigned int ix=0;ix<extpart.size();++ix) min+=extpart[ix]->massMin();
if(min>upp) return false;
_maxmass=max(_maxmass,upp);
// pointers to the particles we need
tPDPtr a1m = getParticleData(ParticleID::a_1minus);
// the different rho resonances
tPDPtr rhom[3];
if(icharge==-3) {
rhom[0] = getParticleData(-213);
rhom[1] = getParticleData(-100213);
rhom[2] = getParticleData(-30213);
}
else if(icharge==3) {
rhom[0] = getParticleData(213);
rhom[1] = getParticleData(100213);
rhom[2] = getParticleData(30213);
}
else {
return false;
}
tPDPtr rho0[3] = {getParticleData(113),getParticleData(100113),
getParticleData(30113)};
// the sigma
tPDPtr sigma = getParticleData(9000221);
// the f_2
tPDPtr f2=getParticleData(225);
// the f_0
tPDPtr f0=getParticleData(10221);
// set up the integration channels
DecayPhaseSpaceChannelPtr newchannel;
if(imode==0) {
for(unsigned int ix=0;ix<3;++ix) {
if(!rho0[ix]) continue;
// the neutral rho channels
// first channel
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1m,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(rho0[ix],0,0.0,iloc+1,iloc+2);
mode->addChannel(newchannel);
// interchanged channel
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1m,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(rho0[ix],0,0.0,iloc,iloc+2);
mode->addChannel(newchannel);
}
// the sigma channels
if(sigma) {
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1m,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(sigma,0,0.0,iloc+1,iloc+2);
mode->addChannel(newchannel);
// interchanged channel
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1m,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(sigma,0,0.0,iloc,iloc+2);
mode->addChannel(newchannel);
}
// the f_2 channels
if(f2) {
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1m,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(f2,0,0.0,iloc+1,iloc+2);
mode->addChannel(newchannel);
// interchanged channel
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1m,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(f2,0,0.0,iloc,iloc+2);
mode->addChannel(newchannel);
}
if(f0) {
// the f_0 channel
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1m,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(f0,0,0.0,iloc+1,iloc+2);
mode->addChannel(newchannel);
// interchanged channel
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1m,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(f0,0,0.0,iloc,iloc+2);
mode->addChannel(newchannel);
}
}
else {
for(unsigned int ix=0;ix<3;++ix) {
if(!rhom[ix]) continue;
// first rho+ channel
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1m,0,0.0,-ires-1,iloc);
newchannel->addIntermediate(rhom[ix],0,0.0,iloc+2,iloc+1);
mode->addChannel(newchannel);
// second rho+ channel
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1m,0,0.0,-ires-1,iloc+1);
newchannel->addIntermediate(rhom[ix],0,0.0,iloc+2,iloc);
mode->addChannel(newchannel);
}
// the sigma channel
if(sigma) {
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1m,0,0.0,-ires-1,iloc+2);
newchannel->addIntermediate(sigma,0,0.0,iloc,iloc+1);
mode->addChannel(newchannel);
}
// the f_2 channel
if(f2) {
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1m,0,0.0,-ires-1,iloc+2);
newchannel->addIntermediate(f2,0,0.0,iloc,iloc+1);
mode->addChannel(newchannel);
}
// the f_0 channel
if(f0) {
newchannel = new_ptr(DecayPhaseSpaceChannel(*phase));
newchannel->addIntermediate(a1m,0,0.0,-ires-1,iloc+2);
newchannel->addIntermediate(f0,0,0.0,iloc,iloc+1);
mode->addChannel(newchannel);
}
}
if(_localparameters) {
for(unsigned int iy=0;iy<_rhomass.size();++iy) {
if(rho0[iy]) mode->resetIntermediate(rho0[iy],_rhomass[iy],_rhowidth[iy]);
if(rhom[iy]) mode->resetIntermediate(rhom[iy],_rhomass[iy],_rhowidth[iy]);
}
if(sigma) mode->resetIntermediate(sigma,_sigmamass,_sigmawidth);
if(f2) mode->resetIntermediate(f2,_f2mass,_f2width);
if(f0) mode->resetIntermediate(f0,_f0mass,_f0width);
mode->resetIntermediate(a1m,_a1mass,_a1width);
}
return true;
}
void ThreePionCLEOCurrent::dataBaseOutput(ofstream & output,bool header,
bool create) const {
if(header){output << "update decayers set parameters=\"";}
if(create) {
output << "create Herwig::ThreePionCLEOCurrent " << name()
<< " HwWeakCurrents.so\n";
}
for(unsigned int ix=0;ix<_rhomass.size();++ix) {
if(ix<2) {
output << "newdef " << name() << ":RhoMasses " << ix
<< " " << _rhomass[ix]/MeV << "\n";
}
else {
output << "insert " << name() << ":RhoMasses " << ix
<< " " << _rhomass[ix]/MeV << "\n";
}
}
for(unsigned int ix=0;ix<_rhowidth.size();++ix) {
if(ix<2) {
output << "newdef " << name() << ":RhoWidths " << ix
<< " " << _rhowidth[ix]/MeV << "\n";
}
else {
output << "insert " << name() << ":RhoWidths " << ix
<< " " << _rhowidth[ix]/MeV << "\n";
}
}
output << "newdef " << name() << ":f_2Mass " << _f2mass/GeV << "\n";
output << "newdef " << name() << ":f_2Width " << _f2width/GeV << "\n";
output << "newdef " << name() << ":f_0Mass " << _f0mass/GeV << "\n";
output << "newdef " << name() << ":f_0Width " << _f0width/GeV << "\n";
output << "newdef " << name() << ":sigmaMass " << _sigmamass/GeV << "\n";
output << "newdef " << name() << ":sigmaWidth " << _sigmawidth/GeV << "\n";
output << "newdef " << name() << ":a1Mass " << _a1mass/GeV << "\n";
output << "newdef " << name() << ":a1Width " <<_a1width /GeV << "\n";
output << "newdef " << name() << ":KaonMass " << _mK/GeV << "\n";
output << "newdef " << name() << ":KStarMass " << _mKstar/GeV << "\n";
output << "newdef " << name() << ":KaonCoupling " << _gammk << "\n";
output << "newdef " << name() << ":Fpi " << _fpi/MeV << "\n";
output << "newdef " << name() << ":a1WidthOption " << _a1opt << "\n";
for(unsigned int ix=0;ix<_rhomagP.size();++ix) {
if(ix<2) {
output << "newdef " << name() << ":RhoPWaveMagnitude " << ix
<< " " << _rhomagP[ix] << "\n";
}
else {
output << "insert " << name() << ":RhoPWaveMagnitude " << ix
<< " " << _rhomagP[ix] << "\n";
}
}
for(unsigned int ix=0;ix<_rhophaseP.size();++ix) {
if(ix<2) {
output << "newdef " << name() << ":RhoPWavePhase " << ix
<< " " << _rhophaseP[ix] << "\n";
}
else {
output << "insert " << name() << ":RhoPWavePhase " << ix
<< " " << _rhophaseP[ix] << "\n";
}
}
for(unsigned int ix=0;ix<_rhomagD.size();++ix) {
if(ix<2) {
output << "newdef " << name() << ":RhoDWaveMagnitude " << ix
<< " " << _rhomagD[ix]*MeV2 << "\n";
}
else {
output << "insert " << name() << ":RhoDWaveMagnitude " << ix
<< " " << _rhomagD[ix]*MeV2 << "\n";
}
}
for(unsigned int ix=0;ix<_rhophaseD.size();++ix) {
if(ix<2) {
output << "newdef " << name() << ":RhoDWavePhase " << ix
<< " " << _rhophaseD[ix] << "\n";
}
else {
output << "insert " << name() << ":RhoDWavePhase " << ix
<< " " << _rhophaseD[ix] << "\n";
}
}
output << "newdef " << name() << ":f0Phase " << _f0phase << "\n";
output << "newdef " << name() << ":f2Phase " <<_f2phase << "\n";
output << "newdef " << name() << ":sigmaPhase " <<_sigmaphase << "\n";
output << "newdef " << name() << ":f0Magnitude " << _f0mag << "\n";
output << "newdef " << name() << ":f2Magnitude " << _f2mag*GeV2 << "\n";
output << "newdef " << name() << ":sigmaMagnitude " <<_sigmamag << "\n";
output << "newdef " << name() << ":LocalParameters " << _localparameters << "\n";
output << "newdef " << name() << ":Initializea1 " <<_initializea1 << "\n";
for(unsigned int ix=0;ix<_a1runwidth.size();++ix) {
if(ix<200) {
output << "newdef " << name() << ":a1RunningWidth " << ix
<< " " << _a1runwidth[ix]/MeV << "\n";
}
else {
output << "insert " << name() << ":a1RunningWidth " << ix
<< " " << _a1runwidth[ix]/MeV << "\n";
}
}
for(unsigned int ix=0;ix<_a1runq2.size();++ix) {
if(ix<200) {
output << "newdef " << name() << ":a1RunningQ2 " << ix
<< " " << _a1runq2[ix]/MeV2 << "\n";
}
else {
output << "insert " << name() << ":a1RunningQ2 " << ix
<< " " << _a1runq2[ix]/MeV2 << "\n";
}
}
ThreeMesonCurrentBase::dataBaseOutput(output,false,false);
if(header) output << "\n\" where BINARY ThePEGName=\""
<< fullName() << "\";" << endl;
}
void ThreePionCLEOCurrent::doinitrun() {
// set up the running a_1 width
inita1Width(0);
ThreeMesonCurrentBase::doinitrun();
}
void ThreePionCLEOCurrent::doupdate() {
ThreeMesonCurrentBase::doupdate();
// update running width if needed
if ( !touched() ) return;
if(_maxmass!=_maxcalc) inita1Width(-1);
}
Energy ThreePionCLEOCurrent::a1width(Energy2 q2) const {
Energy output;
if(_a1opt) output=(*_a1runinter)(q2);
else {
double gam(0.);
if(q2<0.1753*GeV2) {
gam =0.;
}
else if(q2<0.823*GeV2) {
double p=q2/GeV2-0.1753;
gam = 5.80900*p*sqr(p)*(1.-3.00980*p+4.57920*sqr(p));
}
else {
double p=q2/GeV2;
gam = -13.91400+27.67900*p-13.39300*sqr(p)
+3.19240*sqr(p)*p-0.10487*sqr(sqr(p));
}
if(q2<0.1676*GeV2) {
gam+=0.;
}
else if(q2<0.823*GeV2) {
double p=q2/GeV2-0.1676;
gam+= 6.28450*p*sqr(p)*(1.-2.95950*p+4.33550*sqr(p));
}
else {
double p=q2/GeV2;
gam+= -15.41100+32.08800*p-17.66600*sqr(p)
+4.93550*sqr(p)*p-0.37498*sqr(sqr(p));
}
Energy mkst=0.894*GeV,mk=0.496*GeV;
Energy2 mk1sq=sqr(mkst+mk), mk2sq=sqr(mkst-mk);
double c3pi=sqr(0.2384),ckst=sqr(4.7621)*c3pi;
gam*=c3pi;
if(q2>mk1sq) gam+=0.5*ckst*sqrt((q2-mk1sq)*(q2-mk2sq))/q2;
gam = gam*_a1width*_a1mass/GeV2/1.331/0.814/1.0252088;
output = gam*GeV2/sqrt(q2);
}
return output;
}
double
ThreePionCLEOCurrent::threeBodyMatrixElement(const int iopt, const Energy2 q2,
const Energy2 s3, const Energy2 s2,
const Energy2 s1, const Energy,
const Energy, const Energy) const {
Energy p1[5],p2[5],p3[5];
Energy2 p1sq, p2sq, p3sq;
Energy q=sqrt(q2);
Energy2 mpi2c=_mpic*_mpic;
Energy2 mpi20=_mpi0*_mpi0;
// construct the momenta for the 2 neutral 1 charged mode
Complex F1,F2,F3;
if(iopt==0) {
// construct the momenta of the decay products
p1[0] = 0.5*(q2+mpi20-s1)/q; p1sq=p1[0]*p1[0]; p1[4]=sqrt(p1sq-mpi20);
p2[0] = 0.5*(q2+mpi20-s2)/q; p2sq=p2[0]*p2[0]; p2[4]=sqrt(p2sq-mpi20);
p3[0] = 0.5*(q2+mpi2c-s3)/q; p3sq=p3[0]*p3[0]; p3[4]=sqrt(p3sq-mpi2c);
// take momentum of 1 parallel to z axis
p1[1]=ZERO;p1[2]=ZERO;p1[3]=p1[4];
// construct 2
double cos2 = 0.5*(p1sq+p2sq-p3sq-2.*mpi20+mpi2c)/p1[4]/p2[4];
p2[1] = p2[4]*sqrt(1.-cos2*cos2); p2[2]=ZERO; p2[3]=-p2[4]*cos2;
// construct 3
double cos3 = 0.5*(p1sq-p2sq+p3sq-mpi2c)/p1[4]/p3[4];
p3[1] =-p3[4]*sqrt(1.-cos3*cos3); p3[2]=ZERO; p3[3]=-p3[4]*cos3;
// calculate the form factors
CLEOFormFactor(1,-1,q2,s1,s2,s3,F1,F2,F3);
}
// construct the momenta for the 3 charged mode
else {
// construct the momenta of the decay products
p1[0] = 0.5*(q2+mpi2c-s1)/q; p1sq=p1[0]*p1[0]; p1[4]=sqrt(p1sq-mpi2c);
p2[0] = 0.5*(q2+mpi2c-s2)/q; p2sq=p2[0]*p2[0]; p2[4]=sqrt(p2sq-mpi2c);
p3[0] = 0.5*(q2+mpi2c-s3)/q; p3sq=p3[0]*p3[0]; p3[4]=sqrt(p3sq-mpi2c);
// take momentum of 1 parallel to z axis
p1[1]=ZERO;p1[2]=ZERO;p1[3]=p1[4];
// construct 2
double cos2 = 0.5*(p1sq+p2sq-p3sq-mpi2c)/p1[4]/p2[4];
p2[1] = p2[4]*sqrt(1.-cos2*cos2); p2[2]=ZERO; p2[3]=-p2[4]*cos2;
// construct 3
double cos3 = 0.5*(p1sq-p2sq+p3sq-mpi2c)/p1[4]/p3[4];
p3[1] =-p3[4]*sqrt(1.-cos3*cos3); p3[2]=ZERO; p3[3]=-p3[4]*cos3;
// calculate the form factors
CLEOFormFactor(0,-1,q2,s1,s2,s3,F1,F2,F3);
}
// construct a vector with the current
complex<Energy> current[4];
for(unsigned int ix=0;ix<4;++ix)
current[ix] = F1*(p2[ix]-p3[ix])-F2*(p3[ix]-p1[ix])+F3*(p1[ix]-p2[ix]);
complex<Energy2> dot1=current[0]*conj(current[0]);
for(unsigned int ix=1;ix<4;++ix) dot1-=current[ix]*conj(current[ix]);
complex<Energy2> dot2=current[0]*q;
return(-dot1+dot2*conj(dot2)/q2).real() / sqr(_rhomass[0]);
}
diff --git a/Looptools/A/A0.F b/Looptools/A/A0.F
deleted file mode 100644
--- a/Looptools/A/A0.F
+++ /dev/null
@@ -1,80 +0,0 @@
-* A0.F
-* the scalar one-point function
-* this file is part of LoopTools
-* last modified 20 Dec 06 th
-
-#include "defs.h"
-
-
- double complex function XA0(m)
- implicit none
- DVAR m
-
-#include "lt.h"
-
- double complex XA0b
- external XA0b
-
- double complex res(0:1)
- integer key, ier
-
- key = ibits(versionkey, KeyA0, 2)
-
- if( key .ne. 1 ) then
- ier = 0
- call Xffa0(res(0), m, ier)
- if( ier .gt. warndigits ) key = ior(key, 2)
- endif
-
- if( key .ne. 0 ) then
- res(1) = XA0b(m)
- if( key .gt. 1 .and.
- & abs(res(0) - res(1)) .gt. maxdev*abs(res(0)) ) then
-#ifdef COMPLEXPARA
- print *, "Discrepancy in CA0:"
- print *, " m =", m
- print *, "A0C a =", res(0)
- print *, "A0C b =", res(1)
-#else
- print *, "Discrepancy in A0:"
- print *, " m =", m
- print *, "A0 a =", res(0)
- print *, "A0 b =", res(1)
-#endif
- endif
- endif
-
- XA0 = res(iand(key, 1))
- end
-
-************************************************************************
-* adapter code for C++
-
- subroutine XA0sub(res, m)
- implicit none
- double complex res
- DVAR m
-
- double complex XA0
- external XA0
-
- res = XA0(m)
- end
-
-************************************************************************
-* this routine is adapted from Ansgar Denner's bcanew.f
-* to the conventions of LoopTools
-
- double complex function XA0b(m)
- implicit none
- DVAR m
-
-#include "lt.h"
-
- if( m .eq. 0 ) then
- XA0b = 0
- else
- XA0b = m*(1 - log(m/mudim) + delta)
- endif
- end
-
diff --git a/Looptools/A/A00.F b/Looptools/A/A00.F
deleted file mode 100644
--- a/Looptools/A/A00.F
+++ /dev/null
@@ -1,35 +0,0 @@
-* A00.F
-* the scalar one-point function
-* this file is part of LoopTools
-* written by M. Rauch
-* last modified 24 Jan 06 th
-
-#include "defs.h"
-
-
- double complex function XA00(m)
- implicit none
- DVAR m
-
-#include "lt.h"
-
- double complex XA0
- external XA0
-
- XA00 = .25D0*m*(XA0(m) + .5D0*m)
- end
-
-************************************************************************
-* adapter code for C++
-
- subroutine XA00sub(res, m)
- implicit none
- double complex res
- DVAR m
-
- double complex XA00
- external XA00
-
- res = XA00(m)
- end
-
diff --git a/Looptools/A/Aget.F b/Looptools/A/Aget.F
new file mode 100644
--- /dev/null
+++ b/Looptools/A/Aget.F
@@ -0,0 +1,173 @@
+* Aget.F
+* retrieve the one-point tensor coefficients
+* this file is part of LoopTools
+* last modified 25 Jul 14 th
+
+#include "externals.h"
+#include "types.h"
+
+#define npoint 1
+#include "defs.h"
+
+
+ memindex function XAget(m)
+ implicit none
+ DVAR m
+
+#include "lt.h"
+
+ memindex cacheindex
+ external cacheindex, XAcoeff
+
+ DVAR para(1,Paa)
+
+ M(1) = m
+ if( abs(M(1)) .lt. minmass ) M(1) = 0
+
+ XAget = cacheindex(para, Aval(1,0), XAcoeff, RC*Paa, Naa, Ano)
+ end
+
+************************************************************************
+
+ subroutine XAput(res, m)
+ implicit none
+ ComplexType res(*)
+ DVAR m
+
+#include "lt.h"
+
+ external XAcoeff
+
+ DVAR para(1,Paa)
+
+ M(1) = m
+ if( abs(M(1)) .lt. minmass ) M(1) = 0
+
+ call cachecopy(res, para, Aval(1,0), XAcoeff, RC*Paa, Naa, Ano)
+ end
+
+************************************************************************
+
+ subroutine XAputnocache(res, m)
+ implicit none
+ ComplexType res(*)
+ DVAR m
+
+#include "lt.h"
+
+ DVAR para(1,Paa)
+
+ M(1) = m
+ if( abs(M(1)) .lt. minmass ) M(1) = 0
+
+ call Acoeff(res, para)
+ end
+
+************************************************************************
+
+ ComplexType function XA0i(i, m)
+ implicit none
+ integer i
+ DVAR m
+
+#include "lt.h"
+
+ memindex XAget
+ external XAget
+
+ memindex b
+
+ b = XAget(m)
+ XA0i = Aval(i+epsi,b)
+ end
+
+************************************************************************
+
+ ComplexType function XA0(m)
+ implicit none
+ DVAR m
+
+#include "lt.h"
+
+ ComplexType XA0i
+ external XA0i
+
+ XA0 = XA0i(aa0, m)
+ end
+
+************************************************************************
+
+ ComplexType function XA00(m)
+ implicit none
+ DVAR m
+
+#include "lt.h"
+
+ ComplexType XA0i
+ external XA0i
+
+ XA00 = XA0i(aa00, m)
+ end
+
+************************************************************************
+
+ subroutine XAcoeff(A, para)
+ implicit none
+ ComplexType A(*)
+ DVAR para(1,*)
+
+#include "lt.h"
+
+ DVAR m
+ ComplexType res(0:1)
+ integer key, ier
+ logical dump
+
+ m = M(1)
+ key = ibits(versionkey, KeyA0, 2)
+
+ serial = serial + 1
+ dump = ibits(debugkey, DebugA, 1) .ne. 0 .and.
+ & serial .ge. debugfrom .and. serial .le. debugto
+ if( dump ) call XDumpPara(1, para, "Acoeff")
+
+ if( key .ne. 1 ) then
+ ier = 0
+ call Xffa0(res(0), m, ier)
+ if( ier .gt. warndigits ) key = ior(key, 2)
+ endif
+
+ if( key .ne. 0 ) then
+ res(1) = 0
+ if( m .ne. 0 ) res(1) = m*(1 - log(m/mudim) + delta)
+ if( key .gt. 1 .and.
+ & abs(res(0) - res(1)) .gt. maxdev*abs(res(0)) ) then
+#ifdef COMPLEXPARA
+ print *, "Discrepancy in CA0:"
+ print *, " m =", m
+ print *, "A0C a =", res(0)
+ print *, "A0C b =", res(1)
+#else
+ print *, "Discrepancy in A0:"
+ print *, " m =", m
+ print *, "A0 a =", res(0)
+ print *, "A0 b =", res(1)
+#endif
+ endif
+ endif
+
+ A(aa0) = res(iand(key, 1))
+ A(aa00) = .25D0*m*(A(aa0) + .5D0*m)
+ A(1+aa0) = 0
+ A(1+aa00) = 0
+ A(2+aa0) = 0
+ A(2+aa00) = 0
+
+ if( lambda .le. 0 ) then
+ A(1+aa0) = m*uvdiv
+ A(1+aa00) = .25D0*m**2*uvdiv
+ endif
+
+ if( dump ) call XDumpCoeff(1, A)
+ end
+
diff --git a/Looptools/A/ffca0.F b/Looptools/A/ffca0.F
--- a/Looptools/A/ffca0.F
+++ b/Looptools/A/ffca0.F
@@ -1,42 +1,43 @@
* ffca0.F
* the one-point function for complex mass
* original code by G.J. van Oldenborgh
* this file is part of LoopTools
* last modified 7 Dec 10 th
#include "externals.h"
+#include "types.h"
* Input: cm (complex) mass2, re > 0, im < 0.
* Output: ca0 (complex) A0, the one-point function,
* ier 0 (OK)
subroutine ffca0(ca0, cm, ier)
implicit none
- double complex ca0, cm
+ ComplexType ca0, cm
integer ier
#include "ff.h"
- double complex cmu, clogm
+ ComplexType cmu, clogm
- double precision absc
- double complex c
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ RealType absc
+ ComplexType c
+ absc(c) = abs(Re(c)) + abs(Im(c))
* the real case:
* adapted to log-and-pole scheme 25-mar-1992
- if( DIMAG(cm) .eq. 0 .or. nschem .lt. 7 ) then
+ if( Im(cm) .eq. 0 .or. nschem .lt. 7 ) then
call ffxa0(ca0, cm, ier)
return
endif
cmu = cm
if( mudim .ne. 0 ) cmu = cmu/mudim
if( absc(cmu) .gt. xclogm ) then
clogm = log(cmu)
else
clogm = 0
if ( cmu .ne. 0 ) call fferr(1, ier)
endif
ca0 = -cm*(clogm - 1 - delta)
end
diff --git a/Looptools/A/ffxa0.F b/Looptools/A/ffxa0.F
--- a/Looptools/A/ffxa0.F
+++ b/Looptools/A/ffxa0.F
@@ -1,32 +1,33 @@
* ffxa0.F
* the one-point function for real mass
* original code by G.J. van Oldenborgh
* this file is part of LoopTools
* last modified 7 Dec 10 th
#include "externals.h"
+#include "types.h"
* Input: xm (real) mass2,
* Output: ca0 (complex) A0, the one-point function,
* ier 0 (ok)
subroutine ffxa0(ca0, xm, ier)
implicit none
- double complex ca0
- double precision xm
+ ComplexType ca0
+ RealType xm
integer ier
#include "ff.h"
- double precision xmu, xlogm
+ RealType xmu, xlogm
xmu = xm
if( mudim .ne. 0 ) xmu = xmu/mudim
if( xmu .gt. xalogm ) then
xlogm = log(xmu)
else
xlogm = 0
if( xmu .ne. 0 ) call fferr(2, ier)
endif
ca0 = -(xm*(xlogm - 1 - delta))
end
diff --git a/Looptools/B/Bcoeff.F b/Looptools/B/Bcoeff.F
--- a/Looptools/B/Bcoeff.F
+++ b/Looptools/B/Bcoeff.F
@@ -1,103 +1,131 @@
* Bcoeff.F
* invoke the two-point tensor coefficients
* this file is part of LoopTools
-* last modified 22 Dec 10 th
+* last modified 1 Sep 14 th
+#include "externals.h"
+#include "types.h"
+
+#define npoint 2
#include "defs.h"
- subroutine Bcoeff(para, B, ldpara)
+ subroutine Bcoeff(B, para)
implicit none
- integer ldpara
- double precision para(ldpara,Pbb)
- double complex B(Nbb)
+ ComplexType B(*)
+ RealType para(1,*)
#include "lt.h"
- double complex Bcmp(Nbb)
- double precision p, m1, m2
+ ComplexType cmp(Nbb)
+ RealType p, m1, m2, div
integer ier(Nbb), ierall, i
+ logical dump
- p = para(1,1)
- m1 = para(1,2)
- m2 = para(1,3)
+ serial = serial + 1
+ dump = ibits(debugkey, DebugB, 1) .ne. 0 .and.
+ & serial .ge. debugfrom .and. serial .le. debugto
+ if( dump ) call XDumpPara(2, para, "Bcoeff")
- if( lambda .lt. 0 .or.
- & abs(p) + abs(m1) + abs(m2) .lt. eps ) then
- do i = 1, Nbb
- B(i) = 0
- enddo
- if( lambda .eq. -1 ) then
- B(bb0) = 1
- B(bb1) = -.5D0
- B(bb00) = -(p - 3*(m1 + m2))/12D0
- B(bb11) = 1/3D0
- B(bb001) = -(p - 2*m1 - 4*m2)/24D0
- B(bb111) = -.25D0
- if( m1*m2 .eq. 0 .and. abs(p - m1 - m2) .lt. acc )
- & B(dbb0) = -.5D0/p
- if( m2 .eq. 0 .and. abs(p - m1) .lt. acc )
- & B(dbb1) = .5D0/p
- B(dbb00) = -1/12D0
+ do i = 1, Nbb
+ B(i) = 0
+ enddo
+
+ m1 = M(1)
+ m2 = M(2)
+ p = P(1)
+
+ div = uvdiv
+ if( abs(p) + abs(m1) + abs(m2) .lt. zeroeps ) div = div - 1
+ if( div .ne. 0 ) then
+ B(1+bb0) = div
+ B(1+bb1) = -.5D0*div
+ B(1+bb00) = -(p - 3*(m1 + m2))/12D0*div
+ B(1+dbb00) = -1/12D0*div
+ B(1+bb11) = 1/3D0*div
+ B(1+bb001) = (p - 2*m1 - 4*m2)/24D0*div
+ B(1+dbb001) = 1/24D0*div
+ B(1+bb111) = -.25D0*div
+ endif
+
+ if( lambda .le. 0 ) then
+ if( m1*m2 .eq. 0 .and. abs(p - m1 - m2) .lt. diffeps ) then
+ B(1+dbb0) = nan
+ if( p .ne. 0 ) B(1+dbb0) = -.5D0/p
endif
- return
+ if( m2 .eq. 0 .and. abs(p - m1) .lt. diffeps ) then
+ B(1+dbb1) = nan
+ if( p .ne. 0 ) B(1+dbb1) = .5D0/p
+ endif
+ endif
+
+ if( abs(p) + abs(m1) + abs(m2) .lt. zeroeps ) then
+ if( delta .ne. 0 ) then
+ B(bb0) = delta
+ B(bb1) = -.5D0*delta
+ B(bb11) = 1/3D0*delta
+ B(bb111) = -.25*delta
+ B(dbb00) = -1/12D0*delta
+ B(dbb001) = 1/24D0*delta
+ B(dbb0) = nan
+ B(dbb1) = nan
+ endif
+ goto 9
endif
goto (1, 2, 3) ibits(versionkey, KeyBget, 2)
- call Bcoeffa(para, B, ldpara, ier)
+ call BcoeffAD(B, para)
+ goto 9
+
+1 call BcoeffFF(B, para, ier)
ierall = 0
- do i = 1, Nbb
+ do i = 1, Nbb, 3
ierall = max(ierall, ier(i))
enddo
if( ierall .gt. warndigits ) then
- call Bcoeffb(para, Bcmp, ldpara)
- call Bcheck(para, B, Bcmp, ldpara, ier)
+ call BcoeffAD(cmp, para)
+ call Bcheck(cmp, B, ier, para)
endif
- return
+ goto 9
-1 call Bcoeffb(para, B, ldpara)
- return
+2 call BcoeffAD(B, para)
+ call BcoeffFF(cmp, para, ier)
+ call Bcheck(B, cmp, ier, para)
+ goto 9
-2 call Bcoeffa(para, B, ldpara, ier)
- call Bcoeffb(para, Bcmp, ldpara)
- call Bcheck(para, B, Bcmp, ldpara, ier)
- return
+3 call BcoeffFF(B, para, ier)
+ call BcoeffAD(cmp, para)
+ call Bcheck(cmp, B, ier, para)
-3 call Bcoeffa(para, Bcmp, ldpara, ier)
- call Bcoeffb(para, B, ldpara)
- call Bcheck(para, Bcmp, B, ldpara, ier)
+9 if( dump ) call DumpCoeff(2, B)
end
************************************************************************
- subroutine Bcheck(para, Ba, Bb, ldpara, ier)
+ subroutine Bcheck(Ba, Bb, ier, para)
implicit none
- integer ldpara, ier(Nbb)
- DVAR para(ldpara,Pbb)
- double complex Ba(Nbb), Bb(Nbb)
+ ComplexType Ba(*), Bb(*)
+ integer ier(*)
+ DVAR para(1,*)
#include "lt.h"
+#include "ltnames.h"
integer i
logical ini
- character*5 name(Nbb)
- data name /"bb0", "bb1", "bb00", "bb11", "bb001", "bb111",
- & "dbb0", "dbb1", "dbb00", "dbb11"/
-
ini = .TRUE.
- do i = 1, Nbb
+ do i = 1, Nbb, 3
if( abs(Ba(i) - Bb(i)) .gt. maxdev*abs(Ba(i)) ) then
if( ini ) then
- print *, "Discrepancy in Bget:"
- call DumpPara(2, para, ldpara, " ")
+ call DumpPara(2, para, "Discrepancy in Bget")
ini = .FALSE.
endif
- print *, name(i), " a =", Ba(i)
- print *, name(i), " b =", Bb(i)
- if( ier(i) .gt. errdigits ) Ba(i) = Bb(i)
+ print *, coeffname(i,2), " a =", Ba(i)
+ print *, coeffname(i,2), " b =", Bb(i)
+ if( ier(i) .gt. errdigits ) Bb(i) = Ba(i)
endif
enddo
end
diff --git a/Looptools/B/BcoeffAD.F b/Looptools/B/BcoeffAD.F
new file mode 100644
--- /dev/null
+++ b/Looptools/B/BcoeffAD.F
@@ -0,0 +1,321 @@
+* BcoeffAD.F
+* the two-point tensor coefficients from Ansgar Denner's bcanew.f,
+* adapted to the conventions of LoopTools
+* this file is part of LoopTools
+* last modified 1 Sep 14 th
+
+#include "externals.h"
+#include "types.h"
+
+#define npoint 2
+#include "defs.h"
+
+
+ subroutine BcoeffAD(B, para)
+ implicit none
+ ComplexType B(*)
+ RealType para(1,*)
+
+#include "lt.h"
+
+ ComplexType fpv, yfpv, fth, xlogx
+ external fpv, yfpv, fth, xlogx
+
+ RealType p, m1, m2
+ RealType dm, la
+ ComplexType x1, x2, y1, y2, r
+ ComplexType mu, f1, f2, g1, g2, a0
+ integer sel
+
+ m1 = M(1)
+ m2 = M(2)
+ p = P(1)
+
+ dm = m1 - m2
+
+* general case
+ if( abs(p) .gt. zeroeps*(m1 + m2) ) then
+ r = sqrt(ToComplex(p*(p - m1 - m2) -
+ & m1*(p - dm) - m2*(p + dm)))
+ x1 = .5D0*(p + dm + r)/p
+ x2 = .5D0*(p + dm - r)/p
+ if( abs(x2) .gt. abs(x1) ) then
+ x1 = m1/(p*x2)
+ else if( abs(x1) .gt. abs(x2) ) then
+ x2 = m1/(p*x1)
+ endif
+ x1 = x1 + sign(abs(x1), p)*cIeps
+ x2 = x2 - sign(abs(x2), p)*cIeps
+
+ y2 = .5D0*(p - dm + r)/p
+ y1 = .5D0*(p - dm - r)/p
+ if( abs(y2) .gt. abs(y1) ) then
+ y1 = m2/(p*y2)
+ else if( abs(y1) .gt. abs(y2) ) then
+ y2 = m2/(p*y1)
+ endif
+ y1 = y1 - sign(abs(y1), p)*cIeps
+ y2 = y2 + sign(abs(y2), p)*cIeps
+
+ if( abs(y1) .gt. .5D0 .and. abs(y2) .gt. .5D0 ) then
+ mu = log(m2/mudim) - delta
+ B(bb0) = -(mu + fpv(1, x1, y1) + fpv(1, x2, y2))
+ B(bb1) = 1/2D0*(mu + fpv(2, x1, y1) + fpv(2, x2, y2))
+ B(bb11) = -1/3D0*(mu + fpv(3, x1, y1) + fpv(3, x2, y2))
+ B(bb111) = 1/4D0*(mu + fpv(4, x1, y1) + fpv(4, x2, y2))
+ else if( abs(x1) .lt. 10 .and. abs(x2) .lt. 10 ) then
+ mu = log(p/mudim*(1 - cIeps)) - delta
+ g1 = xlogx(y1)
+ f1 = xlogx(-x1) - g1 + 1
+ g2 = xlogx(y2)
+ f2 = xlogx(-x2) - g2 + 1
+ B(bb0) = -(mu - f1 - f2)
+ f1 = x1*f1 - g1 + 1/2D0
+ f2 = x2*f2 - g2 + 1/2D0
+ B(bb1) = 1/2D0*(mu - f1 - f2)
+ f1 = x1*f1 - g1 + 1/3D0
+ f2 = x2*f2 - g2 + 1/3D0
+ B(bb11) = -1/3D0*(mu - f1 - f2)
+ f1 = x1*f1 - g1 + 1/4D0
+ f2 = x2*f2 - g2 + 1/4D0
+ B(bb111) = 1/4D0*(mu - f1 - f2)
+ else if( abs(x1) .gt. .5D0 .and. abs(x2) .gt. .5D0 ) then
+ mu = log(m1/mudim) - delta +
+ & fth(1, x1, y1) + fth(1, x2, y2)
+ B(bb0) = -mu
+ mu = mu + fth(2, x1, y1) + fth(2, x2, y2)
+ B(bb1) = 1/2D0*mu
+ mu = mu + fth(3, x1, y1) + fth(3, x2, y2)
+ B(bb11) = -1/3D0*mu
+ mu = mu + fth(4, x1, y1) + fth(4, x2, y2)
+ B(bb111) = 1/4D0*mu
+ else
+ print *, "BcoeffAD not defined for"
+ print *, " p =", p
+ print *, " m1 =", m1
+ print *, " m2 =", m2
+ B(bb0) = nan
+ B(bb1) = nan
+ B(bb11) = nan
+ B(bb111) = nan
+ endif
+
+ a0 = 0
+ if( m2 .ne. 0 ) a0 = m2*(1 - log(m2/mudim) + delta)
+
+ B(bb00) = ((p + dm)*B(bb1) +
+ & 2*m1*B(bb0) + a0 + m1 + m2 - p/3D0)/6D0
+
+ B(bb001) = .125D0*( 2*m1*B(bb1) - a0 +
+ & (p + dm)*(B(bb11) + 1/6D0) - .5D0*(m1 + m2) )
+
+ if( abs(x1 - x2) .gt. diffeps*abs(x1 + x2) ) then
+ B(dbb11) = (yfpv(3, x2, y2) - yfpv(3, x1, y1))/r
+ sel = 1
+ else if( abs(x1) .gt. 10 ) then
+ B(dbb11) = -Re((3/4D0 + (3 - 4*x1)*fpv(4, x1, y1))/
+ & x1**2)/p
+ sel = 2
+ else if( abs(y1) .gt. diffeps ) then
+ B(dbb11) = -Re(4/3D0 + (3 - 4*x1)*fpv(2, x1, y1))/p
+ sel = 3
+ else
+ B(dbb11) = nan
+ sel = 4
+ endif
+
+ la = lambda
+ if( la .le. 0 ) la = mudim
+
+ if( abs(m1) + abs(m2) .eq. 0 ) then
+ B(dbb0) = nan
+ if( p .ne. 0 ) B(dbb0) = -1/p
+ else if( m1*m2 .eq. 0 .and.
+ & abs(p - m1 - m2) .lt. diffeps ) then
+* IR divergent case
+ B(dbb0) = -(1 + .5D0*log(la/p))/p
+ else if( sel .eq. 1 ) then
+ B(dbb0) = (yfpv(1, x2, y2) - yfpv(1, x1, y1))/r
+ else if( sel .eq. 2 ) then
+ B(dbb0) = -Re((.5D0 + (1 - 2*x1)*fpv(2, x1, y1))/
+ & x1**2)/p
+ else if( sel .eq. 3 ) then
+ B(dbb0) = -Re(2 + (1 - 2*x1)*fpv(0, x1, y1))/p
+ else
+ B(dbb0) = nan
+ endif
+
+ if( abs(m1) + abs(m2) .eq. 0 ) then
+ B(dbb1) = nan
+ if( p .ne. 0 ) B(dbb1) = .5D0/p
+ else if( m2 .eq. 0 .and. abs(p - m1) .lt. diffeps ) then
+* IR divergent case
+ B(dbb1) = .5D0*(3 + log(la/p))/p
+ else if( sel .eq. 1 ) then
+ B(dbb1) = (yfpv(2, x1, y1) - yfpv(2, x2, y2))/r
+ else if( sel .eq. 2 ) then
+ B(dbb1) = Re((2/3D0 + (2 - 3*x1)*fpv(3, x1, y1))/
+ & x1**2)/p
+ else if( sel .eq. 3 ) then
+ B(dbb1) = Re(3/2D0 + (2 - 3*x1)*fpv(1, x1, y1))/p
+ else
+ B(dbb1) = nan
+ endif
+
+* zero momentum
+ else if( abs(dm) .gt. diffeps*(m1 + m2) ) then
+ x2 = m1/dm*(1 - cIeps)
+ y2 = -m2/dm*(1 - cIeps)
+ if( abs(y2) .gt. .5D0 ) then
+ mu = log(m2/mudim) - delta
+ B(bb0) = -(mu + fpv(1, x2, y2))
+ B(bb1) = 1/2D0*(mu + fpv(2, x2, y2))
+ B(bb11) = -1/3D0*(mu + fpv(3, x2, y2))
+ B(bb111) = 1/4D0*(mu + fpv(4, x2, y2))
+ a0 = 0
+ if( m2 .ne. 0 ) a0 = m2*(1 - log(m2/mudim) + delta)
+ B(bb00) = (2*(m1*B(bb0) + a0) + m1 + m2)/8D0
+ else
+ mu = log(m1/mudim) - delta
+ f1 = fpv(1, y2, x2)
+ B(bb0) = -(mu + f1)
+ B(bb1) = 1/2D0*(mu + (1 + x2)*f1 + 1/2D0)
+ B(bb11) = -1/3D0*(mu - (1 + x2*(1 + x2))*yfpv(0, x2, y2) -
+ & x2*(x2 + 1/2D0) - 1/3D0)
+ B(bb111) = 1/4D0*(mu -
+ & (1 + x2*(1 + x2*(1 + x2)))*yfpv(0, x2, y2) -
+ & x2*(x2*(x2 + 1/2D0) + 1/3D0) - 1/4D0)
+ a0 = 0
+ if( m1 .ne. 0 ) a0 = m1*(1 - log(m1/mudim) + delta)
+ B(bb00) = (2*(m2*B(bb0) + a0) + m1 + m2)/8D0
+ endif
+
+ B(bb001) = -( ((m1 + m2)/6D0)**2 +
+ & m1*m2/6D0 * (B(bb0) + 1/3D0) +
+ & (dm - m2)/3D0 * B(bb00) )/dm
+
+ if( abs(x2) .lt. 10 ) then
+ B(dbb0) = (1/2D0 + yfpv(1, x2, y2))/dm
+ B(dbb1) = -(1/3D0 + yfpv(2, x2, y2))/dm
+ B(dbb11) = (1/4D0 + yfpv(3, x2, y2))/dm
+ else
+ B(dbb0) = (1/2D0 + yfpv(2, x2, y2))/m1
+ B(dbb1) = -(1/3D0 + yfpv(3, x2, y2))/m1
+ B(dbb11) = (1/4D0 + yfpv(4, x2, y2))/m1
+ endif
+ else
+ mu = log(m2/mudim) - delta
+ B(bb0) = -mu
+ B(bb1) = 1/2D0*mu
+ B(bb11) = -1/3D0*mu
+ B(bb111) = 1/4D0*mu
+ B(bb00) = .5D0*m1*(1 - mu)
+ B(bb001) = -.5D0*B(bb00)
+ B(dbb0) = 1/6D0/m1
+ B(dbb1) = -1/12D0/m1
+ B(dbb11) = 1/20D0/m1
+ endif
+
+ B(dbb00) = 1/6D0*( 2*m1*B(dbb0) + B(bb1) +
+ & (p + dm)*B(dbb1) - 1/3D0 )
+
+ B(dbb001) = 1/8D0*( 2*m1*B(dbb1) + B(bb11) +
+ & (p + dm)*B(dbb11) + 1/6D0 )
+ end
+
+************************************************************************
+
+ ComplexType function fpv(n, x, y)
+ implicit none
+ integer n
+ ComplexType x, y
+
+#include "lt.h"
+
+ ComplexType xm
+ integer m
+
+ if( abs(x) .lt. 5 ) then
+ if( n .eq. 0 ) then
+ fpv = -log(-y/x)
+ else if( abs(x) .lt. diffeps ) then
+ fpv = -1D0/n
+ else
+ xm = -log(-y/x)
+ do m = 1, n
+ xm = x*xm - 1D0/m
+ enddo
+ fpv = xm
+ endif
+ else
+ fpv = 0
+ xm = 1
+ do m = 1, 50
+ xm = xm/x
+ fpv = fpv + xm/(m + n)
+ if( abs(xm) .lt. precx*abs(fpv) ) return
+ enddo
+ endif
+ end
+
+************************************************************************
+
+ ComplexType function yfpv(n, x, y)
+ implicit none
+ integer n
+ ComplexType x, y
+
+ ComplexType fpv
+ external fpv
+
+ if( abs(y) .eq. 0 ) then
+ yfpv = 0
+ else
+ yfpv = y*fpv(n, x, y)
+ endif
+ end
+
+************************************************************************
+
+ ComplexType function fth(n, x, y)
+ implicit none
+ integer n
+ ComplexType x, y
+
+#include "lt.h"
+
+ ComplexType fpv
+ external fpv
+
+ ComplexType xm
+ integer m
+
+ if( abs(x) .gt. 1D4 ) then
+ xm = 1
+ fth = 0
+ do m = n, 30 + n
+ xm = xm/x
+ fth = fth - xm/(m*(m + 1))
+ if( abs(xm) .lt. precx*abs(fth) ) return
+ enddo
+ else
+ fth = fpv(1, y, x)
+ do m = 1, n - 1
+ fth = x*fth + 1D0/(m*(m + 1))
+ enddo
+ endif
+ end
+
+************************************************************************
+
+ ComplexType function xlogx(x)
+ implicit none
+ ComplexType x
+
+ if( abs(x) .eq. 0 ) then
+ xlogx = 0
+ else
+ xlogx = x*log(x)
+ endif
+ end
+
diff --git a/Looptools/B/BcoeffC.F b/Looptools/B/BcoeffC.F
--- a/Looptools/B/BcoeffC.F
+++ b/Looptools/B/BcoeffC.F
@@ -1,54 +1,52 @@
* BcoeffC.F
* invoke the two-point tensor coefficients
* this file is part of LoopTools
-* last modified 24 Aug 09 th
+* last modified 26 Jan 14 th
+#include "externals.h"
+#include "types.h"
+
+#define npoint 2
#include "defs.h"
- subroutine BcoeffC(para, B, ldpara)
+ subroutine BcoeffC(B, para)
implicit none
- integer ldpara
- double complex para(ldpara,Pbb)
- double complex B(Nbb)
+ ComplexType B(*), para(1,*)
#include "lt.h"
+#include "ltnames.h"
integer ier(Nbb), i
logical ini
- character*5 name(Nbb)
- data name /"bb0", "bb1", "bb11", "bb00", "bb001", "bb111",
- & "dbb0", "dbb1", "dbb00", "dbb11"/
+ do i = 1, Nbb
+ B(i) = 0
+ enddo
- if( lambda .lt. 0 ) then
- do i = 1, Nbb
- B(i) = 0
- enddo
- if( lambda .eq. -1 ) then
- B(bb0) = 1
- B(bb1) = -.5D0
- B(bb00) = -(para(1,1) - 3*(para(1,2) + para(1,3)))/12D0
- B(bb11) = 1/3D0
- B(bb001) = -(para(1,1) - 2*para(1,2) - 4*para(1,3))/24D0
- B(bb111) = -.25D0
- B(dbb00) = -1/12D0
- endif
- return
+ if( lambda .le. 0 ) then
+ B(1+bb0) = 1
+ B(1+bb1) = -.5D0
+ B(1+bb00) = -(P(1) - 3*(M(1) + M(2)))/12D0
+ B(1+bb11) = 1/3D0
+ B(1+bb001) = (P(1) - 2*M(1) - 4*M(2))/24D0
+ B(1+bb111) = -.25D0
+ B(1+dbb00) = -1/12D0
+ B(1+dbb001) = 1/24D0
endif
- call BcoeffaC(para, B, ldpara, ier)
+ call BcoeffFFC(B, para, ier)
ini = .TRUE.
do i = 1, Nbb
if( ier(i) .gt. warndigits ) then
if( ini ) then
print *, "Loss of digits in BgetC for:"
- call DumpParaC(2, para, ldpara, " ")
+ call DumpParaC(2, para, " ")
ini = .FALSE.
endif
- print *, name(i), " claims ", ier(i), "lost digits"
+ print *, coeffname(i,2), " claims ", ier(i), "lost digits"
endif
enddo
end
diff --git a/Looptools/B/BcoeffFF.F b/Looptools/B/BcoeffFF.F
new file mode 100644
--- /dev/null
+++ b/Looptools/B/BcoeffFF.F
@@ -0,0 +1,107 @@
+* BcoeffFF.F
+* the two-point tensor coefficients from FF
+* this file is part of LoopTools
+* last modified 1 Sep 14 th
+
+#include "externals.h"
+#include "types.h"
+
+#define npoint 2
+#include "defs.h"
+
+
+ subroutine XBcoeffFF(B, para, ier)
+ implicit none
+ ComplexType B(*)
+ DVAR para(1,*)
+ integer ier(*)
+
+#include "lt.h"
+
+ DVAR p, m1, m2, dm
+ ComplexType a0(2), b2(2), pdb0
+ integer i
+#ifdef COMPLEXPARA
+ DVAR m1dm
+ ComplexType dmp, d2mp
+#endif
+
+ m1 = M(1)
+ m2 = M(2)
+ p = P(1)
+
+ do i = 1, Nbb
+ ier(i) = 0
+ enddo
+
+ ldot = .TRUE.
+ i = 0
+ call Xffb0(B(bb0), p, m1, m2, i)
+ ier(bb0) = i
+ call Xffa0(a0(1), m1, i)
+ call Xffa0(a0(2), m2, i)
+ ier(bb1) = i
+ call Xffb1(B(bb1), B(bb0), a0, p, m1, m2, Xfpij2, ier(bb1))
+ call Xffb2p(b2, B(bb1), B(bb0), a0, p, m1, m2, Xfpij2, i)
+ ier(bb00) = i
+ ier(bb11) = i
+ B(bb11) = b2(1)
+ B(bb00) = b2(2)
+ ldot = .FALSE.
+
+ dm = m1 - m2
+
+ if( abs(p) .lt. diffeps ) then
+ if( abs(dm) .lt. diffeps ) then
+ B(bb001) = -.5D0*B(bb00)
+ else
+ B(bb001) = -( ((m1 + m2)/6D0)**2 +
+ & m1*m2/6D0 * (B(bb0) + 1/3D0) +
+ & (dm - m2)/3D0 * B(bb00) )/dm
+ endif
+ else
+ B(bb001) = .125D0*( 2*m1*B(bb1) - a0(2) +
+ & (p + dm)*(B(bb11) + 1/6D0) - .5D0*(m1 + m2) )
+ endif
+
+ call Xffdb0(B(dbb0), pdb0, p, m1, m2, ier(dbb0))
+
+#ifdef COMPLEXPARA
+ if( abs(p) .lt. diffeps ) then
+ if( abs(dm) .lt. diffeps ) then
+ B(bb111) = -.25D0*B(bb0)
+ B(dbb1) = -1/12D0/m1
+ else
+ m1dm = m1/dm
+ B(bb111)= 3/16D0 + .25D0*a0(2)/dm*(m1dm + 1) +
+ & .5D0*m1dm*(m1dm*(B(bb1) - .5D0) - 1/6D0)
+ B(dbb1) = (2*m2*B(bb1) + a0(2) - (m1 + 2*m2)/3D0)/dm**2
+ endif
+ else
+ B(bb111) = -.25D0*( a0(2) + 2*m1*B(bb1) +
+ & (p + dm)*(3*B(bb11) + 1/6D0) - .5D0*(m1 + m2) )/p
+ B(dbb1) = .5D0/p*(
+ & (a0(2) - a0(1) + dm*B(bb0))/p -
+ & (p + dm)*B(dbb0) )
+ endif
+
+ dmp = (m1 - m2)/p
+ d2mp = (m1 - 2*m2)/p
+ B(dbb11) = 1/3D0*(
+ & ( (.5D0*(m1 + m2) +
+ & (2*dmp + 1)*a0(1) - (2*dmp + 2)*a0(2))/p -
+ & (d2mp + 2*dmp**2)*B(bb0) )/p +
+ & (d2mp + dmp**2 + 1)*B(dbb0) )
+#else
+ call ffxb111(B(bb111), p, m1, m2, ier(bb111))
+ call ffxdb1(B(dbb1), p, m1, m2, ier(dbb1))
+ call ffxdb11(B(dbb11), p, m1, m2, ier(dbb11))
+#endif
+
+ B(dbb00) = 1/6D0*( 2*m1*B(dbb0) + B(bb1) +
+ & (p + dm)*B(dbb1) - 1/3D0 )
+
+ B(dbb001) = 1/8D0*( 2*m1*B(dbb1) + B(bb11) +
+ & (p + dm)*B(dbb11) + 1/6D0 )
+ end
+
diff --git a/Looptools/B/Bcoeffa.F b/Looptools/B/Bcoeffa.F
deleted file mode 100644
--- a/Looptools/B/Bcoeffa.F
+++ /dev/null
@@ -1,117 +0,0 @@
-* Bcoeffa.F
-* the two-point tensor coefficients from FF
-* this file is part of LoopTools
-* last modified 28 Sep 10 th
-
-#include "defs.h"
-
-
- subroutine XBcoeffa(para, B, ldpara, ier)
- implicit none
- integer ldpara, ier(Nbb)
- DVAR para(ldpara,Pbb)
- double complex B(Nbb)
-
-#include "lt.h"
-
- DVAR p, m1, m2, dm
- double complex a0(2), b2(2), pdb0
- integer i
- logical dump
-#ifdef COMPLEXPARA
- DVAR m1dm
- double complex dmp, d2mp
-#endif
-
-#ifdef COMPLEXPARA
- if( abs(DIMAG(para(1,1))) .gt. 0 )
- & print *, "Warning: complex momenta not implemented"
- if( abs(DIMAG(para(1,2))) +
- & abs(DIMAG(para(1,3))) .eq. 0 ) then
- call Bcoeffa(para, B, 2, ier)
- return
- endif
-#endif
-
- p = para(1,1)
- m1 = para(1,2)
- m2 = para(1,3)
-
- serial = serial + 1
- dump = ibits(debugkey, DebugB, 1) .ne. 0 .and.
- & serial .ge. debugfrom .and. serial .le. debugto
- if( dump ) call XDumpPara(2, para, ldpara, "Bcoeffa")
-
- do i = 1, Nbb
- ier(i) = 0
- enddo
-
- ldot = .TRUE.
- i = 0
- call Xffb0(B(bb0), p, m1, m2, i)
- ier(bb0) = i
- call Xffa0(a0(1), m1, i)
- call Xffa0(a0(2), m2, i)
- ier(bb1) = i
- call Xffb1(B(bb1), B(bb0), a0, p, m1, m2, Xfpij2, ier(bb1))
- call Xffb2p(b2, B(bb1), B(bb0), a0, p, m1, m2, Xfpij2, i)
- ier(bb00) = i
- ier(bb11) = i
- B(bb11) = b2(1)
- B(bb00) = b2(2)
- ldot = .FALSE.
-
- dm = m1 - m2
-
- if( abs(p) .lt. acc ) then
- if( abs(dm) .lt. acc ) then
- B(bb001) = -.5D0*B(bb00)
- else
- B(bb001) = -( ((m1 + m2)/6D0)**2 +
- & m1*m2/6D0 * (B(bb0) + 1/3D0) +
- & (dm - m2)/3D0 * B(bb00) )/dm
- endif
- else
- B(bb001) = .125D0*( 2*m1*B(bb1) - a0(2) +
- & (p + dm)*(B(bb11) + 1/6D0) - .5D0*(m1 + m2) )
- endif
-
- call Xffdb0(B(dbb0), pdb0, p, m1, m2, ier(dbb0))
-
-#ifdef COMPLEXPARA
- if( abs(p) .lt. acc ) then
- if( abs(dm) .lt. acc ) then
- B(bb111) = -.25D0*B(bb0)
- else
- m1dm = m1/dm
- B(bb111)= 3/16D0 + .25D0*a0(2)/dm*(m1dm + 1) +
- & .5D0*m1dm*(m1dm*(B(bb1) - .5D0) - 1/6D0)
- endif
- else
- B(bb111) = -.25D0*( a0(2) + 2*m1*B(bb1) +
- & (p + dm)*(3*B(bb11) + 1/6D0) - .5D0*(m1 + m2) )/p
- endif
-
- B(dbb1) = .5D0/p*(
- & (a0(2) - a0(1) + dm*B(bb0))/p -
- & (p + dm)*B(dbb0) )
-
- dmp = (m1 - m2)/p
- d2mp = (m1 - 2*m2)/p
- B(dbb11) = 1/3D0*(
- & ( (.5D0*(m1 + m2) +
- & (2*dmp + 1)*a0(1) - (2*dmp + 2)*a0(2))/p -
- & (d2mp + 2*dmp**2)*B(bb0) )/p +
- & (d2mp + dmp**2 + 1)*B(dbb0) )
-#else
- call ffxb111(B(bb111), p, m1, m2, ier(bb111))
- call ffxdb1(B(dbb1), p, m1, m2, ier(dbb1))
- call ffxdb11(B(dbb11), p, m1, m2, ier(dbb11))
-#endif
-
- B(dbb00) = 1/6D0*( 2*m1*B(dbb0) + B(bb1) +
- & (p + dm)*B(dbb1) - 1/3D0 )
-
- if( dump ) call DumpCoeff(2, B)
- end
-
diff --git a/Looptools/B/Bcoeffb.F b/Looptools/B/Bcoeffb.F
deleted file mode 100644
--- a/Looptools/B/Bcoeffb.F
+++ /dev/null
@@ -1,309 +0,0 @@
-* Bcoeffb.F
-* the two-point tensor coefficients from Ansgar Denner's bcanew.f,
-* adapted to the conventions of LoopTools
-* this file is part of LoopTools
-* last modified 22 Dec 10 th
-
-#include "defs.h"
-
-
- subroutine Bcoeffb(para, B, ldpara)
- implicit none
- integer ldpara
- double precision para(ldpara,Pbb)
- double complex B(Nbb)
-
-#include "lt.h"
-
- double complex fpv, yfpv, fth, xlogx, A0b
- external fpv, yfpv, fth, xlogx, A0b
-
- double precision p, m1, m2
- double precision minacc, dm, la
- double complex x1, x2, y1, y2, r
- double complex mu, f1, f2, g1, g2
- integer sel
- logical dump
-
- p = para(1,1)
- m1 = para(1,2)
- m2 = para(1,3)
-
- serial = serial + 1
- dump = ibits(debugkey, DebugB, 1) .ne. 0 .and.
- & serial .ge. debugfrom .and. serial .le. debugto
- if( dump ) call DumpPara(2, para, ldpara, "Bcoeffb")
-
- minacc = acc*(m1 + m2)
- dm = m1 - m2
-
-* general case
- if( abs(p) .gt. minacc ) then
- r = sqrt(DCMPLX(p*(p - m1 - m2) -
- & m1*(p - dm) - m2*(p + dm)))
- x1 = .5D0*(p + dm + r)/p
- x2 = .5D0*(p + dm - r)/p
- if( abs(x2) .gt. abs(x1) ) then
- x1 = m1/(p*x2)
- else if( abs(x1) .gt. abs(x2) ) then
- x2 = m1/(p*x1)
- endif
- x1 = x1 + abs(p*x1)/p*eps*cI
- x2 = x2 - abs(p*x2)/p*eps*cI
-
- y2 = .5D0*(p - dm + r)/p
- y1 = .5D0*(p - dm - r)/p
- if( abs(y2) .gt. abs(y1) ) then
- y1 = m2/(p*y2)
- else if( abs(y1) .gt. abs(y2) ) then
- y2 = m2/(p*y1)
- endif
- y1 = y1 - abs(p*y1)/p*eps*cI
- y2 = y2 + abs(p*y2)/p*eps*cI
-
- if( abs(y1) .gt. .5D0 .and. abs(y2) .gt. .5D0 ) then
- mu = log(m2/mudim) - delta
- B(bb0) = -(mu + fpv(1, x1, y1) + fpv(1, x2, y2))
- B(bb1) = 1/2D0*(mu + fpv(2, x1, y1) + fpv(2, x2, y2))
- B(bb11) = -1/3D0*(mu + fpv(3, x1, y1) + fpv(3, x2, y2))
- B(bb111) = 1/4D0*(mu + fpv(4, x1, y1) + fpv(4, x2, y2))
- else if( abs(x1) .lt. 10 .and. abs(x2) .lt. 10 ) then
- mu = log(p/mudim*(1 - cI*eps)) - delta
- g1 = xlogx(y1)
- f1 = xlogx(-x1) - g1 + 1
- g2 = xlogx(y2)
- f2 = xlogx(-x2) - g2 + 1
- B(bb0) = -(mu - f1 - f2)
- f1 = x1*f1 - g1 + 1/2D0
- f2 = x2*f2 - g2 + 1/2D0
- B(bb1) = 1/2D0*(mu - f1 - f2)
- f1 = x1*f1 - g1 + 1/3D0
- f2 = x2*f2 - g2 + 1/3D0
- B(bb11) = -1/3D0*(mu - f1 - f2)
- f1 = x1*f1 - g1 + 1/4D0
- f2 = x2*f2 - g2 + 1/4D0
- B(bb111) = 1/4D0*(mu - f1 - f2)
- else if( abs(x1) .gt. .5D0 .and. abs(x2) .gt. .5D0 ) then
- mu = log(m1/mudim) - delta +
- & fth(1, x1, y1) + fth(1, x2, y2)
- B(bb0) = -mu
- mu = mu + fth(2, x1, y1) + fth(2, x2, y2)
- B(bb1) = 1/2D0*mu
- mu = mu + fth(3, x1, y1) + fth(3, x2, y2)
- B(bb11) = -1/3D0*mu
- mu = mu + fth(4, x1, y1) + fth(4, x2, y2)
- B(bb111) = 1/4D0*mu
- else
- print *, "Bcoeffb not defined for"
- print *, " p =", p
- print *, " m1 =", m1
- print *, " m2 =", m2
- B(bb0) = nan
- B(bb1) = nan
- B(bb11) = nan
- B(bb111) = nan
- endif
-
- B(bb00) = ((p + dm)*B(bb1) +
- & 2*m1*B(bb0) + A0b(m2) + m1 + m2 - p/3D0)/6D0
-
- B(bb001) = .125D0*( 2*m1*B(bb1) - A0b(m2) +
- & (p + dm)*(B(bb11) + 1/6D0) - .5D0*(m1 + m2) )
-
- if( abs(x1 - x2) .gt. acc*abs(x1 + x2) ) then
- B(dbb11) = (yfpv(3, x2, y2) - yfpv(3, x1, y1))/r
- sel = 1
- else if( abs(x1) .gt. 10 ) then
- B(dbb11) = -DBLE((3/4D0 + (3 - 4*x1)*fpv(4, x1, y1))/
- & x1**2)/p
- sel = 2
- else if( abs(y1) .gt. acc ) then
- B(dbb11) = -DBLE(4/3D0 + (3 - 4*x1)*fpv(2, x1, y1))/p
- sel = 3
- else
- B(dbb11) = nan
- endif
-
- if( m1*m2 .eq. 0 .and.
- & abs(p - m1 - m2) .lt. acc ) then
-* IR divergent case
- la = lambda
- if( la .le. 0 ) la = mudim
- B(dbb0) = -(1 + .5D0*log(la/p))/p
- else if( sel .eq. 1 ) then
- B(dbb0) = (yfpv(1, x2, y2) - yfpv(1, x1, y1))/r
- else if( sel .eq. 2 ) then
- B(dbb0) = -DBLE((.5D0 + (1 - 2*x1)*fpv(2, x1, y1))/
- & x1**2)/p
- else if( sel .eq. 3 ) then
- B(dbb0) = -DBLE(2 + (1 - 2*x1)*fpv(0, x1, y1))/p
- else
- B(dbb0) = nan
- endif
-
- if( m2 .eq. 0 .and. abs(p - m1) .lt. acc ) then
-* IR divergent case
- B(dbb1) = .5D0*(3 + log(la/p))/p
- else if( sel .eq. 1 ) then
- B(dbb1) = (yfpv(2, x1, y1) - yfpv(2, x2, y2))/r
- else if( sel .eq. 2 ) then
- B(dbb1) = DBLE((2/3D0 + (2 - 3*x1)*fpv(3, x1, y1))/
- & x1**2)/p
- else if( sel .eq. 3 ) then
- B(dbb1) = DBLE(3/2D0 + (2 - 3*x1)*fpv(1, x1, y1))/p
- else
- B(dbb1) = nan
- endif
-
-* zero momentum
- else if( abs(dm) .gt. minacc ) then
- x2 = m1/dm*(1 - cI*eps)
- y2 = -m2/dm*(1 - cI*eps)
- if( abs(y2) .gt. .5D0 ) then
- mu = log(m2/mudim) - delta
- B(bb0) = -(mu + fpv(1, x2, y2))
- B(bb1) = 1/2D0*(mu + fpv(2, x2, y2))
- B(bb11) = -1/3D0*(mu + fpv(3, x2, y2))
- B(bb111) = 1/4D0*(mu + fpv(4, x2, y2))
- B(bb00) = (2*(m1*B(bb0) + A0b(m2)) + m1 + m2)/8D0
- else
- mu = log(m1/mudim) - delta
- f1 = fpv(1, y2, x2)
- B(bb0) = -(mu + f1)
- B(bb1) = 1/2D0*(mu + (1 + x2)*f1 + 1/2D0)
- B(bb11) = -1/3D0*(mu - (1 + x2*(1 + x2))*yfpv(0, x2, y2) -
- & x2*(x2 + 1/2D0) - 1/3D0)
- B(bb111) = 1/4D0*(mu -
- & (1 + x2*(1 + x2*(1 + x2)))*yfpv(0, x2, y2) -
- & x2*(x2*(x2 + 1/2D0) + 1/3D0) - 1/4D0)
- B(bb00) = (2*(m2*B(bb0) + A0b(m1)) + m1 + m2)/8D0
- endif
-
- B(bb001) = -( ((m1 + m2)/6D0)**2 +
- & m1*m2/6D0 * (B(bb0) + 1/3D0) +
- & (dm - m2)/3D0 * B(bb00) )/dm
-
- if( abs(x2) .lt. 10 ) then
- B(dbb0) = (1/2D0 + yfpv(1, x2, y2))/dm
- B(dbb1) = -(1/3D0 + yfpv(2, x2, y2))/dm
- B(dbb11) = (1/4D0 + yfpv(3, x2, y2))/dm
- else
- B(dbb0) = (1/2D0 + yfpv(2, x2, y2))/m1
- B(dbb1) = -(1/3D0 + yfpv(3, x2, y2))/m1
- B(dbb11) = (1/4D0 + yfpv(4, x2, y2))/m1
- endif
- else
- mu = log(m2/mudim) - delta
- B(bb0) = -mu
- B(bb1) = 1/2D0*mu
- B(bb11) = -1/3D0*mu
- B(bb111) = 1/4D0*mu
- B(bb00) = .5D0*m1*(1 - mu)
- B(bb001) = -.5D0*B(bb00)
- B(dbb0) = 1/6D0/m1
- B(dbb1) = -1/12D0/m1
- B(dbb11) = 1/20D0/m1
- endif
-
- B(dbb00) = 1/6D0*( 2*m1*B(dbb0) + B(bb1) +
- & (p + dm)*B(dbb1) - 1/3D0 )
-
- if( dump ) call DumpCoeff(2, B)
- end
-
-************************************************************************
-
- double complex function fpv(n, x, y)
- implicit none
- integer n
- double complex x, y
-
-#include "lt.h"
-
- double complex xm
- integer m
-
- if( abs(x) .lt. 5 ) then
- if( n .eq. 0 ) then
- fpv = -log(-y/x)
- else if( abs(x) .lt. acc ) then
- fpv = -1D0/n
- else
- xm = -log(-y/x)
- do m = 1, n
- xm = x*xm - 1D0/m
- enddo
- fpv = xm
- endif
- else
- fpv = 0
- xm = 1
- do m = 1, 50
- xm = xm/x
- fpv = fpv + xm/(m + n)
- if( abs(xm) .lt. precx*abs(fpv) ) return
- enddo
- endif
- end
-
-************************************************************************
-
- double complex function yfpv(n, x, y)
- implicit none
- integer n
- double complex x, y
-
- double complex fpv
- external fpv
-
- if( abs(y) .eq. 0 ) then
- yfpv = 0
- else
- yfpv = y*fpv(n, x, y)
- endif
- end
-
-************************************************************************
-
- double complex function fth(n, x, y)
- implicit none
- integer n
- double complex x, y
-
-#include "lt.h"
-
- double complex fpv
- external fpv
-
- double complex xm
- integer m
-
- if( abs(x) .gt. 1D4 ) then
- xm = 1
- fth = 0
- do m = n, 30 + n
- xm = xm/x
- fth = fth - xm/(m*(m + 1))
- if( abs(xm) .lt. precx*abs(fth) ) return
- enddo
- else
- fth = fpv(1, y, x)
- do m = 1, n - 1
- fth = x*fth + 1D0/(m*(m + 1))
- enddo
- endif
- end
-
-************************************************************************
-
- double complex function xlogx(x)
- implicit none
- double complex x
-
- if( abs(x) .eq. 0 ) then
- xlogx = 0
- else
- xlogx = x*log(x)
- endif
- end
-
diff --git a/Looptools/B/Bget.F b/Looptools/B/Bget.F
--- a/Looptools/B/Bget.F
+++ b/Looptools/B/Bget.F
@@ -1,186 +1,282 @@
* Bget.F
* retrieve the two-point tensor coefficients
* this file is part of LoopTools
-* last modified 15 Jun 09 th
+* last modified 23 Mar 15 th
+#include "externals.h"
+#include "types.h"
+
+#define npoint 2
#include "defs.h"
- integer function XBget(p, m1, m2)
+ subroutine XBpara(para, p, m1, m2)
+ implicit none
+ DVAR para(1,*)
+ DVAR p, m1, m2
+
+#include "lt.h"
+
+ P(1) = p
+
+ M(1) = m1
+ if( abs(M(1)) .lt. minmass ) M(1) = 0
+ M(2) = m2
+ if( abs(M(2)) .lt. minmass ) M(2) = 0
+ end
+
+************************************************************************
+
+ memindex function XBget(p, m1, m2)
implicit none
DVAR p, m1, m2
#include "lt.h"
- integer cachelookup
- external cachelookup, XBcoeff
+ memindex cacheindex
+ external cacheindex, XBcoeff
- DVAR para(Pbb)
+#ifdef COMPLEXPARA
+ memindex Bget
+ external Bget
+#endif
- para(1) = p
- para(2) = m1
- if( abs(para(2)) .lt. minmass ) para(2) = 0
- para(3) = m2
- if( abs(para(3)) .lt. minmass ) para(3) = 0
+ DVAR para(1,Pbb)
- XBget = cachelookup(para, Bval(1,0), XBcoeff, RC*Pbb, Nbb)
+#ifdef COMPLEXPARA
+ if( abs(Im(p)) .gt. 0 )
+ & print *, "Complex momenta not implemented"
+ if( abs(Im(m1)) + abs(Im(m2)) .eq. 0 ) then
+ XBget = Bget(p, m1, m2) - offsetC
+ return
+ endif
+#endif
+
+ call XBpara(para, p, m1, m2)
+ XBget = cacheindex(para, Bval(1,0), XBcoeff, RC*Pbb, Nbb, Bno)
end
************************************************************************
- double complex function XB0i(i, p, m1, m2)
+ subroutine XBput(res, p, m1, m2)
+ implicit none
+ ComplexType res(*)
+ DVAR p, m1, m2
+
+#include "lt.h"
+
+ external XBcoeff
+
+ DVAR para(1,Pbb)
+
+#ifdef COMPLEXPARA
+ if( abs(Im(p)) .gt. 0 )
+ & print *, "Complex momenta not implemented"
+ if( abs(Im(m1)) + abs(Im(m2)) .eq. 0 ) then
+ call Bput(res, p, m1, m2)
+ return
+ endif
+#endif
+
+ call XBpara(para, p, m1, m2)
+ call cachecopy(res, para, Bval(1,0), XBcoeff, RC*Pbb, Nbb, Bno)
+ end
+
+************************************************************************
+
+ subroutine XBputnocache(res, p, m1, m2)
+ implicit none
+ ComplexType res(*)
+ DVAR p, m1, m2
+
+#include "lt.h"
+
+ external XBcoeff
+
+ DVAR para(1,Pbb)
+
+#ifdef COMPLEXPARA
+ if( abs(Im(p)) .gt. 0 )
+ & print *, "Complex momenta not implemented"
+ if( abs(Im(m1)) + abs(Im(m2)) .eq. 0 ) then
+ call Bputnocache(res, p, m1, m2)
+ return
+ endif
+#endif
+
+ call XBpara(para, p, m1, m2)
+ call XBcoeff(res, para)
+ end
+
+************************************************************************
+
+ ComplexType function XB0i(i, p, m1, m2)
implicit none
integer i
DVAR p, m1, m2
#include "lt.h"
- integer XBget
+ memindex XBget
external XBget
- integer b
+ memindex b
b = XBget(p, m1, m2)
- XB0i = Bval(i,b)
+ XB0i = Bval(i+epsi,b)
end
************************************************************************
- double complex function XB0(p, m1, m2)
+ ComplexType function XB0(p, m1, m2)
implicit none
DVAR p, m1, m2
#include "lt.h"
- integer XBget
- external XBget
+ ComplexType XB0i
+ external XB0i
- XB0 = Bval(bb0,XBget(p, m1, m2))
+ XB0 = XB0i(bb0, p, m1, m2)
end
************************************************************************
- double complex function XB1(p, m1, m2)
+ ComplexType function XB1(p, m1, m2)
implicit none
DVAR p, m1, m2
#include "lt.h"
- integer XBget
- external XBget
+ ComplexType XB0i
+ external XB0i
- XB1 = Bval(bb1,XBget(p, m1, m2))
+ XB1 = XB0i(bb1, p, m1, m2)
end
************************************************************************
- double complex function XB00(p, m1, m2)
+ ComplexType function XB00(p, m1, m2)
implicit none
DVAR p, m1, m2
#include "lt.h"
- integer XBget
- external XBget
+ ComplexType XB0i
+ external XB0i
- XB00 = Bval(bb00,XBget(p, m1, m2))
+ XB00 = XB0i(bb00, p, m1, m2)
end
************************************************************************
- double complex function XB11(p, m1, m2)
+ ComplexType function XB11(p, m1, m2)
implicit none
DVAR p, m1, m2
#include "lt.h"
- integer XBget
- external XBget
+ ComplexType XB0i
+ external XB0i
- XB11 = Bval(bb11,XBget(p, m1, m2))
+ XB11 = XB0i(bb11, p, m1, m2)
end
************************************************************************
- double complex function XB001(p, m1, m2)
+ ComplexType function XB001(p, m1, m2)
implicit none
DVAR p, m1, m2
#include "lt.h"
- integer XBget
- external XBget
+ ComplexType XB0i
+ external XB0i
- XB001 = Bval(bb001,XBget(p, m1, m2))
+ XB001 = XB0i(bb001, p, m1, m2)
end
************************************************************************
- double complex function XB111(p, m1, m2)
+ ComplexType function XB111(p, m1, m2)
implicit none
DVAR p, m1, m2
#include "lt.h"
- integer XBget
- external XBget
+ ComplexType XB0i
+ external XB0i
- XB111 = Bval(bb111,XBget(p, m1, m2))
+ XB111 = XB0i(bb111, p, m1, m2)
end
************************************************************************
- double complex function XDB0(p, m1, m2)
+ ComplexType function XDB0(p, m1, m2)
implicit none
DVAR p, m1, m2
#include "lt.h"
- integer XBget
- external XBget
+ ComplexType XB0i
+ external XB0i
- XDB0 = Bval(dbb0,XBget(p, m1, m2))
+ XDB0 = XB0i(dbb0, p, m1, m2)
end
************************************************************************
- double complex function XDB1(p, m1, m2)
+ ComplexType function XDB1(p, m1, m2)
implicit none
DVAR p, m1, m2
#include "lt.h"
- integer XBget
- external XBget
+ ComplexType XB0i
+ external XB0i
- XDB1 = Bval(dbb1,XBget(p, m1, m2))
+ XDB1 = XB0i(dbb1, p, m1, m2)
end
************************************************************************
- double complex function XDB00(p, m1, m2)
+ ComplexType function XDB00(p, m1, m2)
implicit none
DVAR p, m1, m2
#include "lt.h"
- integer XBget
- external XBget
+ ComplexType XB0i
+ external XB0i
- XDB00 = Bval(dbb00,XBget(p, m1, m2))
+ XDB00 = XB0i(dbb00, p, m1, m2)
end
************************************************************************
- double complex function XDB11(p, m1, m2)
+ ComplexType function XDB11(p, m1, m2)
implicit none
DVAR p, m1, m2
#include "lt.h"
- integer XBget
- external XBget
+ ComplexType XB0i
+ external XB0i
- XDB11 = Bval(dbb11,XBget(p, m1, m2))
+ XDB11 = XB0i(dbb11, p, m1, m2)
end
+************************************************************************
+
+ ComplexType function XDB001(p, m1, m2)
+ implicit none
+ DVAR p, m1, m2
+
+#include "lt.h"
+
+ ComplexType XB0i
+ external XB0i
+
+ XDB001 = XB0i(dbb001, p, m1, m2)
+ end
+
diff --git a/Looptools/B/ffcb0.F b/Looptools/B/ffcb0.F
--- a/Looptools/B/ffcb0.F
+++ b/Looptools/B/ffcb0.F
@@ -1,835 +1,836 @@
#include "externals.h"
+#include "types.h"
* $Id: ffcb0.f,v 1.11 1996/07/18 10:49:04 gj Exp $
*###[ ffcb0:
subroutine ffcb0(cb0,cp,cma,cmb,ier)
***#[*comment:***********************************************************
* *
* calculates the the two-point function (cf 't Hooft and Veltman) *
* we include an overall factor 1/(i*pi^2) relative to FormF *
* *
* Input: cp (complex) k2, in B&D metric *
* cma (complex) mass2, re>0, im<0. *
* cmb (complex) mass2, re>0, im<0. *
* *
* Output: cb0 (complex) B0, the two-point function, *
* ier (integer) number of digits lost in calculation *
* *
* Calls: ffcb0p,ffxb0p *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE COMPLEX cb0,cp,cma,cmb
+ ComplexType cb0,cp,cma,cmb
*
* local variables
*
integer init,ithres,i,j,nschsa
logical lreal
- DOUBLE COMPLEX cmamb,cmap,cmbp,cm,c,cb0p,cqi(3),cqiqj(3,3)
- DOUBLE PRECISION absc,xp,xma,xmb,sprec,smax
+ ComplexType cmamb,cmap,cmbp,cm,c,cb0p,cqi(3),cqiqj(3,3)
+ RealType absc,xp,xma,xmb,sprec,smax
save init
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
*
* data
*
data init /0/
*
* #] declarations:
* #[ the real cases:
*
- if ( DIMAG(cma) .eq. 0 .and. DIMAG(cmb) .eq. 0 .and.
- + DIMAG(cp).eq.0 ) then
+ if ( Im(cma) .eq. 0 .and. Im(cmb) .eq. 0 .and.
+ + Im(cp).eq.0 ) then
lreal = .TRUE.
elseif ( nschem.le.4 ) then
lreal = .TRUE.
if ( init.eq.0 ) then
init = 1
print *,'ffcb0: nschem <= 4, ignoring complex masses: ',
+ nschem
endif
elseif ( nschem.le.6 ) then
if ( init.eq.0 ) then
init = 1
print *,'ffcb0: nschem = 5,6 complex masses near ',
+ 'threshold: ',nschem
endif
cqi(1) = cma
cqi(2) = cmb
cqi(3) = cp
cqiqj(1,2) = cma - cmb
cqiqj(2,1) = -cqiqj(1,2)
cqiqj(1,3) = cma - cp
cqiqj(3,1) = -cqiqj(1,3)
cqiqj(2,3) = cmb - cp
cqiqj(3,2) = -cqiqj(2,3)
cqiqj(1,1) = 0
cqiqj(2,2) = 0
cqiqj(3,3) = 0
call ffthre(ithres,cqi,cqiqj,3,1,2,3)
if ( ithres.eq.0 .or. ithres.eq.1 .and. nschem.eq.5 ) then
lreal = .TRUE.
else
lreal = .FALSE.
endif
else
lreal = .FALSE.
endif
if ( lreal ) then
- xp = DBLE(cp)
- xma = DBLE(cma)
- xmb = DBLE(cmb)
+ xp = Re(cp)
+ xma = Re(cma)
+ xmb = Re(cmb)
sprec = precx
precx = precc
call ffxb0(cb0,xp,xma,xmb,ier)
precx = sprec
if ( ldot ) then
do 120 j=1,3
do 110 i=1,3
cfpij2(i,j) = fpij2(i,j)
110 continue
120 continue
endif
return
endif
*
* #] the real cases:
* #[ get differences:
*
cmamb = cma - cmb
cmap = cma - cp
cmbp = cmb - cp
*
* #] get differences:
* #[ calculations:
*
* no more schem-checking, please...
*
nschsa = nschem
nschem = 7
call ffcb0p(cb0p,cp,cma,cmb,cmap,cmbp,cmamb,ier)
nschem = nschsa
if ( cma .eq. 0 ) then
if ( cmb .eq. 0 ) then
cm = 1
else
cm = cmb**2
endif
elseif ( cmb .eq. 0 ) then
cm = cma**2
else
cm = cma*cmb
endif
- if ( mudim .ne. 0 ) cm = cm/DBLE(mudim)**2
+ if ( mudim .ne. 0 ) cm = cm/Re(mudim)**2
if ( absc(cm) .gt. xclogm ) then
- cb0 = DBLE(delta) - cb0p - log(cm)/2
+ cb0 = Re(delta) - cb0p - log(cm)/2
smax = max(abs(delta),absc(cb0p),absc(log(cm))/2)
else
call fferr(3,ier)
- cb0 = -cb0p + DBLE(delta)
+ cb0 = -cb0p + Re(delta)
endif
* #] calculations:
*###] ffcb0:
end
*###[ ffcb0p:
subroutine ffcb0p(cb0p,cp,cma,cmb,cmap,cmbp,cmamb,ier)
***#[*comment:***********************************************************
* *
* calculates the main part of the two-point function (cf 't *
* Hooft and Veltman) for all possible cases: masses equal, *
* unequal, equal to zero, real or complex (with a negative *
* imaginary part). I think it works. *
* Has been checked against FormF for all parameter space. *
* Only problems with underflow for extreme cases. VERY OLD CODE. *
* *
* Input: cp (complex) k2, in B&D metric *
* cma (complex) mass2, re>0, im<0. *
* cmb (complex) mass2, re>0, im<0. *
* cmap/b (complex) cma/b - cp *
* cmamb (complex) cma - cmb *
* *
* Output: cb0p (complex) B0, the two-point function, *
* minus log(cm/mu), delta and the *
* factor -ipi^2. *
* ier (integer) 0=ok, 1=numerical problems, 2=error *
* *
* Calls: (z/a)log, atan. *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE COMPLEX cb0p,cp,cma,cmb,cmap,cmbp,cmamb
+ ComplexType cb0p,cp,cma,cmb,cmap,cmbp,cmamb
*
* local variables
*
integer i,j,initeq,initn1,n1,n2,nffeta,nffet1,init,
+ ithres,is1
logical lreal
- DOUBLE PRECISION xp,ax,ay,ffbnd,
+ RealType xp,ax,ay,ffbnd,
+ xprceq,bdeq01,bdeq05,bdeq11,bdeq17,bdeq25,
+ xprcn1,bdn101,bdn105,bdn110,bdn115,
+ xprnn2,bdn201,bdn205,bdn210,bdn215,
+ xpneq(30),xpnn1(30),
+ absc,sprec,xma,xmb,dmap,dmbp,dmamb,smax
- DOUBLE COMPLEX cm,cmp,cm1,cm2,cm1m2,
+ ComplexType cm,cmp,cm1,cm2,cm1m2,
+ cm1p,cm2p,cs,cs1,cs2,cx,cy,csom,clam,cslam,clogmm,
+ zfflo1,c,zm,zp,zm1,zp1,zfflog,cqi(3),
+ cqiqj(3,3),cpiDpj(3,3),ck,clamr,cslamr,zmr,zpr,zm1r,zp1r
save initeq,initn1,xpneq,xpnn1,init,
+ xprceq,bdeq01,bdeq05,bdeq11,bdeq17,bdeq25,
+ xprcn1,bdn101,bdn105,bdn110,bdn115,
+ xprnn2,bdn201,bdn205,bdn210,bdn215
*FOR ABSOFT ONLY
-* DOUBLE COMPLEX csqrt
+* ComplexType csqrt
* external csqrt
*
* common blocks
*
#include "ff.h"
*
* data
*
data xprceq /-1./
data xprcn1 /-1./
data xprnn2 /-1./
data initeq /0/
data initn1 /0/
data init /0/
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
*
* #] declarations:
* #[ fill some dotproducts:
*
call ffcot2(cpiDpj,cp,cma,cmb,cmap,cmbp,cmamb,ier)
if ( ldot ) then
do 20 i=1,3
do 10 j=1,3
cfpij2(j,i) = cpiDpj(j,i)
- fpij2(j,i) = DBLE(cpiDpj(j,i))
+ fpij2(j,i) = Re(cpiDpj(j,i))
10 continue
20 continue
endif
*
* #] fill some dotproducts:
* #[ the real cases:
*
- if ( DIMAG(cma) .eq. 0 .and. DIMAG(cmb) .eq. 0 .and.
- + DIMAG(cp).eq.0 ) then
+ if ( Im(cma) .eq. 0 .and. Im(cmb) .eq. 0 .and.
+ + Im(cp).eq.0 ) then
lreal = .TRUE.
elseif ( nschem.le.4 ) then
lreal = .TRUE.
if( init.eq.0 ) then
init = 1
print *,'ffcb0p: nschem <= 4, ignoring complex masses:',
+ nschem
endif
elseif ( nschem.le.6 ) then
if( init.eq.0 ) then
init = 1
print *,'ffcb0p: nschem = 4,6 complex masses near ',
+ 'threshold: ',nschem
endif
cqi(1) = cma
cqi(2) = cmb
cqi(3) = cp
cqiqj(1,2) = cmamb
cqiqj(2,1) = -cqiqj(1,2)
cqiqj(1,3) = cmap
cqiqj(3,1) = -cqiqj(1,3)
cqiqj(2,3) = cmbp
cqiqj(3,2) = -cqiqj(2,3)
cqiqj(1,1) = 0
cqiqj(2,2) = 0
cqiqj(3,3) = 0
call ffthre(ithres,cqi,cqiqj,3,1,2,3)
if ( ithres.eq.0 .or. ithres.eq.1 .and. nschem.eq.5 ) then
lreal = .TRUE.
else
lreal = .FALSE.
endif
else
lreal = .FALSE.
endif
if ( lreal ) then
- xp = DBLE(cp)
- xma = DBLE(cma)
- xmb = DBLE(cmb)
- dmap = DBLE(cmap)
- dmbp = DBLE(cmbp)
- dmamb = DBLE(cmamb)
+ xp = Re(cp)
+ xma = Re(cma)
+ xmb = Re(cmb)
+ dmap = Re(cmap)
+ dmbp = Re(cmbp)
+ dmamb = Re(cmamb)
sprec = precx
precx = precc
call ffxb0p(cb0p,xp,xma,xmb,dmap,dmbp,dmamb,ier)
precx = sprec
if ( ldot ) then
do 120 j=1,3
do 110 i=1,3
cfpij2(i,j) = fpij2(i,j)
110 continue
120 continue
endif
return
endif
*
* #] the real cases:
* #[ which case:
*
* sort according to the type of mass combination encountered:
* 200: one equal to zero, 300: both equal, 400: rest.
*
if ( cma .eq. 0 ) then
if ( cmb .eq. 0 ) then
goto 100
endif
cm = cmb
cmp = cmbp
goto 200
endif
if ( cmb .eq. 0 ) then
cm = cma
cmp = cmap
goto 200
endif
if ( cma .eq. cmb ) then
cm = cma
cmp = cmap
goto 300
endif
- if ( DBLE(cma) .lt. DBLE(cmb) ) then
+ if ( Re(cma) .lt. Re(cmb) ) then
cm2 = cma
cm1 = cmb
cm1m2 = -cmamb
cm1p = cmbp
cm2p = cmap
is1 = 2
else
cm1 = cma
cm2 = cmb
cm1m2 = cmamb
cm1p = cmap
cm2p = cmbp
is1 = 1
endif
goto 400
* #] which case:
* #[ both masses equal to zero:
100 continue
if ( absc(cp) .gt. xclogm ) then
- if ( DBLE(cp).gt.0 ) then
+ if ( Re(cp).gt.0 ) then
cb0p = log(cp) - c2ipi/2 - 2
else
cb0p = log(-cp) - 2
endif
else
cb0p = 0
call fferr(7,ier)
endif
return
* #] both masses equal to zero:
* #[ one mass zero:
200 continue
*
* special case cp = 0, checked 25-oct-1991
*
if ( cp .eq. 0 ) then
cb0p = -1
goto 990
endif
*
* Normal case:
*
cs1 = cp/cm
cs2 = cmp/cm
* make sure we get the right Riemann sheet!
if ( absc(cs1) .lt. xloss ) then
cs = zfflo1(cs1,ier)
- elseif ( DBLE(cs2).gt.0 ) then
+ elseif ( Re(cs2).gt.0 ) then
cs = zfflog(cs2,0,czero,ier)
else
cs = zfflog(-cs2,0,czero,ier)
cs = cs - c2ipi/2
endif
cs = -cs*cmp/cp
cb0p = cs - 2
goto 990
* #] one mass zero:
* #[ both masses equal:
300 continue
*
* Both masses are equal. Not only this speeds up things, some
* cancellations have to be avoided as well. Checked 25-oct-1991.
* -#[ taylor expansion:
*
* first this special case
*
if ( absc(cp) .lt. 8*xloss*absc(cm) ) then
*
* a Taylor expansion seems appropriate as the result will go
* as k^2 but seems to go as 1/k !!
*
* #[ data and bounds:
if ( initeq .eq. 0 ) then
initeq = 1
xpneq(1) = 1/6D0
do 1 i=2,30
- xpneq(i) = xpneq(i-1)*DBLE(i-1)/DBLE(2*(2*i+1))
+ xpneq(i) = xpneq(i-1)*Re(i-1)/Re(2*(2*i+1))
1 continue
endif
if (xprceq .ne. precc ) then
*
* calculate the boundaries for the number of terms to be
* included in the taylorexpansion
*
xprceq = precc
sprec = precx
precx = precc
bdeq01 = ffbnd(1,1,xpneq)
bdeq05 = ffbnd(1,5,xpneq)
bdeq11 = ffbnd(1,11,xpneq)
bdeq17 = ffbnd(1,17,xpneq)
bdeq25 = ffbnd(1,25,xpneq)
precx = sprec
endif
* #] data and bounds:
cx = cp/cm
ax = absc(cx)
if ( ax .gt. bdeq17 ) then
- csom = cx*(DBLE(xpneq(18)) + cx*(DBLE(xpneq(19)) +
- + cx*(DBLE(xpneq(20)) + cx*(DBLE(xpneq(21)) +
- + cx*(DBLE(xpneq(22)) + cx*(DBLE(xpneq(23)) +
- + cx*(DBLE(xpneq(24)) + cx*(DBLE(xpneq(25)) ))))))))
+ csom = cx*(Re(xpneq(18)) + cx*(Re(xpneq(19)) +
+ + cx*(Re(xpneq(20)) + cx*(Re(xpneq(21)) +
+ + cx*(Re(xpneq(22)) + cx*(Re(xpneq(23)) +
+ + cx*(Re(xpneq(24)) + cx*(Re(xpneq(25)) ))))))))
else
csom = 0
endif
if ( ax .gt. bdeq11 ) then
- csom = cx*(DBLE(xpneq(12)) + cx*(DBLE(xpneq(13)) +
- + cx*(DBLE(xpneq(14)) + cx*(DBLE(xpneq(15)) +
- + cx*(DBLE(xpneq(16)) + cx*(DBLE(xpneq(17)) + csom ))))
+ csom = cx*(Re(xpneq(12)) + cx*(Re(xpneq(13)) +
+ + cx*(Re(xpneq(14)) + cx*(Re(xpneq(15)) +
+ + cx*(Re(xpneq(16)) + cx*(Re(xpneq(17)) + csom ))))
+ ))
endif
if ( ax .gt. bdeq05 ) then
- csom = cx*(DBLE(xpneq(6)) + cx*(DBLE(xpneq(7)) +
- + cx*(DBLE(xpneq(8)) + cx*(DBLE(xpneq(9)) +
- + cx*(DBLE(xpneq(10)) + cx*(DBLE(xpneq(11)) + csom ))))))
+ csom = cx*(Re(xpneq(6)) + cx*(Re(xpneq(7)) +
+ + cx*(Re(xpneq(8)) + cx*(Re(xpneq(9)) +
+ + cx*(Re(xpneq(10)) + cx*(Re(xpneq(11)) + csom ))))))
endif
if ( ax .gt. bdeq01 ) then
- csom = cx*(DBLE(xpneq(2)) + cx*(DBLE(xpneq(3)) +
- + cx*(DBLE(xpneq(4)) + cx*(DBLE(xpneq(5)) + csom ))))
+ csom = cx*(Re(xpneq(2)) + cx*(Re(xpneq(3)) +
+ + cx*(Re(xpneq(4)) + cx*(Re(xpneq(5)) + csom ))))
endif
- cb0p = -cx*(DBLE(xpneq(1))+csom)
+ cb0p = -cx*(Re(xpneq(1))+csom)
goto 990
endif
* -#] taylor expansion:
* -#[ normal case:
*
* normal case. first determine if the arguments of the logarithm
* has positive real part: (we assume Re(cm) > Im(cm) )
*
call ffclmb(clam,-cp,-cm,-cm,cmp,cmp,czero)
cslam = sqrt(clam)
call ffcoot(zm,zp,cone,chalf,cm/cp,cslam/(2*cp),ier)
cs1 = zp/zm
if ( absc(cs1-1) .lt. xloss ) then
* In this case a quicker and more accurate way is to
* calculate log(1-cx).
cs2 = cp - cslam
if ( absc(cs2) .lt. xloss*absc(cp) ) then
cs2 = -cslam*(cp+cslam)/(4*cp*cm)
else
cs2 = -2*cslam/cs2
endif
cs = zfflo1(cs2/(2*cm),ier)
else
* finally the normal case
cs = zfflog(cs1,0,czero,ier)
endif
cs = cslam*cs/cp
cb0p = cs - 2
*
* eta terms
*
n1 = nffet1(zp,1/zm,cs1,ier)
- if ( DIMAG(cp).eq.0 ) then
+ if ( Im(cp).eq.0 ) then
n2 = nffet1(-zp,-1/zm,cs1,ier)
else
* use the onshell expression to get the correct continuation
- ck = DBLE(cp)
+ ck = Re(cp)
call ffclmb(clamr,-ck,-cm,-cm,cm-ck,cm-ck,czero)
cslamr = sqrt(clamr)
call ffcoot(zmr,zpr,cone,chalf,cm/ck,cslamr/(2*ck),ier)
if ( absc(zm-zmr)+absc(zp-zpr).gt.absc(zm-zpr)+absc(zp-zmr)
+ ) then
cs1 = zmr
zmr = zpr
zpr = cs1
endif
- if ( DIMAG(zmr).eq.0 .or. DIMAG(zpr).eq.0 ) then
- if ( DBLE(zpr).gt.DBLE(zmr) ) then
+ if ( Im(zmr).eq.0 .or. Im(zpr).eq.0 ) then
+ if ( Re(zpr).gt.Re(zmr) ) then
n2 = +1
else
n2 = -1
endif
else
n2 = nffeta(-zpr,-1/zmr,ier)
endif
endif
if ( n1+n2 .ne. 0 )
+ cb0p = cb0p - cslam*c2ipi*(n1+n2)/(2*cp)
* also superfluous - just to make sure
goto 990
* -#] normal case:
*
* #] both masses equal:
* #[ unequal nonzero masses:
400 continue
* -#[ get log(xm2/xm1):
cx = cm2/cm1
c = cx-1
if ( 1/absc(cx) .lt. xclogm ) then
call fferr(6,ier)
clogmm = 0
elseif ( absc(c) .lt. xloss ) then
clogmm = zfflo1(cm1m2/cm1,ier)
else
clogmm = log(cx)
endif
* -#] get log(xm2/xm1):
* -#[ cp = 0:
*
* first a special case
*
if ( cp .eq. 0 ) then
cs2 = ((cm2+cm1) / cm1m2)*clogmm
* save the factor 1/2 for the end
cs = - cs2 - 2
if ( absc(cs) .lt. xloss*2 ) then
* Taylor expansions: choose which one
cx = cm1m2/cm1
ax = absc(cx)
if ( ax .lt. .15 .or. precc .gt. 1.E-8 .and. ax
+ .lt. .3 ) then
* #[ taylor 1:
*
* This is the simple Taylor expansion 'n1'
*
*--#[ data and bounds:
* get the coefficients of the taylor expansion
if ( initn1 .eq. 0 ) then
initn1 = 1
do 410 i = 1,30
- 410 xpnn1(i)=DBLE(i)/DBLE((i+1)*(i+2))
+ 410 xpnn1(i)=Re(i)/Re((i+1)*(i+2))
endif
* determine the boundaries for 1,5,10,15 terms
if ( xprcn1 .ne. precc ) then
xprcn1 = precc
sprec = precx
precx = precc
bdn101 = ffbnd(1,1,xpnn1)
bdn105 = ffbnd(1,5,xpnn1)
bdn110 = ffbnd(1,10,xpnn1)
bdn115 = ffbnd(1,15,xpnn1)
precx = sprec
endif
*--#] data and bounds:
* calculate:
if ( ax .gt. bdn110 ) then
- cs = cx*(DBLE(xpnn1(11)) + cx*(DBLE(xpnn1(12))
- + + cx*(DBLE(xpnn1(13)) + cx*(DBLE(xpnn1(14))
- + + cx*(DBLE(xpnn1(15))) ))))
+ cs = cx*(Re(xpnn1(11)) + cx*(Re(xpnn1(12))
+ + + cx*(Re(xpnn1(13)) + cx*(Re(xpnn1(14))
+ + + cx*(Re(xpnn1(15))) ))))
else
cs = 0
endif
if ( ax .gt. bdn105 ) then
- cs = cx*(DBLE(xpnn1(6)) + cx*(DBLE(xpnn1(7)) +
- + cx*(DBLE(xpnn1(8)) + cx*(DBLE(xpnn1(9)) +
- + cx*(DBLE(xpnn1(10)) + cs)))))
+ cs = cx*(Re(xpnn1(6)) + cx*(Re(xpnn1(7)) +
+ + cx*(Re(xpnn1(8)) + cx*(Re(xpnn1(9)) +
+ + cx*(Re(xpnn1(10)) + cs)))))
endif
if ( ax .gt. bdn101 ) then
- cs = cx*(DBLE(xpnn1(2)) + cx*(DBLE(xpnn1(3)) +
- + cx*(DBLE(xpnn1(4)) + cx*(DBLE(xpnn1(5)) +
+ cs = cx*(Re(xpnn1(2)) + cx*(Re(xpnn1(3)) +
+ + cx*(Re(xpnn1(4)) + cx*(Re(xpnn1(5)) +
+ cs))))
endif
- cs = cx*cx*(DBLE(xpnn1(1)) + cs)
+ cs = cx*cx*(Re(xpnn1(1)) + cs)
* #] taylor 1:
else
* #[ taylor 2:
*
* This is the more complicated exponential Taylor
* expansion 'n2'
*
* #[ bounds:
* determine the boundaries for 1,5,10,15 terms for this
* Taylor expansion (starting at i=4)
*
if ( xprnn2 .ne. precc ) then
xprnn2 = precc
sprec = precx
precx = precc
bdn201 = ffbnd(4,1,xinfac)
bdn205 = ffbnd(4,5,xinfac)
bdn210 = ffbnd(4,10,xinfac)
bdn215 = ffbnd(4,15,xinfac)
precx = sprec
endif
* #] bounds:
* calculate:
cy = 2*cx/(2-cx)
ay = absc(cy)
if ( ay .gt. bdn210 ) then
- cs = cy*(DBLE(xinfac(14)) + cy*(DBLE(xinfac(15))
- + + cy*(DBLE(xinfac(16)) + cy*(DBLE(xinfac(17))
- + + cy*(DBLE(xinfac(18)))))))
+ cs = cy*(Re(xinfac(14)) + cy*(Re(xinfac(15))
+ + + cy*(Re(xinfac(16)) + cy*(Re(xinfac(17))
+ + + cy*(Re(xinfac(18)))))))
else
cs = 0
endif
if ( ay .gt. bdn205 ) then
- cs = cy*(DBLE(xinfac(9)) + cy*(DBLE(xinfac(10))
- + + cy*(DBLE(xinfac(11)) + cy*(DBLE(xinfac(12))
- + + cy*(DBLE(xinfac(13)) + cs)))))
+ cs = cy*(Re(xinfac(9)) + cy*(Re(xinfac(10))
+ + + cy*(Re(xinfac(11)) + cy*(Re(xinfac(12))
+ + + cy*(Re(xinfac(13)) + cs)))))
endif
if ( ay .gt. bdn201 ) then
- cs = cy*(DBLE(xinfac(5)) + cy*(DBLE(xinfac(6))
- + + cy*(DBLE(xinfac(7)) + cy*(DBLE(xinfac(8))
+ cs = cy*(Re(xinfac(5)) + cy*(Re(xinfac(6))
+ + + cy*(Re(xinfac(7)) + cy*(Re(xinfac(8))
+ + cs))))
endif
- cs = (1-cx)*cy**4 * (DBLE(xinfac(4)) + cs)
+ cs = (1-cx)*cy**4 * (Re(xinfac(4)) + cs)
cs = cx*cy**2*(1+cy)/12 - cs
cs = - 2*zfflo1(cs,ier)/cy
* #] taylor 2:
endif
endif
cb0p = cs/2
goto 990
endif
* -#] cp = 0:
* -#[ normal case:
*
* (programmed anew 28-oct-1991)
*
call ffclmb(clam,cm1,cm2,cp,cm1m2,cm1p,cm2p)
cslam = sqrt(clam)
if ( is1.eq.1 ) then
cs = +cpiDpj(2,3)
else
cs = -cpiDpj(1,3)
endif
call ffcoot(zm,zp,cp,cs,cm2,cslam/2,ier)
zm1 = 1-zm
zp1 = 1-zp
if ( absc(zm1) .lt. xloss .or. absc(zp1) .lt. xloss ) then
if ( is1.eq.1 ) then
cs = -cpiDpj(1,3)
else
cs = +cpiDpj(2,3)
endif
call ffcoot(zp1,zm1,cp,cs,cm1,cslam/2,ier)
- if ( abs(DIMAG(zm)) .lt. abs(DIMAG(zm1)) ) then
- zm = DCMPLX(DBLE(zm),-DIMAG(zm1))
+ if ( abs(Im(zm)) .lt. abs(Im(zm1)) ) then
+ zm = ToComplex(Re(zm),-Im(zm1))
else
- zm1 = DCMPLX(DBLE(zm1),-DIMAG(zm))
+ zm1 = ToComplex(Re(zm1),-Im(zm))
endif
- if ( abs(DIMAG(zp)) .lt. abs(DIMAG(zp1)) ) then
- zp = DCMPLX(DBLE(zp),-DIMAG(zp1))
+ if ( abs(Im(zp)) .lt. abs(Im(zp1)) ) then
+ zp = ToComplex(Re(zp),-Im(zp1))
else
- zp1 = DCMPLX(DBLE(zp1),-DIMAG(zp))
+ zp1 = ToComplex(Re(zp1),-Im(zp))
endif
endif
- if ( DIMAG(cp).ne.0 ) then
+ if ( Im(cp).ne.0 ) then
* compute roots for Im(cp).eq.0 for continuation terms.
- ck = DBLE(cp)
+ ck = Re(cp)
call ffclmb(clamr,cm1,cm2,ck,cm1m2,cm1-ck,cm2-ck)
cslamr = sqrt(clamr)
if ( absc(cslamr-cslam).gt.absc(cslamr+cslam) )
+ cslamr = -cslamr
cs = (cm2-cm1+ck)/2
call ffcoot(zmr,zpr,ck,cs,cm2,cslamr/2,ier)
zm1r = 1-zmr
zp1r = 1-zpr
if ( absc(zm1r) .lt. xloss .or. absc(zp1r) .lt. xloss ) then
cs = -(cm2-cm1-ck)/2
call ffcoot(zp1r,zm1r,ck,cs,cm1,cslamr/2,ier)
- if ( abs(DIMAG(zmr)) .lt. abs(DIMAG(zm1r)) ) then
- zmr = DCMPLX(DBLE(zmr),-DIMAG(zm1r))
+ if ( abs(Im(zmr)) .lt. abs(Im(zm1r)) ) then
+ zmr = ToComplex(Re(zmr),-Im(zm1r))
else
- zm1r = DCMPLX(DBLE(zm1r),-DIMAG(zmr))
+ zm1r = ToComplex(Re(zm1r),-Im(zmr))
endif
- if ( abs(DIMAG(zpr)) .lt. abs(DIMAG(zp1r)) ) then
- zpr = DCMPLX(DBLE(zpr),-DIMAG(zp1r))
+ if ( abs(Im(zpr)) .lt. abs(Im(zp1r)) ) then
+ zpr = ToComplex(Re(zpr),-Im(zp1r))
else
- zp1r = DCMPLX(DBLE(zp1r),-DIMAG(zpr))
+ zp1r = ToComplex(Re(zp1r),-Im(zpr))
endif
endif
else
zmr = zm
zm1r = zm1
zpr = zp
zp1r = zp1
endif
call ffc1lg(cs1,zm,zm1,zmr,zm1r,-1,ier)
call ffc1lg(cs2,zp,zp1,zpr,zp1r,+1,ier)
cb0p = -clogmm/2 + cs1 + cs2
smax = max(absc(clogmm)/2,absc(cs1),absc(cs2))
if ( absc(cb0p) .lt. xloss*smax ) then
call ffwarn(7,ier,absc(cb0p),smax)
endif
goto 990
* -#] normal case:
* #] unequal nonzero masses:
* #[ debug:
990 continue
* #] debug:
*###] ffcb0p:
end
*###[ ffc1lg:
subroutine ffc1lg(cs,z,z1,zr,z1r,is,ier)
***#[*comment:***********************************************************
* *
* Calculate the potentially unstable combination -1-z*log(1-1/z) *
* = sum_{n=1} 1/(n+1) z^{-n}. *
* *
* Input z,z1 complex root, z1=1-z *
* zr,z1r complex root for Im(p^2)=0, z1r=1-zr *
* is integer -1: roots are z-, +1: z+ *
* *
* Output cs complex see above *
* ier integer usual error flag *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer is,ier
- DOUBLE COMPLEX cs,z,z1,zr,z1r
+ ComplexType cs,z,z1,zr,z1r
*
* local variables
*
- DOUBLE PRECISION absc
- DOUBLE COMPLEX c,zfflog
+ RealType absc
+ ComplexType c,zfflog
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
*
* #] declarations:
* #[ work:
if ( 1 .lt. xclogm*absc(z) ) then
cs = 0
elseif ( 1 .lt. precc*absc(z) ) then
cs = 1/(2*z)
elseif ( 1 .gt. 2*xloss*absc(z) ) then
*
* normal case
*
cs = -1 - z*zfflog(-z1/z,0,czero,ier)
*
* check analytical continuation for Im(p^2) -> 0
*
if ( z.ne.zr .or. z1.ne.z1r ) then
c = -z1r/zr
- if ( DBLE(c).lt.0 ) then
+ if ( Re(c).lt.0 ) then
* check whetehr we chose the correct continuation
- if ( (DIMAG(c).gt.0 .or. DIMAG(c).eq.0 .and.
- + is.eq.+1) .and. DIMAG(-z1/z).lt.0 ) then
+ if ( (Im(c).gt.0 .or. Im(c).eq.0 .and.
+ + is.eq.+1) .and. Im(-z1/z).lt.0 ) then
cs = cs - c2ipi*z
- elseif ( (DIMAG(c).lt.0 .or. DIMAG(c).eq.0 .and.
- + is.eq.-1) .and. DIMAG(-z1/z).gt.0 ) then
+ elseif ( (Im(c).lt.0 .or. Im(c).eq.0 .and.
+ + is.eq.-1) .and. Im(-z1/z).gt.0 ) then
cs = cs + c2ipi*z
endif
endif
endif
if ( absc(cs) .lt. xloss ) call ffwarn(8,ier,absc(cs),1D0)
else
*
* Taylor expansion
*
call ffcayl(cs,1/z,xninv(2),29,ier)
endif
* #] work:
*###] ffc1lg:
end
*###[ ffcot2:
subroutine ffcot2(cpiDpj,cp,cma,cmb,cmap,cmbp,cmamb,ier)
***#[*comment:***********************************************************
* *
* Store the 3 dotproducts in the common block ffdot. *
* *
* Input: see ffxc0p *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE COMPLEX cpiDpj(3,3),cp,cma,cmb,cmap,cmbp,cmamb
+ ComplexType cpiDpj(3,3),cp,cma,cmb,cmap,cmbp,cmamb
*
* local variables
*
integer ier1
- DOUBLE PRECISION absc,xmax
- DOUBLE COMPLEX c
+ RealType absc,xmax
+ ComplexType c
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ work:
ier1 = ier
cpiDpj(1,1) = cma
cpiDpj(2,2) = cmb
cpiDpj(3,3) = cp
if ( absc(cmap) .lt. absc(cmbp) ) then
cpiDpj(1,2) = (cmap + cmb)/2
else
cpiDpj(1,2) = (cmbp + cma)/2
endif
cpiDpj(2,1) = cpiDpj(1,2)
xmax = min(absc(cma),absc(cmb))/2
if ( absc(cmamb) .lt. absc(cmbp) ) then
cpiDpj(1,3) = (-cmamb - cp)/2
else
cpiDpj(1,3) = (cmbp - cma)/2
endif
cpiDpj(3,1) = cpiDpj(1,3)
xmax = min(absc(cma),absc(cp))/2
if ( absc(cmamb) .lt. absc(cmap) ) then
cpiDpj(2,3) = (-cmamb + cp)/2
else
cpiDpj(2,3) = (-cmap + cmb)/2
endif
cpiDpj(3,2) = cpiDpj(2,3)
xmax = min(absc(cmb),absc(cp))/2
ier = ier1
* #] work:
*###] ffcot2:
end
diff --git a/Looptools/B/ffcb1.F b/Looptools/B/ffcb1.F
--- a/Looptools/B/ffcb1.F
+++ b/Looptools/B/ffcb1.F
@@ -1,359 +1,360 @@
#include "externals.h"
+#include "types.h"
*###[ ffcb1:
subroutine ffcb1(cb1,cb0,ca0i,xp,xm1,xm2,piDpj,ier)
***#[*comment:***********************************************************
* *
* Calculate 1 / d^n Q Q(mu) *
* ------ | ------------------------ = B1*p(mu) *
* i pi^2 / (Q^2-m1^2)((Q+p)^2-m2^2) *
* *
* Input: cb0 complex scalar twopoint function *
* ca0i(2) complex scalar onepoint function with *
* m1,m2 *
* xp complex p.p in B&D metric *
* xm1,2 complex m_1^2,m_2^2 *
* piDpj(3,3) complex dotproducts between s1,s2,p *
* ier integer digits lost so far *
* Output: cb1 complex B1 *
* ier integer digits lost *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE COMPLEX xp,xm1,xm2,piDpj(3,3)
- DOUBLE COMPLEX cb1,cb0,ca0i(2)
+ ComplexType xp,xm1,xm2,piDpj(3,3)
+ ComplexType cb1,cb0,ca0i(2)
*
* local variables
*
integer ier0,i,j
- DOUBLE COMPLEX dm1p,dm2p,dm1m2
- DOUBLE PRECISION rm1,rm2,rp,rpiDpj(3,3),sprec
+ ComplexType dm1p,dm2p,dm1m2
+ RealType rm1,rm2,rp,rpiDpj(3,3),sprec
*
* common blocks
*
#include "ff.h"
*
* #] declarations:
* #[ real case:
- if ( DIMAG(xm1).eq.0 .and. DIMAG(xm2).eq.0 ) then
- rm1 = DBLE(xm1)
- rm2 = DBLE(xm2)
- rp = DBLE(xp)
+ if ( Im(xm1).eq.0 .and. Im(xm2).eq.0 ) then
+ rm1 = Re(xm1)
+ rm2 = Re(xm2)
+ rp = Re(xp)
do 20 j=1,3
do 10 i=1,3
- rpiDpj(i,j) = DBLE(piDpj(i,j))
+ rpiDpj(i,j) = Re(piDpj(i,j))
10 continue
20 continue
sprec = precx
precx = precc
call ffxb1(cb1,cb0,ca0i,rp,rm1,rm2,rpiDpj,ier)
precx = sprec
return
endif
* #] real case:
* #[ get differences:
ier0 = 0
dm1m2 = xm1 - xm2
dm1p = xm1 - xp
dm2p = xm2 - xp
* #] get differences:
* #[ call ffcb1a:
call ffcb1a(cb1,cb0,ca0i,xp,xm1,xm2,dm1p,dm2p,dm1m2,piDpj,ier)
* #] call ffcb1a:
*###] ffcb1:
end
*###[ ffcb1a:
subroutine ffcb1a(cb1,cb0,ca0i,xp,xm1,xm2,dm1p,dm2p,dm1m2,piDpj,
+ ier)
***#[*comment:***********************************************************
* *
* Calculate 1 / d^n Q Q(mu) *
* ------ | ------------------------ = B1*p(mu) *
* i pi^2 / (Q^2-m1^2)((Q+p)^2-m2^2) *
* *
* Input: cb0 complex scalar twopoint function *
* ca0i(2) complex scalar onepoint function with *
* m1,m2 *
* xp complex p.p in B&D metric *
* xm1,2 complex m_1^2,m_2^2 *
* piDpj(3,3) complex dotproducts between s1,s2,p *
* ier integer digits lost so far *
* Output: cb1 complex B1 *
* ier integer digits lost *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE COMPLEX xp,xm1,xm2,dm1p,dm2p,dm1m2,piDpj(3,3)
- DOUBLE COMPLEX cb1,cb0,ca0i(2)
+ ComplexType xp,xm1,xm2,dm1p,dm2p,dm1m2,piDpj(3,3)
+ ComplexType cb1,cb0,ca0i(2)
*
* local variables
*
integer i,j,ithres,init
logical lneg,lreal
- DOUBLE PRECISION xmax,absc,bnd101,bnd105,bnd110,bnd115,ax,cprec,
+ RealType xmax,absc,bnd101,bnd105,bnd110,bnd115,ax,cprec,
+ xprec,xmxp
- DOUBLE COMPLEX s,s1,h,slam,xma,xmb,x,small,dmbma,clam,clogm,
+ ComplexType s,s1,h,slam,xma,xmb,x,small,dmbma,clam,clogm,
+ ts2Dp,xlo3,xlogm,cqiqj(3,3),cqi(3)
- DOUBLE COMPLEX cs(5),cc,csom
- DOUBLE PRECISION ffbnd
- DOUBLE COMPLEX zfflo1,zfflo3
- DOUBLE PRECISION rm1,rm2,rp,rm1m2,rm1p,rm2p,rpiDpj(3,3),sprec
+ ComplexType cs(5),cc,csom
+ RealType ffbnd
+ ComplexType zfflo1,zfflo3
+ RealType rm1,rm2,rp,rm1m2,rm1p,rm2p,rpiDpj(3,3),sprec
save cprec,bnd101,bnd105,bnd110,bnd115,init
*FOR ABSOFT ONLY
-* DOUBLE COMPLEX csqrt
+* ComplexType csqrt
* external csqrt
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(cc) = abs(DBLE(cc)) + abs(DIMAG(cc))
+ absc(cc) = abs(Re(cc)) + abs(Im(cc))
*
* data
*
data cprec /0./
*
* #] declarations:
* #[ the real cases:
*
- if ( DIMAG(xm1) .eq. 0 .and. DIMAG(xm2) .eq. 0 ) then
+ if ( Im(xm1) .eq. 0 .and. Im(xm2) .eq. 0 ) then
lreal = .TRUE.
elseif ( nschem.le.4 ) then
lreal = .TRUE.
if ( init.eq.0 ) then
init = 1
print *,'ffcb1a: nschem <= 4, ignoring complex masses:',
+ nschem
endif
elseif ( nschem.le.6 ) then
if ( init.eq.0 ) then
init = 1
print *,'ffcb1a: nschem = 5,6 complex masses near ',
+ 'threshold: ',nschem
endif
cqi(1) = xm1
cqi(2) = xm2
cqi(3) = xp
cqiqj(1,2) = dm1m2
cqiqj(2,1) = -cqiqj(1,2)
cqiqj(1,3) = dm1p
cqiqj(3,1) = -cqiqj(1,3)
cqiqj(2,3) = dm2p
cqiqj(3,2) = -cqiqj(2,3)
cqiqj(1,1) = 0
cqiqj(2,2) = 0
cqiqj(3,3) = 0
call ffthre(ithres,cqi,cqiqj,3,1,2,3)
if ( ithres.eq.0 .or. ithres.eq.1 .and. nschem.eq.5 ) then
lreal = .TRUE.
else
lreal = .FALSE.
endif
else
lreal = .FALSE.
endif
if ( lreal ) then
- rm1 = DBLE(xm1)
- rm2 = DBLE(xm2)
- rp = DBLE(xp)
- rm1p = DBLE(dm1p)
- rm2p = DBLE(dm2p)
- rm1m2 = DBLE(dm1m2)
+ rm1 = Re(xm1)
+ rm2 = Re(xm2)
+ rp = Re(xp)
+ rm1p = Re(dm1p)
+ rm2p = Re(dm2p)
+ rm1m2 = Re(dm1m2)
do 20 j=1,3
do 10 i=1,3
- rpiDpj(i,j) = DBLE(piDpj(i,j))
+ rpiDpj(i,j) = Re(piDpj(i,j))
10 continue
20 continue
sprec = precx
precx = precc
call ffxb1a(cb1,cb0,ca0i,rp,rm1,rm2,rm1m2,rpiDpj,ier)
precx = sprec
return
endif
* #] the real cases:
* #[ p^2 != 0:
- if ( DBLE(xp) .ne. 0 ) then
+ if ( Re(xp) .ne. 0 ) then
* #[ normal case:
if ( dm1m2 .ne. 0 ) then
cs(1) = -ca0i(2)
cs(2) = +ca0i(1)
else
cs(1) = 0
cs(2) = 0
endif
cs(3) = +2*piDpj(1,3)*cb0
cb1 = cs(1) + cs(2) + cs(3)
xmax = max(absc(cs(2)),absc(cs(3)))
if ( absc(cb1) .ge. xloss*xmax ) goto 110
* #] normal case:
* #[ almost equal masses:
if ( absc(dm1m2) .le. xloss*absc(xm1) ) then
cs(2) = dm1m2/xm1*cs(2)
cs(1) = -xm2*zfflo1(-dm1m2/xm2,ier)
cb1 = cs(1) + cs(2) + cs(3)
xmax = max(absc(cs(2)),absc(cs(3)))
if ( absc(cb1) .ge. xloss*xmax ) goto 110
* for the perfectionist (not me (today)):
* if d0=0 and mu~m1(~m2), then the terms of order
* (m1^2-m2^2) also cancel. To patch this I need d0 and mu
endif
* #] almost equal masses:
* #[ p2 -> 0:
if ( xloss**2*max(absc(xm1),absc(xm2)) .gt. absc(xp) ) then
- if ( DBLE(xm2).gt.DBLE(xm1) ) then
+ if ( Re(xm2).gt.Re(xm1) ) then
xma = xm1
xmb = xm2
dmbma = -dm1m2
ts2Dp = +2*piDpj(2,3)
lneg = .FALSE.
else
xma = xm2
xmb = xm1
dmbma = +dm1m2
ts2Dp = -2*piDpj(1,3)
lneg = .TRUE.
endif
else
goto 100
endif
*
* We found a situation in which p2 is much smaller than
* the masses.
*
if ( xma.eq.0 ) then
clogm = 1
elseif ( absc(dmbma) .gt. xloss*absc(xmb) ) then
clogm = log(xmb/xma)
else
clogm = zfflo1(-dmbma/xma,ier)
endif
clam = (dmbma-xp)**2 - 4*xma*xp
slam = sqrt(clam)
small = xp*(-2*(xma+xmb) + xp)/(slam+dmbma)
cs(1) = clogm*xma*(4*xmb*(small-xp) + (small-xp)**2)/(2*
+ (slam+dmbma)*(slam+2*piDpj(1,2)))
if ( cprec.ne.precc ) then
cprec = precc
xprec = precx
precx = precc
bnd101 = ffbnd(2,1,xinfac)
bnd105 = ffbnd(2,5,xinfac)
bnd110 = ffbnd(2,10,xinfac)
bnd115 = ffbnd(2,15,xinfac)
precx = xprec
endif
x = xp/slam
ax = absc(x)
if ( ax.gt.bnd110 ) then
- s = x*(DBLE(xinfac(12)) + x*(DBLE(xinfac(13)) +
- + x*(DBLE(xinfac(14)) + x*(DBLE(xinfac(15)) +
- + x*(DBLE(xinfac(16)) )))))
+ s = x*(Re(xinfac(12)) + x*(Re(xinfac(13)) +
+ + x*(Re(xinfac(14)) + x*(Re(xinfac(15)) +
+ + x*(Re(xinfac(16)) )))))
else
s = 0
endif
if ( ax.gt.bnd105 ) then
- s = x*(DBLE(xinfac(7)) + x*(DBLE(xinfac(8)) +
- + x*(DBLE(xinfac(9)) + x*(DBLE(xinfac(10)) +
- + x*(DBLE(xinfac(11) + s) )))))
+ s = x*(Re(xinfac(7)) + x*(Re(xinfac(8)) +
+ + x*(Re(xinfac(9)) + x*(Re(xinfac(10)) +
+ + x*(Re(xinfac(11) + s) )))))
endif
if ( ax.gt.bnd101) then
- s = x*(DBLE(xinfac(3)) + x*(DBLE(xinfac(4)) +
- + x*(DBLE(xinfac(5)) + x*(DBLE(xinfac(6)) + s))))
+ s = x*(Re(xinfac(3)) + x*(Re(xinfac(4)) +
+ + x*(Re(xinfac(5)) + x*(Re(xinfac(6)) + s))))
endif
s = x**2*(.5D0 + s)
s1 = 2*xp/(ts2Dp + slam)*(s + x)
h = -4*xp**2*xmb/(slam*(slam+ts2Dp)**2) - s + s1
if ( absc(h) .lt. .1 ) then
cs(2) = dmbma*slam/xp*zfflo1(h,ier)
else
print *,'ffcb1: warning: I thought this was small: ',h
print *,' cp,cma,cmb = ',xp,xma,xmb
cs(2) = dmbma*slam/xp*log(1-h)
*** goto 100
endif
if ( lneg ) then
cs(1) = -cs(1)
cs(2) = -cs(2)
endif
cs(3) = -xp*cb0
cb1 = cs(1) + cs(2) + cs(3)
xmax = max(absc(cs(2)),absc(cs(3)))
if ( absc(cb1) .gt. xloss*xmax) goto 110
* #] p2 -> 0:
* #[ give up:
*
* give up...
*
100 continue
110 continue
* #] give up:
cb1 = cb1/(2*xp)
* #] p^2 != 0:
* #[ p^2=0, m1 != m2:
elseif ( dm1m2 .ne. 0 ) then
cs(1) = +xm2/(2*dm1m2**2)*(ca0i(2)+xm2/2)
cs(2) = -xm1/(2*dm1m2**2)*(ca0i(1)+xm1/2)
cs(3) = +ca0i(2)/dm1m2
cb1 = cs(1) + cs(2) + cs(3)
xmax = max(absc(cs(1)),absc(cs(2)),absc(cs(3)))
if ( absc(cb1).ge.xloss**2*xmax ) goto 120
*
* m1 ~ m2, see b21.frm
*
if ( absc(dm1m2).lt.xloss*absc(xm1) ) then
xlogm = zfflo1(dm1m2/xm1,ier)
else
xlogm = log(xm2/xm1)
endif
cs(1) = -(xm1/dm1m2)/2
cs(2) = -xlogm/2*(xm1/dm1m2)**2
- cs(3) = +1/DBLE(4) - ca0i(1)/(2*xm1)
+ cs(3) = +1/Re(4) - ca0i(1)/(2*xm1)
cs(4) = xlogm/2
csom = cs(1) + cs(2) + cs(3) + cs(4)
xmxp = max(absc(cs(2)),absc(cs(3)),absc(cs(4)))
if ( xmxp.lt.xmax ) then
xmax = xmxp
cb1 = csom
if ( absc(cb1).gt.xloss**2*xmax ) goto 120
endif
*
* better
*
xlo3 = zfflo3(dm1m2/xm1,ier)
cs(1) = -(dm1m2/xm1)**2/4
cs(2) = -(dm1m2/xm1)/2
cs(3) = -xlo3/(dm1m2/xm1)**2/2
cs(4) = xlo3/2
- cs(5) = 1/DBLE(2) - ca0i(1)/(2*xm1)
+ cs(5) = 1/Re(2) - ca0i(1)/(2*xm1)
csom = cs(1) + cs(2) + cs(3) + cs(4) + cs(5)
xmxp = max(absc(cs(2)),absc(cs(3)),absc(cs(4)),absc(cs(5)))
if ( xmxp.lt.xmax ) then
xmax = xmxp
cb1 = csom
if ( absc(cb1).gt.xloss**2*xmax ) goto 120
endif
*
* give up
*
120 continue
* #] p^2=0, m1 != m2:
* #[ p^2=0, m1 == m2:
else
cb1 = -cb0/2
endif
* #] p^2=0, m1 == m2:
*###] ffcb1a:
end
diff --git a/Looptools/B/ffcb2p.F b/Looptools/B/ffcb2p.F
--- a/Looptools/B/ffcb2p.F
+++ b/Looptools/B/ffcb2p.F
@@ -1,432 +1,433 @@
#include "externals.h"
+#include "types.h"
*###[ ffcb2p:
subroutine ffcb2p(cb2i,cb1,cb0,ca0i,cp,xm1,xm2,piDpj,ier)
***#[*comment:***********************************************************
* *
* Compute the PV B2, the coefficients of p(mu)p(nu) and g(mu,nu) *
* of 1/(ipi^2)\int d^nQ Q(mu)Q(nu)/(Q^2-m_1^2)/((Q+p)^2-m_2^2) *
* originally based on aaxbx by Andre Aeppli. *
* *
* Input: cb1 complex vector two point function *
* cb0 complex scalar two point function *
* ca0i(2) complex scalar onepoint function with *
* m1,m2 *
* cp complex p.p in B&D metric *
* xm1,2 complex m_1^2,m_2^2 *
* piDpj(3,3) complex dotproducts between s1,s2,p *
* ier integer digits lost so far *
* *
* Output: cb2i(2) complex B21,B22: coeffs of p*p, g in B2 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE COMPLEX cp,xm1,xm2,piDpj(3,3)
- DOUBLE COMPLEX cb2i(2),cb1,cb0,ca0i(2)
- DOUBLE PRECISION rm1,rm2,rp,rpiDpj(3,3),sprec
+ ComplexType cp,xm1,xm2,piDpj(3,3)
+ ComplexType cb2i(2),cb1,cb0,ca0i(2)
+ RealType rm1,rm2,rp,rpiDpj(3,3),sprec
*
* local variables
*
integer i,j
- DOUBLE COMPLEX dm1p,dm2p,dm1m2
+ ComplexType dm1p,dm2p,dm1m2
*
* common blocks
*
*
#include "ff.h"
*
* #] declarations:
* #[ real case:
- if ( DIMAG(xm1).eq.0 .and. DIMAG(xm2).eq.0 ) then
- rm1 = DBLE(xm1)
- rm2 = DBLE(xm2)
- rp = DBLE(cp)
+ if ( Im(xm1).eq.0 .and. Im(xm2).eq.0 ) then
+ rm1 = Re(xm1)
+ rm2 = Re(xm2)
+ rp = Re(cp)
do 20 j=1,3
do 10 i=1,3
- rpiDpj(i,j) = DBLE(piDpj(i,j))
+ rpiDpj(i,j) = Re(piDpj(i,j))
10 continue
20 continue
sprec = precx
precx = precc
call ffxb2p(cb2i,cb1,cb0,ca0i,rp,rm1,rm2,rpiDpj,ier)
precx = sprec
return
endif
* #] real case:
* #[ work:
*
dm1p = xm1 - cp
dm2p = xm2 - cp
dm1m2= xm1 - xm2
call ffcb2q(cb2i,cb1,cb0,ca0i,cp,xm1,xm2,dm1p,dm2p,dm1m2,
+ piDpj,ier)
*
* #] work:
*###] ffcb2p:
end
*###[ ffcb2q:
subroutine ffcb2q(cb2i,cb1,cb0,ca0i,cp,xm1,xm2,dm1p,dm2p,dm1m2,
+ piDpj,ier)
***#[*comment:***********************************************************
* *
* Compute the PV B2, the coefficients of p(mu)p(nu) and g(mu,nu) *
* of 1/(ipi^2)\int d^nQ Q(mu)Q(nu)/(Q^2-m_1^2)/((Q+p)^2-m_2^2) *
* originally based on aaxbx by Andre Aeppli. *
* *
* Input: cb1 complex vector two point function *
* cb0 complex scalar two point function *
* ca0i(2) complex scalar onepoint function with *
* m1,m2 *
* cp complex p.p in B&D metric *
* xm1,2 complex m_1^2,m_2^2 *
* piDpj(3,3) complex dotproducts between s1,s2,p *
* ier integer digits lost so far *
* *
* Output: cb2i(2) complex B21,B22: coeffs of p*p, g in B2 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE COMPLEX cp,xm1,xm2,dm1p,dm2p,dm1m2,piDpj(3,3)
- DOUBLE COMPLEX cb2i(2),cb1,cb0,ca0i(2)
+ ComplexType cp,xm1,xm2,dm1p,dm2p,dm1m2,piDpj(3,3)
+ ComplexType cb2i(2),cb1,cb0,ca0i(2)
*
* local variables
*
integer i,j,ier0,ier1,ithres,init
logical lreal,llogmm
- DOUBLE PRECISION xmax,xmxsav,absc,xmxp
- DOUBLE PRECISION rm1,rm2,rp,rm1p,rm2p,rm1m2,rpiDpj(3,3),sprec
- DOUBLE COMPLEX cs(14),cc,slam,xlo3,csom,clam,xlogmm,zfflo1,alp,
+ RealType xmax,xmxsav,absc,xmxp
+ RealType rm1,rm2,rp,rm1p,rm2p,rm1m2,rpiDpj(3,3),sprec
+ ComplexType cs(14),cc,slam,xlo3,csom,clam,xlogmm,zfflo1,alp,
+ bet,xnoe,xnoe2,zfflo3
- DOUBLE COMPLEX cqi(3),cqiqj(3,3)
+ ComplexType cqi(3),cqiqj(3,3)
save init
* for Absoft only
* external csqrt
-* DOUBLE COMPLEX csqrt
+* ComplexType csqrt
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(cc) = abs(DBLE(cc)) + abs(DIMAG(cc))
+ absc(cc) = abs(Re(cc)) + abs(Im(cc))
*
* #] declarations:
* #[ real cases:
- if ( DIMAG(xm1).eq.0 .and. DIMAG(xm2).eq.0 ) then
+ if ( Im(xm1).eq.0 .and. Im(xm2).eq.0 ) then
lreal = .TRUE.
elseif ( nschem.le.4 ) then
lreal = .TRUE.
if ( init.eq.0 ) then
init = 1
print *,'ffcb2q: nschem <= 4, ignoring complex masses:',
+ nschem
endif
elseif ( nschem.le.6 ) then
if ( init.eq.0 ) then
init = 1
print *,'ffcb2q: nschem = 5,6 complex masses near ',
+ 'threshold: ',nschem
endif
cqi(1) = xm1
cqi(2) = xm2
cqi(3) = cp
cqiqj(1,2) = dm1m2
cqiqj(2,1) = -cqiqj(1,2)
cqiqj(1,3) = dm1p
cqiqj(3,1) = -cqiqj(1,3)
cqiqj(2,3) = dm2p
cqiqj(3,2) = -cqiqj(2,3)
cqiqj(1,1) = 0
cqiqj(2,2) = 0
cqiqj(3,3) = 0
call ffthre(ithres,cqi,cqiqj,3,1,2,3)
if ( ithres.eq.0 .or. ithres.eq.1 .and. nschem.eq.5 ) then
lreal = .TRUE.
else
lreal = .FALSE.
endif
else
lreal = .FALSE.
endif
if ( lreal ) then
- rm1 = DBLE(xm1)
- rm2 = DBLE(xm2)
- rp = DBLE(cp)
- rm1p = DBLE(dm1p)
- rm2p = DBLE(dm2p)
- rm1m2 = DBLE(dm1m2)
+ rm1 = Re(xm1)
+ rm2 = Re(xm2)
+ rp = Re(cp)
+ rm1p = Re(dm1p)
+ rm2p = Re(dm2p)
+ rm1m2 = Re(dm1m2)
do 20 j=1,3
do 10 i=1,3
- rpiDpj(i,j) = DBLE(piDpj(i,j))
+ rpiDpj(i,j) = Re(piDpj(i,j))
10 continue
20 continue
sprec = precx
precx = precc
call ffxb2q(cb2i,cb1,cb0,ca0i,rp,rm1,rm2,rm1m2,rpiDpj,ier)
precx = sprec
return
endif
* #] real cases:
* #[ normal case:
ier0 = ier
ier1 = ier
*
* with thanks to Andre Aeppli, off whom I stole the original
*
- if ( DBLE(cp) .ne. 0) then
+ if ( Re(cp) .ne. 0) then
cs(1) = ca0i(2)
cs(2) = xm1*cb0
cs(3) = 2*piDpj(1,3)*cb1
cs(4) = (xm1+xm2)/2
cs(5) = -cp/6
cb2i(1) = cs(1) - cs(2) + 2*cs(3) - cs(4) - cs(5)
cb2i(2) = cs(1) + 2*cs(2) - cs(3) + 2*cs(4) + 2*cs(5)
xmax = max(absc(cs(2)),absc(cs(3)),absc(cs(4)),absc(cs(5)))
xmxsav = xmax
if ( absc(cb2i(1)) .ge. xloss*xmax ) goto 100
* #] normal case:
* #[ improve: m1=m2:
*
* a relatively simple case: dm1m2 = 0 (bi0.frm)
*
if ( dm1m2.eq.0 ) then
slam = sqrt(cp**2-4*xm1*cp)
xlo3 = zfflo3((cp-slam)/(2*xm1),ier)
- cs(1) = cp*(-1/DBLE(3) + slam/(4*xm1))
+ cs(1) = cp*(-1/Re(3) + slam/(4*xm1))
cs(2) = cp**2*(-slam/(4*xm1**2) - 3/(4*xm1))
cs(3) = cp**3/(4*xm1**2)
cs(4) = cp/xm1*ca0i(1)
cs(5) = xlo3/cp*(-xm1*slam)
cs(6) = xlo3*slam
csom = cs(1) + cs(2) + cs(3) + cs(4) + cs(5) + cs(6)
xmxp = max(absc(cs(2)),absc(cs(3)),absc(cs(4)),
+ absc(cs(5)),absc(cs(6)))
if ( xmxp.lt.xmax ) then
cb2i(1) = csom
xmax = xmxp
endif
if ( absc(cb2i(1)).ge.xloss**2*xmax ) goto 100
endif
* #] improve: m1=m2:
* #[ improve: |cp| < xm1 < xm2:
*
* try again (see bi.frm)
*
clam = 4*(piDpj(1,3)**2 - xm1*cp)
if ( xm1.eq.0 .or. xm2.eq.0 ) then
xlogmm = 0
elseif ( absc(dm1m2).lt.xloss*absc(xm1) ) then
xlogmm = zfflo1(dm1m2/xm1,ier)
else
xlogmm = log(xm2/xm1)
endif
- if ( abs(DBLE(cp)).lt.xloss*absc(xm2) .and.
- + DBLE(xm1).lt.DBLE(xm2) ) then
+ if ( abs(Re(cp)).lt.xloss*absc(xm2) .and.
+ + Re(xm1).lt.Re(xm2) ) then
slam = sqrt(clam)
alp = (2*xm1*xm2/(2*piDpj(1,2)+slam) + xm1)/(slam-dm1m2)
* bet = [xm2-xm1-cp-slam]
bet = 4*xm1*cp/(2*piDpj(1,3)+slam)
cs(1) = cp/xm2*ca0i(2)
cs(2) = xlogmm*bet*(-2*xm1**2*xm2 - 2*xm1**3)
+ /((-dm1m2+slam)*(2*piDpj(1,2)+slam)*(2*piDpj(1,3)+slam))
cs(3) = xlogmm*(-4*cp*xm1**3)
+ /((-dm1m2+slam)*(2*piDpj(1,2)+slam)*(2*piDpj(1,3)+slam))
xnoe = 1/(2*piDpj(2,3)+slam)
xnoe2 = xnoe**2
cs(4) = xnoe2*xm1*bet*(cp-4*xm2)
cs(5) = xnoe2*xm1*2*cp*xm2
cs(6) = xnoe2*xm1**2*bet
cs(7) = xnoe2*xm1**2*4*cp
cs(8) = xnoe2*bet*(cp*xm2+3*xm2**2)
cs(9) = xnoe2*(-6*cp*xm2**2)
cs(10)= cp*(7/6.d0 - 2*xm1*slam*xnoe2 +
+ 4*xm2*slam*xnoe2 - 2*slam*xnoe)
cs(11)= cp**2*( -2*slam*xnoe2 )
xlo3 = zfflo3(2*cp*xnoe,ier)
cs(12) = xlo3*dm1m2**2*slam/cp**2
cs(13) = xlo3*(xm1 - 2*xm2)*slam/cp
cs(14) = xlo3*slam
csom = 0
xmxp = 0
do 50 i=1,14
csom = csom + cs(i)
xmxp = max(xmxp,absc(cs(i)))
50 continue
if ( xmxp.lt.xmax ) then
cb2i(1) = csom
xmax = xmxp
endif
if ( absc(cb2i(1)).ge.xloss**2*xmax ) goto 100
endif
* #] improve: |cp| < xm1 < xm2:
* #[ improve: |cp| < xm2 < xm1:
- if ( abs(DBLE(cp)).lt.xloss*absc(xm1) .and.
- + DBLE(xm2).lt.DBLE(xm1) ) then
+ if ( abs(Re(cp)).lt.xloss*absc(xm1) .and.
+ + Re(xm2).lt.Re(xm1) ) then
slam = sqrt(clam)
alp = (2*xm2*xm1/(2*piDpj(1,2)+slam) + xm2)/(slam+dm1m2)
* bet = [xm1-xm2-cp-slam]
bet = 4*xm2*cp/(-2*piDpj(2,3)+slam)
xnoe = 1/(-2*piDpj(1,3)+slam)
xnoe2 = xnoe**2
cs(1) = cp/xm1*ca0i(1)
cs(2) = -xlogmm*bet*(12*cp*xm1*xm2+6*cp*xm2**2-
+ 6*cp**2*xm2-2*xm1*xm2**2-2*xm2**3)
+ /((dm1m2+slam)*(2*piDpj(1,2)+slam)*(-2*piDpj(2,3)+slam))
cs(3) = -xlogmm*(-24*cp*xm1**2*xm2-4*cp*xm2**3+36*
+ cp**2*xm1*xm2+12*cp**2*xm2**2-12*cp**3*xm2)
+ /((dm1m2+slam)*(2*piDpj(1,2)+slam)*(-2*piDpj(2,3)+slam))
cs(4) = xnoe2*xm2*bet*(cp-4*xm1)
cs(5) = xnoe2*xm2*(-10*cp*xm1)
cs(6) = xnoe2*xm2**2*bet
cs(7) = xnoe2*xm2**2*4*cp
cs(8) = xnoe2*bet*(cp*xm1+3*xm1**2)
cs(9) = xnoe2*6*cp*xm1**2
cs(10)= cp*(7/6.d0 - 2*xm1*slam*xnoe2 +
+ 4*xm2*slam*xnoe2 - 2*slam*xnoe)
cs(11)= cp**2*( -2*slam*xnoe2 )
xlo3 = zfflo3(2*cp*xnoe,ier)
cs(12) = xlo3*dm1m2**2*slam/cp**2
cs(13) = xlo3*(xm1 - 2*xm2)*slam/cp
cs(14) = xlo3*slam
csom = 0
xmxp = 0
do 60 i=1,14
csom = csom + cs(i)
xmxp = max(xmxp,absc(cs(i)))
60 continue
if ( xmxp.lt.xmax ) then
cb2i(1) = csom
xmax = xmxp
endif
if ( absc(cb2i(1)).ge.xloss**2*xmax ) goto 100
endif
* #] improve: |cp| < xm2 < xm1:
* #[ wrap up:
100 continue
xmax = xmxsav
- cb2i(1) = DBLE(1/(3*cp)) * cb2i(1)
- cb2i(2) = DBLE(1/6.d0) * cb2i(2)
+ cb2i(1) = Re(1/(3*cp)) * cb2i(1)
+ cb2i(2) = Re(1/6.d0) * cb2i(2)
* #] wrap up:
* #[ cp=0, m1!=m2:
elseif (dm1m2 .ne. 0) then
* #[ B21:
llogmm = .FALSE.
*
* B21 (see thesis, b21.frm)
*
cs(1) = xm1**2/3/dm1m2**3*ca0i(1)
cs(2) = (-xm1**2 + xm1*xm2 - xm2**2/3)/dm1m2**3*ca0i(2)
cs(3) = (5*xm1**3/18 - xm1*xm2**2/2 + 2*xm2**3/9)
+ /dm1m2**3
cb2i(1) = cs(1)+cs(2)+cs(3)
xmax = max(absc(cs(2)),absc(cs(3)))
if ( absc(cb2i(1)).gt.xloss**2*xmax ) goto 160
*
* ma ~ mb
*
if ( absc(dm1m2).lt.xloss*absc(xm1) ) then
xlogmm = zfflo1(dm1m2/xm1,ier)
else
xlogmm = log(xm2/xm1)
endif
llogmm = .TRUE.
cs(1) = (xm1/dm1m2)/6
cs(2) = (xm1/dm1m2)**2/3
cs(3) = (xm1/dm1m2)**3*xlogmm/3
- cs(4) = -2/DBLE(9) + ca0i(1)/(3*xm1)
+ cs(4) = -2/Re(9) + ca0i(1)/(3*xm1)
cs(5) = -xlogmm/3
csom = cs(1)+cs(2)+cs(3)+cs(4)+cs(5)
xmxp = max(absc(cs(2)),absc(cs(3)),absc(cs(4)),
+ absc(cs(5)))
if ( xmxp.lt.xmax ) then
xmax = xmxp
cb2i(1) = csom
if ( absc(cb2i(1)).gt.xloss**2*xmax ) goto 160
endif
*
* and last try
*
xlo3 = zfflo3(dm1m2/xm1,ier)
cs(1) = (dm1m2/xm1)**2/6
cs(2) = (dm1m2/xm1)/3
cs(3) = xlo3/(3*(dm1m2/xm1)**3)
-*same cs(4) = -2/DBLE(9) + ca0i(1)/(3*xm1)
+*same cs(4) = -2/Re(9) + ca0i(1)/(3*xm1)
cs(5) = -xlo3/3
csom = cs(1)+cs(2)+cs(3)+cs(4)+cs(5)
xmxp = max(absc(cs(2)),absc(cs(3)),absc(cs(4)),
+ absc(cs(5)))
if ( xmxp.lt.xmax ) then
xmax = xmxp
cb2i(1) = csom
if ( absc(cb2i(1)).gt.xloss**2*xmax ) goto 160
endif
*
* give up
*
160 continue
* #] B21:
* #[ B22:
*
* B22
*
cs(1) = +xm1/(4*dm1m2)*ca0i(1)
cs(2) = -xm2/(4*dm1m2)*ca0i(2)
cs(3) = (xm1+xm2)/8
cb2i(2) = cs(1) + cs(2) + cs(3)
xmax = max(absc(cs(2)),absc(cs(3)))
if ( absc(cb2i(2)).gt.xloss*xmax ) goto 210
*
* second try, close together
*
if ( .not.llogmm ) then
if ( abs(dm1m2).lt.xloss*absc(xm1) ) then
xlogmm = zfflo1(dm1m2/xm1,ier)
else
xlogmm = log(xm2/xm1)
endif
endif
- cs(1) = dm1m2*( -1/DBLE(8) - ca0i(1)/(4*xm1) )
+ cs(1) = dm1m2*( -1/Re(8) - ca0i(1)/(4*xm1) )
cs(2) = dm1m2*xlogmm/4
cs(3) = xm1*(xm1/dm1m2)/4*xlogmm
- cs(4) = xm1*( 1/DBLE(4) + ca0i(1)/(2*xm1) )
+ cs(4) = xm1*( 1/Re(4) + ca0i(1)/(2*xm1) )
cs(5) = -xm1*xlogmm/2
csom = cs(1) + cs(2) + cs(3) + cs(4) + cs(5)
xmxp = max(absc(cs(2)),absc(cs(3)),absc(cs(4)),
+ absc(cs(5)))
if ( xmxp.lt.xmax ) then
xmax = xmxp
cb2i(2) = csom
endif
if ( absc(cb2i(2)).gt.xloss*xmax ) goto 210
*
* give up
*
210 continue
* #] B22:
* #] cp=0, m1!=m2:
* #[ cp=0, m1==m2:
else
*
* taken over from ffxb2a, which in turns stem from my thesis GJ
*
cb2i(1) = cb0/3
cb2i(2) = xm1/2*(cb0 + 1)
endif
* #] cp=0, m1==m2:
* #[ finish up:
ier = max(ier0,ier1)
* #] finish up:
*###] ffcb2q:
end
diff --git a/Looptools/B/ffcdb0.F b/Looptools/B/ffcdb0.F
--- a/Looptools/B/ffcdb0.F
+++ b/Looptools/B/ffcdb0.F
@@ -1,713 +1,714 @@
#include "externals.h"
+#include "types.h"
*###[ ffcdb0:
subroutine ffcdb0(cdb0,cdb0p,cp,cma,cmb,ier)
***#[*comment:***********************************************************
* *
* Calculates the derivative of the two-point function with *
* respect to p2, plus the same times p2. *
* *
* Input: cp (complex) k2, in B&D metric *
* cma (complex) mass2 *
* cmb (complex) mass2 *
* *
* Output: cdb0 (complex) dB0/dxp *
* cdb0p (complex) cp*dB0/dxp *
* ier (integer) # of digits lost, if >=100: error *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE COMPLEX cdb0,cdb0p
- DOUBLE COMPLEX cp,cma,cmb
+ ComplexType cdb0,cdb0p
+ ComplexType cp,cma,cmb
*
* local variables
*
integer ier0
- DOUBLE COMPLEX cmamb,cmap,cmbp
- DOUBLE PRECISION xp,xma,xmb
+ ComplexType cmamb,cmap,cmbp
+ RealType xp,xma,xmb
*
* common
*
#include "ff.h"
*
* #] declarations:
* #[ check input:
- if ( DIMAG(cma).eq.0 .and. DIMAG(cmb).eq.0 ) then
- xma = DBLE(cma)
- xmb = DBLE(cmb)
- xp = DBLE(cp)
+ if ( Im(cma).eq.0 .and. Im(cmb).eq.0 ) then
+ xma = Re(cma)
+ xmb = Re(cmb)
+ xp = Re(cp)
call ffxdb0(cdb0,cdb0p,xp,xma,xmb,ier)
return
endif
* #] check input:
* #[ get differences:
ier0 = 0
cmamb = cma - cmb
cmap = cma - cp
cmbp = cmb - cp
* #] get differences:
* #[ calculations:
call ffcdbp(cdb0,cdb0p,cp,cma,cmb,cmap,cmbp,cmamb,ier)
* #] calculations:
*###] ffcdb0:
end
*###[ ffcdbp:
subroutine ffcdbp(cdb0,cdb0p,cp,cma,cmb,cmap,cmbp,cmamb,ier)
***#[*comment:***********************************************************
* *
* calculates the derivatives of the two-point function *
* *
* Input: cp (complex) p.p, in B&D metric *
* cma (complex) mass2, *
* cmb (complex) mass2, *
* dm[ab]p (complex) cm[ab] - cp *
* cmamb (complex) cma - cmb *
* *
* Output: cdb0 (complex) B0' = dB0/dxp *
* cdb0p (complex) cp*B0' *
* ier (integer) 0=ok,>0=numerical problems,>100=error *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE COMPLEX cdb0,cdb0p
- DOUBLE COMPLEX cp,cma,cmb,cmap,cmbp,cmamb
+ ComplexType cdb0,cdb0p
+ ComplexType cp,cma,cmb,cmap,cmbp,cmamb
*
* local variables
*
integer i,initeq,jsign,init,ithres,initir,n1,n2,nffet1
logical lreal
- DOUBLE PRECISION ax,ffbnd,ffbndc,
+ RealType ax,ffbnd,ffbndc,
+ xprceq,bdeq01,bdeq05,bdeq11,bdeq17,bdeq25,
+ xprcn3,bdn301,bdn305,bdn310,bdn315,
+ xprcn5,bdn501,bdn505,bdn510,bdn515,
+ xprec0,bdn001,bdn005,bdn010,bdn015,bdn020,
+ absc,xmax,prcsav
- DOUBLE COMPLEX cm,cdmp,cm1,cm2,cm1m2,cdm1p,
+ ComplexType cm,cdmp,cm1,cm2,cm1m2,cdm1p,
+ cdm2p,s,s1,s1a,s1b,s1p,s2,s2a,s2b,s2p,s3,cx,som,
+ clam,slam,xlogmm,alpha,alph1,xnoe,xpneq(30),
+ zfflo1,zfflo3,d1,d2,diff,h,a,b,c,d,beta,
+ betm2n,s1c,s1d,s1e,s1f,cqi(3),cqiqj(3,3),zm,zp
- DOUBLE COMPLEX cc
- DOUBLE PRECISION xp,xma,xmb,dmamb,dmap,dmbp,sprec
+ ComplexType cc
+ RealType xp,xma,xmb,dmamb,dmap,dmbp,sprec
save initeq,xpneq,init,initir,
+ xprceq,bdeq01,bdeq05,bdeq11,bdeq17,bdeq25,
+ xprcn3,bdn301,bdn305,bdn310,bdn315,
+ xprcn5,bdn501,bdn505,bdn510,bdn515,
+ xprec0,bdn001,bdn005,bdn010,bdn015,bdn020
*for ABSOFT only
-* DOUBLE COMPLEX csqrt
+* ComplexType csqrt
* external csqrt
*
* common blocks
*
#include "ff.h"
*
* data
*
data xprceq /-1./
data xprec0 /-1./
data xprcn3 /-1./
data xprcn5 /-1./
data initeq /0/
*
* statement function
*
- absc(cc) = abs(DBLE(cc)) + abs(DIMAG(cc))
+ absc(cc) = abs(Re(cc)) + abs(Im(cc))
* #] declarations:
* #[ the real cases:
*
- if ( DIMAG(cma) .eq. 0 .and. DIMAG(cmb) .eq. 0 ) then
+ if ( Im(cma) .eq. 0 .and. Im(cmb) .eq. 0 ) then
lreal = .TRUE.
elseif ( nschem.le.2 ) then
lreal = .TRUE.
if ( init.eq.0 ) then
init = 1
print *,'ffcb0: nschem <= 2, ignoring complex masses: ',
+ nschem
endif
elseif ( nschem.le.4 ) then
if ( init.eq.0 ) then
init = 1
print *,'ffcdbp: nschem = 3,4 complex masses near ',
+ 'singularity: ',nschem
endif
- if ( abs(DBLE(cma)) .lt. -xloss*DIMAG(cmb)
- + .and. abs(DBLE(cmbp)) .le. -nwidth*DIMAG(cmb)
- + .or. abs(DBLE(cmb)) .lt. -xloss*DIMAG(cma)
- + .and. abs(DBLE(cmap)) .le. -nwidth*DIMAG(cma) ) then
+ if ( abs(Re(cma)) .lt. -xloss*Im(cmb)
+ + .and. abs(Re(cmbp)) .le. -nwidth*Im(cmb)
+ + .or. abs(Re(cmb)) .lt. -xloss*Im(cma)
+ + .and. abs(Re(cmap)) .le. -nwidth*Im(cma) ) then
lreal = .FALSE.
else
lreal = .TRUE.
endif
elseif ( nschem.le.6 ) then
if ( init.eq.0 ) then
init = 1
print *,'ffcdbp: nschem = 5,6 complex masses near ',
+ 'threshold: ',nschem
endif
cqi(1) = cma
cqi(2) = cmb
cqi(3) = cp
cqiqj(1,2) = cmamb
cqiqj(2,1) = -cqiqj(1,2)
cqiqj(1,3) = cmap
cqiqj(3,1) = -cqiqj(1,3)
cqiqj(2,3) = cmbp
cqiqj(3,2) = -cqiqj(2,3)
cqiqj(1,1) = 0
cqiqj(2,2) = 0
cqiqj(3,3) = 0
call ffthre(ithres,cqi,cqiqj,3,1,2,3)
if ( ithres.eq.0 .or. ithres.eq.1 .and. nschem.eq.5 ) then
lreal = .TRUE.
else
lreal = .FALSE.
endif
else
lreal = .FALSE.
endif
if ( lreal ) then
- xp = DBLE(cp)
- xma = DBLE(cma)
- xmb = DBLE(cmb)
- dmap = DBLE(cmap)
- dmbp = DBLE(cmbp)
- dmamb = DBLE(cmamb)
+ xp = Re(cp)
+ xma = Re(cma)
+ xmb = Re(cmb)
+ dmap = Re(cmap)
+ dmbp = Re(cmbp)
+ dmamb = Re(cmamb)
sprec = precx
precx = precc
call ffxdbp(cdb0,cdb0p,xp,xma,xmb,dmap,dmbp,dmamb,ier)
precx = sprec
return
endif
*
* #] the real cases:
* #[ which case:
*
* sort according to the type of masscombination encountered:
* 100: both masses zero, 200: one equal to zero, 300: both equal
* 400: rest.
*
if ( cma .eq. 0 ) then
if ( cmb .eq. 0 ) then
goto 100
endif
cm = cmb
cdmp = cmbp
goto 200
endif
if ( cmb .eq. 0 ) then
cm = cma
cdmp = cmap
goto 200
elseif ( cmamb .eq. 0 ) then
cm = cma
cdmp = cmap
goto 300
- elseif ( DBLE(cma) .gt. DBLE(cmb) ) then
+ elseif ( Re(cma) .gt. Re(cmb) ) then
cm2 = cma
cm1 = cmb
cm1m2 = -cmamb
cdm1p = cmbp
cdm2p = cmap
else
cm1 = cma
cm2 = cmb
cm1m2 = cmamb
cdm1p = cmap
cdm2p = cmbp
endif
goto 400
* #] which case:
* #[ both masses equal to zero:
100 continue
if ( cp.ne.0 ) cdb0 = -1/cp
cdb0p = -1
return
* #] both masses equal to zero:
* #[ one mass equal to zero:
200 continue
*
* special case cp = 0
*
if ( cp .eq. 0 ) then
cdb0p = 0
cdb0 = 1/(2*cm)
goto 990
*
* special case cp = cm
*
elseif ( cdmp.eq.0 ) then
if ( initir.eq.0 ) then
initir = 1
print *,'ffcdbd: IR divergent B0'', using cutoff ',
& lambda
endif
if ( lambda .le. 0 ) then
cdb0p = -1 + log(cm/mudim)/2
else
cdb0p = -1 + log(cm/lambda)/2
endif
cdb0 = cdb0p/cp
goto 990
endif
*
* Normal case:
*
cx = cp/cm
ax = absc(cx)
if ( ax .lt. xloss ) then
* #[ Taylor expansion:
if ( xprec0 .ne. precx ) then
xprec0 = precc
prcsav = precx
precx = precc
bdn001 = ffbnd(2,1,xninv)
bdn005 = ffbnd(2,5,xninv)
bdn010 = ffbnd(2,10,xninv)
bdn015 = ffbnd(2,15,xninv)
bdn020 = ffbnd(2,20,xninv)
precx = prcsav
endif
if ( ax .gt. bdn015 ) then
- som = cx*(DBLE(xninv(17)) + cx*(DBLE(xninv(18))
- + + cx*(DBLE(xninv(19)) + cx*(DBLE(xninv(20))
- + + cx*(DBLE(xninv(21)) )))))
+ som = cx*(Re(xninv(17)) + cx*(Re(xninv(18))
+ + + cx*(Re(xninv(19)) + cx*(Re(xninv(20))
+ + + cx*(Re(xninv(21)) )))))
else
som = 0
endif
if ( ax .gt. bdn010 ) then
- som = cx*(DBLE(xninv(12)) + cx*(DBLE(xninv(13))
- + + cx*(DBLE(xninv(14)) + cx*(DBLE(xninv(15))
- + + cx*(DBLE(xninv(16)) + som )))))
+ som = cx*(Re(xninv(12)) + cx*(Re(xninv(13))
+ + + cx*(Re(xninv(14)) + cx*(Re(xninv(15))
+ + + cx*(Re(xninv(16)) + som )))))
endif
if ( ax .gt. bdn005 ) then
- som = cx*(DBLE(xninv(7)) + cx*(DBLE(xninv(8))
- + + cx*(DBLE(xninv(9)) + cx*(DBLE(xninv(10))
- + + cx*(DBLE(xninv(11)) + som )))))
+ som = cx*(Re(xninv(7)) + cx*(Re(xninv(8))
+ + + cx*(Re(xninv(9)) + cx*(Re(xninv(10))
+ + + cx*(Re(xninv(11)) + som )))))
endif
if ( ax .gt. bdn001 ) then
- som = cx*(DBLE(xninv(3)) + cx*(DBLE(xninv(4))
- + + cx*(DBLE(xninv(5)) + cx*(DBLE(xninv(6)) + som ))))
+ som = cx*(Re(xninv(3)) + cx*(Re(xninv(4))
+ + + cx*(Re(xninv(5)) + cx*(Re(xninv(6)) + som ))))
endif
- cdb0p = cx*(DBLE(xninv(2)) + som)
+ cdb0p = cx*(Re(xninv(2)) + som)
* #] Taylor expansion:
else
* #[ short formula:
s = log(cdmp/cm)
cdb0p = -(1 + s*cm/cp)
* #] short formula:
endif
cdb0 = cdb0p/cp
goto 990
* #] one mass equal to zero:
* #[ both masses equal:
300 continue
*
* Both masses are equal. Not only this speeds up things, some
* cancellations have to be avoided as well.
*
* first a special case
*
if ( absc(cp) .lt. 8*xloss*absc(cm) ) then
* -#[ taylor expansion:
*
* a Taylor expansion seems appropriate as the result will go
* as k^2 but seems to go as 1/k !!
*
*--#[ data and bounds:
if ( initeq .eq. 0 ) then
initeq = 1
xpneq(1) = 1/6D0
do 1 i=2,30
- xpneq(i) = - xpneq(i-1)*DBLE(i)/DBLE(2*(2*i+1))
+ xpneq(i) = - xpneq(i-1)*Re(i)/Re(2*(2*i+1))
1 continue
endif
if (xprceq .ne. precx ) then
*
* calculate the boundaries for the number of terms to be
* included in the taylorexpansion
*
xprceq = precx
bdeq01 = ffbndc(1,1,xpneq)
bdeq05 = ffbndc(1,5,xpneq)
bdeq11 = ffbndc(1,11,xpneq)
bdeq17 = ffbndc(1,17,xpneq)
bdeq25 = ffbndc(1,25,xpneq)
endif
*--#] data and bounds:
cx = -cp/cm
ax = absc(cx)
if ( ax .gt. bdeq17 ) then
som = cx*(xpneq(18) + cx*(xpneq(19) + cx*(xpneq(20) +
+ cx*(xpneq(21) + cx*(xpneq(22) + cx*(xpneq(23) +
+ cx*(xpneq(24) + cx*(xpneq(25) ))))))))
else
som = 0
endif
if ( ax .gt. bdeq11 ) then
som = cx*(xpneq(12) + cx*(xpneq(13) + cx*(xpneq(14) +
+ cx*(xpneq(15) + cx*(xpneq(16) + cx*(xpneq(17) + som ))))
+ ))
endif
if ( ax .gt. bdeq05 ) then
som = cx*(xpneq(6) + cx*(xpneq(7) + cx*(xpneq(8) + cx*(
+ xpneq(9) + cx*(xpneq(10) + cx*(xpneq(11) + som ))))))
endif
if ( ax .gt. bdeq01 ) then
som = cx*(xpneq(2) + cx*(xpneq(3) + cx*(xpneq(4) + cx*(
+ xpneq(5) + som ))))
endif
cdb0p = -cx*(xpneq(1)+som)
if ( cp.ne.0 ) then
- cdb0 = cdb0p*(1/DBLE(cp))
+ cdb0 = cdb0p*(1/Re(cp))
else
cdb0 = xpneq(1)/cm
endif
goto 990
* -#] taylor expansion:
endif
* -#[ normal case:
*
* normal case
*
call ffclmb(clam,-cp,-cm,-cm,cdmp,cdmp,czero)
slam = sqrt(clam)
call ffcoot(zm,zp,cone,chalf,cm/cp,slam/(2*cp),ier)
s1 = zp/zm
if( abs(s1-1) .lt. xloss ) then
* In this case a quicker and more accurate way is to
* calculate log(1-cx).
print *,'Not tested, probably wrong'
ier = ier + 50
s2 = (cp - slam)
if ( absc(s2) .lt. xloss*absc(cp) ) then
s2 = -slam*(cp+slam)/(4*cp*cm)
else
s2 = -2*slam/s2
endif
s = -2*cm/slam*zfflo1(s2/(2*cm),ier)
else
* finally the normal case
s = -2*cm/slam*log(s1)
endif
*
* eta terms
*
n1 = nffet1(zp,1/zm,s1,ier)
n2 = nffet1(-zp,-1/zm,s1,ier)
if ( n1+n2 .ne. 0 ) then
s1 = cm/slam*c2ipi*(n1+n2)
s = s + s1
endif
cdb0p = s - 1
cdb0 = cdb0p/cp
goto 990
* -#] normal case:
*
* #] both masses equal:
* #[ unequal nonzero masses:
400 continue
* -#[ get log(cm2/cm1):
cx = cm2/cm1
c = cx-1
if ( 1 .lt. xclogm*absc(cx) ) then
call fferr(8,ier)
xlogmm = 0
elseif ( absc(c) .lt. xloss ) then
xlogmm = zfflo1(cm1m2/cm1,ier)
else
xlogmm = log(cx)
endif
* -#] get log(cm2/cm1):
* -#[ cp = 0:
*
* first a special case
*
if ( cp .eq. 0 ) then
*
* repaired 19-nov-1993, see b2.frm
*
s1 = cm1*cm2*xlogmm/cm1m2**3
s2 = (cm1+cm2)/(2*cm1m2**2)
s = s1 + s2
if ( absc(s) .lt. xloss**2*absc(s2) ) then
*
* second try
*
h = zfflo3(cm1m2/cm1,ier)
s1 = -cm1*h/cm1m2**2
s2 = 1/(2*cm1)
s3 = cm1**2*h/cm1m2**3
s = s1 + s2 + s3
if ( absc(s) .lt. xloss*max(absc(s2),absc(s3)) ) then
call ffwarn(234,ier,absc(s),absc(s2))
endif
endif
cdb0 = s
cdb0p = 0
goto 990
endif
* -#] cp = 0:
* -#[ normal case:
*
* proceeding with the normal case
*
call ffclmb(clam,-cp,-cm2,-cm1,cdm2p,cdm1p,cm1m2)
diff = clam + cp*(cdm2p+cm1)
if ( absc(diff) .lt. xloss*absc(clam) ) then
h = cm1m2**2 - cp*(cm1+cm2)
if ( absc(h) .lt. xloss*absc(cm1m2)**2 ) then
if ( absc(cm1m2)**2 .lt. absc(clam) ) diff = h
call ffwarn(235,ier,absc(diff),min(absc(cm1m2)**2,
+ absc(clam)))
endif
endif
*--#[ first try:
* first try the normal way
slam = sqrt(clam)
- if ( abs(DBLE(cm1)) .lt. abs(DBLE(cm2)) ) then
+ if ( abs(Re(cm1)) .lt. abs(Re(cm2)) ) then
s2a = cm1 + cdm2p
else
s2a = cm2 + cdm1p
endif
s2 = s2a + slam
if ( absc(s2) .gt. xloss*absc(slam) ) then
* looks fine
jsign = 1
else
s2 = s2a - slam
jsign = -1
endif
s2 = s2/sqrt(4*cm1*cm2)
if ( absc(s2) .lt. xclogm ) then
call fferr(9,ier)
s2 = 0
elseif ( absc(s2-1) .lt. xloss ) then
ier = ier + 50
print *,'ffcdb0: untested: s2 better in first try'
if ( jsign.eq.1 ) then
s2 = -slam*(s2a+slam)/(2*cm1*cm2)
s2 = -diff/(2*slam*cp)*zfflo1(s2,ier)
else
s2 = +slam*(s2a-slam)/(2*cm1*cm2)
s2 = +diff/(2*slam*cp)*zfflo1(s2,ier)
endif
else
s2 = -diff/(2*slam*cp)*2*log(s2)
if ( jsign .eq. -1 ) s2 = -s2
endif
s1 = -cm1m2*xlogmm/(2*cp)
cdb0p = s1+s2-1
*--#] first try:
if ( absc(cdb0p) .lt. xloss**2*max(absc(s1),absc(s2)) ) then
*--#[ second try:
* this is unacceptable, try a better solution
s1a = diff + slam*cm1m2
if ( absc(s1a) .gt. xloss*absc(diff) ) then
* this works
s1 = -s1a/(2*cp*slam)
else
* by division a more accurate form can be found
s1 = -2*cm1*cm2*cp/(slam*(diff - slam*cm1m2))
endif
s = s1
s1 = s1*xlogmm
- if ( abs(DBLE(cp)).lt.abs(DBLE(cm2)) ) then
+ if ( abs(Re(cp)).lt.abs(Re(cm2)) ) then
s2a = cp - cm1m2
else
s2a = cm2 - cdm1p
endif
s2 = s2a - slam
if ( absc(s2) .gt. xloss*absc(slam) ) then
* at least reasonable
s2 = s2 / (2*cm2)
else
* division again
s2 = (2*cp) / (s2a+slam)
endif
if ( absc(s2) .lt. .1 ) then
* choose a quick way to get the logarithm
s2 = zfflo1(s2,ier)
else
s2 = log(1-s2)
endif
s2 = -diff/(slam*cp)*s2
cdb0p = s1 + s2 - 1
*--#] second try:
if ( absc(cdb0p) .lt. xloss**2*max(absc(s1),absc(s2)) )
+ then
*--#[ third try:
* (we accept two times xloss because that's the same
* as in this try)
* A Taylor expansion might work. We expand
* inside the logs. Only do the necessary work.
*
* #[ split up 1:
xnoe = s2a+slam
a = 1
b = 2/xnoe-1/cp
c = -4/(cp*xnoe)
d = sqrt(cp**(-2) + (2/xnoe)**2)
call ffcoot(d1,d2,a,b,c,d,ier)
- if ( DBLE(cp).gt.0 ) then
+ if ( Re(cp).gt.0 ) then
beta = d2
else
beta = d1
endif
alpha = beta*diff/slam
alph1 = 1-alpha
if ( absc(alph1) .lt. xloss ) then
s1a = 4*cp**2*cm1*cm2/(slam*cm1m2*(diff-slam*
+ cm1m2))
s1b = -diff/slam*4*cm1*cp/(cm1m2*xnoe*(2*cp-
+ xnoe))
b = -1/cp
c = -(2/xnoe)**2
call ffcoot(d1,d2,a,b,c,d,ier)
- if ( DBLE(cp).gt.0 ) then
+ if ( Re(cp).gt.0 ) then
betm2n = d2
else
betm2n = d1
endif
d1 = s1a + s1b - diff/slam*betm2n
xmax = max(absc(s1a),absc(s1b))
if ( xmax .lt. 1 ) then
alph1 = d1
else
xmax = 1
endif
if ( absc(alph1) .lt. xloss*xmax )
+ call ffwarn(236,ier,absc(alph1),xmax)
else
betm2n = beta - 2/xnoe
endif
* #] split up 1:
* #[ s2:
*
* first s2:
*
s2p = s2 - alpha
if ( absc(s2p) .lt. xloss*absc(s2) ) then
* -#[ bounds:
* determine the boundaries for 1,5,10,15 terms
if ( xprcn5 .ne. precx ) then
xprcn5 = precc
prcsav = precx
precx = precc
bdn501 = ffbnd(3,1,xinfac)
bdn505 = ffbnd(3,5,xinfac)
bdn510 = ffbnd(3,10,xinfac)
bdn515 = ffbnd(3,15,xinfac)
precx = prcsav
endif
* -#] bounds:
cx = beta*cp
ax = absc(cx)
if ( ax .gt. bdn510 ) then
- s2a = cx*(DBLE(xinfac(13)) + cx*(DBLE(xinfac(
- + 14))+ cx*(DBLE(xinfac(15)) + cx*(DBLE(xinfac(
- + 16))+ cx*(DBLE(xinfac(17)))))))
+ s2a = cx*(Re(xinfac(13)) + cx*(Re(xinfac(
+ + 14))+ cx*(Re(xinfac(15)) + cx*(Re(xinfac(
+ + 16))+ cx*(Re(xinfac(17)))))))
else
s2a = 0
endif
if ( ax .gt. bdn505 ) then
- s2a = cx*(DBLE(xinfac( 8)) + cx*(DBLE(xinfac(
- + 9))+ cx*(DBLE(xinfac(10)) + cx*(DBLE(xinfac(
- + 11))+ cx*(DBLE(xinfac(12)) + s2a)))))
+ s2a = cx*(Re(xinfac( 8)) + cx*(Re(xinfac(
+ + 9))+ cx*(Re(xinfac(10)) + cx*(Re(xinfac(
+ + 11))+ cx*(Re(xinfac(12)) + s2a)))))
endif
if ( ax .gt. bdn501 ) then
- s2a =cx*(DBLE(xinfac(4))+cx*(DBLE(xinfac(5))
- + +cx*(DBLE(xinfac(6))+cx*(DBLE(xinfac(7))
+ s2a =cx*(Re(xinfac(4))+cx*(Re(xinfac(5))
+ + +cx*(Re(xinfac(6))+cx*(Re(xinfac(7))
+ + s2a))))
endif
- s2a = cx**3*(DBLE(xinfac(3))+s2a)
+ s2a = cx**3*(Re(xinfac(3))+s2a)
s2b = 2*cp/xnoe*(s2a + cx**2/2)
s2p = s2b - s2a
s2p = -diff/(cp*slam)*zfflo1(s2p,ier)
endif
* #] s2:
* #[ s1:
*
* next s1:
*
s1p = s1 - alph1
if ( absc(s1p) .lt. xloss*absc(s1) ) then
* -#[ bounds:
* determine the boundaries for 1,5,10,15 terms
if ( xprcn3 .ne. precx ) then
xprcn3 = precc
prcsav = precx
precx = precc
bdn301 = ffbnd(3,1,xinfac)
bdn305 = ffbnd(3,5,xinfac)
bdn310 = ffbnd(3,10,xinfac)
bdn315 = ffbnd(3,15,xinfac)
precx = prcsav
endif
* -#] bounds:
*
cx = slam*(diff-slam*cm1m2)*alph1/(2*cp*cm1*cm2)
ax = absc(cx)
h = (2*cp*(cm1+cm2) - cp**2)/(slam-cm1m2)
*
* see form job gets1.frm
*
s1b = diff*(diff-slam*cm1m2)*betm2n/(2*cp*cm1*
+ cm2)
s1c = 1/(cm1*xnoe*(2*cp-xnoe))*(
+ cp*( 4*cp*cm2 + 2*cm1m2**2/cm2*(cp-h) +
+ 2*cm1m2*(3*cp-h) - 8*cm1m2**2 )
+ - 2*cm1m2**3/cm2*(3*cp-h)
+ + 4*cm1m2**4/cm2
+ )
s1d = cx*cm1m2/cm1
s1e = -cx**2/2
if ( ax .gt. bdn310 ) then
- s1a = cx*(DBLE(xinfac(13)) + cx*(DBLE(xinfac(
- + 14))+ cx*(DBLE(xinfac(15)) + cx*(DBLE(xinfac(
- + 16))+ cx*(DBLE(xinfac(17)))))))
+ s1a = cx*(Re(xinfac(13)) + cx*(Re(xinfac(
+ + 14))+ cx*(Re(xinfac(15)) + cx*(Re(xinfac(
+ + 16))+ cx*(Re(xinfac(17)))))))
else
s1a = 0
endif
if ( ax .gt. bdn305 ) then
- s1a = cx*(DBLE(xinfac( 8)) + cx*(DBLE(xinfac(
- + 9))+ cx*(DBLE(xinfac(10)) + cx*(DBLE(xinfac(
- + 11))+ cx*(DBLE(xinfac(12)) + s1a)))))
+ s1a = cx*(Re(xinfac( 8)) + cx*(Re(xinfac(
+ + 9))+ cx*(Re(xinfac(10)) + cx*(Re(xinfac(
+ + 11))+ cx*(Re(xinfac(12)) + s1a)))))
endif
if ( ax .gt. bdn301 ) then
- s1a =cx*(DBLE(xinfac(4))+cx*(DBLE(xinfac(5))
- + +cx*(DBLE(xinfac(6))+cx*(DBLE(xinfac(7))
+ s1a =cx*(Re(xinfac(4))+cx*(Re(xinfac(5))
+ + +cx*(Re(xinfac(6))+cx*(Re(xinfac(7))
+ +s1a))))
endif
- s1a = -cx**3 *(DBLE(xinfac(3)) + s1a)
+ s1a = -cx**3 *(Re(xinfac(3)) + s1a)
s1f = cm1m2/cm1*(cx**2/2 - s1a)
s1p = s1e + s1d + s1c + s1b + s1a + s1f
xmax = max(absc(s1a),absc(s1b),absc(s1c),
+ absc(s1d),absc(s1e))
s1p = s*zfflo1(s1p,ier)
endif
* #] s1:
*
* finally ...
*
cdb0p = s1p + s2p
*--#] third try:
endif
endif
- cdb0 = cdb0p*(1/DBLE(cp))
+ cdb0 = cdb0p*(1/Re(cp))
* -#] normal case:
* #] unequal nonzero masses:
990 continue
*###] ffcdbp:
end
diff --git a/Looptools/B/ffcel2.F b/Looptools/B/ffcel2.F
--- a/Looptools/B/ffcel2.F
+++ b/Looptools/B/ffcel2.F
@@ -1,557 +1,558 @@
#include "externals.h"
+#include "types.h"
*###[ ffcel2:
subroutine ffcel2(del2,piDpj,ns,i1,i2,i3,lerr,ier)
*************************************************************************
* calculate in a numerically stable way *
* del2(piDpj(i1,i1),piDpj(i2,i2),piDpj(i3,i3)) = *
* = piDpj(i1,i1)*piDpj(i2,i2) - piDpj(i1,i2)^2 *
* = piDpj(i1,i1)*piDpj(i3,i3) - piDpj(i1,i3)^2 *
* = piDpj(i2,i2)*piDpj(i3,i3) - piDpj(i2,i3)^2 *
* ier is the usual error flag. *
*************************************************************************
implicit none
*
* arguments:
*
integer ns,i1,i2,i3,lerr,ier
- DOUBLE COMPLEX del2,piDpj(ns,ns)
+ ComplexType del2,piDpj(ns,ns)
*
* local variables
*
- DOUBLE COMPLEX s1,s2,cc
- DOUBLE PRECISION absc
+ ComplexType s1,s2,cc
+ RealType absc
*
* common blocks
*
#include "ff.h"
*
- absc(cc) = abs(DBLE(cc)) + abs(DIMAG(cc))
+ absc(cc) = abs(Re(cc)) + abs(Im(cc))
*
* calculations
*
if ( absc(piDpj(i1,i2)) .lt. absc(piDpj(i1,i3)) .and.
+ absc(piDpj(i1,i2)) .lt. absc(piDpj(i2,i3)) ) then
s1 = piDpj(i1,i1)*piDpj(i2,i2)
s2 = piDpj(i1,i2)**2
elseif ( absc(piDpj(i1,i3)) .lt. absc(piDpj(i2,i3)) ) then
s1 = piDpj(i1,i1)*piDpj(i3,i3)
s2 = piDpj(i1,i3)**2
else
s1 = piDpj(i2,i2)*piDpj(i3,i3)
s2 = piDpj(i2,i3)**2
endif
del2 = s1 - s2
if ( absc(del2) .lt. xloss*absc(s2) ) then
if ( lerr .eq. 0 ) then
* we know we have another chance
if ( del2.ne.0 ) then
ier = ier + int(log10(xloss*absc(s2)/absc(del2)))
else
ier = ier + int(log10(xloss*absc(s2)/xclogm))
endif
endif
endif
*###] ffcel2:
end
*###[ ffcl2p:
subroutine ffcl2p(delps1,xpi,dpipj,piDpj,
+ ip1,ip2,ip3,is1,is2,is3,ns)
***#[*comment:***********************************************************
* *
* calculate in a numerically stable way *
* delta_{ip1,is2}^{ip1,ip2} *
* ier is the usual error flag. *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ns,ip1,ip2,ip3,is1,is2,is3
- DOUBLE COMPLEX delps1,xpi(ns),dpipj(ns,ns),piDpj(ns,ns)
+ ComplexType delps1,xpi(ns),dpipj(ns,ns),piDpj(ns,ns)
*
* local variables
*
- DOUBLE COMPLEX s1,s2,s3,som,c
- DOUBLE PRECISION xmax,absc
+ ComplexType s1,s2,s3,som,c
+ RealType xmax,absc
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ stupid tree:
* 1
s1 = xpi(ip1)*piDpj(ip2,is2)
s2 = piDpj(ip1,ip2)*piDpj(ip1,is2)
delps1 = s1 - s2
if ( absc(delps1) .ge. xloss*absc(s1) ) goto 100
som = delps1
xmax = absc(s1)
* 2
s1 = piDpj(ip1,ip2)*piDpj(ip3,is2)
s2 = piDpj(ip1,ip3)*piDpj(ip2,is2)
delps1 = s1 - s2
if ( absc(delps1) .ge. xloss*absc(s1) ) goto 100
if ( absc(s1) .lt. xmax ) then
som = delps1
xmax = absc(s1)
endif
* 3
s1 = piDpj(ip1,ip3)*piDpj(ip1,is2)
s2 = xpi(ip1)*piDpj(ip3,is2)
delps1 = s1 - s2
if ( absc(delps1) .ge. xloss*absc(s1) ) goto 100
if ( absc(s1) .lt. xmax ) then
som = delps1
xmax = absc(s1)
endif
* 4
s1 = xpi(ip1)*piDpj(ip2,is1)
s2 = piDpj(ip1,is1)*piDpj(ip1,ip2)
delps1 = s1 - s2
if ( absc(delps1) .ge. xloss*absc(s1) ) goto 100
if ( absc(s1) .lt. xmax ) then
som = delps1
xmax = absc(s1)
endif
* 5
s1 = piDpj(ip1,is2)*piDpj(ip2,is1)
s2 = piDpj(ip1,is1)*piDpj(ip2,is2)
delps1 = s1 - s2
if ( absc(delps1) .ge. xloss*absc(s1) ) goto 100
if ( absc(s1) .lt. xmax ) then
som = delps1
xmax = absc(s1)
endif
* 6
s1 = piDpj(ip1,ip2)*piDpj(ip3,is1)
s2 = piDpj(ip1,ip3)*piDpj(ip2,is1)
delps1 = s1 - s2
if ( absc(delps1) .ge. xloss*absc(s1) ) goto 100
if ( absc(s1) .lt. xmax ) then
som = delps1
xmax = absc(s1)
endif
* 7
s1 = piDpj(ip2,is2)*piDpj(ip3,is1)
s2 = piDpj(ip2,is1)*piDpj(ip3,is2)
delps1 = s1 - s2
if ( absc(delps1) .ge. xloss*absc(s1) ) goto 100
if ( absc(s1) .lt. xmax ) then
som = delps1
xmax = absc(s1)
endif
* 8
s1 = piDpj(ip1,ip3)*piDpj(ip1,is1)
s2 = xpi(ip1)*piDpj(ip3,is1)
delps1 = s1 - s2
if ( absc(delps1) .ge. xloss*absc(s1) ) goto 100
if ( absc(s1) .lt. xmax ) then
som = delps1
xmax = absc(s1)
endif
* 9
s1 = piDpj(ip1,is1)*piDpj(ip3,is2)
s2 = piDpj(ip1,is2)*piDpj(ip3,is1)
delps1 = s1 - s2
if ( absc(delps1) .ge. xloss*absc(s1) ) goto 100
if ( absc(s1) .lt. xmax ) then
som = delps1
xmax = absc(s1)
endif
*10 22-nov-1993 yet another one
if ( dpipj(1,1).eq.0 ) then
s1 = +xpi(ip1)*dpipj(is3,is2)/2
s2 = -piDpj(ip1,ip2)*dpipj(is2,is1)/2
s3 = +xpi(ip1)*piDpj(ip2,ip3)/2
delps1 = s1+s2+s3
if ( absc(delps1) .ge. xloss*max(absc(s1),absc(s2)) )
+ goto 100
if ( max(absc(s1),absc(s2)) .lt. xmax ) then
som = delps1
xmax = absc(s1)
endif
endif
* NO possibility
delps1 = som
100 continue
* #] stupid tree:
*###] ffcl2p:
end
*###[ ffcl2t:
subroutine ffcl2t(delps,piDpj,in,jn,kn,ln,lkn,islk,iss,ns)
***#[*comment:***********************************************************
* *
* calculate in a numerically stable way *
* *
* \delta_{si,sj}^{sk,sl} *
* *
* with p(lk) = islk*(iss*sl - sk) (islk,iss = +/-1) *
* and NO relationship between s1,s2 assumed (so 1/2 the *
* possibilities of ffdl2s). *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer in,jn,kn,ln,lkn,islk,iss,ns
- DOUBLE COMPLEX delps,piDpj(ns,ns)
+ ComplexType delps,piDpj(ns,ns)
*
* local variables
*
- DOUBLE COMPLEX s1,s2,c
- DOUBLE PRECISION absc
+ ComplexType s1,s2,c
+ RealType absc
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ calculations:
if ( in .eq. jn ) then
delps = 0D0
return
endif
s1 = piDpj(kn,in)*piDpj(ln,jn)
s2 = piDpj(ln,in)*piDpj(kn,jn)
delps = s1 - s2
if ( absc(delps) .ge. xloss*absc(s1) ) goto 10
s1 = piDpj(kn,in)*piDpj(lkn,jn)
s2 = piDpj(lkn,in)*piDpj(kn,jn)
delps = iss*islk*(s1 - s2)
if ( absc(delps) .ge. xloss*absc(s1) ) goto 10
s1 = piDpj(lkn,in)*piDpj(ln,jn)
s2 = piDpj(ln,in)*piDpj(lkn,jn)
delps = islk*(- s1 + s2)
if ( absc(delps) .ge. xloss*absc(s1) ) goto 10
10 continue
* #] calculations:
*###] ffcl2t:
end
*###[ ffcl3m:
subroutine ffcl3m(del3mi,ldel,del3,del2,xpi,dpipj,piDpj,ns,ip1n,
+ ip2n,ip3n,is,itime)
***#[*comment:***********************************************************
* *
* Calculate xpi(i)*del2 - del3(piDpj) *
* *
* / si mu \2 (This appears to be one of the harder *
* = | d | determinants to calculate accurately. *
* \ p1 p2 / Note that we allow a loss of xloss^2) *
* *
* Input: ldel iff .true. del2 and del3 exist *
* del3 \delta^{s(1),p1,p2}_{s(1),p1,p2} *
* del2 \delta^{p1,p2}_{p1,p2} *
* xpi(ns) standard *
* dpipj(ns,ns) standard *
* piDpj(ns,ns) standard *
* ipi pi = xpi(abs(ipi)) [p3=-p1 +/-p2] *
* is si = xpi(is,is+1,..,is+itime-1) *
* itime number of functions to calculate *
* *
* Output: del3mi(3) (\delta^{s_i \mu}_{p_1 p_2})^2 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ns,ip1n,ip2n,ip3n,is,itime
logical ldel
- DOUBLE COMPLEX del3mi(itime),del3,del2,xpi(ns),dpipj(ns,ns),
+ ComplexType del3mi(itime),del3,del2,xpi(ns),dpipj(ns,ns),
+ piDpj(ns,ns)
*
* local variables:
*
- DOUBLE PRECISION smax,xmax,absc
- DOUBLE COMPLEX s(7),som,xsom,c
+ RealType smax,xmax,absc
+ ComplexType s(7),som,xsom,c
integer i,j,k,ip1,ip2,ip3,ipn,is1,is2,isi,is3,ihlp,iqn,
+ jsgn1,jsgn2,jsgn3,jsgnn,iadj(10,10,3:4),init,nm
save iadj,init
logical lmax,ltwist
*
* common blocks:
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
*
* data
*
data iadj /200*0/
data init /0/
* #] declarations:
* #[ initialisations:
if ( init .eq. 0 ) then
init = 1
*
* Fill the array with adjacent values: if
* x = iadj(i,j)
* k = abs(mod(k,100))
* jsgnk = sign(x)
* jsgnj = 1-2*theta(x-100) (ie -1 iff |x|>100)
* then
* pi(k) = jsgnk*( p(i) - jsgnj*pi(j) )
*
do 5 nm=3,4
do 4 i=1,nm
is1 = i
is2 = i+1
if ( is2 .gt. nm ) is2 = 1
is3 = i-1
if ( is3 .eq. 0 ) is3 = nm
ip1 = is1 + nm
iadj(is1,is2,nm) = -ip1
iadj(is2,is1,nm) = ip1
iadj(ip1,is2,nm) = -is1
iadj(is2,ip1,nm) = is1
iadj(is1,ip1,nm) = 100+is2
iadj(ip1,is1,nm) = 100+is2
if ( nm .eq. 3 ) then
iadj(ip1,is2+3,3) = -100-is3-3
iadj(is2+3,ip1,3) = -100-is3-3
endif
4 continue
5 continue
iadj(3,1,4) = -9
iadj(1,3,4) = 9
iadj(9,1,4) = -3
iadj(1,9,4) = 3
iadj(3,9,4) = 100+1
iadj(9,3,4) = 100+1
iadj(2,4,4) = -10
iadj(4,2,4) = 10
iadj(10,4,4) = -2
iadj(4,10,4) = 2
iadj(2,10,4) = 100+4
iadj(10,2,4) = 100+4
endif
if ( ns .eq. 6 ) then
nm = 3
else
nm = 4
endif
* #] initialisations:
* #[ easy tries:
do 40 i=1,itime
isi = i+is-1
lmax = .FALSE.
*
* get xpi(isi)*del2 - del3 ... if del3 and del2 are defined
*
if ( ldel ) then
s(1) = xpi(isi)*del2
som = s(1) - del3
smax = absc(s(1))
if ( absc(som) .ge. xloss**2*smax ) goto 35
xsom = som
xmax = smax
lmax = .TRUE.
endif
ip1 = ip1n
ip2 = ip2n
ip3 = ip3n
do 20 j=1,3
*
* otherwise use the simple threeterm formula
*
s(1) = xpi(ip2)*piDpj(ip1,isi)**2
s(2) = xpi(ip1)*piDpj(ip2,isi)*piDpj(ip2,isi)
s(3) = -2*piDpj(ip2,isi)*piDpj(ip2,ip1)*piDpj(ip1,isi)
som = s(1) + s(2) + s(3)
smax = max(absc(s(1)),absc(s(2)),absc(s(3)))
if ( absc(som) .ge. xloss**2*smax ) goto 35
if ( .not. lmax .or. smax .lt. xmax ) then
xsom = som
xmax = smax
lmax = .TRUE.
endif
*
* if there are cancellations between two of the terms:
* we try mixing with isi.
*
* First map cancellation to s(2)+s(3) (do not mess up
* rotations...)
*
if ( absc(s(1)+s(3)) .lt. absc(s(3))/2 ) then
ihlp = ip1
ip1 = ip2
ip2 = ihlp
som = s(1)
s(1) = s(2)
s(2) = som
ltwist = .TRUE.
else
ltwist = .FALSE.
endif
if ( absc(s(2)+s(3)) .lt. absc(s(3))/2 ) then
*
* switch to the vector pn so that si = jsgn1*p1 + jsgnn*pn
*
k = iadj(isi,ip1,nm)
if ( k .ne. 0 ) then
ipn = abs(k)
jsgnn = isign(1,k)
if ( ipn .gt. 100 ) then
ipn = ipn - 100
jsgn1 = -1
else
jsgn1 = +1
endif
if ( absc(dpipj(ipn,isi)) .lt.
+ xloss*absc(piDpj(ip1,isi)) .and.
+ absc(piDpj(ipn,ip2)) .lt.
+ xloss*absc(piDpj(ip2,isi)) ) then
* same: s(1) = xpi(ip2)*piDpj(ip1,isi)**2
s(2) = jsgnn*piDpj(isi,ip2)*piDpj(ipn,ip2)*
+ xpi(ip1)
s(3) = jsgn1*piDpj(isi,ip2)*piDpj(ip1,ip2)*
+ dpipj(ipn,isi)
som = s(1) + s(2) + s(3)
smax = max(absc(s(1)),absc(s(2)),absc(s(3)))
* print *,' (isi+ip1) with isi,ip1,ip2,ipn: ',
* + isi,ip1,ip2,ipn
* print *,'xpi(ip2),piDpj(ip1,isi)',xpi(ip2),
* + piDpj(ip1,isi)
* print *,'piDpj(isi,ip2),piDpj(ipn,ip2),xpi(ip1)'
* + ,piDpj(isi,ip2),piDpj(ipn,ip2),xpi(ip1)
if ( absc(som) .ge. xloss**2*smax ) goto 35
if ( smax .lt. xmax ) then
xsom = som
xmax = smax
endif
*
* there may be a cancellation between s(1) and
* s(2) left. Introduce a vector q such that
* pn = jsgnq*q + jsgn2*p2. We also need the sign
* jsgn3 in p3 = -p1 - jsgn3*p2
*
k = iadj(ipn,ip2,nm)
if ( k .ne. 0 ) then
iqn = abs(k)
*not used jsgnq = isign(1,k)
if ( iqn .gt. 100 ) then
iqn = iqn - 100
jsgn2 = -1
else
jsgn2 = +1
endif
k = iadj(ip1,ip2,nm)
if ( k .eq. 0 .or. k .lt. 100 ) then
* we have p1,p2,p3 all p's
jsgn3 = +1
elseif ( k .lt. 0 ) then
* ip1,ip2 are 2*s,1*p such that p2-p1=ip3
jsgn3 = -1
else
jsgn3 = 0
endif
* we need one condition on the signs for this
* to work
if ( ip3.ne.0 .and. jsgn1*jsgn2.eq.jsgnn*
+ jsgn3 .and. absc(s(3)).lt.xloss*smax ) then
s(1) = piDpj(ip1,isi)**2*dpipj(iqn,ipn)
s(2) = -jsgn2*jsgn1*piDpj(ipn,ip2)*
+ piDpj(ip1,isi)*dpipj(ipn,isi)
* s(3) stays the same
s(4) = -jsgn2*jsgn1*piDpj(ipn,ip2)*
+ xpi(ip1)*piDpj(isi,ip3)
som = s(1) + s(2) + s(3) + s(4)
smax = max(absc(s(1)),absc(s(2)),
+ absc(s(3)),absc(s(4)))
if (absc(som).ge.xloss**2*smax) goto 35
if ( smax .lt. xmax ) then
xsom = som
xmax = smax
endif
endif
endif
endif
endif
k = iadj(isi,ip2,nm)
if ( k .ne. 0 ) then
ipn = abs(k)
jsgnn = isign(1,k)
if ( ipn .gt. 100 ) then
jsgn1 = -1
ipn = ipn - 100
else
jsgn1 = +1
endif
if ( absc(dpipj(ipn,isi)) .lt.
+ xloss*absc(piDpj(ip2,isi)) .and.
+ absc(piDpj(ipn,ip1)) .lt.
+ xloss*absc(piDpj(ip1,isi)) ) then
s(1) = jsgnn*piDpj(isi,ip1)*piDpj(ipn,ip1)*
+ xpi(ip2)
s(2) = xpi(ip1)*piDpj(ip2,isi)**2
s(3) = jsgn1*piDpj(isi,ip1)*piDpj(ip2,ip1)*
+ dpipj(ipn,isi)
som = s(1) + s(2) + s(3)
smax = max(absc(s(1)),absc(s(2)),absc(s(3)))
print *,' (isi+ip2) with isi,ip1,ip2,ipn: ',
+ isi,ip1,ip2,ipn
if ( absc(som) .ge. xloss**2*smax ) goto 35
if ( smax .lt. xmax ) then
xsom = som
xmax = smax
endif
endif
endif
endif
*
* rotate the ipi
*
if ( ip3 .eq. 0 ) goto 30
if ( j .ne. 3 ) then
if ( .not. ltwist ) then
ihlp = ip1
ip1 = ip2
ip2 = ip3
ip3 = ihlp
else
ihlp = ip2
ip2 = ip3
ip3 = ihlp
endif
endif
20 continue
30 continue
* #] easy tries:
* #[ choose the best value:
*
* These values are the best found:
*
som = xsom
smax = xmax
35 continue
del3mi(i) = som
40 continue
* #] choose the best value:
*###] ffcl3m:
end
diff --git a/Looptools/B/ffdel2.F b/Looptools/B/ffdel2.F
--- a/Looptools/B/ffdel2.F
+++ b/Looptools/B/ffdel2.F
@@ -1,630 +1,631 @@
#include "externals.h"
+#include "types.h"
*###[ ffdel2:
subroutine ffdel2(del2,piDpj,ns,i1,i2,i3,lerr,ier)
*************************************************************************
* calculate in a numerically stable way *
* del2(piDpj(i1,i1),piDpj(i2,i2),piDpj(i3,i3)) = *
* = piDpj(i1,i1)*piDpj(i2,i2) - piDpj(i1,i2)^2 *
* = piDpj(i1,i1)*piDpj(i3,i3) - piDpj(i1,i3)^2 *
* = piDpj(i2,i2)*piDpj(i3,i3) - piDpj(i2,i3)^2 *
* ier is the usual error flag. *
*************************************************************************
implicit none
*
* arguments:
*
integer ns,i1,i2,i3,lerr,ier
- DOUBLE PRECISION del2,piDpj(ns,ns)
+ RealType del2,piDpj(ns,ns)
*
* local variables
*
- DOUBLE PRECISION s1,s2
+ RealType s1,s2
*
* common blocks
*
#include "ff.h"
*
* calculations
*
idsub = idsub + 1
if ( abs(piDpj(i1,i2)) .lt. abs(piDpj(i1,i3)) .and.
+ abs(piDpj(i1,i2)) .lt. abs(piDpj(i2,i3)) ) then
s1 = piDpj(i1,i1)*piDpj(i2,i2)
s2 = piDpj(i1,i2)**2
elseif ( abs(piDpj(i1,i3)) .lt. abs(piDpj(i2,i3)) ) then
s1 = piDpj(i1,i1)*piDpj(i3,i3)
s2 = piDpj(i1,i3)**2
else
s1 = piDpj(i2,i2)*piDpj(i3,i3)
s2 = piDpj(i2,i3)**2
endif
del2 = s1 - s2
if ( abs(del2) .lt. xloss*s2 ) then
if ( lerr .eq. 0 ) then
* we know we have another chance
if ( del2.ne.0 ) then
ier = ier + int(log10(xloss*abs(s2/del2)))
else
ier = ier + int(log10(xloss*abs(s2)/xclogm))
endif
endif
endif
*###] ffdel2:
end
*###[ ffdl2p:
subroutine ffdl2p(delps1,xpi,dpipj,piDpj,
+ ip1,ip2,ip3,is1,is2,is3,ns)
***#[*comment:***********************************************************
* *
* calculate in a numerically stable way *
* delta_{ip1,is2}^{ip1,ip2} *
* ier is the usual error flag. *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ns,ip1,ip2,ip3,is1,is2,is3
- DOUBLE PRECISION delps1,xpi(ns),dpipj(ns,ns),piDpj(ns,ns)
+ RealType delps1,xpi(ns),dpipj(ns,ns),piDpj(ns,ns)
*
* local variables
*
- DOUBLE PRECISION s1,s2,s3,xmax,som
+ RealType s1,s2,s3,xmax,som
*
* common blocks
*
#include "ff.h"
* #] declarations:
* #[ stupid tree:
* 1
s1 = xpi(ip1)*piDpj(ip2,is2)
s2 = piDpj(ip1,ip2)*piDpj(ip1,is2)
delps1 = s1 - s2
if ( abs(delps1) .ge. xloss*abs(s1) ) goto 100
som = delps1
xmax = abs(s1)
* 2
s1 = piDpj(ip1,ip2)*piDpj(ip3,is2)
s2 = piDpj(ip1,ip3)*piDpj(ip2,is2)
delps1 = s1 - s2
if ( abs(delps1) .ge. xloss*abs(s1) ) goto 100
if ( abs(s1) .lt. xmax ) then
som = delps1
xmax = abs(s1)
endif
* 3
s1 = piDpj(ip1,ip3)*piDpj(ip1,is2)
s2 = xpi(ip1)*piDpj(ip3,is2)
delps1 = s1 - s2
if ( abs(delps1) .ge. xloss*abs(s1) ) goto 100
if ( abs(s1) .lt. xmax ) then
som = delps1
xmax = abs(s1)
endif
* 4
s1 = xpi(ip1)*piDpj(ip2,is1)
s2 = piDpj(ip1,is1)*piDpj(ip1,ip2)
delps1 = s1 - s2
if ( abs(delps1) .ge. xloss*abs(s1) ) goto 100
if ( abs(s1) .lt. xmax ) then
som = delps1
xmax = abs(s1)
endif
* 5
s1 = piDpj(ip1,is2)*piDpj(ip2,is1)
s2 = piDpj(ip1,is1)*piDpj(ip2,is2)
delps1 = s1 - s2
if ( abs(delps1) .ge. xloss*abs(s1) ) goto 100
if ( abs(s1) .lt. xmax ) then
som = delps1
xmax = abs(s1)
endif
* 6
s1 = piDpj(ip1,ip2)*piDpj(ip3,is1)
s2 = piDpj(ip1,ip3)*piDpj(ip2,is1)
delps1 = s1 - s2
if ( abs(delps1) .ge. xloss*abs(s1) ) goto 100
if ( abs(s1) .lt. xmax ) then
som = delps1
xmax = abs(s1)
endif
* 7
s1 = piDpj(ip2,is2)*piDpj(ip3,is1)
s2 = piDpj(ip2,is1)*piDpj(ip3,is2)
delps1 = s1 - s2
if ( abs(delps1) .ge. xloss*abs(s1) ) goto 100
if ( abs(s1) .lt. xmax ) then
som = delps1
xmax = abs(s1)
endif
* 8
s1 = piDpj(ip1,ip3)*piDpj(ip1,is1)
s2 = xpi(ip1)*piDpj(ip3,is1)
delps1 = s1 - s2
if ( abs(delps1) .ge. xloss*abs(s1) ) goto 100
if ( abs(s1) .lt. xmax ) then
som = delps1
xmax = abs(s1)
endif
* 9
s1 = piDpj(ip1,is1)*piDpj(ip3,is2)
s2 = piDpj(ip1,is2)*piDpj(ip3,is1)
delps1 = s1 - s2
if ( abs(delps1) .ge. xloss*abs(s1) ) goto 100
if ( abs(s1) .lt. xmax ) then
som = delps1
xmax = abs(s1)
endif
*10 22-nov-1993 yet another one
if ( dpipj(1,1).eq.0 ) then
s1 = +xpi(ip1)*dpipj(is3,is2)/2
s2 = -piDpj(ip1,ip2)*dpipj(is2,is1)/2
s3 = +xpi(ip1)*piDpj(ip2,ip3)/2
delps1 = s1+s2+s3
if ( abs(delps1) .ge. xloss*max(abs(s1),abs(s2)) ) goto 100
if ( max(abs(s1),abs(s2)) .lt. xmax ) then
som = delps1
xmax = abs(s1)
endif
endif
* NO possibility
delps1 = som
100 continue
* #] stupid tree:
*###] ffdl2p:
end
*###[ ffdl2s:
subroutine ffdl2s(delps1,piDpj,in,jn,jin,isji,
+ kn,ln,lkn,islk,ns)
***#[*comment:***********************************************************
* *
* calculate in a numerically stable way *
* *
* \delta_{si,sj}^{sk,sl} *
* *
* with p(ji) = isji*(sj-si) *
* p(lk) = islk*(sl-sk) *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer in,jn,jin,isji,kn,ln,lkn,islk,ns
- DOUBLE PRECISION delps1,piDpj(ns,ns)
+ RealType delps1,piDpj(ns,ns)
*
* local variables
*
integer ii,jj,i,j,ji,k,l,lk,ihlp
- DOUBLE PRECISION s1,s2,som,smax
+ RealType s1,s2,som,smax
*
* common blocks
*
#include "ff.h"
* #] declarations:
* #[ stupid tree:
idsub = idsub + 1
som = 0
smax = 0
i = in
j = jn
ji = jin
k = kn
l = ln
lk = lkn
do 20 ii=1,3
do 10 jj=1,3
s1 = piDpj(i,k)*piDpj(j,l)
s2 = piDpj(i,l)*piDpj(j,k)
delps1 = s1 - s2
if ( ii .gt. 1 ) delps1 = isji*delps1
if ( jj .gt. 1 ) delps1 = islk*delps1
if ( ii .eq. 3 .neqv. jj .eq. 3 ) delps1 = -delps1
if ( abs(delps1) .ge. xloss*abs(s1) ) goto 30
*
* Save the most accurate estimate so far:
if ( ii .eq. 1 .and. jj .eq. 1 .or. abs(s1) .lt. smax
+ ) then
som = delps1
smax = abs(s1)
endif
*
* rotate the jj's
if ( lk .eq. 0 ) goto 20
ihlp = k
k = l
l = lk
lk = ihlp
10 continue
*
* and the ii's
if ( ji .eq. 0 ) goto 25
ihlp = i
i = j
j = ji
ji = ihlp
20 continue
25 continue
delps1 = som
30 continue
* #] stupid tree:
*###] ffdl2s:
end
*###[ ffdl2t:
subroutine ffdl2t(delps,piDpj,in,jn,kn,ln,lkn,islk,iss,ns)
***#[*comment:***********************************************************
* *
* calculate in a numerically stable way *
* *
* \delta_{si,sj}^{sk,sl} *
* *
* with p(lk) = islk*(iss*sl - sk) (islk,iss = +/-1) *
* and NO relationship between s1,s2 assumed (so 1/2 the *
* possibilities of ffdl2s). *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer in,jn,kn,ln,lkn,islk,iss,ns
- DOUBLE PRECISION delps,piDpj(ns,ns)
+ RealType delps,piDpj(ns,ns)
*
* local variables
*
- DOUBLE PRECISION s1,s2,som,smax
+ RealType s1,s2,som,smax
*
* common blocks
*
#include "ff.h"
* #] declarations:
* #[ calculations:
if ( in .eq. jn ) then
delps = 0
return
endif
s1 = piDpj(kn,in)*piDpj(ln,jn)
s2 = piDpj(ln,in)*piDpj(kn,jn)
delps = s1 - s2
if ( abs(delps) .ge. xloss*abs(s1) ) goto 20
som = delps
smax = abs(s1)
s1 = piDpj(kn,in)*piDpj(lkn,jn)
s2 = piDpj(lkn,in)*piDpj(kn,jn)
delps = iss*islk*(s1 - s2)
if ( abs(delps) .ge. xloss*abs(s1) ) goto 20
if ( abs(s1) .lt. smax ) then
som = delps
smax = abs(s1)
endif
s1 = piDpj(lkn,in)*piDpj(ln,jn)
s2 = piDpj(ln,in)*piDpj(lkn,jn)
delps = islk*(- s1 + s2)
if ( abs(delps) .ge. xloss*abs(s1) ) goto 20
if ( abs(s1) .lt. smax ) then
som = delps
smax = abs(s1)
endif
*
* give up
*
delps = som
20 continue
* #] calculations:
*###] ffdl2t:
end
*###[ ffdl3m:
subroutine ffdl3m(del3mi,ldel,del3,del2,xpi,dpipj,piDpj,ns,ip1n,
+ ip2n,ip3n,is,itime)
***#[*comment:***********************************************************
* *
* Calculate xpi(i)*del2 - del3(piDpj) *
* *
* / si mu \2 (This appears to be one of the harder *
* = | d | determinants to calculate accurately. *
* \ p1 p2 / Note that we allow a loss of xloss^2) *
* *
* Input: ldel iff .true. del2 and del3 exist *
* del3 \delta^{s(1),p1,p2}_{s(1),p1,p2} *
* del2 \delta^{p1,p2}_{p1,p2} *
* xpi(ns) standard *
* dpipj(ns,ns) standard *
* piDpj(ns,ns) standard *
* ipi pi = xpi(abs(ipi)) [p3=-p1 +/-p2] *
* is si = xpi(is,is+1,..,is+itime-1) *
* itime number of functions to calculate *
* *
* Output: del3mi(3) (\delta^{s_i \mu}_{p_1 p_2})^2 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ns,ip1n,ip2n,ip3n,is,itime
logical ldel
- DOUBLE PRECISION del3mi(itime),del3,del2,xpi(ns),dpipj(ns,ns),
+ RealType del3mi(itime),del3,del2,xpi(ns),dpipj(ns,ns),
+ piDpj(ns,ns)
*
* local variables:
*
- DOUBLE PRECISION s(7),som,smax,xsom,xmax
+ RealType s(7),som,smax,xsom,xmax
integer i,j,k,ip1,ip2,ip3,ipn,is1,is2,isi,is3,ihlp,iqn,
+ jsgn1,jsgn2,jsgn3,jsgnn,iadj(10,10,3:4),init,nm
save iadj,init
logical lmax,ltwist
*
* common blocks:
*
#include "ff.h"
*
* data
*
data iadj /200*0/
data init /0/
* #] declarations:
* #[ initialisations:
if ( init .eq. 0 ) then
init = 1
*
* Fill the array with adjacent values: if
* x = iadj(i,j)
* k = abs(mod(k,100))
* jsgnk = sign(x)
* jsgnj = 1-2*theta(x-100) (ie -1 iff |x|>100)
* then
* pi(k) = jsgnk*( p(i) - jsgnj*pi(j) )
*
do 5 nm=3,4
do 4 i=1,nm
is1 = i
is2 = i+1
if ( is2 .gt. nm ) is2 = 1
is3 = i-1
if ( is3 .eq. 0 ) is3 = nm
ip1 = is1 + nm
iadj(is1,is2,nm) = -ip1
iadj(is2,is1,nm) = ip1
iadj(ip1,is2,nm) = -is1
iadj(is2,ip1,nm) = is1
iadj(is1,ip1,nm) = 100+is2
iadj(ip1,is1,nm) = 100+is2
if ( nm .eq. 3 ) then
iadj(ip1,is2+3,3) = -100-is3-3
iadj(is2+3,ip1,3) = -100-is3-3
endif
4 continue
5 continue
iadj(3,1,4) = -9
iadj(1,3,4) = 9
iadj(9,1,4) = -3
iadj(1,9,4) = 3
iadj(3,9,4) = 100+1
iadj(9,3,4) = 100+1
iadj(2,4,4) = -10
iadj(4,2,4) = 10
iadj(10,4,4) = -2
iadj(4,10,4) = 2
iadj(2,10,4) = 100+4
iadj(10,2,4) = 100+4
endif
if ( ns .eq. 6 ) then
nm = 3
else
nm = 4
endif
* #] initialisations:
* #[ easy tries:
do 40 i=1,itime
isi = i+is-1
lmax = .FALSE.
*
* get xpi(isi)*del2 - del3 ... if del3 and del2 are defined
*
if ( ldel ) then
s(1) = xpi(isi)*del2
som = s(1) - del3
smax = abs(s(1))
if ( abs(som) .ge. xloss**2*smax ) goto 35
xsom = som
xmax = smax
lmax = .TRUE.
endif
ip1 = ip1n
ip2 = ip2n
ip3 = ip3n
do 20 j=1,3
*
* otherwise use the simple threeterm formula
*
s(1) = xpi(ip2)*piDpj(ip1,isi)**2
s(2) = xpi(ip1)*piDpj(ip2,isi)*piDpj(ip2,isi)
s(3) = -2*piDpj(ip2,isi)*piDpj(ip2,ip1)*piDpj(ip1,isi)
som = s(1) + s(2) + s(3)
smax = max(abs(s(1)),abs(s(2)),abs(s(3)))
if ( abs(som) .ge. xloss**2*smax ) goto 35
if ( .not. lmax .or. smax .lt. xmax ) then
xsom = som
xmax = smax
lmax = .TRUE.
endif
*
* if there are cancellations between two of the terms:
* we try mixing with isi.
*
* First map cancellation to s(2)+s(3) (do not mess up
* rotations...)
*
if ( abs(s(1)+s(3)) .lt. abs(s(3))/2 ) then
ihlp = ip1
ip1 = ip2
ip2 = ihlp
som = s(1)
s(1) = s(2)
s(2) = som
ltwist = .TRUE.
else
ltwist = .FALSE.
endif
if ( abs(s(2)+s(3)) .lt. abs(s(3))/2 ) then
*
* switch to the vector pn so that si = jsgn1*p1 + jsgnn*pn
*
k = iadj(isi,ip1,nm)
if ( k .ne. 0 ) then
ipn = abs(k)
jsgnn = isign(1,k)
if ( ipn .gt. 100 ) then
ipn = ipn - 100
jsgn1 = -1
else
jsgn1 = +1
endif
if (abs(dpipj(ipn,isi)).lt.xloss*abs(piDpj(ip1,isi))
+ .and.
+ abs(piDpj(ipn,ip2)).lt.xloss*abs(piDpj(ip2,isi))
+ ) then
* same: s(1) = xpi(ip2)*piDpj(ip1,isi)**2
s(2) = jsgnn*piDpj(isi,ip2)*piDpj(ipn,ip2)*
+ xpi(ip1)
s(3) = jsgn1*piDpj(isi,ip2)*piDpj(ip1,ip2)*
+ dpipj(ipn,isi)
som = s(1) + s(2) + s(3)
smax = max(abs(s(1)),abs(s(2)),abs(s(3)))
if ( abs(som) .ge. xloss**2*smax ) goto 35
if ( smax .lt. xmax ) then
xsom = som
xmax = smax
endif
*
* there may be a cancellation between s(1) and
* s(2) left. Introduce a vector q such that
* pn = jsgnq*q + jsgn2*p2. We also need the sign
* jsgn3 in p3 = -p1 - jsgn3*p2
*
k = iadj(ipn,ip2,nm)
if ( k .ne. 0 ) then
iqn = abs(k)
if ( iqn .gt. 100 ) then
iqn = iqn - 100
jsgn2 = -1
else
jsgn2 = +1
endif
k = iadj(ip1,ip2,nm)
if ( k .eq. 0 .or. k .lt. 100 ) then
* we have p1,p2,p3 all p's
jsgn3 = +1
elseif ( k .lt. 0 ) then
* ip1,ip2 are 2*s,1*p such that p2-p1=ip3
jsgn3 = -1
else
jsgn3 = 0
endif
* we need one condition on the signs for this
* to work
if ( ip3.ne.0 .and. jsgn1*jsgn2.eq.jsgnn*
+ jsgn3 .and. abs(s(3)).lt.xloss*smax ) then
s(1) = piDpj(ip1,isi)**2*dpipj(iqn,ipn)
s(2) = -jsgn2*jsgn1*piDpj(ipn,ip2)*
+ piDpj(ip1,isi)*dpipj(ipn,isi)
* s(3) stays the same
s(4) = -jsgn2*jsgn1*piDpj(ipn,ip2)*
+ xpi(ip1)*piDpj(isi,ip3)
som = s(1) + s(2) + s(3) + s(4)
smax =max(abs(s(1)),abs(s(2)),abs(s(3)),
+ abs(s(4)))
if ( abs(som).ge.xloss**2*smax ) goto 35
if ( smax .lt. xmax ) then
xsom = som
xmax = smax
endif
endif
endif
endif
endif
k = iadj(isi,ip2,nm)
if ( k .ne. 0 ) then
ipn = abs(k)
jsgnn = isign(1,k)
if ( ipn .gt. 100 ) then
jsgn1 = -1
ipn = ipn - 100
else
jsgn1 = +1
endif
if (abs(dpipj(ipn,isi)).lt.xloss*abs(piDpj(ip2,isi))
+ .and.
+ abs(piDpj(ipn,ip1)).lt.xloss*abs(piDpj(ip1,isi))
+ ) then
s(1) = jsgnn*piDpj(isi,ip1)*piDpj(ipn,ip1)*
+ xpi(ip2)
s(2) = xpi(ip1)*piDpj(ip2,isi)**2
s(3) = jsgn1*piDpj(isi,ip1)*piDpj(ip2,ip1)*
+ dpipj(ipn,isi)
som = s(1) + s(2) + s(3)
smax = max(abs(s(1)),abs(s(2)),abs(s(3)))
print *,' (isi+ip2) with isi,ip1,ip2,ipn: ',
+ isi,ip1,ip2,ipn
if ( abs(som) .ge. xloss**2*smax ) goto 35
if ( smax .lt. xmax ) then
xsom = som
xmax = smax
endif
endif
endif
endif
*
* rotate the ipi
*
if ( ip3 .eq. 0 ) goto 30
if ( j .ne. 3 ) then
if ( .not. ltwist ) then
ihlp = ip1
ip1 = ip2
ip2 = ip3
ip3 = ihlp
else
ihlp = ip2
ip2 = ip3
ip3 = ihlp
endif
endif
20 continue
30 continue
* #] easy tries:
* #[ choose the best value:
*
* These values are the best found:
*
som = xsom
smax = xmax
35 continue
del3mi(i) = som
40 continue
* #] choose the best value:
*###] ffdl3m:
end
diff --git a/Looptools/B/ffxb0.F b/Looptools/B/ffxb0.F
--- a/Looptools/B/ffxb0.F
+++ b/Looptools/B/ffxb0.F
@@ -1,964 +1,968 @@
#include "externals.h"
+#include "types.h"
*###[ ffxb0:
subroutine ffxb0(cb0,xp,xma,xmb,ier)
***#[*comment:***********************************************************
* *
* Calculates the the two-point function (cf 't Hooft and Veltman) *
* we include an overall factor 1/(i*pi^2) relative to FormF *
* *
* Input: xp (real) k2, in B&D metric *
* xma (real) mass2 *
* xmb (real) mass2 *
* *
* Output: cb0 (complex) B0, the two-point function, *
* ier (integer) # of digits lost, if >=100: error *
* *
* Calls: ffxb0p *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE COMPLEX cb0
- DOUBLE PRECISION xp,xma,xmb
+ ComplexType cb0
+ RealType xp,xma,xmb
*
* local variables
*
- DOUBLE COMPLEX cb0p
- DOUBLE PRECISION dmamb,dmap,dmbp,xm
+ ComplexType cb0p
+ RealType dmamb,dmap,dmbp,xm
*
* common blocks
*
#include "ff.h"
*
* #] declarations:
* #[ get differences:
dmamb = xma - xmb
dmap = xma - xp
dmbp = xmb - xp
* #] get differences:
* #[ calculations:
call ffxb0p(cb0p,xp,xma,xmb,dmap,dmbp,dmamb,ier)
if ( xma .eq. 0 ) then
if ( xmb .eq. 0 ) then
xm = 1D0
else
xm = xmb**2
endif
elseif ( xmb .eq. 0 ) then
xm = xma**2
else
xm = xma*xmb
endif
if ( mudim .ne. 0 ) xm = xm/mudim**2
if ( abs(xm) .gt. xalogm ) then
- cb0 = DBLE(delta - log(xm)/2D0) - cb0p
+ cb0 = Re(delta - log(xm)/2D0) - cb0p
else
call fferr(4,ier)
- cb0 = DBLE(delta) - cb0p
+ cb0 = Re(delta) - cb0p
endif
* #] calculations:
*###] ffxb0:
end
*###[ ffxb0p:
subroutine ffxb0p(cb0p,xp,xma,xmb,dmap,dmbp,dmamb,ier)
***#[*comment:***********************************************************
* *
* calculates the two-point function (see 't Hooft and *
* Veltman) for all possible cases: masses equal, unequal, *
* equal to zero. *
* *
* Input: xp (real) p.p, in B&D metric *
* xma (real) mass2, *
* xmb (real) mass2, *
* dm[ab]p (real) xm[ab] - xp *
* dmamb (real) xma - xmb *
* *
* Output: cb0p (complex) B0, the two-point function, minus *
* log(xm1*xm2)/2, delta and ipi^2 *
* ier (integer) 0=ok, 1=numerical problems, 2=error *
* *
* Calls: ffxb0q. *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE COMPLEX cb0p
- DOUBLE PRECISION xp,xma,xmb,dmap,dmbp,dmamb
+ ComplexType cb0p
+ RealType xp,xma,xmb,dmap,dmbp,dmamb
*
* local variables
*
integer i,initeq,initn1,jsign
- DOUBLE PRECISION ax,ay,ffbnd,
+ RealType ax,ay,ffbnd,
+ xprceq,bdeq01,bdeq05,bdeq11,bdeq17,
+ xprcn1,bdn101,bdn105,bdn110,bdn115,
+ xprnn2,bdn205,bdn210,bdn215,bdn220,
+ xprcn3,bdn301,bdn305,bdn310,bdn315,
+ xprcn5,bdn501,bdn505,bdn510,bdn515,
+ absc
- DOUBLE PRECISION xm,dmp,xm1,xm2,dm1m2,dm1p,
+ RealType xm,dmp,xm1,xm2,dm1m2,dm1p,
+ dm2p,s,s1,s1a,s1b,s1p,s2,s2a,s2b,s2p,x,y,som,
+ xlam,slam,xlogmm,alpha,alph1,xnoe,xpneq(30),
+ xpnn1(30),xx,xtel,dfflo1
- DOUBLE COMPLEX cs2a,cs2b,cs2p,c,cx
+ ComplexType cs2a,cs2b,cs2p,c,cx
external ffbnd,dfflo1
save initeq,initn1,xpneq,xpnn1,
+ xprceq,bdeq01,bdeq05,bdeq11,bdeq17,
+ xprcn1,bdn101,bdn105,bdn110,bdn115,
+ xprnn2,bdn205,bdn210,bdn215,bdn220,
+ xprcn3,bdn301,bdn305,bdn310,bdn315,
+ xprcn5,bdn501,bdn505,bdn510,bdn515
*
* common blocks
*
#include "ff.h"
*
* data
*
data xprceq /-1D0/
data xprcn1 /-1D0/
data xprnn2 /-1D0/
data xprcn3 /-1D0/
data xprcn5 /-1D0/
data initeq /0/
data initn1 /0/
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ fill some dotproducts:
if ( ldot ) then
call ffdot2(fpij2,xp,xma,xmb,dmap,dmbp,dmamb,ier)
endif
* #] fill some dotproducts:
* #[ which case:
*
* sort according to the type of masscombination encountered:
* 100: both masses zero, 200: one equal to zero, 300: both equal
* 400: rest.
*
if ( xma .eq. 0 ) then
if ( xmb .eq. 0 ) then
goto 100
endif
xm = xmb
dmp = dmbp
goto 200
endif
if ( xmb .eq. 0 ) then
xm = xma
dmp = dmap
goto 200
elseif ( dmamb .eq. 0 ) then
xm = xma
dmp = dmap
goto 300
elseif ( xma .gt. xmb ) then
xm2 = xma
xm1 = xmb
dm1m2 = -dmamb
dm1p = dmbp
dm2p = dmap
else
xm1 = xma
xm2 = xmb
dm1m2 = dmamb
dm1p = dmap
dm2p = dmbp
endif
goto 400
* #] which case:
* #[ both masses equal to zero:
100 continue
if ( xp .lt. -xalogm ) then
cb0p = log(-xp) - 2
elseif ( xp .gt. xalogm ) then
- cb0p = DCMPLX( DBLE(log(xp) - 2), DBLE(-pi) )
+ cb0p = ToComplex( Re(log(xp) - 2), Re(-pi) )
else
cb0p = 0
call fferr(7,ier)
endif
return
* #] both masses equal to zero:
* #[ one mass equal to zero:
200 continue
*
* special case xp = 0
*
if ( xp .eq. 0 ) then
cb0p = -1
goto 990
*
* special case xp = xm
*
elseif ( dmp.eq.0 ) then
cb0p = -2
goto 990
endif
*
* Normal case:
*
s1 = xp/xm
if ( abs(s1) .lt. xloss ) then
s = dfflo1(s1,ier)
else
s = log(abs(dmp/xm))
endif
s = -s*dmp/xp
cb0p = s - 2
if ( xp .gt. xm )
- + cb0p = cb0p - DCMPLX(0D0,-(dmp/xp)*pi)
+ + cb0p = cb0p - ToComplex(0D0,-(dmp/xp)*pi)
goto 990
* #] one mass equal to zero:
* #[ both masses equal:
300 continue
*
* Both masses are equal. Not only this speeds up things, some
* cancellations have to be avoided as well.
*
* first a special case
*
if ( abs(xp) .lt. 8*xloss*xm ) then
* -#[ taylor expansion:
*
* a Taylor expansion seems appropriate as the result will go
* as k^2 but seems to go as 1/k !!
*
*--#[ data and bounds:
if ( initeq .eq. 0 ) then
initeq = 1
xpneq(1) = 1D0/6D0
do 1 i=2,30
- xpneq(i) = - xpneq(i-1)*DBLE(i-1)/DBLE(2*(2*i+1))
+ xpneq(i) = - xpneq(i-1)*Re(i-1)/Re(2*(2*i+1))
1 continue
endif
if (xprceq .ne. precx ) then
*
* calculate the boundaries for the number of terms to be
* included in the taylorexpansion
*
xprceq = precx
bdeq01 = ffbnd(1,1,xpneq)
bdeq05 = ffbnd(1,5,xpneq)
bdeq11 = ffbnd(1,11,xpneq)
bdeq17 = ffbnd(1,17,xpneq)
endif
*--#] data and bounds:
x = -xp/xm
ax = abs(x)
if ( ax .gt. bdeq17 ) then
som = x*(xpneq(18) + x*(xpneq(19) + x*(xpneq(20) +
+ x*(xpneq(21) + x*(xpneq(22) + x*(xpneq(23) +
+ x*(xpneq(24) + x*xpneq(25) )))))))
else
som = 0
endif
if ( ax .gt. bdeq11 ) then
som = x*(xpneq(12) + x*(xpneq(13) + x*(xpneq(14) +
+ x*(xpneq(15) + x*(xpneq(16) + x*(xpneq(17) + som ))))
+ ))
endif
if ( ax .gt. bdeq05 ) then
som = x*(xpneq(6) + x*(xpneq(7) + x*(xpneq(8) + x*(
+ xpneq(9) + x*(xpneq(10) + x*(xpneq(11) + som ))))))
endif
if ( ax .gt. bdeq01 ) then
som = x*(xpneq(2) + x*(xpneq(3) + x*(xpneq(4) + x*(
+ xpneq(5) + som ))))
endif
cb0p = x*(xpneq(1)+som)
goto 990
* -#] taylor expansion:
endif
* -#[ normal case:
*
* normal case
*
call ffxlmb(xlam,-xp,-xm,-xm,dmp,dmp,0D0)
if ( xlam .ge. 0 ) then
* cases 1,2 and 4
slam = sqrt(xlam)
s2a = dmp + xm
s2 = s2a + slam
if ( abs(s2) .gt. xloss*slam ) then
* looks fine
jsign = 1
else
s2 = s2a - slam
jsign = -1
endif
ax = abs(s2/(2*xm))
if ( ax .lt. xalogm ) then
s = 0
elseif( ax-1 .lt. .1 .and. s2 .gt. 0 ) then
* In this case a quicker and more accurate way is to
* calculate log(1-x).
s2 = (xp - slam)
* the following line is superfluous.
s = -slam/xp*dfflo1(s2/(2*xm),ier)
else
* finally the normal case
s = -slam/xp*log(ax)
if ( jsign .eq. -1 ) s = -s
endif
if ( xp .gt. 2*xm ) then
* in this case ( xlam>0, so xp>(2*m)^2) ) there also
* is an imaginary part
y = -pi*slam/xp
else
y = 0
endif
else
* the root is complex (k^2 between 0 and (2*m1)^2)
slam = sqrt(-xlam)
s = 2*slam/xp*atan2(xp,slam)
y = 0
endif
xx = s - 2
- cb0p = DCMPLX(DBLE(xx),DBLE(y))
+ cb0p = ToComplex(Re(xx),Re(y))
goto 990
* -#] normal case:
*
* #] both masses equal:
* #[ unequal nonzero masses:
* -#[ get log(xm2/xm1):
400 continue
x = xm2/xm1
if ( 1 .lt. xalogm*x ) then
call fferr(8,ier)
xlogmm = 0
elseif ( abs(x-1) .lt. xloss ) then
xlogmm = dfflo1(dm1m2/xm1,ier)
else
xlogmm = log(x)
endif
* -#] get log(xm2/xm1):
* -#[ xp = 0:
*
* first a special case
*
if ( xp .eq. 0 ) then
s2 = ((xm2+xm1) / dm1m2)*xlogmm
s = - s2 - 2
* save the factor 1/2 for the end
if ( abs(s) .lt. xloss*2 ) then
* Taylor expansions: choose which one
x = dm1m2/xm1
ax = abs(x)
if ( ax .lt. .15 .or. precx .gt. 1.E-8 .and. ax
+ .lt. .3 ) then
*
* This is the simple Taylor expansion 'n1'
*
*--#[ data and bounds:
* get the coefficients of the taylor expansion
if ( initn1 .eq. 0 ) then
initn1 = 1
do 410 i = 1,30
- 410 xpnn1(i) = DBLE(i)/DBLE((i+1)*(i+2))
+ 410 xpnn1(i) = Re(i)/Re((i+1)*(i+2))
endif
* determine the boundaries for 1,5,10,15 terms
if ( xprcn1 .ne. precx ) then
xprcn1 = precx
bdn101 = ffbnd(1,1,xpnn1)
bdn105 = ffbnd(1,5,xpnn1)
bdn110 = ffbnd(1,10,xpnn1)
bdn115 = ffbnd(1,15,xpnn1)
endif
*--#] data and bounds:
* calculate:
if ( ax .gt. bdn115 ) then
s = x*(xpnn1(16) + x*(xpnn1(17) + x*(xpnn1(18) +
+ x*(xpnn1(19) + x*xpnn1(20) ))))
else
s = 0
endif
if ( ax .gt. bdn110 ) then
s = x*(xpnn1(11) + x*(xpnn1(12) + x*(xpnn1(13) +
+ x*(xpnn1(14) + x*xpnn1(15) + s))))
endif
if ( ax .gt. bdn105 ) then
s = x*(xpnn1(6) + x*(xpnn1(7) + x*(xpnn1(8) + x*
+ (xpnn1(9) + x*(xpnn1(10) + s)))))
endif
if ( ax .gt. bdn101 ) then
s = x*(xpnn1(2) + x*(xpnn1(3) + x*(xpnn1(4) + x*
+ (xpnn1(5) +s))))
endif
s = x*x*(xpnn1(1) + s)
else
*
* This is the more complicated Taylor expansion 'fc'
*
* #[ bounds:
* determine the boundaries for 1,5,10,15 terms for
* the exponential taylor expansion, assuming it
* starts at n=2.
*
if ( xprnn2 .ne. precx ) then
xprnn2 = precx
bdn205 = ffbnd(4,5,xinfac)
bdn210 = ffbnd(4,10,xinfac)
bdn215 = ffbnd(4,15,xinfac)
bdn220 = ffbnd(4,20,xinfac)
endif
* #] bounds:
* calculate:
y = 2*x/(2-x)
ay = abs(y)
if ( ay .gt. bdn220 ) then
s = y*(xinfac(19) + y*(xinfac(20) + y*(xinfac(
+ 21) + y*(xinfac(22) + y*xinfac(
+ 23) ))))
else
s = 0
endif
if ( ay .gt. bdn215 ) then
s = y*(xinfac(14) + y*(xinfac(15) + y*(xinfac(
+ 16) + y*(xinfac(17) + y*(xinfac(
+ 18) + s)))))
endif
if ( ay .gt. bdn210 ) then
s = y*(xinfac(9) + y*(xinfac(10) + y*(xinfac(11)
+ + y*(xinfac(12) + y*(xinfac(13) + s)))))
endif
if ( ay .gt. bdn205 ) then
s = y*(xinfac(5) + y*(xinfac(6) + y*(xinfac(7) +
+ y*(xinfac(8) + s))))
endif
s = (1-x)*y**4*(xinfac(4)+s)
s = x*y**2*(1+y)/12 - s
s = - 2*dfflo1(s,ier)/y
endif
endif
cb0p = s/2
goto 990
endif
* -#] xp = 0:
* -#[ normal case:
*
* proceeding with the normal case
*
call ffxlmb(xlam,-xp,-xm2,-xm1,dm2p,dm1p,dm1m2)
if ( xlam .gt. 0 ) then
* cases k^2 < -(m2+m1)^2 or k^2 > -(m2-m1)^2:
*--#[ first try:
* first try the normal way
slam = sqrt(xlam)
s2a = dm2p + xm1
s2 = s2a + slam
if ( abs(s2) .gt. xloss*slam ) then
* looks fine
jsign = 1
else
s2 = s2a - slam
jsign = -1
endif
s2 = s2**2/(4*xm1*xm2)
if ( abs(s2) .lt. xalogm ) then
call fferr(9,ier)
s2 = 0
elseif ( abs(s2-1) .lt. xloss ) then
if ( jsign.eq.1 ) then
s2 = -slam*(s2a+slam)/(2*xm1*xm2)
s2 = -slam/(2*xp)*dfflo1(s2,ier)
else
s2 = +slam*(s2a-slam)/(2*xm1*xm2)
s2 = +slam/(2*xp)*dfflo1(s2,ier)
endif
else
s2 = -slam/(2*xp)*log(s2)
if ( jsign .eq. -1 ) s2 = -s2
endif
s1 = -dm1m2*xlogmm/(2*xp)
xx = s1+s2-2
*--#] first try:
if ( abs(xx) .lt. xloss*max(abs(s1),abs(s2)) ) then
*--#[ second try:
* this is unacceptable, try a better solution
s1a = dm1m2 + slam
if ( abs(s1a) .gt. xloss*slam ) then
* (strangely) this works
s1 = -s1a/(2*xp)
else
* by division a more accurate form can be found
s1 = ( -xp/2 + xm1 + xm2 ) / ( slam - dm1m2 )
endif
s1 = s1*xlogmm
if ( abs(xp) .lt. xm2 ) then
s2a = xp - dm1m2
else
s2a = xm2 - dm1p
endif
s2 = s2a - slam
if ( abs(s2) .gt. xloss*slam ) then
* at least reasonable
s2 = s2 / (2*xm2)
else
* division again
s2 = (2*xp) / (s2a+slam)
endif
if ( abs(s2) .lt. .1 ) then
* choose a quick way to get the logarithm
s2 = dfflo1(s2,ier)
else
s2a = abs(1-s2)
s2 = log(s2a)
endif
s2 = -(slam/xp)*s2
xx = s1 + s2 - 2
*--#] second try:
if ( abs(xx) .lt. xloss**2*max(abs(s1),abs(s2)) ) then
*--#[ third try:
* (we accept two times xloss because that's the same
* as in this try)
* A Taylor expansion might work. We expand
* inside the logs. Only do the necessary work.
*
alpha = slam/(slam-dm1m2)
alph1 = -dm1m2/(slam-dm1m2)
*
* First s1:
*
s1p = s1 - 2*alph1
if ( abs(s1p) .lt. xloss*abs(s1) ) then
* -#[ bounds:
* determine the boundaries for 1,5,10,15 terms
if ( xprcn3 .ne. precx ) then
xprcn3 = precx
bdn301 = ffbnd(3,1,xinfac)
bdn305 = ffbnd(3,5,xinfac)
bdn310 = ffbnd(3,10,xinfac)
bdn315 = ffbnd(3,15,xinfac)
endif
* -#] bounds:
xnoe = -xp + 2*xm1 + 2*xm2
x = 4*dm1m2/xnoe
ax = abs(x)
if ( ax .gt. bdn310 ) then
s1a = x*(xinfac(13) + x*(xinfac(14) + x*(
+ xinfac(15) + x*(xinfac(16) + x*
+ xinfac(17) ))))
else
s1a = 0
endif
if ( ax .gt. bdn305 ) then
s1a = x*(xinfac(8) + x*(xinfac(9) + x*(
+ xinfac(10) + x*(xinfac(11) + x*(
+ xinfac(12) + s1a)))))
endif
if ( ax .gt. bdn301 ) then
s1a = x*(xinfac(4) + x*(xinfac(5) + x*(
+ xinfac(6) + x*(xinfac(7) + s1a))))
endif
s1a = x**3 *(xinfac(3) + s1a) *xm2/xm1
s1b = dm1m2*(4*dm1m2**2 - xp*(4*xm1-xp))/
+ (xm1*xnoe**2)
s1p = s1b - s1a
s1p = xnoe*dfflo1(s1p,ier)/(slam - dm1m2)/2
endif
*
* next s2:
*
s2p = s2 - 2*alpha
if ( abs(s2p) .lt. xloss*abs(s2) ) then
* -#[ bounds:
* determine the boundaries for 1,5,10,15 terms
if ( xprcn5 .ne. precx ) then
xprcn5 = precx
bdn501 = ffbnd(4,1,xinfac)
bdn505 = ffbnd(4,5,xinfac)
bdn510 = ffbnd(4,10,xinfac)
bdn515 = ffbnd(4,15,xinfac)
endif
* -#] bounds:
xnoe = slam - dm1m2
x = 2*xp/xnoe
ax = abs(x)
* do not do the Taylor expansion
if ( ax .gt. bdn515 ) goto 495
if ( ax .gt. bdn510 ) then
s2a = x*(xinfac(14) + x*(xinfac(15) + x*(
+ xinfac(16) + x*(xinfac(17) + x*
+ xinfac(18) ))))
else
s2a = 0
endif
if ( ax .gt. bdn505 ) then
s2a = x*(xinfac(9) + x*(xinfac(10) + x*(
+ xinfac(11) + x*(xinfac(12) + x*(
+ xinfac(13) + s2a)))))
endif
if ( ax .gt. bdn501 ) then
s2a = x*(xinfac(5) + x*(xinfac(6) + x*(
+ xinfac(7) + x*(xinfac(8) + s2a))))
endif
s2a = x**4*(xinfac(4)+s2a)*(1-2*xp/(xnoe+xp))
s2b = -2*xp**3 *(-2*xp - xnoe)/(3*(xnoe+xp)*
+ xnoe**3)
s2p = s2b - s2a
s2p = -slam/xp*dfflo1(s2p,ier)
endif
*
* finally ...
*
495 xx = s1p + s2p
*--#] third try:
endif
endif
if ( xp .gt. xm1+xm2 ) then
*--#[ imaginary part:
* in this case ( xlam>0, so xp>(m1+m2)^2) ) there also
* is an imaginary part
y = -pi*slam/xp
else
y = 0
*--#] imaginary part:
endif
else
* the root is complex (k^2 between -(m1+m2)^2 and -(m2-m1)^2)
*--#[ first try:
slam = sqrt(-xlam)
xnoe = dm2p + xm1
s1 = -(dm1m2/(2*xp))*xlogmm
s2 = (slam/xp)*atan2(slam,xnoe)
xx = s1 + s2 - 2
*--#] first try:
- if ( abs(xx) .lt. xloss**2*max(abs(s1),abs(s2)) ) then
+* 13 Apr 11: added x .ne. 0 check to safeguard against div by zero
+ x = 2*xp*xnoe
+ if ( x .ne. 0 .and.
+ & abs(xx) .lt. xloss**2*max(abs(s1),abs(s2)) ) then
*--#[ second try:
* Again two times xloss as we'll accept that in the next
* step as well.
*
xtel = dm1m2**2 - xp**2
- alpha = -xlam/(2*xp*xnoe)
- alph1 = xtel/(2*xp*xnoe)
+ alpha = -xlam/x
+ alph1 = xtel/x
*
* try a taylor expansion on the terms. First s1:
*
s1p = s1 - 2*alph1
if ( abs(s1p) .lt. xloss*abs(s1) ) then
* -#[ bounds:
* determine the boundaries for 1,5,10,15 terms
if ( xprcn3 .ne. precx ) then
xprcn3 = precx
bdn301 = ffbnd(3,1,xinfac)
bdn305 = ffbnd(3,5,xinfac)
bdn310 = ffbnd(3,10,xinfac)
bdn315 = ffbnd(3,15,xinfac)
endif
* -#] bounds:
x = 2*xtel/(dm1m2*xnoe)
ax = abs(x)
* do not do the Taylor expansion
if ( ax .gt. bdn315 ) goto 590
if ( ax .gt. bdn310 ) then
s1a = x*(xinfac(13) + x*(xinfac(14) + x*(
+ xinfac(15) + x*(xinfac(16) + x*
+ xinfac(17) ))))
else
s1a = 0
endif
if ( ax .gt. bdn305 ) then
s1a = x*(xinfac(8) + x*(xinfac(9) + x*(
+ xinfac(10) + x*(xinfac(11) + x*(
+ xinfac(12) + s1a)))))
endif
if ( ax .gt. bdn301 ) then
s1a = x*(xinfac(4) + x*(xinfac(5) + x*(
+ xinfac(6) + x*(xinfac(7) + s1a))))
endif
s1a = x**3 *(xinfac(3) + s1a) *xm2/xm1
s1b = (dm1m2**3*(dm1m2**2-2*xp*xm1) + xp**2*(4*
+ dm1m2*xm1**2-dm1m2**2*(dm1m2+2*xm1))-2*xm2*
+ xp**3*(dm1m2+xp))/(xm1*dm1m2**2*xnoe**2)
s1p = s1b - s1a
s1p = -dm1m2*dfflo1(s1p,ier)/(2*xp)
endif
*
* next s2:
*
590 continue
s2p = s2 - 2*alpha
if ( abs(s2p) .lt. xloss*abs(s2) ) then
* -#[ bounds:
* determine the boundaries for 1,5,10,15 terms
if ( xprcn3 .ne. precx ) then
xprcn3 = precx
bdn301 = ffbnd(3,1,xinfac)
bdn305 = ffbnd(3,5,xinfac)
bdn310 = ffbnd(3,10,xinfac)
bdn315 = ffbnd(3,15,xinfac)
endif
* -#] bounds:
- cx = DCMPLX(0D0,-slam/xnoe)
+ cx = ToComplex(0D0,-slam/xnoe)
ax = absc(cx)
if ( ax .gt. bdn315 ) goto 600
if ( ax .gt. bdn310 ) then
- cs2a = cx*(DBLE(xinfac(13)) + cx*(DBLE(xinfac(14
- + )) + cx*(DBLE(xinfac(15)) + cx*(DBLE(xinfac(16
- + )) + cx*(DBLE(xinfac(17)))))))
+ cs2a = cx*(Re(xinfac(13)) + cx*(Re(xinfac(14
+ + )) + cx*(Re(xinfac(15)) + cx*(Re(xinfac(16
+ + )) + cx*(Re(xinfac(17)))))))
else
cs2a = 0
endif
if ( ax .gt. bdn305 ) then
- cs2a = cx*(DBLE(xinfac(8)) + cx*(DBLE(xinfac(9))
- + + cx*(DBLE(xinfac(10)) + cx*(DBLE(xinfac(11))
- + + cx*(DBLE(xinfac(12)) + cs2a)))))
+ cs2a = cx*(Re(xinfac(8)) + cx*(Re(xinfac(9))
+ + + cx*(Re(xinfac(10)) + cx*(Re(xinfac(11))
+ + + cx*(Re(xinfac(12)) + cs2a)))))
endif
if ( ax .gt. bdn301 ) then
- cs2a = cx*(DBLE(xinfac(4)) + cx*(DBLE(xinfac(5))
- + + cx*(DBLE(xinfac(6)) + cx*(DBLE(xinfac(7))
+ cs2a = cx*(Re(xinfac(4)) + cx*(Re(xinfac(5))
+ + + cx*(Re(xinfac(6)) + cx*(Re(xinfac(7))
+ + cs2a))))
endif
- cs2a = cx**3*(DBLE(xinfac(3))+cs2a)*
- + DCMPLX(DBLE(xnoe),DBLE(slam))
- cs2b = DCMPLX(DBLE(xnoe-xlam/xnoe/2),
- + -DBLE(slam**3/xnoe**2/2))
+ cs2a = cx**3*(Re(xinfac(3))+cs2a)*
+ + ToComplex(Re(xnoe),Re(slam))
+ cs2b = ToComplex(Re(xnoe-xlam/xnoe/2),
+ + -Re(slam**3/xnoe**2/2))
cs2p = cs2b + cs2a
- s2p = slam*atan2(DIMAG(cs2p),DBLE(cs2p))/xp
+ s2p = slam*atan2(Im(cs2p),Re(cs2p))/xp
endif
600 continue
xx = s1p + s2p
*--#] second try:
endif
y = 0
endif
- cb0p = DCMPLX(DBLE(xx),DBLE(y))
+ cb0p = ToComplex(Re(xx),Re(y))
goto 990
* -#] normal case:
* #] unequal nonzero masses:
* #[ debug:
990 continue
* #] debug:
*###] ffxb0p:
end
*###[ ffxlmb:
subroutine ffxlmb(xlambd,a1,a2,a3,a12,a13,a23)
***#[*comment:***********************************************************
* calculate in a numerically stable way *
* lambda(a1,a2,a3) = *
* a1**2 + a2**2 + a3**2 - 2*a2*a3 - 2*a3*a1 - 2*a1*a2 *
* aij = ai - aj are required for greater accuracy at times *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE PRECISION xlambd,a1,a2,a3,a12,a13,a23
+ RealType xlambd,a1,a2,a3,a12,a13,a23
*
* local variables
*
- DOUBLE PRECISION aa1,aa2,aa3,a,aff,asq
+ RealType aa1,aa2,aa3,a,aff,asq
*
* common blocks
*
#include "ff.h"
* #] declarations:
* #[ calculations:
aa1 = abs(a1)
aa2 = abs(a2)
aa3 = abs(a3)
*
* first see if there are input parameters with opposite sign:
*
if ( a1 .lt. 0 .and. a2 .gt. 0 .or.
+ a1 .gt. 0 .and. a2 .lt. 0 ) then
goto 12
elseif ( a1 .lt. 0 .and. a3 .gt. 0 .or.
+ a1 .gt. 0 .and. a3 .lt. 0 ) then
goto 13
*
* all have the same sign, choose the smallest 4*ai*aj term
*
elseif ( aa1 .gt. aa2 .and. aa1 .gt. aa3 ) then
goto 23
elseif ( aa2 .gt. aa3 ) then
goto 13
else
goto 12
endif
12 continue
if ( aa1 .gt. aa2 ) then
a = a13 + a2
else
a = a1 + a23
endif
aff = 4*a1*a2
goto 100
13 continue
if ( aa1 .gt. aa3 ) then
a = a12 + a3
else
a = a1 - a23
endif
aff = 4*a1*a3
goto 100
23 continue
if ( aa2 .gt. aa3 ) then
a = a12 - a3
else
a = a13 - a2
endif
aff = 4*a2*a3
100 continue
asq = a**2
xlambd = asq - aff
* #] calculations:
*###] ffxlmb:
end
*###[ ffclmb:
subroutine ffclmb(clambd,cc1,cc2,cc3,cc12,cc13,cc23)
***#[*comment:***********************************************************
* calculate in cc numerically stable way *
* lambda(cc1,cc2,cc3) = *
* cc1**2 + cc2**2 + cc3**2 - 2*cc2*cc3 - 2*cc3*cc1 - 2*cc1*cc2 *
* cij = ci - cj are required for greater accuracy at times *
* ier is the usual error flag. *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE COMPLEX clambd,cc1,cc2,cc3,cc12,cc13,cc23
+ ComplexType clambd,cc1,cc2,cc3,cc12,cc13,cc23
*
* local variables
*
- DOUBLE PRECISION aa1,aa2,aa3,absc
- DOUBLE COMPLEX cc,cff,csq,c
+ RealType aa1,aa2,aa3,absc
+ ComplexType cc,cff,csq,c
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ calculations (rather old style ...):
aa1 = absc(cc1)
aa2 = absc(cc2)
aa3 = absc(cc3)
*
* first see if there are input parameters with opposite sign:
*
- if ( DBLE(cc1) .lt. 0 .and. DBLE(cc2) .gt. 0 .or.
- + DBLE(cc1) .gt. 0 .and. DBLE(cc2) .lt. 0 ) then
+ if ( Re(cc1) .lt. 0 .and. Re(cc2) .gt. 0 .or.
+ + Re(cc1) .gt. 0 .and. Re(cc2) .lt. 0 ) then
goto 12
- elseif ( DBLE(cc1) .lt. 0 .and. DBLE(cc3) .gt. 0 .or.
- + DBLE(cc1) .gt. 0 .and. DBLE(cc3) .lt. 0 ) then
+ elseif ( Re(cc1) .lt. 0 .and. Re(cc3) .gt. 0 .or.
+ + Re(cc1) .gt. 0 .and. Re(cc3) .lt. 0 ) then
goto 13
*
* all have the same sign, choose the smallest 4*ci*cj term
*
elseif ( aa1 .gt. aa2 .and. aa1 .gt. aa3 ) then
goto 23
elseif ( aa2 .gt. aa3 ) then
goto 13
else
goto 12
endif
12 continue
if ( aa1 .gt. aa2 ) then
cc = cc13 + cc2
else
cc = cc1 + cc23
endif
cff = 4*cc1*cc2
goto 100
13 continue
if ( aa1 .gt. aa3 ) then
cc = cc12 + cc3
else
cc = cc1 - cc23
endif
cff = 4*cc1*cc3
goto 100
23 continue
if ( aa2 .gt. aa3 ) then
cc = cc12 - cc3
else
cc = cc13 - cc2
endif
cff = 4*cc2*cc3
100 continue
csq = cc**2
clambd = csq - cff
* #] calculations (rather old style ...):
*###] ffclmb:
end
*###[ ffdot2:
subroutine ffdot2(piDpj,xp,xma,xmb,dmap,dmbp,dmamb,ier)
***#[*comment:***********************************************************
* *
* Store the 3 dotproducts in the common block ffdot. *
* *
* Input: see ffxb0p *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE PRECISION piDpj(3,3),xp,xma,xmb,dmap,dmbp,dmamb
+ RealType piDpj(3,3),xp,xma,xmb,dmap,dmbp,dmamb
*
* local variables
*
integer ier1
*
* common blocks
*
#include "ff.h"
*
* statement function
*
-* absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+* absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ work:
ier1 = ier
piDpj(1,1) = xma
piDpj(2,2) = xmb
piDpj(3,3) = xp
if ( abs(dmap) .lt. abs(dmbp) ) then
piDpj(1,2) = (dmap + xmb)/2
else
piDpj(1,2) = (dmbp + xma)/2
endif
piDpj(2,1) = piDpj(1,2)
if ( abs(dmamb) .lt. abs(dmbp) ) then
piDpj(1,3) = (-dmamb - xp)/2
else
piDpj(1,3) = (dmbp - xma)/2
endif
piDpj(3,1) = piDpj(1,3)
if ( abs(dmamb) .lt. abs(dmap) ) then
piDpj(2,3) = (-dmamb + xp)/2
else
piDpj(2,3) = (-dmap + xmb)/2
endif
piDpj(3,2) = piDpj(2,3)
ier = ier1
* #] work:
*###] ffdot2:
end
diff --git a/Looptools/B/ffxb1.F b/Looptools/B/ffxb1.F
--- a/Looptools/B/ffxb1.F
+++ b/Looptools/B/ffxb1.F
@@ -1,281 +1,282 @@
#include "externals.h"
+#include "types.h"
*###[ ffxb1:
subroutine ffxb1(cb1,cb0,ca0i,xp,xm1,xm2,piDpj,ier)
***#[*comment:***********************************************************
* *
* Calculate 1 / d^n Q Q(mu) *
* ------ | ------------------------ = B1*p(mu) *
* i pi^2 / (Q^2-m1^2)((Q+p)^2-m2^2) *
* *
* Input: cb0 complex scalar twopoint function *
* ca0i(2) complex scalar onepoint function with *
* m1,m2 *
* xp real p.p in B&D metric *
* xm1,2 real m_1^2,m_2^2 *
* piDpj(3,3) real dotproducts between s1,s2,p *
* ier integer digits lost so far *
* Output: cb1 complex B1 *
* ier integer digits lost *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE PRECISION xp,xm1,xm2,piDpj(3,3)
- DOUBLE COMPLEX cb1,cb0,ca0i(2)
+ RealType xp,xm1,xm2,piDpj(3,3)
+ ComplexType cb1,cb0,ca0i(2)
*
* local variables
*
- DOUBLE PRECISION dm1m2
+ RealType dm1m2
*
* common blocks
*
#include "ff.h"
*
* #] declarations:
* #[ get differences:
dm1m2 = xm1 - xm2
* #] get differences:
* #[ call ffxb1a:
call ffxb1a(cb1,cb0,ca0i,xp,xm1,xm2,dm1m2,piDpj,ier)
* #] call ffxb1a:
*###] ffxb1:
end
*###[ ffxb1a:
subroutine ffxb1a(cb1,cb0,ca0i,xp,xm1,xm2,dm1m2,piDpj,ier)
***#[*comment:***********************************************************
* *
* Calculate 1 / d^n Q Q(mu) *
* ------ | ------------------------ = B1*p(mu) *
* i pi^2 / (Q^2-m1^2)((Q+p)^2-m2^2) *
* *
* Input: cb0 complex scalar twopoint function *
* ca0i(2) complex scalar onepoint function with *
* m1,m2 *
* xp real p.p in B&D metric *
* xm1,2 real m_1^2,m_2^2 *
* piDpj(3,3) real dotproducts between s1,s2,p *
* ier integer digits lost so far *
* Output: cb1 complex B1 *
* ier integer digits lost *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE PRECISION xp,xm1,xm2,dm1m2,piDpj(3,3)
- DOUBLE COMPLEX cb1,cb0,ca0i(2)
+ RealType xp,xm1,xm2,dm1m2,piDpj(3,3)
+ ComplexType cb1,cb0,ca0i(2)
*
* local variables
*
logical lneg
- DOUBLE PRECISION xmax,absc,s,s1,h,slam,bnd101,bnd105,bnd110,
+ RealType xmax,absc,s,s1,h,slam,bnd101,bnd105,bnd110,
+ xma,xmb,x,ax,xlogm,small,dmbma,xprec,xlam,ts2Dp,
+ xmxp,xlo3,dfflo3
- DOUBLE COMPLEX cs(5),cc,csom
- DOUBLE PRECISION ffbnd,dfflo1
+ ComplexType cs(5),cc,csom
+ RealType ffbnd,dfflo1
external ffbnd,dfflo1,dfflo3
save xprec,bnd101,bnd105,bnd110
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(cc) = abs(DBLE(cc)) + abs(DIMAG(cc))
+ absc(cc) = abs(Re(cc)) + abs(Im(cc))
*
* data
*
data xprec /0D0/
*
* #] declarations:
* #[ p^2 != 0:
if ( xp .ne. 0 ) then
* #[ normal case:
if ( dm1m2 .ne. 0 ) then
cs(1) = -ca0i(2)
cs(2) = +ca0i(1)
else
cs(1) = 0
cs(2) = 0
endif
- cs(3) = +DBLE(2*piDpj(1,3))*cb0
+ cs(3) = +Re(2*piDpj(1,3))*cb0
cb1 = cs(1) + cs(2) + cs(3)
xmax = max(absc(cs(2)),absc(cs(3)))
if ( absc(cb1) .ge. xloss*xmax ) goto 110
* #] normal case:
* #[ almost equal masses:
if ( abs(dm1m2) .le. xloss*xm1 ) then
- cs(2) = DBLE(dm1m2/xm1)*cs(2)
+ cs(2) = Re(dm1m2/xm1)*cs(2)
cs(1) = -xm2*dfflo1(-dm1m2/xm2,ier)
cb1 = cs(1) + cs(2) + cs(3)
xmax = max(absc(cs(2)),absc(cs(3)))
if ( absc(cb1) .ge. xloss*xmax ) goto 110
* for the perfectionist (not me (today)):
* if d0=0 and mu~m1(~m2), then the terms of order
* (m1^2-m2^2) also cancel. To patch this I need d0 and mu
endif
* #] almost equal masses:
* #[ p2 -> 0:
if ( xloss**2*max(xm1,xm2) .gt. abs(xp) ) then
if ( xm2.gt.xm1 ) then
xma = xm1
xmb = xm2
ts2Dp = +2*piDpj(2,3)
lneg = .FALSE.
else
xma = xm2
xmb = xm1
ts2Dp = -2*piDpj(1,3)
lneg = .TRUE.
endif
else
goto 100
endif
*
* We found a situation in which p2 is much smaller than
* the masses.
*
dmbma = abs(dm1m2)
if ( xma.eq.0 ) then
xlogm = 1
elseif ( dmbma .gt. xloss*xmb ) then
xlogm = log(xmb/xma)
else
xlogm = dfflo1(-dmbma/xma,ier)
endif
xlam = (dmbma-xp)**2 - 4*xma*xp
if ( xlam.gt.0 ) then
* #[ real roots:
slam = sqrt(xlam)
small = xp*(-2*(xma+xmb) + xp)/(slam+dmbma)
h = slam+2*piDpj(1,2)
cs(1) = xlogm*xma*(4*xmb*(small-xp) + (small-xp)**2)/(2*
+ (slam+dmbma)*h)
if ( xprec.ne.precx ) then
xprec = precx
bnd101 = ffbnd(2,1,xinfac)
bnd105 = ffbnd(2,5,xinfac)
bnd110 = ffbnd(2,10,xinfac)
endif
x = xp/slam
ax = abs(x)
if ( ax.gt.bnd110 ) then
s = x*(xinfac(12) + x*(xinfac(13) + x*(xinfac(14) +
+ x*(xinfac(15) + x*xinfac(16) ))))
else
s = 0
endif
if ( ax.gt.bnd105 ) then
s = x*(xinfac(7) + x*(xinfac(8) + x*(xinfac(9) +
+ x*(xinfac(10) + x*(xinfac(11) + s )))))
endif
if ( ax.gt.bnd101) then
s = x*(xinfac(3) + x*(xinfac(4) + x*(xinfac(5) +
+ x*(xinfac(6) + s ))))
endif
s = x**2*(.5D0 + s)
h = ts2Dp + slam
s1 = 2*xp/h*(s + x)
h = -4*xp**2*xmb/(slam*h**2) - s + s1
if ( abs(h) .lt. .1 ) then
cs(2) = dmbma*slam/xp*dfflo1(h,ier)
else
goto 100
endif
if ( lneg ) then
cs(1) = -cs(1)
cs(2) = -cs(2)
endif
- cs(3) = -DBLE(xp)*cb0
+ cs(3) = -Re(xp)*cb0
cb1 = cs(1) + cs(2) + cs(3)
xmax = max(absc(cs(2)),absc(cs(3)))
if ( absc(cb1) .gt. xloss*xmax) goto 110
*
* this still occurs in the case xp << dmamb << xma,
* with a cancellation of order dmamb/xma between cs1 and
* cs2; as the standard model does not contain these kind
* of doublets I leave this as an exercise for the
* reader...
*
* #] real roots:
else
* #[ imaginary roots:
* #] imaginary roots:
endif
* #] p2 -> 0:
* #[ give up:
*
* give up...
*
100 continue
110 continue
* #] give up:
- cb1 = cb1*(1/DBLE(2*xp))
+ cb1 = cb1*(1/Re(2*xp))
* #] p^2 != 0:
* #[ p^2=0, m1 != m2:
elseif ( dm1m2 .ne. 0 ) then
- cs(1) = +DBLE(xm2/(2*dm1m2**2))*(ca0i(2)+DBLE(xm2)/2)
- cs(2) = -DBLE(xm1/(2*dm1m2**2))*(ca0i(1)+DBLE(xm1)/2)
- cs(3) = +ca0i(2)*(1/DBLE(dm1m2))
+ cs(1) = +Re(xm2/(2*dm1m2**2))*(ca0i(2)+Re(xm2)/2)
+ cs(2) = -Re(xm1/(2*dm1m2**2))*(ca0i(1)+Re(xm1)/2)
+ cs(3) = +ca0i(2)*(1/Re(dm1m2))
cb1 = cs(1) + cs(2) + cs(3)
xmax = max(absc(cs(1)),absc(cs(2)),absc(cs(3)))
if ( absc(cb1).ge.xloss**2*xmax ) goto 120
*
* m1 ~ m2, see b21.frm
*
if ( abs(dm1m2).lt.xloss*xm1 ) then
xlogm = dfflo1(dm1m2/xm1,ier)
else
xlogm = log(xm2/xm1)
endif
cs(1) = -(xm1/dm1m2)/2
cs(2) = -xlogm/2*(xm1/dm1m2)**2
- cs(3) = +1/DBLE(4) - ca0i(1)*DBLE(1/(2*xm1))
+ cs(3) = +1/Re(4) - ca0i(1)*Re(1/(2*xm1))
cs(4) = xlogm/2
csom = cs(1) + cs(2) + cs(3) + cs(4)
xmxp = max(absc(cs(2)),absc(cs(3)),absc(cs(4)))
if ( xmxp.lt.xmax ) then
xmax = xmxp
cb1 = csom
if ( absc(cb1).gt.xloss**2*xmax ) goto 120
endif
*
* better
*
xlo3 = dfflo3(dm1m2/xm1,ier)
cs(1) = -(dm1m2/xm1)**2/4
cs(2) = -(dm1m2/xm1)/2
cs(3) = -xlo3/(dm1m2/xm1)**2/2
cs(4) = xlo3/2
- cs(5) = 1/DBLE(2) - ca0i(1)*DBLE(1/(2*xm1))
+ cs(5) = 1/Re(2) - ca0i(1)*Re(1/(2*xm1))
csom = cs(1) + cs(2) + cs(3) + cs(4) + cs(5)
xmxp = max(absc(cs(2)),absc(cs(3)),absc(cs(4)),absc(cs(5)))
if ( xmxp.lt.xmax ) then
xmax = xmxp
cb1 = csom
if ( absc(cb1).gt.xloss**2*xmax ) goto 120
endif
*
* give up
*
120 continue
* #] p^2=0, m1 != m2:
* #[ p^2=0, m1 == m2:
else
cb1 = -cb0/2
endif
* #] p^2=0, m1 == m2:
*###] ffxb1a:
end
diff --git a/Looptools/B/ffxb2p.F b/Looptools/B/ffxb2p.F
--- a/Looptools/B/ffxb2p.F
+++ b/Looptools/B/ffxb2p.F
@@ -1,412 +1,413 @@
#include "externals.h"
+#include "types.h"
*###[ ffxb2p:
subroutine ffxb2p(cb2i,cb1,cb0,ca0i,xp,xm1,xm2,piDpj,ier)
***#[*comment:***********************************************************
* *
* Compute the PV B2, the coefficients of p(mu)p(nu) and g(mu,nu) *
* of 1/(ipi^2)\int d^nQ Q(mu)Q(nu)/(Q^2-m_1^2)/((Q+p)^2-m_2^2) *
* originally based on aaxbx by Andre Aeppli. *
* *
* Input: cb1 complex vector two point function *
* cb0 complex scalar two point function *
* ca0i(2) complex scalar onepoint function with *
* m1,m2 *
* xp real p.p in B&D metric *
* xm1,2 real m_1^2,m_2^2 *
* piDpj(3,3) real dotproducts between s1,s2,p *
* ier integer digits lost so far *
* *
* Output: cb2i(2) complex B21,B22: coeffs of p*p, g in B2 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE PRECISION xp,xm1,xm2,piDpj(3,3)
- DOUBLE COMPLEX cb2i(2),cb1,cb0,ca0i(2)
+ RealType xp,xm1,xm2,piDpj(3,3)
+ ComplexType cb2i(2),cb1,cb0,ca0i(2)
*
* local variables
*
- DOUBLE PRECISION dm1m2
+ RealType dm1m2
*
* #] declarations:
* #[ work:
*
dm1m2= xm1 - xm2
call ffxb2q(cb2i,cb1,cb0,ca0i,xp,xm1,xm2,dm1m2,piDpj,ier)
*
* #] work:
*###] ffxb2p:
end
*###[ ffxb2q:
subroutine ffxb2q(cb2i,cb1,cb0,ca0i,xp,xm1,xm2,dm1m2,piDpj,ier)
***#[*comment:***********************************************************
* *
* Compute the PV B2, the coefficients of p(mu)p(nu) and g(mu,nu) *
* of 1/(ipi^2)\int d^nQ Q(mu)Q(nu)/(Q^2-m_1^2)/((Q+p)^2-m_2^2) *
* originally based on aaxbx by Andre Aeppli. *
* *
* Input: cb1 complex vector two point function *
* cb0 complex scalar two point function *
* ca0i(2) complex scalar onepoint function with *
* m1,m2 *
* xp real p.p in B&D metric *
* xm1,2 real m_1^2,m_2^2 *
* piDpj(3,3) real dotproducts between s1,s2,p *
* ier integer digits lost so far *
* *
* Output: cb2i(2) complex B21,B22: coeffs of p*p, g in B2 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE PRECISION xp,xm1,xm2,dm1m2,piDpj(3,3)
- DOUBLE COMPLEX cb2i(2),cb1,cb0,ca0i(2)
+ RealType xp,xm1,xm2,dm1m2,piDpj(3,3)
+ ComplexType cb2i(2),cb1,cb0,ca0i(2)
*
* local variables
*
integer i,ier0,ier1
logical llogmm
- DOUBLE PRECISION xmax,absc,xlam,slam,bet,xmxp,dfflo3,xlo3,
+ RealType xmax,absc,xlam,slam,bet,xmxp,dfflo3,xlo3,
+ xmxsav,xnoe,xnoe2,xlogmm,dfflo1
- DOUBLE COMPLEX cs(16),cc,csom,clo3,zfflo3
+ ComplexType cs(16),cc,csom,clo3,zfflo3
external dfflo1,dfflo3,zfflo3
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(cc) = abs(DBLE(cc)) + abs(DIMAG(cc))
+ absc(cc) = abs(Re(cc)) + abs(Im(cc))
*
* #] declarations:
* #[ normal case:
ier0 = ier
ier1 = ier
*
* with thanks to Andre Aeppli, off whom I stole the original
*
if ( xp .ne. 0) then
cs(1) = ca0i(2)
- cs(2) = DBLE(xm1)*cb0
- cs(3) = DBLE(2*piDpj(1,3))*cb1
+ cs(2) = Re(xm1)*cb0
+ cs(3) = Re(2*piDpj(1,3))*cb1
cs(4) = (xm1+xm2)/2
cs(5) = -xp/6
cb2i(1) = cs(1) - cs(2) - cs(4) + 2*cs(3) - cs(5)
cb2i(2) = cs(1) + 2*cs(2) - cs(3) + 2*cs(4) + 2*cs(5)
xmax = max(absc(cs(2)),absc(cs(3)),absc(cs(4)),absc(cs(5)))
xmxsav = xmax
if ( absc(cb2i(1)) .ge. xloss*xmax ) goto 100
* #] normal case:
* #[ improve: m1=m2:
*
* a relatively simple case: dm1m2 = 0 (bi0.frm)
*
if ( dm1m2.eq.0 .and. xm1.ne.0 ) then
if ( xp.lt.0 ) then
slam = sqrt(xp**2-4*xm1*xp)
xlo3 = dfflo3((xp-slam)/(2*xm1),ier)
- cs(1) = xp*(-1/DBLE(3) + slam/(4*xm1))
+ cs(1) = xp*(-1/Re(3) + slam/(4*xm1))
cs(2) = xp**2*(-slam/(4*xm1**2) - 3/(4*xm1))
cs(3) = xp**3/(4*xm1**2)
- cs(4) = DBLE(xp/xm1)*ca0i(1)
+ cs(4) = Re(xp/xm1)*ca0i(1)
cs(5) = xlo3/xp*(-xm1*slam)
cs(6) = xlo3*slam
else
slam = isgnal*sqrt(-xp**2+4*xm1*xp)
- clo3 = zfflo3(DCMPLX(DBLE(xp/(2*xm1)),
- + DBLE(-slam/(2*xm1))),ier)
- cs(1) = DBLE(xp)*DCMPLX(-1/DBLE(3),
- + DBLE(slam/(4*xm1)))
- cs(2) = DBLE(xp**2)*DCMPLX(DBLE(-3/(4*xm1)),
- + DBLE(-slam/(4*xm1**2)))
- cs(3) = DBLE(xp**3/(4*xm1**2))
- cs(4) = DBLE(xp/xm1)*ca0i(1)
- cs(5) = clo3*DCMPLX(DBLE(0),DBLE(-xm1*slam/xp))
- cs(6) = clo3*DCMPLX(DBLE(0),DBLE(slam))
+ clo3 = zfflo3(ToComplex(Re(xp/(2*xm1)),
+ + Re(-slam/(2*xm1))),ier)
+ cs(1) = Re(xp)*ToComplex(-1/Re(3),
+ + Re(slam/(4*xm1)))
+ cs(2) = Re(xp**2)*ToComplex(Re(-3/(4*xm1)),
+ + Re(-slam/(4*xm1**2)))
+ cs(3) = Re(xp**3/(4*xm1**2))
+ cs(4) = Re(xp/xm1)*ca0i(1)
+ cs(5) = clo3*ToComplex(Re(0),Re(-xm1*slam/xp))
+ cs(6) = clo3*ToComplex(Re(0),Re(slam))
endif
csom = cs(1) + cs(2) + cs(3) + cs(4) + cs(5) + cs(6)
xmxp = max(absc(cs(2)),absc(cs(3)),absc(cs(4)),
+ absc(cs(5)),absc(cs(6)))
*
* get rid of noise in the imaginary part
*
- if ( xloss*abs(DIMAG(csom)).lt.precc*abs(DBLE(csom)) )
- + csom = DCMPLX(DBLE(csom),DBLE(0))
+ if ( xloss*abs(Im(csom)).lt.precc*abs(Re(csom)) )
+ + csom = ToComplex(Re(csom),Re(0))
if ( xmxp.lt.xmax ) then
cb2i(1) = csom
xmax = xmxp
endif
if ( absc(cb2i(1)).ge.xloss**2*xmax ) goto 100
endif
* #] improve: m1=m2:
* #[ improve: |xp| < xm1 < xm2:
*
* try again (see bi.frm)
*
xlam = 4*(piDpj(1,3)**2 - xm1*xp)
if ( xm1.eq.0 .or. xm2.eq.0 ) then
xlogmm = 0
elseif ( abs(dm1m2).lt.xloss*xm1 ) then
xlogmm = dfflo1(dm1m2/xm1,ier)
else
xlogmm = log(xm2/xm1)
endif
if ( xlam.gt.0 .and. abs(xp).lt.xloss*xm2 .and.
+ xm1.lt.xm2 ) then
slam = sqrt(xlam)
bet = 4*xm1*xp/(2*piDpj(1,3)+slam)
- cs(1) = DBLE(xp/xm2)*ca0i(2)
+ cs(1) = Re(xp/xm2)*ca0i(2)
cs(2) = -xlogmm*bet*xm1**2*2*(xm2 + xm1)
+ /((-dm1m2+slam)*(2*piDpj(1,2)+slam)*(2*piDpj(1,3)+slam))
cs(3) = xlogmm*(-4*xp*xm1**3)
+ /((-dm1m2+slam)*(2*piDpj(1,2)+slam)*(2*piDpj(1,3)+slam))
xnoe = 1/(2*piDpj(2,3)+slam)
xnoe2 = xnoe**2
cs(4) = xnoe2*xm1*bet*(xp-4*xm2)
cs(5) = xnoe2*xm1*2*xp*xm2
cs(6) = xnoe2*xm1**2*bet
cs(7) = xnoe2*xm1**2*4*xp
cs(8) = xnoe2*bet*xm2*(xp+3*xm2)
cs(9) = xnoe2*(-6*xp*xm2**2)
cs(10)= xp*(7/6.d0 - 2*xm1*slam*xnoe2 +
+ 4*xm2*slam*xnoe2 - 2*slam*xnoe)
cs(11)= xp**2*( -2*slam*xnoe2 )
xlo3 = dfflo3(2*xp*xnoe,ier)
cs(12) = xlo3*dm1m2**2*slam/xp**2
cs(13) = xlo3*(xm1 - 2*xm2)*slam/xp
cs(14) = xlo3*slam
csom = 0
xmxp = 0
do 50 i=1,14
csom = csom + cs(i)
xmxp = max(xmxp,absc(cs(i)))
50 continue
if ( xmxp.lt.xmax ) then
cb2i(1) = csom
xmax = xmxp
endif
cs(7) = -2*bet*xnoe2*xm2*dm1m2
cs(6) = -bet*xm1**2*xlogmm*
& (2*(xm1 + xm2)/(2*piDpj(1,3)+slam) + 1)/
& ((-dm1m2+slam)*(2*piDpj(1,2)+slam))
cs(5) = xnoe2*xp*((xm1 + xm2)*(bet + 4*dm1m2) +
& 2*xm2*(dm1m2 + slam))
cs(4) = xnoe2*(bet*dm1m2**2 -
& 2*xp*slam*(dm1m2 + 1/xnoe + xp))
cs(3) = 7/6D0*xp
xmxp = dm1m2/xp
cs(2) = xlo3*slam*(xmxp*(xmxp + 1) - xm2/xp + 1)
csom = 0
xmxp = 0
do i=7,1,-1
c do i=1,7
csom = csom + cs(i)
xmxp = max(xmxp,absc(cs(i)))
enddo
if ( xmxp.lt.xmax ) then
cb2i(1) = csom
xmax = xmxp
endif
if ( absc(cb2i(1)).ge.xloss**2*xmax ) goto 100
endif
* #] improve: |xp| < xm1 < xm2:
* #[ improve: |xp| < xm2 < xm1:
if ( xlam.gt.0 .and. abs(xp).lt.xloss*xm1 .and.
+ xm2.lt.xm1 ) then
slam = sqrt(xlam)
bet = 4*xm2*xp/(-2*piDpj(2,3)+slam)
xnoe = 1/(-2*piDpj(1,3)+slam)
xnoe2 = xnoe**2
- cs(1) = DBLE(xp/xm1)*ca0i(1)
+ cs(1) = Re(xp/xm1)*ca0i(1)
cs(2) = -2*xlogmm*bet*xm2*
+ (3*xp*(2*xm1 + xm2 - xp) - xm2*(xm1 + xm2))/
+ ((dm1m2+slam)*(2*piDpj(1,2)+slam)*(-2*piDpj(2,3)+slam))
cs(3) = -4*xlogmm*xm2*xp*
+ (-6*xm1**2-xm2**2+ 3*xp*(3*xm1 + xm2 - xp))/
+ ((dm1m2+slam)*(2*piDpj(1,2)+slam)*(-2*piDpj(2,3)+slam))
cs(4) = xnoe2*xm2*bet*(xp-4*xm1)
cs(5) = xnoe2*xm2*(-10*xp*xm1)
cs(6) = xnoe2*xm2**2*bet
cs(7) = xnoe2*xm2**2*4*xp
cs(8) = xnoe2*bet*xm1*(xp+3*xm1)
cs(9) = xnoe2*6*xp*xm1**2
cs(10)= xp*(7/6.d0 - 2*xm1*slam*xnoe2 +
+ 4*xm2*slam*xnoe2 - 2*slam*xnoe)
cs(11)= xp**2*( -2*slam*xnoe2 )
xlo3 = dfflo3(2*xp*xnoe,ier)
cs(12) = xlo3*dm1m2**2*slam/xp**2
cs(13) = xlo3*(xm1 - 2*xm2)*slam/xp
cs(14) = xlo3*slam
csom = 0
xmxp = 0
do 60 i=1,14
csom = csom + cs(i)
xmxp = max(xmxp,absc(cs(i)))
60 continue
if ( xmxp.lt.xmax ) then
cb2i(1) = csom
xmax = xmxp
endif
xmxp = xlogmm*xm2/((dm1m2+slam)*
& (2*piDpj(1,2)+slam)*(-2*piDpj(2,3)+slam))
cs(8) = 2*bet*(xnoe2*dm1m2*xm1 + xmxp*(xm1+xm2)*xm2)
cs(7) = 2*xmxp*xp*(13*xm1**2 + xm2**2 + dm1m2**2)
cs(6) = 2*xnoe2*xp*dm1m2*(xm1 + 2*dm1m2)
cs(5) = bet*xnoe2*(dm1m2**2 + xp*(xm1 + xm2))
cs(4)= xp*(7/6D0 -
& 2*slam*xnoe*(xnoe*(dm1m2 - xm2 + xp) + 1))
cs(3) = -2*xmxp*xp*(
& 3*(bet + 2*xp)*(2*xm1 + xm2 - xp) +
& 2*xm1*(3*xp + dm1m2) )
xmxp = dm1m2/xp
cs(2) = xlo3*slam*(xmxp*(xmxp + 1) - xm2/xp + 1)
csom = 0
xmxp = 0
do i=8,1,-1
csom = csom + cs(i)
xmxp = max(xmxp,absc(cs(i)))
enddo
if ( xmxp.lt.xmax ) then
cb2i(1) = csom
xmax = xmxp
endif
if ( absc(cb2i(1)).ge.xloss**2*xmax ) goto 100
endif
* #] improve: |xp| < xm2 < xm1:
* #[ wrap up:
100 continue
xmax = xmxsav
- cb2i(1) = DBLE(1/(3*xp)) * cb2i(1)
- cb2i(2) = DBLE(1/6.d0) * cb2i(2)
+ cb2i(1) = Re(1/(3*xp)) * cb2i(1)
+ cb2i(2) = Re(1/6.d0) * cb2i(2)
* #] wrap up:
* #[ xp=0, m1!=m2:
elseif (dm1m2 .ne. 0) then
* #[ B21:
llogmm = .FALSE.
*
* B21 (see thesis, b21.frm)
*
- cs(1) = DBLE(xm1**2/3/dm1m2**3)*ca0i(1)
- cs(2) = DBLE((-xm1**2 + xm1*xm2 - xm2**2/3)/dm1m2**3)*
+ cs(1) = Re(xm1**2/3/dm1m2**3)*ca0i(1)
+ cs(2) = Re((-xm1**2 + xm1*xm2 - xm2**2/3)/dm1m2**3)*
+ ca0i(2)
cs(3) = (5*xm1**3/18 - xm1*xm2**2/2 + 2*xm2**3/9)
+ /dm1m2**3
cb2i(1) = cs(1)+cs(2)+cs(3)
xmax = max(absc(cs(2)),absc(cs(3)))
if ( absc(cb2i(1)).gt.xloss**2*xmax ) goto 160
*
* ma ~ mb
*
if ( abs(dm1m2).lt.xloss*xm1 ) then
xlogmm = dfflo1(dm1m2/xm1,ier)
else
xlogmm = log(xm2/xm1)
endif
llogmm = .TRUE.
cs(1) = (xm1/dm1m2)/6
cs(2) = (xm1/dm1m2)**2/3
cs(3) = (xm1/dm1m2)**3*xlogmm/3
- cs(4) = -2/DBLE(9) + ca0i(1)*DBLE(1/(3*xm1))
+ cs(4) = -2/Re(9) + ca0i(1)*Re(1/(3*xm1))
cs(5) = -xlogmm/3
csom = cs(1)+cs(2)+cs(3)+cs(4)+cs(5)
xmxp = max(absc(cs(2)),absc(cs(3)),absc(cs(4)),
+ absc(cs(5)))
if ( xmxp.lt.xmax ) then
xmax = xmxp
cb2i(1) = csom
if ( absc(cb2i(1)).gt.xloss**2*xmax ) goto 160
endif
*
* and last try
*
xlo3 = dfflo3(dm1m2/xm1,ier)
cs(1) = (dm1m2/xm1)**2/6
cs(2) = (dm1m2/xm1)/3
cs(3) = xlo3/(3*(dm1m2/xm1)**3)
-*same cs(4) = -2/DBLE(9) + ca0i(1)*DBLE(1/(3*xm1))
+*same cs(4) = -2/Re(9) + ca0i(1)*Re(1/(3*xm1))
cs(5) = -xlo3/3
csom = cs(1)+cs(2)+cs(3)+cs(4)+cs(5)
xmxp = max(absc(cs(2)),absc(cs(3)),absc(cs(4)),
+ absc(cs(5)))
if ( xmxp.lt.xmax ) then
xmax = xmxp
cb2i(1) = csom
if ( absc(cb2i(1)).gt.xloss**2*xmax ) goto 160
endif
*
* give up
*
160 continue
* #] B21:
* #[ B22:
*
* B22
*
- cs(1) = +DBLE(xm1/(4*dm1m2))*ca0i(1)
- cs(2) = -DBLE(xm2/(4*dm1m2))*ca0i(2)
+ cs(1) = +Re(xm1/(4*dm1m2))*ca0i(1)
+ cs(2) = -Re(xm2/(4*dm1m2))*ca0i(2)
cs(3) = (xm1+xm2)/8
cb2i(2) = cs(1) + cs(2) + cs(3)
xmax = max(absc(cs(2)),absc(cs(3)))
if ( absc(cb2i(2)).gt.xloss*xmax ) goto 210
*
* second try, close together
*
if ( .not.llogmm ) then
if ( abs(dm1m2).lt.xloss*xm1 ) then
xlogmm = dfflo1(dm1m2/xm1,ier)
else
xlogmm = log(xm2/xm1)
endif
endif
- cs(1) = dm1m2*( -1/DBLE(8) - ca0i(1)*DBLE(1/(4*xm1)) )
+ cs(1) = dm1m2*( -1/Re(8) - ca0i(1)*Re(1/(4*xm1)) )
cs(2) = dm1m2*xlogmm/4
cs(3) = xm1*(xm1/dm1m2)/4*xlogmm
- cs(4) = xm1*( 1/DBLE(4) + ca0i(1)*DBLE(1/(2*xm1)) )
+ cs(4) = xm1*( 1/Re(4) + ca0i(1)*Re(1/(2*xm1)) )
cs(5) = -xm1*xlogmm/2
csom = cs(1) + cs(2) + cs(3) + cs(4) + cs(5)
xmxp = max(absc(cs(2)),absc(cs(3)),absc(cs(4)),
+ absc(cs(5)))
if ( xmxp.lt.xmax ) then
xmax = xmxp
cb2i(2) = csom
endif
if ( absc(cb2i(2)).gt.xloss*xmax ) goto 210
*
* give up
*
210 continue
* #] B22:
* #] xp=0, m1!=m2:
* #[ xp=0, m1==m2:
else
*
* taken over from ffxb2a, which in turns stem from my thesis GJ
*
cb2i(1) = cb0/3
- cb2i(2) = DBLE(xm1/2)*(cb0 + 1)
+ cb2i(2) = Re(xm1/2)*(cb0 + 1)
endif
* #] xp=0, m1==m2:
* #[ finish up:
ier = max(ier0,ier1)
* #] finish up:
*###] ffxb2q:
end
diff --git a/Looptools/B/ffxdb0.F b/Looptools/B/ffxdb0.F
--- a/Looptools/B/ffxdb0.F
+++ b/Looptools/B/ffxdb0.F
@@ -1,670 +1,671 @@
#include "externals.h"
+#include "types.h"
*###[ ffxdb0:
subroutine ffxdb0(cdb0,cdb0p,xp,xma,xmb,ier)
***#[*comment:***********************************************************
* *
* Calculates the the derivative of the two-point function with *
* respect to p2 and the same times p2 (one is always well-defined)*
* *
* Input: xp (real) k2, in B&D metric *
* xma (real) mass2 *
* xmb (real) mass2 *
* *
* Output: cdb0 (complex) dB0/dxp *
* cdb0p (complex) xp*dB0/dxp *
* ier (integer) # of digits lost, if >=100: error *
* *
* Calls: ffxdba *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE COMPLEX cdb0,cdb0p
- DOUBLE PRECISION xp,xma,xmb
+ ComplexType cdb0,cdb0p
+ RealType xp,xma,xmb
*
* local variables
*
- DOUBLE PRECISION dmamb,dmap,dmbp
+ RealType dmamb,dmap,dmbp
*
* common blocks
*
#include "ff.h"
*
* #] declarations:
dmamb = (sqrt(xma) - sqrt(xmb))**2
if( abs(xp - dmamb) .lt. precx .and.
& abs(dmamb) .gt. precx .and.
& xma .gt. precx .and. xmb .gt. precx ) then
cdb0p = .5D0*(xmb - xma)/dmamb*log(xmb/xma) - 2
cdb0 = cdb0p/dmamb
return
endif
* #[ get differences:
dmamb = xma - xmb
dmap = xma - xp
dmbp = xmb - xp
* #] get differences:
* #[ calculations:
call ffxdbp(cdb0,cdb0p,xp,xma,xmb,dmap,dmbp,dmamb,ier)
* #] calculations:
*###] ffxdb0:
end
*###[ ffxdbp:
subroutine ffxdbp(cdb0,cdb0p,xp,xma,xmb,dmap,dmbp,dmamb,ier)
***#[*comment:***********************************************************
* *
* calculates the derivatives of the two-point function *
* Veltman) for all possible cases: masses equal, unequal, *
* equal to zero. *
* *
* Input: xp (real) p.p, in B&D metric *
* xma (real) mass2, *
* xmb (real) mass2, *
* dm[ab]p (real) xm[ab] - xp *
* dmamb (real) xma - xmb *
* *
* Output: cdb0 (complex) B0' = dB0/dxp *
* cdb0p (complex) xp*dB0/dxp *
* ier (integer) 0=ok,>0=numerical problems,>100=error *
* *
* Calls: ffxdbp. *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE COMPLEX cdb0,cdb0p
- DOUBLE PRECISION xp,xma,xmb,dmap,dmbp,dmamb
+ ComplexType cdb0,cdb0p
+ RealType xp,xma,xmb,dmap,dmbp,dmamb
*
* local variables
*
integer i,initeq,jsign,initir
- DOUBLE PRECISION ax,ffbnd,
+ RealType ax,ffbnd,
+ xprceq,bdeq01,bdeq05,bdeq11,bdeq17,
+ xprcn3,bdn301,bdn305,bdn310,
+ xprcn5,bdn501,bdn505,bdn510,
+ xprec0,bdn001,bdn005,bdn010,bdn015
- DOUBLE PRECISION xm,dmp,xm1,xm2,dm1m2,dm1p,
+ RealType xm,dmp,xm1,xm2,dm1m2,dm1p,
+ dm2p,s,s1,s1a,s1b,s1p,s2,s2a,s2b,s2p,x,y,som,
+ xlam,slam,xlogmm,alpha,alph1,xnoe,xpneq(30),
+ xx,dfflo1,dfflo3,d1,d2,diff,h,a,b,c,d,beta,
+ betm2n,xmax,s1c,s1d,s1e,s1f,s3
external ffbnd,dfflo1,dfflo3
save initeq,xpneq,initir,
+ xprceq,bdeq01,bdeq05,bdeq11,bdeq17,
+ xprcn3,bdn301,bdn305,bdn310,
+ xprcn5,bdn501,bdn505,bdn510,
+ xprec0,bdn001,bdn005,bdn010,bdn015
*
* common blocks
*
#include "ff.h"
*
* data
*
data xprceq /-1D0/
data xprec0 /-1D0/
data xprcn3 /-1D0/
data xprcn5 /-1D0/
data initeq /0/
data initir /0/
*
* #] declarations:
* #[ which case:
*
* sort according to the type of masscombination encountered:
* 100: both masses zero, 200: one equal to zero, 300: both equal
* 400: rest.
*
if ( xma .eq. 0 ) then
if ( xmb .eq. 0 ) then
goto 100
endif
xm = xmb
dmp = dmbp
goto 200
endif
if ( xmb .eq. 0 ) then
xm = xma
dmp = dmap
goto 200
elseif ( dmamb .eq. 0 ) then
xm = xma
dmp = dmap
goto 300
elseif ( xma .gt. xmb ) then
xm2 = xma
xm1 = xmb
dm1m2 = -dmamb
dm1p = dmbp
dm2p = dmap
else
xm1 = xma
xm2 = xmb
dm1m2 = dmamb
dm1p = dmap
dm2p = dmbp
endif
goto 400
* #] which case:
* #[ both masses equal to zero:
100 continue
if ( xp.ne.0 ) cdb0 = -1/xp
cdb0p = -1
return
* #] both masses equal to zero:
* #[ one mass equal to zero:
200 continue
*
* special case xp = 0
*
if ( xp .eq. 0 ) then
cdb0p = 0
cdb0 = 1/(2*xm)
goto 990
*
* special case xp = xm
*
- elseif ( dmp.eq.0 ) then
+ elseif ( abs(dmp) .lt. diffeps ) then
if ( lsmug ) then
- if ( DBLE(cmipj(1,3)).lt.DBLE(cmipj(2,3)) ) then
- cdb0p = -1 - log(cmipj(1,3)*DBLE(1/xm))
+ if ( Re(cmipj(1,3)).lt.Re(cmipj(2,3)) ) then
+ cdb0p = -1 - log(cmipj(1,3)*Re(1/xm))
else
- cdb0p = -1 - log(cmipj(2,3)*DBLE(1/xm))
+ cdb0p = -1 - log(cmipj(2,3)*Re(1/xm))
endif
else
if ( initir.eq.0 ) then
initir = 1
print *,'ffxdb0: IR divergent B0'', using cutoff ',
+ lambda
endif
if ( lambda .le. 0 ) then
cdb0p = -1 + log(xm/mudim)/2
else
cdb0p = -1 + log(xm/lambda)/2
endif
endif
- cdb0 = cdb0p*(1/DBLE(xp))
+ cdb0 = cdb0p*(1/Re(xp))
goto 990
endif
*
* Normal case:
*
x = xp/xm
ax = abs(x)
if ( ax .lt. xloss ) then
* #[ Taylor expansion:
if ( xprec0 .ne. precx ) then
xprec0 = precx
bdn001 = ffbnd(2,1,xninv)
bdn005 = ffbnd(2,5,xninv)
bdn010 = ffbnd(2,10,xninv)
bdn015 = ffbnd(2,15,xninv)
endif
if ( ax .gt. bdn015 ) then
som = x*(xninv(17) + x*(xninv(18) + x*(xninv(19) +
+ x*(xninv(20) + x*xninv(21) ))))
else
som = 0
endif
if ( ax .gt. bdn010 ) then
som = x*(xninv(12) + x*(xninv(13) + x*(xninv(14) +
+ x*(xninv(15) + x*(xninv(16) + som )))))
endif
if ( ax .gt. bdn005 ) then
som = x*(xninv(7) + x*(xninv(8) + x*(xninv(9) +
+ x*(xninv(10) + x*(xninv(11) + som )))))
endif
if ( ax .gt. bdn001 ) then
som = x*(xninv(3) + x*(xninv(4) + x*(xninv(5) +
+ x*(xninv(6) + som ))))
endif
cdb0p = x*(xninv(2) + som)
* #] Taylor expansion:
else
* #[ short formula:
s = log(abs(dmp/xm))
cdb0p = -(1 + s*xm/xp)
- if ( xp.gt.xm ) cdb0p = cdb0p+DCMPLX(DBLE(0),DBLE(xm/xp*pi))
+ if ( xp.gt.xm ) cdb0p = cdb0p+ToComplex(Re(0),Re(xm/xp*pi))
* #] short formula:
endif
- cdb0 = cdb0p*(1/DBLE(xp))
+ cdb0 = cdb0p*(1/Re(xp))
goto 990
* #] one mass equal to zero:
* #[ both masses equal:
300 continue
*
* Both masses are equal. Not only this speeds up things, some
* cancellations have to be avoided as well.
*
* first a special case
*
if ( abs(xp) .lt. 8*xloss*xm ) then
* -#[ taylor expansion:
*
* a Taylor expansion seems appropriate as the result will go
* as k^2 but seems to go as 1/k !!
*
*--#[ data and bounds:
if ( initeq .eq. 0 ) then
initeq = 1
xpneq(1) = 1D0/6D0
do 1 i=2,30
- xpneq(i) = - xpneq(i-1)*DBLE(i)/DBLE(2*(2*i+1))
+ xpneq(i) = - xpneq(i-1)*Re(i)/Re(2*(2*i+1))
1 continue
endif
if (xprceq .ne. precx ) then
*
* calculate the boundaries for the number of terms to be
* included in the taylorexpansion
*
xprceq = precx
bdeq01 = ffbnd(1,1,xpneq)
bdeq05 = ffbnd(1,5,xpneq)
bdeq11 = ffbnd(1,11,xpneq)
bdeq17 = ffbnd(1,17,xpneq)
endif
*--#] data and bounds:
x = -xp/xm
ax = abs(x)
if ( ax .gt. bdeq17 ) then
som = x*(xpneq(18) + x*(xpneq(19) + x*(xpneq(20) +
+ x*(xpneq(21) + x*(xpneq(22) + x*(xpneq(23) +
+ x*(xpneq(24) + x*xpneq(25) )))))))
else
som = 0
endif
if ( ax .gt. bdeq11 ) then
som = x*(xpneq(12) + x*(xpneq(13) + x*(xpneq(14) +
+ x*(xpneq(15) + x*(xpneq(16) + x*(xpneq(17) + som ))))
+ ))
endif
if ( ax .gt. bdeq05 ) then
som = x*(xpneq(6) + x*(xpneq(7) + x*(xpneq(8) + x*(
+ xpneq(9) + x*(xpneq(10) + x*(xpneq(11) + som ))))))
endif
if ( ax .gt. bdeq01 ) then
som = x*(xpneq(2) + x*(xpneq(3) + x*(xpneq(4) + x*(
+ xpneq(5) + som ))))
endif
cdb0p = -x*(xpneq(1)+som)
if ( xp.ne.0 ) then
- cdb0 = cdb0p*(1/DBLE(xp))
+ cdb0 = cdb0p*(1/Re(xp))
else
cdb0 = xpneq(1)/xm
endif
goto 990
* -#] taylor expansion:
endif
* -#[ normal case:
*
* normal case
*
call ffxlmb(xlam,-xp,-xm,-xm,dmp,dmp,0D0)
if ( xlam .eq. 0 ) then
call fferr(86,ier)
return
elseif ( xlam .gt. 0 ) then
* cases 1,2 and 4
slam = sqrt(xlam)
s2a = dmp + xm
s2 = s2a + slam
if ( abs(s2) .gt. xloss*slam ) then
* looks fine
jsign = 1
else
s2 = s2a - slam
jsign = -1
endif
ax = abs(s2/(2*xm))
if ( ax .lt. xalogm ) then
s = 0
elseif( ax-1 .lt. .1 .and. s2 .gt. 0 ) then
* In this case a quicker and more accurate way is to
* calculate log(1-x).
s2 = (xp - slam)
* the following line is superfluous.
s = 2*xm/slam*dfflo1(s2/(2*xm),ier)
else
* finally the normal case
s = 2*xm/slam*log(ax)
if ( jsign .eq. -1 ) s = -s
endif
if ( xp .gt. 2*xm ) then
* in this case ( xlam>0, so xp>(2*m)^2) ) there also
* is an imaginary part
y = pi*2*xm/slam
else
y = 0
endif
else
* the root is complex (k^2 between 0 and (2*m1)^2)
slam = sqrt(-xlam)
s = 4*xm/slam*atan2(xp,slam)
y = 0
endif
xx = s - 1
- cdb0p = DCMPLX(DBLE(xx),DBLE(y))
- cdb0 = cdb0p*(1/DBLE(xp))
+ cdb0p = ToComplex(Re(xx),Re(y))
+ cdb0 = cdb0p*(1/Re(xp))
goto 990
* -#] normal case:
*
* #] both masses equal:
* #[ unequal nonzero masses:
* -#[ get log(xm2/xm1):
400 continue
x = xm2/xm1
if ( 1 .lt. xalogm*x ) then
call fferr(8,ier)
xlogmm = 0
elseif ( abs(x-1) .lt. xloss ) then
xlogmm = dfflo1(dm1m2/xm1,ier)
else
xlogmm = log(x)
endif
* -#] get log(xm2/xm1):
* -#[ xp = 0:
*
* first a special case
*
if ( xp .eq. 0 ) then
*
* repaired 19-nov-1993, see b2.frm
*
s1 = xm1*xm2*xlogmm/dm1m2**3
s2 = (xm1+xm2)/(2*dm1m2**2)
s = s1 + s2
if ( abs(s) .lt. xloss**2*s2 ) then
*
* second try
*
h = dfflo3(dm1m2/xm1,ier)
s1 = -xm1*h/dm1m2**2
s2 = 1/(2*xm1)
s3 = xm1**2*h/dm1m2**3
s = s1 + s2 + s3
if ( abs(s) .lt. xloss*max(abs(s2),abs(s3)) ) then
call ffwarn(228,ier,s,s2)
endif
endif
cdb0 = s
cdb0p = 0
goto 990
endif
* -#] xp = 0:
* -#[ normal case:
*
* proceeding with the normal case
*
call ffxlmb(xlam,-xp,-xm2,-xm1,dm2p,dm1p,dm1m2)
diff = xlam + xp*(dm2p+xm1)
if ( abs(diff) .lt. xloss*xlam ) then
h = dm1m2**2 - xp*(xm1+xm2)
if ( abs(h) .lt. xloss*dm1m2**2 ) then
if ( dm1m2**2 .lt. abs(xlam) ) diff = h
endif
endif
if ( xlam .eq. 0 ) then
call fferr(86,ier)
return
elseif ( xlam .gt. 0 ) then
* cases k^2 < -(m2+m1)^2 or k^2 > -(m2-m1)^2:
*--#[ first try:
* first try the normal way
slam = sqrt(xlam)
s2a = dm2p + xm1
s2 = s2a + slam
if ( abs(s2) .gt. xloss*slam ) then
* looks fine
jsign = 1
else
s2 = s2a - slam
jsign = -1
endif
s2 = s2**2/(4*xm1*xm2)
if ( abs(s2) .lt. xalogm ) then
call fferr(9,ier)
s2 = 0
elseif ( abs(s2-1) .lt. xloss ) then
if ( jsign.eq.1 ) then
s2 = -slam*(s2a+slam)/(2*xm1*xm2)
s2 = -diff/(2*slam*xp)*dfflo1(s2,ier)
else
ier = ier + 50
print *,'ffxdb0: untested: s2 better in first try'
s2 = +slam*(s2a-slam)/(2*xm1*xm2)
s2 = +diff/(2*slam*xp)*dfflo1(s2,ier)
endif
else
s2 = -diff/(2*slam*xp)*log(s2)
if ( jsign .eq. -1 ) s2 = -s2
endif
s1 = -dm1m2*xlogmm/(2*xp)
xx = s1+s2-1
*--#] first try:
if ( abs(xx) .lt. xloss**2*max(abs(s1),abs(s2)) ) then
*--#[ second try:
* this is unacceptable, try a better solution
s1a = diff + slam*dm1m2
if ( abs(s1a) .gt. xloss*diff ) then
* this works
s1 = -s1a/(2*xp*slam)
else
* by division a more accurate form can be found
s1 = -2*xm1*xm2*xp/(slam*(diff - slam*dm1m2))
endif
s = s1
s1 = s1*xlogmm
if ( abs(xp) .lt. xm2 ) then
s2a = xp - dm1m2
else
s2a = xm2 - dm1p
endif
s2 = s2a - slam
if ( abs(s2) .gt. xloss*slam ) then
* at least reasonable
s2 = s2 / (2*xm2)
else
* division again
s2 = (2*xp) / (s2a+slam)
endif
if ( abs(s2) .lt. .1 ) then
* choose a quick way to get the logarithm
s2 = dfflo1(s2,ier)
elseif ( s2.eq.1 ) then
print *,'ffxdbp: error: arg log would be 0!'
print *,' xp,xma,xmb = ',xp,xma,xmb
goto 600
else
s2 = log(abs(1 - s2))
endif
s2 = -diff/(slam*xp)*s2
xx = s1 + s2 - 1
*--#] second try:
if ( abs(xx) .lt. xloss**2*max(abs(s1),abs(s2)) ) then
*--#[ third try:
* (we accept two times xloss because that's the same
* as in this try)
* A Taylor expansion might work. We expand
* inside the logs. Only do the necessary work.
*
* #[ split up 1:
xnoe = s2a+slam
a = 1
b = 2/xnoe-1/xp
c = -4/(xp*xnoe)
d = sqrt((2/xnoe)**2 + 1/xp**2)
call ffroot(d1,d2,a,b,c,d,ier)
if ( xp.gt.0 ) then
beta = d2
else
beta = d1
endif
alpha = beta*diff/slam
alph1 = 1-alpha
if ( alph1 .lt. xloss ) then
s1a = 4*xp**2*xm1*xm2/(slam*dm1m2*(diff-slam*
+ dm1m2))
s1b = -diff/slam*4*xm1*xp/(dm1m2*xnoe*(2*xp-
+ xnoe))
b = -1/xp
c = -(2/xnoe)**2
call ffroot(d1,d2,a,b,c,d,ier)
if ( xp.gt.0 ) then
betm2n = d2
else
betm2n = d1
endif
d1 = s1a + s1b - diff/slam*betm2n
xmax = max(abs(s1a),abs(s1b))
if ( xmax .lt. 1 ) then
alph1 = d1
else
xmax = 1
endif
else
betm2n = beta - 2/xnoe
endif
* #] split up 1:
* #[ s2:
*
* first s2:
*
s2p = s2 - alpha
if ( abs(s2p) .lt. xloss*abs(s2) ) then
* -#[ bounds:
* determine the boundaries for 1,5,10,15 terms
if ( xprcn5 .ne. precx ) then
xprcn5 = precx
bdn501 = ffbnd(3,1,xinfac)
bdn505 = ffbnd(3,5,xinfac)
bdn510 = ffbnd(3,10,xinfac)
endif
* -#] bounds:
x = beta*xp
ax = abs(x)
if ( ax .gt. bdn510 ) then
s2a = x*(xinfac(13) + x*(xinfac(14) + x*(
+ xinfac(15) + x*(xinfac(16) + x*
+ xinfac(17) ))))
else
s2a = 0
endif
if ( ax .gt. bdn505 ) then
s2a = x*(xinfac(8) + x*(xinfac(9) + x*(
+ xinfac(10) + x*(xinfac(11) + x*(
+ xinfac(12) + s2a)))))
endif
if ( ax .gt. bdn501 ) then
s2a = x*(xinfac(4) + x*(xinfac(5) + x*(
+ xinfac(6) + x*(xinfac(7) + s2a))))
endif
s2a = x**3*(xinfac(3)+s2a)
s2b = 2*xp/xnoe*(s2a + x**2/2)
s2p = s2b - s2a
s2p = -diff/(xp*slam)*dfflo1(s2p,ier)
endif
* #] s2:
* #[ s1:
*
* next s1:
*
s1p = s1 - alph1
if ( abs(s1p) .lt. xloss*abs(s1) ) then
* -#[ bounds:
* determine the boundaries for 1,5,10,15 terms
if ( xprcn3 .ne. precx ) then
xprcn3 = precx
bdn301 = ffbnd(3,1,xinfac)
bdn305 = ffbnd(3,5,xinfac)
bdn310 = ffbnd(3,10,xinfac)
endif
* -#] bounds:
*
x = slam*(diff-slam*dm1m2)*alph1/(2*xp*xm1*xm2)
h = (2*xp*(xm1+xm2) - xp**2)/(slam-dm1m2)
ax = abs(x)
*
* see form job gets1.frm
*
s1b = diff*(diff-slam*dm1m2)*betm2n/(2*xp*xm1*
+ xm2)
s1c = 1/(xm1*xnoe*(2*xp-xnoe))*(
+ xp*( 4*xp*xm2 + 2*dm1m2**2/xm2*(xp-h) +
+ 2*dm1m2*(3*xp-h) - 8*dm1m2**2 )
+ - 2*dm1m2**3/xm2*(3*xp-h)
+ + 4*dm1m2**4/xm2
+ )
s1d = x*dm1m2/xm1
s1e = -x**2/2
if ( ax .gt. bdn310 ) then
s1a = x*(xinfac(13) + x*(xinfac(14) + x*(
+ xinfac(15) + x*(xinfac(16) + x*
+ xinfac(17) ))))
else
s1a = 0
endif
if ( ax .gt. bdn305 ) then
s1a = x*(xinfac(8) + x*(xinfac(9) + x*(
+ xinfac(10) + x*(xinfac(11) + x*(
+ xinfac(12) + s1a)))))
endif
if ( ax .gt. bdn301 ) then
s1a = x*(xinfac(4) + x*(xinfac(5) + x*(
+ xinfac(6) + x*(xinfac(7) + s1a))))
endif
s1a = -x**3 *(xinfac(3) + s1a)
s1f = dm1m2/xm1*(x**2/2 - s1a)
s1p = s1e + s1d + s1c + s1b + s1a + s1f
xmax = max(abs(s1a),abs(s1b),abs(s1c),abs(s1d),
+ abs(s1e))
s1p = s*dfflo1(s1p,ier)
endif
* #] s1:
*
* finally ...
*
xx = s1p + s2p
*--#] third try:
endif
endif
600 continue
if ( xp .gt. xm1+xm2 ) then
*--#[ imaginary part:
* in this case ( xlam>0, so xp>(m1+m2)^2) ) there also
* is an imaginary part
y = -pi*diff/(slam*xp)
else
y = 0
*--#] imaginary part:
endif
else
* the root is complex (k^2 between -(m1+m2)^2 and -(m2-m1)^2)
*--#[ first try:
slam = sqrt(-xlam)
xnoe = dm2p + xm1
s1 = -(dm1m2/(2*xp))*xlogmm
s2 = -diff/(slam*xp)*atan2(slam,xnoe)
xx = s1 + s2 - 1
*--#] first try:
y = 0
endif
- cdb0p = DCMPLX(DBLE(xx),DBLE(y))
- cdb0 = cdb0p*(1/DBLE(xp))
+ cdb0p = ToComplex(Re(xx),Re(y))
+ cdb0 = cdb0p*(1/Re(xp))
goto 990
* -#] normal case:
* #] unequal nonzero masses:
990 continue
*###] ffxdbp:
end
diff --git a/Looptools/B/ffxdb1.F b/Looptools/B/ffxdb1.F
--- a/Looptools/B/ffxdb1.F
+++ b/Looptools/B/ffxdb1.F
@@ -1,411 +1,411 @@
#include "externals.h"
+#include "types.h"
*###[ ffxdb1:
subroutine ffxdb1(cdb1, p, m1, m2, ier)
***#[*comment:***********************************************************
* *
* DB1 function (derivative of B1) *
* *
* algorithm adapted from Ansgar Denner's bcanew.f *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE COMPLEX cdb1
- DOUBLE PRECISION p, m1, m2
+ ComplexType cdb1
+ RealType p, m1, m2
integer ier
- DOUBLE COMPLEX ffpvf, ffypvf
+ ComplexType ffpvf, ffypvf
external ffpvf, ffypvf
- DOUBLE COMPLEX xp, xm, yp, ym, r
+ ComplexType xp, xm, yp, ym, r
#include "ff.h"
logical initir
save initir
data initir /.FALSE./
*
* #[ declarations:
- if( abs(p) .gt. acc*(m1 + m2) ) then
+ if( abs(p) .gt. diffeps*(m1 + m2) ) then
* IR divergent case
if( m2 .eq. 0 .and. p .eq. m1 ) then
if( .not. initir ) then
initir = .TRUE.
print *, "ffxdb1: IR divergent B1', using cutoff ",
+ lambda
endif
if( lambda .le. 0 ) then
cdb1 = .5D0*(3 + log(mudim/p))/p
else
cdb1 = .5D0*(3 + log(lambda/p))/p
endif
return
endif
call ffroots(p, m1, m2, xp, xm, yp, ym, r, ier)
- if( abs(xp - xm) .gt. acc*abs(xp + xm) ) then
+ if( abs(xp - xm) .gt. diffeps*abs(xp + xm) ) then
cdb1 = (ffypvf(2, xp, yp) - ffypvf(2, xm, ym))/r
else if( abs(xp) .gt. 10 ) then
- cdb1 = DBLE( (2/3D0 +
+ cdb1 = Re( (2/3D0 +
+ (2 - 3*xp)*ffpvf(3, xp, yp))/xp**2 )/p
- else if( abs(yp) .gt. acc ) then
- cdb1 = DBLE( (3/2D0 +
+ else if( abs(yp) .gt. diffeps ) then
+ cdb1 = Re( (3/2D0 +
+ (2 - 3*xp)*ffpvf(1, xp, yp)) )/p
else
call fferr(101, ier)
cdb1 = nan
endif
* zero momentum case
- else if( abs(m1 - m2) .gt. acc*(m1 + m2) ) then
- xm = (1 - cI*eps)*m1/(m1 - m2)
- ym = (1 - cI*eps)*m2/(m2 - m1)
+ else if( abs(m1 - m2) .gt. diffeps*(m1 + m2) ) then
+ xm = (1 - cIeps)*m1/(m1 - m2)
+ ym = (1 - cIeps)*m2/(m2 - m1)
if( abs(xm) .lt. 10 ) then
cdb1 = -(1/3D0 + ffypvf(2, xm, ym))/(m1 - m2)
else
cdb1 = -(1/3D0 + ffypvf(3, xm, ym))/m1
endif
else
cdb1 = -1/12D0/m1
endif
end
*###[ ffxdb11:
subroutine ffxdb11(cdb11, p, m1, m2, ier)
***#[*comment:***********************************************************
* *
* DB11 function (derivative of B11) *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE COMPLEX cdb11
- DOUBLE PRECISION p, m1, m2
+ ComplexType cdb11
+ RealType p, m1, m2
integer ier
- DOUBLE COMPLEX ffpvf, ffypvf
+ ComplexType ffpvf, ffypvf
external ffpvf, ffypvf
- DOUBLE COMPLEX xp, xm, yp, ym, r
+ ComplexType xp, xm, yp, ym, r
#include "ff.h"
*
* #] declarations:
- if( abs(p) .gt. acc*(m1 + m2) ) then
+ if( abs(p) .gt. diffeps*(m1 + m2) ) then
call ffroots(p, m1, m2, xp, xm, yp, ym, r, ier)
- if( abs(xp - xm) .gt. acc*abs(xp + xm) ) then
+ if( abs(xp - xm) .gt. diffeps*abs(xp + xm) ) then
cdb11 = (ffypvf(3, xm, ym) - ffypvf(3, xp, yp))/r
else if( abs(xp) .gt. 10 ) then
- cdb11 = DBLE( (-3/4D0 +
+ cdb11 = Re( (-3/4D0 +
+ (4*xp - 3)*ffpvf(4, xp, yp))/xp**2 )/p
- else if( abs(yp) .gt. acc ) then
- cdb11 = DBLE( (-4/3D0 +
+ else if( abs(yp) .gt. diffeps ) then
+ cdb11 = Re( (-4/3D0 +
+ (4*xp - 3)*ffpvf(2, xp, yp))/p )
else
c call fferr(102, ier)
cdb11 = nan
endif
* zero momentum case
- else if( abs(m1 - m2) .gt. acc*(m1 + m2) ) then
- xm = (1 - cI*eps)*m1/(m1 - m2)
- ym = (1 - cI*eps)*m2/(m2 - m1)
+ else if( abs(m1 - m2) .gt. diffeps*(m1 + m2) ) then
+ xm = (1 - cIeps)*m1/(m1 - m2)
+ ym = (1 - cIeps)*m2/(m2 - m1)
if( abs(xm) .lt. 10 ) then
cdb11 = (1/4D0 + ffypvf(3, xm, ym))/(m1 - m2)
else
cdb11 = (1/4D0 + ffypvf(4, xm, ym))/m1
endif
else
cdb11 = 1/20D0/m1
endif
end
*###[ ffxdb11:
subroutine ffxb111(cb111, p, m1, m2, ier)
***#[*comment:***********************************************************
* *
* B111 function (coefficient of p_mu p_nu p_rho) *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE COMPLEX cb111
- DOUBLE PRECISION p, m1, m2
+ ComplexType cb111
+ RealType p, m1, m2
integer ier
- DOUBLE COMPLEX ffpvf, ffypvf, ffthf, ffxlogx
+ ComplexType ffpvf, ffypvf, ffthf, ffxlogx
external ffpvf, ffypvf, ffthf, ffxlogx
- DOUBLE COMPLEX xp, xm, yp, ym, r
+ ComplexType xp, xm, yp, ym, r
#include "ff.h"
*
* #] declarations:
- if( abs(p) .gt. acc*(m1 + m2) ) then
+ if( abs(p) .gt. diffeps*(m1 + m2) ) then
call ffroots(p, m1, m2, xp, xm, yp, ym, r, ier)
if( abs(yp) .gt. .5D0 .and. abs(ym) .gt. .5D0 ) then
cb111 = 1/4D0*( log(m2/mudim) - delta +
& ffpvf(4, xp, yp) + ffpvf(4, xm, ym) )
else if( abs(xp) .lt. 10 .and. abs(xm) .lt. 10 ) then
- cb111 = 1/4D0*( log(p/mudim*(1 - cI*eps)) -
+ cb111 = 1/4D0*( log(p/mudim*(1 - cIeps)) -
& delta - 1/2D0 +
& (1 + xp)*(1 + xp**2)*ffxlogx(yp) -
& xp*(1/3D0 + xp*(1/2D0 + xp*(1 + ffxlogx(-xp)))) +
& (1 + xm)*(1 + xm**2)*ffxlogx(ym) -
& xm*(1/3D0 + xm*(1/2D0 + xm*(1 + ffxlogx(-xm)))) )
else if( abs(xp) .gt. .5D0 .and. abs(xm) .gt. .5D0 ) then
cb111 = 1/4D0*( log(m1/mudim) - delta +
& ffthf(4, xp, yp) + ffthf(4, xm, ym) )
else
c call fferr(102, ier)
cb111 = nan
endif
* zero momentum case
- else if( abs(m1 - m2) .gt. acc*(m1 + m2) ) then
- xm = (1 - cI*eps)*m1/(m1 - m2)
- ym = (1 - cI*eps)*m2/(m2 - m1)
+ else if( abs(m1 - m2) .gt. diffeps*(m1 + m2) ) then
+ xm = (1 - cIeps)*m1/(m1 - m2)
+ ym = (1 - cIeps)*m2/(m2 - m1)
if( abs(ym) .gt. .5D0 ) then
cb111 = 1/4D0*(log(m2/mudim) - delta + ffpvf(4, xm, ym))
else
cb111 = 1/4D0*(log(m1/mudim) - delta -
& (1 + xm*(1 + xm*(1 + xm)))*ffypvf(0, xm, ym) -
& xm*(xm*(xm + 1/2D0) + 1/3D0) - 1/4D0)
endif
else
cb111 = 1/4D0*(log(m2/mudim) - delta)
endif
end
*###[ ffroots
subroutine ffroots(p, m1, m2, xp, xm, yp, ym, r, ier)
***#[*comment:***********************************************************
* *
* roots of quadratic equation *
* p*x^2 + (m2 - m1 - p)*x + m2 - I eps = *
* p*(x - xp)*(x - xm) = p*(x - 1 + yp)*(x - 1 + ym) *
* i.e. x[pm] = 1 - y[pm] *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE PRECISION p, m1, m2
- DOUBLE COMPLEX xp, xm, yp, ym, r
+ RealType p, m1, m2
+ ComplexType xp, xm, yp, ym, r
integer ier
- DOUBLE PRECISION qx, qy
+ RealType qx, qy
#include "ff.h"
*
* #] declarations:
* #[ check input:
if( p .eq. 0 ) then
call fferr(39, ier)
return
endif
* #] check input:
qx = m1 - m2 + p
qy = m2 - m1 + p
- r = sqrt(DCMPLX(p*(p - m1 - m2) - m1*qy - m2*qx))
+ r = sqrt(ToComplex(p*(p - m1 - m2) - m1*qy - m2*qx))
xp = .5D0*(qx + r)/p
xm = .5D0*(qx - r)/p
if( abs(xm) .gt. abs(xp) ) then
xp = m1/(p*xm)
else if( abs(xp) .gt. abs(xm) ) then
xm = m1/(p*xp)
endif
- xp = xp + abs(p*xp)/p*eps*cI
- xm = xm - abs(p*xm)/p*eps*cI
+ xp = xp + sign(abs(xp), p)*cIeps
+ xm = xm - sign(abs(xm), p)*cIeps
ym = .5D0*(qy + r)/p
yp = .5D0*(qy - r)/p
if( abs(ym) .gt. abs(yp) ) then
yp = m2/(p*ym)
else if( abs(yp) .gt. abs(ym) ) then
ym = m2/(p*yp)
endif
- yp = yp - abs(p*yp)/p*eps*cI
- ym = ym + abs(p*ym)/p*eps*cI
-
+ yp = yp - sign(abs(yp), p)*cIeps
+ ym = ym + sign(abs(ym), p)*cIeps
end
*###[ ffpvf
- DOUBLE COMPLEX function ffpvf(n, x, y)
+ ComplexType function ffpvf(n, x, y)
***#[*comment:***********************************************************
* *
* Passarino-Veltman function f(n, x) *
* here third arg y = 1 - x *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer n
- DOUBLE COMPLEX x, y
+ ComplexType x, y
- DOUBLE COMPLEX xm
+ ComplexType xm
integer m
#include "ff.h"
*
* #] declarations:
if( abs(x) .lt. 5 ) then
if( n .eq. 0 ) then
ffpvf = -log(-y/x)
else if( abs(x) .lt. 1D-14 ) then
ffpvf = -1D0/n
else
xm = -log(-y/x)
do m = 1, n
xm = x*xm - 1D0/m
enddo
ffpvf = xm
endif
else
ffpvf = 0
xm = 1
do m = 1, 30
xm = xm/x
ffpvf = ffpvf + xm/(m + n)
if( abs(xm) .lt. precx*abs(ffpvf) ) return
enddo
endif
end
*###[ ffypvf
- DOUBLE COMPLEX function ffypvf(n, x, y)
+ ComplexType function ffypvf(n, x, y)
***#[*comment:***********************************************************
* *
* y*ffpvf(n, x, y) *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer n
- DOUBLE COMPLEX x, y
+ ComplexType x, y
- DOUBLE COMPLEX ffpvf
+ ComplexType ffpvf
external ffpvf
*
* #] declarations:
if( abs(y) .eq. 0 ) then
ffypvf = 0
else
ffypvf = y*ffpvf(n, x, y)
endif
end
*###[ ffypvf
- DOUBLE COMPLEX function ffxlogx(x)
+ ComplexType function ffxlogx(x)
***#[*comment:***********************************************************
* *
* x*log(x) *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE COMPLEX x
+ ComplexType x
*
* #] declarations:
if( abs(x) .eq. 0 ) then
ffxlogx = 0
else
ffxlogx = x*log(x)
endif
end
*###[ ffthf
- DOUBLE COMPLEX function ffthf(n, x, y)
+ ComplexType function ffthf(n, x, y)
***#[*comment:***********************************************************
* *
* y*ffpvf(n, x, y) *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer n
- DOUBLE COMPLEX x, y
+ ComplexType x, y
- DOUBLE COMPLEX ffpvf
+ ComplexType ffpvf
external ffpvf
- DOUBLE COMPLEX xm
+ ComplexType xm
integer m
#include "ff.h"
*
* #] declarations:
if( abs(x) .gt. 1D4 ) then
xm = n
ffthf = 0
do m = 1, 30
xm = xm/x
ffthf = ffthf - xm/(m*(m + n))
if( abs(xm) .lt. precx*abs(ffthf) ) return
enddo
else
xm = ffpvf(1, y, x)
ffthf = xm
do m = 1, n - 1
xm = x*xm + 1D0/(m*(m + 1))
ffthf = ffthf + xm
enddo
endif
end
diff --git a/Looptools/C/C0.F b/Looptools/C/C0.F
deleted file mode 100644
--- a/Looptools/C/C0.F
+++ /dev/null
@@ -1,696 +0,0 @@
-* C0.F
-* the scalar three-point function
-* this file is part of LoopTools
-* last modified 21 Dec 10 th
-
-#include "defs.h"
-
-#define legs 3
-#define M(i) xpi(i)
-#define P(i) xpi(i+legs)
-
-
- double complex function C0(p1, p2, p1p2, m1, m2, m3)
- implicit none
- double precision p1, p2, p1p2, m1, m2, m3
-
-#include "lt.h"
-
- external C0soft, C0coll, C0softDR, C0collDR
-
- double complex res(0:1)
- double precision xpi(6)
- integer key, ier
-
- M(1) = m1
- M(2) = m2
- M(3) = m3
- P(1) = p1
- P(2) = p2
- P(3) = p1p2
-
- if( lambda .le. 0 ) then
- call CDispatch(C0, xpi, C0softDR, C0collDR)
- return
- endif
-
- ier = 0
- key = ibits(versionkey, KeyC0, 2)
-
- if( key .ne. 1 ) then
- call ffxc0(res(0), xpi, ier)
- if( ier .gt. warndigits ) then
- ier = 0
- call ffxc0r(res(0), xpi, ier)
- if( ier .gt. warndigits ) key = ior(key, 2)
- endif
- endif
-
- if( key .ne. 0 ) then
- call CDispatch(res(1), xpi, C0soft, C0coll)
- if( key .gt. 1 .and.
- & abs(res(0) - res(1)) .gt. maxdev*abs(res(0)) ) then
- print *, "Discrepancy in C0:"
- print *, " p1 =", p1
- print *, " p2 =", p2
- print *, " p1p2 =", p1p2
- print *, " m1 =", m1
- print *, " m2 =", m2
- print *, " m3 =", m3
- print *, "C0 a =", res(0)
- print *, "C0 b =", res(1)
- if( ier .gt. errdigits ) res(0) = res(1)
- endif
- endif
-
- C0 = res(iand(key, 1))
- end
-
-************************************************************************
-* adapter code for C++
-
- subroutine c0sub(res, p1, p2, p1p2, m1, m2, m3)
- implicit none
- double complex res
- double precision p1, p2, p1p2, m1, m2, m3
-
- double complex C0
- external C0
-
- res = C0(p1, p2, p1p2, m1, m2, m3)
- end
-
-************************************************************************
-
- subroutine CDispatch(res, xpi, soft, coll)
- implicit none
- double complex res
- double precision xpi(6)
- external soft, coll
-
-#include "lt.h"
-
- integer i, z, c, perm
-
- double complex C0p3, C0p2, C0p1, C0p0
- external C0p3, C0p2, C0p1, C0p0
-
- integer p123, p231, p312
- parameter (p123 = O'123', p231 = O'231', p312 = O'312')
-
- integer xpiperm(3)
- data xpiperm /p123, p231, p312/
-
-#define Px(j) P(ibits(perm,3*(3-j),3))
-#define Mx(j) M(ibits(perm,3*(3-j),3))
-
-555 z = 0
- c = 0
- do i = 1, 3
- perm = xpiperm(i)
- if( abs(Mx(1)) .lt. eps ) then
- if( abs(Px(1) - Mx(2)) +
- & abs(Px(3) - Mx(3)) .lt. acc ) then
- if( DEBUGLEVEL .gt. 0 )
- & print '(A,O3)', "soft C0, perm = ", perm
- call soft(res, xpi, perm)
- return
- endif
- if( abs(Px(1)) + abs(Mx(2)) .lt. eps ) c = perm
- endif
- if( abs(P(i)) .lt. eps ) z = z + 1
- enddo
-
- if( c .ne. 0 ) then
- if( DEBUGLEVEL .gt. 0 )
- & print '(A,O3)', "collinear C0, perm = ", perm
- call coll(res, xpi, c)
- if( res .eq. c ) goto 555
- return
- endif
-
- goto (1, 2, 3) z
-
- res = C0p3(xpi, p123) + C0p3(xpi, p231) + C0p3(xpi, p312)
- return
-
-1 res = C0p2(xpi, p123) + C0p2(xpi, p231) + C0p2(xpi, p312)
- return
-
-2 res = C0p1(xpi, p123) + C0p1(xpi, p231) + C0p1(xpi, p312)
- return
-
-3 res = C0p0(xpi)
- end
-
-************************************************************************
-* the following routines are adapted from Ansgar Denner's bcanew.f
-* to the conventions of LoopTools;
-* they are used for double-checking the results of FF
-
-* all mom-squares != 0
-
- double complex function C0p3(xpi, perm)
- implicit none
- double precision xpi(6)
- integer perm
-
-#include "lt.h"
-
- double precision m1, m2, m3, p1, p2, p3
- double precision m12, m13, m23, a2, n
- double complex a, b, c
- double complex y1, y2, y3, y4, x1, x2, x3, x4, z3, z4
- integer z3z4, x1z3, x3z3, x2z4, x4z4
-
- double complex spence
- integer eta
- external spence, eta
-
- m1 = Mx(1)
- m2 = Mx(2)
- m3 = Mx(3)
- p1 = Px(1)
- p2 = Px(2)
- p3 = Px(3)
-
- m12 = m1 - m2
- m13 = m1 - m3
- m23 = m2 - m3
-
- a2 = (p1 - p2 - p3)**2 - 4*p2*p3
- a = sqrt(DCMPLX(a2))
- n = .5D0/p1
- c = (p1*(p1 - p2 - p3 - m13 - m23) - m12*(p2 - p3))/a
-
- y1 = n*(c + (p1 - m12))
- y4 = n*(c - (p1 - m12))
- if( abs(y1) .lt. abs(y4) )
- & y1 = ((p1 - m12)*(p2 + m23)*p3 -
- & (p1 - p2 - m13)*(m12*p2 + m23*p1))/(a2*p1*y4)
-
- y2 = n*(c - (p1 + m12))
- y4 = n*(c + (p1 + m12))
- if( abs(y2) .lt. abs(y4) )
- & y2 = ((p1 + m12)*(p3 + m13)*p2 +
- & (p1 - p3 - m23)*(m12*p3 - m13*p1))/(a2*p1*y4)
-
- b = sqrt(DCMPLX((p1 - m12)**2 - 4*p1*m2))
- y3 = n*(c + b)
- y4 = n*(c - b)
- n = (p1*((p1 - p2 - p3)*m3 + p2*p3 + m13*m23) +
- & p2*((p2 - p3 - p1)*m1 + m12*m13) +
- & p3*((p3 - p1 - p2)*m2 - m12*m23))/(a2*p1)
- if( abs(y3) .lt. abs(y4) ) then
- y3 = n/y4
- else
- y4 = n/y3
- endif
- c = a*b
- if( c .ne. 0 ) then
- y3 = y3 + cI*eps*abs(c*y3)/c
- y4 = y4 - cI*eps*abs(c*y4)/c
- else
- y3 = y3*(1 + cI*eps)
- y4 = y4*(1 - cI*eps)
- endif
-
- C0p3 = spence(y2/y3, 0D0) + spence(y2/y4, 0D0) -
- & spence(y1/y3, 0D0) - spence(y1/y4, 0D0)
-
- if( DIMAG(a) .ne. 0 ) then
- c = abs(b)/b*eps*cI
- x1 = -.5D0/p1*( p1 - m12 + b) - c
- x2 = -.5D0/p1*( p1 - m12 - b) - c
- x3 = -.5D0/p1*(-p1 - m12 + b) - c
- x4 = -.5D0/p1*(-p1 - m12 - b) - c
- z3 = 1/y3
- z4 = 1/y4
- z3z4 = eta(z3, 0D0, z4, 0D0, 0D0)
- x1z3 = eta(x1, 0D0, z3, 0D0, 0D0)
- x3z3 = eta(x3, 0D0, z3, 0D0, 0D0)
- x2z4 = eta(x2, 0D0, z4, 0D0, 0D0)
- x4z4 = eta(x4, 0D0, z4, 0D0, 0D0)
- c = log(y1)*(eta(x1, 0D0, x2, 0D0, 0D0) +
- & z3z4 - x1z3 - x2z4) -
- & log(y2)*(eta(x3, 0D0, x4, 0D0, 0D0) +
- & z3z4 - x3z3 - x4z4) +
- & log(y3)*(x1z3 - x3z3) +
- & log(y4)*(x2z4 - x4z4)
- if( DIMAG(a) .gt. 0 .and. p1 .lt. 0 ) c = c - log(y1/y2)
- C0p3 = C0p3 + c2ipi*c
- endif
-
- C0p3 = C0p3/a
- end
-
-************************************************************************
-* one mom-square zero
-
- double complex function C0p2(xpi, perm)
- implicit none
- double precision xpi(6)
- integer perm
-
-#include "lt.h"
-
- double precision m1, m2, m3, p1, p2, p3
- double precision m12, m23, m13, a, c, y1, y2
- double complex b, y3, y4
-
- double complex spence
- external spence
-
- if( abs(Px(1)) .lt. eps ) then
- C0p2 = 0
- return
- endif
-
- m1 = Mx(1)
- m2 = Mx(2)
- m3 = Mx(3)
- p1 = Px(1)
- p2 = Px(2)
- p3 = Px(3)
-
- m12 = m1 - m2
- m23 = m2 - m3
- m13 = m1 - m3
-
- if( abs(p3) .lt. eps ) then
- a = p1 - p2
- y1 = -2*p1*(m13 - a)
- y2 = -2*p1*m13
- else
- a = p3 - p1
- y1 = -2*p1*m23
- y2 = -2*p1*(m23 + a)
- endif
-
- c = p1*(p1 - p2 - p3 - m13 - m23) - m12*(p2 - p3)
- b = a*sqrt(DCMPLX((p1 - m12)**2 - 4*p1*m2))
- y3 = c + b
- y4 = c - b
- c = 4*p1*(
- & p1*((p1 - p2 - p3)*m3 + p2*p3 + m13*m23) +
- & p2*((p2 - p3 - p1)*m1 + m12*m13) +
- & p3*((p3 - p1 - p2)*m2 - m12*m23) )
- if( abs(y3) .lt. abs(y4) ) then
- y3 = c/y4
- else
- y4 = c/y3
- endif
- c = a/p1
- if( c .ne. 0 ) then
- y3 = y3 + cI*eps*abs(c*y3)/c
- y4 = y4 - cI*eps*abs(c*y4)/c
- else
- y3 = y3*(1 + cI*eps)
- y4 = y4*(1 - cI*eps)
- endif
-
- C0p2 = (spence(y2/y3, 0D0) + spence(y2/y4, 0D0) -
- & spence(y1/y3, 0D0) - spence(y1/y4, 0D0))/a
- end
-
-************************************************************************
-* two mom-squares zero
-
- double complex function C0p1(xpi, perm)
- implicit none
- double precision xpi(6)
- integer perm
-
-#include "lt.h"
-
- double precision m1, m2, m3, p1, p2, p3
- double precision m12, m23, m13, c, y1, y2
- double complex b, y3, y4
-
- double complex spence
- external spence
-
- if( abs(Px(1)) .lt. eps ) then
- C0p1 = 0
- return
- endif
-
- m1 = Mx(1)
- m2 = Mx(2)
- m3 = Mx(3)
- p1 = Px(1)
- p2 = Px(2)
- p3 = Px(3)
-
- m12 = m1 - m2
- m23 = m2 - m3
- m13 = m1 - m3
-
- C0p1 = 0
-
- if( abs(m13) .gt. acc ) then
- y1 = m23 - p1
- y2 = m23
- c = m23 + p1*m3/m13
- y3 = c - cI*eps*sign(1D0, p1/m13)*abs(c)
- C0p1 = spence(y1/y3, 0D0) - spence(y2/y3, 0D0)
- endif
-
- y1 = -2*p1*m23
- y2 = -2*p1*(m23 - p1)
-
- c = p1*(p1 - m13 - m23)
- b = p1*sqrt(DCMPLX((p1 - m12)**2 - 4*p1*m2))
- y3 = c - b
- y4 = c + b
- c = 4*p1**2*(p1*m3 + m13*m23)
- if( abs(y3) .lt. abs(y4) ) then
- y3 = c/y4
- else
- y4 = c/y3
- endif
- y3 = y3 - cI*eps*abs(y3)
- y4 = y4 + cI*eps*abs(y4)
-
- C0p1 = (C0p1 +
- & spence(y1/y3, 0D0) + spence(y1/y4, 0D0) -
- & spence(y2/y3, 0D0) - spence(y2/y4, 0D0))/p1
- end
-
-************************************************************************
-
- double complex function C0p0(xpi)
- implicit none
- double precision xpi(6)
-
-#include "lt.h"
-
- double precision m1, m2, m3
- double precision m12, m23, m13
-
- m1 = M(1)
- m2 = M(2)
- m3 = M(3)
-
- m12 = m1 - m2
- m23 = m2 - m3
- m13 = m1 - m3
-
- if( abs(m23) .lt. acc ) then
- if( abs(m13) .lt. acc ) then
- C0p0 = -.5D0/m1
- else
- C0p0 = (m13 - m1*log(m1/m3))/m13**2
- endif
- else
- if( abs(m12) .lt. acc ) then
- C0p0 = (-m23 + m3*log(m2/m3))/m23**2
- else if( abs(m13) .lt. acc ) then
- C0p0 = (m23 - m2*log(m2/m3))/m23**2
- else
- C0p0 = m3/(m13*m23)*log(m1/m3) - m2/(m12*m23)*log(m1/m2)
- endif
- endif
- end
-
-************************************************************************
-
- subroutine C0soft(res, xpi, perm)
- implicit none
- double complex res
- double precision xpi(6)
- integer perm
-
-#include "lt.h"
-
- double complex ln, spence
- external ln, spence
-
- double precision s, m1, m2
- double precision a, h1, h2, h3, ps
- double complex ls
-
- logical ini
- data ini /.FALSE./
-
- s = Px(2)
- m1 = Px(1)
- m2 = Px(3)
-
- a = sqrt(4*m1*m2)
- if( abs(a) .lt. eps ) then
- ps = max(minmass, 1D-14)
- if( abs(m1) .lt. eps ) m1 = ps
- if( abs(m2) .lt. eps ) m2 = ps
- if( .not. ini ) then
- print *, "collinear-divergent C0, using mass cutoff ", ps
- ini = .TRUE.
- endif
- endif
-
- if( abs(s) .lt. acc ) then
- if( abs(m1 - m2) .lt. acc ) then
- res = -.5D0*log(m1/lambda)/m1
- else
- res = -.25D0*log(m2*m1/lambda**2)*
- & log(m1/m2)/(m1 - m2)
- endif
- return
- endif
-
- ps = s - m1 - m2
- a = (ps - a)*(ps + a)
- if( a .lt. 0 ) then
- print *, "C0soft: complex square root not implemented"
- a = 0
- endif
- a = sqrt(a)
- if( ps .le. 0 ) then
- h1 = .5D0*(a - ps)
- else
- h1 = -2*m1*m2/(a + ps)
- endif
- ps = s - m1 + m2
- if( ps .le. 0 ) then
- h2 = .5D0*(a - ps)
- else
- h2 = -2*s*m2/(a + ps)
- endif
- ps = s + m1 - m2
- if( ps .le. 0 ) then
- h3 = .5D0*(a - ps)
- else
- h3 = -2*m1*s/(a + ps)
- endif
-
- ls = ln(-a/s, -1D0)
- res = (-pi6 +
- & spence(DCMPLX(h2/a), -1D0) + spence(DCMPLX(h3/a), -1D0) -
- & .5D0*(ln(-h2/s, -1D0)**2 + ln(-h3/s, -1D0)**2) +
- & .25D0*(ln(-m1/s, -1D0)**2 + ln(-m2/s, -1D0)**2) -
- & ls*(ln(-h1/s, -1D0) - ls) +
- & ln(-lambda/s, -1D0)*ln(h1/sqrt(m1*m2), 1D0))/a
- end
-
-************************************************************************
-
- subroutine C0coll(res, xpi, perm)
- implicit none
- double complex res
- double precision xpi(6)
- integer perm
-
-#include "lt.h"
-
- logical ini
- data ini /.FALSE./
-
- Px(1) = max(minmass, 1D-14)
- res = perm
-
- if( ini ) return
- print *, "collinear-divergent C0, using mass cutoff ", Px(1)
- ini = .TRUE.
- end
-
-************************************************************************
-
- subroutine C0softDR(res, xpi, perm)
- implicit none
- double complex res
- double precision xpi(6)
- integer perm
-
-#include "lt.h"
-
- double precision s, m1, m2
- double precision m, dm, r
- double complex root, fac, ls, lm, mK, lmK
-
- double complex Li2omx2, lnrat, cln, spence
- external Li2omx2, lnrat, cln, spence
-
- s = Px(2)
- m1 = Px(1)
- m2 = Px(3)
-
- m = sqrt(m1*m2)
- if( abs(m) .lt. eps ) then
- if( abs(m1) .lt. eps ) then
- m1 = m2
- if( abs(m1) .lt. eps ) then
- if( abs(s) .lt. eps ) then
- print *, "C0softDR: all scales zero"
- res = nan
- return
- endif
-* qltri1
- if( DEBUGLEVEL .gt. 1 ) print *, "qltri1"
- if( lambda .eq. -2 ) then
- res = 1/s
- else if( lambda .eq. -1 ) then
- res = lnrat(mudim, -s)/s
- else
- res = .5D0*lnrat(mudim, -s)**2/s
- endif
- return
- endif
- endif
- if( abs(s - m1) .lt. acc ) then
-* qltri5
- if( DEBUGLEVEL .gt. 1 ) print *, "qltri5"
- if( lambda .eq. -2 ) then
- res = 0
- else if( lambda .eq. -1 ) then
- res = -.5D0/m1
- else
- res = (-.5D0*lnrat(mudim, m1) + 1)/m1
- endif
- return
- endif
-
-* qltri4
- if( DEBUGLEVEL .gt. 1 ) print *, "qltri4"
- if( lambda .eq. -2 ) then
- res = .5D0/(s - m1)
- else if( lambda .eq. -1 ) then
- res = (.5D0*lnrat(mudim, m1) + lnrat(m1, m1 - s))/(s - m1)
- else
- ls = lnrat(m1, m1 - s)
- lm = lnrat(mudim, m1)
- res = (lm*(.25D0*lm + ls) + .5D0*ls**2 + pi12 -
- & spence(DCMPLX(s/(s - m1)), 0D0))/(s - m1)
- endif
- return
- endif
-
- if( lambda .eq. -2 ) then
- res = 0
- return
- endif
-
-* qltri6
- if( DEBUGLEVEL .gt. 1 ) print *, "qltri6"
- dm = sqrt(m1) - sqrt(m2)
- r = s - dm**2
- root = sqrt(DCMPLX((r - 4*m)/r))
- mK = -4*m/(r*(1 + root)**2)
-
- if( abs(mK - 1) .lt. acc ) then
- if( lambda .eq. -1 ) then
- res = .5D0/m
- else
- res = 0
- if( abs(m1 - m2) .gt. acc )
- & res = 2 + .5D0*(sqrt(m1) + sqrt(m2))/dm*log(m2/m1)
- res = .5D0/m*(log(mudim/m) - res)
- endif
- return
- endif
-
- lmK = cln(mK, 1D0)
- fac = 1/(r*root)
-
- if( lambda .eq. -1 ) then
- res = fac*lmK
- else
- res = fac*( lmK*(.5D0*lmK + log(mudim/m)) -
- & .125D0*log(m1/m2)**2 +
- & Li2omx2(mK, 1D0, mK, 1D0) -
- & Li2omx2(mK, 1D0, DCMPLX(sqrt(m1/m2)), 0D0) -
- & Li2omx2(mK, 1D0, DCMPLX(sqrt(m2/m1)), 0D0) )
- endif
- end
-
-************************************************************************
-
- subroutine C0collDR(res, xpi, perm)
- implicit none
- double complex res
- double precision xpi(6)
- integer perm
-
-#include "lt.h"
-
- double precision s1, s2, m
- double precision m1, m2, r
- double complex l1, l2, lm
-
- double complex Li2omrat, lnrat
- external Li2omrat, lnrat
-
- if( lambda .eq. -2 ) then
- res = 0
- return
- endif
-
- m = Mx(3)
- s1 = Px(2)
- s2 = Px(3)
-
- if( abs(m) .lt. eps ) then
-* qltri2
- if( DEBUGLEVEL .gt. 1 ) print *, "qltri2"
- r = .5D0*(s2 - s1)/s1
- if( abs(r) .lt. acc ) then
- if( lambda .eq. -1 ) then
- res = (1 - r*mudim/s1)/s1
- else
- res = (lnrat(mudim, -s1)*(1 - r) - r)/s1
- endif
- return
- endif
- l1 = lnrat(mudim, -s1)
- l2 = lnrat(mudim, -s2)
- res = (l1 - l2)/(s1 - s2)
- if( lambda .ne. -1 ) res = .5D0*(l1 + l2)*res
- return
- endif
-
-* qltri3
- if( DEBUGLEVEL .gt. 1 ) print *, "qltri3"
- m1 = m - s1
- m2 = m - s2
- l1 = lnrat(m1, m)
- l2 = lnrat(m2, m)
- lm = lnrat(mudim, m)
-
- r = .5D0*(s1 - s2)/m1
- if( abs(r) .lt. acc ) then
- if( lambda .eq. -1 ) then
- res = (1 - r)/m1
- else
- m = m/s1
- res = (lm - (m + 1)*(l2 + r) -
- & r*((m*(m - 2) - 1)*l2 + lm))/m1
- endif
- return
- endif
-
- res = l2 - l1
- if( lambda .ne. -1 )
- & res = (lm - l1 - l2)*res +
- & Li2omrat(m1, m) - Li2omrat(m2, m)
- res = res/(s1 - s2)
- end
-
diff --git a/Looptools/C/C0C.F b/Looptools/C/C0C.F
deleted file mode 100644
--- a/Looptools/C/C0C.F
+++ /dev/null
@@ -1,55 +0,0 @@
-* C0C.F
-* the scalar three-point function for complex parameters
-* this file is part of LoopTools
-* last modified 24 Jan 06 th
-
-#include "defs.h"
-
-
- double complex function C0C(p1, p2, p1p2, m1, m2, m3)
- implicit none
- double complex p1, p2, p1p2, m1, m2, m3
-
-#include "lt.h"
-
- double complex cpi(6)
- integer ier
-
- cpi(1) = m1
- cpi(2) = m2
- cpi(3) = m3
- cpi(4) = p1
- cpi(5) = p2
- cpi(6) = p1p2
- ier = 0
- call ffcc0(C0C, cpi, ier)
-
- if( ier .gt. warndigits ) then
- ier = 0
- call ffcc0r(C0C, cpi, ier)
- if( ier .gt. warndigits ) then
- print *, "C0C claims ", ier, " lost digits"
- print *, " p1 =", p1
- print *, " p2 =", p2
- print *, " p1p2 =", p1p2
- print *, " m1 =", m1
- print *, " m2 =", m2
- print *, " m3 =", m3
- endif
- endif
- end
-
-************************************************************************
-* adapter code for C++
-
- subroutine c0subc(res, p1, p2, p1p2, m1, m2, m3)
- implicit none
- double complex res
- double complex p1, p2, p1p2, m1, m2, m3
-
- double complex C0C
- external C0C
-
- res = C0C(p1, p2, p1p2, m1, m2, m3)
- end
-
diff --git a/Looptools/C/C0func.F b/Looptools/C/C0func.F
new file mode 100644
--- /dev/null
+++ b/Looptools/C/C0func.F
@@ -0,0 +1,719 @@
+* C0.F
+* the scalar three-point function
+* this file is part of LoopTools
+* last modified 1 Sep 14 th
+
+#include "externals.h"
+#include "types.h"
+
+#define npoint 3
+#include "defs.h"
+
+
+ subroutine C0func(res, para)
+ implicit none
+ ComplexType res(0:2)
+ RealType para(1,*)
+
+#include "lt.h"
+
+ external C0soft, C0coll, C0softDR, C0collDR
+
+ res(0) = 0
+ res(1) = 0
+ res(2) = 0
+
+ if( lambda .le. 0 ) then
+ call CDispatch(res, para, C0softDR, C0collDR)
+ else
+ call CDispatch(res, para, C0soft, C0coll)
+ endif
+ end
+
+************************************************************************
+
+ subroutine CDispatch(res, para, soft, coll)
+ implicit none
+ ComplexType res(0:2)
+ RealType para(1,*)
+ external soft, coll
+
+#include "lt.h"
+#include "perm.h"
+
+ integer i, z, c, s, perm, ier, key
+ ComplexType alt
+
+ ComplexType C0p3, C0p2, C0p1, C0p0
+ external C0p3, C0p2, C0p1, C0p0
+
+ integer paraperm(3)
+ data paraperm /p123, p231, p312/
+
+#define Px(j) P(ibits(perm,3*(3-j),3))
+#define Mx(j) M(ibits(perm,3*(3-j),3))
+
+ c = 0
+555 z = 0
+ s = 0
+ do i = 1, 3
+ perm = paraperm(i)
+ if( abs(Mx(1)) .lt. zeroeps ) then
+ if( abs(Px(1) - Mx(2)) +
+ & abs(Px(3) - Mx(3)) .lt. diffeps ) then
+ if( DEBUGLEVEL .gt. 0 )
+ & print '("soft C0, perm = ",O3)', perm
+ s = perm
+ goto 556
+ endif
+ if( abs(Px(1)) + abs(Mx(2)) .lt. zeroeps ) c = perm
+ endif
+ if( abs(P(i)) .lt. zeroeps ) z = z + 1
+ enddo
+
+ if( c .ne. 0 ) then
+ if( DEBUGLEVEL .gt. 0 )
+ & print '("collinear C0, perm = ",O3)', perm
+ call coll(res, para, c)
+ if( c .eq. 0 ) goto 555
+ return
+ endif
+
+556 if( lambda .lt. 0 .or. (s .ne. 0 .and. lambda .eq. 0) ) then
+ res(0) = 0
+ if( s .ne. 0 ) call soft(res, para, s)
+ return
+ endif
+
+ key = ibits(versionkey, KeyC0, 2)
+
+ if( key .ne. 1 ) then
+ ier = 0
+ call ffxc0(res(0), para, ier)
+ if( ier .gt. warndigits ) then
+ ier = 0
+ call ffxc0r(res(0), para, ier)
+ if( ier .gt. warndigits ) key = ior(key, 2)
+ if( ier .ge. errdigits ) key = ior(key, 3)
+ endif
+ if( key .eq. 0 ) return
+ alt = res(0)
+ endif
+
+ if( s .ne. 0 ) then
+ call soft(res, para, s)
+ goto 9
+ endif
+
+ goto (1, 2, 3) z
+
+ res(0) = C0p3(para, p123) + C0p3(para, p231) + C0p3(para, p312)
+ goto 9
+
+1 res(0) = C0p2(para, p123) + C0p2(para, p231) + C0p2(para, p312)
+ goto 9
+
+2 res(0) = C0p1(para, p123) + C0p1(para, p231) + C0p1(para, p312)
+ goto 9
+
+3 res(0) = C0p0(para)
+
+9 if( key .ne. 0 ) then
+ if( key .gt. 1 .and.
+ & abs(res(0) - alt) .gt. maxdev*abs(alt) ) then
+ print *, "Discrepancy in C0:"
+ print *, " p1 =", P(1)
+ print *, " p2 =", P(2)
+ print *, " p1p2 =", P(3)
+ print *, " m1 =", M(1)
+ print *, " m2 =", M(2)
+ print *, " m3 =", M(3)
+ print *, "C0 a =", alt
+ print *, "C0 b =", res(0)
+ if( ier .gt. errdigits ) alt = res(0)
+ endif
+ endif
+
+ if( .not. btest(key, 0) ) res(0) = alt
+ end
+
+************************************************************************
+
+ subroutine CDump(s, para, perm)
+ implicit none
+ character*(*) s
+ RealType para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ print '(A,", perm = ",O3)', s, perm
+ if( DEBUGLEVEL .gt. 1 ) then
+ print *, "p1 =", Px(1)
+ print *, "p2 =", Px(2)
+ print *, "p3 =", Px(3)
+ print *, "m1 =", Mx(1)
+ print *, "m2 =", Mx(2)
+ print *, "m3 =", Mx(3)
+ endif
+ end
+
+************************************************************************
+* the following routines are adapted from Ansgar Denner's bcanew.f
+* to the conventions of LoopTools;
+* they are used for double-checking the results of FF
+
+* all mom-squares != 0
+
+ ComplexType function C0p3(para, perm)
+ implicit none
+ RealType para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ RealType m1, m2, m3, p1, p2, p3, pp1, pp2, pp3
+ RealType m12, m13, m23, a2, n, n1, n2, n3, n123, s
+ ComplexType a, b, c
+ ComplexType y1, y2, y3, y4, x1, x2, x3, x4, z3, z4
+ integer z3z4, x1z3, x3z3, x2z4, x4z4
+
+ ComplexType spence
+ integer eta
+ external spence, eta
+
+ if( DEBUGLEVEL .gt. 0 ) call CDump("C0p3", para, perm)
+
+ m1 = Mx(1)
+ m2 = Mx(2)
+ m3 = Mx(3)
+ p1 = Px(1)
+ p2 = Px(2)
+ p3 = Px(3)
+
+ m12 = m1 - m2
+ m13 = m1 - m3
+ m23 = m2 - m3
+
+ a2 = (p1 - p2 - p3)**2 - 4*p2*p3
+ a = sqrt(ToComplex(a2))
+ n = .5D0/p1
+ c = (p1*(p1 - p2 - p3 - m13 - m23) - m12*(p2 - p3))/a
+
+ n123 = p1*(p2*p3 + m13*m23) + m12*(m13*p2 - m23*p3)
+ pp1 = p1*(p1 - p2 - p3)
+ pp2 = p2*(p1 - p2 + p3)
+ pp3 = p3*(p1 + p2 - p3)
+ n1 = n123 - m23*pp1 - m12*pp2
+ n2 = n123 - m13*pp1 + m12*pp3
+ n3 = n123 + m3*pp1 - m1*pp2 - m2*pp3
+
+ y1 = n*(c + (p1 - m12))
+ y4 = n*(c - (p1 - m12))
+ if( abs(y1) .lt. abs(y4) ) y1 = n1/(a2*p1*y4)
+
+ y2 = n*(c - (p1 + m12))
+ y4 = n*(c + (p1 + m12))
+ if( abs(y2) .lt. abs(y4) ) y2 = n2/(a2*p1*y4)
+
+ b = sqrt(ToComplex((p1 - m12)**2 - 4*p1*m2))
+ y3 = n*(c + b)
+ y4 = n*(c - b)
+ if( abs(y3) .lt. abs(y4) ) then
+ y3 = n3/(a2*p1*y4)
+ else
+ y4 = n3/(a2*p1*y3)
+ endif
+ s = Re(a*b)
+ y3 = y3 + sign(abs(y3), s)*cIeps
+ y4 = y4 - sign(abs(y4), s)*cIeps
+
+ C0p3 = spence(0, y2/y3, 0D0) + spence(0, y2/y4, 0D0) -
+ & spence(0, y1/y3, 0D0) - spence(0, y1/y4, 0D0)
+
+ if( Im(a) .ne. 0 ) then
+ c = cIeps
+ if( abs(b) .ne. 0 ) c = abs(b)/b*c
+ x1 = c - n*( p1 - m12 + b)
+ x2 = c - n*( p1 - m12 - b)
+ x3 = c - n*(-p1 - m12 + b)
+ x4 = c - n*(-p1 - m12 - b)
+ z3 = 1/y3
+ z4 = 1/y4
+ z3z4 = eta(z3, 0D0, z4, 0D0, 0D0)
+ x1z3 = eta(x1, 0D0, z3, 0D0, 0D0)
+ x3z3 = eta(x3, 0D0, z3, 0D0, 0D0)
+ x2z4 = eta(x2, 0D0, z4, 0D0, 0D0)
+ x4z4 = eta(x4, 0D0, z4, 0D0, 0D0)
+ c = log(y1)*(eta(x1, 0D0, x2, 0D0, 0D0) +
+ & z3z4 - x1z3 - x2z4) -
+ & log(y2)*(eta(x3, 0D0, x4, 0D0, 0D0) +
+ & z3z4 - x3z3 - x4z4) +
+ & log(y3)*(x1z3 - x3z3) +
+ & log(y4)*(x2z4 - x4z4)
+ if( Im(a) .gt. 0 .and. p1 .lt. 0 ) c = c - log(y1/y2)
+ C0p3 = C0p3 + c2ipi*c
+ endif
+
+ C0p3 = C0p3/a
+
+ if( DEBUGLEVEL .gt. 1 ) print *, "C0p3 =", C0p3
+ end
+
+************************************************************************
+* one mom-square zero
+
+ ComplexType function C0p2(para, perm)
+ implicit none
+ RealType para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ RealType m1, m2, m3, p1, p2, p3
+ RealType m12, m23, m13, a, c, y1, y2
+ ComplexType b, y3, y4
+
+ ComplexType spence
+ external spence
+
+ if( DEBUGLEVEL .gt. 0 ) call CDump("C0p2", para, perm)
+
+ if( abs(Px(1)) .lt. zeroeps ) then
+ C0p2 = 0
+ return
+ endif
+
+ m1 = Mx(1)
+ m2 = Mx(2)
+ m3 = Mx(3)
+ p1 = Px(1)
+ p2 = Px(2)
+ p3 = Px(3)
+
+ m12 = m1 - m2
+ m23 = m2 - m3
+ m13 = m1 - m3
+
+ if( abs(p3) .lt. zeroeps ) then
+ a = p1 - p2
+ y1 = -2*p1*(m13 - a)
+ y2 = -2*p1*m13
+ else
+ a = p3 - p1
+ y1 = -2*p1*m23
+ y2 = -2*p1*(m23 + a)
+ endif
+
+ c = p1*(p1 - p2 - p3 - m13 - m23) - m12*(p2 - p3)
+ b = a*sqrt(ToComplex((p1 - m12)**2 - 4*p1*m2))
+ y3 = c + b
+ y4 = c - b
+ c = 4*p1*(
+ & p1*((p1 - p2 - p3)*m3 + p2*p3 + m13*m23) +
+ & p2*((p2 - p3 - p1)*m1 + m12*m13) +
+ & p3*((p3 - p1 - p2)*m2 - m12*m23) )
+ if( abs(y3) .lt. abs(y4) ) then
+ y3 = c/y4
+ else
+ y4 = c/y3
+ endif
+ c = a/p1
+ y3 = y3 + sign(abs(y3), c)*cIeps
+ y4 = y4 - sign(abs(y4), c)*cIeps
+
+ C0p2 = (spence(0, y2/y3, 0D0) + spence(0, y2/y4, 0D0) -
+ & spence(0, y1/y3, 0D0) - spence(0, y1/y4, 0D0))/a
+
+ if( DEBUGLEVEL .gt. 1 ) print *, "C0p2 =", C0p2
+ end
+
+************************************************************************
+* two mom-squares zero
+
+ ComplexType function C0p1(para, perm)
+ implicit none
+ RealType para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ RealType m1, m2, m3, p1, p2, p3
+ RealType m12, m23, m13, c, y1, y2
+ ComplexType b, y3, y4
+
+ ComplexType spence
+ external spence
+
+ if( DEBUGLEVEL .gt. 0 ) call CDump("C0p1", para, perm)
+
+ if( abs(Px(1)) .lt. zeroeps ) then
+ C0p1 = 0
+ return
+ endif
+
+ m1 = Mx(1)
+ m2 = Mx(2)
+ m3 = Mx(3)
+ p1 = Px(1)
+ p2 = Px(2)
+ p3 = Px(3)
+
+ m12 = m1 - m2
+ m23 = m2 - m3
+ m13 = m1 - m3
+
+ C0p1 = 0
+
+ if( abs(m13) .gt. diffeps ) then
+ y1 = m23 - p1
+ y2 = m23
+ c = m23 + p1*m3/m13
+ y3 = c - sign(c, p1/m13)*cIeps
+ C0p1 = spence(0, y1/y3, 0D0) - spence(0, y2/y3, 0D0)
+ endif
+
+ y1 = -2*p1*m23
+ y2 = -2*p1*(m23 - p1)
+
+ c = p1*(p1 - m13 - m23)
+ b = p1*sqrt(ToComplex((p1 - m12)**2 - 4*p1*m2))
+ y3 = c - b
+ y4 = c + b
+ c = 4*p1**2*(p1*m3 + m13*m23)
+ if( abs(y3) .lt. abs(y4) ) then
+ y3 = c/y4
+ else
+ y4 = c/y3
+ endif
+ y3 = y3 - abs(y3)*cIeps
+ y4 = y4 + abs(y4)*cIeps
+
+ C0p1 = (C0p1 +
+ & spence(0, y1/y3, 0D0) + spence(0, y1/y4, 0D0) -
+ & spence(0, y2/y3, 0D0) - spence(0, y2/y4, 0D0))/p1
+
+ if( DEBUGLEVEL .gt. 1 ) print *, "C0p1 =", C0p1
+ end
+
+************************************************************************
+
+ ComplexType function C0p0(para)
+ implicit none
+ RealType para(1,*)
+
+#include "lt.h"
+#include "perm.h"
+
+ RealType m1, m2, m3
+ RealType m12, m23, m13
+
+ if( DEBUGLEVEL .gt. 0 ) call CDump("C0p0", para, p123)
+
+ m1 = M(1)
+ m2 = M(2)
+ m3 = M(3)
+
+ m12 = m1 - m2
+ m23 = m2 - m3
+ m13 = m1 - m3
+
+ if( abs(m23) .lt. diffeps ) then
+ if( abs(m13) .lt. diffeps ) then
+ C0p0 = -.5D0/m1
+ else
+ C0p0 = (m13 - m1*log(m1/m3))/m13**2
+ endif
+ else
+ if( abs(m12) .lt. diffeps ) then
+ C0p0 = (-m23 + m3*log(m2/m3))/m23**2
+ else if( abs(m13) .lt. diffeps ) then
+ C0p0 = (m23 - m2*log(m2/m3))/m23**2
+ else
+ C0p0 = m3/(m13*m23)*log(m1/m3) - m2/(m12*m23)*log(m1/m2)
+ endif
+ endif
+
+ if( DEBUGLEVEL .gt. 1 ) print *, "C0p0 =", C0p0
+ end
+
+************************************************************************
+
+ subroutine C0soft(res, para, perm)
+ implicit none
+ ComplexType res
+ RealType para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ ComplexType spence
+ external spence
+
+ RealType s, m1, m2
+ RealType a, h1, h2, h3, ps
+ ComplexType ls
+
+ logical ini
+ data ini /.FALSE./
+
+ if( DEBUGLEVEL .gt. 0 ) call CDump("C0soft", para, perm)
+
+ s = Px(2)
+ m1 = Px(1)
+ m2 = Px(3)
+
+ a = sqrt(4*m1*m2)
+ if( abs(a) .lt. zeroeps ) then
+ ps = max(minmass, 1D-14)
+ if( abs(m1) .lt. zeroeps ) m1 = ps
+ if( abs(m2) .lt. zeroeps ) m2 = ps
+ if( .not. ini ) then
+ print *, "collinear-divergent C0, using mass cutoff ", ps
+ ini = .TRUE.
+ endif
+ endif
+
+ if( abs(s) .lt. diffeps ) then
+ if( abs(m1 - m2) .lt. diffeps ) then
+ res = -.5D0*log(m1/lambda)/m1
+ else
+ res = -.25D0*log(m2*m1/lambda**2)*
+ & log(m1/m2)/(m1 - m2)
+ endif
+ return
+ endif
+
+ ps = s - m1 - m2
+ a = (ps - a)*(ps + a)
+ if( a .lt. 0 ) then
+ print *, "C0soft: complex square-root not implemented"
+ a = 0
+ endif
+ a = sqrt(a)
+ if( ps .le. 0 ) then
+ h1 = .5D0*(a - ps)
+ else
+ h1 = -2*m1*m2/(a + ps)
+ endif
+ ps = s - m1 + m2
+ if( ps .le. 0 ) then
+ h2 = .5D0*(a - ps)
+ else
+ h2 = -2*s*m2/(a + ps)
+ endif
+ ps = s + m1 - m2
+ if( ps .le. 0 ) then
+ h3 = .5D0*(a - ps)
+ else
+ h3 = -2*m1*s/(a + ps)
+ endif
+
+ ls = ln(-a/s, -1)
+ res = (-pi6 +
+ & spence(0, ToComplex(h2/a), -1D0) +
+ & spence(0, ToComplex(h3/a), -1D0) -
+ & .5D0*(ln(-h2/s, -1)**2 + ln(-h3/s, -1)**2) +
+ & .25D0*(ln(-m1/s, -1)**2 + ln(-m2/s, -1)**2) -
+ & ls*(ln(-h1/s, -1) - ls) +
+ & ln(-lambda/s, -1)*ln(h1/sqrt(m1*m2), 1))/a
+
+ if( DEBUGLEVEL .gt. 1 ) print *, "C0soft =", res
+ end
+
+************************************************************************
+
+ subroutine C0coll(res, para, perm)
+ implicit none
+ ComplexType res
+ RealType para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ logical ini
+ data ini /.FALSE./
+
+ if( DEBUGLEVEL .gt. 0 ) call CDump("C0coll", para, perm)
+
+ Px(1) = max(minmass, 1D-14)
+ if( ini ) then
+ print *, "collinear-divergent C0, using mass cutoff ", Px(1)
+ ini = .TRUE.
+ endif
+
+ perm = 0
+ end
+
+************************************************************************
+
+ subroutine C0softDR(res, para, perm)
+ implicit none
+ ComplexType res(0:2)
+ RealType para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ RealType s, m1, m2
+ RealType m, dm, r, f
+ ComplexType root, fac, ls, lm, mK, lmK
+
+ ComplexType Li2omx2, spence
+ external Li2omx2, spence
+
+ if( DEBUGLEVEL .gt. 0 ) call CDump("C0softDR", para, perm)
+
+ s = Px(2)
+ m1 = Px(1)
+ m2 = Px(3)
+
+ m = sqrt(m1*m2)
+ if( abs(m) .lt. zeroeps ) then
+ if( abs(m1) .lt. zeroeps ) then
+ m1 = m2
+ if( abs(m1) .lt. zeroeps ) then
+ if( abs(s) .lt. zeroeps ) then
+ print *, "C0softDR: all scales zero"
+ res(0) = nan
+ res(1) = nan
+ res(2) = nan
+ goto 9
+ endif
+* qltri1
+ if( DEBUGLEVEL .gt. 1 ) print *, "C0softDR: qltri1"
+ lm = lnrat(mudim, -s)
+ res(2) = 1/s
+ res(1) = lm/s
+ res(0) = .5D0*lm*res(1)
+ goto 9
+ endif
+ endif
+ if( abs(s - m1) .lt. diffeps ) then
+* qltri5
+ if( DEBUGLEVEL .gt. 1 ) print *, "C0softDR: qltri5"
+ f = -.5D0/m1
+ res(1) = f
+ res(0) = f*(lnrat(mudim, m1) - 2)
+ res(2) = 0
+ goto 9
+ endif
+
+* qltri4
+ if( DEBUGLEVEL .gt. 1 ) print *, "C0softDR: qltri4"
+ ls = lnrat(m1, m1 - s)
+ lm = lnrat(mudim, m1)
+ f = .5D0/(s - m1)
+ res(2) = f
+ res(1) = f*(lm + 2*ls)
+ res(0) = f*((ls + lm*(1 - 1/sqrt2))*(ls + lm*(1 + 1/sqrt2)) +
+ & pi6 - 2*spence(0, ToComplex(s/(s - m1)), 0D0))
+ goto 9
+ endif
+
+* qltri6
+ if( DEBUGLEVEL .gt. 1 ) print *, "C0softDR: qltri6"
+ dm = sqrt(m1) - sqrt(m2)
+ r = s - dm**2
+ root = sqrt(ToComplex((r - 4*m)/r))
+ mK = -4*m/(r*(1 + root)**2)
+
+ if( abs(mK - 1) .lt. diffeps ) then
+ r = 0
+ if( abs(m1 - m2) .gt. diffeps )
+ & r = 2 + .5D0*(sqrt(m1) + sqrt(m2))/dm*log(m2/m1)
+ f = .5D0/m
+ res(1) = f
+ res(0) = f*(log(mudim/m) - r)
+ res(2) = 0
+ goto 9
+ endif
+
+ lmK = ln(mK, 1)
+ fac = 1/(r*root)
+ res(0) = fac*( lmK*(.5D0*lmK + log(mudim/m)) -
+ & .125D0*log(m1/m2)**2 +
+ & Li2omx2(mK, 1D0, mK, 1D0) -
+ & Li2omx2(mK, 1D0, ToComplex(sqrt(m1/m2)), 0D0) -
+ & Li2omx2(mK, 1D0, ToComplex(sqrt(m2/m1)), 0D0) )
+ res(1) = fac*lmK
+ res(2) = 0
+
+9 if( DEBUGLEVEL .gt. 1 ) then
+ print *, "C0softDR:0 =", res(0)
+ print *, "C0softDR:1 =", res(1)
+ print *, "C0softDR:2 =", res(2)
+ endif
+ end
+
+************************************************************************
+
+ subroutine C0collDR(res, para, perm)
+ implicit none
+ ComplexType res(0:2)
+ RealType para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ RealType s1, s2, m
+ RealType m1, m2, r
+ ComplexType l1, l2, lm
+
+ ComplexType Li2omrat
+ external Li2omrat
+
+ if( DEBUGLEVEL .gt. 0 ) call CDump("C0collDR", para, perm)
+
+ m = Mx(3)
+ s1 = Px(2)
+ s2 = Px(3)
+
+ if( abs(m) .lt. zeroeps ) then
+* qltri2
+ if( DEBUGLEVEL .gt. 1 ) print *, "C0collDR: qltri2"
+ r = .5D0*(s2 - s1)/s1
+ if( abs(r) .lt. diffeps ) then
+ res(0) = (lnrat(mudim, -s1)*(1 - r) - r)/s1
+ res(1) = (1 - r*mudim/s1)/s1
+ res(2) = 0
+ goto 9
+ endif
+ l1 = lnrat(mudim, -s1)
+ l2 = lnrat(mudim, -s2)
+ res(1) = (l1 - l2)/(s1 - s2)
+ res(0) = .5D0*(l1 + l2)*res(1)
+ res(2) = 0
+ goto 9
+ endif
+
+* qltri3
+ if( DEBUGLEVEL .gt. 1 ) print *, "C0collDR: qltri3"
+ m1 = m - s1
+ m2 = m - s2
+ l2 = lnrat(m2, m)
+ lm = lnrat(mudim, m)
+
+ r = .5D0*(s1 - s2)/m1
+ if( abs(r) .lt. diffeps ) then
+ m = m/s1
+ res(0) = (lm - (m + 1)*(l2 + r) -
+ & r*((m*(m - 2) - 1)*l2 + lm))/m1
+ res(1) = (1 - r)/m1
+ res(2) = 0
+ goto 9
+ endif
+
+ l1 = lnrat(m1, m)
+ res(0) = ((lm - l1 - l2)*(l2 - l1) +
+ & Li2omrat(m1, m) - Li2omrat(m2, m))/(s1 - s2)
+ res(1) = (l2 - l1)/(s1 - s2)
+ res(2) = 0
+
+9 if( DEBUGLEVEL .gt. 1 ) then
+ print *, "C0collDR:0 =", res(0)
+ print *, "C0collDR:1 =", res(1)
+ print *, "C0collDR:2 =", res(2)
+ endif
+ end
+
diff --git a/Looptools/C/C0funcC.F b/Looptools/C/C0funcC.F
new file mode 100644
--- /dev/null
+++ b/Looptools/C/C0funcC.F
@@ -0,0 +1,38 @@
+* C0funcC.F
+* the scalar three-point function for complex parameters
+* this file is part of LoopTools
+* last modified 20 Feb 14 th
+
+#include "externals.h"
+#include "types.h"
+
+#define npoint 3
+#include "defs.h"
+
+
+ subroutine C0funcC(res, para)
+ implicit none
+ ComplexType res, para(1,*)
+
+ integer ier
+
+#include "lt.h"
+
+ ier = 0
+ call ffcc0(res, para, ier)
+
+ if( ier .gt. warndigits ) then
+ ier = 0
+ call ffcc0r(res, para, ier)
+ if( ier .gt. warndigits ) then
+ print *, "C0C claims ", ier, " lost digits"
+ print *, " p1 =", P(1)
+ print *, " p2 =", P(2)
+ print *, " p1p2 =", P(3)
+ print *, " m1 =", M(1)
+ print *, " m2 =", M(2)
+ print *, " m3 =", M(3)
+ endif
+ endif
+ end
+
diff --git a/Looptools/C/Cget.F b/Looptools/C/Cget.F
--- a/Looptools/C/Cget.F
+++ b/Looptools/C/Cget.F
@@ -1,207 +1,312 @@
* Cget.F
* the three-point tensor coefficients
* this file is part of LoopTools
* improvements by M. Rauch
-* last modified 28 Sep 10 th
+* last modified 20 Jan 16 th
+#include "externals.h"
+#include "types.h"
+
+#define npoint 3
#include "defs.h"
- integer function XCget(p1, p2, p1p2, m1, m2, m3)
+ subroutine XCpara(para, p1, p2, p1p2, m1, m2, m3)
+ implicit none
+ DVAR para(1,*)
+ DVAR p1, p2, p1p2, m1, m2, m3
+
+#include "lt.h"
+
+ P(1) = p1
+ P(2) = p2
+ P(3) = p1p2
+
+ M(1) = m1
+ if( abs(M(1)) .lt. minmass ) M(1) = 0
+ M(2) = m2
+ if( abs(M(2)) .lt. minmass ) M(2) = 0
+ M(3) = m3
+ if( abs(M(3)) .lt. minmass ) M(3) = 0
+ end
+
+************************************************************************
+
+ memindex function XCget(p1, p2, p1p2, m1, m2, m3)
implicit none
DVAR p1, p2, p1p2, m1, m2, m3
#include "lt.h"
- integer cachelookup
- external cachelookup, XCcoeff
+ memindex cacheindex
+ external cacheindex, XCcoefx
- integer dummy
- DVAR dvardummy
+#ifdef COMPLEXPARA
+ memindex Cget
+ external Cget
+#endif
- DVAR para(Pcc)
+ DVAR para(1,Pcc)
- para(1) = p1
- para(2) = p2
- para(3) = p1p2
- para(4) = m1
- if( abs(para(4)) .lt. minmass ) para(4) = 0
- para(5) = m2
- if( abs(para(5)) .lt. minmass ) para(5) = 0
- para(6) = m3
- if( abs(para(6)) .lt. minmass ) para(6) = 0
- XCget = cachelookup(para, Cval(1,0), XCcoeff, RC*Pcc, Ncc)
+#ifdef COMPLEXPARA
+ if( abs(Im(p1)) + abs(Im(p2)) + abs(Im(p1p2)) .gt. 0 )
+ & print *, "Complex momenta not implemented"
+ if( abs(Im(m1)) + abs(Im(m2)) + abs(Im(m3)) .eq. 0 ) then
+ XCget = Cget(p1, p2, p1p2, m1, m2, m3) - offsetC
+ return
+ endif
+#endif
+
+ call XCpara(para, p1, p2, p1p2, m1, m2, m3)
+ XCget = cacheindex(para, Cval(1,0), XCcoefx, RC*Pcc, Ncc, Cno)
end
************************************************************************
- double complex function XC0i(i, p1, p2, p1p2, m1, m2, m3)
+ subroutine XCput(res, p1, p2, p1p2, m1, m2, m3)
+ implicit none
+ ComplexType res(*)
+ DVAR p1, p2, p1p2, m1, m2, m3
+
+#include "lt.h"
+
+ external XCcoefx
+
+ DVAR para(1,Pcc)
+
+#ifdef COMPLEXPARA
+ if( abs(Im(p1)) + abs(Im(p2)) + abs(Im(p1p2)) .gt. 0 )
+ & print *, "Complex momenta not implemented"
+ if( abs(Im(m1)) + abs(Im(m2)) + abs(Im(m3)) .eq. 0 ) then
+ call Cput(res, p1, p2, p1p2, m1, m2, m3)
+ return
+ endif
+#endif
+
+ call XCpara(para, p1, p2, p1p2, m1, m2, m3)
+ call cachecopy(res, para, Cval(1,0), XCcoefx, RC*Pcc, Ncc, Cno)
+ end
+
+************************************************************************
+
+ subroutine XC0nocache(res, p1, p2, p1p2, m1, m2, m3)
+ implicit none
+ ComplexType res(*)
+ DVAR p1, p2, p1p2, m1, m2, m3
+
+#include "lt.h"
+
+ DVAR para(1,Pcc)
+
+#ifdef COMPLEXPARA
+ if( abs(Im(p1)) + abs(Im(p2)) + abs(Im(p1p2)) .gt. 0 )
+ & print *, "Complex momenta not implemented"
+ if( abs(Im(m1)) + abs(Im(m2)) + abs(Im(m3)) .eq. 0 ) then
+ call C0nocache(res, p1, p2, p1p2, m1, m2, m3)
+ return
+ endif
+#endif
+
+ call XCpara(para, p1, p2, p1p2, m1, m2, m3)
+ call C0func(res, para)
+ end
+
+************************************************************************
+
+ ComplexType function XC0i(i, p1, p2, p1p2, m1, m2, m3)
implicit none
integer i
DVAR p1, p2, p1p2, m1, m2, m3
#include "lt.h"
- integer XCget
+ memindex XCget
external XCget
- integer b
+ memindex b
b = XCget(p1, p2, p1p2, m1, m2, m3)
- XC0i = Cval(i,b)
+ XC0i = Cval(i+epsi,b)
end
************************************************************************
- subroutine XCcoeff(para, C, ldpara)
+ ComplexType function XC0(p1, p2, p1p2, m1, m2, m3)
implicit none
- integer ldpara
- DVAR para(ldpara,Pcc)
- double complex C(Ncc)
+ DVAR p1, p2, p1p2, m1, m2, m3
#include "lt.h"
- integer XBget
- double complex XC0
- external XBget, XC0
+ ComplexType XC0i
+ external XC0i
+
+ XC0 = XC0i(cc0, p1, p2, p1p2, m1, m2, m3)
+ end
+
+************************************************************************
+
+ subroutine XCcoefx(C, para)
+ implicit none
+ ComplexType C(*)
+ DVAR para(1,*)
+
+#include "lt.h"
+
+ memindex b12, b23, b13
+
+ memindex XBget
+ external XBget
+
+ b12 = XBget(P(1), M(1), M(2))
+ b23 = XBget(P(2), M(2), M(3))
+ b13 = XBget(P(3), M(1), M(3))
+
+ call XCcoeff(C, para, Bval(1,b12), Bval(1,b23), Bval(1,b13))
+ end
+
+************************************************************************
+
+ subroutine XCcoeff(C, para, B12, B23, B13)
+ implicit none
+ ComplexType C(*), B12(*), B23(*), B13(*)
+ DVAR para(1,*)
+
+#include "lt.h"
+
+ memindex XBget
+ external XBget
DVAR p1, p2, p1p2, m1, m2, m3
DVAR f1, f2
QVAR G(2,2)
- double complex bsum, b1sum, b00sum, b11sum, in(2)
- integer B12, B23, B13
+ ComplexType bsum(0:2), b1sum(0:2), b00sum(0:2), b11sum(0:2)
+ ComplexType in(0:2,2)
logical dump
#ifdef SOLVE_EIGEN
QVAR Ginv(2,2)
+#define IN(i) in(:,i)
#define SOLVE_SETUP XInverse(2, G,2, Ginv,2)
-#define SOLVE(b) XSolve(2, G,2, Ginv,2, b)
+#define SOLVER(b) XSolve(2, G,2, Ginv,2, b)
#else
integer perm(2)
-#define IN(i) in(perm(i))
+#define IN(i) in(:,perm(i))
#define SOLVE_SETUP XDecomp(2, G,2, perm)
-#define SOLVE(b) XSolve(2, G,2, b)
+#define SOLVER(b) XSolve(2, G,2, b)
#endif
+#define OUT(i) in(:,i)
-#ifdef COMPLEXPARA
- if( abs(DIMAG(para(1,1))) +
- & abs(DIMAG(para(1,2))) +
- & abs(DIMAG(para(1,3))) .gt. 0 )
- & print *, "Warning: complex momenta not implemented"
- if( abs(DIMAG(para(1,4))) +
- & abs(DIMAG(para(1,5))) +
- & abs(DIMAG(para(1,6))) .eq. 0 ) then
- call Ccoeff(para, C, 2)
- return
- endif
-#endif
-
- p1 = para(1,1)
- p2 = para(1,2)
- p1p2 = para(1,3)
- m1 = para(1,4)
- m2 = para(1,5)
- m3 = para(1,6)
-
- B12 = XBget(p1, m1, m2)
- B23 = XBget(p2, m2, m3)
- B13 = XBget(p1p2, m1, m3)
+ integer finite(0:2)
+ data finite /1, 0, 0/
serial = serial + 1
dump = ibits(debugkey, DebugC, 1) .ne. 0 .and.
& serial .ge. debugfrom .and. serial .le. debugto
- if( dump ) call XDumpPara(3, para, ldpara, "Ccoeff")
+ if( dump ) call XDumpPara(3, para, "Ccoeff")
- f1 = QPREC(m2) - QPREC(m1) - QPREC(p1)
- f2 = QPREC(m3) - QPREC(m1) - QPREC(p1p2)
+ m1 = M(1)
+ m2 = M(2)
+ m3 = M(3)
+ p1 = P(1)
+ p2 = P(2)
+ p1p2 = P(3)
- G(1,1) = 2*QPREC(p1)
- G(2,2) = 2*QPREC(p1p2)
- G(1,2) = QPREC(p1) + QPREC(p1p2) - QPREC(p2)
+ f1 = m2
+ f1 = f1 - m1
+ f1 = f1 - p1
+ f2 = m3
+ f2 = f2 - m1
+ f2 = f2 - p1p2
+
+ G(1,1) = 2*p1
+ G(2,2) = 2*p1p2
+ G(1,2) = p1
+ G(1,2) = G(1,2) + p1p2
+ G(1,2) = G(1,2) - p2
G(2,1) = G(1,2)
call SOLVE_SETUP
- bsum = Bval(bb0,B23) + Bval(bb1,B23)
- b1sum = Bval(bb1,B23) + Bval(bb11,B23)
- b00sum = Bval(bb00,B23) + Bval(bb001,B23)
- b11sum = Bval(bb11,B23) + Bval(bb111,B23)
+ bsum = B23(BB0) + B23(BB1)
+ b1sum = B23(BB1) + B23(BB11)
+ b00sum = B23(BB00) + B23(BB001)
+ b11sum = B23(BB11) + B23(BB111)
- C(cc0) = XC0(p1, p2, p1p2, m1, m2, m3)
+ call XC0func(C(CC0), para)
- IN(1) = f1*C(cc0) - Bval(bb0,B23) + Bval(bb0,B13)
- IN(2) = f2*C(cc0) - Bval(bb0,B23) + Bval(bb0,B12)
- call SOLVE(in)
- C(cc1) = in(1)
- C(cc2) = in(2)
+ IN(1) = f1*C(CC0) - B23(BB0) + B13(BB0)
+ IN(2) = f2*C(CC0) - B23(BB0) + B12(BB0)
+ call SOLVER(in)
+ C(CC1) = OUT(1)
+ C(CC2) = OUT(2)
- C(cc00) = .5D0*(m1*C(cc0) -
- & .5D0*(f1*C(cc1) + f2*C(cc2) - Bval(bb0,B23) - 1))
+ C(CC00) = .5D0*(m1*C(CC0) -
+ & .5D0*(f1*C(CC1) + f2*C(CC2) - B23(BB0) - finite))
- IN(1) = f1*C(cc1) + bsum - 2*C(cc00)
- IN(2) = f2*C(cc1) + bsum + Bval(bb1,B12)
- call SOLVE(in)
- C(cc11) = in(1)
- C(cc12) = in(2)
+ IN(1) = f1*C(CC1) + bsum - 2*C(CC00)
+ IN(2) = f2*C(CC1) + bsum + B12(BB1)
+ call SOLVER(in)
+ C(CC11) = OUT(1)
+ C(CC12) = OUT(2)
- IN(1) = f1*C(cc2) - Bval(bb1,B23) + Bval(bb1,B13)
- IN(2) = f2*C(cc2) - Bval(bb1,B23) - 2*C(cc00)
- call SOLVE(in)
- C(cc12) = .5D0*(C(cc12) + in(1))
- C(cc22) = in(2)
+ IN(1) = f1*C(CC2) - B23(BB1) + B13(BB1)
+ IN(2) = f2*C(CC2) - B23(BB1) - 2*C(CC00)
+ call SOLVER(in)
+ C(CC12) = .5D0*(C(CC12) + OUT(1))
+ C(CC22) = OUT(2)
- C(cc001) = 1/3D0*(m1*C(cc1) -
- & .5D0*(f1*C(cc11) + f2*C(cc12) + bsum + 1/3D0))
- C(cc002) = 1/3D0*(m1*C(cc2) -
- & .5D0*(f1*C(cc12) + f2*C(cc22) - Bval(bb1,B23) + 1/3D0))
+ C(CC001) = 1/3D0*(m1*C(CC1) -
+ & .5D0*(f1*C(CC11) + f2*C(CC12) + bsum + finite/3D0))
+ C(CC002) = 1/3D0*(m1*C(CC2) -
+ & .5D0*(f1*C(CC12) + f2*C(CC22) - B23(BB1) + finite/3D0))
bsum = bsum + b1sum
- IN(1) = f1*C(cc11) - bsum - 4*C(cc001)
- IN(2) = f2*C(cc11) - bsum + Bval(bb11,B12)
- call SOLVE(in)
- C(cc111) = in(1)
- C(cc112) = in(2)
+ IN(1) = f1*C(CC11) - bsum - 4*C(CC001)
+ IN(2) = f2*C(CC11) - bsum + B12(BB11)
+ call SOLVER(in)
+ C(CC111) = OUT(1)
+ C(CC112) = OUT(2)
- IN(1) = f1*C(cc22) - Bval(bb11,B23) + Bval(bb11,B13)
- IN(2) = f2*C(cc22) - Bval(bb11,B23) - 4*C(cc002)
- call SOLVE(in)
- C(cc122) = in(1)
- C(cc222) = in(2)
+ IN(1) = f1*C(CC22) - B23(BB11) + B13(BB11)
+ IN(2) = f2*C(CC22) - B23(BB11) - 4*C(CC002)
+ call SOLVER(in)
+ C(CC122) = OUT(1)
+ C(CC222) = OUT(2)
- C(cc0000) = 1/4D0*(m1*C(cc00) -
- & .5D0*(f1*C(cc001) + f2*C(cc002) - Bval(bb00,B23) -
- & (m1 + m2 + m3 - .25D0*(p1 + p2 + p1p2))/6D0))
+ C(CC0000) = 1/4D0*(m1*C(CC00) -
+ & .5D0*(f1*C(CC001) + f2*C(CC002) - B23(BB00) -
+ & finite*(m1 + m2 + m3 - .25D0*(p1 + p2 + p1p2))/6D0))
- IN(1) = f1*C(cc001) + b00sum - 2*C(cc0000)
- IN(2) = f2*C(cc001) + b00sum + Bval(bb001,B12)
- call SOLVE(in)
- C(cc0011) = in(1)
- C(cc0012) = in(2)
+ IN(1) = f1*C(CC001) + b00sum - 2*C(CC0000)
+ IN(2) = f2*C(CC001) + b00sum + B12(BB001)
+ call SOLVER(in)
+ C(CC0011) = OUT(1)
+ C(CC0012) = OUT(2)
- IN(1) = f1*C(cc002) - Bval(bb001,B23) + Bval(bb001,B13)
- IN(2) = f2*C(cc002) - Bval(bb001,B23) - 2*C(cc0000)
- call SOLVE(in)
- C(cc0012) = .5D0*(C(cc0012) + in(1))
- C(cc0022) = in(2)
+ IN(1) = f1*C(CC002) - B23(BB001) + B13(BB001)
+ IN(2) = f2*C(CC002) - B23(BB001) - 2*C(CC0000)
+ call SOLVER(in)
+ C(CC0012) = .5D0*(C(CC0012) + OUT(1))
+ C(CC0022) = OUT(2)
bsum = bsum + b1sum + b11sum
- IN(1) = f1*C(cc111) + bsum - 6*C(cc0011)
- IN(2) = f2*C(cc111) + bsum + Bval(bb111,B12)
- call SOLVE(in)
- C(cc1111) = in(1)
- C(cc1112) = in(2)
+ IN(1) = f1*C(CC111) + bsum - 6*C(CC0011)
+ IN(2) = f2*C(CC111) + bsum + B12(BB111)
+ call SOLVER(in)
+ C(CC1111) = OUT(1)
+ C(CC1112) = OUT(2)
- IN(1) = f1*C(cc222) - Bval(bb111,B23) + Bval(bb111,B13)
- IN(2) = f2*C(cc222) - Bval(bb111,B23) - 6*C(cc0022)
- call SOLVE(in)
- C(cc1222) = in(1)
- C(cc2222) = in(2)
+ IN(1) = f1*C(CC222) - B23(BB111) + B13(BB111)
+ IN(2) = f2*C(CC222) - B23(BB111) - 6*C(CC0022)
+ call SOLVER(in)
+ C(CC1222) = OUT(1)
+ C(CC2222) = OUT(2)
- IN(1) = f1*C(cc122) + b11sum - 2*C(cc0022)
- IN(2) = f2*C(cc122) + b11sum - 4*C(cc0012)
- call SOLVE(in)
- C(cc1122) = in(1)
- C(cc1222) = .5D0*(C(cc1222) + in(2))
+ IN(1) = f1*C(CC122) + b11sum - 2*C(CC0022)
+ IN(2) = f2*C(CC122) + b11sum - 4*C(CC0012)
+ call SOLVER(in)
+ C(CC1122) = OUT(1)
+ C(CC1222) = .5D0*(C(CC1222) + OUT(2))
if( dump ) call XDumpCoeff(3, C)
end
diff --git a/Looptools/C/ffcc0.F b/Looptools/C/ffcc0.F
--- a/Looptools/C/ffcc0.F
+++ b/Looptools/C/ffcc0.F
@@ -1,1008 +1,1009 @@
#include "externals.h"
+#include "types.h"
* $Id: ffcc0.f,v 1.2 1996/06/30 19:03:55 gj Exp $
*###[ ffcc0:
subroutine ffcc0(cc0,cpi,ier)
***#[*comment:***********************************************************
* *
* Calculates the threepoint function closely following *
* recipe in 't Hooft & Veltman, NP B(183) 1979. *
* B&D metric is used throughout! *
* *
* p2 | | *
* v | *
* / \ *
* m2/ \m3 *
* p1 / \ p3 *
* -> / m1 \ <- *
* ------------------------ *
* *
* 1 / 1 *
* = ----- \d^4Q---------------------------------------- *
* ipi^2 / [Q^2-m1^2][(Q+p1)^2-m2^2][(Q-p3)^2-m3^2] *
* *
* If the function is infra-red divergent (p1=m2,p3=m3,m1=0 or *
* cyclic) the function is calculated with a user-supplied cutoff *
* lambda in the common block /ffregul/. *
* *
* the parameter nschem in the common block /fflags/ determines *
* which recipe is followed, see ffinit.f *
* *
* Input: cpi(6) (complex) m1^2,m2^3,p1^2,p2^2,p3^2 *
* of divergences, but C0 has none) *
* /ffregul/ lambda (real) IR cutoff *
* /fflags/..nschem(integer) 6: full complex, 0: real, else: *
* some or all logs *
* /fflags/..nwidth(integer) when |p^2-Re(m^2)| < nwidth|Im(m^2) *
* use complex mass *
* ier (integer) number of digits lost so far *
* Output: cc0 (complex) C0, the threepoint function *
* ier (integer) number of digits lost more than (at *
* most) xloss^5 *
* Calls: ffcc0p,ffcb0p *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE COMPLEX cc0,cpi(6)
+ ComplexType cc0,cpi(6)
*
* local variables:
*
integer i,j,init
- DOUBLE COMPLEX cdpipj(6,6)
- DOUBLE PRECISION xpi(6),sprecx
+ ComplexType cdpipj(6,6)
+ RealType xpi(6),sprecx
save init
*
* common blocks:
*
#include "ff.h"
*
* data
*
data init/0/
*
* #] declarations:
* #[ the real case:
*
* take a faster route if all masses are real or nschem < 3
*
if ( nschem .ge. 3 ) then
do 10 i = 1,6
- if ( DIMAG(cpi(i)) .ne. 0 ) goto 30
+ if ( Im(cpi(i)) .ne. 0 ) goto 30
10 continue
elseif ( init .eq. 0 ) then
init = 1
print *,'ffcc0: disregarding complex masses, nschem= ',
+ nschem
endif
do 20 i = 1,6
- xpi(i) = DBLE(cpi(i))
+ xpi(i) = Re(cpi(i))
20 continue
sprecx = precx
precx = precc
call ffxc0(cc0,xpi,ier)
precx = sprecx
if ( ldot ) call ffcod3(cpi)
return
30 continue
*
* #] the real case:
* #[ check input:
*
idsub = 0
*
* #] check input:
* #[ convert input:
do 70 i=1,6
cdpipj(i,i) = 0
do 60 j = 1,6
cdpipj(j,i) = cpi(j) - cpi(i)
60 continue
70 continue
* #] convert input:
* #[ call ffcc0a:
call ffcc0a(cc0,cpi,cdpipj,ier)
* #] call ffcc0a:
*###] ffcc0:
end
*###[ ffcc0r:
subroutine ffcc0r(cc0,cpi,ier)
***#[*comment:***********************************************************
* *
* Tries all 2 permutations of the 3pointfunction *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
integer ier
- DOUBLE COMPLEX cc0,cc0p,cpi(6),cqi(6)
+ ComplexType cc0,cc0p,cpi(6),cqi(6)
integer inew(6,2),irota,ier1,i,j,ialsav
save inew
#include "ff.h"
data inew /1,2,3,4,5,6,
+ 1,3,2,6,5,4/
* #] declarations:
* #[ calculations:
cc0 = 0
ier = 999
ialsav = isgnal
do 30 j = -1,1,2
do 20 irota=1,2
do 10 i=1,6
cqi(inew(i,irota)) = cpi(i)
10 continue
print '(a,i1,a,i2)','---#[ rotation ',irota,': isgnal ',
+ isgnal
ier1 = 0
ner = 0
id = id + 1
isgnal = ialsav
call ffcc0(cc0p,cqi,ier1)
ier1 = ier1 + ner
print '(a,i1,a,i2)','---#] rotation ',irota,': isgnal ',
+ isgnal
print '(a,2g28.16,i3)','c0 = ',cc0p,ier1
if ( ier1 .lt. ier ) then
cc0 = cc0p
ier = ier1
endif
20 continue
ialsav = -ialsav
30 continue
* #] calculations:
*###] ffcc0r:
end
*###[ ffcc0a:
subroutine ffcc0a(cc0,cpi,cdpipj,ier)
***#[*comment:***********************************************************
* *
* see ffcc0 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE COMPLEX cc0,cpi(6),cdpipj(6,6)
+ ComplexType cc0,cpi(6),cdpipj(6,6)
*
* local variables:
*
integer i,j,irota,inew(6,6),i1,i2,i3,initlo,ithres(3),ifound
logical ljust
-* DOUBLE COMPLEX cs,cs1,cs2
- DOUBLE COMPLEX cqi(6),cqiqj(6,6),cqiDqj(6,6)
- DOUBLE PRECISION xqi(6),dqiqj(6,6),qiDqj(6,6),sprec
+* ComplexType cs,cs1,cs2
+ ComplexType cqi(6),cqiqj(6,6),cqiDqj(6,6)
+ RealType xqi(6),dqiqj(6,6),qiDqj(6,6),sprec
save initlo
*
* common blocks:
*
#include "ff.h"
*
* memory
*
integer iermem(memory),ialmem(memory),nscmem(memory),memind,
+ ierini
- DOUBLE COMPLEX cpimem(6,memory)
- DOUBLE COMPLEX cc0mem(memory)
- DOUBLE PRECISION dl2mem(memory)
+ ComplexType cpimem(6,memory)
+ ComplexType cc0mem(memory)
+ RealType dl2mem(memory)
save memind,iermem,ialmem,cpimem,cc0mem
data memind /0/
*
* data
*
data inew /1,2,3,4,5,6,
+ 2,3,1,5,6,4,
+ 3,1,2,6,4,5,
+ 1,3,2,6,5,4,
+ 3,2,1,5,4,6,
+ 2,1,3,4,6,5/
data initlo /0/
*
* #] declarations:
* #[ initialisations:
if ( lmem .and. memind .eq. 0 ) then
do 2 i=1,memory
do 1 j=1,6
cpimem(j,i) = 0
1 continue
ialmem(i) = 0
nscmem(i) = -1
2 continue
endif
idsub = 0
ljust = .FALSE.
* #] initialisations:
* #[ handle special cases:
- if ( DIMAG(cpi(1)).eq.0 .and. DIMAG(cpi(2)).eq.0 .and.
- + DIMAG(cpi(3)).eq.0 ) then
+ if ( Im(cpi(1)).eq.0 .and. Im(cpi(2)).eq.0 .and.
+ + Im(cpi(3)).eq.0 ) then
do 4 i=1,6
- xqi(i) = DBLE(cpi(i))
+ xqi(i) = Re(cpi(i))
do 3 j=1,6
- dqiqj(j,i) = DBLE(cdpipj(j,i))
+ dqiqj(j,i) = Re(cdpipj(j,i))
3 continue
4 continue
sprec = precx
precx = precc
call ffxc0a(cc0,xqi,dqiqj,ier)
precx = sprec
if ( ldot ) call ffcod3(cpi)
return
endif
* goto 5
* No special cases for the moment...
**
* The infrared divergent diagrams cannot be complex
**
* The general case cannot handle cpi=0, pj=pk. These are simple
* though.
**
* if ( cpi(4) .eq. 0 .and. cdpipj(5,6) .eq. 0 .and. cdpipj(1,2)
* + .ne. 0 ) then
* call ffcb0p(cs1,-cpi(5),cpi(1),cpi(3),cdpipj(1,6),
* + cdpipj(3,5),cdpipj(1,3),ier)
* call ffcb0p(cs2,-cpi(5),cpi(2),cpi(3),cdpipj(2,5),
* + cdpipj(3,5),cdpipj(2,3),ier)
* cs = cs1 - cs2
* cc0 = cs/cdpipj(1,2)
* elseif ( cpi(6) .eq. 0 .and. cdpipj(4,5) .eq. 0 .and.
* + cdpipj(3,1) .ne. 0 ) then
* call ffcb0p(cs1,-cpi(4),cpi(3),cpi(2),cdpipj(3,5),
* + cdpipj(2,4),cdpipj(3,2),ier)
* call ffcb0p(cs2,-cpi(4),cpi(1),cpi(2),cdpipj(1,4),
* + cdpipj(2,4),cdpipj(1,2),ier)
* cs = cs1 - cs2
* cc0 = cs/cdpipj(3,1)
* elseif ( cpi(5) .eq. 0 .and. cdpipj(6,4) .eq. 0 .and.
* + cdpipj(2,3) .ne. 0 ) then
* call ffcb0p(cs1,-cpi(6),cpi(2),cpi(1),cdpipj(2,4),
* + cdpipj(1,6),cdpipj(2,1),ier)
* call ffcb0p(cs2,-cpi(6),cpi(3),cpi(1),cdpipj(3,6),
* + cdpipj(1,6),cdpipj(3,1),ier)
* cs = cs1 - cs2
* cc0 = cs/cdpipj(2,3)
* else
* goto 5
* endif
**
* common piece - excuse my style
**
* print *,'ffcc0: WARNING: this algorithm has not yet been tested'
* if ( absc(cs) .lt. xloss*absc(cs1) )
* + call ffwarn(26,ier,absc(cs),absc(cs1))
**
* return
* 5 continue
* #] handle special cases:
* #[ rotate to alpha in (0,1):
call ffcrt3(irota,cqi,cqiqj,cpi,cdpipj,6,2,ier)
* #] rotate to alpha in (0,1):
* #[ look in memory:
ierini = ier+ner
if ( lmem ) then
do 70 i=1,memory
do 60 j=1,6
if ( cqi(j) .ne. cpimem(j,i) ) goto 70
60 continue
if ( ialmem(i) .ne. isgnal .or.
+ nscmem(i) .ne. nschem ) goto 70
* we found an already calculated masscombination ..
* (maybe check differences as well)
cc0 = cc0mem(i)
ier = ier+iermem(i)
if ( ldot ) then
fodel2 = dl2mem(i)
fdel2 = fodel2
* we forgot to recalculate the stored quantities
ljust = .TRUE.
goto 71
endif
return
70 continue
endif
71 continue
* #] look in memory:
* #[ dot products:
call ffcot3(cqiDqj,cqi,cqiqj,6,ier)
*
* save dotproducts for tensor functions if requested
*
if ( ldot ) then
do 75 i=1,6
do 74 j=1,6
cfpij3(j,i) = cqiDqj(inew(i,irota),inew(j,irota))
74 continue
75 continue
if ( irota .gt. 3 ) then
*
* the signs of the s's have been changed
*
do 77 i=1,3
do 76 j=4,6
cfpij3(j,i) = -cfpij3(j,i)
cfpij3(i,j) = -cfpij3(i,j)
76 continue
77 continue
endif
*
* also give the real dotproducts as reals
*
do 79 i=4,6
do 78 j=4,6
- fpij3(j,i) = DBLE(cfpij3(j,i))
+ fpij3(j,i) = Re(cfpij3(j,i))
78 continue
79 continue
endif
if ( ljust ) return
* #] dot products:
* #[ handle poles-only approach:
sprec = precx
precx = precc
if ( nschem.le.6 ) then
if ( initlo.eq.0 ) then
initlo = 1
if ( nschem.eq.1 .or. nschem.eq.2 ) then
print *,'ffcc0a: disregarding all complex masses'
elseif ( nschem.eq.3 ) then
print *,'ffcc0a: undefined nschem=3'
elseif ( nschem.eq.4 ) then
print *,'ffcc0a: using the scheme in which ',
+ 'complex masses are used everywhere when ',
+ 'there is a divergent log'
elseif ( nschem.eq.5 ) then
print *,'ffcc0a: using the scheme in which ',
+ 'complex masses are used everywhere when ',
+ 'there is a divergent or almost divergent log'
elseif ( nschem.eq.6 ) then
print *,'ffcc0a: using the scheme in which ',
+ 'complex masses are used everywhere when ',
+ 'there is a singular log'
elseif ( nschem.eq.7 ) then
print *,'ffcc0a: using complex masses'
endif
if ( nschem.ge.3 ) then
print *,'ffcc0a: switching to complex when ',
+ '|p^2-Re(m^2)| < ',nwidth,'*|Im(m^2)|'
endif
endif
do 9 i=1,6
- xqi(i) = DBLE(cqi(i))
+ xqi(i) = Re(cqi(i))
do 8 j=1,6
- dqiqj(j,i) = DBLE(cqiqj(j,i))
- qiDqj(j,i) = DBLE(cqiDqj(j,i))
+ dqiqj(j,i) = Re(cqiqj(j,i))
+ qiDqj(j,i) = Re(cqiDqj(j,i))
8 continue
9 continue
i1 = 0
ithres(1) = 0
ithres(2) = 0
ithres(3) = 0
if ( nschem.le.2 ) goto 21
*
do 10 i1=1,3
*
* search for a combination of 2 almost on-shell particles
* and a light one
*
i2 = mod(i1,3)+1
i3 = mod(i2,3)+1
call ffbglg(ifound,cqi,cqiqj,cqiDqj,6,i1,i2,i3,i1+3,
+ i3+3)
if ( ifound .ne. 0 ) goto 11
10 continue
i1 = 0
11 continue
if ( nschem.ge.4 .and. i1.ne.0 ) goto 30
if ( nschem.le.3 ) goto 21
*
do 20 i=1,3
i2 = mod(i,3)+1
call ffthre(ithres(i),cqi,cqiqj,6,i,i2,i+3)
20 continue
*
if ( nschem.eq.5 .and. (ithres(1).eq.2 .or.
+ ithres(2).eq.2 .or. ithres(3).eq.2) ) goto 30
if ( nschem.eq.6 .and. (ithres(1).eq.1 .or.
+ ithres(2).eq.1 .or. ithres(3).eq.1) ) goto 30
*
21 continue
*
* The infrared divergent diagrams are calculated in ffxc0i:
*
if ( dqiqj(2,4).eq.0 .and. dqiqj(3,6).eq.0 .and. xqi(1).eq.0
+ .or. dqiqj(3,5).eq.0 .and. dqiqj(1,4).eq.0 .and. xqi(2).eq.0
+ .or. dqiqj(1,6).eq.0 .and. dqiqj(2,5).eq.0 .and. xqi(3).eq.0
+ ) then
call ffxc0i(cc0,xqi,dqiqj,ier)
else
call ffxc0b(cc0,xqi,dqiqj,qiDqj,ier)
endif
* the dotproducts are already set, but I forgot this
if ( ldot ) fodel2 = fdel2
goto 31
*
* the complex case
*
30 continue
precx = sprec
call ffcc0b(cc0,cqi,cqiqj,cqiDqj,ier)
31 continue
*
* #] handle poles-only approach:
* #[ call ffcc0b:
else
precx = sprec
call ffcc0b(cc0,cqi,cqiqj,cqiDqj,ier)
endif
* #] call ffcc0b:
* #[ add to memory:
if ( lmem ) then
memind = memind + 1
if ( memind .gt. memory ) memind = 1
do 200 j=1,6
cpimem(j,memind) = cqi(j)
200 continue
cc0mem(memind) = cc0
iermem(memind) = ier+ner-ierini
ialmem(memind) = isgnal
nscmem(memind) = nschem
dl2mem(memind) = fodel2
endif
* #] add to memory:
*###] ffcc0a:
end
*###[ ffcc0b:
subroutine ffcc0b(cc0,cqi,cqiqj,cqiDqj,ier)
***#[*comment:***********************************************************
* *
* see ffcc0 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
integer nerr
parameter (nerr=6)
*
* arguments
*
- DOUBLE COMPLEX cc0,cqi(6),cqiqj(6,6),cqiDqj(6,6)
+ ComplexType cc0,cqi(6),cqiqj(6,6),cqiDqj(6,6)
integer ier
*
* local variables:
*
integer isoort(8),ipi12(8),i,j,k,ipi12t,ilogi(3),ier0,ieri(nerr)
- DOUBLE COMPLEX cs3(80),cs,cs1,cs2,cslam,c,cel2,cel3,cel2s(3),
+ ComplexType cs3(80),cs,cs1,cs2,cslam,c,cel2,cel3,cel2s(3),
+ cel3mi(3),clogi(3),calph(3),cblph(3),cetalm,cetami(6),
+ csdel2,celpsi(3)
- DOUBLE PRECISION xmax,absc,del2,qiDqj(6,6)
+ RealType xmax,absc,del2,qiDqj(6,6)
*
* common blocks:
*
#include "ff.h"
*
* statement function:
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
*
* #] declarations:
* #[ calculations:
*
* some determinants
*
do 98 i = 1,nerr
ieri(i) = 0
98 continue
do 104 i=4,6
do 103 j=4,6
- qiDqj(j,i) = DBLE(cqiDqj(j,i))
+ qiDqj(j,i) = Re(cqiDqj(j,i))
103 continue
104 continue
call ffdel2(del2,qiDqj,6,4,5,6,1,ier)
fodel2 = del2
fdel2 = fodel2
- cel2 = DCMPLX(DBLE(del2))
+ cel2 = ToComplex(Re(del2))
call ffcel3(cel3,cqiDqj)
- if ( DIMAG(cel3).ne.0 .and.
- + abs(DIMAG(cel3)).lt.precc*abs(DBLE(cel3)) ) then
- cel3 = DBLE(cel3)
+ if ( Im(cel3).ne.0 .and.
+ + abs(Im(cel3)).lt.precc*abs(Re(cel3)) ) then
+ cel3 = Re(cel3)
endif
call ffcl3m(cel3mi,.TRUE.,cel3,cel2,cqi,cqiqj,cqiDqj,6, 4,5,6,
+ 1,3)
do 105 i=1,3
j = i+1
if ( j .eq. 4 ) j = 1
call ffcel2(cel2s(i),cqiDqj,6,i+3,i,j,1,ieri(i))
k = i-1
if ( k .eq. 0 ) k = 3
call ffcl2p(celpsi(i),cqi,cqiqj,cqiDqj,i+3,j+3,k+3,i,j,k,6)
105 continue
- cetalm = cel3*DBLE(1/del2)
+ cetalm = cel3*Re(1/del2)
do 108 i=1,3
- cetami(i) = cel3mi(i)*DBLE(1/del2)
+ cetami(i) = cel3mi(i)*Re(1/del2)
108 continue
- csdel2 = isgnal*DBLE(sqrt(-del2))
+ csdel2 = isgnal*Re(sqrt(-del2))
ier0 = 0
do 99 i=1,nerr
ier0 = max(ier0,ieri(i))
99 continue
ier = ier + ier0
*
* initialize cs3:
*
do 80 i=1,80
cs3(i) = 0
80 continue
do 90 i=1,8
ipi12(i) = 0
90 continue
*
* get alpha,1-alpha
*
call ffcoot(cblph(1),calph(1),cqi(5),-cqiDqj(5,6),cqi(6),csdel2,
+ ier)
call ffcoot(calph(3),cblph(3),cqi(5),-cqiDqj(5,4),cqi(4),csdel2,
+ ier)
cs1 = cblph(1) - chalf
cs2 = calph(1) - chalf
- if ( l4also .and. ( DBLE(calph(1)) .gt. 1 .or. DBLE(calph(1))
+ if ( l4also .and. ( Re(calph(1)) .gt. 1 .or. Re(calph(1))
+ .lt. 0 ) .and. absc(cs1) .lt. absc(cs2) ) then
calph(1) = cblph(1)
calph(3) = cblph(3)
csdel2 = -csdel2
isgnal = -isgnal
endif
cslam = 2*csdel2
*
* and the calculations
*
call ffcc0p(cs3,ipi12,isoort,clogi,ilogi,cqi,cqiqj,cqiDqj,
+ csdel2,cel2s,cetalm,cetami,celpsi,calph,3,ier)
*
* sum'em up:
*
cs = 0
xmax = 0
do 110 i=1,80
cs = cs + cs3(i)
xmax = max(xmax,absc(cs))
110 continue
ipi12t = ipi12(1)
do 120 i=2,8
ipi12t = ipi12t + ipi12(i)
120 continue
- cs = cs + ipi12t*DBLE(pi12)
+ cs = cs + ipi12t*Re(pi12)
*
* check for imaginary part zero (this may have to be dropped)
*
- if ( abs(DIMAG(cs)) .lt. precc*abs(DBLE(cs)) )
- + cs = DCMPLX(DBLE(cs))
+ if ( abs(Im(cs)) .lt. precc*abs(Re(cs)) )
+ + cs = ToComplex(Re(cs))
cc0 = - cs/cslam
* #] calculations:
*###] ffcc0b:
end
*###[ ffcrt3:
subroutine ffcrt3(irota,cqi,cdqiqj,cpi,cdpipj,ns,iflag,ier)
***#[*comment:***********************************************************
* *
* rotates the arrays cpi, cdpipj into cqi,cdqiqj so that *
* cpi(6),cpi(4) suffer the strongest outside cancellations and *
* cpi(6) > cpi(4) if iflag = 1, so that cpi(5) largest and cpi(5) *
* and cpi(6) suffer cancellations if iflag = 2. *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer irota,ns,iflag,ier
- DOUBLE COMPLEX cpi(ns),cdpipj(ns,ns),cqi(ns),cdqiqj(ns,ns)
+ ComplexType cpi(ns),cdpipj(ns,ns),cqi(ns),cdqiqj(ns,ns)
*
* local variables
*
- DOUBLE PRECISION a1,a2,a3,xpimax,absc
- DOUBLE COMPLEX c
+ RealType a1,a2,a3,xpimax,absc
+ ComplexType c
integer i,j,inew(6,6)
save inew
*
* common blocks
*
#include "ff.h"
*
* data
*
data inew /1,2,3,4,5,6,
+ 2,3,1,5,6,4,
+ 3,1,2,6,4,5,
+ 1,3,2,6,5,4,
+ 3,2,1,5,4,6,
+ 2,1,3,4,6,5/
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
*
* #] declarations:
* #[ get largest cancellation:
if ( iflag .eq. 1 ) then
a1 = absc(cdpipj(6,4))/max(absc(cpi(6)+cpi(4)),xclogm)
a2 = absc(cdpipj(5,4))/max(absc(cpi(5)+cpi(4)),xclogm)
a3 = absc(cdpipj(5,6))/max(absc(cpi(6)+cpi(5)),xclogm)
if ( a1 .le. a2 .and. a1 .le. a3 ) then
if ( absc(cpi(6)) .lt. absc(cpi(4)) ) then
irota = 4
else
irota = 1
endif
elseif ( a2 .le. a3 ) then
if ( absc(cpi(4)) .lt. absc(cpi(5)) ) then
irota = 6
else
irota = 3
endif
else
if ( absc(cpi(5)) .lt. absc(cpi(6)) ) then
irota = 5
else
irota = 2
endif
endif
elseif ( iflag .eq. 2 ) then
- xpimax = max(DBLE(cpi(4)),DBLE(cpi(5)),DBLE(cpi(6)))
+ xpimax = max(Re(cpi(4)),Re(cpi(5)),Re(cpi(6)))
if ( xpimax .eq. 0 ) then
- if ( DBLE(cpi(5)) .ne. 0 ) then
+ if ( Re(cpi(5)) .ne. 0 ) then
irota = 1
- elseif ( DBLE(cpi(4)) .ne. 0 ) then
+ elseif ( Re(cpi(4)) .ne. 0 ) then
irota = 2
- elseif ( DBLE(cpi(6)) .ne. 0 ) then
+ elseif ( Re(cpi(6)) .ne. 0 ) then
irota = 3
else
call fferr(40,ier)
return
endif
- elseif ( DBLE(cpi(5)) .eq. xpimax ) then
- if ( DBLE(cpi(4)) .le. DBLE(cpi(6)) ) then
+ elseif ( Re(cpi(5)) .eq. xpimax ) then
+ if ( Re(cpi(4)) .le. Re(cpi(6)) ) then
irota = 1
else
irota = 4
endif
- elseif ( DBLE(cpi(4)) .eq. xpimax ) then
- if ( DBLE(cpi(5)) .ge. DBLE(cpi(6)) ) then
+ elseif ( Re(cpi(4)) .eq. xpimax ) then
+ if ( Re(cpi(5)) .ge. Re(cpi(6)) ) then
irota = 2
else
irota = 5
endif
else
- if ( DBLE(cpi(4)) .ge. DBLE(cpi(6)) ) then
+ if ( Re(cpi(4)) .ge. Re(cpi(6)) ) then
irota = 3
else
irota = 6
endif
endif
else
call fferr(35,ier)
endif
* #] get largest cancellation:
* #[ rotate:
do 20 i=1,6
cqi(inew(i,irota)) = cpi(i)
do 10 j=1,6
cdqiqj(inew(i,irota),inew(j,irota)) = cdpipj(i,j)
10 continue
20 continue
* #] rotate:
*###] ffcrt3:
end
*###[ ffcot3:
subroutine ffcot3(cpiDpj,cpi,cdpipj,ns,ier)
***#[*comment:***********************************************************
* *
* calculate the dotproducts pi.pj with *
* *
* pi = si i1=1,3 *
* pi = p(i-3) i1=4,6 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ns,ier
- DOUBLE COMPLEX cpi(ns),cdpipj(ns,ns),cpiDpj(ns,ns)
+ ComplexType cpi(ns),cdpipj(ns,ns),cpiDpj(ns,ns)
*
* locals
*
integer is1,is2,is3,ip1,ip2,ip3,ier1
- DOUBLE COMPLEX c
- DOUBLE PRECISION absc
+ ComplexType c
+ RealType absc
*
* rest
*
#include "ff.h"
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
*
* #] declarations:
* #[ calculations:
*
ier1 = 0
do 10 is1=1,3
is2 = is1 + 1
if ( is2 .eq. 4 ) is2 = 1
is3 = is2 + 1
if ( is3 .eq. 4 ) is3 = 1
ip1 = is1 + 3
ip2 = is2 + 3
ip3 = is3 + 3
*
* pi.pj, si.sj
*
cpiDpj(is1,is1) = cpi(is1)
cpiDpj(ip1,ip1) = cpi(ip1)
*
* si.s(i+1)
*
if ( absc(cdpipj(is1,ip1)) .le. absc(cdpipj(is2,ip1)) ) then
cpiDpj(is1,is2) = (cdpipj(is1,ip1) + cpi(is2))/2
else
cpiDpj(is1,is2) = (cdpipj(is2,ip1) + cpi(is1))/2
endif
cpiDpj(is2,is1) = cpiDpj(is1,is2)
*
* pi.si
*
if ( absc(cdpipj(is2,is1)) .le. absc(cdpipj(is2,ip1)) ) then
cpiDpj(ip1,is1) = (cdpipj(is2,is1) - cpi(ip1))/2
else
cpiDpj(ip1,is1) = (cdpipj(is2,ip1) - cpi(is1))/2
endif
cpiDpj(is1,ip1) = cpiDpj(ip1,is1)
*
* pi.s(i+1)
*
if ( absc(cdpipj(is2,is1)) .le. absc(cdpipj(ip1,is1)) ) then
cpiDpj(ip1,is2) = (cdpipj(is2,is1) + cpi(ip1))/2
else
cpiDpj(ip1,is2) = (cdpipj(ip1,is1) + cpi(is2))/2
endif
cpiDpj(is2,ip1) = cpiDpj(ip1,is2)
*
* pi.s(i+2)
*
if ( (absc(cdpipj(is2,is1)) .le. absc(cdpipj(ip3,is1)) .and.
+ absc(cdpipj(is2,is1)) .le. absc(cdpipj(is2,ip2))) .or.
+ (absc(cdpipj(ip3,ip2)) .le. absc(cdpipj(ip3,is1)) .and.
+ absc(cdpipj(ip3,ip2)).le.absc(cdpipj(is2,ip2))))then
cpiDpj(ip1,is3) = (cdpipj(ip3,ip2)+cdpipj(is2,is1))/2
else
cpiDpj(ip1,is3) = (cdpipj(ip3,is1)+cdpipj(is2,ip2))/2
endif
cpiDpj(is3,ip1) = cpiDpj(ip1,is3)
*
* pi.p(i+1)
*
if ( absc(cdpipj(ip3,ip1)) .le. absc(cdpipj(ip3,ip2)) ) then
cpiDpj(ip1,ip2) = (cdpipj(ip3,ip1) - cpi(ip2))/2
else
cpiDpj(ip1,ip2) = (cdpipj(ip3,ip2) - cpi(ip1))/2
endif
cpiDpj(ip2,ip1) = cpiDpj(ip1,ip2)
10 continue
ier = ier + ier1
* #] calculations:
*###] ffcot3:
end
*###[ ffbglg:
subroutine ffbglg(ifound,cqi,cqiqj,cqiDqj,ns,i1,i2,i3,ip1,ip3)
***#[*comment:***********************************************************
* *
* Find a configuration which contains big logs, i.e. terms which *
* would be IR divergent but for the finite width effects. *
* We also use the criterium that delta^{s1 s2 s[34]}_{s1 s2 s[34]}*
* should not be 0 when m^2 is shifted over nwidth*Im(m^2) *
* *
* Input: cqi(ns) (complex) masses, p^2 *
* cqiqj(ns,ns) (complex) diff cqi(i)-cqi(j) * *
* cqiDqj(ns,ns) (complex) cqi(i).cqi(j) * *
* ns (integer) size of cqi,cqiqj *
* i1,i2,i3 (integer) combo to be tested *
* small,~onshell,~onshell *
* ip1,ip3 (integer) (i1,i2) and (i1,i3) inx *
* Output: ifound (integer) 0: no divergence, 1: IR *
* -1: del(s,s,s)~0 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ifound,ns,i1,i2,i3,ip1,ip3
- DOUBLE COMPLEX cqi(ns),cqiqj(ns,ns),cqiDqj(ns,ns)
+ ComplexType cqi(ns),cqiqj(ns,ns),cqiDqj(ns,ns)
*
* locals vars
*
integer i123
- DOUBLE PRECISION absc
- DOUBLE COMPLEX cel3,cdm2,cdm3,c
+ RealType absc
+ ComplexType cel3,cdm2,cdm3,c
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
*
* #] declarations:
* #[ work:
ifound = 0
- if ( abs(DBLE(cqi(i1))) .lt. -xloss*(DIMAG(cqi(i2)) +
- + DIMAG(cqi(i3)))
- + .and. abs(DBLE(cqiqj(ip1,i2))) .le. -nwidth*DIMAG(cqi(i2))
- + .and. abs(DBLE(cqiqj(ip3,i3))) .le. -nwidth*DIMAG(cqi(i3))
+ if ( abs(Re(cqi(i1))) .lt. -xloss*(Im(cqi(i2)) +
+ + Im(cqi(i3)))
+ + .and. abs(Re(cqiqj(ip1,i2))) .le. -nwidth*Im(cqi(i2))
+ + .and. abs(Re(cqiqj(ip3,i3))) .le. -nwidth*Im(cqi(i3))
+ ) then
ifound = 1
return
endif
if ( nschem.ge.5 .and. cqi(i1).eq.0 ) then
i123 = 2**i1 + 2**i2 + 2**i3
if ( i123.eq.2**1+2**2+2**3 .or. i123.eq.2**1+2**2+2**4 )
+ then
cel3 = - cqiDqj(i1,i2)**2*cqi(i3)
+ - cqiDqj(i1,i3)**2*cqi(i2)
+ + 2*cqiDqj(i1,i2)*cqiDqj(i1,i3)*cqiDqj(i2,i3)
cdm2 = cqiDqj(i1,i2)*cqiDqj(ip3,i3) +
+ cqiDqj(i1,i3)*cqiDqj(ip1,i3)
cdm3 = -cqiDqj(i1,i2)*cqiDqj(ip3,i2) -
+ cqiDqj(i1,i3)*cqiDqj(ip1,i2)
- if ( 2*absc(cel3) .lt.-nwidth*(absc(cdm2)*DIMAG(cqi(i2))
- + + absc(cdm3)*DIMAG(cqi(i3))) ) then
+ if ( 2*absc(cel3) .lt.-nwidth*(absc(cdm2)*Im(cqi(i2))
+ + + absc(cdm3)*Im(cqi(i3))) ) then
ifound = -1
endif
endif
endif
* #] work:
*###] ffbglg:
end
*###[ ffthre:
subroutine ffthre(ithres,cqi,cqiqj,ns,i1,i2,ip)
***#[*comment:***********************************************************
* *
* look for threshold effects. *
* ithres = 1: 3 heavy masses *
* ithres = 2: 2 masses almost equal and 1 zero *
* *
* Input: cqi(ns) (complex) usual masses,p^2 *
* cqiqj(ns,ns) (complex) cqi(i)-cqi(j) *
* ns (integer) size *
* i1,i2 (integer) position to be tested *
* ip (integer) (i1,i2) index *
* *
* Output: ithres (integer) see above, 0 if nothing *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ithres,ns,i1,i2,ip
- DOUBLE COMPLEX cqi(ns),cqiqj(ns,ns)
+ ComplexType cqi(ns),cqiqj(ns,ns)
*
* local variables
*
integer ier0
- DOUBLE COMPLEX c
- DOUBLE PRECISION absc,xq1,xq2,xq3,dq1q2,dq1q3,dq2q3,xlam,d1,d2,
+ ComplexType c
+ RealType absc,xq1,xq2,xq3,dq1q2,dq1q3,dq2q3,xlam,d1,d2,
+ sprecx
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
*
* #] declarations:
* #[ work:
ithres = 0
- if ( DIMAG(cqi(i1)).eq.0 .and. DIMAG(cqi(i2)).eq.0 .or.
+ if ( Im(cqi(i1)).eq.0 .and. Im(cqi(i2)).eq.0 .or.
+ nschem.le.4 ) return
- if ( DBLE(cqi(i1)).lt.-DIMAG(cqi(i2)) .and.
- + abs(DBLE(cqiqj(ip,i2))).lt.-nwidth*DIMAG(cqi(i2))
- + .or. DBLE(cqi(i2)).lt.-DIMAG(cqi(i1)) .and.
- + abs(DBLE(cqiqj(ip,i1))).lt.-nwidth*DIMAG(cqi(i1)) ) then
+ if ( Re(cqi(i1)).lt.-Im(cqi(i2)) .and.
+ + abs(Re(cqiqj(ip,i2))).lt.-nwidth*Im(cqi(i2))
+ + .or. Re(cqi(i2)).lt.-Im(cqi(i1)) .and.
+ + abs(Re(cqiqj(ip,i1))).lt.-nwidth*Im(cqi(i1)) ) then
ithres = 2
- elseif ( nschem.ge.6 .and. DBLE(cqi(i1)).ne.0 .and.
- + DBLE(cqi(i2)).ne.0 ) then
+ elseif ( nschem.ge.6 .and. Re(cqi(i1)).ne.0 .and.
+ + Re(cqi(i2)).ne.0 ) then
ier0 = 0
- xq1 = DBLE(cqi(i1))
- xq2 = DBLE(cqi(i2))
- xq3 = DBLE(cqi(ip))
- dq1q2 = DBLE(cqiqj(i1,i2))
- dq1q3 = DBLE(cqiqj(i1,ip))
- dq2q3 = DBLE(cqiqj(i2,ip))
+ xq1 = Re(cqi(i1))
+ xq2 = Re(cqi(i2))
+ xq3 = Re(cqi(ip))
+ dq1q2 = Re(cqiqj(i1,i2))
+ dq1q3 = Re(cqiqj(i1,ip))
+ dq2q3 = Re(cqiqj(i2,ip))
sprecx = precx
precx = precc
call ffxlmb(xlam,xq1,xq2,xq3, dq1q2,dq1q3,dq2q3)
precx = sprecx
d1 = absc(cqiqj(i1,ip) - cqi(i2))
d2 = absc(cqiqj(i2,ip) - cqi(i1))
-* if ( d1 .lt. -nwidth*DIMAG(cqi(i1)) .or.
-** + d2 .lt. -nwidth*DIMAG(cqi(i2)) )
+* if ( d1 .lt. -nwidth*Im(cqi(i1)) .or.
+** + d2 .lt. -nwidth*Im(cqi(i2)) )
** + call ffwarn(182,ier0,x1,x1)
- if ( abs(xlam) .lt. -nwidth*(DBLE(d1)*
- + DIMAG(cqi(i1)) + d2*DIMAG(cqi(i2))) ) then
+ if ( abs(xlam) .lt. -nwidth*(Re(d1)*
+ + Im(cqi(i1)) + d2*Im(cqi(i2))) ) then
ithres = 1
endif
endif
* #] work:
*###] ffthre:
end
*###[ ffcod3:
subroutine ffcod3(cpi)
***#[*comment:***********************************************************
* *
* Convert real dorproducts into complex ones, adding the *
* imaginary parts where appropriate. *
* *
* Input: cpi(6) complex m^2, p^2 *
* /ffdots/fpij3(6,6) real p.p real *
* *
* Output: /ffcots/cfpij3(6,6) complex p.p complex *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE COMPLEX cpi(6)
+ ComplexType cpi(6)
*
* local variables
*
integer i,i1,i2,ip
*
* common blocks
*
#include "ff.h"
*
* #] declarations:
* #[ add widths:
*
do 25 i=1,3
ip = i+3
i1 = 1 + mod(i,3)
i2 = 1 + mod(i1,3)
* s.s
cfpij3(i,i) = cpi(i)
- cfpij3(i1,i) = DCMPLX(DBLE(fpij3(i1,i)),
- + (DIMAG(cpi(i1))+DIMAG(cpi(i)))/2)
+ cfpij3(i1,i) = ToComplex(Re(fpij3(i1,i)),
+ + (Im(cpi(i1))+Im(cpi(i)))/2)
cfpij3(i,i1) = cfpij3(i1,i)
* s.p
- cfpij3(i,ip) = DCMPLX(DBLE(fpij3(i,ip)),
- + (DIMAG(cpi(i1))-DIMAG(cpi(i)))/2)
+ cfpij3(i,ip) = ToComplex(Re(fpij3(i,ip)),
+ + (Im(cpi(i1))-Im(cpi(i)))/2)
cfpij3(ip,i) = cfpij3(i,ip)
- cfpij3(i1,ip) = DCMPLX(DBLE(fpij3(i1,ip)),
- + (DIMAG(cpi(i1))-DIMAG(cpi(i)))/2)
+ cfpij3(i1,ip) = ToComplex(Re(fpij3(i1,ip)),
+ + (Im(cpi(i1))-Im(cpi(i)))/2)
cfpij3(ip,i1) = cfpij3(i1,ip)
- cfpij3(i2,ip) = DCMPLX(DBLE(fpij3(i2,ip)),
- + (DIMAG(cpi(i1))-DIMAG(cpi(i)))/2)
+ cfpij3(i2,ip) = ToComplex(Re(fpij3(i2,ip)),
+ + (Im(cpi(i1))-Im(cpi(i)))/2)
cfpij3(ip,i2) = cfpij3(i2,ip)
* p.p
cfpij3(ip,ip) = cpi(ip)
cfpij3(ip,i1+3) = fpij3(ip,i1+3)
cfpij3(i1+3,ip) = cfpij3(ip,i1+3)
25 continue
fodel2 = fdel2
*
* #] add widths:
*###] ffcod3:
end
diff --git a/Looptools/C/ffcc0p.F b/Looptools/C/ffcc0p.F
--- a/Looptools/C/ffcc0p.F
+++ b/Looptools/C/ffcc0p.F
@@ -1,444 +1,445 @@
#include "externals.h"
+#include "types.h"
*###[ ffcc0p:
subroutine ffcc0p(cs3,ipi12,isoort,clogi,ilogi,cpi,cpipj,
+ cpiDpj,sdel2,cel2si,etalam,etami,delpsi,alpha,npoin,ier)
***#[*comment:***********************************************************
* *
* Calculates the threepoint function closely following *
* recipe in 't Hooft & Veltman, NP B(183) 1979. *
* Bjorken and Drell metric is used nowadays! *
* *
* p2 ^ | *
* | | *
* / \ *
* m2/ \m3 *
* p1 / \ p3 *
* <- / m1 \ -> *
* ------------------------ *
* *
* Input: cpi(1-3) (complex) pi squared (,2=untransformed *
* when npoin=4) *
* cpi(4-6) (complex) internal mass squared *
* cpipj(6,6) (complex) cpi(i)-cpi(j) *
* cpiDpj(6,6) (complex) pi(i).pi(j) *
* *
* Output: cs3 (complex)(48) C0, not yet summed. *
* ipi12 (integer)(3) factors pi^2/12, not yet summed *
* cslam (complex) lambda(p1,p2,p3). *
* isoort (integer)(3) indication of he method used *
* ier (integer) 0=ok, 1=inaccurate, 2=error *
* *
* Calls: ffcel2,ffcoot,ffccyz,ffcdwz,ffcs3,ffcs4 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ipi12(8),isoort(8),ilogi(3),npoin,ier
- DOUBLE COMPLEX cs3(80),clogi(3),cpi(6),cpipj(6,6),
+ ComplexType cs3(80),clogi(3),cpi(6),cpipj(6,6),
+ cpiDpj(6,6),sdel2,cel2si(3),etalam,etami(6),
+ delpsi(3),alpha(3)
*
* local variables:
*
integer i,j,k,ip,ierw,jsoort(8),iw,ismall(3)
logical l4,l4pos
- DOUBLE COMPLEX c,cs,zfflog,cs1,cs2,cs4
- DOUBLE COMPLEX cy(4,3),cz(4,3),cw(4,3),cdyz(2,2,3),
+ ComplexType c,cs,zfflog,cs1,cs2,cs4
+ ComplexType cy(4,3),cz(4,3),cw(4,3),cdyz(2,2,3),
+ cdwy(2,2,3),cdwz(2,2,3),cd2yzz(3),cd2yww(3)
- DOUBLE COMPLEX csdl2i(3)
-* DOUBLE COMPLEX cyp,cym,ca,cb,cc,cd
- DOUBLE COMPLEX zfflo1
- DOUBLE PRECISION absc
+ ComplexType csdl2i(3)
+* ComplexType cyp,cym,ca,cb,cc,cd
+ ComplexType zfflo1
+ RealType absc
external zfflo1,zfflog
*
* common blocks:
*
#include "ff.h"
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ get roots etc:
* #[ get z-roots:
if ( npoin .ne. 3 ) then
l4pos = .FALSE.
else
l4pos = l4also
endif
do 10 i=1,3
*
* get roots (y,z)
*
ip = i+3
* first get the roots
j = i+1
if ( j .eq. 4 ) j = 1
csdl2i(i) = sqrt(-cel2si(i))
if ( cpi(ip) .eq. 0 ) then
if ( i .eq. 1 .and. alpha(3) .eq. 0 .or.
+ i .eq. 3 .and. alpha(1) .eq. 0 ) then
isoort(2*i-1) = 0
isoort(2*i) = 0
l4pos = .FALSE.
goto 10
endif
endif
call ffccyz(cy(1,i),cz(1,i),cdyz(1,1,i),cd2yzz(i),i,
+ sdel2,csdl2i(i),etalam,etami,delpsi(i),
+ cpi,cpiDpj,isoort(2*i-1),ier)
10 continue
* #] get z-roots:
* #[ get w-roots:
*
* get w's:
*
ierw = 0
l4 = .FALSE.
if ( isoort(4) .eq. 0 ) then
call fferr(10,ierw)
goto 90
endif
do 70 iw = 1,3,2
if ( .not. l4pos .or. alpha(4-iw) .eq. 0 ) then
jsoort(2*iw-1) = 0
jsoort(2*iw) = 0
l4pos = .FALSE.
else
jsoort(2*iw-1) = -1
jsoort(2*iw) = -1
cd2yww(iw) = -cd2yzz(2)/alpha(4-iw)
do 20 j=1,2
cw(j+iw-1,iw) = cz(j+3-iw,2)/alpha(4-iw)
cw(j+3-iw,iw) = 1 - cw(j+iw-1,iw)
if ( absc(cw(j+3-iw,iw)) .lt. xloss ) then
cs = cz(j+iw-1,2) - alpha(iw)
if ( absc(cs) .lt. xloss*absc(alpha(iw)) ) then
ierw = 1
goto 70
endif
cw(j+3-iw,iw) = cs/alpha(4-iw)
endif
cdwy(j,2,iw) = cdyz(2,j,2)/alpha(4-iw)
do 15 i=1,2
cdwz(j,i,iw) = cw(j,iw) - cz(i,iw)
if ( absc(cdwz(j,i,iw)) .ge. xloss*absc(cw(j,iw)) )
+ goto 14
cdwz(j,i,iw) = cz(i+2,iw) - cw(j+2,iw)
if ( absc(cdwz(j,i,iw)) .ge. xloss*absc(cw(j+2,iw)) )
+ goto 14
cdwz(j,i,iw) = cdwy(j,2,iw) + cdyz(2,i,iw)
if ( absc(cdwz(j,i,iw)) .ge. xloss*absc(cdwy(j,2,iw)) )
+ goto 14
l4 = .TRUE.
call ffcdwz(cdwz(1,1,iw),cz(1,iw),j,i,iw,
+ alpha(1),alpha(3),cpi,cpipj,cpiDpj,csdl2i,
+ sdel2,6,ierw)
14 continue
15 continue
20 continue
endif
70 continue
* #] get w-roots:
* #[ which case:
90 if ( l4 ) then
- if ( DIMAG(alpha(1)) .ne. 0 ) then
+ if ( Im(alpha(1)) .ne. 0 ) then
l4pos = .FALSE.
elseif ( ierw .ge. 1 ) then
l4pos = .FALSE.
else
ier = max(ier,ierw)
endif
endif
* #] which case:
* #] get roots etc:
* #[ logarithms for 4point function:
if ( npoin .eq. 4 ) then
do 95 i = 1,3
ismall(i) = 0
if ( ilogi(i) .ne. -999 ) goto 95
if ( isoort(2*i) .ne. 0 ) then
* maybe add sophisticated factors i*pi later
c = -cdyz(2,1,i)/cdyz(2,2,i)
if ( absc(c-1) .lt. xloss ) then
cs = cd2yzz(i)/cdyz(2,2,i)
clogi(i) = zfflo1(cs,ier)
ilogi(i) = 0
ismall(i) = 1
- elseif ( DBLE(c) .gt. 0 ) then
+ elseif ( Re(c) .gt. 0 ) then
clogi(i) = zfflog(c,0,czero,ier)
ilogi(i) = 0
else
if ( absc(c+1) .lt. xloss ) then
cs = -2*csdl2i(i)/cdyz(2,2,i)/
- + DBLE(cpi(i+3))
+ + Re(cpi(i+3))
clogi(i) = zfflo1(cs,ier)
ismall(i) = -1
else
cs = 0
clogi(i) = zfflog(-c,0,czero,ier)
endif
- if ( DIMAG(c).lt.0 .or. DIMAG(cs).lt.0 ) then
+ if ( Im(c).lt.0 .or. Im(cs).lt.0 ) then
ilogi(i) = -1
- elseif ( DIMAG(c).gt.0 .or. DIMAG(cs).gt.0 ) then
+ elseif ( Im(c).gt.0 .or. Im(cs).gt.0 ) then
ilogi(i) = +1
- elseif ( DBLE(cdyz(2,2,i)) .eq. 0 ) then
- ilogi(i)=-nint(sign(1D0,DBLE(cpi(i+3))))
+ elseif ( Re(cdyz(2,2,i)) .eq. 0 ) then
+ ilogi(i)=-nint(sign(1D0,Re(cpi(i+3))))
ier = ier + 50
print *,'doubtful imaginary part ',ilogi(i)
endif
- if ( abs(DIMAG(c)).lt.precc*absc(c) .and.
- + abs(DIMAG(cs)).lt.precc*absc(cs) ) then
+ if ( abs(Im(c)).lt.precc*absc(c) .and.
+ + abs(Im(cs)).lt.precc*absc(cs) ) then
print *,'ffcc0p: error: imaginary part doubtful'
ier = ier + 50
endif
endif
endif
95 continue
do 96 i=1,3
j = i + 1
if ( j .eq. 4 ) j = 1
if ( abs(ismall(i)+ismall(j)) .eq. 2 .and. absc(clogi(i)+
+ clogi(j)) .lt. xloss*absc(clogi(i)) ) then
* assume that we got here because of complex sqrt(-delta)
- cs1=-2*cI*DIMAG(cy(2,i))*csdl2i(j)/DBLE(cpi(j+3))/
+ cs1=-2*cI*Im(cy(2,i))*csdl2i(j)/Re(cpi(j+3))/
+ (cdyz(2,2,i)*cdyz(2,2,j))
- cs2=-2*cI*DIMAG(cy(2,j))*csdl2i(i)/DBLE(cpi(i+3))/
+ cs2=-2*cI*Im(cy(2,j))*csdl2i(i)/Re(cpi(i+3))/
+ (cdyz(2,2,i)*cdyz(2,2,j))
cs = cs1 + cs2
if ( absc(cs) .lt. xloss*absc(cs1) ) then
k = j+1
if ( k .eq. 4 ) k = 1
cs1 = cpipj(j+3,i+3)*cpi(j)
cs2 = cpiDpj(k+3,j)*cpiDpj(j+3,j)
cs4 = -cpiDpj(k+3,j)*cpiDpj(i+3,j)
cs = cs1 + cs2 + cs4
if ( absc(cs) .lt. xloss*max(absc(cs1),absc(cs2),
+ absc(cs4)) ) then
print *,'ffcc0p: cancellations in delj-deli'
goto 96
endif
- cs1 = cI*DIMAG(cy(2,j))*cs/(csdl2i(i)+csdl2i(j))
+ cs1 = cI*Im(cy(2,j))*cs/(csdl2i(i)+csdl2i(j))
call ffcl2t(cs2,cpiDpj,k+3,j,4,5,6,+1,-1,6)
- cs2 = -cs2*csdl2i(j)/sdel2/DBLE(cpi(j+3))
+ cs2 = -cs2*csdl2i(j)/sdel2/Re(cpi(j+3))
cs = cs1 + cs2
if ( absc(cs) .lt. xloss*absc(cs1) ) then
print *,'ffcc0p: cancellations in extra terms'
goto 96
endif
- cs = -2*cs/DBLE(cpi(i+3))/(cdyz(2,2,i)*
+ cs = -2*cs/Re(cpi(i+3))/(cdyz(2,2,i)*
+ cdyz(2,2,j))
endif
clogi(i) = zfflo1(cs,ier)
clogi(j) = 0
endif
96 continue
endif
* #] logarithms for 4point function:
* #[ integrals:
if ( .not. l4 .or. .not. l4pos ) then
* normal case
do 200 i=1,3
j = 2*i-1
if ( isoort(2*i-1) .ne. 0 ) then
call ffcs3(cs3(20*i-19),ipi12(2*i-1),cy(1,i),
+ cz(1,i),cdyz(1,1,i),cd2yzz(i),cpi,cpiDpj,
+ i,6,isoort(j),ier)
endif
200 continue
isoort(7) = 0
isoort(8) = 0
else
isoort(3) = jsoort(1)
isoort(4) = jsoort(2)
call ffcs4(cs3(1),ipi12(1),cw(1,1),cy(1,1),
+ cz(1,1),cdwy(1,1,1),cdwz(1,1,1),cdyz(1,1,1),
+ cd2yww(1),cd2yzz(1),cpi,cpiDpj,
+ cpi(5)*alpha(3)**2,1,6,isoort(1),ier)
isoort(7) = jsoort(5)
isoort(8) = jsoort(6)
call ffcs4(cs3(41),ipi12(1),cw(1,3),cy(1,3),
+ cz(1,3),cdwy(1,1,3),cdwz(1,1,3),cdyz(1,1,3),
+ cd2yww(3),cd2yzz(3),cpi,cpiDpj,
+ cpi(5)*alpha(1)**2,3,6,isoort(5),ier)
endif
* #] integrals:
*###] ffcc0p:
end
*###[ ffccyz:
subroutine ffccyz(cy,cz,cdyz,cd2yzz,ivert,csdelp,csdels,etalam,
+ etami,delps,xpi,piDpj,isoort,ier)
***#[*comment:***********************************************************
* *
* calculate in a numerically stable way *
* *
* cz(1,2) = (-p(ip1).p(is2) +/- csdelp)/xpi(ip1) *
* cy(1,2) = (-p(ip1).p(is2) +/- sdisc)/xpi(ip1) *
* cdisc = csdels + etaslam*xpi(ip1) *
* *
* cy(3,4) = 1-cy(1,2) *
* cz(3,4) = 1-cz(1,2) *
* cdyz(i,j) = cy(i) - cz(j) *
* *
* Input: ivert (integer) defines the vertex *
* csdelp (complex) sqrt(lam(p1,p2,p3))/2 *
* csdels (complex) sqrt(lam(p,ma,mb))/2 *
* etalam (complex) det(si.sj)/det(pi.pj) *
* etami(6) (complex) si.si - etalam *
* xpi(ns) (complex) standard *
* piDpj(ns,ns) (complex) standard *
* ns (integer) dim of xpi,piDpj *
* *
* Output: cy(4),cz(4),cdyz(4,4) (complex) see above *
* ier (integer) usual error flag *
* *
* Calls: fferr,ffroot *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ivert,ier,isoort(2)
- DOUBLE COMPLEX cy(4),cz(4),cdyz(2,2),cd2yzz,csdelp,csdels
- DOUBLE COMPLEX etalam,etami(6),delps,xpi(6),piDpj(6,6)
+ ComplexType cy(4),cz(4),cdyz(2,2),cd2yzz,csdelp,csdels
+ ComplexType etalam,etami(6),delps,xpi(6),piDpj(6,6)
*
* local variables:
*
integer ip1,is1,is2,is3
- DOUBLE COMPLEX cdisc,c
- DOUBLE PRECISION absc
+ ComplexType cdisc,c
+ RealType absc
*
* common blocks:
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ set up pointers:
is1 = ivert
is2 = ivert+1
if ( is2 .eq. 4 ) is2 = 1
is3 = ivert-1
if ( is3 .eq. 0 ) is3 = 3
ip1 = is1 + 3
* #] set up pointers:
* #[ xk = 0:
if ( xpi(ip1) .eq. 0 ) then
isoort(2) = 0
if ( piDpj(is1,ip1) .eq. 0 ) then
isoort(1) = 0
return
endif
- if ( DIMAG(etalam).ne.0 ) then
+ if ( Im(etalam).ne.0 ) then
isoort(1) = -1
else
isoort(1) = -3
endif
cy(1) = etami(is2) / piDpj(is1,ip1) /2
cy(2) = cy(1)
cy(3) = - etami(is1) / piDpj(is1,ip1) /2
cy(4) = cy(3)
cz(1) = xpi(is2) / piDpj(is1,ip1) /2
cz(2) = cz(1)
cz(3) = - xpi(is1) / piDpj(is1,ip1) /2
cz(4) = cz(3)
cdyz(1,1) = - etalam / piDpj(is1,ip1) /2
cdyz(1,2) = cdyz(1,1)
cdyz(2,1) = cdyz(1,1)
cdyz(2,2) = cdyz(1,1)
return
endif
* #] xk = 0:
* #[ get cy(1,2),cz(1,2):
- if ( DIMAG(etalam).ne.0 ) then
+ if ( Im(etalam).ne.0 ) then
isoort(1) = -1
isoort(2) = -1
else
isoort(1) = -3
isoort(2) = -3
endif
call ffcoot(cz(1),cz(2),xpi(ip1),piDpj(ip1,is2),xpi(is2),
+ csdels,ier)
cdisc = delps/csdelp
call ffcoot(cy(1),cy(2),xpi(ip1),piDpj(ip1,is2),etami(is2),
+ cdisc,ier)
* #] get cy(1,2),cz(1,2):
* #[ get cy(3,4),cz(3,4):
cz(4) = 1-cz(2)
cz(3) = 1-cz(1)
if ( absc(cz(3)) .lt. xloss .or. absc(cz(4)) .lt. xloss ) then
call ffcoot(cz(4),cz(3),xpi(ip1),-piDpj(ip1,is1),
+ xpi(is1),csdels,ier)
endif
* the imaginary part may not be accurate in these cases, take
* some precautions:
if ( cz(3) .eq. 0 ) cz(1) = 1
if ( cz(4) .eq. 0 ) cz(2) = 1
- if ( DIMAG(cz(1)).eq.0 )
- + cz(1) = DCMPLX(DBLE(cz(1)),-DIMAG(cz(3)))
- if ( DIMAG(cz(2)).eq.0 )
- + cz(2) = DCMPLX(DBLE(cz(2)),-DIMAG(cz(4)))
- if ( DIMAG(cz(1)) .gt. 0 .neqv. DIMAG(cz(3)) .lt. 0 ) then
- if ( abs(DBLE(cz(1))) .ge. abs(DBLE(cz(3))) ) then
- cz(1) = DCMPLX(DBLE(cz(1)),-DIMAG(cz(3)))
+ if ( Im(cz(1)).eq.0 )
+ + cz(1) = ToComplex(Re(cz(1)),-Im(cz(3)))
+ if ( Im(cz(2)).eq.0 )
+ + cz(2) = ToComplex(Re(cz(2)),-Im(cz(4)))
+ if ( Im(cz(1)) .gt. 0 .neqv. Im(cz(3)) .lt. 0 ) then
+ if ( abs(Re(cz(1))) .ge. abs(Re(cz(3))) ) then
+ cz(1) = ToComplex(Re(cz(1)),-Im(cz(3)))
else
- cz(3) = DCMPLX(DBLE(cz(3)),-DIMAG(cz(1)))
+ cz(3) = ToComplex(Re(cz(3)),-Im(cz(1)))
endif
endif
- if ( DIMAG(cz(2)) .gt. 0 .neqv. DIMAG(cz(4)) .lt. 0 ) then
- if ( abs(DBLE(cz(2))) .ge. abs(DBLE(cz(4))) ) then
- cz(2) = DCMPLX(DBLE(cz(2)),-DIMAG(cz(4)))
+ if ( Im(cz(2)) .gt. 0 .neqv. Im(cz(4)) .lt. 0 ) then
+ if ( abs(Re(cz(2))) .ge. abs(Re(cz(4))) ) then
+ cz(2) = ToComplex(Re(cz(2)),-Im(cz(4)))
else
- cz(4) = DCMPLX(DBLE(cz(4)),-DIMAG(cz(2)))
+ cz(4) = ToComplex(Re(cz(4)),-Im(cz(2)))
endif
endif
cy(4) = 1-cy(2)
cy(3) = 1-cy(1)
if ( absc(cy(3)) .lt. xloss .or. absc(cy(4)) .lt. xloss ) then
call ffcoot(cy(4),cy(3),xpi(ip1),-piDpj(ip1,is1),
+ etami(is1),cdisc,ier)
endif
if ( cy(3) .eq. 0 ) cy(1) = 1
if ( cy(4) .eq. 0 ) cy(2) = 1
- if ( DIMAG(cy(1)).eq.0 )
- + cy(1) = DCMPLX(DBLE(cy(1)),-DIMAG(cy(3)))
- if ( DIMAG(cy(2)).eq.0 )
- + cy(2) = DCMPLX(DBLE(cy(2)),-DIMAG(cy(4)))
- if ( DIMAG(cy(1)) .gt. 0 .neqv. DIMAG(cy(3)) .lt. 0 ) then
- if ( abs(DBLE(cy(1))) .ge. abs(DBLE(cy(3))) ) then
- cy(1) = DCMPLX(DBLE(cy(1)),-DIMAG(cy(3)))
+ if ( Im(cy(1)).eq.0 )
+ + cy(1) = ToComplex(Re(cy(1)),-Im(cy(3)))
+ if ( Im(cy(2)).eq.0 )
+ + cy(2) = ToComplex(Re(cy(2)),-Im(cy(4)))
+ if ( Im(cy(1)) .gt. 0 .neqv. Im(cy(3)) .lt. 0 ) then
+ if ( abs(Re(cy(1))) .ge. abs(Re(cy(3))) ) then
+ cy(1) = ToComplex(Re(cy(1)),-Im(cy(3)))
else
- cy(3) = DCMPLX(DBLE(cy(3)),-DIMAG(cy(1)))
+ cy(3) = ToComplex(Re(cy(3)),-Im(cy(1)))
endif
endif
- if ( DIMAG(cy(2)) .gt. 0 .neqv. DIMAG(cy(4)) .lt. 0 ) then
- if ( abs(DBLE(cy(2))) .ge. abs(DBLE(cy(4))) ) then
- cy(2) = DCMPLX(DBLE(cy(2)),-DIMAG(cy(4)))
+ if ( Im(cy(2)) .gt. 0 .neqv. Im(cy(4)) .lt. 0 ) then
+ if ( abs(Re(cy(2))) .ge. abs(Re(cy(4))) ) then
+ cy(2) = ToComplex(Re(cy(2)),-Im(cy(4)))
else
- cy(4) = DCMPLX(DBLE(cy(4)),-DIMAG(cy(2)))
+ cy(4) = ToComplex(Re(cy(4)),-Im(cy(2)))
endif
endif
* #] get cy(3,4),cz(3,4):
* #[ get cdyz:
* Note that cdyz(i,j) only exists for i,j=1,2!
if ( absc(cdisc+csdels) .gt. xloss*absc(cdisc) ) then
cdyz(2,1) = ( cdisc + csdels )/xpi(ip1)
cdyz(2,2) = etalam/(xpi(ip1)*cdyz(2,1))
else
cdyz(2,2) = ( cdisc - csdels )/xpi(ip1)
cdyz(2,1) = etalam/(xpi(ip1)*cdyz(2,2))
endif
cdyz(1,1) = -cdyz(2,2)
cdyz(1,2) = -cdyz(2,1)
cd2yzz = 2*cdisc/xpi(ip1)
* #] get cdyz:
*###] ffccyz:
end
diff --git a/Looptools/C/ffcel3.F b/Looptools/C/ffcel3.F
--- a/Looptools/C/ffcel3.F
+++ b/Looptools/C/ffcel3.F
@@ -1,120 +1,121 @@
#include "externals.h"
+#include "types.h"
*###[ ffcel3:
subroutine ffcel3(del3,piDpj)
***#[*comment:***********************************************************
* *
* Calculate del3(piDpj) = det(si.sj) with *
* the momenta as follows: *
* p(1-3) = s(i) *
* p(4-6) = p(i) *
* *
* Input: piDpj(6,6) (real) *
* *
* Output: del3 (real) det(si.sj) *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
- DOUBLE COMPLEX del3,piDpj(6,6)
+ ComplexType del3,piDpj(6,6)
*
* local variables:
*
integer mem,nperm
parameter(mem=10,nperm=16)
integer i,jj(6),iperm(3,nperm),imem,memarr(mem,3),memind,inow
- DOUBLE COMPLEX s(6),del3p,cc
- DOUBLE PRECISION xmax,xmaxp,absc
+ ComplexType s(6),del3p,cc
+ RealType xmax,xmaxp,absc
save iperm,memind,memarr,inow
*
* common blocks:
*
#include "ff.h"
*
* statement function
*
- absc(cc) = abs(DBLE(cc)) + abs(DIMAG(cc))
+ absc(cc) = abs(Re(cc)) + abs(Im(cc))
* #] declarations:
* #[ data:
data memind /0/
data memarr /mem*0,mem*0,mem*1/
data inow /1/
*
* these are all permutations that give a non-zero result with the
* correct sign. This list was generated with getperm3.
*
data iperm/
+ 1,2,3, 1,2,5, 1,6,2, 1,4,3,
+ 1,3,5, 1,4,5, 1,6,4, 1,5,6,
+ 2,4,3, 2,3,6, 2,4,5, 2,6,4,
+ 2,5,6, 3,4,5, 3,6,4, 3,5,6/
* #] data:
* #[ starting point in memory?:
*
* see if we know were to start, if not: go on as last time
*
do 5 i=1,mem
if ( id .eq. memarr(i,1) .and. idsub .eq. memarr(i,2) ) then
inow = memarr(i,3)
goto 6
endif
5 continue
6 continue
* #] starting point in memory?:
* #[ calculations:
imem = inow
del3 = 0
xmax = 0
10 continue
jj(1) = iperm(1,inow)
jj(3) = iperm(2,inow)
jj(5) = iperm(3,inow)
jj(2) = iperm(1,inow)
jj(4) = iperm(2,inow)
jj(6) = iperm(3,inow)
s(1) = +piDpj(jj(1),jj(2))*piDpj(jj(3),jj(4))*piDpj(jj(5),jj(6))
s(2) = +piDpj(jj(1),jj(4))*piDpj(jj(3),jj(6))*piDpj(jj(5),jj(2))
s(3) = +piDpj(jj(1),jj(6))*piDpj(jj(3),jj(2))*piDpj(jj(5),jj(4))
s(4) = -piDpj(jj(1),jj(2))*piDpj(jj(3),jj(6))*piDpj(jj(5),jj(4))
s(5) = -piDpj(jj(1),jj(6))*piDpj(jj(3),jj(4))*piDpj(jj(5),jj(2))
s(6) = -piDpj(jj(1),jj(4))*piDpj(jj(3),jj(2))*piDpj(jj(5),jj(6))
del3p = 0
xmaxp = 0
do 20 i=1,6
del3p = del3p + s(i)
xmaxp = max(xmaxp,absc(s(i)))
20 continue
if ( absc(del3p) .lt. xloss*xmaxp ) then
if ( inow .eq. imem .or. xmaxp .lt. xmax ) then
del3 = del3p
xmax = xmaxp
endif
inow = inow + 1
if ( inow .gt. nperm ) inow = 1
if ( inow .eq. imem ) then
goto 800
endif
goto 10
endif
del3 = del3p
xmax = xmaxp
* #] calculations:
* #[ into memory:
800 continue
memind = memind + 1
if ( memind .gt. mem ) memind = 1
memarr(memind,1) = id
memarr(memind,2) = idsub
memarr(memind,3) = inow
* #] into memory:
*###] ffcel3:
end
diff --git a/Looptools/C/ffdcc0.F b/Looptools/C/ffdcc0.F
deleted file mode 100644
--- a/Looptools/C/ffdcc0.F
+++ /dev/null
@@ -1,317 +0,0 @@
-*###[ ffdcc0:
- subroutine ffdcc0(cs3,ipi12,isoort,clogi,ilogi,xpi,piDpj,
- + xqi,qiDqj,sdel2,del2s,etalam,etami,delpsi,alph,
- + ddel2s,ldel2s,npoin,ier)
-***#[*comment:***********************************************************
-* *
-* Calculates the difference of two threepoint functions *
-* C(3,...a) - C(4,...b) *
-* *
-* Input: xpi(6,3:4) (complex) transformed mi,pi squared in Ci *
-* piDpj(6,6,3:4)(complex) pi(i).pi(j) *
-* xqi(10,10) (complex) transformed mi,pi squared in D *
-* qiDqj(10,10) (complex) qi(i).qi(j) *
-* sdel2 (complex) sqrt(delta_{p_1 p_2}^{p_1 p_2}) *
-* del2s(3,3:4) (complex) delta_{p_i s_i}^{p_i s_i} *
-* etalam(3:4) (complex) delta_{s_1 s_2 s_3}^{s_1 s_2 s_3}
-* /delta_{p_1 p_2}^{p_1 p_2} *
-* etami(6,3:4) (complex) m_i^2 - etalam *
-* ddel2s(2:3) (complex) del2s(i,3) - del2s(i,4) *
-* alph(3) (complex) alph(1)=alpha, alph(3)=1-alpha *
-* *
-* Output: cs3 (complex)(160) C0(3)-C0(4), not yet summed. *
-* ipi12 (integer)(6) factors pi^2/12, not yet summed *
-* slam (complex) lambda(p1,p2,p3). *
-* isoort (integer)(16) indication of he method used *
-* clogi (complex)(6) log(-dyz(2,1,i)/dyz(2,2,i)) *
-* ilogi (integer)(6) factors i*pi in this *
-* ier (integer) 0=ok, 1=inaccurate, 2=error *
-* *
-* Calls: ... *
-* *
-***#]*comment:***********************************************************
-* #[ declarations:
- implicit none
-*
-* arguments:
-*
- integer ipi12(16),isoort(16),ilogi(6),npoin,ier
- logical ldel2s
- DOUBLE COMPLEX cs3(160),clogi(6)
- DOUBLE COMPLEX xqi(10),qiDqj(10,10),
- + xpi(6,3:4),piDpj(6,6,3:4),
- + sdel2,del2s(3,3:4),etalam(3:4),etami(6,3:4),alph(3),
- + ddel2s(2:3),delpsi(3,3:4)
-*
-* local variables:
-*
- integer i,j,k,ip,ii,ifirst,ieri(8)
- DOUBLE COMPLEX c,cc
- DOUBLE COMPLEX sdel2i(3,3:4),s(5),som,zfflo1,
- + y(4,3:4,3),z(4,3:4,3),dyz(2,2,3:4,3),d2yzz(3:4,3),
- + dyzzy(4,3),dsdel2,dyyzz(2,3)
- DOUBLE PRECISION smax,absc,xmax
- DOUBLE COMPLEX zfflog
- external zfflo1,zfflog
-*
-* common blocks:
-*
- include 'ff.h'
-*
-* statement function
-*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
-* #] declarations:
-* #[ get y,z-roots:
- do 20 k=3,4
- do 10 i=1,3
-*
-* get roots (y,z)
-*
- ip = i+3
- sdel2i(i,k) = sqrt(-del2s(i,k))
-* then handle the special case Si = 0
- if ( xpi(ip,k) .eq. 0 ) then
- if ( i .eq. 1 .and. alph(3) .eq. 0 .or.
- + i .eq. 3 .and. alph(1) .eq. 0 ) then
- isoort(2*i-1+8*(k-3)) = 0
- isoort(2*i+8*(k-3)) = 0
- goto 10
- endif
- endif
- call ffccyz(y(1,k,i),z(1,k,i),dyz(1,1,k,i),d2yzz(k,i),i,
- + sdel2,sdel2i(i,k),etalam(k),etami(1,k),delpsi(i,k),
- + xpi(1,k),piDpj(1,1,k),isoort(2*i-1+8*(k-3)),ier)
- 10 continue
- 20 continue
-* #] get y,z-roots:
-* #[ get differences:
-*
-* the only important differences are y4z3-z3y4 and (1-y4)(1-z3)-
-* (1-y3)(1-z4). Note that the errors work in parallel.
-*
- do 199 i=1,8
- ieri(i) = 0
- 199 continue
- if ( isoort(1) .eq. isoort(9) ) then
-* #[ vertices (1):
- som = qiDqj(7,2)/sdel2
-*
-* flag if we have a cancellation
-*
- if ( absc(som) .lt. xloss ) then
- isoort(1) = isoort(1) - 10
- isoort(9) = isoort(9) - 10
- endif
- do 201 k=1,4
- dyzzy(k,1) = som*z(k,3,1)
- if ( k .gt. 2 ) dyzzy(k,1) = -dyzzy(k,1)
- 201 continue
- dyyzz(1,1) = som
- dyyzz(2,1) = som
-* #] vertices (1):
- endif
- if ( isoort(3) .eq. isoort(11) ) then
-* #[ vertices (2):
- ifirst = 0
- do 22 j=1,2
- do 21 k=1,2
- ii = 2*(j-1) + k
- dyzzy(ii,2) = y(2*j,4,2)*z(ii,3,2)-y(2*j,3,2)*z(ii,4,2)
- xmax = absc(y(2*j,4,2)*z(ii,3,2))
- if ( absc(dyzzy(ii,2)) .ge. xmax ) goto 21
- isoort(3) = isoort(3) - 10
- isoort(11) = isoort(11) - 10
- if ( ifirst .eq. 0 ) then
- if ( ddel2s(2) .eq. 0 ) then
- dsdel2 = 0
- else
- dsdel2 = ddel2s(2)/(sdel2i(2,3)+sdel2i(2,4))
- endif
- endif
- if ( ifirst .le. 1 ) then
- if ( j .eq. 1 ) then
- s(1) = xqi(6)*qiDqj(7,4)*qiDqj(5,4)/sdel2
- s(2) = -qiDqj(7,4)*sdel2i(2,3)
- s(3) = +qiDqj(6,4)*dsdel2
- else
- s(1) = xqi(6)*qiDqj(7,2)*qiDqj(5,2)/sdel2
- s(2) = -qiDqj(7,2)*sdel2i(2,3)
- s(3) = +qiDqj(6,2)*dsdel2
- endif
- endif
- if ( ifirst .le. 0 ) then
- ifirst = 2
- s(4) = -qiDqj(5,10)*qiDqj(7,4)*sdel2i(2,3)/sdel2
- s(5) = delpsi(2,3)*dsdel2/sdel2
- endif
- if ( k .eq. 1 ) then
- som = s(1) + s(2) + s(3) + s(4) + s(5)
- else
- som = s(1) - s(2) - s(3) - s(4) - s(5)
- endif
- smax = max(absc(s(1)),absc(s(2)),absc(s(3)),absc(s(4)),
- + absc(s(5)))/DBLE(xqi(6))**2
- if ( smax .lt. xmax ) then
- dyzzy(ii,2) = som*(1/DBLE(xqi(6))**2)
- xmax = smax
- endif
- 21 continue
-*
-* get dyyzz
-*
- if ( ldel2s ) then
- dyyzz(j,2) = dyz(2,j,4,2) - dyz(2,j,3,2)
- xmax = absc(dyz(2,j,4,2))
- if ( absc(dyyzz(j,2)) .ge. xloss*xmax ) goto 22
- 1002 format(a,i1,a,2g22.14,g12.4)
- print *,'ffdcc0: under construction!'
-*
-* (could be copied from real case)
-*
- endif
-*
-* bookkeeping
-*
- ifirst = ifirst - 1
- 22 continue
-* #] vertices (2):
- endif
- if ( isoort(5) .eq. isoort(13) ) then
-* #[ vertices (3):
- ifirst = 0
- do 26 j=1,2
- do 25 k=1,2
- ii = 2*(j-1) + k
- dyzzy(ii,3) = y(2*j,4,3)*z(ii,3,3)-y(2*j,3,3)*z(ii,4,3)
- xmax = absc(y(2*j,4,3)*z(ii,3,3))
- if ( absc(dyzzy(ii,3)) .ge. xmax ) goto 25
- isoort(5) = isoort(5) - 10
- isoort(13) = isoort(13) - 10
- if ( ifirst .eq. 0 ) then
- if ( ddel2s(2) .eq. 0 ) then
- dsdel2 = 0
- else
- dsdel2 = ddel2s(3)/(sdel2i(3,3)+sdel2i(3,4))
- endif
- endif
- if ( ifirst .le. 1 ) then
- if ( j .eq. 1 ) then
- s(1) = xqi(8)*qiDqj(7,1)*qiDqj(5,1)/sdel2
- s(2) = +qiDqj(7,1)*sdel2i(3,3)
- s(3) = +qiDqj(9,1)*dsdel2
- else
- s(1) = xqi(8)*qiDqj(7,4)*qiDqj(5,4)/sdel2
- s(2) = +qiDqj(7,4)*sdel2i(3,3)
- s(3) = +qiDqj(9,4)*dsdel2
- endif
- endif
- if ( ifirst .le. 0 ) then
- ifirst = 2
- s(4) = -qiDqj(5,9)*qiDqj(7,1)*sdel2i(3,3)/sdel2
- s(5) = delpsi(3,3)*dsdel2/sdel2
- endif
- if ( k .eq. 1 ) then
- som = s(1) + s(2) + s(3) + s(4) + s(5)
- else
- som = s(1) - s(2) - s(3) - s(4) - s(5)
- endif
- smax = max(absc(s(1)),absc(s(2)),absc(s(3)),absc(s(4)),
- + absc(s(5)))/DBLE(xqi(8))**2
- if ( smax .lt. xmax ) then
- dyzzy(ii,3) = som*(1/DBLE(xqi(8))**2)
- xmax = smax
- endif
- 25 continue
-*
-* get dyyzz
-*
- if ( ldel2s ) then
- dyyzz(j,3) = dyz(2,j,4,3) - dyz(2,j,3,3)
- xmax = absc(dyz(2,j,4,3))
- if ( absc(dyyzz(j,3)) .ge. xloss*xmax ) goto 24
- print *,'ffdcc0: under construction!'
-*
-* (could be copied from real case)
-*
- endif
-*
-* bookkeeping
-*
- 24 continue
- ifirst = ifirst - 1
- 26 continue
-* #] vertices (3):
- endif
- ier = ier + max(ieri(1),ieri(2),ieri(3),ieri(4),ieri(5),ieri(6),
- + ieri(7),ieri(8))
-* #] get differences:
-* #[ logarithms for 4point function:
- if ( npoin .eq. 4 ) then
- do 96 k = 3,4
- do 95 i = 1,3
- ii = i+3*(k-3)
- if ( ilogi(ii) .ne. -999 ) goto 95
- if ( isoort(2*i+8*(k-3)) .ne. 0 ) then
-* maybe add sophisticated factors i*pi later
- c = -dyz(2,1,i,k)/dyz(2,2,i,k)
- cc = c-1
- if ( absc(cc) .lt. xloss ) then
- s(1) = d2yzz(i,k)/dyz(2,2,i,k)
- clogi(ii) = zfflo1(s(1),ier)
- ilogi(ii) = 0
- elseif ( DBLE(c) .gt. 0 ) then
- clogi(ii) = zfflog(c,0,czero,ier)
- ilogi(ii) = 0
- else
- cc = c+1
- if ( absc(cc) .lt. xloss ) then
- s(1) = -2*sdel2i(i,k)/dyz(2,2,i,k)/
- + DBLE(xpi(i+3,k))
- clogi(ii) = zfflo1(s(1),ier)
- else
- s(1) = 0
- clogi(ii) = zfflog(-c,0,czero,ier)
- endif
- if ( DIMAG(c) .lt. -precc*absc(c) .or. DIMAG(s(1))
- + .lt. -precc*absc(s(1)) ) then
- ilogi(ii) = -1
- elseif ( DIMAG(c) .gt. precc*absc(c) .or.
- + DIMAG(s(1)) .gt. precc*absc(s(1)) ) then
- ilogi(ii) = +1
- elseif ( DBLE(dyz(2,2,i,k)) .eq. 0 ) then
- ilogi(ii) = -nint(sign(1D0,DBLE(xpi(i+3,k))))
- ier = ier + 50
- print *,'doubtful imaginary part ',ilogi(ii)
- else
- call fferr(78,ier)
- print *,'c = ',c
- endif
- endif
- endif
- 95 continue
- 96 continue
- endif
-* #] logarithms for 4point function:
-* #[ integrals:
- do 100 i=1,3
- j = 2*i-1
- if ( isoort(j) .eq. 0 ) then
- if ( isoort(j+8) .ne. 0 ) then
- call ffcs3(cs3(20*i+61),ipi12(j+8),y(1,4,i),
- + z(1,4,i),dyz(1,1,4,i),d2yzz(4,i),
- + xpi(1,4),piDpj(1,1,4),i,6,isoort(j+8),ier)
- endif
- elseif ( isoort(j+8) .eq. 0 ) then
- call ffcs3(cs3(20*i-19),ipi12(j),y(1,3,i),
- + z(1,3,i),dyz(1,1,3,i),d2yzz(3,i),
- + xpi(1,3),piDpj(1,1,3),i,6,isoort(j),ier)
- else
- call ffdcs(cs3(20*i-19),ipi12(j),y(1,3,i),z(1,3,i),
- + dyz(1,1,3,i),d2yzz(3,i),dyzzy(1,i),dyyzz(1,i),
- + xpi,piDpj,i,6,isoort(j),ier)
- endif
- 100 continue
-* #] integrals:
-*###] ffdcc0:
- end
diff --git a/Looptools/C/ffdel3.F b/Looptools/C/ffdel3.F
--- a/Looptools/C/ffdel3.F
+++ b/Looptools/C/ffdel3.F
@@ -1,244 +1,245 @@
#include "externals.h"
+#include "types.h"
*###[ ffdel3:
subroutine ffdel3(del3,piDpj)
***#[*comment:***********************************************************
* *
* Calculate del3(piDpj) = det(si.sj) with *
* the momenta as follows: *
* p(1-3) = s(i) *
* p(4-6) = p(i) *
* *
* Input: xpi(ns) (real) m^2(i),i=1,3; p^2(i-3),i=4,10 *
* piDpj(ns,ns) (real) *
* ns (integer) *
* ier (integer) *
* *
* Output: del3 (real) det(si.sj) *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
- DOUBLE PRECISION del3,piDpj(6,6)
+ RealType del3,piDpj(6,6)
*
* local variables:
*
integer mem,nperm
parameter(mem=10,nperm=16)
integer i,jj(6),iperm(3,nperm),imem,memarr(mem,3),memind,inow
- DOUBLE PRECISION s(6),xmax,del3p,xmaxp
+ RealType s(6),xmax,del3p,xmaxp
save iperm,memind,memarr,inow
*
* common blocks:
*
#include "ff.h"
* #] declarations:
* #[ data:
data memind /0/
data memarr /mem*0,mem*0,mem*1/
data inow /1/
*
* these are all permutations that give a non-zero result with the
* correct sign. This list was generated with getperm3.
*
data iperm/
+ 1,2,3, 1,2,5, 1,6,2, 1,4,3,
+ 1,3,5, 1,4,5, 1,6,4, 1,5,6,
+ 2,4,3, 2,3,6, 2,4,5, 2,6,4,
+ 2,5,6, 3,4,5, 3,6,4, 3,5,6/
* #] data:
* #[ starting point in memory?:
*
* see if we know were to start, if not: go on as last time
*
do 5 i=1,mem
if ( id .eq. memarr(i,1) .and. idsub .eq. memarr(i,2) ) then
inow = memarr(i,3)
goto 6
endif
5 continue
6 continue
* #] starting point in memory?:
* #[ calculations:
imem = inow
del3 = 0
xmax = 0
10 continue
jj(1) = iperm(1,inow)
jj(3) = iperm(2,inow)
jj(5) = iperm(3,inow)
jj(2) = iperm(1,inow)
jj(4) = iperm(2,inow)
jj(6) = iperm(3,inow)
s(1) = +piDpj(jj(1),jj(2))*piDpj(jj(3),jj(4))*piDpj(jj(5),jj(6))
s(2) = +piDpj(jj(1),jj(4))*piDpj(jj(3),jj(6))*piDpj(jj(5),jj(2))
s(3) = +piDpj(jj(1),jj(6))*piDpj(jj(3),jj(2))*piDpj(jj(5),jj(4))
s(4) = -piDpj(jj(1),jj(2))*piDpj(jj(3),jj(6))*piDpj(jj(5),jj(4))
s(5) = -piDpj(jj(1),jj(6))*piDpj(jj(3),jj(4))*piDpj(jj(5),jj(2))
s(6) = -piDpj(jj(1),jj(4))*piDpj(jj(3),jj(2))*piDpj(jj(5),jj(6))
del3p = 0
xmaxp = 0
do 20 i=1,6
del3p = del3p + s(i)
xmaxp = max(xmaxp,abs(s(i)))
20 continue
if ( abs(del3p) .lt. xloss*xmaxp ) then
if ( inow .eq. imem .or. xmaxp .lt. xmax ) then
del3 = del3p
xmax = xmaxp
endif
inow = inow + 1
if ( inow .gt. nperm ) inow = 1
if ( inow .eq. imem ) goto 800
goto 10
endif
del3 = del3p
xmax = xmaxp
* #] calculations:
* #[ into memory:
800 continue
memind = memind + 1
if ( memind .gt. mem ) memind = 1
memarr(memind,1) = id
memarr(memind,2) = idsub
memarr(memind,3) = inow
* #] into memory:
*###] ffdel3:
end
*(##[ ffdl3s:
subroutine ffdl3s(dl3s,piDpj,ii,ns)
***#[*comment:***********************************************************
* *
* Calculate dl3s(piDpj) = det(si.sj) with *
* the momenta indicated by the indices ii(1-6,1), ii(1-6,2) *
* as follows: *
* p(|ii(1,)|-|ii(3,)|) = s(i) *
* p(|ii(4,)|-|ii(6,)|) = p(i) = sgn(ii())*(s(i+1) - s(i)) *
* *
* At this moment (26-apr-1990) only the diagonal is tried *
* *
* Input: xpi(ns) (real) m^2(i),i=1,3; p^2(i-3),i=4,10 *
* piDpj(ns,ns) (real) *
* ii(6,2) (integer) see above *
* ns (integer) *
* ier (integer) *
* *
* Output: dl3s (real) det(si.sj) *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ii(6,2),ns
- DOUBLE PRECISION dl3s,piDpj(ns,ns)
+ RealType dl3s,piDpj(ns,ns)
*
* local variables:
*
integer mem,nperm
parameter(mem=10,nperm=16)
integer i,jj(6),jsgn,iperm(3,nperm),imem,memarr(mem,3),
+ memind,inow
- DOUBLE PRECISION s(6),xmax,dl3sp,xmaxp
+ RealType s(6),xmax,dl3sp,xmaxp
save iperm,memind,memarr,inow
*
* common blocks:
*
#include "ff.h"
* #] declarations:
* #[ data:
data memind /0/
data memarr /mem*0,mem*0,mem*1/
data inow /1/
*
* these are all permutations that give a non-zero result with the
* correct sign. This list was generated with getperm3.
*
data iperm/
+ 1,2,3, 1,2,5, 1,6,2, 1,4,3,
+ 1,3,5, 1,4,5, 1,6,4, 1,5,6,
+ 2,4,3, 2,3,6, 2,4,5, 2,6,4,
+ 2,5,6, 3,4,5, 3,6,4, 3,5,6/
* #] data:
* #[ starting point in memory?:
*
* see if we know were to start, if not: go on as last time
*
do 5 i=1,mem
if ( id .eq. memarr(i,1) .and. idsub .eq. memarr(i,2) ) then
inow = memarr(i,3)
goto 6
endif
5 continue
6 continue
* #] starting point in memory?:
* #[ calculations:
imem = inow
dl3s = 0
xmax = 0
10 continue
jj(1) = abs(ii(iperm(1,inow),1))
jj(3) = abs(ii(iperm(2,inow),1))
jj(5) = abs(ii(iperm(3,inow),1))
jj(2) = abs(ii(iperm(1,inow),2))
jj(4) = abs(ii(iperm(2,inow),2))
jj(6) = abs(ii(iperm(3,inow),2))
jsgn = sign(1,ii(iperm(1,inow),1))
+ *sign(1,ii(iperm(2,inow),1))
+ *sign(1,ii(iperm(3,inow),1))
+ *sign(1,ii(iperm(1,inow),2))
+ *sign(1,ii(iperm(2,inow),2))
+ *sign(1,ii(iperm(3,inow),2))
s(1) = +piDpj(jj(1),jj(2))*piDpj(jj(3),jj(4))*piDpj(jj(5),jj(6))
s(2) = +piDpj(jj(1),jj(4))*piDpj(jj(3),jj(6))*piDpj(jj(5),jj(2))
s(3) = +piDpj(jj(1),jj(6))*piDpj(jj(3),jj(2))*piDpj(jj(5),jj(4))
s(4) = -piDpj(jj(1),jj(2))*piDpj(jj(3),jj(6))*piDpj(jj(5),jj(4))
s(5) = -piDpj(jj(1),jj(6))*piDpj(jj(3),jj(4))*piDpj(jj(5),jj(2))
s(6) = -piDpj(jj(1),jj(4))*piDpj(jj(3),jj(2))*piDpj(jj(5),jj(6))
dl3sp = 0
xmaxp = 0
do 20 i=1,6
dl3sp = dl3sp + s(i)
xmaxp = max(xmaxp,abs(s(i)))
20 continue
if ( abs(dl3sp) .lt. xloss*xmaxp ) then
if ( inow .eq. imem .or. xmaxp .lt. xmax ) then
dl3s = jsgn*dl3sp
xmax = xmaxp
endif
inow = inow + 1
if ( inow .gt. nperm ) inow = 1
if ( inow .eq. imem ) goto 800
goto 10
endif
dl3s = jsgn*dl3sp
xmax = xmaxp
* #] calculations:
* #[ into memory:
800 continue
memind = memind + 1
if ( memind .gt. mem ) memind = 1
memarr(memind,1) = id
memarr(memind,2) = idsub
memarr(memind,3) = inow
* #] into memory:
*)##] ffdl3s:
end
diff --git a/Looptools/C/ffdxc0.F b/Looptools/C/ffdxc0.F
--- a/Looptools/C/ffdxc0.F
+++ b/Looptools/C/ffdxc0.F
@@ -1,817 +1,818 @@
#include "externals.h"
+#include "types.h"
*###[ ffdxc0:
subroutine ffdxc0(cs3,ipi12,isoort,clogi,ilogi,xpi,dpipj,piDpj,
+ xqi,qiDqj,sdel2,del2s,etalam,etami,delpsi,alph,
+ ddel2s,ldel2s,npoin,ier)
***#[*comment:***********************************************************
* *
* Calculates the difference of two threepoint functions *
* C(3,...a) - C(4,...b) *
* For this we not only calculate the roots of the three-point *
* function y,z(1-4,3-4,1-3) but also the combinations *
* *
* yzzy = y(,4,)*z(,3,) - z(,4,)*y(,3,) *
* and *
* yyzz = y(,4,) - z(,4,) - y(,3,) + z(,3,) *
* *
* This is done explicitly for most special cases, so a lot of *
* lines of code result. This may be shortened with a smart use *
* of indices, however, it is readable now. *
* *
* Input: xpi(6,3:4) (real) transformed mi,pi squared in Ci *
* dpipj(6,6,3:4) (real) xpi(i)-xpi(j) *
* piDpj(6,6,3:4) (real) pi(i).pi(j) *
* xqi(10,10) (real) transformed mi,pi squared in D *
* qiDqj(10,10) (real) qi(i).qi(j) *
* sdel2 (real) sqrt(delta_{p_1 p_2}^{p_1 p_2}) *
* del2s(3,3:4) (real) delta_{p_i s_i}^{p_i s_i} *
* etalam(3:4) (real) delta_{s_1 s_2 s_3}^{s_1 s_2 s_3}
* /delta_{p_1 p_2}^{p_1 p_2} *
* etami(6,3:4) (real) m_i^2 - etalam *
* ddel2s(2:3) (real) del2s(i,3) - del2s(i,4) *
* alph(3) (real) alph(1)=alpha, alph(3)=1-alpha *
* ldel2s (logical) indicates yes/no limit del2s->0 *
* *
* Output: cs3 (complex)(160) C0(3)-C0(4), not yet summed. *
* ipi12 (integer)(6) factors pi^2/12, not yet summed *
* slam (complex) lambda(p1,p2,p3). *
* isoort (integer)(16) indication of he method used *
* clogi (complex)(6) log(-dyz(2,1,i)/dyz(2,2,i)) *
* ilogi (integer)(6) factors i*pi in this *
* ier (integer) 0=ok, 1=inaccurate, 2=error *
* *
* Calls: ... *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ipi12(16),isoort(16),ilogi(6),npoin,ier
logical ldel2s
- DOUBLE COMPLEX cs3(160),clogi(6)
- DOUBLE PRECISION xqi(10),qiDqj(10,10),
+ ComplexType cs3(160),clogi(6)
+ RealType xqi(10),qiDqj(10,10),
+ xpi(6,3:4),dpipj(6,6,3:4),piDpj(6,6,3:4),
+ sdel2,del2s(3,3:4),etalam(3:4),etami(6,3:4),alph(3),
+ ddel2s(2:3),delpsi(3,3:4)
*
* local variables:
*
integer i,j,k,l,ip,ier0,ii,ifirst,ieri(12),idone(6)
logical lcompl
- DOUBLE COMPLEX c,csom,cs(5),csdeli(3,3:4),csdel2,
+ ComplexType c,csom,cs(5),csdeli(3,3:4),csdel2,
+ cy(4,3:4,3),cz(4,3:4,3),cdyz(2,2,3:4,3),cd2yzz(3:4,3),
+ cpi(6,3:4),cpiDpj(6,6,3:4),cdyzzy(4,3),cdyyzz(2,3)
- DOUBLE PRECISION sdel2i(3,3:4),s(5),som,smax,absc,dfflo1,
+ RealType sdel2i(3,3:4),s(5),som,smax,absc,dfflo1,
+ y(4,3:4,3),z(4,3:4,3),dyz(2,2,3:4,3),d2yzz(3:4,3),
+ dy2z(4,3:4,3),dyzzy(4,3),dsdel2,xmax
- DOUBLE COMPLEX zxfflg,zfflo1
+ ComplexType zxfflg,zfflo1
external dfflo1,zxfflg,zfflo1
*
* common blocks:
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ get y,z-roots:
lcompl = .FALSE.
do 20 k=3,4
do 10 i=1,3
*
* get roots (y,z) and flag what to do: 0=nothing, 1=normal,
* -1=complex
*
ip = i+3
* first get the roots
if ( del2s(i,k) .le. 0 ) then
* real case
sdel2i(i,k) = sqrt(-del2s(i,k))
* then handle the special case Si = 0
if ( xpi(ip,k) .eq. 0 ) then
if ( i .eq. 1 .and. alph(3) .eq. 0 .or.
+ i .eq. 3 .and. alph(1) .eq. 0 ) then
isoort(2*i-1+8*(k-3)) = 0
isoort(2*i+8*(k-3)) = 0
goto 10
endif
endif
call ffxxyz(y(1,k,i),z(1,k,i),dyz(1,1,k,i),d2yzz(k,i),
+ dy2z(1,k,i),i,sdel2,sdel2i(i,k),etalam(k),etami(1,k),
+ delpsi(i,k),xpi(1,k),dpipj(1,1,k),piDpj(1,1,k),
+ isoort(2*i-1+8*(k-3)),ldel2s,6,ier)
else
* complex case
sdel2i(i,k) = sqrt(del2s(i,k))
- csdeli(i,k) = DCMPLX(0D0,sdel2i(i,k))
+ csdeli(i,k) = ToComplex(0D0,sdel2i(i,k))
lcompl = .TRUE.
call ffcxyz(cy(1,k,i),cz(1,k,i),cdyz(1,1,k,i),cd2yzz(k,i),i,
+ sdel2,sdel2i(i,k),etami(1,k),delpsi(i,k),xpi(
+ 1,k),piDpj(1,1,k),isoort(2*i-1+8*(k-3)),ldel2s,6,ier)
endif
10 continue
20 continue
* #] get y,z-roots:
* #[ convert to complex if necessary:
do 60 i=2,3
l = 2*i-1
if ( isoort(l).gt.0 .and. isoort(l+8).lt.0 ) then
k = 3
* we get -5, -105 if they have equal roots, isoort=+2
* -6, -106 if they have unequal roots, isoort=+1
if ( .not.ldel2s ) then
isoort(l) = isoort(l)-7
isoort(l+1) = isoort(l+1)-7
else
isoort(l) = isoort(l)-207
isoort(l+1) = isoort(l+1)-207
endif
elseif ( isoort(l).lt.0 .and. isoort(l+8).gt.0 ) then
k = 4
if ( .not.ldel2s ) then
isoort(l+8) = isoort(l+8)-7
isoort(l+9) = isoort(l+9)-7
else
isoort(l+8) = isoort(l+8)-207
isoort(l+9) = isoort(l+9)-207
endif
else
k = 0
endif
if ( k .ne. 0 ) then
do 30 j=1,4
cy(j,k,i) = y(j,k,i)
cz(j,k,i) = z(j,k,i)
30 continue
do 50 j=1,2
do 40 l=1,2
cdyz(l,j,k,i) = dyz(l,j,k,i)
40 continue
50 continue
cd2yzz(k,i) = d2yzz(k,i)
csdeli(i,k) = sdel2i(i,k)
endif
60 continue
* #] convert to complex if necessary:
* #[ get differences:
*
* the only important differences are y4z3-z3y4 and (1-y4)(1-z3)-
* (1-y3)(1-z4)
*
do 100 i=1,12
ieri(i) = 0
100 continue
* #[ vertices (1):
som = qiDqj(7,2)/sdel2
if ( isoort(1) .ge. 0 ) then
* Note that the isoorts are equal as the vertex is equal.
*
* flag if we have a cancellation
*
if ( abs(som) .lt. xloss ) then
isoort(1) = isoort(1) + 10
isoort(9) = isoort(9) + 10
endif
do 110 k=1,4
dyzzy(k,1) = som*z(k,3,1)
if ( k .gt. 2 ) dyzzy(k,1) = -dyzzy(k,1)
110 continue
else
if ( abs(som) .lt. xloss ) then
isoort(1) = isoort(1) - 10
isoort(9) = isoort(9) - 10
endif
do 120 k=1,4
- cdyzzy(k,1) = DBLE(som)*cz(k,3,1)
+ cdyzzy(k,1) = Re(som)*cz(k,3,1)
if ( k .gt. 2 ) cdyzzy(k,1) = -cdyzzy(k,1)
120 continue
cdyyzz(1,1) = som
cdyyzz(2,1) = som
endif
* #] vertices (1):
* #[ vertices (2):
if ( isoort(3) .ge. 0 ) then
* #[ real case: (note that this implies isoort(11)>0)
ifirst = 0
do 150 j=1,2
do 140 k=1,2
ii = 2*(j-1) + k
dyzzy(ii,2) = y(2*j,4,2)*z(ii,3,2)-y(2*j,3,2)*z(ii,4,2)
xmax = abs(y(2*j,4,2)*z(ii,3,2))
if ( abs(dyzzy(ii,2)) .ge. xmax ) goto 140
isoort(3) = isoort(3) + 10
isoort(11) = isoort(11) + 10
if ( ldel2s ) then
print *,'ffdxc0: not ready for del2s=0, real case'
goto 130
endif
if ( ifirst .le. 0 ) then
if ( ddel2s(2) .eq. 0 ) then
dsdel2 = 0
else
dsdel2 = ddel2s(2)/(sdel2i(2,3)+sdel2i(2,4))
endif
endif
if ( ifirst .le. 1 ) then
if ( j .eq. 1 ) then
s(1) = xqi(6)*qiDqj(7,4)*qiDqj(5,4)/sdel2
s(2) = -qiDqj(7,4)*sdel2i(2,3)
s(3) = +qiDqj(6,4)*dsdel2
else
s(1) = xqi(6)*qiDqj(7,2)*qiDqj(5,2)/sdel2
s(2) = -qiDqj(7,2)*sdel2i(2,3)
s(3) = +qiDqj(6,2)*dsdel2
endif
endif
if ( ifirst .le. 0 ) then
ifirst = 2
s(4) = -qiDqj(5,10)*qiDqj(7,4)*sdel2i(2,3)/sdel2
s(5) = delpsi(2,3)*dsdel2/sdel2
endif
if ( k .eq. 1 ) then
som = s(1) + s(2) + s(3) + s(4) + s(5)
else
som = s(1) - s(2) - s(3) - s(4) - s(5)
endif
smax = max(abs(s(1)),abs(s(2)),abs(s(3)),abs(s(4)),
+ abs(s(5)))/xqi(6)**2
if ( smax .lt. xmax ) then
dyzzy(ii,2) = som/xqi(6)**2
xmax = smax
endif
130 continue
140 continue
ifirst = ifirst - 1
150 continue
* #] real case:
else
* #[ complex case:
ifirst = 0
do 180 j=1,2
do 170 k=1,2
ii = 2*(j-1) + k
cdyzzy(ii,2) = cy(2*j,4,2)*cz(ii,3,2)-cy(2*j,3,2)*
+ cz(ii,4,2)
xmax = absc(cy(2*j,4,2)*cz(ii,3,2))
if ( absc(cdyzzy(ii,2)) .ge. xmax ) goto 170
isoort(3) = isoort(3) - 10
isoort(11) = isoort(11) - 10
if ( ldel2s ) then
ip = 3
else
ip = 6
endif
if ( mod(isoort(3),10).ne.0 .or. mod(isoort(11),10).ne.0
+ ) then
*
* one of the roots is really real
*
if ( ifirst .le. 0 ) then
- csdel2=DBLE(ddel2s(2))/(csdeli(2,3)+csdeli(2,4))
+ csdel2=Re(ddel2s(2))/(csdeli(2,3)+csdeli(2,4))
endif
if ( ifirst .le. 1 ) then
if ( j .eq. 1 .neqv. ldel2s ) then
if ( .not.ldel2s ) then
cs(1)=xqi(6)*qiDqj(7,4)*qiDqj(5,4)/sdel2
- cs(2) = -DBLE(qiDqj(7,4))*csdeli(2,3)
- cs(3) = +DBLE(qiDqj(6,4))*csdel2
+ cs(2) = -Re(qiDqj(7,4))*csdeli(2,3)
+ cs(3) = +Re(qiDqj(6,4))*csdel2
else
cs(1)=-xqi(3)*qiDqj(5,10)*qiDqj(7,2)/
+ sdel2
- cs(2) = -DBLE(qiDqj(7,2))*csdeli(2,3)
- cs(3) = -DBLE(qiDqj(6,3))*csdel2
+ cs(2) = -Re(qiDqj(7,2))*csdeli(2,3)
+ cs(3) = -Re(qiDqj(6,3))*csdel2
endif
else
cs(1) = xqi(ip)*qiDqj(7,2)*qiDqj(5,2)/sdel2
- cs(2) = -DBLE(qiDqj(7,2))*csdeli(2,3)
- cs(3) = +DBLE(qiDqj(ip,2))*csdel2
+ cs(2) = -Re(qiDqj(7,2))*csdeli(2,3)
+ cs(3) = +Re(qiDqj(ip,2))*csdel2
endif
endif
if ( ifirst .le. 0 ) then
ifirst = 2
if ( .not.ldel2s ) then
- cs(4) = -DBLE(qiDqj(5,10)*qiDqj(7,4)/sdel2)*
+ cs(4) = -Re(qiDqj(5,10)*qiDqj(7,4)/sdel2)*
+ csdeli(2,3)
else
- cs(4) = -DBLE(qiDqj(5,3)*qiDqj(7,2)/sdel2)*
+ cs(4) = -Re(qiDqj(5,3)*qiDqj(7,2)/sdel2)*
+ csdeli(2,3)
endif
- cs(5) = DBLE(delpsi(2,3)/sdel2)*csdel2
+ cs(5) = Re(delpsi(2,3)/sdel2)*csdel2
endif
else
*
* both roots are complex
*
if ( ifirst .eq. 0 ) then
dsdel2 = -ddel2s(2)/(sdel2i(2,3)+sdel2i(2,4))
- csdel2 = DCMPLX(0D0,dsdel2)
+ csdel2 = ToComplex(0D0,dsdel2)
endif
if ( ifirst .le. 1 ) then
if ( j .eq. 1 .neqv. ldel2s ) then
if ( .not.ldel2s ) then
cs(1)=xqi(6)*qiDqj(7,4)*qiDqj(5,4)/sdel2
- cs(2)=-DCMPLX(0D0,qiDqj(7,4)*sdel2i(2,3))
- cs(3)=+DCMPLX(0D0,qiDqj(6,3)*dsdel2)
+ cs(2)=-ToComplex(0D0,qiDqj(7,4)*sdel2i(2,3))
+ cs(3)=+ToComplex(0D0,qiDqj(6,3)*dsdel2)
else
cs(1)=-xqi(3)*qiDqj(5,10)*qiDqj(7,2)/
+ sdel2
- cs(2)=-DCMPLX(0D0,qiDqj(7,2)*sdel2i(2,3))
- cs(3)=-DCMPLX(0D0,qiDqj(6,3)*dsdel2)
+ cs(2)=-ToComplex(0D0,qiDqj(7,2)*sdel2i(2,3))
+ cs(3)=-ToComplex(0D0,qiDqj(6,3)*dsdel2)
endif
else
cs(1) = xqi(ip)*qiDqj(7,2)*qiDqj(5,2)/sdel2
- cs(2) = -DCMPLX(0D0,qiDqj(7,2)*sdel2i(2,3))
- cs(3) = +DCMPLX(0D0,qiDqj(ip,2)*dsdel2)
+ cs(2) = -ToComplex(0D0,qiDqj(7,2)*sdel2i(2,3))
+ cs(3) = +ToComplex(0D0,qiDqj(ip,2)*dsdel2)
endif
endif
if ( ifirst .eq. 0 ) then
ifirst = 2
if ( .not.ldel2s ) then
- cs(4) = -DCMPLX(0D0,qiDqj(5,10)*qiDqj(7,4)*
+ cs(4) = -ToComplex(0D0,qiDqj(5,10)*qiDqj(7,4)*
+ sdel2i(2,3)/sdel2)
else
- cs(4) = -DCMPLX(0D0,qiDqj(5,3)*qiDqj(7,2)*
+ cs(4) = -ToComplex(0D0,qiDqj(5,3)*qiDqj(7,2)*
+ sdel2i(2,3)/sdel2)
endif
- cs(5) = DCMPLX(0D0,delpsi(2,3)*dsdel2/sdel2)
+ cs(5) = ToComplex(0D0,delpsi(2,3)*dsdel2/sdel2)
endif
endif
if ( k .eq. 1 ) then
csom = cs(1) + cs(2) + cs(3) + cs(4) + cs(5)
else
csom = cs(1) - cs(2) - cs(3) - cs(4) - cs(5)
endif
smax = max(absc(cs(1)),absc(cs(2)),absc(cs(3)),
+ absc(cs(4)),absc(cs(5)))/xqi(ip)**2
if ( smax .lt. xmax ) then
- cdyzzy(ii,2) = csom/DBLE(xqi(ip))**2
+ cdyzzy(ii,2) = csom/Re(xqi(ip))**2
xmax = smax
endif
170 continue
*
* get cdyyzz
*
if ( ldel2s ) then
cdyyzz(j,2) = cdyz(2,j,4,2) - cdyz(2,j,3,2)
xmax = absc(cdyz(2,j,4,2))
if ( absc(cdyyzz(j,2)) .ge. xloss*xmax ) goto 175
if ( ifirst .le. 0 ) then
if ( mod(isoort( 3),10).ne.0 .or.
+ mod(isoort(11),10).ne.0 ) then
- csdel2=DBLE(ddel2s(2))/(csdeli(2,3)+csdeli(2,4))
+ csdel2=Re(ddel2s(2))/(csdeli(2,3)+csdeli(2,4))
else
dsdel2 = -ddel2s(2)/(sdel2i(2,3)+sdel2i(2,4))
- csdel2 = DCMPLX(0D0,dsdel2)
+ csdel2 = ToComplex(0D0,dsdel2)
endif
endif
- cs(2) = csdel2/DBLE(xqi(3))
+ cs(2) = csdel2/Re(xqi(3))
cs(1) = qiDqj(5,3)*qiDqj(7,2)/(sdel2*xqi(3))
if ( j .eq. 1 ) then
csom = cs(1) + cs(2)
else
csom = cs(1) - cs(2)
endif
smax = absc(cs(1))
if ( smax .lt. xmax ) then
cdyyzz(j,2) = csom
xmax = smax
endif
endif
*
* bookkeeping
*
175 continue
ifirst = ifirst - 1
180 continue
* #] complex case:
endif
* #] vertices (2):
* #[ vertices (3):
if ( isoort(5) .ge. 0 ) then
* #[ real case: (note that this implies isoort(15)>0)
ifirst = 0
do 210 j=1,2
do 200 k=1,2
ii = 2*(j-1) + k
dyzzy(ii,3) = y(2*j,4,3)*z(ii,3,3)-y(2*j,3,3)*z(ii,4,3)
xmax = abs(y(2*j,4,3)*z(ii,3,3))
if ( abs(dyzzy(ii,3)) .ge. xmax ) goto 200
isoort(5) = isoort(5) + 10
isoort(13) = isoort(13) + 10
if ( ldel2s ) then
print *,'ffdxc0: not ready for del2s=0, real case'
goto 190
endif
if ( ifirst .le. 0 ) then
if ( ddel2s(2) .eq. 0 ) then
dsdel2 = 0
else
dsdel2 = ddel2s(3)/(sdel2i(3,3)+sdel2i(3,4))
endif
endif
if ( ifirst .le. 1 ) then
if ( j .eq. 1 ) then
s(1) = xqi(8)*qiDqj(7,1)*qiDqj(5,1)/sdel2
s(2) = +qiDqj(7,1)*sdel2i(3,3)
s(3) = +qiDqj(9,1)*dsdel2
else
s(1) = xqi(8)*qiDqj(7,4)*qiDqj(5,4)/sdel2
s(2) = +qiDqj(7,4)*sdel2i(3,3)
s(3) = +qiDqj(9,4)*dsdel2
endif
endif
if ( ifirst .le. 0 ) then
ifirst = 2
s(4) = -qiDqj(5,9)*qiDqj(7,1)*sdel2i(3,3)/sdel2
s(5) = delpsi(3,3)*dsdel2/sdel2
endif
if ( k .eq. 1 ) then
som = s(1) + s(2) + s(3) + s(4) + s(5)
else
som = s(1) - s(2) - s(3) - s(4) - s(5)
endif
smax = max(abs(s(1)),abs(s(2)),abs(s(3)),abs(s(4)),
+ abs(s(5)))/xqi(8)**2
if ( smax .lt. xmax ) then
dyzzy(ii,3) = som/xqi(8)**2
xmax = smax
endif
190 continue
200 continue
ifirst = ifirst - 1
210 continue
* #] real case:
else
* #[ complex case:
ifirst = 0
do 240 j=1,2
do 230 k=1,2
ii = 2*(j-1) + k
cdyzzy(ii,3) = cy(2*j,4,3)*cz(ii,3,3)-cy(2*j,3,3)*
+ cz(ii,4,3)
xmax = absc(cy(2*j,4,3)*cz(ii,3,3))
if ( absc(cdyzzy(ii,3)) .ge. xmax ) goto 230
isoort(5) = isoort(5) - 10
isoort(13) = isoort(13) - 10
if ( ldel2s ) then
ip = 3
else
ip = 8
endif
if ( mod(isoort(3),10).ne.0 .or. mod(isoort(11),10).ne.0
+ ) then
*
* one of the roots is really real
*
if ( ifirst .le. 0 ) then
- csdel2=DBLE(ddel2s(3))/(csdeli(3,3)+csdeli(3,4))
+ csdel2=Re(ddel2s(3))/(csdeli(3,3)+csdeli(3,4))
endif
if ( ifirst .le. 1 ) then
if ( j .eq. 1 ) then
cs(1) = xqi(ip)*qiDqj(7,1)*qiDqj(5,1)/sdel2
- cs(2) = +DBLE(qiDqj(7,1))*csdeli(3,3)
+ cs(2) = +Re(qiDqj(7,1))*csdeli(3,3)
if ( .not.ldel2s ) then
- cs(3) = +DBLE(qiDqj(9,1))*csdel2
+ cs(3) = +Re(qiDqj(9,1))*csdel2
else
- cs(3) = +DBLE(qiDqj(3,1))*csdel2
+ cs(3) = +Re(qiDqj(3,1))*csdel2
endif
else
if ( .not.ldel2s ) then
cs(1) = xqi(ip)*qiDqj(7,4)*qiDqj(5,4)/
+ sdel2
- cs(2) = DBLE(qiDqj(7,4))*csdeli(3,3)
+ cs(2) = Re(qiDqj(7,4))*csdeli(3,3)
else
cs(1) = xqi(ip)*qiDqj(7,1)*qiDqj(5,9)/
+ sdel2
- cs(2) = DBLE(qiDqj(7,1))*csdeli(3,3)
+ cs(2) = Re(qiDqj(7,1))*csdeli(3,3)
endif
- cs(3) = +DBLE(qiDqj(9,3))*csdel2
+ cs(3) = +Re(qiDqj(9,3))*csdel2
endif
if ( ldel2s ) cs(3) = -cs(3)
endif
if ( ifirst .le. 0 ) then
ifirst = 2
if ( .not.ldel2s ) then
- cs(4) = -DBLE(qiDqj(5,9)*qiDqj(7,1)/sdel2)*
+ cs(4) = -Re(qiDqj(5,9)*qiDqj(7,1)/sdel2)*
+ csdeli(3,3)
else
- cs(4) = DBLE(qiDqj(5,4)*qiDqj(7,1)/sdel2)*
+ cs(4) = Re(qiDqj(5,4)*qiDqj(7,1)/sdel2)*
+ csdeli(3,3)
endif
- cs(5) = DBLE(delpsi(3,3)/sdel2)*csdel2
+ cs(5) = Re(delpsi(3,3)/sdel2)*csdel2
endif
else
*
* both roots are complex
*
if ( ifirst .eq. 0 ) then
dsdel2 = -ddel2s(3)/(sdel2i(3,3)+sdel2i(3,4))
- csdel2 = DCMPLX(0D0,dsdel2)
+ csdel2 = ToComplex(0D0,dsdel2)
endif
if ( ifirst .le. 1 ) then
if ( j .eq. 1 ) then
cs(1) = xqi(ip)*qiDqj(7,1)*qiDqj(5,1)/sdel2
- cs(2) = +DCMPLX(0D0,qiDqj(7,1)*sdel2i(3,3))
+ cs(2) = +ToComplex(0D0,qiDqj(7,1)*sdel2i(3,3))
if ( .not.ldel2s ) then
- cs(3) = +DCMPLX(0D0,qiDqj(9,1)*dsdel2)
+ cs(3) = +ToComplex(0D0,qiDqj(9,1)*dsdel2)
else
- cs(3) = +DCMPLX(0D0,qiDqj(3,1)*dsdel2)
+ cs(3) = +ToComplex(0D0,qiDqj(3,1)*dsdel2)
endif
else
if ( .not.ldel2s ) then
cs(1)= xqi(ip)*qiDqj(7,4)*qiDqj(5,4)/
+ sdel2
- cs(2)=DCMPLX(0D0,qiDqj(7,4)*sdel2i(3,3))
+ cs(2)=ToComplex(0D0,qiDqj(7,4)*sdel2i(3,3))
else
cs(1)= xqi(ip)*qiDqj(7,1)*qiDqj(5,9)/
+ sdel2
- cs(2)=DCMPLX(0D0,qiDqj(7,1)*sdel2i(3,3))
+ cs(2)=ToComplex(0D0,qiDqj(7,1)*sdel2i(3,3))
endif
- cs(3) = +DCMPLX(0D0,qiDqj(9,3)*dsdel2)
+ cs(3) = +ToComplex(0D0,qiDqj(9,3)*dsdel2)
endif
if ( ldel2s ) cs(3) = -cs(3)
endif
if ( ifirst .le. 0 ) then
ifirst = 2
if ( .not.ldel2s ) then
- cs(4) = -DCMPLX(0D0,qiDqj(5,9)*qiDqj(7,1)*
+ cs(4) = -ToComplex(0D0,qiDqj(5,9)*qiDqj(7,1)*
+ sdel2i(3,3)/sdel2)
else
- cs(4) = DCMPLX(0D0,qiDqj(5,4)*qiDqj(7,1)*
+ cs(4) = ToComplex(0D0,qiDqj(5,4)*qiDqj(7,1)*
+ sdel2i(3,3)/sdel2)
endif
- cs(5) = DCMPLX(0D0,delpsi(3,3)*dsdel2/sdel2)
+ cs(5) = ToComplex(0D0,delpsi(3,3)*dsdel2/sdel2)
endif
endif
if ( k .eq. 1 ) then
csom = cs(1) + cs(2) + cs(3) + cs(4) + cs(5)
else
csom = cs(1) - cs(2) - cs(3) - cs(4) - cs(5)
endif
smax =max(absc(cs(1)),absc(cs(2)),absc(cs(3)),
+ absc(cs(4)),absc(cs(5)))/xqi(ip)**2
if ( smax .lt. xmax ) then
- cdyzzy(ii,3) = csom/DBLE(xqi(ip))**2
+ cdyzzy(ii,3) = csom/Re(xqi(ip))**2
xmax = smax
endif
230 continue
*
* get cdyyzz
*
if ( ldel2s ) then
cdyyzz(j,3) = cdyz(2,j,4,3) - cdyz(2,j,3,3)
xmax = absc(cdyz(2,j,4,3))
if ( absc(cdyyzz(j,3)) .ge. xloss*xmax ) goto 235
if ( ifirst .le. 0 ) then
if ( mod(isoort( 5),10).ne.0 .or.
+ mod(isoort(13),10).ne.0 ) then
- csdel2=DBLE(ddel2s(3))/(csdeli(3,3)+csdeli(3,4))
+ csdel2=Re(ddel2s(3))/(csdeli(3,3)+csdeli(3,4))
else
dsdel2 = -ddel2s(3)/(sdel2i(3,3)+sdel2i(3,4))
- csdel2 = DCMPLX(0D0,dsdel2)
+ csdel2 = ToComplex(0D0,dsdel2)
endif
endif
- cs(2) = -csdel2/DBLE(xqi(3))
+ cs(2) = -csdel2/Re(xqi(3))
cs(1) = qiDqj(5,3)*qiDqj(7,1)/(sdel2*xqi(3))
if ( j .eq. 1 ) then
csom = cs(1) + cs(2)
else
csom = cs(1) - cs(2)
endif
smax = absc(cs(1))
if ( smax .lt. xmax ) then
cdyyzz(j,3) = csom
xmax = smax
endif
endif
*
* bookkeeping
*
235 continue
ifirst = ifirst - 1
240 continue
* #] complex case:
endif
* #] vertices (3):
ier0 = 0
do 250 i = 1,12
ier0 = max(ier0,ieri(i))
250 continue
ier = ier + ier0
* #] get differences:
* #[ logarithms for 4point function:
*
* Not yet made stable ...
*
if ( npoin .eq. 4 ) then
do 420 i = 1,3
do 410 k = 3,4
ii = i+3*(k-3)
if ( ilogi(ii) .ne. -999 ) then
idone(ii) = 0
goto 410
endif
l = 2*i+8*(k-3)-1
if ((isoort(l).gt.0 .or. mod(isoort(l),10).le.-5) .and.
+ (isoort(l+1).ge.0 .or. mod(isoort(l+1),10).le.-5)) then
* #[ real case:
*
* the real case (isoort=-5,-6: really real but complex for ffdcs)
*
s(1) = -dyz(2,1,k,i)/dyz(2,2,k,i)
if ( abs(s(1)-1) .lt. xloss ) then
clogi(ii) = dfflo1(d2yzz(k,i)/dyz(2,2,k,i),ier)
ilogi(ii) = 0
else
if ( abs(s(1)+1) .lt. xloss ) then
clogi(ii) = dfflo1(-2*sdel2i(i,k)/(xpi(i+3,k)*
+ dyz(2,2,k,i)),ier)
else
clogi(ii) = zxfflg(abs(s(1)),0,0D0,ier)
endif
if ( dyz(2,2,k,i).gt.0 .and. dyz(2,1,k,i).gt.0 )
+ then
ilogi(ii) = -1
elseif ( dyz(2,1,k,i).lt.0 .and. dyz(2,2,k,i).lt.0)
+ then
ilogi(ii) = +1
else
ilogi(ii) = 0
endif
* in case del2s=0 and i=3 we pick up a minus sign, I think
if ( ldel2s .and. i .eq. 3 ) ilogi(ii) = -ilogi(ii)
endif
idone(ii) = 1
* #] real case:
elseif ( isoort(l) .lt. 0 ) then
* #[ complex case:
* for stability split the unit circle up in 4*pi/2
* (this may have to be improved to 8*pi/4...)
*
ier0 = 0
- if ( DBLE(cdyz(2,1,k,i)) .gt. abs(DIMAG(cdyz(2,1,k,i))))
+ if ( Re(cdyz(2,1,k,i)) .gt. abs(Im(cdyz(2,1,k,i))))
+ then
- som =2*atan2(DIMAG(cdyz(2,1,k,i)),DBLE(
+ som =2*atan2(Im(cdyz(2,1,k,i)),Re(
+ cdyz(2,1,k,i)))
- clogi(ii) = DCMPLX(0D0,som)
- if ( DIMAG(cdyz(2,1,k,i)) .gt. 0 ) then
+ clogi(ii) = ToComplex(0D0,som)
+ if ( Im(cdyz(2,1,k,i)) .gt. 0 ) then
ilogi(ii) = -1
else
ilogi(ii) = +1
endif
- elseif ( DBLE(cdyz(2,1,k,i)) .lt.
- + -abs(DIMAG(cdyz(2,1,k,i))) ) then
- if ( DIMAG(cdyz(2,1,k,i)) .eq. 0 ) then
+ elseif ( Re(cdyz(2,1,k,i)) .lt.
+ + -abs(Im(cdyz(2,1,k,i))) ) then
+ if ( Im(cdyz(2,1,k,i)) .eq. 0 ) then
call fferr(82,ier)
print *,'isoort = ',isoort(l),isoort(l+1)
endif
- som = 2*atan2(-DIMAG(cdyz(2,1,k,i)),-DBLE(
+ som = 2*atan2(-Im(cdyz(2,1,k,i)),-Re(
+ cdyz(2,1,k,i)))
- clogi(ii) = DCMPLX(0D0,som)
- if ( DIMAG(cdyz(2,1,k,i)) .gt. 0 ) then
+ clogi(ii) = ToComplex(0D0,som)
+ if ( Im(cdyz(2,1,k,i)) .gt. 0 ) then
ilogi(ii) = +1
else
ilogi(ii) = -1
endif
else
- s(1) = -DBLE(cdyz(2,1,k,i))
- s(2) = DIMAG(cdyz(2,1,k,i))
+ s(1) = -Re(cdyz(2,1,k,i))
+ s(2) = Im(cdyz(2,1,k,i))
som = 2*atan2(s(1),s(2))
- clogi(ii) = DCMPLX(0D0,som)
+ clogi(ii) = ToComplex(0D0,som)
ilogi(ii) = 0
endif
idone(ii) = 1
* #] complex case:
endif
410 continue
if ( idone(ii) .ne. 0 .and. idone(ii-3) .ne. 0 .and.
+ absc(clogi(ii)-clogi(ii-3)).lt.xloss*absc(clogi(ii)) .and.
+ ilogi(ii).eq.ilogi(ii-3) ) then
* #[ subtract more smartly:
if ( isoort(l).gt.0 .and. isoort(l+1).ge.0 ) then
goto 420
else
cs(1) = cdyzzy(1,i)
cs(2) = cdyzzy(2,i)
if ( i .eq. 1 ) then
cs(3) = 0
else
goto 420
endif
csom = cs(1) - cs(2) + cs(3)
xmax = max(absc(cs(1)),absc(cs(2)),absc(cs(3)))
* change this to "no warning and quit" later
c = csom/(cdyz(2,2,3,i)*cdyz(2,1,4,i))
c = zfflo1(c,ier)
*
* the log is never much bigger than 1, so demand at least
* accuracy to 0.1; this will catch all i*pi errors
*
if ( abs(clogi(ii-3)-clogi(ii)-c).gt.0.1 ) then
print *,'ffdxc0: error in smart logs: ',clogi(ii-3)-
+ clogi(ii),c,' not used'
goto 420
endif
clogi(ii-3) = c
clogi(ii) = 0
endif
* #] subtract more smartly:
endif
420 continue
* An algorithm to obtain the sum of two small logarithms more
* accurately has been put in ffcc0p, not yet here
endif
* #] logarithms for 4point function:
* #[ real case integrals:
if ( .not. lcompl ) then
* normal case
do 510 i=1,3
j = 2*i-1
if ( isoort(j) .eq. 0 ) then
if ( isoort(j+8) .ne. 0 ) then
call ffcxs3(cs3(20*i+61),ipi12(j+8),y(1,4,i),
+ z(1,4,i),dyz(1,1,4,i),d2yzz(4,i),dy2z(1,4,i),
+ xpi(1,4),piDpj(1,1,4),i,6,isoort(j+8),ier)
endif
elseif ( isoort(j+8) .eq. 0 ) then
call ffcxs3(cs3(20*i-19),ipi12(j),y(1,3,i),
+ z(1,3,i),dyz(1,1,3,i),d2yzz(3,i),dy2z(1,3,i),
+ xpi(1,3),piDpj(1,1,3),i,6,isoort(j),ier)
else
call ffdcxs(cs3(20*i-19),ipi12(j),y(1,3,i),z(1,3,i),
+ dyz(1,1,3,i),d2yzz(3,i),dy2z(1,3,i),dyzzy(1,i),
+ xpi,piDpj,i,6,isoort(j),ier)
endif
510 continue
isoort(7) = 0
isoort(8) = 0
* #] real case integrals:
* #[ complex case integrals:
else
* convert xpi
do 540 k=3,4
*not cetami(1,k) = etami(1,k)
*used cetami(3,k) = etami(3,k)
do 530 i=1,6
cpi(i,k) = xpi(i,k)
do 520 j=1,6
cpiDpj(j,i,k) = piDpj(j,i,k)
520 continue
530 continue
540 continue
do 550 i=1,3
j = 2*i-1
if ( isoort(j) .eq. 0 ) then
if ( isoort(j+8) .ne. 0 ) then
call ffcxs3(cs3(20*i+61),ipi12(j+8),y(1,4,i),
+ z(1,4,i),dyz(1,1,4,i),d2yzz(4,i),dy2z(1,4,i),
+ xpi(1,4),piDpj(1,1,4),i,6,isoort(j+8),ier)
endif
elseif ( isoort(j+8) .eq. 0 ) then
call ffcxs3(cs3(20*i-19),ipi12(j),y(1,3,i),
+ z(1,3,i),dyz(1,1,3,i),d2yzz(3,i),dy2z(1,3,i),
+ xpi(1,3),piDpj(1,1,3),i,6,isoort(j),ier)
elseif ( isoort(j) .gt. 0 ) then
if ( isoort(j+8) .gt. 0 ) then
call ffdcxs(cs3(20*i-19),ipi12(j),y(1,3,i),
+ z(1,3,i),dyz(1,1,3,i),d2yzz(3,i),dy2z(1,3,i),
+ dyzzy(1,i),xpi,piDpj,i,6,isoort(j),ier)
else
print *,'ffdxc0: error: should not occur!'
call ffcxs3(cs3(20*i-19),ipi12(j),y(1,3,i),
+ z(1,3,i),dyz(1,1,3,i),d2yzz(3,i),dy2z(1,3,i),
+ xpi(1,3),piDpj(1,1,3),i,6,isoort(j),ier)
call ffcs3(cs3(20*i+61),ipi12(j+8),cy(1,4,i),
+ cz(1,4,i),cdyz(1,1,4,i),cd2yzz(4,i),
+ cpi(1,4),cpiDpj(1,1,4),i,6,isoort(j+8),ier)
endif
else
if ( isoort(j+8) .lt. 0 ) then
call ffdcs(cs3(20*i-19),ipi12(j),cy(1,3,i),
+ cz(1,3,i),cdyz(1,1,3,i),cd2yzz(3,i),
+ cdyzzy(1,i),cdyyzz(1,i),cpi,cpiDpj,
+ i,6,isoort(j),ier)
else
print *,'ffdxc0: error: should not occur!'
call ffcs3(cs3(20*i-19),ipi12(j),cy(1,3,i),
+ cz(1,3,i),cdyz(1,1,3,i),cd2yzz(3,i),
+ cpi(1,3),cpiDpj(1,1,3),i,6,isoort(j),ier)
call ffcxs3(cs3(20*i+61),ipi12(j+8),y(1,4,i),
+ z(1,4,i),dyz(1,1,4,i),d2yzz(4,i),dy2z(1,4,i),
+ xpi(1,4),piDpj(1,1,4),i,6,isoort(j+8),ier)
endif
endif
550 continue
isoort(7) = 0
isoort(8) = 0
endif
return
* #] complex case integrals:
*###] ffdxc0:
end
diff --git a/Looptools/C/ffxc0.F b/Looptools/C/ffxc0.F
--- a/Looptools/C/ffxc0.F
+++ b/Looptools/C/ffxc0.F
@@ -1,744 +1,745 @@
#include "externals.h"
+#include "types.h"
* $Id: ffxc0.f,v 1.5 1996/08/15 09:36:47 gj Exp $
*###[ ffxc0:
subroutine ffxc0(cc0,xpi,ier)
***#[*comment:***********************************************************
* *
* Calculates the threepoint function closely following *
* recipe in 't Hooft & Veltman, NP B(183) 1979. *
* Bjorken and Drell metric is used nowadays! *
* *
* p2 | | *
* v | *
* / \ *
* m2/ \m3 *
* p1 / \ p3 *
* -> / m1 \ <- *
* ------------------------ *
* *
* 1 / 1 *
* = ----- \d^4Q---------------------------------------- *
* ipi^2 / [Q^2-m1^2][(Q+p1)^2-m2^2][(Q-p3)^2-m3^2] *
* *
* If the function is infra-red divergent (p1=m2,p3=m3,m1=0 or *
* cyclic) the function is calculated with a user-supplied cutoff *
* lambda in the common block /ffregul/. *
* *
* Input: xpi (real) i=1,3: mass^2, i=4,6: pi.pi *
* Output: cc0 (complex) C0, the threepoint function. *
* ier (integer) 0=ok, 1=inaccurate, 2=error *
* Calls: ffxc0p,ffxb0p *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE COMPLEX cc0
- DOUBLE PRECISION xpi(6)
+ ComplexType cc0
+ RealType xpi(6)
integer ier
*
* local variables:
*
integer i,j
- DOUBLE PRECISION dpipj(6,6)
+ RealType dpipj(6,6)
*
* common blocks:
*
#include "ff.h"
* #] declarations:
* #[ special case: all momenta^2 = 0
*
if (abs(xpi(4)) + abs(xpi(5)) + abs(xpi(6)) .lt. 1D-10) then
call ffxc0p0(cc0, xpi)
return
endif
* #[ convert input:
do 40 i=1,6
do 39 j = 1,6
dpipj(j,i) = xpi(j) - xpi(i)
39 continue
40 continue
* #] convert input:
* #[ call ffxc0a:
call ffxc0a(cc0,xpi,dpipj,ier)
* #] call ffxc0a:
*###] ffxc0:
end
*###[ ffxc0a:
subroutine ffxc0a(cc0,xpi,dpipj,ier)
***#[*comment:***********************************************************
* *
* See ffxc0. *
* *
* Input: xpi (real) i=1,3: mass^2, i=4,6: pi.pi *
* dpipj (real) = xpi(i) - xpi(j) *
* Output: cc0 (complex) C0, the threepoint function. *
* ier (integer) 0=ok, 1=inaccurate, 2=error *
* Calls: ffxc0p,ffxb0p *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE COMPLEX cc0
- DOUBLE PRECISION xpi(6),dpipj(6,6)
+ ComplexType cc0
+ RealType xpi(6),dpipj(6,6)
integer ier
*
* local variables:
*
logical ljust
integer i,j,inew(6,6)
-* DOUBLE COMPLEX cs,cs1,cs2
- DOUBLE PRECISION xqi(6),dqiqj(6,6),qiDqj(6,6),lambda0,dum66(6,6)
+* ComplexType cs,cs1,cs2
+ RealType xqi(6),dqiqj(6,6),qiDqj(6,6),lambda0,dum66(6,6)
save inew,lambda0
*
* common blocks:
*
#include "ff.h"
*
* memory
*
integer iermem(memory),ialmem(memory),memind,ierini
- DOUBLE PRECISION xpimem(6,memory),dl2mem(memory)
- DOUBLE COMPLEX cc0mem(memory)
+ RealType xpimem(6,memory),dl2mem(memory)
+ ComplexType cc0mem(memory)
save memind,iermem,ialmem,xpimem,dl2mem,cc0mem
data memind /0/
*
* data
*
data lambda0 /1.D0/
data inew /1,2,3,4,5,6,
+ 2,3,1,5,6,4,
+ 3,1,2,6,4,5,
+ 1,3,2,6,5,4,
+ 3,2,1,5,4,6,
+ 2,1,3,4,6,5/
* #] declarations:
* #[ initialisations:
if ( lmem .and. memind .eq. 0 ) then
do 2 i=1,memory
do 1 j=1,6
xpimem(j,i) = 0
1 continue
ialmem(i) = 0
2 continue
endif
idsub = 0
ljust = .FALSE.
* #] initialisations:
* #[ handle special cases:
*
* The infrared divergent diagrams are calculated in ffxc0i:
*
if ( dpipj(2,4).eq.0 .and. dpipj(3,6).eq.0 .and. xpi(1).eq.0
+ .or. dpipj(3,5).eq.0 .and. dpipj(1,4).eq.0 .and. xpi(2).eq.0
+ .or. dpipj(1,6).eq.0 .and. dpipj(2,5).eq.0 .and. xpi(3).eq.0 )
+ then
call ffxc0i(cc0,xpi,dpipj,ier)
return
endif
* #] handle special cases:
* #[ rotate to alpha in (0,1):
call ffrot3(irota3,xqi,dqiqj,qiDqj,xpi,dpipj,dum66,2,3,ier)
* #] rotate to alpha in (0,1):
* #[ look in memory:
ierini = ier+ner
if ( lmem .and. lambda .eq. lambda0 ) then
do 70 i=1,memory
do 60 j=1,6
if ( xqi(j) .ne. xpimem(j,i) ) goto 70
60 continue
if ( ialmem(i) .ne. isgnal ) goto 70
* we found an already calculated mass combination ..
* (maybe check differences as well)
cc0 = cc0mem(i)
ier = ier+iermem(i)
if ( ldot ) then
fdel2 = dl2mem(i)
* we forgot to recalculate the stored quantities
ljust = .TRUE.
goto 71
endif
return
70 continue
elseif ( lmem ) then
lambda0 = lambda
endif
71 continue
* #] look in memory:
* #[ dot products:
call ffdot3(qiDqj,xqi,dqiqj,6,ier)
*
* save dotproducts for tensor functions if requested
*
if ( ldot ) then
do 75 i=1,6
do 74 j=1,6
fpij3(j,i) = qiDqj(inew(i,irota3),inew(j,irota3))
74 continue
75 continue
if ( irota3 .gt. 3 ) then
*
* the sign of the s's has been changed!
*
do 77 i=1,3
do 76 j=4,6
fpij3(j,i) = -fpij3(j,i)
fpij3(i,j) = -fpij3(i,j)
76 continue
77 continue
endif
endif
if ( ljust ) return
* #] dot products:
* #[ call ffxc0b:
call ffxc0b(cc0,xqi,dqiqj,qiDqj,ier)
* #] call ffxc0b:
* #[ add to memory:
if ( lmem ) then
memind = memind + 1
if ( memind .gt. memory ) memind = 1
do 200 j=1,6
xpimem(j,memind) = xqi(j)
200 continue
cc0mem(memind) = cc0
iermem(memind) = ier+ner-ierini
ialmem(memind) = isgnal
dl2mem(memind) = fdel2
endif
* #] add to memory:
*###] ffxc0a:
end
*###[ ffxc0b:
subroutine ffxc0b(cc0,xqi,dqiqj,qiDqj,ier)
***#[*comment:***********************************************************
* *
* See ffxc0. *
* *
* Input: xpi (real) i=1,3: mass^2, i=4,6: pi.pi *
* dpipj (real) = xpi(i) - xpi(j) *
* Output: cc0 (complex) C0, the threepoint function. *
* ier (integer) 0=ok, 1=inaccurate, 2=error *
* Calls: ffxc0p,ffxb0p *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE COMPLEX cc0
- DOUBLE PRECISION xqi(6),dqiqj(6,6),qiDqj(6,6)
+ ComplexType cc0
+ RealType xqi(6),dqiqj(6,6),qiDqj(6,6)
integer ier
*
* local variables:
*
integer nerr
parameter(nerr=6)
integer isoort(8),ipi12(8),i,j,k,ipi12t,ilogi(3),ier0,ieri(nerr)
- DOUBLE COMPLEX cs3(80),cs,c,clogi(3),cslam,cetalm,
+ ComplexType cs3(80),cs,c,clogi(3),cslam,cetalm,
+ cetami(6),cel2s(3),calph(3),cblph(3),csdel2,
+ cqi(6),cdqiqj(6,6),cqiDqj(6,6),celpsi(3)
- DOUBLE PRECISION del2,del2s(3),del3,delpsi(3),
+ RealType del2,del2s(3),del3,delpsi(3),
+ del3mi(3)
- DOUBLE PRECISION xmax,absc,alph(3),etalam,etami(6),sdel2,
+ RealType xmax,absc,alph(3),etalam,etami(6),sdel2,
+ blph(3)
*
* common blocks:
*
#include "ff.h"
*
* statement function:
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
*
* #] declarations:
* #[ calculations:
*
* some determinants
*
do 98 i = 1,nerr
ieri(i) = 0
98 continue
call ffdel2(del2,qiDqj, 6, 4,5,6, 1,ier)
if ( ldot ) fdel2 = del2
if ( del2 .gt. 0 ) then
* shouldn't occur ...
* 12-10-1993 three spacelike momenta are OK
if ( .not.(xqi(4).lt.0 .and. xqi(5).lt.0 .and. xqi(6).lt.0)
+ ) then
call fferr(41,ier)
print *,'xpi = ',xqi
endif
elseif ( del2 .eq. 0 ) then
call fferr(42,ier)
return
endif
call ffdel3(del3,qiDqj)
call ffdl3m(del3mi,.TRUE.,del3,del2,xqi,dqiqj,qiDqj,6, 4,5,6,
+ 1,3)
do 101 i=1,3
j = i+1
if ( j .eq. 4 ) j = 1
call ffdel2(del2s(i),qiDqj,6, i+3,i,j, 1,ieri(i))
k = i-1
if ( k .eq. 0 ) k = 3
call ffdl2p(delpsi(i),xqi,dqiqj,qiDqj,i+3,j+3,k+3,i,j,k,6)
101 continue
ier0 = 0
do 99 i=1,nerr
ier0 = max(ier0,ieri(i))
99 continue
ier = ier + ier0
*
* initialize cs3:
*
do 80 i=1,80
cs3(i) = 0
80 continue
do 90 i=1,8
ipi12(i) = 0
90 continue
do 100 i=1,3
clogi(i) = 0
ilogi(i) = 0
100 continue
* #[ complex case:
* in case of three spacelike momenta or unphysical real ones
if ( del2 .gt. 0 ) then
do 102 i=1,3
cel2s(i) = del2s(i)
celpsi(i) = delpsi(i)
cetami(i) = del3mi(i)/del2
102 continue
do 104 i=1,6
cqi(i) = xqi(i)
do 103 j=1,6
cdqiqj(j,i) = dqiqj(j,i)
cqiDqj(j,i) = qiDqj(j,i)
103 continue
104 continue
cetalm = del3/del2
- csdel2 = isgnal*DCMPLX(0D0,sqrt(del2))
+ csdel2 = isgnal*ToComplex(0D0,sqrt(del2))
*
* get alpha,1-alpha
*
call ffcoot(cblph(1),calph(1),cqi(5),-cqiDqj(5,6),cqi(6),
+ csdel2,ier)
call ffcoot(calph(3),cblph(3),cqi(5),-cqiDqj(5,4),cqi(4),
+ csdel2,ier)
cslam = 2*csdel2
call ffcc0p(cs3,ipi12,isoort,clogi,ilogi,cqi,cdqiqj,cqiDqj,
+ csdel2,cel2s,cetalm,cetami,celpsi,calph,3,ier)
goto 109
endif
* #] complex case:
etalam = del3/del2
do 106 i=1,3
etami(i) = del3mi(i)/del2
106 continue
if ( abs(isgnal).ne.1 ) then
print *,'ffxc0b: error: isgnal should be +/-1, not ',isgnal
print *,' forgot to call ltini?'
call ltini
endif
sdel2 = isgnal*sqrt(-del2)
*
* get alpha,1-alpha
*
call ffroot(blph(1),alph(1),xqi(5),-qiDqj(5,6),xqi(6),sdel2,ier)
call ffroot(alph(3),blph(3),xqi(5),-qiDqj(5,4),xqi(4),sdel2,ier)
if ( l4also .and. ( alph(1) .gt. 1 .or. alph(1) .lt. 0 ) .and.
+ abs(blph(1)-.5D0) .lt. abs(alph(1)-.5D0) ) then
alph(1) = blph(1)
alph(3) = blph(3)
sdel2 = -sdel2
isgnal = -isgnal
endif
cslam = 2*sdel2
*
* and the calculations
*
call ffxc0p(cs3,ipi12,isoort,clogi,ilogi,xqi,dqiqj,qiDqj,
+ sdel2,del2s,etalam,etami,delpsi,alph,3,ier)
*
* sum'em up:
*
109 continue
cs = 0
xmax = 0
do 110 i=1,80
* if ( cs3(i) .ne. 0 ) then
cs = cs + cs3(i)
xmax = max(xmax,absc(cs))
* endif
110 continue
ipi12t = 0
do 120 i=1,8
ipi12t = ipi12t + ipi12(i)
120 continue
- cs = cs + ipi12t*DBLE(pi12)
+ cs = cs + ipi12t*Re(pi12)
*
* A imaginary component less than precc times the real part is
* zero (may be removed)
*
- if ( abs(DIMAG(cs)) .lt. precc*abs(DBLE(cs)) )
- + cs = DCMPLX(DBLE(cs))
+ if ( abs(Im(cs)) .lt. precc*abs(Re(cs)) )
+ + cs = ToComplex(Re(cs))
*
* Finally ...
*
cc0 = - cs/cslam
* #] calculations:
*###] ffxc0b:
end
*###[ ffrot3:
subroutine ffrot3(irota,xqi,dqiqj,qiDqj,xpi,dpipj,piDpj,
+ iflag,npoin,ier)
***#[*comment:***********************************************************
* *
* rotates the arrays xpi, dpipj into xqi,dqiqj so that *
* xpi(6),xpi(4) suffer the strongest outside cancellations and *
* xpi(6) > xpi(4) if iflag = 1, so that xpi(5) largest and xpi(5) *
* and xpi(6) suffer cancellations if iflag = 2. *
* if iflag = 3 make xqi(3)=0. *
* If npoin=4, rotate piDpj into qiDqj as well. *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer irota,iflag,ier,npoin
- DOUBLE PRECISION xpi(6),dpipj(6,6),piDpj(6,6),xqi(6),dqiqj(6,6),
+ RealType xpi(6),dpipj(6,6),piDpj(6,6),xqi(6),dqiqj(6,6),
+ qiDqj(6,6)
*
* local variables
*
- DOUBLE PRECISION a1,a2,a3,xpimax
- DOUBLE COMPLEX chulp(3,3)
+ RealType a1,a2,a3,xpimax
+ ComplexType chulp(3,3)
integer i,j,inew(6,6)
save inew
*
* common blocks
*
#include "ff.h"
*
* data
*
data inew /1,2,3,4,5,6,
+ 2,3,1,5,6,4,
+ 3,1,2,6,4,5,
+ 1,3,2,6,5,4,
+ 3,2,1,5,4,6,
+ 2,1,3,4,6,5/
* #] declarations:
* #[ get largest cancellation:
if ( iflag .eq. 1 ) then
a1 = abs(dpipj(6,4))/max(abs(xpi(6)+xpi(4)),xalogm)
a2 = abs(dpipj(5,4))/max(abs(xpi(5)+xpi(4)),xalogm)
a3 = abs(dpipj(5,6))/max(abs(xpi(6)+xpi(5)),xalogm)
if ( a1 .le. a2 .and. a1 .le. a3 ) then
irota = 1
if ( abs(xpi(6)) .lt. abs(xpi(4)) ) then
irota = 4
endif
elseif ( a2 .le. a3 ) then
irota = 3
if ( abs(xpi(4)) .lt. abs(xpi(5)) ) then
irota = 6
endif
else
irota = 2
if ( abs(xpi(5)) .lt. abs(xpi(6)) ) then
irota = 5
endif
endif
elseif ( iflag .eq. 2 ) then
xpimax = max(xpi(4),xpi(5),xpi(6))
if ( xpimax .eq. 0 ) then
if ( xpi(5) .ne. 0 ) then
irota = 1
elseif ( xpi(4) .ne. 0 ) then
irota = 2
elseif ( xpi(6) .ne. 0 ) then
irota = 3
else
call fferr(40,ier)
irota = 1
endif
elseif ( xpi(5) .eq. xpimax ) then
if ( xpi(4) .le. xpi(6) ) then
irota = 1
else
irota = 4
endif
elseif ( xpi(4) .eq. xpimax ) then
if ( xpi(5) .ge. xpi(6) ) then
irota = 2
else
irota = 5
endif
else
if ( xpi(4) .ge. xpi(6) ) then
irota = 3
else
irota = 6
endif
endif
elseif ( iflag .eq. 3 ) then
if ( dpipj(2,4).eq.0 .and. dpipj(3,6).eq.0 .and.
+ xpi(1).eq.0 ) then
irota = 3
elseif ( dpipj(1,6).eq.0 .and. dpipj(2,5).eq.0 .and.
+ xpi(3).eq.0 ) then
irota = 1
elseif ( dpipj(3,5).eq.0 .and. dpipj(1,4).eq.0 .and.
+ xpi(2).eq.0 ) then
irota = 2
else
call fferr(35,ier)
irota = 1
endif
else
call fferr(35,ier)
irota = 1
endif
* #] get largest cancellation:
* #[ rotate:
do 20 i=1,6
xqi(inew(i,irota)) = xpi(i)
do 10 j=1,6
dqiqj(inew(i,irota),inew(j,irota)) = dpipj(i,j)
10 continue
20 continue
*
* when called in a 4pointfunction we already have the dotproducts
*
if ( npoin .eq. 4 ) then
do 80 j=1,6
do 70 i=1,6
qiDqj(inew(i,irota),inew(j,irota)) = piDpj(i,j)
70 continue
80 continue
endif
*DEBUG if ( iflag .eq. 3 .and. lsmug ) then
if ( lsmug ) then
*
* do not forget to rotate the smuggled differences
*
do 40 j=1,3
do 30 i=1,3
chulp(i,j) = cmipj(i,j)
30 continue
40 continue
do 60 j=1,3
do 50 i=1,3
cmipj(inew(i,irota),inew(j+3,irota)-3) = chulp(i,j)
50 continue
60 continue
endif
* #] rotate:
*###] ffrot3:
end
*###[ ffdot3:
subroutine ffdot3(piDpj,xpi,dpipj,ns,ier)
***#[*comment:***********************************************************
* *
* calculate the dotproducts pi.pj with *
* *
* pi = si i1=1,3 *
* pi = p(i-3) i1=4,6 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ns,ier
- DOUBLE PRECISION xpi(6),dpipj(6,6),piDpj(6,6)
+ RealType xpi(6),dpipj(6,6),piDpj(6,6)
*
* locals
*
integer is1,is2,is3,ip1,ip2,ip3,i,j,ier1,inew(6,6)
save inew
*
* rest
*
#include "ff.h"
*
* data
*
data inew /1,2,3,4,5,6,
+ 2,3,1,5,6,4,
+ 3,1,2,6,4,5,
+ 1,3,2,6,5,4,
+ 3,2,1,5,4,6,
+ 2,1,3,4,6,5/
*
* #] declarations:
* #[ check input:
if ( ns .ne. 6 ) print *,'ffdot3: error: ns /= 6 '
* #] check input:
* #[ copy if known:
*
if ( idot.ge.3 ) then
do 2 i=1,6
do 1 j=1,6
piDpj(inew(j,irota3),inew(i,irota3)) = fpij3(j,i)
1 continue
2 continue
if ( irota3 .gt. 3 ) then
*
* the sign of the s's has been changed!
*
do 4 i=1,3
do 3 j=4,6
piDpj(j,i) = -piDpj(j,i)
piDpj(i,j) = -piDpj(i,j)
3 continue
4 continue
endif
return
endif
*
* #] copy if known:
* #[ calculations:
ier1 = ier
do 10 is1=1,3
is2 = is1 + 1
if ( is2 .eq. 4 ) is2 = 1
is3 = is2 + 1
if ( is3 .eq. 4 ) is3 = 1
ip1 = is1 + 3
ip2 = is2 + 3
ip3 = is3 + 3
*
* pi.pj, si.sj
*
piDpj(is1,is1) = xpi(is1)
piDpj(ip1,ip1) = xpi(ip1)
*
* si.s(i+1)
*
if ( xpi(is2) .le. xpi(is1) ) then
piDpj(is1,is2) = (dpipj(is1,ip1) + xpi(is2))/2
else
piDpj(is1,is2) = (dpipj(is2,ip1) + xpi(is1))/2
endif
piDpj(is2,is1) = piDpj(is1,is2)
*
* pi.si
*
if ( abs(xpi(ip1)) .le. xpi(is1) ) then
piDpj(ip1,is1) = (dpipj(is2,is1) - xpi(ip1))/2
else
piDpj(ip1,is1) = (dpipj(is2,ip1) - xpi(is1))/2
endif
piDpj(is1,ip1) = piDpj(ip1,is1)
*
* pi.s(i+1)
*
if ( abs(xpi(ip1)) .le. xpi(is2) ) then
piDpj(ip1,is2) = (dpipj(is2,is1) + xpi(ip1))/2
else
piDpj(ip1,is2) = (dpipj(ip1,is1) + xpi(is2))/2
endif
piDpj(is2,ip1) = piDpj(ip1,is2)
*
* pi.s(i+2)
*
if ( min(abs(dpipj(is2,is1)),abs(dpipj(ip3,ip2))) .le.
+ min(abs(dpipj(ip3,is1)),abs(dpipj(is2,ip2))) ) then
piDpj(ip1,is3) = (dpipj(ip3,ip2) + dpipj(is2,is1))/2
else
piDpj(ip1,is3) = (dpipj(ip3,is1) + dpipj(is2,ip2))/2
endif
piDpj(is3,ip1) = piDpj(ip1,is3)
*
* pi.p(i+1)
*
if ( idot.le.0 ) then
if ( abs(xpi(ip2)) .le. abs(xpi(ip1)) ) then
piDpj(ip1,ip2) = (dpipj(ip3,ip1) - xpi(ip2))/2
else
piDpj(ip1,ip2) = (dpipj(ip3,ip2) - xpi(ip1))/2
endif
piDpj(ip2,ip1) = piDpj(ip1,ip2)
else
piDpj(inew(ip2,irota3),inew(ip1,irota3)) =
+ fpij3(ip1,ip2)
piDpj(inew(ip1,irota3),inew(ip2,irota3)) =
+ piDpj(inew(ip2,irota3),inew(ip1,irota3))
endif
10 continue
ier = ier1
*
* #] calculations:
*###] ffdot3:
end
*###[ ffxc0r:
subroutine ffxc0r(cc0,xpi,ier)
***#[*comment:***********************************************************
* *
* Tries all 2 permutations of the 3pointfunction *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
integer ier
- DOUBLE PRECISION xpi(6),xqi(6)
- DOUBLE COMPLEX cc0,cc0p
+ RealType xpi(6),xqi(6)
+ ComplexType cc0,cc0p
integer inew(6,2),irota,ier1,i,j,ialsav
save inew
#include "ff.h"
data inew /1,2,3,4,5,6,
+ 1,3,2,6,5,4/
* #] declarations:
* #[ calculations:
cc0 = 0
ier = 999
ialsav = isgnal
do 30 j = -1,1,2
do 20 irota=1,2
do 10 i=1,6
xqi(inew(i,irota)) = xpi(i)
10 continue
print '(a,i1,a,i2)','---#[ rotation ',irota,': isgnal ',
+ isgnal
ier1 = 0
ner = 0
id = id + 1
isgnal = ialsav
call ffxc0(cc0p,xqi,ier1)
ier1 = ier1 + ner
print '(a,i1,a,i2)','---#] rotation ',irota,': isgnal ',
+ isgnal
print '(a,2g28.16,i3)','c0 = ',cc0p,ier1
if ( ier1 .lt. ier ) then
cc0 = cc0p
ier = ier1
endif
20 continue
ialsav = -ialsav
30 continue
* #] calculations:
*###] ffxc0r:
end
diff --git a/Looptools/C/ffxc0i.F b/Looptools/C/ffxc0i.F
--- a/Looptools/C/ffxc0i.F
+++ b/Looptools/C/ffxc0i.F
@@ -1,763 +1,764 @@
#include "externals.h"
+#include "types.h"
*--#[ log:
* $Id: ffxc0i.f,v 1.3 1996/06/03 12:11:43 gj Exp $
* $Log: ffxc0i.f,v $
c Revision 1.3 1996/06/03 12:11:43 gj
c Added an error message for ffxc0j with zero masses, which is ill-defined.
c
c Revision 1.2 1995/12/01 15:04:40 gj
c Fixed a ridiculous bug: wrong sign for p4^2=0, m2<m1.
c
*--#] log:
*###[ ffxc0i:
subroutine ffxc0i(cc0,xpi,dpipj,ier)
***#[*comment:***********************************************************
* *
* Calculates the infrared finite part of a infrared divergent *
* threepoint function with the factor ipi^2. The cutoff *
* parameter is assumed to be in /ffregul/. *
* *
* Input: xpi(6) (real) pi.pi (B&D) *
* dpipj(6,6) (real) xpi(i)-xpi(j) *
* lambda (real) cutoff (either photon mass**2 *
* or radiation limit). *
* Output: cc0 (complex) C0, the threepoint function. *
* ier (integer) usual error flag *
* Calls: *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE COMPLEX cc0
- DOUBLE PRECISION xpi(6),dpipj(6,6)
+ ComplexType cc0
+ RealType xpi(6),dpipj(6,6)
*
* local variables
*
integer init,ipi12,i,ilogi(3),irota,n
integer j,inew(6,6)
- DOUBLE COMPLEX cs(15),csum,c,clogi(3)
- DOUBLE PRECISION xqi(6),dqiqj(6,6),qiDqj(6,6),sdel2,xmax,absc,
+ ComplexType cs(15),csum,c,clogi(3)
+ RealType xqi(6),dqiqj(6,6),qiDqj(6,6),sdel2,xmax,absc,
+ dum66(6,6),del2,m1,m2
save init,inew,ilogi
*
* common blocks etc
*
#include "ff.h"
*
* data
*
data init /0/
data inew /1,2,3,4,5,6,
+ 2,3,1,5,6,4,
+ 3,1,2,6,4,5,
+ 1,3,2,6,5,4,
+ 3,2,1,5,4,6,
+ 2,1,3,4,6,5/
data ilogi /3*0/
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
*
* initialisations
*
do 1 i=1,15
cs(i) = 0
1 continue
ipi12 = 0
* #] declarations:
* #[ check input:
if ( init .eq. 0 .and. .not.lsmug ) then
init = 1
print *,'ffxc0i: infra-red divergent threepoint function, ',
+ 'working with a cutoff ',lambda
endif
if ( .not.lsmug .and. lambda .eq. 0 ) then
call fferr(59,ier)
return
endif
* #] check input:
* #[ groundwork:
*
* rotate to xpi(3)=0, xpi(1)=xpi(6), xpi(2)=xpi(5)
*
call ffrot3(irota,xqi,dqiqj,qiDqj,xpi,dpipj,dum66,3,3,ier)
*
* get some dotproducts
*
if ( ldot ) then
call ffdot3(qiDqj,xqi,dqiqj,6,ier)
do 5 i=1,6
do 4 j=1,6
fpij3(j,i) = qiDqj(inew(i,irota),inew(j,irota))
4 continue
5 continue
else
if ( abs(xqi(4)) .lt. xqi(1) ) then
qiDqj(4,1) = dqiqj(2,1) - xqi(4)
xmax = abs(xqi(4))
else
qiDqj(4,1) = dqiqj(2,4) - xqi(1)
xmax = xqi(1)
endif
qiDqj(4,1) = qiDqj(4,1)/2
qiDqj(1,4) = qiDqj(4,1)
if ( abs(xqi(4)) .lt. xqi(2) ) then
qiDqj(4,2) = dqiqj(2,1) + xqi(4)
xmax = abs(xqi(4))
else
qiDqj(4,2) = xqi(2) - dqiqj(1,4)
xmax = xqi(2)
endif
qiDqj(4,2) = qiDqj(4,2)/2
qiDqj(2,4) = qiDqj(4,2)
if ( xqi(1) .lt. xqi(2) ) then
qiDqj(1,2) = xqi(1) + dqiqj(2,4)
xmax = xqi(1)
else
qiDqj(1,2) = xqi(2) + dqiqj(1,4)
xmax = xqi(2)
endif
qiDqj(1,2) = qiDqj(1,2)/2
qiDqj(2,1) = qiDqj(1,2)
qiDqj(1,1) = xqi(1)
qiDqj(2,2) = xqi(2)
qiDqj(4,4) = xqi(4)
endif
* #] groundwork:
* #[ calculations:
*
call ffdel2(del2,qiDqj,6,1,2,4,1,ier)
if ( ldot ) fdel2 = del2
*
* the case del2=0 is hopeless - this is really a two-point function
*
if ( abs(del2) .lt. 1D-14 ) then
if(xpi(1) .eq. 0) then
m1 = xpi(2)
m2 = xpi(3)
else if(xpi(2) .eq. 0) then
m1 = xpi(1)
m2 = xpi(3)
else
m1 = xpi(1)
m2 = xpi(2)
endif
if(m1 .eq. m2) then
cc0 = -1/(16*pi**2)/2D0/m1 * log(lambda/m1)
else
m1 = sqrt(m1)
m2 = sqrt(m2)
cc0 = -1/(16*pi**2)/2D0/(m1*m2) *
+ (log(lambda/(m1*m2)) - 2
+ + (m1 + m2)/(m1 - m2)*log(m1/m2))
endif
return
endif
*
* we cannot yet handle the complex case
*
if ( del2 .gt. 0 ) then
call fferr(83,ier)
return
endif
*
sdel2 = isgnal*sqrt(-del2)
*
call ffxc0j(cs,ipi12,sdel2,clogi,ilogi,xqi,dqiqj,qiDqj,
+ lambda,3,ier)
* #] calculations:
* #[ sum:
*
* Sum
*
xmax = 0
csum = 0
if ( .not.lsmug ) then
n = 10
else
n = 15
endif
do i=1,n
csum = csum + cs(i)
xmax = max(xmax,absc(csum))
enddo
- csum = csum + ipi12*DBLE(pi12)
- cc0 = -csum*DBLE(1/(2*sdel2))
+ csum = csum + ipi12*Re(pi12)
+ cc0 = -csum*Re(1/(2*sdel2))
* #] sum:
*###] ffxc0i:
end
*###[ ffxc0j:
subroutine ffxc0j(cs,ipi12,sdel2i,clogi,ilogi,
+ xpi,dpipj,piDpj,lamsq,npoin,ier)
***#[*comment:***********************************************************
* *
* Calculates the infrared finite part of a infrared divergent *
* threepoint function with the factor ipi^2. *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ipi12,ilogi(3),npoin,ier
- DOUBLE COMPLEX cs(15),clogi(3)
- DOUBLE PRECISION xpi(6),dpipj(6,6),piDpj(6,6),lamsq,sdel2i
+ ComplexType cs(15),clogi(3)
+ RealType xpi(6),dpipj(6,6),piDpj(6,6),lamsq,sdel2i
*
* local variables
*
integer i,ieps,ieps1,n,ier0
- DOUBLE COMPLEX clog1,clog2,cdum(2),cel3,cdyzm,cdyzp,cli,chulp,
+ ComplexType clog1,clog2,cdum(2),cel3,cdyzm,cdyzp,cli,chulp,
+ carg1,carg2,chulp1
- DOUBLE COMPLEX zfflog,zxfflg,cc
- DOUBLE PRECISION del2,zm,zp,zm1,zp1,sdel2,hulp,dum(3),
+ ComplexType zfflog,zxfflg,cc
+ RealType del2,zm,zp,zm1,zp1,sdel2,hulp,dum(3),
+ dfflo1,dyzp,dyzm,wm,wp,absc,arg1,arg2,del3
external dfflo1,zfflog,zxfflg
*
* common blocks etc
*
#include "ff.h"
*
* statement function
*
- absc(cc) = abs(DBLE(cc)) + abs(DIMAG(cc))
+ absc(cc) = abs(Re(cc)) + abs(Im(cc))
*
* #] declarations:
* #[ get determinants, roots, ieps:
*
if ( lsmug ) then
- del3 = (- DBLE(xpi(1))*DBLE(cmipj(2,2))**2
- + - DBLE(xpi(2))*DBLE(cmipj(1,3))**2
- + + 2*DBLE(piDpj(1,2))*DBLE(cmipj(2,2))*
- + DBLE(cmipj(1,3)) )/4
+ del3 = (- Re(xpi(1))*Re(cmipj(2,2))**2
+ + - Re(xpi(2))*Re(cmipj(1,3))**2
+ + + 2*Re(piDpj(1,2))*Re(cmipj(2,2))*
+ + Re(cmipj(1,3)) )/4
if ( nschem .ge. 3 ) then
- cel3 = (- DBLE(xpi(1))*cmipj(2,2)**2
- + - DBLE(xpi(2))*cmipj(1,3)**2
- + + 2*DBLE(piDpj(1,2))*cmipj(2,2)*cmipj(1,3) )/4
+ cel3 = (- Re(xpi(1))*cmipj(2,2)**2
+ + - Re(xpi(2))*cmipj(1,3)**2
+ + + 2*Re(piDpj(1,2))*cmipj(2,2)*cmipj(1,3) )/4
else
- cel3 = DBLE(del3)
+ cel3 = Re(del3)
endif
endif
del2 = -sdel2i**2
*
* the routine as it stands can not handle sdel2<0.
* the simplest solution seems to be to switch to sdel2>0 for
* the time being - we calculate a complete 3point function so it
* should not be a problem (just a sign). Of course this spoils a
* good check on the correctness.
*
sdel2 = abs(sdel2i)
*
if ( xpi(4).eq.0 ) then
zm = xpi(2)/dpipj(2,1)
zm1 = -xpi(1)/dpipj(2,1)
else
call ffroot(zm,zp,xpi(4),piDpj(4,2),xpi(2),sdel2,ier)
if ( dpipj(1,2) .ne. 0 ) then
call ffroot(zp1,zm1,xpi(4),-piDpj(4,1),xpi(1),sdel2,ier)
else
zm1 = zp
zp1 = zm
endif
endif
* imag sign ok 30-oct-1989
ieps = -1
if ( xpi(4).ne.0 ) dyzp = -2*sdel2/xpi(4)
*
* #] get determinants, roots, ieps:
* #[ the finite+divergent S1:
*
if ( xpi(4).ne.0 ) then
call ffcxr(cs(1),ipi12,zm,zm1,zp,zp1,dyzp,
+ .FALSE.,0D0,0D0,0D0,.FALSE.,dum,ieps,ier)
endif
*
* Next the divergent piece
*
if ( .not.lsmug ) then
*
* Here we dropped the term log(lam/lamsq)*log(-zm/zm1)
*
if ( abs(zm1) .gt. 1/xloss ) then
clog1 = dfflo1(1/zm1,ier)
elseif ( zm.ne.0 ) then
clog1 = zxfflg(-zm/zm1,-2,0D0,ier)
else
call fferr(97,ier)
return
endif
hulp = zm*zm1*4*del2/lamsq**2
*
* 14-jan-1994: do not count when this is small, this was
* meant to be so by the user carefully adjusting lamsq
*
ier0 = ier
if ( hulp.eq.0 ) call fferr(97,ier)
clog2 = zxfflg(hulp,2,0D0,ier0)
cs(8) = -clog1*clog2/2
else
*
* checked 4-aug-1992, but found Yet Another Bug 30-sep-1992
*
- cdyzm = cel3*DBLE(1/(-2*sdel2*del2))
+ cdyzm = cel3*Re(1/(-2*sdel2*del2))
dyzm = del3/(-2*sdel2*del2)
- carg1 = +cdyzm*DBLE(1/zm)
+ carg1 = +cdyzm*Re(1/zm)
arg1 = +dyzm/zm
- clog1 = zfflog(-carg1,+ieps,DCMPLX(DBLE(zm),DBLE(0)),ier)
- if (DIMAG(cdyzm) .lt. 0 .and. arg1 .gt. 0 ) then
+ clog1 = zfflog(-carg1,+ieps,ToComplex(Re(zm),Re(0)),ier)
+ if (Im(cdyzm) .lt. 0 .and. arg1 .gt. 0 ) then
clog1 = clog1 - c2ipi
* ier = ier + 50
endif
cs(8) = -clog1**2/2
- carg2 = -cdyzm*DBLE(1/zm1)
+ carg2 = -cdyzm*Re(1/zm1)
arg2 = -dyzm/zm1
- clog2 = zfflog(-carg2,ieps,DCMPLX(DBLE(-zm1),DBLE(0)),ier)
- if ( DIMAG(cdyzm) .lt. 0 .and. arg2 .gt. 0 ) then
+ clog2 = zfflog(-carg2,ieps,ToComplex(Re(-zm1),Re(0)),ier)
+ if ( Im(cdyzm) .lt. 0 .and. arg2 .gt. 0 ) then
clog2 = clog2 + c2ipi
endif
cs(9) = +clog2**2/2
endif
* #] the finite+divergent S1:
* #[ log(1) for npoin=4:
if ( npoin .eq. 4 ) then
if ( ilogi(1) .eq. -999 ) then
if ( .not.lsmug ) then
hulp = xpi(4)*lamsq/(4*del2)
ier0 = ier
if ( hulp.eq.0 ) call fferr(97,ier)
clogi(1) = -zxfflg(abs(hulp),0,0D0,ier0)
if ( hulp .lt. 0 ) then
if ( xpi(4) .gt. 0 ) then
ilogi(1) = -1
else
ilogi(1) = +1
endif
else
ilogi(1) = 0
endif
else
if ( xpi(4).eq.0 ) then
print *,'ffxc0i: cannot handle t=0 yet, sorry'
print *,'Please regularize with a small mass'
stop
endif
- chulp = -cdyzm*DBLE(1/dyzp)
+ chulp = -cdyzm*Re(1/dyzp)
chulp1 = 1+chulp
if ( absc(chulp1) .lt. xloss )
+ call ffwarn(129,ier,absc(chulp1),1D0)
call ffxclg(clogi(1),ilogi(1),chulp,chulp1,dyzp,
+ ier)
endif
endif
endif
* #] log(1) for npoin=4:
* #[ the log(lam) Si:
if ( .not.lsmug ) then
*
* Next the divergent S_i (easy).
* The term -2*log(lam/lamsq)*log(xpi(2)/xpi(1)) has been discarded
* with lam the photon mass (regulator).
* If lamsq = sqrt(xpi(1)*xpi(2)) the terms cancel as well
*
if ( dpipj(1,2).ne.0 .and. xloss*abs(xpi(1)*xpi(2)-lamsq**2)
+ .gt.precx*lamsq**2 ) then
if ( xpi(1) .ne. lamsq ) then
ier0 = ier
if ( xpi(1).eq.0 ) call fferr(97,ier)
cs(9) = -zxfflg(xpi(1)/lamsq,0,0D0,ier0)**2 /4
endif
if ( xpi(2) .ne. lamsq ) then
ier0 = ier
if ( xpi(2).eq.0 ) call fferr(97,ier)
cs(10) = zxfflg(xpi(2)/lamsq,0,0D0,ier0)**2 /4
endif
endif
* #] the log(lam) Si:
* #[ the logs for A_i<0:
if ( npoin.eq.4 ) then
clogi(2) = 0
ilogi(2) = 0
clogi(3) = 0
ilogi(3) = 0
endif
* #] the logs for A_i<0:
* #[ the off-shell S3:
else
*
* the divergent terms in the offshell regulator scheme - not
* quite as easy
* wm = p3.p2/sqrtdel - 1 = -s1.s2/sqrtdel - 1
* wp = p3.p2/sqrtdel + 1 = -s1.s2/sqrtdel + 1
* Note that we took the choice sdel2<0 in S1 when
* \delta^{p1 s2}_{p1 p2} < 0 by using yp=zm
*
wm = -1 - piDpj(1,2)/sdel2
wp = wm + 2
if ( abs(wm) .lt. abs(wp) ) then
wm = -xpi(5)*xpi(6)/(del2*wp)
else
wp = -xpi(5)*xpi(6)/(del2*wm)
endif
*
* the im sign
*
- if ( -DBLE(cmipj(1,3)) .gt. 0 ) then
+ if ( -Re(cmipj(1,3)) .gt. 0 ) then
ieps = -1
else
ieps = +1
endif
*
- if ( nschem .lt. 3 .or. DIMAG(cmipj(1,3)).eq.0 .and.
- + DIMAG(cmipj(2,2)).eq.0 ) then
+ if ( nschem .lt. 3 .or. Im(cmipj(1,3)).eq.0 .and.
+ + Im(cmipj(2,2)).eq.0 ) then
* #[ real case:
*
* first z-,z+
*
- dyzp = -DBLE(cmipj(1,3))*DBLE(wm)/(2*DBLE(xpi(6))) -
- + DBLE(cmipj(2,2))/(2*DBLE(sdel2))
- dyzm = -DBLE(cmipj(1,3))*DBLE(wp)/(2*DBLE(xpi(6))) -
- + DBLE(cmipj(2,2))/(2*DBLE(sdel2))
+ dyzp = -Re(cmipj(1,3))*Re(wm)/(2*Re(xpi(6))) -
+ + Re(cmipj(2,2))/(2*Re(sdel2))
+ dyzm = -Re(cmipj(1,3))*Re(wp)/(2*Re(xpi(6))) -
+ + Re(cmipj(2,2))/(2*Re(sdel2))
*
* the (di)logs
*
clog1 = zxfflg(-dyzp,-ieps,1D0,ier)
cs(10) = -clog1**2/2
ipi12 = ipi12 - 4
clog2 = zxfflg(-dyzm,+ieps,1D0,ier)
cs(11) = -clog2**2/2
ipi12 = ipi12 - 2
hulp = dyzp/dyzm
if ( dyzp .lt. 0 ) then
ieps1 = -ieps
else
ieps1 = +ieps
endif
call ffzxdl(cli,i,cdum(1),hulp,+ieps1,ier)
cs(12) = -cli
ipi12 = ipi12 - i
*
* the log for npoin=4
*
if ( npoin.eq.4 ) then
if ( ilogi(3) .eq. -999 ) then
- if ( DBLE(cmipj(1,3)) .eq. 0 ) then
+ if ( Re(cmipj(1,3)) .eq. 0 ) then
chulp = -1
chulp1 = 0
elseif ( dyzp .lt. dyzm ) then
chulp = -dyzm/dyzp
- chulp1 = +DBLE(cmipj(1,3))/DBLE(xpi(6)*dyzp)
+ chulp1 = +Re(cmipj(1,3))/Re(xpi(6)*dyzp)
else
chulp = -dyzp/dyzm
- chulp1 = -DBLE(cmipj(1,3))/DBLE(xpi(6)*dyzm)
+ chulp1 = -Re(cmipj(1,3))/Re(xpi(6)*dyzm)
endif
call ffxclg(clogi(3),ilogi(3),chulp,chulp1,dyzp,
+ ier)
endif
endif
* #] real case:
else
* #[ complex case:
*
* first z+
*
- cdyzp = -cmipj(1,3)*DBLE(wm)/(2*DBLE(xpi(6))) -
- + cmipj(2,2)/(2*DBLE(sdel2))
+ cdyzp = -cmipj(1,3)*Re(wm)/(2*Re(xpi(6))) -
+ + cmipj(2,2)/(2*Re(sdel2))
clog1 = zfflog(-cdyzp,-ieps,cone,ier)
- if ( ieps*DIMAG(cdyzp).lt.0.and.DBLE(cdyzp).gt.0 ) then
+ if ( ieps*Im(cdyzp).lt.0 .and. Re(cdyzp).gt.0 ) then
clog1 = clog1 - ieps*c2ipi
endif
cs(10) = -clog1**2/2
ipi12 = ipi12 - 4
*
* now z-
*
- cdyzm = -cmipj(1,3)*DBLE(wp)/(2*DBLE(xpi(6))) -
- + cmipj(2,2)/(2*DBLE(sdel2))
+ cdyzm = -cmipj(1,3)*Re(wp)/(2*Re(xpi(6))) -
+ + cmipj(2,2)/(2*Re(sdel2))
clog2 = zfflog(-cdyzm,+ieps,cone,ier)
- if ( ieps*DIMAG(cdyzm).gt.0.and.DBLE(cdyzm).gt.0 ) then
+ if ( ieps*Im(cdyzm).gt.0 .and. Re(cdyzm).gt.0 ) then
clog2 = clog2 + ieps*c2ipi
endif
cs(11) = -clog2**2/2
ipi12 = ipi12 - 2
*
* the dilog
*
chulp = cdyzp/cdyzm
- hulp = DBLE(cdyzp)/DBLE(cdyzm)
- if ( DBLE(cdyzp) .lt. 0 ) then
+ hulp = Re(cdyzp)/Re(cdyzm)
+ if ( Re(cdyzp) .lt. 0 ) then
ieps1 = -ieps
else
ieps1 = +ieps
endif
- if ( DIMAG(chulp) .eq. 0 ) then
- hulp = DBLE(chulp)
+ if ( Im(chulp) .eq. 0 ) then
+ hulp = Re(chulp)
call ffzxdl(cli,i,cdum(1),hulp,+ieps1,ier)
else
call ffzzdl(cli,i,cdum(1),chulp,ier)
- if ( hulp.gt.1 .and. ieps1*DIMAG(chulp).lt.0 ) then
+ if ( hulp.gt.1 .and. ieps1*Im(chulp).lt.0 ) then
cli = cli + ieps1*c2ipi*zfflog(chulp,0,czero,ier)
endif
endif
cs(12) = -cli
ipi12 = ipi12 - i
*
* the log for npoin=4
*
if ( npoin.eq.4 ) then
if ( ilogi(3) .eq. -999 ) then
if ( cmipj(1,3) .eq. 0 ) then
chulp = -1
chulp1 = 0
- elseif ( DBLE(cdyzp) .lt. DBLE(cdyzm) ) then
+ elseif ( Re(cdyzp) .lt. Re(cdyzm) ) then
chulp = -cdyzm/cdyzp
- chulp1 = +cmipj(1,3)/cdyzp*DBLE(1/xpi(6))
+ chulp1 = +cmipj(1,3)/cdyzp*Re(1/xpi(6))
else
chulp = -cdyzp/cdyzm
- chulp1 = -cmipj(1,3)/cdyzm*DBLE(1/xpi(6))
+ chulp1 = -cmipj(1,3)/cdyzm*Re(1/xpi(6))
endif
- dyzp = DBLE(cdyzp)
+ dyzp = Re(cdyzp)
call ffxclg(clogi(3),ilogi(3),chulp,chulp1,dyzp,
+ ier)
endif
endif
* #] complex case:
endif
* #] the off-shell S3:
* #[ the off-shell S2:
*
* the im sign
*
- if ( -DBLE(cmipj(2,2)) .gt. 0 ) then
+ if ( -Re(cmipj(2,2)) .gt. 0 ) then
ieps = -1
else
ieps = +1
endif
*
if ( nschem .lt. 3 ) then
* #[ real case:
*
* first z-
*
- dyzm = -DBLE(cmipj(2,2))*DBLE(wp)/(2*DBLE(xpi(5))) -
- + DBLE(cmipj(1,3))/(2*DBLE(sdel2))
+ dyzm = -Re(cmipj(2,2))*Re(wp)/(2*Re(xpi(5))) -
+ + Re(cmipj(1,3))/(2*Re(sdel2))
clog1 = zxfflg(+dyzm,-ieps,1D0,ier)
cs(13) = +clog1**2/2
ipi12 = ipi12 + 4
*
* now z+
*
- dyzp = -DBLE(cmipj(2,2))*DBLE(wm)/(2*DBLE(xpi(5))) -
- + DBLE(cmipj(1,3))/(2*DBLE(sdel2))
+ dyzp = -Re(cmipj(2,2))*Re(wm)/(2*Re(xpi(5))) -
+ + Re(cmipj(1,3))/(2*Re(sdel2))
clog2 = zxfflg(+dyzp,+ieps,1D0,ier)
cs(14) = +clog2**2/2
ipi12 = ipi12 + 2
hulp = dyzm/dyzp
if ( dyzm .lt. 0 ) then
ieps1 = -ieps
else
ieps1 = +ieps
endif
call ffzxdl(cli,i,cdum(1),hulp,-ieps1,ier)
cs(15) = +cli
ipi12 = ipi12 + i
*
* the log for npoin=4
*
if ( npoin.eq.4 ) then
if ( ilogi(2) .eq. -999 ) then
- if ( DBLE(cmipj(2,2)) .eq. 0 ) then
+ if ( Re(cmipj(2,2)) .eq. 0 ) then
chulp = -1
chulp1 = 0
elseif ( dyzp .lt. dyzm ) then
chulp = -dyzm/dyzp
- chulp1 = +DBLE(cmipj(2,2))/DBLE(xpi(5)*dyzp)
+ chulp1 = +Re(cmipj(2,2))/Re(xpi(5)*dyzp)
elseif ( dyzp .gt. dyzm ) then
chulp = -dyzp/dyzm
- chulp1 = -DBLE(cmipj(2,2))/DBLE(xpi(5)*dyzm)
+ chulp1 = -Re(cmipj(2,2))/Re(xpi(5)*dyzm)
endif
call ffxclg(clogi(2),ilogi(2),chulp,chulp1,dyzp,
+ ier)
endif
endif
* #] real case:
else
* #[ complex case:
*
* first z-
*
- cdyzm = -cmipj(2,2)*DBLE(wp)/(2*DBLE(xpi(5))) -
- + cmipj(1,3)/(2*DBLE(sdel2))
+ cdyzm = -cmipj(2,2)*Re(wp)/(2*Re(xpi(5))) -
+ + cmipj(1,3)/(2*Re(sdel2))
clog1 = zfflog(+cdyzm,-ieps,cone,ier)
- if ( DBLE(cdyzm).lt.0.and.ieps*DIMAG(cdyzm).gt.0 ) then
+ if ( Re(cdyzm).lt.0.and.ieps*Im(cdyzm).gt.0 ) then
clog1 = clog1 - ieps*c2ipi
endif
cs(13) = +clog1**2/2
ipi12 = ipi12 + 4
*
* now z+
*
- cdyzp = -cmipj(2,2)*DBLE(wm)/(2*DBLE(xpi(5))) -
- + cmipj(1,3)/(2*DBLE(sdel2))
+ cdyzp = -cmipj(2,2)*Re(wm)/(2*Re(xpi(5))) -
+ + cmipj(1,3)/(2*Re(sdel2))
clog2 = zfflog(+cdyzp,+ieps,cone,ier)
- if ( DBLE(cdyzp).lt.0.and.ieps*DIMAG(cdyzp).lt.0 ) then
+ if ( Re(cdyzp).lt.0.and.ieps*Im(cdyzp).lt.0 ) then
clog2 = clog2 + ieps*c2ipi
endif
cs(14) = +clog2**2/2
ipi12 = ipi12 + 2
*
* and ghe dilog
*
chulp = cdyzm/cdyzp
- hulp = DBLE(dyzm)/DBLE(dyzp)
- if ( DBLE(cdyzm) .lt. 0 ) then
+ hulp = Re(dyzm)/Re(dyzp)
+ if ( Re(cdyzm) .lt. 0 ) then
ieps1 = -ieps
else
ieps1 = +ieps
endif
- if ( DIMAG(chulp ) .eq. 0 ) then
- hulp = DBLE(chulp)
+ if ( Im(chulp ) .eq. 0 ) then
+ hulp = Re(chulp)
call ffzxdl(cli,i,cdum(1),hulp,-ieps1,ier)
else
call ffzzdl(cli,i,cdum(1),chulp,ier)
- if ( hulp.gt.1 .and. ieps1*DIMAG(chulp).gt.0 ) then
+ if ( hulp.gt.1 .and. ieps1*Im(chulp).gt.0 ) then
cli = cli - ieps1*c2ipi*zfflog(chulp,0,czero,ier)
endif
endif
cs(15) = +cli
ipi12 = ipi12 + i
*
* the log for npoin=4
*
if ( npoin.eq.4 ) then
if ( ilogi(2) .eq. -999 ) then
if ( cmipj(2,2) .eq. 0 ) then
chulp = -1
chulp1 = 0
- elseif ( DBLE(cdyzp) .lt. DBLE(cdyzm) ) then
+ elseif ( Re(cdyzp) .lt. Re(cdyzm) ) then
chulp = -cdyzm/cdyzp
- chulp1 = +cmipj(2,2)/cdyzp*DBLE(1/xpi(5))
- elseif ( DBLE(cdyzp) .gt. DBLE(cdyzm) ) then
+ chulp1 = +cmipj(2,2)/cdyzp*Re(1/xpi(5))
+ elseif ( Re(cdyzp) .gt. Re(cdyzm) ) then
chulp = -cdyzp/cdyzm
- chulp1 = -cmipj(2,2)/cdyzm*DBLE(1/xpi(5))
+ chulp1 = -cmipj(2,2)/cdyzm*Re(1/xpi(5))
endif
- dyzp = DBLE(cdyzp)
+ dyzp = Re(cdyzp)
call ffxclg(clogi(2),ilogi(2),chulp,chulp1,dyzp,
+ ier)
endif
endif
* #] complex case:
endif
endif
* #] the off-shell S2:
* #[ sdel2<0!:
if ( sdel2i.gt.0 .neqv. xpi(4).eq.0.and.xpi(1).gt.xpi(2) ) then
if ( .not.lsmug ) then
n = 10
else
n = 15
endif
do 10 i=1,n
cs(i) = -cs(i)
10 continue
ipi12 = -ipi12
if ( npoin.eq.4 ) then
do 20 i=1,3
ilogi(i) = -ilogi(i)
clogi(i) = -clogi(i)
20 continue
endif
endif
* #] sdel2<0!:
*###] ffxc0j:
end
*###[ ffxclg:
subroutine ffxclg(clg,ilg,chulp,chulp1,dyzp,ier)
***#[*comment:***********************************************************
* *
* compute the extra logs for npoin=4 given chulp=-cdyzm/cdyzp *
* all flagchecking has already been done. *
* *
* Input: chulp (complex) see above *
* chulp1 (complex) 1+chulp (in case chulp ~ -1) *
* dyzp (real) (real part of) y-z+ for im part *
* Output: clg (complex) the log *
* ilg (integer) factor i*pi split off clg *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ilg,ier
- DOUBLE PRECISION dyzp
- DOUBLE COMPLEX clg,chulp,chulp1
+ RealType dyzp
+ ComplexType clg,chulp,chulp1
*
* local variables
*
- DOUBLE PRECISION hulp,hulp1,dfflo1
- DOUBLE COMPLEX zxfflg,zfflog,zfflo1
+ RealType hulp,hulp1,dfflo1
+ ComplexType zxfflg,zfflog,zfflo1
external dfflo1,zxfflg,zfflog,zfflo1
*
* common blocks
*
#include "ff.h"
*
* #] declarations:
* #[ work:
*
- if ( DIMAG(chulp) .eq. 0 ) then
- hulp = DBLE(chulp)
- hulp1 = DBLE(chulp1)
+ if ( Im(chulp) .eq. 0 ) then
+ hulp = Re(chulp)
+ hulp1 = Re(chulp1)
if ( abs(hulp1) .lt. xloss ) then
- clg = DBLE(dfflo1(hulp1,ier))
+ clg = Re(dfflo1(hulp1,ier))
else
clg = zxfflg(abs(hulp),0,0D0,ier)
endif
if ( hulp .lt. 0 ) then
if ( dyzp.lt.0 ) then
ilg = +1
else
ilg = -1
endif
else
ilg = 0
endif
else
*
* may have to be improved
*
- if ( abs(DBLE(chulp1))+abs(DIMAG(chulp1)) .lt. xloss ) then
+ if ( abs(Re(chulp1))+abs(Im(chulp1)) .lt. xloss ) then
clg = zfflo1(chulp1,ier)
else
clg = zfflog(chulp,0,czero,ier)
endif
ilg = 0
- if ( DBLE(chulp) .lt. 0 ) then
- if ( dyzp.lt.0 .and. DIMAG(clg).lt.0 ) then
+ if ( Re(chulp) .lt. 0 ) then
+ if ( dyzp.lt.0 .and. Im(clg).lt.0 ) then
ilg = +2
- elseif ( dyzp.gt.0 .and. DIMAG(clg).gt.0 ) then
+ elseif ( dyzp.gt.0 .and. Im(clg).gt.0 ) then
ilg = -2
endif
endif
endif
* #] work:
*###] ffxclg:
end
diff --git a/Looptools/C/ffxc0p.F b/Looptools/C/ffxc0p.F
--- a/Looptools/C/ffxc0p.F
+++ b/Looptools/C/ffxc0p.F
@@ -1,510 +1,511 @@
#include "externals.h"
+#include "types.h"
* $Id: ffxc0p.f,v 1.3 1995/10/06 09:17:26 gj Exp $
* $Log: ffxc0p.f,v $
c Revision 1.3 1995/10/06 09:17:26 gj
c Found stupid typo in ffxc0p which caused the result to be off by pi^2/3 in
c some equal-mass cases. Added checks to ffcxs4.f ffcrr.f.
c
*###[ ffxc0p:
subroutine ffxc0p(cs3,ipi12,isoort,clogi,ilogi,xpi,dpipj,piDpj,
+ sdel2,del2s,etalam,etami,delpsi,alph,npoin,ier)
***#[*comment:***********************************************************
* *
* calculates the threepoint function closely following *
* recipe in 't Hooft & Veltman, NP B(183) 1979. *
* Bjorken and Drell metric is used nowadays! *
* *
* p2 ^ | *
* | | *
* / \ *
* m2/ \m3 *
* p1 / \ p3 *
* <- / m1 \ -> *
* ------------------------ *
* *
* Input: xpi(1-3) (real) pi squared *
* xpi(4-6) (real) internal mass squared *
* dpipj(6,6) (real) xpi(i)-xpi(j) *
* piDpj(6,6) (real) pi(i).pi(j) *
* sdel2 (real) sqrt(delta_{p_1 p_2}^{p_1 p_2}) *
* del2s(3) (real) delta_{p_i s_i}^{p_i s_i} *
* etalam (real) delta_{s_1 s_2 s_3}^{s_1 s_2 s_3}
* /delta_{p_1 p_2}^{p_1 p_2} *
* etami(6) (real) m_i^2 - etalam *
* alph(3) (real) alph(1)=alpha, alph(3)=1-alpha *
* *
* Output: cs3(80) (complex) C0, not yet summed. *
* ipi12(8) (integer) factors pi^2/12, not yet summed *
* slam (complex) lambda(p1,p2,p3). *
* isoort(8) (integer) indication of he method used *
* clogi(3) (complex) log(-dyz(2,1,i)/dyz(2,2,i)) *
* ilogi(3) (integer) factors i*pi in this *
* ier (integer) number of digits inaccurate in *
* answer *
* *
* Calls: ffroot,ffxxyz,ffcxyz,ffdwz,ffcdwz, *
* ffcxs3,ffcs3,ffcxs4,ffcs4 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ipi12(8),isoort(8),ilogi(3),npoin,ier
- DOUBLE COMPLEX cs3(80),clogi(3)
- DOUBLE PRECISION xpi(6),dpipj(6,6),piDpj(6,6),sdel2,del2s(3),
+ ComplexType cs3(80),clogi(3)
+ RealType xpi(6),dpipj(6,6),piDpj(6,6),sdel2,del2s(3),
+ etalam,etami(6),delpsi(3),alph(3)
*
* local variables:
*
integer i,j,k,m,ip,jsoort(8),ierw,iw,ier0,ier1,irota,
+ ilogip(3)
logical l4,lcompl,lcpi,l4pos
- DOUBLE COMPLEX c,cs,calph(3),csdl2i(3),csdel2
- DOUBLE COMPLEX cy(4,3),cz(4,3),cw(4,3),cdyz(2,2,3),cdwy(2,2,3),
+ ComplexType c,cs,calph(3),csdl2i(3),csdel2
+ ComplexType cy(4,3),cz(4,3),cw(4,3),cdyz(2,2,3),cdwy(2,2,3),
+ cdwz(2,2,3),cd2yzz(3),cd2yww(3)
- DOUBLE COMPLEX cpi(6),cdpipj(6,6),cpiDpj(6,6),clogip(3)
- DOUBLE PRECISION y(4,3),z(4,3),w(4,3),dyz(2,2,3),dwy(2,2,3),
+ ComplexType cpi(6),cdpipj(6,6),cpiDpj(6,6),clogip(3)
+ RealType y(4,3),z(4,3),w(4,3),dyz(2,2,3),dwy(2,2,3),
+ dwz(2,2,3),d2yzz(3),d2yww(3),dy2z(4,3)
- DOUBLE PRECISION sdel2i(3),s1,s2
- DOUBLE PRECISION absc,s,xqi(6),dqiqj(6,6),qiDqj(6,6)
- DOUBLE PRECISION dfflo1
- DOUBLE COMPLEX zxfflg
+ RealType sdel2i(3),s1,s2
+ RealType absc,s,xqi(6),dqiqj(6,6),qiDqj(6,6)
+ RealType dfflo1
+ ComplexType zxfflg
external dfflo1,zxfflg
*
* common blocks:
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ IR case:
*
* but only the off-shell regulator case - the log(lam) has been
* caught before
*
if ( lsmug ) then
do 5 i=1,3
if ( xpi(i) .eq. 0 ) then
j = mod(i,3)+1
k = mod(j,3)+1
if ( piDpj(i,j).eq.0 .and. piDpj(i,k).eq.0 ) then
call ffrot3(irota,xqi,dqiqj,qiDqj,
+ xpi,dpipj,piDpj,3,4,ier)
if ( npoin.eq.4 ) call ffrt3p(clogip,ilogip,
+ irota,clogi,ilogi,+1)
call ffxc0j(cs3(1),ipi12(1),sdel2,clogip,ilogip,
+ xqi,dqiqj,qiDqj,0D0,4,ier)
if ( npoin.eq.4 ) call ffrt3p(clogi,ilogi,irota,
+ clogip,ilogip,-1)
return
endif
endif
5 continue
endif
* #] IR case:
* #[ get roots etc:
* #[ get z-roots:
* if ( npoin .eq. 3 ) then
l4pos = l4also
* else
* l4pos = .FALSE.
* endif
lcompl = .FALSE.
ier1 = ier
do 10 i=1,3
*
* get roots (y,z,w) and flag what to do: 0=nothing, 1=normal,
* -1=complex
*
ip = i+3
* first get the roots
ier0 = ier
if ( del2s(i) .le. 0 ) then
* real case
sdel2i(i) = sqrt(-del2s(i))
csdl2i(i) = sdel2i(i)
* then handle the special case Si = 0
if ( xpi(ip) .eq. 0 ) then
if ( i .eq. 1 .and. alph(3) .eq. 0 .or.
+ i .eq. 3 .and. alph(1) .eq. 0 ) then
isoort(2*i-1) = 0
isoort(2*i) = 0
l4pos = .FALSE.
goto 10
endif
endif
call ffxxyz(y(1,i),z(1,i),dyz(1,1,i),d2yzz(i),dy2z(1,i),
+ i,sdel2,sdel2i(i),etalam,etami,delpsi(i),xpi,
+ dpipj,piDpj,isoort(2*i-1),.FALSE.,6,ier0)
else
* complex case
sdel2i(i) = sqrt(del2s(i))
- csdl2i(i) = DCMPLX(0D0,sdel2i(i))
+ csdl2i(i) = ToComplex(0D0,sdel2i(i))
lcompl = .TRUE.
call ffcxyz(cy(1,i),cz(1,i),cdyz(1,1,i),cd2yzz(i),i,
+ sdel2,sdel2i(i),etami,delpsi(i),xpi,
+ piDpj,isoort(2*i-1),.FALSE.,6,ier0)
endif
ier1 = max(ier1,ier0)
10 continue
ier = ier1
* #] get z-roots:
* #[ get w-roots:
*
* get w's:
*
ierw = ier
l4 = .FALSE.
lcpi = .FALSE.
if ( isoort(4) .eq. 0 ) then
* no error message; just bail out
ierw = ierw + 100
goto 90
endif
do 70 iw = 1,3,2
if ( .not. l4pos .or. alph(4-iw) .eq. 0 ) then
jsoort(2*iw-1) = 0
jsoort(2*iw) = 0
l4pos = .FALSE.
else
if ( isoort(4) .gt. 0 .and. isoort(2*iw) .ge. 0 ) then
jsoort(2*iw-1) = 1
jsoort(2*iw) = 1
d2yww(iw) = -d2yzz(2)/alph(4-iw)
do 20 j=1,2
w(j+iw-1,iw) = z(j+3-iw,2)/alph(4-iw)
w(j+3-iw,iw) = 1 - w(j+iw-1,iw)
if ( abs(w(j+3-iw,iw)) .lt. xloss ) then
s = z(j+iw-1,2) - alph(iw)
if ( abs(s) .lt. xloss*alph(iw) ) then
ierw = ierw + 15
goto 70
endif
w(j+3-iw,iw) = s/alph(4-iw)
endif
dwy(j,2,iw) = dyz(2,j,2)/alph(4-iw)
do 15 i=1,2
dwz(j,i,iw) = w(j,iw) - z(i,iw)
if ( abs(dwz(j,i,iw)) .ge. xloss*abs(w(j,iw)) )
+ goto 14
dwz(j,i,iw) = z(i+2,iw) - w(j+2,iw)
if ( abs(dwz(j,i,iw)) .ge. xloss*abs(w(j+2,iw)) )
+ goto 14
dwz(j,i,iw) = dwy(j,2,iw) + dyz(2,i,iw)
if ( abs(dwz(j,i,iw)) .ge. xloss*abs(dwy(j,2,iw)) )
+ goto 14
l4 = .TRUE.
call ffdwz(dwz(1,1,iw),z(1,iw),j,i,iw,
+ alph(1),alph(3),xpi,dpipj,piDpj,sdel2i,6,ierw)
14 continue
15 continue
20 continue
else
* convert to complex ...
jsoort(2*iw-1) = -10
jsoort(2*iw) = -10
if ( isoort(4).ge.0 .and. (iw.eq.1 .or. isoort(2).ge.0) )
+ then
cd2yzz(2) = d2yzz(2)
do 21 i=1,4
cy(i,2) = y(i,2)
cz(i,2) = z(i,2)
21 continue
do 23 i=1,2
do 22 j=1,2
cdyz(j,i,2) = dyz(j,i,2)
22 continue
23 continue
endif
if ( isoort(2*iw) .ge. 0 ) then
cd2yzz(iw) = d2yzz(iw)
do 24 i=1,4
cy(i,iw) = y(i,iw)
cz(i,iw) = z(i,iw)
24 continue
do 26 i=1,2
do 25 j=1,2
cdyz(j,i,iw) = dyz(j,i,iw)
25 continue
26 continue
endif
- cd2yww(iw) = -cd2yzz(2)/DBLE(alph(4-iw))
+ cd2yww(iw) = -cd2yzz(2)/Re(alph(4-iw))
do 30 j=1,2
- cw(j+iw-1,iw) = cz(j+3-iw,2)/DBLE(alph(4-iw))
+ cw(j+iw-1,iw) = cz(j+3-iw,2)/Re(alph(4-iw))
cw(j+3-iw,iw) = 1 - cw(j+iw-1,iw)
if ( absc(cw(j+3-iw,iw)) .lt. xloss ) then
- cs = cz(j+iw-1,2) - DBLE(alph(iw))
+ cs = cz(j+iw-1,2) - Re(alph(iw))
if ( absc(cs) .lt. xloss*alph(iw) ) ierw = ierw + 15
- cw(j+3-iw,iw) = cs/DBLE(alph(4-iw))
+ cw(j+3-iw,iw) = cs/Re(alph(4-iw))
endif
- cdwy(j,2,iw) = cdyz(2,j,2)/DBLE(alph(4-iw))
+ cdwy(j,2,iw) = cdyz(2,j,2)/Re(alph(4-iw))
do 29 i=1,2
cdwz(j,i,iw) = cw(j,iw) - cz(i,iw)
if ( absc(cdwz(j,i,iw)) .ge. xloss*absc(cw(j,iw)) )
+ goto 31
cdwz(j,i,iw) = cz(i+2,iw) - cw(j+2,iw)
if ( absc(cdwz(j,i,iw)) .ge. xloss*absc(cw(j+2,iw)))
+ goto 31
cdwz(j,i,iw) = cdwy(j,2,iw) + cdyz(2,i,iw)
if ( absc(cdwz(j,i,iw)).ge.xloss*absc(cdwy(j,2,iw)))
+ goto 31
l4 = .TRUE.
if ( .not. lcpi ) then
lcpi = .TRUE.
calph(1) = alph(1)
calph(3) = alph(3)
csdel2 = sdel2
do 28 k=1,6
cpi(k) = xpi(k)
do 27 m=1,6
cdpipj(m,k) = dpipj(m,k)
cpiDpj(m,k) = piDpj(m,k)
27 continue
28 continue
endif
call ffcdwz(cdwz(1,1,iw),cz(1,iw),j,i,iw,
+ calph(1),calph(3),cpi,cdpipj,cpiDpj,csdl2i,
+ csdel2,6,ierw)
31 continue
29 continue
30 continue
endif
endif
70 continue
90 continue
ierw = ierw-ier
* #] get w-roots:
* #[ which case:
if ( l4 ) then
* 21-aug-1995. added check for isoort(2*i-1).eq.0 to avoid
* undefined variables etc in ffdcs, ffdcrr. They should be
* able to handle this, but are not (yet?)
if ( ierw .ge. 1 .or. isoort(1).eq.0 .or. isoort(3).eq.0
+ .or. isoort(5).eq.0 ) then
l4pos = .FALSE.
else
ier = ier + ierw
endif
endif
* #] which case:
* #] get roots etc:
* #[ logarithms for 4point function:
if ( npoin .eq. 4 ) then
do 95 i = 1,3
if ( ilogi(i) .ne. -999 ) goto 95
if ( isoort(2*i) .gt. 0 .and.
+ isoort(2*i-1) .ge. 0 ) then
s1 = -dyz(2,1,i)/dyz(2,2,i)
if ( abs(s1-1) .lt. xloss ) then
clogi(i) = dfflo1(d2yzz(i)/dyz(2,2,i),ier)
ilogi(i) = 0
else
if ( abs(s1+1) .lt. xloss ) then
clogi(i) = dfflo1(-2*sdel2i(i)/(xpi(i+3)*
+ dyz(2,2,i)),ier)
else
clogi(i) = zxfflg(abs(s1),0,0D0,ier)
endif
if ( dyz(2,2,i).gt.0 .and. dyz(2,1,i).gt.0 ) then
ilogi(i) = -1
elseif ( dyz(2,1,i).lt.0 .and. dyz(2,2,i).lt.0) then
ilogi(i) = +1
else
ilogi(i) = 0
endif
endif
elseif ( isoort(2*i-1) .lt. 0 ) then
* for stability split the unit circle up in 4*pi/2
* (this may have to be improved to 8*pi/4...)
ier0 = 0
- if ( DBLE(cdyz(2,1,i)) .gt. DIMAG(cdyz(2,1,i)) ) then
- s = 2*atan2(DIMAG(cdyz(2,1,i)),DBLE(cdyz(2,1,i)))
- clogi(i) = DCMPLX(0D0,s)
+ if ( Re(cdyz(2,1,i)) .gt. Im(cdyz(2,1,i)) ) then
+ s = 2*atan2(Im(cdyz(2,1,i)),Re(cdyz(2,1,i)))
+ clogi(i) = ToComplex(0D0,s)
ilogi(i) = -1
- elseif ( DBLE(cdyz(2,1,i)) .lt. -DIMAG(cdyz(2,1,i)))
+ elseif ( Re(cdyz(2,1,i)) .lt. -Im(cdyz(2,1,i)))
+ then
- if ( DIMAG(cdyz(2,1,i)) .eq. 0 ) then
+ if ( Im(cdyz(2,1,i)) .eq. 0 ) then
call fferr(84,ier)
endif
- s = 2*atan2(-DIMAG(cdyz(2,1,i)),-DBLE(cdyz(2,1,i)))
- clogi(i) = DCMPLX(0D0,s)
+ s = 2*atan2(-Im(cdyz(2,1,i)),-Re(cdyz(2,1,i)))
+ clogi(i) = ToComplex(0D0,s)
ilogi(i) = 1
else
- s1 = -DBLE(cdyz(2,1,i))
- s2 = DIMAG(cdyz(2,1,i))
+ s1 = -Re(cdyz(2,1,i))
+ s2 = Im(cdyz(2,1,i))
s = 2*atan2(s1,s2)
- clogi(i) = DCMPLX(0D0,s)
+ clogi(i) = ToComplex(0D0,s)
ilogi(i) = 0
endif
endif
95 continue
* An algorithm to obtain the sum of two small logarithms more
* accurately has been put in ffcc0p, not yet here
endif
* #] logarithms for 4point function:
* #[ real case integrals:
ier1 = ier
if ( .not. lcompl ) then
if ( .not. l4 .or. .not. l4pos ) then
* normal case
do 100 i=1,3
j = 2*i-1
if ( isoort(j) .ne. 0 ) then
ier0 = ier
call ffcxs3(cs3(20*i-19),ipi12(j),y(1,i),z(1,i),
+ dyz(1,1,i),d2yzz(i),dy2z(1,i),xpi,piDpj,
+ i,6,isoort(j),ier0)
ier1 = max(ier1,ier0)
endif
100 continue
isoort(7) = 0
isoort(8) = 0
else
do 110 i=1,3,2
j = 2*i-1
isoort(j+2) = jsoort(j)
isoort(j+3) = jsoort(j+1)
ier0 = ier
call ffcxs4(cs3(20*i-19),ipi12(j),w(1,i),y(1,i),
+ z(1,i),dwy(1,1,i),dwz(1,1,i),dyz(1,1,i),
+ d2yww(i),d2yzz(i),xpi,piDpj,i,6,isoort(j),ier0)
ier1 = max(ier1,ier0)
110 continue
endif
* #] real case integrals:
* #[ complex case integrals:
else
* convert xpi
if ( .not.lcpi ) then
do 190 i=1,6
cpi(i) = xpi(i)
190 continue
endif
if ( .not. l4 .or. .not. l4pos ) then
* normal case
do 200 i=1,3
j = 2*i-1
ier0 = ier
if ( isoort(j) .gt. 0 ) then
call ffcxs3(cs3(20*i-19),ipi12(2*i-1),y(1,i),
+ z(1,i),dyz(1,1,i),d2yzz(i),dy2z(1,i),
+ xpi,piDpj,i,6,isoort(j),ier0)
elseif( isoort(j) .ne. 0 ) then
call ffcs3(cs3(20*i-19),ipi12(2*i-1),cy(1,i),
+ cz(1,i),cdyz(1,1,i),cd2yzz(i),cpi,
+ cpiDpj,i,6,isoort(j),ier0)
endif
ier1 = max(ier1,ier0)
200 continue
isoort(7) = 0
isoort(8) = 0
else
isoort(3) = jsoort(1)
isoort(4) = jsoort(2)
ier0 = ier
if ( isoort(1) .gt. 0 .and. isoort(3) .gt. 0 ) then
call ffcxs4(cs3(1),ipi12(1),w(1,1),y(1,1),
+ z(1,1),dwy(1,1,1),dwz(1,1,1),dyz(1,1,1),
+ d2yww(1),d2yzz(1),xpi,piDpj,1,6,isoort(1),ier0)
else
call ffcs4(cs3(1),ipi12(1),cw(1,1),cy(1,1),
+ cz(1,1),cdwy(1,1,1),cdwz(1,1,1),cdyz(1,1,1),
+ cd2yww(1),cd2yzz(1),cpi,cpiDpj,
- + DCMPLX(xpi(5)*alph(3)**2),1,6,isoort(1),
+ + ToComplex(xpi(5)*alph(3)**2),1,6,isoort(1),
+ ier0)
endif
ier1 = max(ier1,ier0)
isoort(7) = jsoort(5)
isoort(8) = jsoort(6)
ier0 = ier
if ( isoort(5) .gt. 0 .and. isoort(7) .gt. 0 ) then
call ffcxs4(cs3(41),ipi12(5),w(1,3),y(1,3),
+ z(1,3),dwy(1,1,3),dwz(1,1,3),dyz(1,1,3),
+ d2yww(3),d2yzz(3),xpi,piDpj,3,6,isoort(5),ier0)
else
call ffcs4(cs3(41),ipi12(5),cw(1,3),cy(1,3),
+ cz(1,3),cdwy(1,1,3),cdwz(1,1,3),cdyz(1,1,3),
+ cd2yww(3),cd2yzz(3),cpi,cpiDpj,
- + DCMPLX(xpi(5)*alph(1)**2),3,6,isoort(5),
+ + ToComplex(xpi(5)*alph(1)**2),3,6,isoort(5),
+ ier0)
endif
ier1 = max(ier1,ier0)
endif
endif
ier = ier1
* #] complex case integrals:
*###] ffxc0p:
end
*###[ ffrt3p:
subroutine ffrt3p(clogip,ilogip,irota,clogi,ilogi,idir)
***#[*comment:***********************************************************
* *
* rotates the arrays clogi,ilogi also over irota (idir=+1) or *
* back (-1) *
* *
* Input: irota (integer) index in rotation array *
* clogi(3) (complex) only if idir=-1 *
* ilogi(3) (integer) indicates which clogi are needed*
* (idir=+1), i*pi terms (idir=-1) *
* idir (integer) direction: forward (+1) or *
* backward (-1) *
* Output: clogip(3) (integer) clogi rotated *
* ilogip(3) (integer) ilogi rotated *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer irota,idir,ilogi(3),ilogip(3)
- DOUBLE COMPLEX clogi(3),clogip(3)
+ ComplexType clogi(3),clogip(3)
*
* local variables
*
integer i,inew(6,6)
save inew
*
* common blocks
*
#include "ff.h"
*
* data
*
data inew /1,2,3,4,5,6,
+ 2,3,1,5,6,4,
+ 3,1,2,6,4,5,
+ 1,3,2,6,5,4,
+ 3,2,1,5,4,6,
+ 2,1,3,4,6,5/
* #] declarations:
* #[ rotate:
*
* the clogi, ilogi are numbered according to the p_i
*
if ( idir .eq. +1 ) then
do 10 i=1,3
ilogip(inew(i+3,irota)-3) = ilogi(i)
clogip(inew(i+3,irota)-3) = clogi(i)
10 continue
else
do 20 i=1,3
ilogip(i) = ilogi(inew(i+3,irota)-3)
clogip(i) = clogi(inew(i+3,irota)-3)
20 continue
endif
*
* #] rotate:
*###] ffrt3p:
end
diff --git a/Looptools/C/ffxc0p0.F b/Looptools/C/ffxc0p0.F
--- a/Looptools/C/ffxc0p0.F
+++ b/Looptools/C/ffxc0p0.F
@@ -1,86 +1,87 @@
#include "externals.h"
+#include "types.h"
*###[ ffxc0p0
subroutine ffxc0p0(cc0, xpi)
***#[*comment:***********************************************************
* *
* C0 function for all three momenta^2 = 0 *
* input parameters as for ffxc0 *
* *
* original code from David Garcia *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE COMPLEX cc0
- DOUBLE PRECISION xpi(6)
+ ComplexType cc0
+ RealType xpi(6)
- DOUBLE PRECISION m1, m2, m3, m
+ RealType m1, m2, m3, m
#include "ff.h"
m1 = xpi(1)
m2 = xpi(2)
m3 = xpi(3)
* sort the masses such that m1 >= m2 >= m3
* this is important to avoid complex logs later
if( m1 .lt. m2 ) then
m = m2
m2 = m1
m1 = m
endif
if( m2 .lt. m3 ) then
m = m3
m3 = m2
m2 = m
endif
if( m1 .lt. m2 ) then
m = m2
m2 = m1
m1 = m
endif
m = (m1 + m2 + m3)*1D-6
if( m3 .gt. m ) then
* non-zero masses:
if( m2 - m3 .gt. m ) then
if( m1 - m2 .gt. m ) then
* m1 != m2 != m3
cc0 = (log(m3/m2) + m1/(m3 - m1)*log(m3/m1) -
& m1/(m2 - m1)*log(m2/m1))/(m2 - m3)
else
* m1 = m2 != m3
cc0 = (1 - m3/(m2 - m3)*log(m2/m3))/(m3 - m2)
endif
else
if( m1 - m2 .gt. m ) then
* m1 != m2 = m3
cc0 = (1 - m1/(m2 - m1)*log(m2/m1))/(m1 - m2)
else
* m1 = m2 = m3
cc0 = -.5D0/m1
endif
endif
else
* zero masses:
if( m1 - m2 .gt. m ) then
* m1 != m2, m3 = 0
cc0 = log(m2/m1)/(m1 - m2)
else
* m1 = m2, m3 = 0
cc0 = -1/m1
endif
endif
end
diff --git a/Looptools/COPYING.HwLooptools b/Looptools/COPYING.HwLooptools
--- a/Looptools/COPYING.HwLooptools
+++ b/Looptools/COPYING.HwLooptools
@@ -1,504 +1,165 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
- Preamble
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
+ 0. Additional Definitions.
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
+ 1. Exception to Section 3 of the GNU GPL.
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
+ 2. Conveying Modified Versions.
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+ 3. Object Code Incorporating Material from Library Header Files.
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
+ 4. Combined Works.
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
-
-
diff --git a/Looptools/D/D0.F b/Looptools/D/D0.F
deleted file mode 100644
--- a/Looptools/D/D0.F
+++ /dev/null
@@ -1,1713 +0,0 @@
-* D0.F
-* the scalar four-point function
-* this file is part of LoopTools
-* last modified 14 Dec 10 th
-
-#include "defs.h"
-
-#define legs 4
-#define M(i) xpi(i)
-#define P(i) xpi(i+legs)
-
-
- double complex function D0(p1, p2, p3, p4, p1p2, p2p3,
- & m1, m2, m3, m4)
- implicit none
- double precision p1, p2, p3, p4, p1p2, p2p3
- double precision m1, m2, m3, m4
-
-#include "lt.h"
-
- double complex res(0:1)
- double precision xpi(13)
- integer key, ier
-
- external D0softDR, D0collDR, D0soft, D0coll
-
- M(1) = m1
- M(2) = m2
- M(3) = m3
- M(4) = m4
- P(1) = p1
- P(2) = p2
- P(3) = p3
- P(4) = p4
- P(5) = p1p2
- P(6) = p2p3
- P(7) = 0
- P(8) = 0
- P(9) = 0
-
- if( lambda .le. 0 ) then
- call DDispatch(D0, xpi, D0softDR, D0collDR)
- return
- endif
-
- ier = 0
- key = ibits(versionkey, KeyD0, 2)
-
- if( key .ne. 1 ) then
- call ffxd0(res(0), xpi, ier)
- if( ier .gt. warndigits ) then
- ier = 0
- call ffxd0r(res(0), xpi, ier)
- if( ier .gt. warndigits ) key = ior(key, 2)
- if( ier .ge. errdigits ) key = ior(key, 3)
- endif
- endif
-
- if( key .ne. 0 ) then
- call DDispatch(res(1), xpi, D0soft, D0coll)
- if( key .gt. 1 .and.
- & abs(res(0) - res(1)) .gt. maxdev*abs(res(0)) ) then
- print *, "Discrepancy in D0:"
- print *, " p1 =", p1
- print *, " p2 =", p2
- print *, " p3 =", p3
- print *, " p4 =", p4
- print *, " p1p2 =", p1p2
- print *, " p2p3 =", p2p3
- print *, " m1 =", m1
- print *, " m2 =", m2
- print *, " m3 =", m3
- print *, " m4 =", m4
- print *, "D0 a =", res(0)
- print *, "D0 b =", res(1)
- if( ier .gt. errdigits ) res(0) = res(1)
- endif
- endif
-
- D0 = res(iand(key, 1))
- end
-
-************************************************************************
-* adapter code for C++
-
- subroutine d0sub(res, p1, p2, p3, p4, p1p2, p2p3,
- & m1, m2, m3, m4)
- implicit none
- double complex res
- double precision p1, p2, p3, p4, p1p2, p2p3
- double precision m1, m2, m3, m4
-
- double complex D0
- external D0
-
- res = D0(p1, p2, p3, p4, p1p2, p2p3, m1, m2, m3, m4)
- end
-
-************************************************************************
-
- subroutine DDispatch(res, xpi, soft, coll)
- implicit none
- double complex res
- double precision xpi(13)
- external soft, coll
-
-#include "lt.h"
-
- integer i, z, s, perm
-
- integer xpiperm(12), mperm(0:7)
- data xpiperm /
- & O'1234561234', O'1635421243', O'5264131324',
- & O'2341652341', O'6351242431', O'2546132314',
- & O'3412563412', O'5462313142', O'3615243421',
- & O'4123654123', O'4526314132', O'6153424213' /
- data mperm / O'1234561234', O'1234561234',
- & O'5264131324', O'1234561234', O'4321561432',
- & O'1635421243', O'5361421342', O'1234561234' /
-
-* 0 1 1xxx O'1234561234'
-* 1 2 12xx O'1234561234'
-* 2 2 13xx O'5264131324'
-* 3 3 123x O'1234561234'
-* 4 2 14xx O'4321561432'
-* 5 3 124x O'1635421243'
-* 6 3 134x O'5361421342'
-* 7 4 xxxx O'1234561234'
-
-#define pj(p,j) ibits(p,3*(10-j),3)
-#define mj(p,j) ibits(p,3*(4-j),3)
-
-#define Px(j) P(pj(perm,j))
-#define Mx(j) M(mj(perm,j))
-
- z = 0
- s = 0
- do i = 1, 12
- perm = xpiperm(i)
- if( abs(Mx(1)) .lt. eps ) then
- if( abs(Px(1)) + abs(Mx(2)) .lt. eps ) then
- call coll(res, xpi, perm)
- if( res .ne. perm ) return
- endif
- if( s .eq. 0 .and.
- & abs(Px(1) - Mx(2)) +
- & abs(Px(4) - Mx(4)) .lt. acc ) s = perm
- if( z .eq. 0 ) z = perm
- endif
- enddo
-
- if( s .ne. 0 ) then
- call soft(res, xpi, s)
- return
- endif
-
- if( z .eq. 0 ) then
- call D0m4(res, xpi)
- return
- endif
-
- perm = z
- z = 0
- if( abs(Mx(2)) .lt. eps ) z = 1
- if( abs(Mx(3)) .lt. eps ) z = z + 2
- if( abs(Mx(4)) .lt. eps ) z = z + 4
- s = mperm(z)
- if( s .ne. O'1234561234' ) perm =
- & pj(perm, pj(s, 1))*8**9 +
- & pj(perm, pj(s, 2))*8**8 +
- & pj(perm, pj(s, 3))*8**7 +
- & pj(perm, pj(s, 4))*8**6 +
- & pj(perm, pj(s, 5))*8**5 +
- & pj(perm, pj(s, 6))*8**4 +
- & mj(perm, mj(s, 1))*8**3 +
- & mj(perm, mj(s, 2))*8**2 +
- & mj(perm, mj(s, 3))*8**1 +
- & mj(perm, mj(s, 4))*8**0
-
- goto (2, 2, 3, 2, 3, 3, 4) z
-
- call D0m3(res, xpi, perm)
- return
-
-2 call D0m2(res, xpi, perm)
- return
-
-3 call D0m1(res, xpi, perm)
- return
-
-4 call D0m0(res, xpi)
- end
-
-************************************************************************
-
- subroutine D0soft(res, xpi, perm)
- implicit none
- double complex res
- double precision xpi(13)
- integer perm
-
-#include "lt.h"
-
- double precision m3, p1, p2, p3, p4, p1p2, p2p3
- double precision r1, r3, r4
- double complex xs, x2, x3, y, c, fac
- double complex lxs, lx2, lx3, l1x2, l1x3, ly, lm
-
- double complex ln, spence, bdK
- external ln, spence, bdK
-
- m3 = Mx(3)
- p1 = Px(1)
- p2 = Px(2)
- p3 = Px(3)
- p4 = Px(4)
- p1p2 = Px(5)
- p2p3 = Px(6)
-
- r1 = sqrt(p1)
- r4 = sqrt(p4)
- fac = .5D0/(r1*r4*(p1p2 - m3))
- xs = bdK(p2p3, r1, r4)
- lxs = -1
- if( xs .ne. 1 ) then
- lxs = log(xs)
- fac = 2*xs/((1 - xs)*(1 + xs))*fac
- endif
-
-* massless case
- if( abs(m3) .lt. eps ) then
- if( abs(p1 - p2) + abs(p3 - p4) .lt. acc ) then
- res = -2*ln(-lambda/p1p2, 1D0)*lxs*fac
- return
- endif
- y = (r1*(p3 - p4 + cI*eps))/(r4*(p2 - p1 + cI*eps))
- ly = log(y)
- c = ln(lambda/(r1*r4), 0D0) +
- & ln((p2 - p1)/p1p2, p1 - p2) +
- & ln((p3 - p4)/p1p2, p4 - p3)
- if( xs .eq. 1 ) then
- res = fac*(c - 2 - (1 + y)/(1 - y)*ly)
- else
- res = fac*(pi6 -
- & spence(xs/y, 0D0) -
- & (lxs + log(1/y))*log(1 - xs/y) -
- & spence(xs*y, 0D0) -
- & (lxs + ly)*(log(1 - xs*y) + .5D0*(lxs - ly)) +
- & spence(xs**2, 0D0) +
- & lxs*(2*log((1 - xs)*(1 + xs)) - c))
- endif
- return
- endif
-
-* massive case
- r3 = sqrt(m3)
- x2 = bdK(p2, r1, r3)
- x3 = bdK(p3, r4, r3)
- lx2 = log(x2)
- lx3 = log(x3)
- l1x3 = log(1/x3)
- lm = 2*ln(r3*sqrt(lambda)/(m3 - p1p2), 1D0)
- if( xs .eq. 1 ) then
- c = -2
- if( abs(x2 - x3) .gt. acc ) then
- c = (1 + x2/x3)/(1 - x2/x3)*(lx2 + l1x3) +
- & (1 + x2*x3)/(1 - x2*x3)*(lx2 + lx3) + 2
- else if( abs(x2 - 1) .gt. acc ) then
- c = -2*(x2**2 + 1)/((x2 - 1)*(x2 + 1))*lx2
- endif
- res = fac*(lm - c)
- else
- l1x2 = log(1/x2)
- res = fac*( .5D0*pi**2 +
- & lxs*(2*log((1 - xs)*(1 + xs)) - lm) +
- & spence(xs**2, 0D0) + lx2**2 + lx3**2 -
- & spence(xs/(x2*x3), 0D0) -
- & (lxs + l1x2 + l1x3)*log(1 - xs/(x2*x3)) -
- & spence(xs*x2/x3, 0D0) -
- & (lxs + lx2 + l1x3)*log(1 - xs*x2/x3) -
- & spence(xs/x2*x3, 0D0) -
- & (lxs + l1x2 + lx3)*log(1 - xs/x2*x3) -
- & spence(xs*x2*x3, 0D0) -
- & (lxs + lx2 + lx3)*log(1 - xs*x2*x3) )
- endif
- end
-
-************************************************************************
-
- double complex function bdK(x, m1, m2)
-* this is actually -K from the Beenakker/Denner paper for D0soft
- implicit none
- double precision x, m1, m2
-
-#include "lt.h"
-
- double precision d
- double complex t
-
- d = x - (m1 - m2)**2
- if( abs(d) .lt. acc ) then
- bdK = 1
- else
- t = 4*m1*m2/(d + cI*eps)
- bdK = -t/(sqrt(1 - t) + 1)**2
- endif
- end
-
-************************************************************************
-
- subroutine D0coll(res, xpi, perm)
- implicit none
- double complex res
- double precision xpi(13)
- integer perm
-
-#include "lt.h"
-
- logical ini
- data ini /.FALSE./
-
- Px(1) = max(minmass, 1D-14)
- res = perm
-
- if( ini ) return
- print *, "collinear-divergent D0, using mass cutoff ", Px(1)
- ini = .TRUE.
- end
-
-************************************************************************
-* IR-divergent D0 in dim reg
-* from W. Beenakker and A. Denner, NPB 338 (1990) 349
-
- subroutine D0softDR(res, xpi, perm)
- implicit none
- double complex res
- double precision xpi(13)
- integer perm
-
-#include "lt.h"
-
- double precision m2, m3, m4, p2, p3, t, p2p3, q2, q3
- double precision r1, r3, r4, m24, sy
- double complex c, fac, xs, x2, x3, lxs, lx2, lx3, lm, y
-
- double complex bdK, ln, cln, lnrat, Li2omx2, Li2omx3
- external bdK, ln, cln, lnrat, Li2omx2, Li2omx3
-
-c PRINT *, "D0softDR"
-
- if( lambda .eq. -2 ) then
- res = 0
- return
- endif
-
- m2 = Mx(2)
- m3 = Mx(3)
- m4 = Mx(4)
- t = m3 - Px(5)
- p2p3 = Px(6)
-
- p2 = Px(2)
- q2 = m2 - p2
- p3 = Px(3)
- q3 = m4 - p3
-
- r1 = sqrt(m2)
- r4 = sqrt(m4)
-
- fac = .5D0/(r1*r4*t)
- xs = bdK(p2p3, r1, r4)
- lxs = -1
- if( xs .ne. 1 ) then
- lxs = log(xs)
- fac = 2*xs/((1 - xs)*(1 + xs))*fac
- endif
-
- if( abs(m3) .lt. eps ) then
- if( abs(q2) + abs(q3) .lt. acc ) then
-* qlbox14: D0(m2, m2, m4, m4; p1p2, p2p3; 0, m2, 0, m4)
-c PRINT *, "D0softDR: qlbox14"
- res = 2*fac*lxs
- if( lambda .ne. -1 ) res = res*lnrat(mudim, t)
- return
- endif
-
-* qlbox15: D0(m2, p2, p3, m4; p1p2, p2p3; 0, m2, 0, m4)
-* Beenakker-Denner Eq. (2.11)
-c PRINT *, "D0softDR: qlbox15"
- if( lambda .eq. -1 ) then
- res = fac*lxs
- return
- endif
-
- if( abs(q2*q3) .lt. acc ) then
- m24 = m2
- if( abs(q2) .lt. acc ) m24 = m4
- res = fac*( lxs*(lxs + log(mudim/m24) +
- & 2*lnrat(q2 + q3, t)) +
- & Li2omx2(xs, 1D0, xs, 1D0) )
- return
- endif
-
- y = r1*q3/(r4*q2)
- sy = sign(.5D0, r1*q3) - sign(.5D0, r4*q2)
-
- if( xs .eq. 1 ) then
- res = fac*( -log(mudim/(r1*r4)) +
- & lnrat(q2, t) + lnrat(q3, t) + 2 +
- & (1 + y)/(1 - y)*ln(y, sy) )
- else
- res = fac*( -.5D0*ln(y, sy)**2 +
- & lxs*(.5D0*lxs + lnrat(q2, t) + lnrat(q3, t) +
- & log(mudim/(r1*r4))) +
- & Li2omx2(xs, 1D0, xs, 1D0) -
- & Li2omx2(xs, 1D0, y, sy) -
- & Li2omx2(xs, 1D0, 1/y, -sy) )
- endif
- return
- endif
-
-* qlbox16: D0(m2, p2, p3, m4; p1p2, p2p3; 0, m2, m3, m4)
-* Beenakker-Denner Eq. (2.9)
-c PRINT *, "D0softDR: qlbox16"
-
- if( lambda .eq. -1 ) then
- res = fac*lxs
- return
- endif
-
- r3 = sqrt(m3)
- x2 = bdK(p2, r1, r3)
- x3 = bdK(p3, r4, r3)
- lx2 = log(x2)
- lx3 = log(x3)
-
- lm = 2*lnrat(sqrt(m3*mudim), t)
-
- if( xs .eq. 1 ) then
- c = -2
- if( abs(x2 - x3) .gt. acc ) then
- c = (1 + x2/x3)/(1 - x2/x3)*(lx2 + log(1/x3)) +
- & (1 + x2*x3)/(1 - x2*x3)*(lx2 + lx3) + 2
- else if( abs(x2 - 1) .gt. acc ) then
- c = -2*(x2**2 + 1)/((x2 - 1)*(x2 + 1))*lx2
- endif
- res = fac*(c - lm)
- else
- res = fac*(lm*lxs - lx2**2 - lx3**2 +
- & Li2omx2(xs, 1D0, xs, 1D0) -
- & Li2omx3(xs, 1D0, x2, 1D0, x3, 1D0) -
- & Li2omx3(xs, 1D0, 1/x2, -1D0, 1/x3, -1D0) -
- & Li2omx3(xs, 1D0, x2, 1D0, 1/x3, -1D0) -
- & Li2omx3(xs, 1D0, 1/x2, -1D0, x3, 1D0))
- endif
- end
-
-************************************************************************
-
- subroutine D0collDR(res, xpi, perm)
- implicit none
- double complex res
- double precision xpi(13)
- integer perm
-
-#include "lt.h"
-
- integer z, s
-
-* see D0table.f
- integer pperm(0:127)
- data pperm /
- & -898440548, -898440548, -865381277, -898440548,
- & -898440548, -1972182372, -865381277, -1972182372,
- & -898440548, -898440548, -865381277, -1972182372,
- & -898440548, -1972182372, -865381277, 1249043100,
- & -898440548, -898440548, -1939123101, -1939123101,
- & -898440548, -1972182372, -1939123101, 1368319628,
- & -898440548, -898440548, -1939123101, 1282102371,
- & -898440548, -1972182372, -1939123101, 175301276,
- & -898440548, -1921432484, -865381277, -1921432484,
- & -898440548, -1972182372, -865381277, -1972182372,
- & -898440548, -1921432484, -865381277, 1299792988,
- & -898440548, -1921432484, -865381277, 1249043100,
- & -898440548, -1921432484, -1939123101, -1939123101,
- & -898440548, -1972182372, -1939123101, 1368319628,
- & -898440548, -1921432484, -1939123101, 1282102371,
- & -898440548, -1972182372, -1939123101, 175301276,
- & -898440548, -898440548, -1904860509, -1904860509,
- & -898440548, -1972182372, -1904860509, -1972182372,
- & -898440548, -898440548, -1904860509, 1316364963,
- & -898440548, -1972182372, -1904860509, 1249043100,
- & -898440548, -898440548, -1904860509, -1939123101,
- & -898440548, -1972182372, -1904860509, 1368319628,
- & -898440548, -898440548, -1904860509, 1282102371,
- & -898440548, -1972182372, -1904860509, 175301276,
- & -898440548, -1921432484, -1904860509, 1907239051,
- & -898440548, -1972182372, -1904860509, 1907239051,
- & -898440548, -1921432484, -1904860509, 833497227,
- & -898440548, -1972182372, -1904860509, 833497227,
- & -898440548, -1921432484, -1904860509, 1907239051,
- & -898440548, -1972182372, -1904860509, 850499737,
- & -898440548, -1921432484, -1904860509, 833497227,
- & -898440548, -1972182372, -1904860509, 175301276 /
-
- z = 0
- if( abs(Mx(3)) .lt. eps ) z = 1
- if( abs(Mx(4)) .lt. eps ) z = z + 2
- if( abs(Px(2)) .lt. eps ) z = z + 4
- if( abs(Px(3)) .lt. eps ) z = z + 8
- if( abs(Px(4)) .lt. eps ) z = z + 16
- if( abs(Px(5)) .lt. eps ) z = z + 32
- if( abs(Px(6)) .lt. eps ) z = z + 64
- s = pperm(z)
- if( iand(s, O'7777777777') .ne. O'1234561234' ) perm =
- & pj(perm, pj(s, 1))*8**9 +
- & pj(perm, pj(s, 2))*8**8 +
- & pj(perm, pj(s, 3))*8**7 +
- & pj(perm, pj(s, 4))*8**6 +
- & pj(perm, pj(s, 5))*8**5 +
- & pj(perm, pj(s, 6))*8**4 +
- & mj(perm, mj(s, 1))*8**3 +
- & mj(perm, mj(s, 2))*8**2 +
- & mj(perm, mj(s, 3))*8**1 +
- & mj(perm, mj(s, 4))*8**0
-
- goto (22,22,22,23, 22,22,22,23, 10,11,12,13)
- & ibits(s, 30, 2) + ibits(z, 0, 2)*4 - 3
-
- call D0m2p3(res, xpi, perm)
- return
-
-23 call D0m1p3(res, xpi, perm)
- return
-
-22 call D0m1p2(res, xpi, perm)
- return
-
-13 call D0m0p3(res, xpi, perm)
- return
-
-12 call D0m0p2(res, xpi, perm)
- return
-
-11 call D0m0p1(res, xpi, perm)
- return
-
-10 call D0m0p0(res, xpi, perm)
- end
-
-************************************************************************
-* qlbox1: D0(0, 0, 0, 0; p1p2, p2p3; 0, 0, 0, 0)
-* Bern, Dixon, Kosower, NPB 412 (1994) 751 [hep-ph/9306240], Eq. (I.11)
-
- subroutine D0m0p0(res, xpi, perm)
- implicit none
- double complex res
- double precision xpi(13)
- integer perm
-
-#include "lt.h"
-
- double precision s, t, fac
-
- double complex lnrat
- external lnrat
-
-c PRINT *, "D0m0p0: qlbox1"
- s = -Px(5)
- t = -Px(6)
- fac = 1/(s*t)
- if( lambda .eq. -2 )then
- res = 4*fac
- else if( lambda .eq. -1 ) then
- res = 2*fac*(-lnrat(t, mudim) - lnrat(s, mudim))
- else
- res = fac*(lnrat(t, mudim)**2 + lnrat(s, mudim)**2 -
- & lnrat(t, s)**2 - pi**2)
- endif
- end
-
-************************************************************************
-* qlbox2: D0(0, 0, 0, p4; p1p2, p2p3; 0, 0, 0, 0)
-* One-mass integral as given in
-* Ellis, Giele, Zanderighi, Eq. (A22).
-
- subroutine D0m0p1(res, xpi, perm)
- implicit none
- double complex res
- double precision xpi(13)
- integer perm
-
-#include "lt.h"
-
- double precision s, t, m4, fac
- double complex l1, l2
-
- double complex lnrat, Li2omrat
- external lnrat, Li2omrat
-
-c PRINT *, "D0m0p1: qlbox2"
- s = -Px(5)
- t = -Px(6)
- m4 = -Px(4)
- fac = 1/(s*t)
- if( lambda .eq. -2 ) then
- res = 2*fac
- else if( lambda .eq. -1 ) then
- res = 2*fac*(lnrat(m4, mudim) -
- & lnrat(t, mudim) - lnrat(s, mudim))
- else
- l1 = sqrt(lnrat(t, mudim)**2 + lnrat(m4, t)**2 +
- & lnrat(s, mudim)**2 + lnrat(m4, s)**2)
- l2 = sqrt(lnrat(m4, mudim)**2 + lnrat(t, s)**2)
- res = fac*((l1 - l2)*(l1 + l2) +
- & 2*(Li2omrat(t, m4) + Li2omrat(s, m4) - pi6))
- endif
- end
-
-************************************************************************
-
- subroutine D0m0p2(res, xpi, perm)
- implicit none
- double complex res
- double precision xpi(13)
- integer perm
-
-#include "lt.h"
-
- double precision s, t, q2, q3, q4, fac, r
- double complex ls, lt, lq2, lq3, lq4
-
- double complex lnrat, lndiv0, lndiv1, Li2omrat, Li2omrat2
- external lnrat, lndiv0, lndiv1, Li2omrat, Li2omrat2
-
-c PRINT *, "D0m0p2"
- s = -Px(5)
- t = -Px(6)
- fac = 1/(s*t)
- q4 = -Px(4)
- q3 = -Px(3)
-
- if( abs(q3) .lt. eps ) then
-* qlbox3: D0(0, p2, 0, p4; p1p2, p2p3; 0, 0, 0, 0)
-* Bern, Dixon, Kosower, NPB 412 (1994) 751 [hep-ph/9306240], Eq. (I.13)
-c PRINT *, "D0m0p2: qlbox3"
-
- if( lambda .eq. -2 ) then
- res = 0
- return
- endif
-
- q2 = -Px(2)
- r = 1 - q2*q4*fac
-
-* Use expansion only in cases where signs (s,t,m2,m4) are not
-* ++-- or --++
- if( abs(r) .lt. 1D-6 .and.
- & (fac .lt. 0 .or. q2*q4 .lt. 0) ) then
-* expanded case
- if( lambda .eq. -1 ) then
- res = -(2 + r)*fac
- else
- res = fac*(2 - .5D0*r +
- & (2 + r)*(lnrat(s, mudim) + lnrat(t, q4)) +
- & 2*(lndiv0(q4, t) + lndiv0(q4, s)) +
- & r*(lndiv1(q4, t) + lndiv1(q4, s)))
- endif
- else
-* general case
- fac = 1/(s*t - q2*q4)
- if( lambda .eq. -1 ) then
- res = 2*fac*(lnrat(q2, s) + lnrat(q4, t))
- else
- ls = lnrat(s, mudim)
- lt = lnrat(t, mudim)
- lq2 = lnrat(q2, mudim)
- lq4 = lnrat(q4, mudim)
- res = fac*(
- & (ls - lq2)*(ls + lq2) +
- & (lt - lq4)*(lt + lq4) - lnrat(s, t)**2 +
- & 2*(Li2omrat2(q2, s, q4, t) -
- & Li2omrat(q2, s) - Li2omrat(q2, t) -
- & Li2omrat(q4, s) - Li2omrat(q4, t)) )
- endif
- endif
- return
- endif
-
-* qlbox4: D0(0, 0, p3, p4; p1p2, p2p3; 0, 0, 0, 0)
-* Bern, Dixon, Kosower, NPB 412 (1994) 751 [hep-ph/9306240], Eq. (I.14)
-c PRINT *, "D0m0p2: qlbox4"
-
- if( lambda .eq. -2 ) then
- res = fac
- else if( lambda .eq. -1 ) then
- res = -fac*(lnrat(s, q3) + lnrat(t, q4) + lnrat(t, mudim))
- else
- ls = lnrat(s, mudim)
- lt = lnrat(t, mudim)
- lq3 = lnrat(q3, mudim)
- lq4 = lnrat(q4, mudim)
- res = fac*(
- & .5D0*((ls - lq3)*(ls + lq3) +
- & (lt - lq4)*(lt + lq4) + lt**2) +
- & lnrat(s, q3)*lnrat(s, q4) - lnrat(s, t)**2 -
- & 2*(Li2omrat(q3, t) + Li2omrat(q4, t)) )
- endif
- end
-
-************************************************************************
-* qlbox5: D0(0, p2, p3, p4; p1p2, p2p3; 0, 0, 0, 0)
-* Bern, Dixon, Kosower, NPB 412 (1994) 751 [hep-ph/9306240], Eq. (I.15)
-* or from hep-ph/0508308v3 Eq. (A27)
-* (v3 corrects previous versions)
-
- subroutine D0m0p3(res, xpi, perm)
- implicit none
- double complex res
- double precision xpi(13)
- integer perm
-
-#include "lt.h"
-
- double precision s, t, q2, q3, q4, fac, r
-
- double complex lnrat, lndiv0, lndiv1, Li2omrat, Li2omrat2
- external lnrat, lndiv0, lndiv1, Li2omrat, Li2omrat2
-
-c PRINT *, "D0m0p3: qlbox5"
-
- if( lambda .eq. -2 ) then
- res = 0
- return
- endif
-
- s = -Px(5)
- t = -Px(6)
- fac = 1/(s*t)
- q2 = -Px(2)
- q3 = -Px(3)
- q4 = -Px(4)
-
- r = 1 - q2*q4*fac
-
-* Use expansion only in cases where signs of (s,t,q2,q4) are
-* not ++-- or --++
- if( abs(r) .lt. 1D-6 .and.
- & (fac .lt. 0 .or. q2*q4 .lt. 0) ) then
-* expanded case
- if( lambda .eq. -1 ) then
- res = -.5D0*(2 + r)*fac
- else
- res = lndiv0(q4, t)
- res = fac*(
- & .5D0*(2 + r)*(2 + (1 + q4/t)*res -
- & lnrat(mudim, s) - lnrat(q3, t)) +
- & r*(lndiv1(q4, t) - res - 1) )
- endif
- else
-* general case
- fac = 1/(s*t - q2*q4)
- if( lambda .eq. -1 ) then
- res = fac*(lnrat(q2, t) + lnrat(q4, s))
- else
- res = fac*(
- & (lnrat(q3, t) + lnrat(mudim, t))*lnrat(q2, t) +
- & (lnrat(q3, s) + lnrat(mudim, s))*lnrat(q4, s) -
- & .5D0*(lnrat(t, q2)**2 + lnrat(s, q4)**2) -
- & lnrat(s, t)**2 -
- & 2*(Li2omrat(q2, s) + Li2omrat(q4, t) -
- & Li2omrat2(q2, s, q4, t)) )
- endif
- endif
- end
-
-************************************************************************
-
- subroutine D0m1p2(res, xpi, perm)
- implicit none
- double complex res
- double precision xpi(13)
- integer perm
-
-#include "lt.h"
-
- double precision m4, s, t, q3, q4, fac
- double complex lm, ls, lt, lq
- integer ir
-
- double complex lnrat, Li2omrat, Li2omrat2
- external lnrat, Li2omrat, Li2omrat2
-
-c PRINT *, "D0m1p2"
- m4 = Mx(4)
- s = -Px(5)
- t = m4 - Px(6)
- fac = 1/(s*t)
- q3 = m4 - Px(3)
- q4 = m4 - Px(4)
-
- ir = 0
- if( abs(q3) .lt. acc ) ir = 1
- if( abs(q4) .lt. acc ) then
- ir = ir + 1
- q4 = q3
- endif
-
- if( lambda .eq. -2 ) then
- res = .5D0*(2 + ir)*fac
- return
- endif
-
- goto (1, 2) ir
-
-* qlbox8: D0(0, 0, p3, p4; p1p2, p2p3; 0, 0, 0, m4)
-c PRINT *, "D0m1p2: qlbox8"
- lm = lnrat(s, mudim)
- if( lambda .eq. -1 ) then
- res = fac*(lnrat(q3, t) + lnrat(q4, t) - lm)
- else
- ls = lnrat(s, m4)
- res = fac*(-2*(Li2omrat(q3, t) + Li2omrat(q4, t)) -
- & Li2omrat2(q3, s, q4, m4) - pi6 +
- & .5D0*(lm - ls)*(lm + ls) + 2*lm*lnrat(t, m4) -
- & lnrat(q3, mudim)*lnrat(q3, m4) -
- & lnrat(q4, mudim)*lnrat(q4, m4))
- endif
- return
-
-1 continue
-* qlbox7: D0(0, 0, m4, p4; p1p2, p2p3; 0, 0, 0, m4)
-c PRINT *, "D0m1p2: qlbox7"
- ls = lnrat(s, m4)
- lt = lnrat(t, m4)
- lm = lnrat(mudim, m4)
- lq = lnrat(q4, m4)
- if( lambda .eq. -1 ) then
- res = fac*(1.5D0*lm - 2*lt - ls + lq)
- else
- res = fac*(2*ls*lt - lq**2 - 5*pi12 +
- & lm*(.75D0*lm - 2*lt - ls + lq) -
- & 2*Li2omrat(q4, t))
- endif
- return
-
-2 continue
-* qlbox6: D0(0, 0, m4, m4; p1p2, p2p3; 0, 0, 0, m4)
-c PRINT *, "D0m1p2: qlbox6"
- ls = lnrat(s, m4)
- lt = lnrat(t, m4)
- lm = lnrat(mudim, m4)
- if( lambda .eq. -1 ) then
- res = fac*(2*(lm - lt) - ls)
- else
- res = fac*((lm - ls)*(lm - 2*lt) - .5D0*pi**2)
- endif
- end
-
-************************************************************************
-
- subroutine D0m1p3(res, xpi, perm)
- implicit none
- double complex res
- double precision xpi(13)
- integer perm
-
-#include "lt.h"
-
- double precision s, t, m4, q2, q3, q4, m4mu, fac
-
- double complex lnrat, Li2omrat, Li2omrat2
- external lnrat, Li2omrat, Li2omrat2
-
-c PRINT *, "D0m1p3"
-
- if( lambda .eq. -2 ) then
- res = 0
- return
- endif
-
- q2 = -Px(2)
- s = -Px(5)
- m4 = Mx(4)
- q3 = m4 - Px(3)
- q4 = m4 - Px(4)
- t = m4 - Px(6)
-
- if( abs(t) .lt. acc ) then
- t = q4
- q4 = 0
- s = q2
- q2 = -Px(5)
- endif
-
- m4mu = sqrt(m4*mudim)
-
-* qlbox9: D0(0, p2, p3, m4; p1p2, p2p3; 0, 0, 0, m4)
- if( abs(q4) .lt. acc ) then
-c PRINT *, "D0m1p3: qlbox9"
- fac = 1/(s*t)
- if( lambda .eq. -1 ) then
- res = -fac*(lnrat(t, m4mu) + lnrat(s, q2))
- else
- res = fac*(Li2omrat2(q3, q2, t, m4) + 2*Li2omrat(s, q2) +
- & lnrat(t, m4mu) + lnrat(s, q2) + pi12)
- endif
- return
- endif
-
-* qlbox10: D0(0, p2, p3, p4; p1p2, p2p3; 0, 0, 0, m4)
-c PRINT *, "D0m1p3: qlbox10"
- fac = 1/(s*t - q2*q4)
- res = fac*(lnrat(q2, mudim) + lnrat(q4, mudim) -
- & lnrat(s, mudim) - lnrat(t, mudim))
- if( lambda .ne. -1 ) then
- res = 2*res*lnrat(m4mu, t) +
- & fac*(Li2omrat2(q3, q2, t, m4) - Li2omrat2(q3, s, q4, m4) +
- & 2*(Li2omrat2(q2, s, q4, t) +
- & Li2omrat(q2, s) - Li2omrat(t, q4)))
- endif
- end
-
-************************************************************************
-
- subroutine D0m2p3(res, xpi, perm)
- implicit none
- double complex res
- double precision xpi(13)
- integer perm
-
-#include "lt.h"
-
- double precision s, t, m3, m4, q3, q4, p3, fac, m3mu, m4mu
- double precision p34, c, s3t, s4s
- double complex ls, lt, lq3, lq4, d
- double complex x43(4), r3t, r4s, r43p, r43m
- double complex logs, dilogs
- integer ir, case
-
- double complex lnrat, cln, Li2rat, Li2omrat, Li2omrat2
- external lnrat, cln, Li2rat, Li2omrat, Li2omrat2
-
-c PRINT *, "D0m2p3"
- m3 = Mx(3)
- s = m3 - Px(5)
- q3 = m3 - Px(2)
- m4 = Mx(4)
- t = m4 - Px(6)
- q4 = m4 - Px(4)
-
- if( abs(s*t) .lt. eps ) then
- s = q3
- q3 = m3 - Px(5)
- t = q4
- q4 = m4 - Px(6)
- endif
-
- fac = 1/(s*t - q3*q4)
-
- ir = 0
- if( abs(q3) .lt. acc ) ir = 1
- if( abs(q4) .lt. acc ) then
- ir = ir + 1
- q4 = q3
- s = t
- t = m3 - Px(5)
- m4 = m3
- m3 = Mx(4)
- endif
-
- if( lambda .eq. -2 ) then
- res = .5D0*fac*ir
- return
- endif
-
- if( lambda .eq. -1 ) goto (10, 11, 12) ir + 1
-
- p3 = Px(3)
- if( abs(p3) .lt. eps ) then
- case = 1
- logs = lnrat(m3, m4)**2
- else
- p34 = p3 + m3 - m4
- c = -4*p3*m3
- d = sqrt(DCMPLX(p34**2 + c))
-
- x43(1) = -p34 - d
- x43(2) = p34 - d
- if( abs(x43(1)) .lt. abs(x43(2)) ) then
- x43(1) = c/x43(2)
- else
- x43(2) = c/x43(1)
- endif
-
- p34 = -p3 + m3 - m4
- c = -4*p3*m4
-
- x43(3) = -p34 - d
- x43(4) = p34 - d
- if( abs(x43(3)) .lt. abs(x43(4)) ) then
- x43(3) = c/x43(4)
- else
- x43(4) = c/x43(3)
- endif
-
- if( abs(DIMAG(d)) .lt. eps ) then
- case = 2
- logs = lnrat(x43(1), x43(3))**2 +
- & lnrat(x43(2), x43(4))**2
- else
- case = 3
- r43p = x43(1)/x43(3)
- r43m = x43(2)/x43(4)
- logs = cln(r43p, 0D0)**2 + cln(r43m, 0D0)**2
- endif
- endif
-
- goto (1, 2) ir
-
-* qlbox13: D0(0, p2, p3, p4; p1p2, p2p3; 0, 0, m3, m4)
-c PRINT *, "D0m2p3: qlbox13"
-
- ls = lnrat(s, mudim)
- lt = lnrat(t, mudim)
- lq3 = lnrat(q3, mudim)
- lq4 = lnrat(q4, mudim)
-
- if( case .eq. 1 ) then
- dilogs = Li2omrat2(q3, t, -1D0, -1D0) +
- & Li2omrat2(q3, t, m4, m3) +
- & Li2omrat2(q4, s, m3, m4) +
- & Li2omrat2(q4, s, -1D0, -1D0)
- else if( case .eq. 2 ) then
- dilogs = Li2omrat2(q3, t, x43(4), x43(2)) +
- & Li2omrat2(q3, t, x43(3), x43(1)) +
- & Li2omrat2(q4, s, x43(1), x43(3)) +
- & Li2omrat2(q4, s, x43(2), x43(4))
- else
- r3t = q3/t
- s3t = sign(.5D0, q3) - sign(.5D0, t)
- r4s = q4/s
- s4s = sign(.5D0, q4) - sign(.5D0, s)
- dilogs = Li2rat(r3t,s3t, 1/r43m,0D0) +
- & Li2rat(r3t,s3t, 1/r43p,0D0) +
- & Li2rat(r4s,s4s, r43p,0D0) +
- & Li2rat(r4s,s4s, r43m,0D0)
- endif
-
- res = -fac*(dilogs + .5D0*logs + lq3**2 + lq4**2 +
- & 2*(Li2omrat(q3, s) + Li2omrat(q4, t) -
- & Li2omrat2(q3, s, q4, t) - ls*lt) +
- & (lt - lq3)*log(m3/mudim) + (ls - lq4)*log(m4/mudim))
- return
-
-10 res = fac*(lnrat(q3, mudim) + lnrat(q4, mudim) -
- & lnrat(s, mudim) - lnrat(t, mudim))
- return
-
-1 continue
-* qlbox12: D0(0, m3, p3, p4; p1p2, p2p3; 0, 0, m3, m4)
-c PRINT *, "D0m2p3: qlbox12"
-
- m3mu = sqrt(m3*mudim)
- ls = lnrat(s, m3mu)
- lt = lnrat(t, m3mu)
- lq4 = lnrat(q4, m3mu)
-
- if( case .eq. 1 ) then
- dilogs = 0
- else if( case .eq. 2 ) then
- dilogs = Li2omrat2(q4, s, x43(1), x43(3)) +
- & Li2omrat2(q4, s, x43(2), x43(4))
- else
- r4s = q4/s
- s4s = sign(.5D0, q4) - sign(.5D0, s)
- dilogs = Li2rat(r4s,s4s, r43p,0D0) +
- & Li2rat(r4s,s4s, r43m,0D0)
- endif
-
- res = -fac*(dilogs + .5D0*logs + pi12 +
- & 2*(Li2omrat(q4, t) - ls*lt) +
- & lq4**2 + (ls - lq4)*log(m4/m3))
- return
-
-11 m3mu = sqrt(m3*mudim)
- res = fac*(lnrat(q4, m3mu) - lnrat(s, m3mu) - lnrat(t, m3mu))
- return
-
-2 continue
-* qlbox11: D0(0, m3, p3, m4; p1p2, p2p3; 0, 0, m3, m4)
-c PRINT *, "D0m2p3: qlbox11"
-
- m3mu = sqrt(m3*mudim)
- m4mu = sqrt(m4*mudim)
- ls = lnrat(s, m3mu)
- lt = lnrat(t, m4mu)
-
- res = fac*(.25D0*log(m3/m4)**2 - .5D0*(logs + pi**2) +
- & 2*lnrat(s, sqrt(m3*mudim))*lnrat(t, sqrt(m4*mudim)))
- return
-
-12 res = -fac*(lnrat(s, sqrt(m3*mudim)) +
- & lnrat(t, sqrt(m4*mudim)))
- end
-
-************************************************************************
-* this routine is adapted from Ansgar Denner's bcanew.f
-* to the conventions of LoopTools;
-* it is used for double-checking the results of FF
-* M. Rauch: implemented the log branch cuts for k13 < 2
-* (from Denner, Nierste, Scharf; Nucl Phys B367 (1991) 637)
-
-#define AddEps(k) k*DCMPLX(1D0, -sign(eps, k))
-#define k2r(k) (.5D0*k*(1 + sqrt(DCMPLX((1 - 2/k)*(1 + 2/k)))))
-
- subroutine D0m4(res, xpi)
- implicit none
- double complex res
- double precision xpi(13)
-
-#include "lt.h"
-
- double precision tmp, ir1324, gamma, s1, s2
- double precision kij(6), irij(6), ix(2,4)
- double complex rij(6), x(2,4), l(2,4), q13, q24
- double complex a, b, c, d, disc, ki, etas
- integer j
-
- double precision k12, k13, k14, k23, k24, k34
- double precision ir12, ir13, ir14, ir23, ir24, ir34
- double complex r12, r14, r13, r23, r24, r34
- equivalence (kij(1), k12), (rij(1), r12), (irij(1), ir12)
- equivalence (kij(2), k23), (rij(2), r23), (irij(2), ir23)
- equivalence (kij(3), k34), (rij(3), r34), (irij(3), ir34)
- equivalence (kij(4), k14), (rij(4), r14), (irij(4), ir14)
- equivalence (kij(5), k13), (rij(5), r13), (irij(5), ir13)
- equivalence (kij(6), k24), (rij(6), r24), (irij(6), ir24)
-
- double complex cln, xspence, xeta, xetatilde
- integer eta
- external cln, xspence, xeta, xetatilde, eta
-
- k12 = (M(1) + M(2) - P(1))/sqrt(M(1)*M(2))
- k23 = (M(2) + M(3) - P(2))/sqrt(M(2)*M(3))
- k34 = (M(3) + M(4) - P(3))/sqrt(M(3)*M(4))
- k14 = (M(1) + M(4) - P(4))/sqrt(M(1)*M(4))
- k13 = (M(1) + M(3) - P(5))/sqrt(M(1)*M(3))
- k24 = (M(2) + M(4) - P(6))/sqrt(M(2)*M(4))
-
-* test if r_13 can be made real by a permutation
-* if one of the r_ij is real r_13 must be made real => case 1
- if( abs(k13) .ge. 2 ) then
-* nothing to do
-* otherwise try all permutations
- else if( abs(k12) .ge. 2 ) then
-* 2 <-> 3
- tmp = k12
- k12 = k13
- k13 = tmp
- tmp = k24
- k24 = k34
- k34 = tmp
- else if( abs(k14) .ge. 2 ) then
-* 3 <-> 4
- tmp = k13
- k13 = k14
- k14 = tmp
- tmp = k23
- k23 = k24
- k24 = tmp
- else if( abs(k23) .ge. 2 ) then
-* 1 <-> 2
- tmp = k13
- k13 = k23
- k23 = tmp
- tmp = k14
- k14 = k24
- k24 = tmp
- else if( abs(k24) .ge. 2 ) then
-* 1 -> 4, 2 -> 1, 3 -> 2, 4 -> 3
- tmp = k12
- k12 = k23
- k23 = k34
- k34 = k14
- k14 = tmp
- tmp = k13
- k13 = k24
- k24 = tmp
- else if( abs(k34) .ge. 2 ) then
-* 1 <-> 4
- tmp = k12
- k12 = k24
- k24 = tmp
- tmp = k13
- k13 = k34
- k34 = tmp
-* else
-* nothing found => all r_ij on the complex unit circle => case 2
- endif
-
- r12 = k2r(k12)
- r23 = k2r(k23)
- r34 = k2r(k34)
- r14 = k2r(k14)
- r13 = 1/k2r(k13)
- r24 = 1/k2r(k24)
-
- do j = 1, 6
- if( DIMAG(rij(j)) .eq. 0 ) then
- ki = kij(j) - cI*eps
- irij(j) = sign(1D0, abs(rij(j)) - 1)*
- & DIMAG(k2r(ki))
- else
- irij(j) = 0
- endif
- enddo
-
- ir1324 = sign(1D0, DBLE(r24))*ir13 -
- & sign(1D0, DBLE(r13))*ir24
-
- a = k34/r24 - k23 + (k12 - k14/r24)*r13
- b = (1/r13 - r13)*(1/r24 - r24) + k12*k34 - k14*k23
- c = k34*r24 - k23 + (k12 - k14*r24)/r13
- d = k23 + (r24*k14 - k12)*r13 - r24*k34
- disc = sqrt(b**2 - 4*a*(c + cI*eps*d))
- ix(1,4) = DIMAG(.5D0/a*(b - disc))
- ix(2,4) = DIMAG(.5D0/a*(b + disc))
-
- disc = sqrt(b**2 - 4*a*c)
- x(1,4) = .5D0/a*(b - disc)
- x(2,4) = .5D0/a*(b + disc)
- if( abs(x(1,4)) .gt. abs(x(2,4)) ) then
- x(2,4) = c/(a*x(1,4))
- else
- x(1,4) = c/(a*x(2,4))
- endif
-
- x(1,1) = x(1,4)/r24
- x(2,1) = x(2,4)/r24
- x(1,2) = x(1,4)*r13/r24
- x(2,2) = x(2,4)*r13/r24
- x(1,3) = x(1,4)*r13
- x(2,3) = x(2,4)*r13
-
- s1 = sign(1D0, DBLE(x(1,4)))
- s2 = sign(1D0, DBLE(x(2,4)))
- ix(1,1) = ix(1,4)*DBLE(x(1,1))*s1
- ix(2,1) = ix(2,4)*DBLE(x(2,1))*s2
- ix(1,2) = ix(1,4)*DBLE(x(1,2))*s1
- ix(2,2) = ix(2,4)*DBLE(x(2,2))*s2
- ix(1,3) = ix(1,4)*DBLE(x(1,3))*s1
- ix(2,3) = ix(2,4)*DBLE(x(2,3))*s2
-
- res = 0
- do j = 1, 4
- res = res + Sgn(j)*(
- & xspence(x(1,j), ix(1,j), rij(j), irij(j)) +
- & xspence(x(1,j), ix(1,j), 1/rij(j), -irij(j)) )
- enddo
-
- gamma = sign(1D0, DBLE(a*(x(2,4) - x(1,4))))
- l(1,4) = c2ipi*eta(r13, ir13, 1/r24, -ir24, ir1324)
- l(2,4) = l(1,4)
-
- if( DIMAG(r13) .eq. 0 ) then
- r12 = k12 - r24*k14
- r23 = k23 - r24*k34
- r34 = k34 - r13*k14
- r14 = k23 - r13*k12
- q13 = k13 - 2*r13
- q24 = k24 - 2*r24
-
- c = gamma*sign(1D0, DIMAG(r24) + ir24)
- l(1,1) = cln(-x(1,1), -ix(1,1)) +
- & cln(r14 - q13/x(1,1), -1D0) +
- & cln((r12 - q24*x(1,4))/d, c)
- l(2,1) = cln(-x(2,1), -ix(2,1)) +
- & cln(r14 - q13/x(2,1), -1D0) +
- & cln((r12 - q24*x(2,4))/d, -c)
-
- c = gamma*sign(1D0, DBLE(r13)*(DIMAG(r24) + ir24))
- l(1,2) = cln(-x(1,2), -ix(1,2)) +
- & cln(r14 - q13/x(1,1), -1D0) +
- & cln((r23 - q24*x(1,3))/d, c)
- l(2,2) = cln(-x(2,2), -ix(2,2)) +
- & cln(r14 - q13/x(2,1), -1D0) +
- & cln((r23 - q24*x(2,3))/d, -c)
-
- l(1,3) = cln(-x(1,3), -ix(1,3)) +
- & cln(r34 - q13/x(1,4), -1D0) +
- & cln((r23 - q24*x(1,3))/d, c)
- l(2,3) = cln(-x(2,3), -ix(2,3)) +
- & cln(r34 - q13/x(2,4), -1D0) +
- & cln((r23 - q24*x(2,3))/d, -c)
-
- etas =
- & xetatilde(x(1,4), ix(1,4), r13, ir13, l(1,3)) +
- & xetatilde(x(1,4), ix(1,4), 1/r24, -ir24, l(1,1)) -
- & xetatilde(x(1,4), ix(1,4), r13/r24, ir1324, l(1,2)) +
- & xetatilde(x(1,4), ix(1,4), -r13/r24, -ir1324, l(1,4))
- else
- do j = 1, 3
- l(1,j) = log(-x(1,j)) +
- & cln(kij(j) - 1/x(1,j) - x(1,j), -x(1,j)*b*gamma)
- l(2,j) = log(-x(2,j)) +
- & cln(kij(j) - 1/x(2,j) - x(2,j), -x(2,j)*b*gamma)
- enddo
-
- etas =
- & xeta(x(1,4), ix(1,4), r13, ir13, ix(1,3), l(1,3)) +
- & xeta(x(1,4), ix(1,4), 1/r24, -ir24, ix(1,1), l(1,1)) -
- & xeta(x(1,4), ix(1,4), r13/r24, ir1324, ix(1,2), l(1,2)) +
- & xeta(x(1,4), ix(1,4), -r13/r24, -ir1324, ix(1,4), l(1,4))*
- & (1 - sign(1D0, DBLE(b))*gamma)
- endif
-
- res = (res - c2ipi*etas + (l(2,2) - l(1,2))*l(1,4))/
- & (sqrt(M(1)*M(2)*M(3)*M(4))*disc)
- end
-
-************************************************************************
-
- subroutine D0m3(res, xpi, perm)
- implicit none
- double complex res
- double precision xpi(13)
- integer perm
-
-#include "lt.h"
-
- double precision m2, m3, m4, p1, p2, p3, p4, p1p2, p2p3
- double precision m, k12, k13, k14, k23, k24, k34
- double precision ir12, ir14, ir24, ix1(2), ix4(2)
- double complex r12, r14, r24, q12, q24
- double complex x1(2), x4(2), l4(2)
- double complex a, b, c, d
-
- double complex cln, xspence, xetatilde
- external cln, xspence, xetatilde
-
- m2 = Mx(2)
- m3 = Mx(3)
- m4 = Mx(4)
- p1 = Px(1)
- p2 = Px(2)
- p3 = Px(3)
- p4 = Px(4)
- p1p2 = Px(5)
- p2p3 = Px(6)
-
- m = sqrt(m3*m4)
- k23 = (m4 - p4)/m
- k12 = (m4 + m3 - p3)/m
- r12 = k2r(k12)
- ir12 = 0
- if( k12 .lt. -2 ) ir12 = sign(10D0, 1 - abs(r12))
-
- m = sqrt(m2*m3)
- k34 = (m2 - p1)/m
- k14 = (m2 + m3 - p2)/m
- r14 = k2r(k14)
- ir14 = 0
- if( k14 .lt. -2 ) ir14 = sign(10D0, 1 - abs(r14))
-
- k13 = (m3 - p1p2)/m3
-
- m = sqrt(m2*m4)
- k24 = (m2 + m4 - p2p3)/m
- r24 = k2r(k24)
- ir24 = 0
- if( k24 .lt. -2 ) ir24 = sign(10D0, 1 - abs(r24))
-
- q24 = r24 - 1/r24
- q12 = k12 - r24*k14
-
- a = k34/r24 - k23
- b = k12*k34 - k13*q24 - k14*k23
- c = k13*q12 + r24*k34 - k23
- d = sqrt(DCMPLX((k12*k34 - k13*k24 - k14*k23)**2 -
- & 4*(k13*(k13 - k23*(k12 - k14*k24)) +
- & k23*(k23 - k24*k34) + k34*(k34 - k13*k14))))
- x4(1) = .5D0/a*(b - d)
- x4(2) = .5D0/a*(b + d)
- if( abs(x4(1)) .gt. abs(x4(2)) ) then
- x4(2) = c/(a*x4(1))
- else
- x4(1) = c/(a*x4(2))
- endif
-
- d = -k34*r24 + k23
- ix4(1) = sign(1D0, DBLE(d))
- ix4(2) = -ix4(1)
-
- x1(1) = x4(1)/r24
- x1(2) = x4(2)/r24
- ix1(1) = sign(1D0, ix4(1)*DBLE(r24))
- ix1(2) = -ix1(1)
-
- c = cln(DCMPLX(k13), -1D0)
- l4(1) = c + cln((q12 + q24*x4(1))/d, DBLE(q24*ix4(1)/d))
- l4(2) = c + cln((q12 + q24*x4(2))/d, DBLE(q24*ix4(2)/d))
-
- res = (
- & xspence(x4, ix4, r14, ir14) +
- & xspence(x4, ix4, 1/r14, -ir14) -
- & xspence(x4, ix4, DCMPLX(k34/k13), -k13) -
- & xspence(x1, ix1, r12, ir12) -
- & xspence(x1, ix1, 1/r12, -ir12) +
- & xspence(x1, ix1, DCMPLX(k23/k13), -k13) -
- & c2ipi*xetatilde(x4, ix4, 1/r24, -ir24, l4)
- & )/(m3*m*a*(x4(2) - x4(1)))
- end
-
-************************************************************************
-
- subroutine D0m2(res, xpi, perm)
- implicit none
- double complex res
- double precision xpi(13)
- integer perm
-
-#include "lt.h"
-
- double precision m3, m4, p1, p2, p3, p4, p1p2, p2p3
- double precision m, k12, k13, k14, k23, k24, k34
- double complex k12c, k13c, k23c, k24c, k34c
- double complex r14, x4(2)
- double complex a, b, c, disc
-
- double complex xspence
- external xspence
-
- double precision imzero(2)
- data imzero /0D0, 0D0/
-
- m3 = Mx(3)
- m4 = Mx(4)
- p1 = Px(1)
- p2 = Px(2)
- p3 = Px(3)
- p4 = Px(4)
- p1p2 = Px(5)
- p2p3 = Px(6)
-
- k12 = (m3 - p2)/m3
- k12c = AddEps(k12)
-
- k13 = (m3 - p1p2)/m3
- k13c = AddEps(k13)
-
- k23 = -p1/m3
- k23c = AddEps(k23)
-
- m = sqrt(m3*m4)
- k24 = (m4 - p2p3)/m
- k24c = AddEps(k24)/k12c
- k34 = (m4 - p4)/m
- k34c = AddEps(k34)/k13c
- k14 = (m3 + m4 - p3)/m
- r14 = k2r(k14)
- r14 = r14*DCMPLX(1D0, sign(eps, DBLE(1/r14 - r14)))
-
- a = k34*k24 - k23
- b = k13*k24 + k12*k34 - k14*k23
- c = k13*k12 - k23*(1 - cI*eps)
- disc = sqrt(b**2 - 4*a*c)
- x4(1) = .5D0/a*(b - disc)
- x4(2) = .5D0/a*(b + disc)
- if( abs(x4(1)) .gt. abs(x4(2)) ) then
- x4(2) = c/(a*x4(1))
- else
- x4(1) = c/(a*x4(2))
- endif
-
- res = (
- & xspence(x4, imzero, r14, 0D0) +
- & xspence(x4, imzero, 1/r14, 0D0) -
- & xspence(x4, imzero, k34c, 0D0) -
- & xspence(x4, imzero, k24c, 0D0) +
- & (log(x4(2)) - log(x4(1)))*
- & (log(k12c) + log(k13c) - log(k23c))
- & )/(m3*m*a*(x4(2) - x4(1)))
- end
-
-************************************************************************
-
- subroutine D0m1(res, xpi, perm)
- implicit none
- double complex res
- double precision xpi(13)
- integer perm
-
-#include "lt.h"
-
- double precision m4, k12, k13, k14, k23, k24, k34
- double complex k12c, k13c, k14c, k23c, k24c, k34c
- double precision a, b
- double complex c, disc, x4(2)
-
- double complex xspence
- external xspence
-
- double precision imzero(2)
- data imzero /0D0, 0D0/
-
- m4 = Mx(4)
- k12 = (m4 - Px(3))/m4
- k12c = AddEps(k12)
- k13 = (m4 - Px(4))/m4
- k13c = AddEps(k13)
- k14 = (m4 - Px(6))/m4
- k14c = AddEps(k14)
- k23 = -Px(5)/m4
- k23c = AddEps(k23)
- k24 = -Px(2)/m4
- k24c = AddEps(k24)/k12c
- k34 = -Px(1)/m4
- k34c = AddEps(k34)/k13c
-
- a = k34*k24
- b = k13*k24 + k12*k34 - k14*k23
- c = k13*k12 - k23*(1 - cI*eps)
- disc = sqrt(b*b - 4*a*c)
- x4(1) = .5D0/a*(b - disc)
- x4(2) = .5D0/a*(b + disc)
- if( abs(x4(1)) .gt. abs(x4(2)) ) then
- x4(2) = c/(a*x4(1))
- else
- x4(1) = c/(a*x4(2))
- endif
-
- res = (
- & xspence(x4, imzero, k14c, 0D0) -
- & xspence(x4, imzero, k34c, 0D0) -
- & xspence(x4, imzero, k24c, 0D0) +
- & (log(x4(2)) - log(x4(1)))*
- & (log(k12c) + log(k13c) - log(k23c))
- & )/(m4**2*a*(x4(2) - x4(1)))
- end
-
-************************************************************************
-
- subroutine D0m0(res, xpi)
- implicit none
- double complex res
- double precision xpi(13)
-
-#include "lt.h"
-
- double precision m2, k12, k13, k14, k23, k24, k34
- double complex k12c, k13c, k14c, k23c, k24c, k34c
- double precision a, b
- double complex c, disc, x4(2)
-
- double complex xspence
- external xspence
-
- double precision imzero(2)
- data imzero /0D0, 0D0/
-
- m2 = abs(P(6))
- k12 = -P(1)/m2
- k12c = AddEps(k12)
- k13 = -P(5)/m2
- k13c = AddEps(k13)
- k14 = -P(4)/m2
- k14c = AddEps(k14)
- k23 = -P(2)/m2
- k23c = AddEps(k23)
- k24 = -P(6)/m2
- k24c = AddEps(k24)/k12c
- k34 = -P(3)/m2
- k34c = AddEps(k34)/k13c
-
- a = k34*k24
- b = k13*k24 + k12*k34 - k14*k23
- c = k13*k12 + cI*eps*k23
- disc = sqrt(b*b - 4*a*c)
- x4(1) = .5D0/a*(b - disc)
- x4(2) = .5D0/a*(b + disc)
- if( abs(x4(1)) .gt. abs(x4(2)) ) then
- x4(2) = c/(a*x4(1))
- else
- x4(1) = c/(a*x4(2))
- endif
-
- res = (
- & (log(x4(2)) - log(x4(1)))*
- & (-.5D0*(log(x4(2)) + log(x4(1))) +
- & log(k12c) + log(k13c) - log(k23c) - log(k14c)) -
- & xspence(x4, imzero, k34c, 0D0) -
- & xspence(x4, imzero, k24c, 0D0)
- & )/(m2**2*a*(x4(2) - x4(1)))
- end
-
-************************************************************************
-
- double complex function xspence(z1, im1, z2, im2)
- implicit none
- double complex z1(2), z2
- double precision im1(2), im2
-
-#include "lt.h"
-
- double complex cspence
- external cspence
-
- xspence = cspence(z1(2), im1(2), z2, im2) -
- & cspence(z1(1), im1(1), z2, im2)
- end
-
-************************************************************************
-
- double complex function cspence(z1, im1, z2, im2)
- implicit none
- double complex z1, z2
- double precision im1, im2
-
-#include "lt.h"
-
- double complex cln, spence
- integer eta
- external cln, spence, eta
-
- double complex z12
- double precision im12
- integer etas
-
- z12 = z1*z2
- im12 = im2*sign(1D0, DBLE(z1))
- if( DBLE(z12) .gt. .5D0 ) then
- cspence = spence(1 - z12, 0D0)
- etas = eta(z1, im1, z2, im2, im12)
- if( etas .ne. 0 ) cspence = cspence +
- & etas*cln(1 - z12, -im12)*c2ipi
- else if( abs(z12) .lt. 1D-4 ) then
- cspence = pi6
- if( abs(z12) .gt. 1D-14 ) cspence = cspence -
- & spence(z12, 0D0) +
- & (cln(z1, im1) + cln(z2, im2))*z12*
- & (1 + z12*(.5D0 + z12*(1/3D0 + z12/4D0)))
- else
- cspence = pi6 - spence(z12, 0D0) -
- & (cln(z1, im1) + cln(z2, im2))*cln(1 - z12, 0D0)
- endif
- end
-
-************************************************************************
-
- double complex function xeta(z1, im1, z2, im2, im12, l1)
- implicit none
- double complex z1(2), z2, l1(2)
- double precision im1(2), im2, im12
-
-#include "lt.h"
-
- integer eta
- external eta
-
- xeta = l1(2)*eta(z1(2), im1(2), z2, im2, im12) -
- & l1(1)*eta(z1(1), im1(1), z2, im2, im12)
- end
-
-************************************************************************
-
- double complex function xetatilde(z1, im1, z2, im2, l1)
- implicit none
- double complex z1(2), z2, l1(2)
- double precision im1(2), im2
-
-#include "lt.h"
-
- integer etatilde
- external etatilde
-
- xetatilde = l1(2)*etatilde(z1(2), im1(2), z2, im2) -
- & l1(1)*etatilde(z1(1), im1(1), z2, im2)
- end
-
-************************************************************************
-
- integer function etatilde(c1, im1x, c2, im2x)
- implicit none
- double complex c1, c2
- double precision im1x, im2x
-
- double precision im1, im2
-
- integer eta
- external eta
-
- im1 = DIMAG(c1)
- if( im1 .eq. 0 ) im1 = im1x
- im2 = DIMAG(c2)
- if( im2 .ne. 0 ) then
- etatilde = eta(c1, im1x, c2, 0D0, 0D0)
- else if( DBLE(c2) .gt. 0 ) then
- etatilde = 0
- else if( im1 .gt. 0 .and. im2x .gt. 0 ) then
- etatilde = -1
- else if( im1 .lt. 0 .and. im2x .lt. 0 ) then
- etatilde = 1
- else
- etatilde = 0
-#ifdef WARNINGS
- if( im1 .eq. 0 .and. DBLE(c1) .lt. 0 .or.
- & im2x .eq. 0 .and. DBLE(c1*c2) .lt. 0 )
- & print *, "etatilde not defined"
-#endif
- endif
- end
-
diff --git a/Looptools/D/D0C.F b/Looptools/D/D0C.F
deleted file mode 100644
--- a/Looptools/D/D0C.F
+++ /dev/null
@@ -1,77 +0,0 @@
-* D0C.F
-* the scalar four-point function with complex masses
-* this file is part of LoopTools
-* last modified 29 Jan 09 th
-
-#include "defs.h"
-
-
- double complex function D0C(p1, p2, p3, p4, p1p2, p2p3,
- & m1, m2, m3, m4)
- implicit none
- double complex p1, p2, p3, p4, p1p2, p2p3
- double complex m1, m2, m3, m4
-
-#include "lt.h"
-
- double complex cpi(10), res(0:1)
- integer key, ier, ier1
-
- cpi(1) = m1
- cpi(2) = m2
- cpi(3) = m3
- cpi(4) = m4
- cpi(5) = p1
- cpi(6) = p2
- cpi(7) = p3
- cpi(8) = p4
- cpi(9) = p1p2
- cpi(10) = p2p3
-
- ier = 0
- key = ibits(versionkey, KeyD0C, 2)
-
- if( key .ne. 1 ) call ffd0c(res(0), cpi, 0, ier)
-
- if( key .ne. 0 ) then
- ier1 = 0
- call ffd0c(res(1), cpi, 1, ier1)
- if( key .gt. 1 .and.
- & abs(res(0) - res(1)) .gt. maxdev*abs(res(0)) ) then
- print *, "Discrepancy in D0C:"
- print *, " p1 =", p1
- print *, " p2 =", p2
- print *, " p3 =", p3
- print *, " p4 =", p4
- print *, " p1p2 =", p1p2
- print *, " p2p3 =", p2p3
- print *, " m1 =", m1
- print *, " m2 =", m2
- print *, " m3 =", m3
- print *, " m4 =", m4
- print *, "D0C a =", res(0)
- print *, "D0C b =", res(1)
- if( ier1 .lt. ier .and. ier .gt. errdigits )
- & res(0) = res(1)
- endif
- endif
-
- D0C = res(iand(key, 1))
- end
-
-************************************************************************
-* adapter code for C++
-
- subroutine d0subc(res, p1, p2, p3, p4, p1p2, p2p3,
- & m1, m2, m3, m4)
- implicit none
- double complex res
- double complex p1, p2, p3, p4, p1p2, p2p3
- double complex m1, m2, m3, m4
-
- double complex D0C
- external D0C
-
- res = D0C(p1, p2, p3, p4, p1p2, p2p3, m1, m2, m3, m4)
- end
-
diff --git a/Looptools/D/D0func.F b/Looptools/D/D0func.F
new file mode 100644
--- /dev/null
+++ b/Looptools/D/D0func.F
@@ -0,0 +1,1914 @@
+* D0func.F
+* the scalar four-point function
+* this file is part of LoopTools
+* last modified 1 Sep 14 th
+
+#include "externals.h"
+#include "types.h"
+
+#define npoint 4
+#include "defs.h"
+
+
+ subroutine D0func(res, para)
+ implicit none
+ ComplexType res(0:2)
+ RealType para(1,*)
+
+#include "lt.h"
+
+ external D0softDR, D0collDR, D0soft, D0coll
+
+ res(0) = 0
+ res(1) = 0
+ res(2) = 0
+
+ if( lambda .le. 0 ) then
+ call DDispatch(res, para, D0softDR, D0collDR)
+ else
+ call DDispatch(res, para, D0soft, D0coll)
+ endif
+ end
+
+************************************************************************
+
+ subroutine DDispatch(res, para, soft, coll)
+ implicit none
+ ComplexType res(0:2)
+ RealType para(1,*)
+ external soft, coll
+
+#include "lt.h"
+#include "perm.h"
+
+ integer i, z, s, perm, key, ier
+ ComplexType alt
+
+ integer pperm(12), mperm(0:7)
+ data pperm /
+ & p1234, p1243, p1324,
+ & p2341, p2431, p2314,
+ & p3412, p3142, p3421,
+ & p4123, p4132, p4213 /
+ data mperm / p1234, p1234,
+ & p1324, p1234, p1432,
+ & p1243, p1342, p1234 /
+
+* 0 1 1xxx O'1234561234'
+* 1 2 12xx O'1234561234'
+* 2 2 13xx O'5264131324'
+* 3 3 123x O'1234561234'
+* 4 2 14xx O'4321561432'
+* 5 3 124x O'1635421243'
+* 6 3 134x O'5361421342'
+* 7 4 xxxx O'1234561234'
+
+#define pj(p,j) ibits(p,3*(10-j),3)
+#define mj(p,j) ibits(p,3*(4-j),3)
+
+#define Px(j) P(pj(perm,j))
+#define Mx(j) M(mj(perm,j))
+
+ z = 0
+ s = 0
+ do i = 1, 12
+ perm = pperm(i)
+ if( abs(Mx(1)) .lt. zeroeps ) then
+ if( abs(Px(1)) + abs(Mx(2)) .lt. zeroeps ) then
+ if( DEBUGLEVEL .gt. 0 )
+ & print '("collinear D0, perm = ",O10)', perm
+ call coll(res, para, perm)
+ if( perm .eq. 0 ) return
+ endif
+ if( s .eq. 0 .and.
+ & abs(Px(1) - Mx(2)) +
+ & abs(Px(4) - Mx(4)) .lt. diffeps ) s = perm
+ if( z .eq. 0 ) z = perm
+ endif
+ enddo
+
+ if( s .ne. 0 .and. lambda .le. 0 ) then
+ if( DEBUGLEVEL .gt. 0 )
+ & print '("soft D0, perm = ",O10)', s
+ call soft(res, para, s)
+ return
+ endif
+
+ key = ibits(versionkey, KeyD0, 2)
+
+ if( key .ne. 1 ) then
+ P(7) = 0
+ P(8) = 0
+ P(9) = 0
+ ier = 0
+ call ffxd0(res(0), para, ier)
+ if( ier .gt. warndigits ) then
+ ier = 0
+ call ffxd0r(res(0), para, ier)
+ if( ier .gt. warndigits ) key = ior(key, 2)
+ if( ier .ge. errdigits ) key = ior(key, 3)
+ endif
+ if( key .eq. 0 ) return
+ alt = res(0)
+ endif
+
+ if( s .ne. 0 ) then
+ if( DEBUGLEVEL .gt. 0 )
+ & print '("soft D0, perm = ",O10)', s
+ call soft(res, para, s)
+ goto 9
+ endif
+
+ if( z .eq. 0 ) then
+ call D0m4(res(0), para)
+ goto 9
+ endif
+
+ perm = z
+ z = 0
+ if( abs(Mx(2)) .lt. zeroeps ) z = 1
+ if( abs(Mx(3)) .lt. zeroeps ) z = z + 2
+ if( abs(Mx(4)) .lt. zeroeps ) z = z + 4
+ s = mperm(z)
+ if( s .ne. p1234 ) perm =
+ & pj(perm, pj(s, 1))*8**9 +
+ & pj(perm, pj(s, 2))*8**8 +
+ & pj(perm, pj(s, 3))*8**7 +
+ & pj(perm, pj(s, 4))*8**6 +
+ & pj(perm, pj(s, 5))*8**5 +
+ & pj(perm, pj(s, 6))*8**4 +
+ & mj(perm, mj(s, 1))*8**3 +
+ & mj(perm, mj(s, 2))*8**2 +
+ & mj(perm, mj(s, 3))*8**1 +
+ & mj(perm, mj(s, 4))*8**0
+
+ goto (2, 2, 3, 2, 3, 3, 4) z
+
+ call D0m3(res(0), para, perm)
+ goto 9
+
+2 call D0m2(res(0), para, perm)
+ goto 9
+
+3 call D0m1(res(0), para, perm)
+ goto 9
+
+4 call D0m0(res(0), para)
+
+9 if( key .gt. 1 .and.
+ & abs(res(0) - alt) .gt. maxdev*abs(alt) ) then
+ print *, "Discrepancy in D0:"
+ print *, " p1 =", P(1)
+ print *, " p2 =", P(2)
+ print *, " p3 =", P(3)
+ print *, " p4 =", P(4)
+ print *, " p1p2 =", P(5)
+ print *, " p2p3 =", P(6)
+ print *, " m1 =", M(1)
+ print *, " m2 =", M(2)
+ print *, " m3 =", M(3)
+ print *, " m4 =", M(4)
+ print *, "D0 a =", alt
+ print *, "D0 b =", res(0)
+ endif
+
+ if( .not. btest(key, 0) ) res(0) = alt
+ end
+
+************************************************************************
+
+ subroutine DDump(s, para,ldpara, perm)
+ implicit none
+ character*(*) s
+ integer ldpara, perm
+ RealType para(ldpara,*)
+
+#include "lt.h"
+
+ print '(A,", perm = ",O4)', s, iand(perm, O'7777')
+ if( DEBUGLEVEL .gt. 1 ) then
+ print *, "p1 =", Px(1)
+ print *, "p2 =", Px(2)
+ print *, "p3 =", Px(3)
+ print *, "p4 =", Px(4)
+ print *, "p1p2 =", Px(5)
+ print *, "p2p3 =", Px(6)
+ print *, "m1 =", Mx(1)
+ print *, "m2 =", Mx(2)
+ print *, "m3 =", Mx(3)
+ print *, "m4 =", Mx(4)
+ endif
+ end
+
+************************************************************************
+
+ subroutine D0soft(res, para, perm)
+ implicit none
+ ComplexType res
+ RealType para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ RealType m3, p1, p2, p3, p4, p1p2, p2p3
+ RealType r1, r3, r4
+ ComplexType xs, x2, x3, y, c, fac
+ ComplexType lxs, lx2, lx3, l1x2, l1x3, ly, lm
+ integer ier
+
+ ComplexType bdK, zfflo1, spence
+ external bdK, zfflo1, spence
+
+ m3 = Mx(3)
+ p1 = Px(1)
+ p2 = Px(2)
+ p3 = Px(3)
+ p4 = Px(4)
+ p1p2 = Px(5)
+ p2p3 = Px(6)
+
+ if( DEBUGLEVEL .gt. 0 ) call DDump("D0soft", para,1, perm)
+
+ ier = 0
+
+ r1 = sqrt(p1)
+ r4 = sqrt(p4)
+ fac = .5D0/(r1*r4*(p1p2 - m3))
+ xs = bdK(p2p3, r1, r4)
+ lxs = -1
+ if( xs .ne. 1 ) then
+ lxs = log(xs)
+ fac = 2*xs/((1 - xs)*(1 + xs))*fac
+ endif
+
+* massless case
+ if( abs(m3) .lt. zeroeps ) then
+ if( abs(p1 - p2) + abs(p3 - p4) .lt. diffeps ) then
+ res = -2*ln(-lambda/p1p2, 1)*lxs*fac
+ return
+ endif
+ y = (r1*(p3 - p4 + cIeps))/(r4*(p2 - p1 + cIeps))
+ ly = log(y)
+ c = ln(lambda/(r1*r4), 0) +
+ & ln((p2 - p1)/p1p2, p1 - p2) +
+ & ln((p3 - p4)/p1p2, p4 - p3)
+ if( xs .eq. 1 ) then
+ res = fac*(c - 2 - (1 + y)/(1 - y)*ly)
+ else
+ res = fac*(pi6 -
+ & spence(0, xs/y, 0D0) -
+ & (lxs + log(1/y))*zfflo1(xs/y, ier) -
+ & spence(0, xs*y, 0D0) -
+ & (lxs + ly)*(zfflo1(xs*y, ier) + .5D0*(lxs - ly)) +
+ & spence(0, xs**2, 0D0) +
+ & lxs*(2*zfflo1(xs**2, ier) - c))
+ endif
+ goto 9
+ endif
+
+* massive case
+ r3 = sqrt(m3)
+ x2 = bdK(p2, r1, r3)
+ x3 = bdK(p3, r4, r3)
+ lx2 = log(x2)
+ lx3 = log(x3)
+ l1x3 = log(1/x3)
+ lm = 2*ln(r3*sqrt(lambda)/(m3 - p1p2), 1)
+ if( xs .eq. 1 ) then
+ c = -2
+ if( abs(x2 - x3) .gt. diffeps ) then
+ c = (1 + x2/x3)/(1 - x2/x3)*(lx2 + l1x3) +
+ & (1 + x2*x3)/(1 - x2*x3)*(lx2 + lx3) + 2
+ else if( abs(x2 - 1) .gt. diffeps ) then
+ c = -2*(x2**2 + 1)/((x2 - 1)*(x2 + 1))*lx2
+ endif
+ res = fac*(lm - c)
+ else
+ l1x2 = log(1/x2)
+ res = fac*( .5D0*pi**2 +
+ & lxs*(2*zfflo1(xs**2, ier) - lm) +
+ & spence(0, xs**2, 0D0) + lx2**2 + lx3**2 -
+ & spence(0, xs/(x2*x3), 0D0) -
+ & (lxs + l1x2 + l1x3)*zfflo1(xs/(x2*x3), ier) -
+ & spence(0, xs*x2/x3, 0D0) -
+ & (lxs + lx2 + l1x3)*zfflo1(xs*x2/x3, ier) -
+ & spence(0, xs/x2*x3, 0D0) -
+ & (lxs + l1x2 + lx3)*zfflo1(xs/x2*x3, ier) -
+ & spence(0, xs*x2*x3, 0D0) -
+ & (lxs + lx2 + lx3)*zfflo1(xs*x2*x3, ier) )
+ endif
+
+9 if( DEBUGLEVEL .gt. 1 ) print *, "D0soft =", res
+ end
+
+************************************************************************
+
+ ComplexType function bdK(x, m1, m2)
+* this is actually -K from the Beenakker/Denner paper for D0soft
+ implicit none
+ RealType x, m1, m2
+
+#include "lt.h"
+
+ RealType d
+ ComplexType t
+
+ d = x - (m1 - m2)**2
+ if( abs(d) .lt. diffeps ) then
+ bdK = 1
+ else
+ t = 4*m1*m2/(d + cIeps)
+ bdK = -t/(sqrt(1 - t) + 1)**2
+ endif
+ end
+
+************************************************************************
+
+ subroutine D0coll(res, para, perm)
+ implicit none
+ ComplexType res
+ RealType para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ logical ini
+ data ini /.FALSE./
+
+ if( DEBUGLEVEL .gt. 0 ) call DDump("D0coll", para,1, perm)
+
+ Px(1) = max(minmass, 1D-14)
+
+ if( ini ) return
+ print *, "collinear-divergent D0, using mass cutoff ", Px(1)
+ ini = .TRUE.
+ end
+
+************************************************************************
+* IR-divergent D0 in dim reg
+* from W. Beenakker and A. Denner, NPB 338 (1990) 349
+
+ subroutine D0softDR(res, para, perm)
+ implicit none
+ ComplexType res(0:2)
+ RealType para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ RealType m2, m3, m4, p2, p3, t, p2p3, q2, q3
+ RealType r1, r3, r4, m24, sy
+ ComplexType c, fac, xs, x2, x3, lxs, lx2, lx3, lm, y
+
+ ComplexType bdK, Li2omx2, Li2omx3
+ external bdK, Li2omx2, Li2omx3
+
+ if( DEBUGLEVEL .gt. 0 ) call DDump("D0softDR", para,1, perm)
+
+ m3 = Mx(3)
+ t = m3 - Px(5)
+ p2p3 = Px(6)
+
+ m2 = Px(1)
+ p2 = Px(2)
+ q2 = m2 - p2
+ m4 = Px(4)
+ p3 = Px(3)
+ q3 = m4 - p3
+
+ r1 = sqrt(m2)
+ r4 = sqrt(m4)
+
+ fac = .5D0/(r1*r4*t)
+ xs = bdK(p2p3, r1, r4)
+ lxs = -1
+ if( xs .ne. 1 ) then
+ lxs = log(xs)
+ fac = 2*xs/((1 - xs)*(1 + xs))*fac
+ endif
+
+ res(1) = fac*lxs
+ res(2) = 0
+
+ if( abs(m3) .lt. zeroeps ) then
+ if( abs(q2) + abs(q3) .lt. diffeps ) then
+* qlbox14: D0(m2, m2, m4, m4; p1p2, p2p3; 0, m2, 0, m4)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0softDR: qlbox14"
+ res(1) = 2*res(1)
+ res(0) = res(1)*lnrat(mudim, t)
+ goto 9
+ endif
+
+* qlbox15: D0(m2, p2, p3, m4; p1p2, p2p3; 0, m2, 0, m4)
+* Beenakker-Denner Eq. (2.11)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0softDR: qlbox15"
+
+ if( abs(q2*q3) .lt. diffeps ) then
+ m24 = m2
+ if( abs(q2) .lt. diffeps ) m24 = m4
+ res(0) = fac*( lxs*(lxs + log(mudim/m24) +
+ & 2*lnrat(q2 + q3, t)) +
+ & Li2omx2(xs, 1D0, xs, 1D0) )
+ goto 9
+ endif
+
+ y = r1*q3/(r4*q2)
+ sy = sign(.5D0, r1*q3) - sign(.5D0, r4*q2)
+
+ if( xs .eq. 1 ) then
+ res(0) = fac*( -log(mudim/(r1*r4)) +
+ & lnrat(q2, t) + lnrat(q3, t) + 2 +
+ & (1 + y)/(1 - y)*ln(y, sy) )
+ else
+ res(0) = fac*( -.5D0*ln(y, sy)**2 +
+ & lxs*(.5D0*lxs + lnrat(q2, t) + lnrat(q3, t) +
+ & log(mudim/(r1*r4))) +
+ & Li2omx2(xs, 1D0, xs, 1D0) -
+ & Li2omx2(xs, 1D0, y, sy) -
+ & Li2omx2(xs, 1D0, 1/y, -sy) )
+ endif
+ goto 9
+ endif
+
+* qlbox16: D0(m2, p2, p3, m4; p1p2, p2p3; 0, m2, m3, m4)
+* Beenakker-Denner Eq. (2.9)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0softDR: qlbox16"
+
+ r3 = sqrt(m3)
+ x2 = bdK(p2, r1, r3)
+ x3 = bdK(p3, r4, r3)
+ lx2 = log(x2)
+ lx3 = log(x3)
+
+ lm = 2*lnrat(sqrt(m3*mudim), t)
+
+ if( xs .eq. 1 ) then
+ c = -2
+ if( abs(x2 - x3) .gt. diffeps ) then
+ c = (1 + x2/x3)/(1 - x2/x3)*(lx2 + log(1/x3)) +
+ & (1 + x2*x3)/(1 - x2*x3)*(lx2 + lx3) + 2
+ else if( abs(x2 - 1) .gt. diffeps ) then
+ c = -2*(x2**2 + 1)/((x2 - 1)*(x2 + 1))*lx2
+ endif
+ res(0) = fac*(c - lm)
+ else
+ res(0) = fac*(lm*lxs - lx2**2 - lx3**2 +
+ & Li2omx2(xs, 1D0, xs, 1D0) -
+ & Li2omx3(xs, 1D0, x2, 1D0, x3, 1D0) -
+ & Li2omx3(xs, 1D0, 1/x2, -1D0, 1/x3, -1D0) -
+ & Li2omx3(xs, 1D0, x2, 1D0, 1/x3, -1D0) -
+ & Li2omx3(xs, 1D0, 1/x2, -1D0, x3, 1D0))
+ endif
+
+9 if( DEBUGLEVEL .gt. 1 ) then
+ print *, "D0softDR:0 =", res(0)
+ print *, "D0softDR:1 =", res(1)
+ print *, "D0softDR:2 =", res(2)
+ endif
+ end
+
+************************************************************************
+
+ subroutine D0collDR(res, para, perm_)
+ implicit none
+ ComplexType res(0:2)
+ RealType para(1,*)
+ integer perm_
+
+#include "lt.h"
+#include "perm.h"
+
+ integer perm, z, s
+
+* # of non-zero momenta
+ integer nz1, nz2, nz3
+ parameter (nz1 = 1073741824) ! O'10000000000'
+ parameter (nz2 = -2147483648) ! O'20000000000'
+ parameter (nz3 = -1073741824) ! O'30000000000'
+
+ integer nz1p1234, nz2p1234, nz3p1234
+ parameter (nz1p1234 = nz1 + p1234)
+ parameter (nz2p1234 = nz2 + p1234)
+ parameter (nz3p1234 = nz3 + p1234)
+ integer nz1p1243, nz2p1243, nz3p1243
+ parameter (nz1p1243 = nz1 + p1243)
+ parameter (nz2p1243 = nz2 + p1243)
+ parameter (nz3p1243 = nz3 + p1243)
+ integer nz1p2134, nz2p2134, nz3p2134
+ parameter (nz1p2134 = nz1 + p2134)
+ parameter (nz2p2134 = nz2 + p2134)
+ parameter (nz3p2134 = nz3 + p2134)
+ integer nz1p2143, nz2p2143, nz3p2143
+ parameter (nz1p2143 = nz1 + p2143)
+ parameter (nz2p2143 = nz2 + p2143)
+ parameter (nz3p2143 = nz3 + p2143)
+ integer nz1p3214, nz2p3214, nz3p3214
+ parameter (nz1p3214 = nz1 + p3214)
+ parameter (nz2p3214 = nz2 + p3214)
+ parameter (nz3p3214 = nz3 + p3214)
+ integer nz1p4213, nz2p4213, nz3p4213
+ parameter (nz1p4213 = nz1 + p4213)
+ parameter (nz2p4213 = nz2 + p4213)
+ parameter (nz3p4213 = nz3 + p4213)
+
+ integer pperm(0:127)
+ data pperm /
+* 1ppppp12mm 0ppp 1
+* 3m 0ppp 1
+* m4 0ppp 1432652143
+* 34 0ppp 1
+ & nz3p1234, nz3p1234, nz3p2143, nz3p1234,
+* 12pppp12mm 0ppp 1
+* 3m 00pp 1
+* m4 0ppp 1432652143
+* 34 00pp 1
+ & nz3p1234, nz2p1234, nz3p2143, nz2p1234,
+* 1p3ppp12mm 0ppp 1
+* 3m 0ppp 1
+* m4 0ppp 1432652143
+* 34 0p0p 1
+ & nz3p1234, nz3p1234, nz3p2143, nz2p1234,
+* 123ppp12mm 0ppp 1
+* 3m 00pp 1
+* m4 0ppp 1432652143
+* 34 000p 1
+ & nz3p1234, nz2p1234, nz3p2143, nz1p1234,
+* 1pp4pp12mm 0ppp 1
+* 3m 0ppp 1
+* m4 00pp 1432652143
+* 34 00pp 1432652143
+ & nz3p1234, nz3p1234, nz2p2143, nz2p2143,
+* 12p4pp12mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1432652143
+* 34 000p 2143563214
+ & nz3p1234, nz2p1234, nz2p2143, nz1p3214,
+* 1p34pp12mm 0ppp 1
+* 3m 0ppp 1
+* m4 00pp 1432652143
+* 34 000p 1432652143
+ & nz3p1234, nz3p1234, nz2p2143, nz1p2143,
+* 1234pp12mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1432652143
+* 34 0000 1
+ & nz3p1234, nz2p1234, nz2p2143, p1234,
+* 1ppp5p12mm 0ppp 1
+* 3m 00pp 1536242134
+* m4 0ppp 1432652143
+* 34 00pp 1536242134
+ & nz3p1234, nz2p2134, nz3p2143, nz2p2134,
+* 12pp5p12mm 0ppp 1
+* 3m 00pp 1
+* m4 0ppp 1432652143
+* 34 00pp 1
+ & nz3p1234, nz2p1234, nz3p2143, nz2p1234,
+* 1p3p5p12mm 0ppp 1
+* 3m 00pp 1536242134
+* m4 0ppp 1432652143
+* 34 000p 1536242134
+ & nz3p1234, nz2p2134, nz3p2143, nz1p2134,
+* 123p5p12mm 0ppp 1
+* 3m 00pp 1536242134
+* m4 0ppp 1432652143
+* 34 000p 1
+ & nz3p1234, nz2p2134, nz3p2143, nz1p1234,
+* 1pp45p12mm 0ppp 1
+* 3m 00pp 1536242134
+* m4 00pp 1432652143
+* 34 00pp 1432652143
+ & nz3p1234, nz2p2134, nz2p2143, nz2p2143,
+* 12p45p12mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1432652143
+* 34 000p 2143563214
+ & nz3p1234, nz2p1234, nz2p2143, nz1p3214,
+* 1p345p12mm 0ppp 1
+* 3m 00pp 1536242134
+* m4 00pp 1432652143
+* 34 000p 1432652143
+ & nz3p1234, nz2p2134, nz2p2143, nz1p2143,
+* 12345p12mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1432652143
+* 34 0000 1
+ & nz3p1234, nz2p1234, nz2p2143, p1234,
+* 1pppp612mm 0ppp 1
+* 3m 0ppp 1
+* m4 00pp 1635421243
+* 34 00pp 1635421243
+ & nz3p1234, nz3p1234, nz2p1243, nz2p1243,
+* 12ppp612mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1635421243
+* 34 00pp 1
+ & nz3p1234, nz2p1234, nz2p1243, nz2p1234,
+* 1p3pp612mm 0ppp 1
+* 3m 0ppp 1
+* m4 00pp 1635421243
+* 34 000p 1635421243
+ & nz3p1234, nz3p1234, nz2p1243, nz1p1243,
+* 123pp612mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1635421243
+* 34 000p 1
+ & nz3p1234, nz2p1234, nz2p1243, nz1p1234,
+* 1pp4p612mm 0ppp 1
+* 3m 0ppp 1
+* m4 00pp 1635421243
+* 34 00pp 1432652143
+ & nz3p1234, nz3p1234, nz2p1243, nz2p2143,
+* 12p4p612mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1635421243
+* 34 000p 2143563214
+ & nz3p1234, nz2p1234, nz2p1243, nz1p3214,
+* 1p34p612mm 0ppp 1
+* 3m 0ppp 1
+* m4 00pp 1635421243
+* 34 000p 1432652143
+ & nz3p1234, nz3p1234, nz2p1243, nz1p2143,
+* 1234p612mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1635421243
+* 34 0000 1
+ & nz3p1234, nz2p1234, nz2p1243, p1234,
+* 1ppp5612mm 0ppp 1
+* 3m 00pp 1536242134
+* m4 00pp 1635421243
+* 34 000p 6153424213
+ & nz3p1234, nz2p2134, nz2p1243, nz1p4213,
+* 12pp5612mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1635421243
+* 34 000p 6153424213
+ & nz3p1234, nz2p1234, nz2p1243, nz1p4213,
+* 1p3p5612mm 0ppp 1
+* 3m 00pp 1536242134
+* m4 00pp 1635421243
+* 34 0000 6153424213
+ & nz3p1234, nz2p2134, nz2p1243, p4213,
+* 123p5612mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1635421243
+* 34 0000 6153424213
+ & nz3p1234, nz2p1234, nz2p1243, p4213,
+* 1pp45612mm 0ppp 1
+* 3m 00pp 1536242134
+* m4 00pp 1635421243
+* 34 000p 6153424213
+ & nz3p1234, nz2p2134, nz2p1243, nz1p4213,
+* 12p45612mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1635421243
+* 34 0000 6254314231
+ & nz3p1234, nz2p1234, nz2p1243, p4231,
+* 1p345612mm 0ppp 1
+* 3m 00pp 1536242134
+* m4 00pp 1635421243
+* 34 0000 6153424213
+ & nz3p1234, nz2p2134, nz2p1243, p4213,
+* 12345612mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1635421243
+* 34 0000 1
+ & nz3p1234, nz2p1234, nz2p1243, p1234 /
+
+ if( DEBUGLEVEL .gt. 0 ) call DDump("D0collDR", para,1, perm)
+
+ perm = perm_
+ perm_ = 0
+
+ z = 0
+ if( abs(Mx(3)) .lt. zeroeps ) z = 1
+ if( abs(Mx(4)) .lt. zeroeps ) z = z + 2
+ if( abs(Px(2)) .lt. zeroeps ) z = z + 4
+ if( abs(Px(3)) .lt. zeroeps ) z = z + 8
+ if( abs(Px(4)) .lt. zeroeps ) z = z + 16
+ if( abs(Px(5)) .lt. zeroeps ) z = z + 32
+ if( abs(Px(6)) .lt. zeroeps ) z = z + 64
+ s = pperm(z)
+ if( iand(s, O'7777777777') .ne. p1234 ) perm =
+ & pj(perm, pj(s, 1))*8**9 +
+ & pj(perm, pj(s, 2))*8**8 +
+ & pj(perm, pj(s, 3))*8**7 +
+ & pj(perm, pj(s, 4))*8**6 +
+ & pj(perm, pj(s, 5))*8**5 +
+ & pj(perm, pj(s, 6))*8**4 +
+ & mj(perm, mj(s, 1))*8**3 +
+ & mj(perm, mj(s, 2))*8**2 +
+ & mj(perm, mj(s, 3))*8**1 +
+ & mj(perm, mj(s, 4))*8**0
+
+ goto (22,22,22,23, 22,22,22,23, 10,11,12,13)
+ & ibits(s, 30, 2) + ibits(z, 0, 2)*4 - 3
+
+ call D0m2p3(res, para, perm)
+ return
+
+23 call D0m1p3(res, para, perm)
+ return
+
+22 call D0m1p2(res, para, perm)
+ return
+
+13 call D0m0p3(res, para,1, perm)
+ return
+
+12 call D0m0p2(res, para,1, perm)
+ return
+
+11 call D0m0p1(res, para,1, perm)
+ return
+
+10 call D0m0p0(res, para,1, perm)
+ end
+
+************************************************************************
+* qlbox1: D0(0, 0, 0, 0; p1p2, p2p3; 0, 0, 0, 0)
+* Bern, Dixon, Kosower, NPB 412 (1994) 751 [hep-ph/9306240], Eq. (I.11)
+
+ subroutine D0m0p0(res, para,ldpara, perm)
+ implicit none
+ ComplexType res(0:2)
+ integer ldpara, perm
+ RealType para(1,*)
+
+#include "lt.h"
+
+ RealType s, t, fac
+ ComplexType lsm, ltm, lts
+
+ if( DEBUGLEVEL .gt. 0 )
+ & call DDump("D0m0p0: qlbox1", para,ldpara, perm)
+
+ s = -Px(5)
+ t = -Px(6)
+ fac = 1/(s*t)
+ lsm = lnrat(s, mudim)
+ ltm = lnrat(t, mudim)
+ lts = lnrat(t, s)
+ res(0) = fac*((ltm - pi)*(ltm + pi) - (lts - lsm)*(lts + lsm))
+ res(1) = -2*fac*(lsm + ltm)
+ res(2) = 4*fac
+
+ if( DEBUGLEVEL .gt. 1 ) then
+ print *, "D0m0p0:0 =", res(0)
+ print *, "D0m0p0:1 =", res(1)
+ print *, "D0m0p0:2 =", res(2)
+ endif
+ end
+
+************************************************************************
+* qlbox2: D0(0, 0, 0, p4; p1p2, p2p3; 0, 0, 0, 0)
+* One-mass integral as given in
+* Ellis, Giele, Zanderighi, Eq. (A22).
+
+ subroutine D0m0p1(res, para,ldpara, perm)
+ implicit none
+ ComplexType res(0:2)
+ integer ldpara, perm
+ RealType para(ldpara,*)
+
+#include "lt.h"
+
+ RealType s, t, m4, fac
+ ComplexType ls, lt, l4, l1, l2
+
+ ComplexType Li2omrat
+ external Li2omrat
+
+ if( DEBUGLEVEL .gt. 0 )
+ & call DDump("D0m0p1: qlbox2", para,ldpara, perm)
+
+ s = -Px(5)
+ t = -Px(6)
+ m4 = -Px(4)
+ fac = 1/(s*t)
+ ls = lnrat(s, mudim)
+ lt = lnrat(t, mudim)
+ l4 = lnrat(m4, mudim)
+ l1 = sqrt(lt**2 + ls**2 + lnrat(m4, s)**2 + lnrat(m4, t)**2)
+ l2 = sqrt(l4**2 + lnrat(t, s)**2)
+ res(0) = fac*((l1 - l2)*(l1 + l2) +
+ & 2*(Li2omrat(t, m4) + Li2omrat(s, m4) - pi6))
+ res(1) = 2*fac*(l4 - lt - ls)
+ res(2) = 2*fac
+
+ if( DEBUGLEVEL .gt. 1 ) then
+ print *, "D0m0p1:0 =", res(0)
+ print *, "D0m0p1:1 =", res(1)
+ print *, "D0m0p1:2 =", res(2)
+ endif
+ end
+
+************************************************************************
+
+ subroutine D0m0p2(res, para,ldpara, perm)
+ implicit none
+ ComplexType res(0:2)
+ integer ldpara, perm
+ RealType para(ldpara,*)
+
+#include "lt.h"
+
+ RealType s, t, q2, q3, q4, fac, r
+ ComplexType ls, lt, lq2, lq3, lq4, lsq3
+
+ ComplexType lndiv0, lndiv1, Li2omrat, Li2omrat2
+ external lndiv0, lndiv1, Li2omrat, Li2omrat2
+
+ if( DEBUGLEVEL .gt. 0 ) call DDump("D0m0p2", para,ldpara, perm)
+
+ s = -Px(5)
+ t = -Px(6)
+ fac = 1/(s*t)
+ q4 = -Px(4)
+ q3 = -Px(3)
+
+ if( abs(q3) .lt. zeroeps ) then
+* qlbox3: D0(0, p2, 0, p4; p1p2, p2p3; 0, 0, 0, 0)
+* Bern, Dixon, Kosower, NPB 412 (1994) 751 [hep-ph/9306240], Eq. (I.13)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0m0p2: qlbox3"
+
+ q2 = -Px(2)
+ r = 1 - q2*q4*fac
+
+* Use expansion only in cases where signs (s,t,m2,m4) are not
+* ++-- or --++
+ if( abs(r) .lt. 1D-6 .and.
+ & (fac .lt. 0 .or. q2*q4 .lt. 0) ) then
+* expanded case
+ res(0) = fac*(2 - .5D0*r +
+ & (2 + r)*(lnrat(s, mudim) + lnrat(t, q4)) +
+ & 2*(lndiv0(q4, t) + lndiv0(q4, s)) +
+ & r*(lndiv1(q4, t) + lndiv1(q4, s)))
+ res(1) = -(2 + r)*fac
+ res(2) = 0
+ else
+* general case
+ fac = 1/(s*t - q2*q4)
+ ls = lnrat(s, mudim)
+ lt = lnrat(t, mudim)
+ lq2 = lnrat(q2, mudim)
+ lq4 = lnrat(q4, mudim)
+ res(0) = fac*(
+ & (ls - lq2)*(ls + lq2) +
+ & (lt - lq4)*(lt + lq4) - lnrat(s, t)**2 +
+ & 2*(Li2omrat2(q2, s, q4, t) -
+ & Li2omrat(q2, s) - Li2omrat(q2, t) -
+ & Li2omrat(q4, s) - Li2omrat(q4, t)) )
+ res(1) = 2*fac*(lnrat(q2, s) + lnrat(q4, t))
+ res(2) = 0
+ endif
+ else
+* qlbox4: D0(0, 0, p3, p4; p1p2, p2p3; 0, 0, 0, 0)
+* Bern, Dixon, Kosower, NPB 412 (1994) 751 [hep-ph/9306240], Eq. (I.14)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0m0p2: qlbox4"
+
+ ls = lnrat(s, mudim)
+ lt = lnrat(t, mudim)
+ lq3 = lnrat(q3, mudim)
+ lq4 = lnrat(q4, mudim)
+ lsq3 = lnrat(s, q3)
+ res(0) = fac*(
+ & .5D0*((ls - lq3)*(ls + lq3) +
+ & (lt - lq4)*(lt + lq4) + lt**2) +
+ & lsq3*lnrat(s, q4) - lnrat(s, t)**2 -
+ & 2*(Li2omrat(q3, t) + Li2omrat(q4, t)) )
+ res(1) = -fac*(lsq3 + lnrat(t, q4) + lt)
+ res(2) = fac
+ endif
+
+ if( DEBUGLEVEL .gt. 1 ) then
+ print *, "D0m0p2:0 =", res(0)
+ print *, "D0m0p2:1 =", res(1)
+ print *, "D0m0p2:2 =", res(2)
+ endif
+ end
+
+************************************************************************
+* qlbox5: D0(0, p2, p3, p4; p1p2, p2p3; 0, 0, 0, 0)
+* Bern, Dixon, Kosower, NPB 412 (1994) 751 [hep-ph/9306240], Eq. (I.15)
+* or from hep-ph/0508308v3 Eq. (A27)
+* (v3 corrects previous versions)
+
+ subroutine D0m0p3(res, para,ldpara, perm)
+ implicit none
+ ComplexType res(0:2)
+ integer ldpara, perm
+ RealType para(ldpara,*)
+
+#include "lt.h"
+
+ RealType s, t, q2, q3, q4, fac, r
+ ComplexType l2, l4
+
+ ComplexType lndiv0, lndiv1, Li2omrat, Li2omrat2
+ external lndiv0, lndiv1, Li2omrat, Li2omrat2
+
+ if( DEBUGLEVEL .gt. 1 )
+ & call DDump("D0m0p3: qlbox5", para,ldpara, perm)
+
+ s = -Px(5)
+ t = -Px(6)
+ fac = 1/(s*t)
+ q2 = -Px(2)
+ q3 = -Px(3)
+ q4 = -Px(4)
+
+ r = 1 - q2*q4*fac
+
+* Use expansion only in cases where signs of (s,t,q2,q4) are
+* not ++-- or --++
+ if( abs(r) .lt. 1D-6 .and.
+ & (fac .lt. 0 .or. q2*q4 .lt. 0) ) then
+* expanded case
+ l4 = lndiv0(q4, t)
+ res(0) = fac*(
+ & .5D0*(2 + r)*(2 + (1 + q4/t)*l4 -
+ & lnrat(mudim, s) - lnrat(q3, t)) +
+ & r*(lndiv1(q4, t) - l4 - 1) )
+ res(1) = -.5D0*(2 + r)*fac
+ res(2) = 0
+ else
+* general case
+ fac = 1/(s*t - q2*q4)
+ l2 = lnrat(q2, t)
+ l4 = lnrat(q4, s)
+ res(0) = fac*(
+ & (lnrat(q3, t) + lnrat(mudim, t))*l2 +
+ & (lnrat(q3, s) + lnrat(mudim, s))*l4 -
+ & .5D0*(lnrat(t, q2)**2 + lnrat(s, q4)**2) -
+ & lnrat(s, t)**2 -
+ & 2*(Li2omrat(q2, s) + Li2omrat(q4, t) -
+ & Li2omrat2(q2, s, q4, t)) )
+ res(1) = fac*(l2 + l4)
+ res(2) = 0
+ endif
+
+ if( DEBUGLEVEL .gt. 1 ) then
+ print *, "D0m0p3:0 =", res(0)
+ print *, "D0m0p3:1 =", res(1)
+ print *, "D0m0p3:2 =", res(2)
+ endif
+ end
+
+************************************************************************
+
+ subroutine D0m1p2(res, para, perm)
+ implicit none
+ ComplexType res(0:2)
+ RealType para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ RealType m4, s, t, q3, q4, fac
+ ComplexType lm, ls, lt, lq
+ integer ir
+
+ ComplexType Li2omrat, Li2omrat2
+ external Li2omrat, Li2omrat2
+
+ if( DEBUGLEVEL .gt. 1 ) call DDump("D0m1p2", para,1, perm)
+
+ m4 = Mx(4)
+ s = -Px(5)
+ t = m4 - Px(6)
+ fac = 1/(s*t)
+ q3 = m4 - Px(3)
+ q4 = m4 - Px(4)
+
+ ir = 0
+ if( abs(q3) .lt. diffeps ) ir = 1
+ if( abs(q4) .lt. diffeps ) then
+ ir = ir + 1
+ q4 = q3
+ endif
+
+ res(2) = .5D0*(2 + ir)*fac
+
+ goto (1, 2) ir
+
+* qlbox8: D0(0, 0, p3, p4; p1p2, p2p3; 0, 0, 0, m4)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0m1p2: qlbox8"
+ lm = lnrat(s, mudim)
+ ls = lnrat(s, m4)
+ res(0) = fac*(-2*(Li2omrat(q3, t) + Li2omrat(q4, t)) -
+ & Li2omrat2(q3, s, q4, m4) - pi6 +
+ & .5D0*(lm - ls)*(lm + ls) + 2*lm*lnrat(t, m4) -
+ & lnrat(q3, mudim)*lnrat(q3, m4) -
+ & lnrat(q4, mudim)*lnrat(q4, m4))
+ res(1) = fac*(lnrat(q3, t) + lnrat(q4, t) - lm)
+ goto 9
+
+1 continue
+* qlbox7: D0(0, 0, m4, p4; p1p2, p2p3; 0, 0, 0, m4)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0m1p2: qlbox7"
+ ls = lnrat(s, m4)
+ lt = lnrat(t, m4)
+ lm = lnrat(mudim, m4)
+ lq = lnrat(q4, m4)
+ res(0) = fac*(2*ls*lt - lq**2 - 5*pi12 +
+ & lm*(.75D0*lm - 2*lt - ls + lq) -
+ & 2*Li2omrat(q4, t))
+ res(1) = fac*(1.5D0*lm - 2*lt - ls + lq)
+ goto 9
+
+2 continue
+* qlbox6: D0(0, 0, m4, m4; p1p2, p2p3; 0, 0, 0, m4)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0m1p2: qlbox6"
+ ls = lnrat(s, m4)
+ lt = lnrat(t, m4)
+ lm = lnrat(mudim, m4)
+ res(0) = fac*((lm - ls)*(lm - 2*lt) - .5D0*pi**2)
+ res(1) = fac*(2*(lm - lt) - ls)
+
+9 if( DEBUGLEVEL .gt. 1 ) then
+ print *, "D0m1p2:0 =", res(0)
+ print *, "D0m1p2:1 =", res(1)
+ print *, "D0m1p2:2 =", res(2)
+ endif
+ end
+
+************************************************************************
+
+ subroutine D0m1p3(res, para, perm)
+ implicit none
+ ComplexType res(0:2)
+ RealType para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ RealType s, t, m4, q2, q3, q4, m4mu, fac
+ ComplexType ll
+
+ ComplexType Li2omrat, Li2omrat2
+ external Li2omrat, Li2omrat2
+
+ if( DEBUGLEVEL .gt. 1 ) call DDump("D0m1p3", para,1, perm)
+
+ q2 = -Px(2)
+ s = -Px(5)
+ m4 = Mx(4)
+ q3 = m4 - Px(3)
+ q4 = m4 - Px(4)
+ t = m4 - Px(6)
+
+ if( abs(t) .lt. diffeps ) then
+ t = q4
+ q4 = 0
+ s = q2
+ q2 = -Px(5)
+ endif
+
+ m4mu = sqrt(m4*mudim)
+
+* qlbox9: D0(0, p2, p3, m4; p1p2, p2p3; 0, 0, 0, m4)
+ if( abs(q4) .lt. diffeps ) then
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0m1p3: qlbox9"
+ fac = 1/(s*t)
+ ll = lnrat(t, m4mu) + lnrat(s, q2)
+ res(0) = fac*(Li2omrat2(q3, q2, t, m4) +
+ & 2*Li2omrat(s, q2) + ll**2 + pi12)
+ res(1) = -fac*ll
+ res(2) = .5D0*fac
+ else
+* qlbox10: D0(0, p2, p3, p4; p1p2, p2p3; 0, 0, 0, m4)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0m1p3: qlbox10"
+ fac = 1/(s*t - q2*q4)
+ ll = lnrat(q2, mudim) + lnrat(q4, mudim) -
+ & lnrat(s, mudim) - lnrat(t, mudim)
+ res(0) = fac*(
+ & 2*ll*lnrat(m4mu, t) +
+ & Li2omrat2(q3, q2, t, m4) -
+ & Li2omrat2(q3, s, q4, m4) +
+ & 2*(Li2omrat2(q2, s, q4, t) -
+ & Li2omrat(q2, s) + Li2omrat(t, q4)) )
+ res(1) = fac*ll
+ res(2) = 0
+ endif
+
+ if( DEBUGLEVEL .gt. 1 ) then
+ print *, "D0m1p3:0 =", res(0)
+ print *, "D0m1p3:1 =", res(1)
+ print *, "D0m1p3:2 =", res(2)
+ endif
+ end
+
+************************************************************************
+
+ subroutine D0m2p3(res, para, perm)
+ implicit none
+ ComplexType res(0:2)
+ RealType para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ RealType s, t, m3, m4, q3, q4, p3, fac, m3mu
+ RealType p34, c, s3t, s4s, tmp
+ ComplexType ls, lt, lq3, lq4, d
+ ComplexType x43(4), r3t, r4s, r43p, r43m
+ ComplexType logs, dilogs
+ integer ir, case
+
+ ComplexType Li2rat, Li2omrat, Li2omrat2
+ external Li2rat, Li2omrat, Li2omrat2
+
+ if( DEBUGLEVEL .gt. 1 ) call DDump("D0m2p3", para,1, perm)
+
+ m3 = Mx(3)
+ s = m3 - Px(5)
+ q3 = m3 - Px(2)
+ m4 = Mx(4)
+ t = m4 - Px(6)
+ q4 = m4 - Px(4)
+
+ if( abs(s) .lt. diffeps .or. abs(t) .lt. diffeps ) then
+* switch from p1234 to p2134 = 1536242134
+ tmp = s
+ s = q3
+ q3 = tmp
+ tmp = t
+ t = q4
+ q4 = tmp
+ endif
+
+ fac = 1/(s*t - q3*q4)
+
+ ir = 0
+ if( abs(q3) .lt. diffeps ) ir = 1
+ if( abs(q4) .lt. diffeps ) then
+ ir = ir + 1
+ q4 = q3
+ tmp = s
+ s = t
+ t = tmp
+ m4 = m3
+ m3 = Mx(4)
+ endif
+
+ res(2) = .5D0*fac*ir
+
+ p3 = Px(3)
+ if( abs(p3) .lt. zeroeps ) then
+ case = 1
+ logs = lnrat(m3, m4)**2
+ else
+ p34 = p3 + m3 - m4
+ c = -4*p3*m3
+ d = sqrt(ToComplex(p34**2 + c))
+
+ x43(1) = -p34 - d
+ x43(2) = p34 - d
+ if( abs(x43(1)) .lt. abs(x43(2)) ) then
+ x43(1) = c/x43(2)
+ else
+ x43(2) = c/x43(1)
+ endif
+
+ p34 = -p3 + m3 - m4
+ c = -4*p3*m4
+
+ x43(3) = -p34 - d
+ x43(4) = p34 - d
+ if( abs(x43(3)) .lt. abs(x43(4)) ) then
+ x43(3) = c/x43(4)
+ else
+ x43(4) = c/x43(3)
+ endif
+
+ if( abs(Im(d)) .lt. zeroeps ) then
+ case = 2
+ logs = lnrat(x43(1), x43(3))**2 +
+ & lnrat(x43(2), x43(4))**2
+ else
+ case = 3
+ r43p = x43(1)/x43(3)
+ r43m = x43(2)/x43(4)
+ logs = ln(r43p, 0)**2 + ln(r43m, 0)**2
+ endif
+ endif
+
+ goto (1, 2) ir
+
+* qlbox13: D0(0, p2, p3, p4; p1p2, p2p3; 0, 0, m3, m4)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0m2p3: qlbox13"
+
+ ls = lnrat(s, mudim)
+ lt = lnrat(t, mudim)
+ lq3 = lnrat(q3, mudim)
+ lq4 = lnrat(q4, mudim)
+
+ if( case .eq. 1 ) then
+ dilogs = Li2omrat2(q3, t, -1D0, -1D0) +
+ & Li2omrat2(q3, t, m4, m3) +
+ & Li2omrat2(q4, s, m3, m4) +
+ & Li2omrat2(q4, s, -1D0, -1D0)
+ else if( case .eq. 2 ) then
+ dilogs = Li2omrat2(q3, t, x43(4), x43(2)) +
+ & Li2omrat2(q3, t, x43(3), x43(1)) +
+ & Li2omrat2(q4, s, x43(1), x43(3)) +
+ & Li2omrat2(q4, s, x43(2), x43(4))
+ else
+ r3t = q3/t
+ s3t = sign(.5D0, q3) - sign(.5D0, t)
+ r4s = q4/s
+ s4s = sign(.5D0, q4) - sign(.5D0, s)
+ dilogs = Li2rat(r3t,s3t, 1/r43m,0D0) +
+ & Li2rat(r3t,s3t, 1/r43p,0D0) +
+ & Li2rat(r4s,s4s, r43p,0D0) +
+ & Li2rat(r4s,s4s, r43m,0D0)
+ endif
+
+ res(0) = -fac*(dilogs + .5D0*logs + lq3**2 + lq4**2 +
+ & 2*(Li2omrat(q3, s) + Li2omrat(q4, t) -
+ & Li2omrat2(q3, s, q4, t) - ls*lt) +
+ & (lt - lq3)*log(m3/mudim) + (ls - lq4)*log(m4/mudim))
+ res(1) = fac*(lq3 + lq4 - ls - lt)
+ goto 9
+
+1 continue
+* qlbox12: D0(0, m3, p3, p4; p1p2, p2p3; 0, 0, m3, m4)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0m2p3: qlbox12"
+
+ m3mu = sqrt(m3*mudim)
+ ls = lnrat(s, m3mu)
+ lt = lnrat(t, m3mu)
+ lq4 = lnrat(q4, m3mu)
+
+ if( case .eq. 1 ) then
+ dilogs = Li2omrat2(q4, s, m3, m4) +
+ & Li2omrat2(q4, s, -1D0, -1D0)
+ else if( case .eq. 2 ) then
+ dilogs = Li2omrat2(q4, s, x43(1), x43(3)) +
+ & Li2omrat2(q4, s, x43(2), x43(4))
+ else
+ r4s = q4/s
+ s4s = sign(.5D0, q4) - sign(.5D0, s)
+ dilogs = Li2rat(r4s,s4s, r43p,0D0) +
+ & Li2rat(r4s,s4s, r43m,0D0)
+ endif
+
+ res(0) = -fac*(dilogs + .5D0*logs + pi12 +
+ & 2*(Li2omrat(q4, t) - ls*lt) +
+ & lq4**2 + (ls - lq4)*log(m4/m3))
+ res(1) = fac*(lq4 - ls - lt)
+ goto 9
+
+2 continue
+* qlbox11: D0(0, m3, p3, m4; p1p2, p2p3; 0, 0, m3, m4)
+
+* qlbox11a: D0(0, p2, p3, p4; m3, m4; 0, 0, m3, m4)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0m2p3: qlbox11"
+
+ ls = lnrat(s, sqrt(m3*mudim))
+ lt = lnrat(t, sqrt(m4*mudim))
+
+ res(0) = fac*(.25D0*log(m3/m4)**2 -
+ & .5D0*(logs + pi**2) + 2*ls*lt)
+ res(1) = -fac*(ls + lt)
+
+9 if( DEBUGLEVEL .gt. 1 ) then
+ print *, "D0m2p3:0 =", res(0)
+ print *, "D0m2p3:1 =", res(1)
+ print *, "D0m2p3:2 =", res(2)
+ endif
+ end
+
+************************************************************************
+* this routine is adapted from Ansgar Denner's bcanew.f
+* to the conventions of LoopTools;
+* it is used for double-checking the results of FF
+* M. Rauch: implemented the log branch cuts for k13 < 2
+* (from Denner, Nierste, Scharf; Nucl Phys B367 (1991) 637)
+
+cc#define AddEps(k) k*ToComplex(1D0, -sign(eps, k))
+c#define AddEps(k) k*(1 - sign(1D0, k)*cIeps)
+#define AddEps(k) (k - max(abs(k), 1D0)*cIeps)
+c#define k2r(k) (.5D0*k*(1 + sqrt(ToComplex((1 - 2/k)*(1 + 2/k)))))
+#define k2r(k) (.5D0*(k + sign(1D0, Re(k))*sqrt(ToComplex((k - 2)*(k + 2)))))
+
+ subroutine D0m4(res, para)
+ implicit none
+ ComplexType res
+ RealType para(1,*)
+
+#include "lt.h"
+#include "perm.h"
+
+ RealType tmp, ir1324, gamma, s1, s2
+ RealType kij(6), irij(6), ix(2,4)
+ ComplexType rij(6), x(2,4), l(2,4), q13, q24
+ ComplexType a, b, c, d, disc, ki, etas
+ integer j
+
+ RealType k12, k13, k14, k23, k24, k34
+ RealType ir12, ir13, ir14, ir23, ir24, ir34
+ ComplexType r12, r14, r13, r23, r24, r34
+ equivalence (kij(1), k12), (rij(1), r12), (irij(1), ir12)
+ equivalence (kij(2), k23), (rij(2), r23), (irij(2), ir23)
+ equivalence (kij(3), k34), (rij(3), r34), (irij(3), ir34)
+ equivalence (kij(4), k14), (rij(4), r14), (irij(4), ir14)
+ equivalence (kij(5), k13), (rij(5), r13), (irij(5), ir13)
+ equivalence (kij(6), k24), (rij(6), r24), (irij(6), ir24)
+
+ ComplexType xspence, xeta, xetatilde
+ integer eta
+ external xspence, xeta, xetatilde, eta
+
+ if( DEBUGLEVEL .gt. 0 ) call DDump("D0m4", para,1, p1234)
+
+ k12 = (M(1) + M(2) - P(1))/sqrt(M(1)*M(2))
+ k23 = (M(2) + M(3) - P(2))/sqrt(M(2)*M(3))
+ k34 = (M(3) + M(4) - P(3))/sqrt(M(3)*M(4))
+ k14 = (M(1) + M(4) - P(4))/sqrt(M(1)*M(4))
+ k13 = (M(1) + M(3) - P(5))/sqrt(M(1)*M(3))
+ k24 = (M(2) + M(4) - P(6))/sqrt(M(2)*M(4))
+
+* test if r_13 can be made real by a permutation
+* if one of the r_ij is real r_13 must be made real => case 1
+ if( abs(k13) .ge. 2 ) then
+* nothing to do
+* otherwise try all permutations
+ else if( abs(k12) .ge. 2 ) then
+* 2 <-> 3
+ tmp = k12
+ k12 = k13
+ k13 = tmp
+ tmp = k24
+ k24 = k34
+ k34 = tmp
+ else if( abs(k14) .ge. 2 ) then
+* 3 <-> 4
+ tmp = k13
+ k13 = k14
+ k14 = tmp
+ tmp = k23
+ k23 = k24
+ k24 = tmp
+ else if( abs(k23) .ge. 2 ) then
+* 1 <-> 2
+ tmp = k13
+ k13 = k23
+ k23 = tmp
+ tmp = k14
+ k14 = k24
+ k24 = tmp
+ else if( abs(k24) .ge. 2 ) then
+* 1 -> 4, 2 -> 1, 3 -> 2, 4 -> 3
+ tmp = k12
+ k12 = k23
+ k23 = k34
+ k34 = k14
+ k14 = tmp
+ tmp = k13
+ k13 = k24
+ k24 = tmp
+ else if( abs(k34) .ge. 2 ) then
+* 1 <-> 4
+ tmp = k12
+ k12 = k24
+ k24 = tmp
+ tmp = k13
+ k13 = k34
+ k34 = tmp
+* else
+* nothing found => all r_ij on the complex unit circle => case 2
+ endif
+
+ r12 = k2r(k12)
+ r23 = k2r(k23)
+ r34 = k2r(k34)
+ r14 = k2r(k14)
+ r13 = 1/k2r(k13)
+ r24 = 1/k2r(k24)
+
+ do j = 1, 6
+ if( Im(rij(j)) .eq. 0 ) then
+ ki = kij(j) - cIeps
+ irij(j) = sign(1D0, abs(rij(j)) - 1)*
+ & Im(k2r(ki))
+ else
+ irij(j) = 0
+ endif
+ enddo
+
+ ir1324 = sign(1D0, Re(r24))*ir13 -
+ & sign(1D0, Re(r13))*ir24
+
+ a = k34/r24 - k23 + (k12 - k14/r24)*r13
+ b = (1/r13 - r13)*(1/r24 - r24) + k12*k34 - k14*k23
+ c = k34*r24 - k23 + (k12 - k14*r24)/r13
+ d = k23 + (r24*k14 - k12)*r13 - r24*k34
+ disc = sqrt(b**2 - 4*a*(c + d*cIeps))
+ ix(1,4) = Im(.5D0/a*(b - disc))
+ ix(2,4) = Im(.5D0/a*(b + disc))
+
+ disc = sqrt(b**2 - 4*a*c)
+ x(1,4) = .5D0/a*(b - disc)
+ x(2,4) = .5D0/a*(b + disc)
+ if( abs(x(1,4)) .gt. abs(x(2,4)) ) then
+ x(2,4) = c/(a*x(1,4))
+ else
+ x(1,4) = c/(a*x(2,4))
+ endif
+
+ x(1,1) = x(1,4)/r24
+ x(2,1) = x(2,4)/r24
+ x(1,2) = x(1,4)*r13/r24
+ x(2,2) = x(2,4)*r13/r24
+ x(1,3) = x(1,4)*r13
+ x(2,3) = x(2,4)*r13
+
+ s1 = sign(1D0, Re(x(1,4)))
+ s2 = sign(1D0, Re(x(2,4)))
+ ix(1,1) = ix(1,4)*Re(x(1,1))*s1
+ ix(2,1) = ix(2,4)*Re(x(2,1))*s2
+ ix(1,2) = ix(1,4)*Re(x(1,2))*s1
+ ix(2,2) = ix(2,4)*Re(x(2,2))*s2
+ ix(1,3) = ix(1,4)*Re(x(1,3))*s1
+ ix(2,3) = ix(2,4)*Re(x(2,3))*s2
+
+ res = 0
+ do j = 1, 4
+ res = res + Sgn(j)*(
+ & xspence(x(1,j), ix(1,j), rij(j), irij(j)) +
+ & xspence(x(1,j), ix(1,j), 1/rij(j), -irij(j)) )
+ enddo
+
+ gamma = sign(1D0, Re(a*(x(2,4) - x(1,4))))
+ l(1,4) = c2ipi*eta(r13, ir13, 1/r24, -ir24, ir1324)
+ l(2,4) = l(1,4)
+
+ if( Im(r13) .eq. 0 ) then
+ r12 = k12 - r24*k14
+ r23 = k23 - r24*k34
+ r34 = k34 - r13*k14
+ r14 = k23 - r13*k12
+ q13 = k13 - 2*r13
+ q24 = k24 - 2*r24
+
+ c = gamma*sign(1D0, Im(r24) + ir24)
+ l(1,1) = ln(-x(1,1), -ix(1,1)) +
+ & ln(r14 - q13/x(1,1), -1) +
+ & ln((r12 - q24*x(1,4))/d, c)
+ l(2,1) = ln(-x(2,1), -ix(2,1)) +
+ & ln(r14 - q13/x(2,1), -1) +
+ & ln((r12 - q24*x(2,4))/d, -c)
+
+ c = gamma*sign(1D0, Re(r13)*(Im(r24) + ir24))
+ l(1,2) = ln(-x(1,2), -ix(1,2)) +
+ & ln(r14 - q13/x(1,1), -1) +
+ & ln((r23 - q24*x(1,3))/d, c)
+ l(2,2) = ln(-x(2,2), -ix(2,2)) +
+ & ln(r14 - q13/x(2,1), -1) +
+ & ln((r23 - q24*x(2,3))/d, -c)
+
+ l(1,3) = ln(-x(1,3), -ix(1,3)) +
+ & ln(r34 - q13/x(1,4), -1) +
+ & ln((r23 - q24*x(1,3))/d, c)
+ l(2,3) = ln(-x(2,3), -ix(2,3)) +
+ & ln(r34 - q13/x(2,4), -1) +
+ & ln((r23 - q24*x(2,3))/d, -c)
+
+ etas =
+ & xetatilde(x(1,4), ix(1,4), r13, ir13, l(1,3)) +
+ & xetatilde(x(1,4), ix(1,4), 1/r24, -ir24, l(1,1)) -
+ & xetatilde(x(1,4), ix(1,4), r13/r24, ir1324, l(1,2)) +
+ & xetatilde(x(1,4), ix(1,4), -r13/r24, -ir1324, l(1,4))
+ else
+ do j = 1, 3
+ l(1,j) = log(-x(1,j)) +
+ & ln(kij(j) - 1/x(1,j) - x(1,j), -x(1,j)*b*gamma)
+ l(2,j) = log(-x(2,j)) +
+ & ln(kij(j) - 1/x(2,j) - x(2,j), -x(2,j)*b*gamma)
+ enddo
+
+ etas =
+ & xeta(x(1,4), ix(1,4), r13, ir13, ix(1,3), l(1,3)) +
+ & xeta(x(1,4), ix(1,4), 1/r24, -ir24, ix(1,1), l(1,1)) -
+ & xeta(x(1,4), ix(1,4), r13/r24, ir1324, ix(1,2), l(1,2)) +
+ & xeta(x(1,4), ix(1,4), -r13/r24, -ir1324, ix(1,4), l(1,4))*
+ & (1 - sign(1D0, Re(b))*gamma)
+ endif
+
+ res = (res - c2ipi*etas + (l(2,2) - l(1,2))*l(1,4))/
+ & (sqrt(M(1)*M(2)*M(3)*M(4))*disc)
+
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0m4 =", res
+ end
+
+************************************************************************
+
+ subroutine D0m3(res, para, perm)
+ implicit none
+ ComplexType res
+ RealType para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ RealType m2, m3, m4, p1, p2, p3, p4, p1p2, p2p3
+ RealType m, k12, k13, k14, k23, k24, k34
+ RealType ir12, ir14, ir24, ix1(2), ix4(2)
+ ComplexType r12, r14, r24, q12, q24
+ ComplexType x1(2), x4(2), l4(2)
+ ComplexType a, b, c, d
+
+ ComplexType xspence, xetatilde
+ external xspence, xetatilde
+
+ if( DEBUGLEVEL .gt. 1 ) call DDump("D0m3", para,1, perm)
+
+ m2 = Mx(2)
+ m3 = Mx(3)
+ m4 = Mx(4)
+ p1 = Px(1)
+ p2 = Px(2)
+ p3 = Px(3)
+ p4 = Px(4)
+ p1p2 = Px(5)
+ p2p3 = Px(6)
+
+ m = sqrt(m3*m4)
+ k23 = (m4 - p4)/m
+ k12 = (m4 + m3 - p3)/m
+ r12 = k2r(k12)
+ ir12 = 0
+ if( k12 .lt. -2 ) ir12 = sign(10D0, 1 - abs(r12))
+
+ m = sqrt(m2*m3)
+ k34 = (m2 - p1)/m
+ k14 = (m2 + m3 - p2)/m
+ r14 = k2r(k14)
+ ir14 = 0
+ if( k14 .lt. -2 ) ir14 = sign(10D0, 1 - abs(r14))
+
+ k13 = (m3 - p1p2)/m3
+
+ m = sqrt(m2*m4)
+ k24 = (m2 + m4 - p2p3)/m
+ r24 = k2r(k24)
+ ir24 = 0
+ if( k24 .lt. -2 ) ir24 = sign(10D0, 1 - abs(r24))
+
+ q24 = r24 - 1/r24
+ q12 = k12 - r24*k14
+
+ a = k34/r24 - k23
+ b = k12*k34 - k13*q24 - k14*k23
+ c = k13*q12 + r24*k34 - k23
+ d = sqrt(ToComplex((k12*k34 - k13*k24 - k14*k23)**2 -
+ & 4*(k13*(k13 - k23*(k12 - k14*k24)) +
+ & k23*(k23 - k24*k34) + k34*(k34 - k13*k14))))
+ x4(1) = .5D0/a*(b - d)
+ x4(2) = .5D0/a*(b + d)
+ if( abs(x4(1)) .gt. abs(x4(2)) ) then
+ x4(2) = c/(a*x4(1))
+ else
+ x4(1) = c/(a*x4(2))
+ endif
+
+ d = -k34*r24 + k23
+ ix4(1) = sign(1D0, Re(d))
+ ix4(2) = -ix4(1)
+
+ x1(1) = x4(1)/r24
+ x1(2) = x4(2)/r24
+ ix1(1) = sign(1D0, ix4(1)*Re(r24))
+ ix1(2) = -ix1(1)
+
+ c = ln(k13, -1)
+ l4(1) = c + ln((q12 + q24*x4(1))/d, Re(q24*ix4(1)/d))
+ l4(2) = c + ln((q12 + q24*x4(2))/d, Re(q24*ix4(2)/d))
+
+ res = (
+ & xspence(x4, ix4, r14, ir14) +
+ & xspence(x4, ix4, 1/r14, -ir14) -
+ & xspence(x4, ix4, ToComplex(k34/k13), -k13) -
+ & xspence(x1, ix1, r12, ir12) -
+ & xspence(x1, ix1, 1/r12, -ir12) +
+ & xspence(x1, ix1, ToComplex(k23/k13), -k13) -
+ & c2ipi*xetatilde(x4, ix4, 1/r24, -ir24, l4)
+ & )/(m3*m*a*(x4(2) - x4(1)))
+
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0m3 =", res
+ end
+
+************************************************************************
+
+ subroutine D0m2(res, para, perm)
+ implicit none
+ ComplexType res
+ RealType para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ RealType m3, m4, p1, p2, p3, p4, p1p2, p2p3
+ RealType m, k12, k13, k14, k23, k24, k34
+ ComplexType k12c, k13c, k23c, k24c, k34c
+ ComplexType r14, x4(2)
+ ComplexType a, b, c, disc
+
+ ComplexType xspence
+ external xspence
+
+ RealType imzero(2)
+ data imzero /0D0, 0D0/
+
+ if( DEBUGLEVEL .gt. 1 ) call DDump("D0m2", para,1, perm)
+
+ m3 = Mx(3)
+ m4 = Mx(4)
+ p1 = Px(1)
+ p2 = Px(2)
+ p3 = Px(3)
+ p4 = Px(4)
+ p1p2 = Px(5)
+ p2p3 = Px(6)
+
+ k12 = (m3 - p2)/m3
+ k12c = AddEps(k12)
+
+ k13 = (m3 - p1p2)/m3
+ k13c = AddEps(k13)
+
+ k23 = -p1/m3
+ k23c = AddEps(k23)
+
+ m = sqrt(m3*m4)
+ k24 = (m4 - p2p3)/m
+ k24c = AddEps(k24)/k12c
+ k34 = (m4 - p4)/m
+ k34c = AddEps(k34)/k13c
+ k14 = (m3 + m4 - p3)/m
+ r14 = k2r(k14)
+ r14 = r14*(1 + cIeps*sign(1D0, Re(1/r14 - r14)))
+c r14 = r14*ToComplex(1D0, sign(eps, Re(1/r14 - r14)))
+
+ a = k34*k24 - k23
+ b = k13*k24 + k12*k34 - k14*k23
+ c = k13*k12 - k23*(1 - cIeps)
+ disc = sqrt(b**2 - 4*a*c)
+ x4(1) = .5D0/a*(b - disc)
+ x4(2) = .5D0/a*(b + disc)
+ if( abs(x4(1)) .gt. abs(x4(2)) ) then
+ x4(2) = c/(a*x4(1))
+ else
+ x4(1) = c/(a*x4(2))
+ endif
+
+ res = (
+ & xspence(x4, imzero, r14, 0D0) +
+ & xspence(x4, imzero, 1/r14, 0D0) -
+ & xspence(x4, imzero, k34c, 0D0) -
+ & xspence(x4, imzero, k24c, 0D0) +
+ & (log(x4(2)) - log(x4(1)))*
+ & (log(k12c) + log(k13c) - log(k23c))
+ & )/(m3*m*a*(x4(2) - x4(1)))
+
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0m2 =", res
+ end
+
+************************************************************************
+
+ subroutine D0m1(res, para, perm)
+ implicit none
+ ComplexType res
+ RealType para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ RealType m4, k12, k13, k14, k23, k24, k34
+ ComplexType k12c, k13c, k14c, k23c, k24c, k34c
+ RealType a, b
+ ComplexType c, disc, x4(2)
+
+ ComplexType xspence
+ external xspence
+
+ RealType imzero(2)
+ data imzero /0D0, 0D0/
+
+ if( DEBUGLEVEL .gt. 1 ) call DDump("D0m1", para,1, perm)
+
+ m4 = Mx(4)
+ k12 = (m4 - Px(3))/m4
+ k12c = AddEps(k12)
+ k13 = (m4 - Px(4))/m4
+ k13c = AddEps(k13)
+ k14 = (m4 - Px(6))/m4
+ k14c = AddEps(k14)
+ k23 = -Px(5)/m4
+ k23c = AddEps(k23)
+ k24 = -Px(2)/m4
+ k24c = AddEps(k24)/k12c
+ k34 = -Px(1)/m4
+ k34c = AddEps(k34)/k13c
+
+ a = k34*k24
+ b = k13*k24 + k12*k34 - k14*k23
+ c = k13*k12 - k23*(1 - cIeps)
+ disc = sqrt(b*b - 4*a*c)
+ x4(1) = .5D0/a*(b - disc)
+ x4(2) = .5D0/a*(b + disc)
+ if( abs(x4(1)) .gt. abs(x4(2)) ) then
+ x4(2) = c/(a*x4(1))
+ else
+ x4(1) = c/(a*x4(2))
+ endif
+
+ res = (
+ & xspence(x4, imzero, k14c, 0D0) -
+ & xspence(x4, imzero, k34c, 0D0) -
+ & xspence(x4, imzero, k24c, 0D0) +
+ & (log(x4(2)) - log(x4(1)))*
+ & (log(k12c) + log(k13c) - log(k23c))
+ & )/(m4**2*a*(x4(2) - x4(1)))
+
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0m1 =", res
+ end
+
+************************************************************************
+
+ subroutine D0m0(res, para)
+ implicit none
+ ComplexType res
+ RealType para(1,*)
+
+#include "lt.h"
+#include "perm.h"
+
+ RealType m2, k12, k13, k14, k23, k24, k34
+ ComplexType k12c, k13c, k14c, k23c, k24c, k34c
+ RealType a, b
+ ComplexType c, disc, x4(2)
+
+ ComplexType xspence
+ external xspence
+
+ RealType imzero(2)
+ data imzero /0D0, 0D0/
+
+ if( DEBUGLEVEL .gt. 1 ) call DDump("D0m0", para,1, p1234)
+
+ m2 = abs(P(6))
+ k12 = -P(1)/m2
+ k12c = AddEps(k12)
+ k13 = -P(5)/m2
+ k13c = AddEps(k13)
+ k14 = -P(4)/m2
+ k14c = AddEps(k14)
+ k23 = -P(2)/m2
+ k23c = AddEps(k23)
+ k24 = -P(6)/m2
+ k24c = AddEps(k24)/k12c
+ k34 = -P(3)/m2
+ k34c = AddEps(k34)/k13c
+
+ a = k34*k24
+ b = k13*k24 + k12*k34 - k14*k23
+ c = k13*k12 + k23*cIeps
+ disc = sqrt(b*b - 4*a*c)
+ x4(1) = .5D0/a*(b - disc)
+ x4(2) = .5D0/a*(b + disc)
+ if( abs(x4(1)) .gt. abs(x4(2)) ) then
+ x4(2) = c/(a*x4(1))
+ else
+ x4(1) = c/(a*x4(2))
+ endif
+
+ res = (
+ & (log(x4(2)) - log(x4(1)))*
+ & (-.5D0*(log(x4(2)) + log(x4(1))) +
+ & log(k12c) + log(k13c) - log(k23c) - log(k14c)) -
+ & xspence(x4, imzero, k34c, 0D0) -
+ & xspence(x4, imzero, k24c, 0D0)
+ & )/(m2**2*a*(x4(2) - x4(1)))
+
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0m0 =", res
+ end
+
+************************************************************************
+
+ ComplexType function xspence(z1, im1, z2, im2)
+ implicit none
+ ComplexType z1(2), z2
+ RealType im1(2), im2
+
+#include "lt.h"
+
+ ComplexType cspence
+ external cspence
+
+ xspence = cspence(z1(2), im1(2), z2, im2) -
+ & cspence(z1(1), im1(1), z2, im2)
+ end
+
+************************************************************************
+
+ ComplexType function cspence(z1, im1, z2, im2)
+ implicit none
+ ComplexType z1, z2
+ RealType im1, im2
+
+#include "lt.h"
+
+ ComplexType spence
+ integer eta
+ external spence, eta
+
+ ComplexType z12
+ RealType im12
+ integer etas
+
+ z12 = z1*z2
+ im12 = im2*sign(1D0, Re(z1))
+ if( Re(z12) .gt. .5D0 ) then
+ cspence = spence(1, z12, 0D0)
+ etas = eta(z1, im1, z2, im2, im12)
+ if( etas .ne. 0 ) cspence = cspence +
+ & etas*ln(1 - z12, -im12)*c2ipi
+ else if( abs(z12) .lt. 1D-4 ) then
+ cspence = pi6
+ if( abs(z12) .gt. 1D-14 ) cspence = cspence -
+ & spence(0, z12, 0D0) +
+ & (ln(z1, im1) + ln(z2, im2))*z12*
+ & (1 + z12*(.5D0 + z12*(1/3D0 + z12/4D0)))
+ else
+ cspence = pi6 - spence(0, z12, 0D0) -
+ & (ln(z1, im1) + ln(z2, im2))*ln(1 - z12, 0)
+ endif
+ end
+
+************************************************************************
+
+ ComplexType function xeta(z1, im1, z2, im2, im12, l1)
+ implicit none
+ ComplexType z1(2), z2, l1(2)
+ RealType im1(2), im2, im12
+
+#include "lt.h"
+
+ integer eta
+ external eta
+
+ xeta = l1(2)*eta(z1(2), im1(2), z2, im2, im12) -
+ & l1(1)*eta(z1(1), im1(1), z2, im2, im12)
+ end
+
+************************************************************************
+
+ ComplexType function xetatilde(z1, im1, z2, im2, l1)
+ implicit none
+ ComplexType z1(2), z2, l1(2)
+ RealType im1(2), im2
+
+#include "lt.h"
+
+ integer etatilde
+ external etatilde
+
+ xetatilde = l1(2)*etatilde(z1(2), im1(2), z2, im2) -
+ & l1(1)*etatilde(z1(1), im1(1), z2, im2)
+ end
+
+************************************************************************
+
+ integer function etatilde(c1, im1x, c2, im2x)
+ implicit none
+ ComplexType c1, c2
+ RealType im1x, im2x
+
+ RealType im1, im2
+
+ integer eta
+ external eta
+
+ im1 = Im(c1)
+ if( im1 .eq. 0 ) im1 = im1x
+ im2 = Im(c2)
+ if( im2 .ne. 0 ) then
+ etatilde = eta(c1, im1x, c2, 0D0, 0D0)
+ else if( Re(c2) .gt. 0 ) then
+ etatilde = 0
+ else if( im1 .gt. 0 .and. im2x .gt. 0 ) then
+ etatilde = -1
+ else if( im1 .lt. 0 .and. im2x .lt. 0 ) then
+ etatilde = 1
+ else
+ etatilde = 0
+#ifdef WARNINGS
+ if( im1 .eq. 0 .and. Re(c1) .lt. 0 .or.
+ & im2x .eq. 0 .and. Re(c1*c2) .lt. 0 )
+ & print *, "etatilde not defined"
+#endif
+ endif
+ end
+
diff --git a/Looptools/D/D0funcC.F b/Looptools/D/D0funcC.F
new file mode 100644
--- /dev/null
+++ b/Looptools/D/D0funcC.F
@@ -0,0 +1,982 @@
+* D0funcC.F
+* the scalar four-point function with complex masses
+* this file is part of LoopTools
+* last modified 1 Sep 14 th
+
+#include "externals.h"
+#include "types.h"
+
+#define npoint 4
+#include "defs.h"
+
+
+ subroutine D0funcC(res, para)
+ implicit none
+ ComplexType res(0:2), para(1,*)
+
+#include "lt.h"
+
+ external D0CsoftDR, D0CcollDR, D0Csoft, D0Ccoll
+
+ res(0) = 0
+ res(1) = 0
+ res(2) = 0
+
+ if( lambda .le. 0 ) then
+ call DCDispatch(res, para, D0CsoftDR, D0CcollDR)
+ else
+ call DCDispatch(res, para, D0Csoft, D0Ccoll)
+ endif
+ end
+
+************************************************************************
+
+ subroutine DCDispatch(res, para, soft, coll)
+ implicit none
+ ComplexType res(0:2), para(1,*)
+ external soft, coll
+
+#include "lt.h"
+#include "perm.h"
+
+ integer i, z, s, perm, ier, key
+ ComplexType alt
+
+ integer pperm(12)
+ data pperm /
+ & p1234, p1243, p1324,
+ & p2341, p2431, p2314,
+ & p3412, p3142, p3421,
+ & p4123, p4132, p4213 /
+
+* 0 1 1xxx O'1234561234'
+* 1 2 12xx O'1234561234'
+* 2 2 13xx O'5264131324'
+* 3 3 123x O'1234561234'
+* 4 2 14xx O'4321561432'
+* 5 3 124x O'1635421243'
+* 6 3 134x O'5361421342'
+* 7 4 xxxx O'1234561234'
+
+#define pj(p,j) ibits(p,3*(10-j),3)
+#define mj(p,j) ibits(p,3*(4-j),3)
+
+#define Pc(j) P(pj(perm,j))
+#define Mc(j) M(mj(perm,j))
+#define Px(j) Re(Pc(j))
+
+ z = 0
+ s = 0
+ do i = 1, 12
+ perm = pperm(i)
+c PRINT '(I3,O12)', i, perm
+c PRINT '(6F14.2)', Px(1), Px(2), Px(3), Px(4), Px(5), Px(6)
+c PRINT '(8F14.2)', Mc(1), Mc(2), Mc(3), Mc(4)
+ if( abs(Mc(1)) .lt. zeroeps ) then
+ if( abs(Px(1)) + abs(Mc(2)) .lt. zeroeps ) then
+ if( DEBUGLEVEL .gt. 0 )
+ & print '("collinear D0C, perm = ",O10)', perm
+ call coll(res, para, perm)
+ if( perm .eq. 0 ) return
+ endif
+ if( s .eq. 0 .and.
+ & abs(Px(1) - Mc(2)) +
+ & abs(Px(4) - Mc(4)) .lt. diffeps ) s = perm
+ if( z .eq. 0 ) z = perm
+ endif
+ enddo
+
+ if( s .ne. 0 ) then
+ if( DEBUGLEVEL .gt. 0 )
+ & print '("soft D0C, perm = ",O10)', s
+ call soft(res, para, s)
+ return
+ endif
+
+ key = ibits(versionkey, KeyD0C, 2)
+
+ if( key .ne. 1 ) then
+ call ffd0c(res(0), para, 0, ier)
+ if( key .eq. 0 ) return
+ alt = res(0)
+ endif
+
+ ier = 0
+ call ffd0c(res(0), para, 1, ier)
+
+ if( key .gt. 1 .and.
+ & abs(res(0) - alt) .gt. maxdev*abs(alt) ) then
+ print *, "Discrepancy in D0C:"
+ print *, " p1 =", P(1)
+ print *, " p2 =", P(2)
+ print *, " p3 =", P(3)
+ print *, " p4 =", P(4)
+ print *, " p1p2 =", P(5)
+ print *, " p2p3 =", P(6)
+ print *, " m1 =", M(1)
+ print *, " m2 =", M(2)
+ print *, " m3 =", M(3)
+ print *, " m4 =", M(4)
+ print *, "D0C a =", alt
+ print *, "D0C b =", res(0)
+ if( ier .le. errdigits ) res(0) = alt
+ endif
+
+ if( .not. btest(key, 1) ) res(0) = alt
+ end
+
+************************************************************************
+
+ subroutine DCDump(s, para, perm)
+ implicit none
+ character*(*) s
+ ComplexType para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ print '(A,", perm = ",O4)', s, iand(perm, O'7777')
+ if( DEBUGLEVEL .gt. 1 ) then
+ print *, "p1 =", Px(1)
+ print *, "p2 =", Px(2)
+ print *, "p3 =", Px(3)
+ print *, "p4 =", Px(4)
+ print *, "p1p2 =", Px(5)
+ print *, "p2p3 =", Px(6)
+ print *, "m1 =", Mc(1)
+ print *, "m2 =", Mc(2)
+ print *, "m3 =", Mc(3)
+ print *, "m4 =", Mc(4)
+ endif
+ end
+
+************************************************************************
+
+ subroutine D0Csoft(res, para, perm)
+ implicit none
+ ComplexType res, para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ RealType p1, p2, p3, p4, p1p2, p2p3
+ RealType r1, r4
+ ComplexType m3, r3
+ ComplexType xs, x2, x3, y, c, fac
+ ComplexType lxs, lx2, lx3, l1x2, l1x3, ly, lm
+ integer ier
+
+ ComplexType spence, bdK, bdKC, zfflo1
+ external spence, bdK, bdKC, zfflo1
+
+ m3 = Mc(3)
+ p1 = Px(1)
+ p2 = Px(2)
+ p3 = Px(3)
+ p4 = Px(4)
+ p1p2 = Px(5)
+ p2p3 = Px(6)
+
+ if( DEBUGLEVEL .gt. 0 ) call DCDump("D0Csoft", para, perm)
+
+ ier = 0
+
+ r1 = sqrt(p1)
+ r4 = sqrt(p4)
+ fac = .5D0/(r1*r4*(p1p2 - m3))
+ xs = bdK(p2p3, r1, r4)
+ lxs = -1
+ if( xs .ne. 1 ) then
+ lxs = log(xs)
+ fac = 2*xs/((1 - xs)*(1 + xs))*fac
+ endif
+
+* massless case
+* (should have been re-routed to real D0, keep here for safety)
+ if( abs(m3) .lt. zeroeps ) then
+ if( abs(p1 - p2) + abs(p3 - p4) .lt. diffeps ) then
+ res = -2*ln(-lambda/p1p2, 1)*lxs*fac
+ return
+ endif
+ y = (r1*(p3 - p4 + cIeps))/(r4*(p2 - p1 + cIeps))
+ ly = log(y)
+ c = ln(lambda/(r1*r4), 0) +
+ & ln((p2 - p1)/p1p2, p1 - p2) +
+ & ln((p3 - p4)/p1p2, p4 - p3)
+ if( xs .eq. 1 ) then
+ res = fac*(c - 2 - (1 + y)/(1 - y)*ly)
+ else
+ res = fac*(pi6 -
+ & spence(0, xs/y, 0D0) -
+ & (lxs + log(1/y))*zfflo1(xs/y, ier) -
+ & spence(0, xs*y, 0D0) -
+ & (lxs + ly)*(zfflo1(xs*y, ier) + .5D0*(lxs - ly)) +
+ & spence(0, xs**2, 0D0) +
+ & lxs*(2*zfflo1(xs**2, ier) - c))
+ endif
+ return
+ endif
+
+* massive case
+ r3 = sqrt(m3)
+ x2 = bdKC(p2, r1, r3)
+ x3 = bdKC(p3, r4, r3)
+ lx2 = log(x2)
+ lx3 = log(x3)
+ l1x3 = log(1/x3)
+ lm = 2*ln(r3*sqrt(lambda)/(m3 - p1p2), 1)
+ if( xs .eq. 1 ) then
+ c = -2
+ if( abs(x2 - x3) .gt. diffeps ) then
+ c = (1 + x2/x3)/(1 - x2/x3)*(lx2 + l1x3) +
+ & (1 + x2*x3)/(1 - x2*x3)*(lx2 + lx3) + 2
+ else if( abs(x2 - 1) .gt. diffeps ) then
+ c = -2*(x2**2 + 1)/((x2 - 1)*(x2 + 1))*lx2
+ endif
+ res = fac*(lm - c)
+ else
+ l1x2 = log(1/x2)
+ res = fac*( .5D0*pi**2 +
+ & lxs*(2*zfflo1(xs**2, ier) - lm) +
+ & spence(0, xs**2, 0D0) + lx2**2 + lx3**2 -
+ & spence(0, xs/(x2*x3), 0D0) -
+ & (lxs + l1x2 + l1x3)*zfflo1(xs/(x2*x3), ier) -
+ & spence(0, xs*x2/x3, 0D0) -
+ & (lxs + lx2 + l1x3)*zfflo1(xs*x2/x3, ier) -
+ & spence(0, xs/x2*x3, 0D0) -
+ & (lxs + l1x2 + lx3)*zfflo1(xs/x2*x3, ier) -
+ & spence(0, xs*x2*x3, 0D0) -
+ & (lxs + lx2 + lx3)*zfflo1(xs*x2*x3, ier) )
+ endif
+ end
+
+************************************************************************
+
+ ComplexType function bdKC(x, m1, m2)
+* this is actually -K from the Beenakker/Denner paper for D0soft
+ implicit none
+ RealType x, m1
+ ComplexType m2
+
+#include "lt.h"
+
+ ComplexType d, t
+
+ d = x - (m1 - m2)**2
+ if( abs(d) .lt. diffeps ) then
+ bdKC = 1
+ else
+ t = 4*m1*m2/(d + cIeps)
+ bdKC = -t/(sqrt(1 - t) + 1)**2
+ endif
+ end
+
+************************************************************************
+
+ subroutine D0Ccoll(res, para, perm)
+ implicit none
+ ComplexType res, para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ logical ini
+ data ini /.FALSE./
+
+ if( DEBUGLEVEL .gt. 0 ) call DCDump("D0coll", para, perm)
+
+ Pc(1) = max(minmass, 1D-14)
+
+ if( ini ) return
+ print *, "collinear-divergent D0C, using mass cutoff ", Px(1)
+ ini = .TRUE.
+ end
+
+************************************************************************
+* IR-divergent D0 in dim reg
+* from W. Beenakker and A. Denner, NPB 338 (1990) 349
+
+ subroutine D0CsoftDR(res, para, perm)
+ implicit none
+ ComplexType res(0:2), para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ RealType m2, m4, p2, p3, p2p3
+ RealType r1, r4, m24, sy, q2, q3
+ ComplexType m3, r3, t, fac
+ ComplexType c, xs, x2, x3, lxs, lx2, lx3, lm, y
+
+ ComplexType bdK, bdKC, Li2omx2, Li2omx3
+ external bdK, bdKC, Li2omx2, Li2omx3
+
+ if( DEBUGLEVEL .gt. 0 ) call DCDump("D0CsoftDR", para, perm)
+
+ m3 = Mc(3)
+ t = m3 - Px(5)
+ p2p3 = Px(6)
+
+ m2 = Px(1)
+ p2 = Px(2)
+ q2 = m2 - p2
+ m4 = Px(4)
+ p3 = Px(3)
+ q3 = m4 - p3
+
+ r1 = sqrt(m2)
+ r4 = sqrt(m4)
+
+ fac = .5D0/(r1*r4*t)
+ xs = bdK(p2p3, r1, r4)
+ lxs = -1
+ if( xs .ne. 1 ) then
+ lxs = log(xs)
+ fac = 2*xs/((1 - xs)*(1 + xs))*fac
+ endif
+
+ res(1) = fac*lxs
+ res(2) = 0
+
+ if( abs(m3) .lt. zeroeps ) then
+* (should have been re-routed to real D0, keep here for safety)
+ if( abs(q2) + abs(q3) .lt. diffeps ) then
+* qlbox14: D0(m2, m2, m4, m4; p1p2, p2p3; 0, m2, 0, m4)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0CsoftDR: qlbox14"
+ res(1) = 2*res(1)
+ res(0) = res(1)*lnrat(mudim, t)
+ return
+ endif
+
+* qlbox15: D0(m2, p2, p3, m4; p1p2, p2p3; 0, m2, 0, m4)
+* Beenakker-Denner Eq. (2.11)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0CsoftDR: qlbox15"
+
+ if( abs(q2*q3) .lt. diffeps ) then
+ m24 = m2
+ if( abs(q2) .lt. diffeps ) m24 = m4
+ res(0) = fac*( lxs*(lxs + log(mudim/m24) +
+ & 2*lnrat(q2 + q3, t)) +
+ & Li2omx2(xs, 1D0, xs, 1D0) )
+ return
+ endif
+
+ y = r1*q3/(r4*q2)
+ sy = sign(.5D0, r1*q3) - sign(.5D0, r4*q2)
+
+ if( xs .eq. 1 ) then
+ res(0) = fac*( -log(mudim/(r1*r4)) +
+ & lnrat(q2, t) + lnrat(q3, t) + 2 +
+ & (1 + y)/(1 - y)*ln(y, sy) )
+ else
+ res(0) = fac*( -.5D0*ln(y, sy)**2 +
+ & lxs*(.5D0*lxs + lnrat(q2, t) + lnrat(q3, t) +
+ & log(mudim/(r1*r4))) +
+ & Li2omx2(xs, 1D0, xs, 1D0) -
+ & Li2omx2(xs, 1D0, y, sy) -
+ & Li2omx2(xs, 1D0, 1/y, -sy) )
+ endif
+ return
+ endif
+
+* qlbox16: D0(m2, p2, p3, m4; p1p2, p2p3; 0, m2, m3, m4)
+* Beenakker-Denner Eq. (2.9)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0softDR: qlbox16"
+
+ r3 = sqrt(m3)
+ x2 = bdKC(p2, r1, r3)
+ x3 = bdKC(p3, r4, r3)
+ lx2 = log(x2)
+ lx3 = log(x3)
+
+ lm = 2*lnrat(sqrt(m3*mudim), t)
+
+ if( xs .eq. 1 ) then
+ c = -2
+ if( abs(x2 - x3) .gt. diffeps ) then
+ c = (1 + x2/x3)/(1 - x2/x3)*(lx2 + log(1/x3)) +
+ & (1 + x2*x3)/(1 - x2*x3)*(lx2 + lx3) + 2
+ else if( abs(x2 - 1) .gt. diffeps ) then
+ c = -2*(x2**2 + 1)/((x2 - 1)*(x2 + 1))*lx2
+ endif
+ res(0) = fac*(c - lm)
+ else
+ res(0) = fac*(lm*lxs - lx2**2 - lx3**2 +
+ & Li2omx2(xs, 1D0, xs, 1D0) -
+ & Li2omx3(xs, 1D0, x2, 1D0, x3, 1D0) -
+ & Li2omx3(xs, 1D0, 1/x2, -1D0, 1/x3, -1D0) -
+ & Li2omx3(xs, 1D0, x2, 1D0, 1/x3, -1D0) -
+ & Li2omx3(xs, 1D0, 1/x2, -1D0, x3, 1D0))
+ endif
+ end
+
+************************************************************************
+
+ subroutine D0CcollDR(res, para, perm_)
+ implicit none
+ ComplexType res(0:2), para(1,*)
+ integer perm_
+
+#include "lt.h"
+#include "perm.h"
+
+ integer perm, z, s
+
+* # of non-zero momenta
+ integer nz1, nz2, nz3
+ parameter (nz1 = 1073741824) ! O'10000000000'
+ parameter (nz2 = -2147483648) ! O'20000000000'
+ parameter (nz3 = -1073741824) ! O'30000000000'
+
+ integer nz1p1234, nz2p1234, nz3p1234
+ parameter (nz1p1234 = nz1 + p1234)
+ parameter (nz2p1234 = nz2 + p1234)
+ parameter (nz3p1234 = nz3 + p1234)
+ integer nz1p1243, nz2p1243, nz3p1243
+ parameter (nz1p1243 = nz1 + p1243)
+ parameter (nz2p1243 = nz2 + p1243)
+ parameter (nz3p1243 = nz3 + p1243)
+ integer nz1p2134, nz2p2134, nz3p2134
+ parameter (nz1p2134 = nz1 + p2134)
+ parameter (nz2p2134 = nz2 + p2134)
+ parameter (nz3p2134 = nz3 + p2134)
+ integer nz1p2143, nz2p2143, nz3p2143
+ parameter (nz1p2143 = nz1 + p2143)
+ parameter (nz2p2143 = nz2 + p2143)
+ parameter (nz3p2143 = nz3 + p2143)
+ integer nz1p3214, nz2p3214, nz3p3214
+ parameter (nz1p3214 = nz1 + p3214)
+ parameter (nz2p3214 = nz2 + p3214)
+ parameter (nz3p3214 = nz3 + p3214)
+ integer nz1p4213, nz2p4213, nz3p4213
+ parameter (nz1p4213 = nz1 + p4213)
+ parameter (nz2p4213 = nz2 + p4213)
+ parameter (nz3p4213 = nz3 + p4213)
+
+ integer pperm(0:127)
+ data pperm /
+* 1ppppp12mm 0ppp 1
+* 3m 0ppp 1
+* m4 0ppp 1432652143
+* 34 0ppp 1
+ & nz3p1234, nz3p1234, nz3p2143, nz3p1234,
+* 12pppp12mm 0ppp 1
+* 3m 00pp 1
+* m4 0ppp 1432652143
+* 34 00pp 1
+ & nz3p1234, nz2p1234, nz3p2143, nz2p1234,
+* 1p3ppp12mm 0ppp 1
+* 3m 0ppp 1
+* m4 0ppp 1432652143
+* 34 0p0p 1
+ & nz3p1234, nz3p1234, nz3p2143, nz2p1234,
+* 123ppp12mm 0ppp 1
+* 3m 00pp 1
+* m4 0ppp 1432652143
+* 34 000p 1
+ & nz3p1234, nz2p1234, nz3p2143, nz1p1234,
+* 1pp4pp12mm 0ppp 1
+* 3m 0ppp 1
+* m4 00pp 1432652143
+* 34 00pp 1432652143
+ & nz3p1234, nz3p1234, nz2p2143, nz2p2143,
+* 12p4pp12mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1432652143
+* 34 000p 2143563214
+ & nz3p1234, nz2p1234, nz2p2143, nz1p3214,
+* 1p34pp12mm 0ppp 1
+* 3m 0ppp 1
+* m4 00pp 1432652143
+* 34 000p 1432652143
+ & nz3p1234, nz3p1234, nz2p2143, nz1p2143,
+* 1234pp12mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1432652143
+* 34 0000 1
+ & nz3p1234, nz2p1234, nz2p2143, p1234,
+* 1ppp5p12mm 0ppp 1
+* 3m 00pp 1536242134
+* m4 0ppp 1432652143
+* 34 00pp 1536242134
+ & nz3p1234, nz2p2134, nz3p2143, nz2p2134,
+* 12pp5p12mm 0ppp 1
+* 3m 00pp 1
+* m4 0ppp 1432652143
+* 34 00pp 1
+ & nz3p1234, nz2p1234, nz3p2143, nz2p1234,
+* 1p3p5p12mm 0ppp 1
+* 3m 00pp 1536242134
+* m4 0ppp 1432652143
+* 34 000p 1536242134
+ & nz3p1234, nz2p2134, nz3p2143, nz1p2134,
+* 123p5p12mm 0ppp 1
+* 3m 00pp 1536242134
+* m4 0ppp 1432652143
+* 34 000p 1
+ & nz3p1234, nz2p2134, nz3p2143, nz1p1234,
+* 1pp45p12mm 0ppp 1
+* 3m 00pp 1536242134
+* m4 00pp 1432652143
+* 34 00pp 1432652143
+ & nz3p1234, nz2p2134, nz2p2143, nz2p2143,
+* 12p45p12mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1432652143
+* 34 000p 2143563214
+ & nz3p1234, nz2p1234, nz2p2143, nz1p3214,
+* 1p345p12mm 0ppp 1
+* 3m 00pp 1536242134
+* m4 00pp 1432652143
+* 34 000p 1432652143
+ & nz3p1234, nz2p2134, nz2p2143, nz1p2143,
+* 12345p12mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1432652143
+* 34 0000 1
+ & nz3p1234, nz2p1234, nz2p2143, p1234,
+* 1pppp612mm 0ppp 1
+* 3m 0ppp 1
+* m4 00pp 1635421243
+* 34 00pp 1635421243
+ & nz3p1234, nz3p1234, nz2p1243, nz2p1243,
+* 12ppp612mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1635421243
+* 34 00pp 1
+ & nz3p1234, nz2p1234, nz2p1243, nz2p1234,
+* 1p3pp612mm 0ppp 1
+* 3m 0ppp 1
+* m4 00pp 1635421243
+* 34 000p 1635421243
+ & nz3p1234, nz3p1234, nz2p1243, nz1p1243,
+* 123pp612mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1635421243
+* 34 000p 1
+ & nz3p1234, nz2p1234, nz2p1243, nz1p1234,
+* 1pp4p612mm 0ppp 1
+* 3m 0ppp 1
+* m4 00pp 1635421243
+* 34 00pp 1432652143
+ & nz3p1234, nz3p1234, nz2p1243, nz2p2143,
+* 12p4p612mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1635421243
+* 34 000p 2143563214
+ & nz3p1234, nz2p1234, nz2p1243, nz1p3214,
+* 1p34p612mm 0ppp 1
+* 3m 0ppp 1
+* m4 00pp 1635421243
+* 34 000p 1432652143
+ & nz3p1234, nz3p1234, nz2p1243, nz1p2143,
+* 1234p612mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1635421243
+* 34 0000 1
+ & nz3p1234, nz2p1234, nz2p1243, p1234,
+* 1ppp5612mm 0ppp 1
+* 3m 00pp 1536242134
+* m4 00pp 1635421243
+* 34 000p 6153424213
+ & nz3p1234, nz2p2134, nz2p1243, nz1p4213,
+* 12pp5612mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1635421243
+* 34 000p 6153424213
+ & nz3p1234, nz2p1234, nz2p1243, nz1p4213,
+* 1p3p5612mm 0ppp 1
+* 3m 00pp 1536242134
+* m4 00pp 1635421243
+* 34 0000 6153424213
+ & nz3p1234, nz2p2134, nz2p1243, p4213,
+* 123p5612mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1635421243
+* 34 0000 6153424213
+ & nz3p1234, nz2p1234, nz2p1243, p4213,
+* 1pp45612mm 0ppp 1
+* 3m 00pp 1536242134
+* m4 00pp 1635421243
+* 34 000p 6153424213
+ & nz3p1234, nz2p2134, nz2p1243, nz1p4213,
+* 12p45612mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1635421243
+* 34 0000 6254314231
+ & nz3p1234, nz2p1234, nz2p1243, p4231,
+* 1p345612mm 0ppp 1
+* 3m 00pp 1536242134
+* m4 00pp 1635421243
+* 34 0000 6153424213
+ & nz3p1234, nz2p2134, nz2p1243, p4213,
+* 12345612mm 0ppp 1
+* 3m 00pp 1
+* m4 00pp 1635421243
+* 34 0000 1
+ & nz3p1234, nz2p1234, nz2p1243, p1234 /
+
+ if( DEBUGLEVEL .gt. 0 ) call DCDump("D0CcollDR", para, perm)
+
+ perm = perm_
+ perm_ = 0
+
+ z = 0
+ if( abs(Mc(3)) .lt. zeroeps ) z = 1
+ if( abs(Mc(4)) .lt. zeroeps ) z = z + 2
+ if( abs(Px(2)) .lt. zeroeps ) z = z + 4
+ if( abs(Px(3)) .lt. zeroeps ) z = z + 8
+ if( abs(Px(4)) .lt. zeroeps ) z = z + 16
+ if( abs(Px(5)) .lt. zeroeps ) z = z + 32
+ if( abs(Px(6)) .lt. zeroeps ) z = z + 64
+ s = pperm(z)
+ if( iand(s, O'7777777777') .ne. p1234 ) perm =
+ & pj(perm, pj(s, 1))*8**9 +
+ & pj(perm, pj(s, 2))*8**8 +
+ & pj(perm, pj(s, 3))*8**7 +
+ & pj(perm, pj(s, 4))*8**6 +
+ & pj(perm, pj(s, 5))*8**5 +
+ & pj(perm, pj(s, 6))*8**4 +
+ & mj(perm, mj(s, 1))*8**3 +
+ & mj(perm, mj(s, 2))*8**2 +
+ & mj(perm, mj(s, 3))*8**1 +
+ & mj(perm, mj(s, 4))*8**0
+
+ goto (22,22,22,23, 22,22,22,23, 10,11,12,13)
+ & ibits(s, 30, 2) + ibits(z, 0, 2)*4 - 3
+
+ call D0Cm2p3(res, para, perm)
+ return
+
+23 call D0Cm1p3(res, para, perm)
+ return
+
+22 call D0Cm1p2(res, para, perm)
+ return
+
+13 call D0m0p3(res, para,2, perm)
+ return
+
+12 call D0m0p2(res, para,2, perm)
+ return
+
+11 call D0m0p1(res, para,2, perm)
+ return
+
+10 call D0m0p0(res, para,2, perm)
+ end
+
+************************************************************************
+
+ subroutine D0Cm1p2(res, para, perm)
+ implicit none
+ ComplexType res(0:2), para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ ComplexType s
+ ComplexType m4, t, q3, q4, fac
+ ComplexType lm, ls, lt, lq
+ integer ir
+
+ ComplexType Li2omrat, cLi2omrat, cLi2omrat2
+ external Li2omrat, cLi2omrat, cLi2omrat2
+
+ if( DEBUGLEVEL .gt. 1 ) call DCDump("D0Cm1p2", para, perm)
+
+ m4 = Mc(4)
+ s = -Px(5)
+ t = m4 - Px(6)
+ fac = 1/(s*t)
+ q3 = m4 - Px(3)
+ q4 = m4 - Px(4)
+
+ ir = 0
+ if( abs(q3) .lt. diffeps ) ir = 1
+ if( abs(q4) .lt. diffeps ) then
+ ir = ir + 1
+ q4 = q3
+ endif
+
+ res(2) = .5D0*(2 + ir)*fac
+
+ goto (1, 2) ir
+
+* qlbox8: D0(0, 0, p3, p4; p1p2, p2p3; 0, 0, 0, m4)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0Cm1p2: qlbox8"
+ lm = lnrat(s, mudim)
+ ls = lnrat(s, m4)
+ res(0) = fac*(-2*(cLi2omrat(q3, t) + cLi2omrat(q4, t)) -
+ & cLi2omrat2(q3, s, q4, m4) - pi6 +
+ & .5D0*(lm - ls)*(lm + ls) + 2*lm*lnrat(t, m4) -
+ & lnrat(q3, mudim)*lnrat(q3, m4) -
+ & lnrat(q4, mudim)*lnrat(q4, m4))
+ res(1) = fac*(lnrat(q3, t) + lnrat(q4, t) - lm)
+ return
+
+1 continue
+* qlbox7: D0(0, 0, m4, p4; p1p2, p2p3; 0, 0, 0, m4)
+* (should have been re-routed to real D0, keep here for safety)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0Cm1p2: qlbox7"
+ ls = lnrat(s, m4)
+ lt = lnrat(t, m4)
+ lm = lnrat(mudim, m4)
+ lq = lnrat(q4, m4)
+ res(0) = fac*(2*ls*lt - lq**2 - 5*pi12 +
+ & lm*(.75D0*lm - 2*lt - ls + lq) -
+ & 2*Li2omrat(q4, t))
+ res(1) = fac*(1.5D0*lm - 2*lt - ls + lq)
+ return
+
+2 continue
+* qlbox6: D0(0, 0, m4, m4; p1p2, p2p3; 0, 0, 0, m4)
+* (should have been re-routed to real D0, keep here for safety)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0Cm1p2: qlbox6"
+ ls = lnrat(s, m4)
+ lt = lnrat(t, m4)
+ lm = lnrat(mudim, m4)
+ res(0) = fac*((lm - ls)*(lm - 2*lt) - .5D0*pi**2)
+ res(1) = fac*(2*(lm - lt) - ls)
+ end
+
+************************************************************************
+
+ subroutine D0Cm1p3(res, para, perm)
+ implicit none
+ ComplexType res(0:2), para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ ComplexType s, q2
+ ComplexType m4, m4mu, q3, q4, t, fac, ll
+
+ ComplexType Li2omrat, cLi2omrat, Li2omrat2, cLi2omrat2
+ external Li2omrat, cLi2omrat, Li2omrat2, cLi2omrat2
+
+ if( DEBUGLEVEL .gt. 1 ) call DCDump("D0Cm1p3", para, perm)
+
+ q2 = -Px(2)
+ s = -Px(5)
+ m4 = Mc(4)
+ q3 = m4 - Px(3)
+ q4 = m4 - Px(4)
+ t = m4 - Px(6)
+
+ if( abs(t) .lt. diffeps ) then
+ t = q4
+ q4 = 0
+ s = q2
+ q2 = -Px(5)
+ endif
+
+ m4mu = sqrt(m4*mudim)
+
+* qlbox9: D0(0, p2, p3, m4; p1p2, p2p3; 0, 0, 0, m4)
+* (should have been re-routed to real D0, keep here for safety)
+ if( abs(q4) .lt. diffeps ) then
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0Cm1p3: qlbox9"
+ fac = 1/(Re(s)*Re(t))
+ ll = lnrat(t, m4mu) + lnrat(s, q2)
+ res(0) = fac*(Li2omrat2(q3, q2, t, m4) +
+ & 2*Li2omrat(s, q2) + ll**2 + pi12)
+ res(1) = -fac*ll
+ res(2) = .5D0*fac
+ return
+ endif
+
+* qlbox10: D0(0, p2, p3, p4; p1p2, p2p3; 0, 0, 0, m4)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0Cm1p3: qlbox10"
+ fac = 1/(Re(s)*t - Re(q2)*q4)
+ ll = lnrat(q2, mudim) + lnrat(q4, mudim) -
+ & lnrat(s, mudim) - lnrat(t, mudim)
+ res(0) = fac*(
+ & 2*ll*lnrat(m4mu, t) +
+ & cLi2omrat2(q3, q2, t, m4) -
+ & cLi2omrat2(q3, s, q4, m4) +
+ & 2*(cLi2omrat2(q2, s, q4, t) -
+ & cLi2omrat(q2, s) + cLi2omrat(t, q4)) )
+ res(1) = fac*ll
+ res(2) = 0
+ end
+
+************************************************************************
+
+ subroutine D0Cm2p3(res, para, perm)
+ implicit none
+ ComplexType res(0:2), para(1,*)
+ integer perm
+
+#include "lt.h"
+
+ RealType p3, m3mu
+ ComplexType m3, m4, s, t, q3, q4, tmp, fac
+ ComplexType p34, c, s3t, s4s
+ ComplexType ls, lt, lq3, lq4, d
+ ComplexType x43(4), r3t, r4s, r43p, r43m
+ ComplexType logs, dilogs
+ integer ir, case
+
+ ComplexType minus1
+ parameter (minus1 = -1)
+
+ ComplexType Li2rat, cLi2omrat, cLi2omrat2
+ external Li2rat, cLi2omrat, cLi2omrat2
+
+ if( DEBUGLEVEL .gt. 1 ) call DCDump("D0Cm2p3", para, perm)
+
+ m3 = Mc(3)
+ s = m3 - Px(5)
+ q3 = m3 - Px(2)
+ m4 = Mc(4)
+ t = m4 - Px(6)
+ q4 = m4 - Px(4)
+
+ if( abs(s) .lt. diffeps .or. abs(t) .lt. diffeps ) then
+* switch from p1234 to p2134 = 1536242134
+ tmp = s
+ s = q3
+ q3 = tmp
+ tmp = t
+ t = q4
+ q4 = tmp
+ endif
+
+ fac = 1/(s*t - q3*q4)
+
+ ir = 0
+ if( abs(q3) .lt. diffeps ) ir = 1
+ if( abs(q4) .lt. diffeps ) then
+ ir = ir + 1
+ q4 = q3
+ tmp = s
+ s = t
+ t = tmp
+ m4 = m3
+ m3 = Mc(4)
+ endif
+
+ res(2) = .5D0*fac*ir
+
+ p3 = Px(3)
+ if( abs(p3) .lt. zeroeps ) then
+ case = 1
+ logs = lnrat(m3, m4)**2
+ else
+ p34 = p3 + m3 - m4
+ c = -4*p3*m3
+ d = sqrt(p34**2 + c)
+
+ x43(1) = -p34 - d
+ x43(2) = p34 - d
+ if( abs(x43(1)) .lt. abs(x43(2)) ) then
+ x43(1) = c/x43(2)
+ else
+ x43(2) = c/x43(1)
+ endif
+
+ p34 = -p3 + m3 - m4
+ c = -4*p3*m4
+
+ x43(3) = -p34 - d
+ x43(4) = p34 - d
+ if( abs(x43(3)) .lt. abs(x43(4)) ) then
+ x43(3) = c/x43(4)
+ else
+ x43(4) = c/x43(3)
+ endif
+
+ if( abs(Im(d)) .lt. zeroeps ) then
+ case = 2
+ logs = lnrat(x43(1), x43(3))**2 +
+ & lnrat(x43(2), x43(4))**2
+ else
+ case = 3
+ r43p = x43(1)/x43(3)
+ r43m = x43(2)/x43(4)
+ logs = ln(r43p, 0)**2 + ln(r43m, 0)**2
+ endif
+ endif
+
+ goto (1, 2) ir
+
+* qlbox13: D0(0, p2, p3, p4; p1p2, p2p3; 0, 0, m3, m4)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0Cm2p3: qlbox13"
+
+ ls = lnrat(s, mudim)
+ lt = lnrat(t, mudim)
+ lq3 = lnrat(q3, mudim)
+ lq4 = lnrat(q4, mudim)
+
+ if( case .eq. 1 ) then
+ dilogs = cLi2omrat2(q3, t, minus1, minus1) +
+ & cLi2omrat2(q3, t, m4, m3) +
+ & cLi2omrat2(q4, s, m3, m4) +
+ & cLi2omrat2(q4, s, minus1, minus1)
+ else if( case .eq. 2 ) then
+ dilogs = cLi2omrat2(q3, t, x43(4), x43(2)) +
+ & cLi2omrat2(q3, t, x43(3), x43(1)) +
+ & cLi2omrat2(q4, s, x43(1), x43(3)) +
+ & cLi2omrat2(q4, s, x43(2), x43(4))
+ else
+ r3t = q3/t
+ s3t = sign(.5D0, Re(q3)) - sign(.5D0, Re(t))
+ r4s = q4/s
+ s4s = sign(.5D0, Re(q4)) - sign(.5D0, Re(s))
+ dilogs = Li2rat(r3t,s3t, 1/r43m,0D0) +
+ & Li2rat(r3t,s3t, 1/r43p,0D0) +
+ & Li2rat(r4s,s4s, r43p,0D0) +
+ & Li2rat(r4s,s4s, r43m,0D0)
+ endif
+
+ res(0) = -fac*(dilogs + .5D0*logs + lq3**2 + lq4**2 +
+ & 2*(cLi2omrat(q3, s) + cLi2omrat(q4, t) -
+ & cLi2omrat2(q3, s, q4, t) - ls*lt) +
+ & (lt - lq3)*log(m3/mudim) + (ls - lq4)*log(m4/mudim))
+ res(1) = fac*(lq3 + lq4 - ls - lt)
+ return
+
+1 continue
+* qlbox12: D0(0, m3, p3, p4; p1p2, p2p3; 0, 0, m3, m4)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0Cm2p3: qlbox12"
+
+ m3mu = sqrt(Re(m3)*mudim)
+ ls = lnrat(s, m3mu)
+ lt = lnrat(t, m3mu)
+ lq4 = lnrat(q4, m3mu)
+
+ if( case .eq. 1 ) then
+ dilogs = cLi2omrat2(q4, s, m3, m4) +
+ & cLi2omrat2(q4, s, -1D0, -1D0)
+ else if( case .eq. 2 ) then
+ dilogs = cLi2omrat2(q4, s, x43(1), x43(3)) +
+ & cLi2omrat2(q4, s, x43(2), x43(4))
+ else
+ r4s = q4/s
+ s4s = sign(.5D0, Re(q4)) - sign(.5D0, Re(s))
+ dilogs = Li2rat(r4s,s4s, r43p,0D0) +
+ & Li2rat(r4s,s4s, r43m,0D0)
+ endif
+
+ res(0) = -fac*(dilogs + .5D0*logs + pi12 +
+ & 2*(cLi2omrat(q4, t) - ls*lt) +
+ & lq4**2 + (ls - lq4)*log(m4/m3))
+ res(1) = fac*(lq4 - ls - lt)
+ return
+
+2 continue
+* qlbox11: D0(0, m3, p3, m4; p1p2, p2p3; 0, 0, m3, m4)
+
+* qlbox11a: D0(0, p2, p3, p4; m3, m4; 0, 0, m3, m4)
+* (should have been re-routed to real D0, keep here for safety)
+ if( DEBUGLEVEL .gt. 1 ) print *, "D0Cm2p3: qlbox11"
+
+ ls = lnrat(s, sqrt(Re(m3)*mudim))
+ lt = lnrat(t, sqrt(Re(m4)*mudim))
+
+ res(0) = fac*(.25D0*log(Re(m3)/Re(m4))**2 -
+ & .5D0*(logs + pi**2) + 2*ls*lt)
+ res(1) = -fac*(ls + lt)
+ end
+
diff --git a/Looptools/D/Dget.F b/Looptools/D/Dget.F
--- a/Looptools/D/Dget.F
+++ b/Looptools/D/Dget.F
@@ -1,440 +1,561 @@
* Dget.F
* retrieve the four-point tensor coefficients
* this file is part of LoopTools
* improvements by M. Rauch
-* last modified 28 Sep 10 th
+* last modified 20 Jan 16 th
+#include "externals.h"
+#include "types.h"
+
+#define npoint 4
#include "defs.h"
- integer function XDget(p1, p2, p3, p4, p1p2, p2p3,
+ subroutine XDpara(para, p1, p2, p3, p4, p1p2, p2p3,
+ & m1, m2, m3, m4)
+ implicit none
+ DVAR para(1,*)
+ DVAR p1, p2, p3, p4, p1p2, p2p3
+ DVAR m1, m2, m3, m4
+
+#include "lt.h"
+
+ P(1) = p1
+ P(2) = p2
+ P(3) = p3
+ P(4) = p4
+ P(5) = p1p2
+ P(6) = p2p3
+
+ M(1) = m1
+ if( abs(M(1)) .lt. minmass ) M(1) = 0
+ M(2) = m2
+ if( abs(M(2)) .lt. minmass ) M(2) = 0
+ M(3) = m3
+ if( abs(M(3)) .lt. minmass ) M(3) = 0
+ M(4) = m4
+ if( abs(M(4)) .lt. minmass ) M(4) = 0
+ end
+
+************************************************************************
+
+ memindex function XDget(p1, p2, p3, p4, p1p2, p2p3,
& m1, m2, m3, m4)
implicit none
DVAR p1, p2, p3, p4, p1p2, p2p3
DVAR m1, m2, m3, m4
#include "lt.h"
- integer cachelookup
- external cachelookup, XDcoeff
+ memindex cacheindex
+ external cacheindex, XDcoefx
- DVAR para(Pdd)
+#ifdef COMPLEXPARA
+ memindex Dget
+ external Dget
+#endif
- para(1) = p1
- para(2) = p2
- para(3) = p3
- para(4) = p4
- para(5) = p1p2
- para(6) = p2p3
- para(7) = m1
- if( abs(para(7)) .lt. minmass ) para(7) = 0
- para(8) = m2
- if( abs(para(8)) .lt. minmass ) para(8) = 0
- para(9) = m3
- if( abs(para(9)) .lt. minmass ) para(9) = 0
- para(10) = m4
- if( abs(para(10)) .lt. minmass ) para(10) = 0
+ DVAR para(1,Pdd+3)
- XDget = cachelookup(para, Dval(1,0), XDcoeff, RC*Pdd, Ndd)
+#ifdef COMPLEXPARA
+ if( abs(Im(p1)) + abs(Im(p2)) +
+ & abs(Im(p3)) + abs(Im(p4)) +
+ & abs(Im(p1p2)) + abs(Im(p2p3)) .gt. 0 )
+ & print *, "Complex momenta not implemented"
+ if( abs(Im(m1)) + abs(Im(m2)) +
+ & abs(Im(m3)) + abs(Im(m4)) .eq. 0 ) then
+ XDget = Dget(p1, p2, p3, p4, p1p2, p2p3,
+ & m1, m2, m3, m4) - offsetC
+ return
+ endif
+#endif
+
+ call XDpara(para, p1, p2, p3, p4, p1p2, p2p3, m1, m2, m3, m4)
+ XDget = cacheindex(para, Dval(1,0), XDcoefx, RC*Pdd, Ndd, Dno)
end
************************************************************************
- double complex function XD0i(i, p1, p2, p3, p4, p1p2, p2p3,
+ subroutine XDput(res, p1, p2, p3, p4, p1p2, p2p3,
+ & m1, m2, m3, m4)
+ implicit none
+ ComplexType res(*)
+ DVAR p1, p2, p3, p4, p1p2, p2p3
+ DVAR m1, m2, m3, m4
+
+#include "lt.h"
+
+ external XDcoefx
+
+ DVAR para(1,Pdd+3)
+
+#ifdef COMPLEXPARA
+ if( abs(Im(p1)) + abs(Im(p2)) +
+ & abs(Im(p3)) + abs(Im(p4)) +
+ & abs(Im(p1p2)) + abs(Im(p2p3)) .gt. 0 )
+ & print *, "Complex momenta not implemented"
+ if( abs(Im(m1)) + abs(Im(m2)) +
+ & abs(Im(m3)) + abs(Im(m4)) .eq. 0 ) then
+ call Dput(res, p1, p2, p3, p4, p1p2, p2p3, m1, m2, m3, m4)
+ return
+ endif
+#endif
+
+ call XDpara(para, p1, p2, p3, p4, p1p2, p2p3, m1, m2, m3, m4)
+ call cachecopy(res, para, Dval(1,0), XDcoefx, RC*Pdd, Ndd, Dno)
+ end
+
+************************************************************************
+
+ subroutine XD0nocache(res, p1, p2, p3, p4, p1p2, p2p3,
+ & m1, m2, m3, m4)
+ implicit none
+ ComplexType res(*)
+ DVAR p1, p2, p3, p4, p1p2, p2p3
+ DVAR m1, m2, m3, m4
+
+#include "lt.h"
+
+ DVAR para(1,Pdd+3)
+
+#ifdef COMPLEXPARA
+ if( abs(Im(p1)) + abs(Im(p2)) +
+ & abs(Im(p3)) + abs(Im(p4)) +
+ & abs(Im(p1p2)) + abs(Im(p2p3)) .gt. 0 )
+ & print *, "Complex momenta not implemented"
+ if( abs(Im(m1)) + abs(Im(m2)) +
+ & abs(Im(m3)) + abs(Im(m4)) .eq. 0 ) then
+ call D0nocache(res, p1, p2, p3, p4, p1p2, p2p3,
+ & m1, m2, m3, m4)
+ return
+ endif
+#endif
+
+ call XDpara(para, p1, p2, p3, p4, p1p2, p2p3, m1, m2, m3, m4)
+ call XD0func(res, para)
+ end
+
+************************************************************************
+
+ ComplexType function XD0i(i, p1, p2, p3, p4, p1p2, p2p3,
& m1, m2, m3, m4)
implicit none
integer i
DVAR p1, p2, p3, p4, p1p2, p2p3
DVAR m1, m2, m3, m4
#include "lt.h"
- integer XDget
+ memindex XDget
external XDget
- integer b
+ memindex b
b = XDget(p1, p2, p3, p4, p1p2, p2p3, m1, m2, m3, m4)
- XD0i = Dval(i,b)
+ XD0i = Dval(i+epsi,b)
end
************************************************************************
- subroutine XDcoeff(para, D, ldpara)
+ ComplexType function XD0(p1, p2, p3, p4, p1p2, p2p3,
+ & m1, m2, m3, m4)
implicit none
- integer ldpara
- DVAR para(ldpara,Pdd)
- double complex D(Ndd)
+ DVAR p1, p2, p3, p4, p1p2, p2p3
+ DVAR m1, m2, m3, m4
#include "lt.h"
- integer XCget
- double complex XD0
- external XCget, XD0
+ ComplexType XD0i
+ external XD0i
+
+ XD0 = XD0i(dd0, p1, p2, p3, p4, p1p2, p2p3, m1, m2, m3, m4)
+ end
+
+************************************************************************
+
+ subroutine XDcoefx(D, para)
+ implicit none
+ ComplexType D(*)
+ DVAR para(1,*)
+
+#include "lt.h"
+
+ memindex c234, c134, c124, c123
+
+ memindex XCget
+ external XCget
+
+ c234 = XCget(P(2), P(3), P(6), M(2), M(3), M(4))
+ c134 = XCget(P(5), P(3), P(4), M(1), M(3), M(4))
+ c124 = XCget(P(1), P(6), P(4), M(1), M(2), M(4))
+ c123 = XCget(P(1), P(2), P(5), M(1), M(2), M(3))
+
+ call XDcoeff(D, para,
+ & Cval(1,c234), Cval(1,c134), Cval(1,c124), Cval(1,c123))
+ end
+
+************************************************************************
+
+ subroutine XDcoeff(D, para, C234, C134, C124, C123)
+ implicit none
+ ComplexType D(*), C234(*), C134(*), C124(*), C123(*)
+ DVAR para(1,*)
+
+#include "lt.h"
DVAR p1, p2, p3, p4, p1p2, p2p3, m1, m2, m3, m4
DVAR f1, f2, f3
QVAR G(3,3)
- double complex c0sum, c1sum, c2sum, csum
- double complex c00sum, c11sum, c12sum, c22sum
- double complex in(3)
- integer C234, C134, C124, C123
+ ComplexType c0sum(0:2), c1sum(0:2), c2sum(0:2), csum(0:2)
+ ComplexType c00sum(0:2), c11sum(0:2), c12sum(0:2), c22sum(0:2)
+ ComplexType in(0:2,3)
logical dump
#ifdef SOLVE_EIGEN
QVAR Ginv(3,3)
+#define IN(i) in(:,i)
#define SOLVE_SETUP XInverse(3, G,3, Ginv,3)
-#define SOLVE(b) XSolve(3, G,3, Ginv,3, b)
+#define SOLVER(b) XSolve(3, G,3, Ginv,3, b)
#else
integer perm(3)
-#define IN(i) in(perm(i))
+#define IN(i) in(:,perm(i))
#define SOLVE_SETUP XDecomp(3, G,3, perm)
-#define SOLVE(b) XSolve(3, G,3, b)
+#define SOLVER(b) XSolve(3, G,3, b)
#endif
+#define OUT(i) in(:,i)
-#ifdef COMPLEXPARA
- if( abs(DIMAG(para(1,1))) +
- & abs(DIMAG(para(1,2))) +
- & abs(DIMAG(para(1,3))) +
- & abs(DIMAG(para(1,4))) +
- & abs(DIMAG(para(1,5))) +
- & abs(DIMAG(para(1,6))) .gt. 0 )
- & print *, "Warning: complex momenta not implemented"
- if( abs(DIMAG(para(1,7))) +
- & abs(DIMAG(para(1,8))) +
- & abs(DIMAG(para(1,9))) +
- & abs(DIMAG(para(1,10))) .eq. 0 ) then
- call Dcoeff(para, D, 2)
- return
- endif
-#endif
-
- p1 = para(1,1)
- p2 = para(1,2)
- p3 = para(1,3)
- p4 = para(1,4)
- p1p2 = para(1,5)
- p2p3 = para(1,6)
- m1 = para(1,7)
- m2 = para(1,8)
- m3 = para(1,9)
- m4 = para(1,10)
-
- C234 = XCget(p2, p3, p2p3, m2, m3, m4)
- C134 = XCget(p1p2, p3, p4, m1, m3, m4)
- C124 = XCget(p1, p2p3, p4, m1, m2, m4)
- C123 = XCget(p1, p2, p1p2, m1, m2, m3)
+ integer finite(0:2)
+ data finite /1, 0, 0/
serial = serial + 1
dump = ibits(debugkey, DebugD, 1) .ne. 0 .and.
& serial .ge. debugfrom .and. serial .le. debugto
- if( dump ) call XDumpPara(4, para, ldpara, "Dcoeff")
+ if( dump ) call XDumpPara(4, para, "Dcoeff")
- f1 = QPREC(m2) - QPREC(m1) - QPREC(p1)
- f2 = QPREC(m3) - QPREC(m1) - QPREC(p1p2)
- f3 = QPREC(m4) - QPREC(m1) - QPREC(p4)
+ m1 = M(1)
+ m2 = M(2)
+ m3 = M(3)
+ m4 = M(4)
+ p1 = P(1)
+ p2 = P(2)
+ p3 = P(3)
+ p4 = P(4)
+ p1p2 = P(5)
+ p2p3 = P(6)
- G(1,1) = 2*QPREC(p1)
- G(2,2) = 2*QPREC(p1p2)
- G(3,3) = 2*QPREC(p4)
- G(1,2) = QPREC(p1) + QPREC(p1p2) - QPREC(p2)
+ f1 = m2
+ f1 = f1 - m1
+ f1 = f1 - p1
+ f2 = m3
+ f2 = f2 - m1
+ f2 = f2 - p1p2
+ f3 = m4
+ f3 = f3 - m1
+ f3 = f3 - p4
+
+ G(1,1) = 2*p1
+ G(2,2) = 2*p1p2
+ G(3,3) = 2*p4
+ G(1,2) = p1
+ G(1,2) = G(1,2) + p1p2
+ G(1,2) = G(1,2) - p2
G(2,1) = G(1,2)
- G(1,3) = QPREC(p1) + QPREC(p4) - QPREC(p2p3)
+ G(1,3) = p1
+ G(1,3) = G(1,3) + p4
+ G(1,3) = G(1,3) - p2p3
G(3,1) = G(1,3)
- G(2,3) = QPREC(p1p2) - QPREC(p3) + QPREC(p4)
+ G(2,3) = p1p2
+ G(2,3) = G(2,3) - p3
+ G(2,3) = G(2,3) + p4
G(3,2) = G(2,3)
call SOLVE_SETUP
- c0sum = Cval(cc0,C234) + Cval(cc1,C234) + Cval(cc2,C234)
- c1sum = Cval(cc1,C234) + Cval(cc11,C234) + Cval(cc12,C234)
- c2sum = Cval(cc2,C234) + Cval(cc12,C234) + Cval(cc22,C234)
+ c0sum = C234(CC0) + C234(CC1) + C234(CC2)
+ c1sum = C234(CC1) + C234(CC11) + C234(CC12)
+ c2sum = C234(CC2) + C234(CC12) + C234(CC22)
csum = c0sum + c1sum + c2sum
- c00sum = Cval(cc00,C234) +
- & Cval(cc001,C234) + Cval(cc002,C234)
- c11sum = Cval(cc11,C234) +
- & Cval(cc111,C234) + Cval(cc112,C234)
- c12sum = Cval(cc12,C234) +
- & Cval(cc112,C234) + Cval(cc122,C234)
- c22sum = Cval(cc22,C234) +
- & Cval(cc122,C234) + Cval(cc222,C234)
+ c00sum = C234(CC00) + C234(CC001) + C234(CC002)
+ c11sum = C234(CC11) + C234(CC111) + C234(CC112)
+ c12sum = C234(CC12) + C234(CC112) + C234(CC122)
+ c22sum = C234(CC22) + C234(CC122) + C234(CC222)
- D(dd0) = XD0(p1, p2, p3, p4, p1p2, p2p3, m1, m2, m3, m4)
+ call XD0func(D(DD0), para)
- IN(1) = f1*D(dd0) - Cval(cc0,C234) + Cval(cc0,C134)
- IN(2) = f2*D(dd0) - Cval(cc0,C234) + Cval(cc0,C124)
- IN(3) = f3*D(dd0) - Cval(cc0,C234) + Cval(cc0,C123)
- call SOLVE(in)
- D(dd1) = in(1)
- D(dd2) = in(2)
- D(dd3) = in(3)
+ IN(1) = f1*D(DD0) - C234(CC0) + C134(CC0)
+ IN(2) = f2*D(DD0) - C234(CC0) + C124(CC0)
+ IN(3) = f3*D(DD0) - C234(CC0) + C123(CC0)
+ call SOLVER(in)
+ D(DD1) = OUT(1)
+ D(DD2) = OUT(2)
+ D(DD3) = OUT(3)
- D(dd00) = m1*D(dd0) - .5D0*
- & (D(dd1)*f1 + D(dd2)*f2 + D(dd3)*f3 - Cval(cc0,C234))
+ D(DD00) = m1*D(DD0) - .5D0*
+ & (D(DD1)*f1 + D(DD2)*f2 + D(DD3)*f3 - C234(CC0))
- IN(1) = f1*D(dd1) + c0sum - 2*D(dd00)
- IN(2) = f2*D(dd1) + c0sum + Cval(cc1,C124)
- IN(3) = f3*D(dd1) + c0sum + Cval(cc1,C123)
- call SOLVE(in)
- D(dd11) = in(1)
- D(dd12) = in(2)
- D(dd13) = in(3)
+ IN(1) = f1*D(DD1) + c0sum - 2*D(DD00)
+ IN(2) = f2*D(DD1) + c0sum + C124(CC1)
+ IN(3) = f3*D(DD1) + c0sum + C123(CC1)
+ call SOLVER(in)
+ D(DD11) = OUT(1)
+ D(DD12) = OUT(2)
+ D(DD13) = OUT(3)
- IN(1) = f1*D(dd2) - Cval(cc1,C234) + Cval(cc1,C134)
- IN(2) = f2*D(dd2) - Cval(cc1,C234) - 2*D(dd00)
- IN(3) = f3*D(dd2) - Cval(cc1,C234) + Cval(cc2,C123)
- call SOLVE(in)
- D(dd12) = .5D0*(D(dd12) + in(1))
- D(dd22) = in(2)
- D(dd23) = in(3)
+ IN(1) = f1*D(DD2) - C234(CC1) + C134(CC1)
+ IN(2) = f2*D(DD2) - C234(CC1) - 2*D(DD00)
+ IN(3) = f3*D(DD2) - C234(CC1) + C123(CC2)
+ call SOLVER(in)
+ D(DD12) = .5D0*(D(DD12) + OUT(1))
+ D(DD22) = OUT(2)
+ D(DD23) = OUT(3)
- IN(1) = f1*D(dd3) - Cval(cc2,C234) + Cval(cc2,C134)
- IN(2) = f2*D(dd3) - Cval(cc2,C234) + Cval(cc2,C124)
- IN(3) = f3*D(dd3) - Cval(cc2,C234) - 2*D(dd00)
- call SOLVE(in)
- D(dd13) = .5D0*(D(dd13) + in(1))
- D(dd23) = .5D0*(D(dd23) + in(2))
- D(dd33) = in(3)
+ IN(1) = f1*D(DD3) - C234(CC2) + C134(CC2)
+ IN(2) = f2*D(DD3) - C234(CC2) + C124(CC2)
+ IN(3) = f3*D(DD3) - C234(CC2) - 2*D(DD00)
+ call SOLVER(in)
+ D(DD13) = .5D0*(D(DD13) + OUT(1))
+ D(DD23) = .5D0*(D(DD23) + OUT(2))
+ D(DD33) = OUT(3)
- IN(1) = f1*D(dd00) - Cval(cc00,C234) + Cval(cc00,C134)
- IN(2) = f2*D(dd00) - Cval(cc00,C234) + Cval(cc00,C124)
- IN(3) = f3*D(dd00) - Cval(cc00,C234) + Cval(cc00,C123)
- call SOLVE(in)
- D(dd001) = in(1)
- D(dd002) = in(2)
- D(dd003) = in(3)
+ IN(1) = f1*D(DD00) - C234(CC00) + C134(CC00)
+ IN(2) = f2*D(DD00) - C234(CC00) + C124(CC00)
+ IN(3) = f3*D(DD00) - C234(CC00) + C123(CC00)
+ call SOLVER(in)
+ D(DD001) = OUT(1)
+ D(DD002) = OUT(2)
+ D(DD003) = OUT(3)
- IN(1) = f1*D(dd11) - csum - 4*D(dd001)
- IN(2) = f2*D(dd11) - csum + Cval(cc11,C124)
- IN(3) = f3*D(dd11) - csum + Cval(cc11,C123)
- call SOLVE(in)
- D(dd111) = in(1)
- D(dd112) = in(2)
- D(dd113) = in(3)
+ IN(1) = f1*D(DD11) - csum - 4*D(DD001)
+ IN(2) = f2*D(DD11) - csum + C124(CC11)
+ IN(3) = f3*D(DD11) - csum + C123(CC11)
+ call SOLVER(in)
+ D(DD111) = OUT(1)
+ D(DD112) = OUT(2)
+ D(DD113) = OUT(3)
- IN(1) = f1*D(dd22) - Cval(cc11,C234) + Cval(cc11,C134)
- IN(2) = f2*D(dd22) - Cval(cc11,C234) - 4*D(dd002)
- IN(3) = f3*D(dd22) - Cval(cc11,C234) + Cval(cc22,C123)
- call SOLVE(in)
- D(dd122) = in(1)
- D(dd222) = in(2)
- D(dd223) = in(3)
+ IN(1) = f1*D(DD22) - C234(CC11) + C134(CC11)
+ IN(2) = f2*D(DD22) - C234(CC11) - 4*D(DD002)
+ IN(3) = f3*D(DD22) - C234(CC11) + C123(CC22)
+ call SOLVER(in)
+ D(DD122) = OUT(1)
+ D(DD222) = OUT(2)
+ D(DD223) = OUT(3)
- IN(1) = f1*D(dd33) - Cval(cc22,C234) + Cval(cc22,C134)
- IN(2) = f2*D(dd33) - Cval(cc22,C234) + Cval(cc22,C124)
- IN(3) = f3*D(dd33) - Cval(cc22,C234) - 4*D(dd003)
- call SOLVE(in)
- D(dd133) = in(1)
- D(dd233) = in(2)
- D(dd333) = in(3)
+ IN(1) = f1*D(DD33) - C234(CC22) + C134(CC22)
+ IN(2) = f2*D(DD33) - C234(CC22) + C124(CC22)
+ IN(3) = f3*D(DD33) - C234(CC22) - 4*D(DD003)
+ call SOLVER(in)
+ D(DD133) = OUT(1)
+ D(DD233) = OUT(2)
+ D(DD333) = OUT(3)
- IN(1) = f1*D(dd13) + c2sum - 2*D(dd003)
- IN(2) = f2*D(dd13) + c2sum + Cval(cc12,C124)
- IN(3) = f3*D(dd13) + c2sum - 2*D(dd001)
- call SOLVE(in)
- D(dd113) = .5D0*(D(dd113) + in(1))
- D(dd123) = in(2)
- D(dd133) = .5D0*(D(dd133) + in(3))
+ IN(1) = f1*D(DD13) + c2sum - 2*D(DD003)
+ IN(2) = f2*D(DD13) + c2sum + C124(CC12)
+ IN(3) = f3*D(DD13) + c2sum - 2*D(DD001)
+ call SOLVER(in)
+ D(DD113) = .5D0*(D(DD113) + OUT(1))
+ D(DD123) = OUT(2)
+ D(DD133) = .5D0*(D(DD133) + OUT(3))
- D(dd0000) = 1/3D0*(m1*D(dd00) -
- & .5D0*(f1*D(dd001) + f2*D(dd002) + f3*D(dd003) -
- & Cval(cc00,C234) - 1/6D0))
- D(dd0011) = 1/3D0*(m1*D(dd11) -
- & .5D0*(f1*D(dd111) + f2*D(dd112) + f3*D(dd113) - csum))
- D(dd0012) = 1/3D0*(m1*D(dd12) -
- & .5D0*(f1*D(dd112) + f2*D(dd122) + f3*D(dd123) + c1sum))
- D(dd0013) = 1/3D0*(m1*D(dd13) -
- & .5D0*(f1*D(dd113) + f2*D(dd123) + f3*D(dd133) + c2sum))
- D(dd0022) = 1/3D0*(m1*D(dd22) -
- & .5D0*(f1*D(dd122) + f2*D(dd222) + f3*D(dd223) -
- & Cval(cc11,C234)))
- D(dd0023) = 1/3D0*(m1*D(dd23) -
- & .5D0*(f1*D(dd123) + f2*D(dd223) + f3*D(dd233) -
- & Cval(cc12,C234)))
- D(dd0033) = 1/3D0*(m1*D(dd33) -
- & .5D0*(f1*D(dd133) + f2*D(dd233) + f3*D(dd333) -
- & Cval(cc22,C234)))
+ D(DD0000) = 1/3D0*(m1*D(DD00) -
+ & .5D0*(f1*D(DD001) + f2*D(DD002) + f3*D(DD003) -
+ & C234(CC00) - finite/6D0))
+ D(DD0011) = 1/3D0*(m1*D(DD11) -
+ & .5D0*(f1*D(DD111) + f2*D(DD112) + f3*D(DD113) - csum))
+ D(DD0012) = 1/3D0*(m1*D(DD12) -
+ & .5D0*(f1*D(DD112) + f2*D(DD122) + f3*D(DD123) + c1sum))
+ D(DD0013) = 1/3D0*(m1*D(DD13) -
+ & .5D0*(f1*D(DD113) + f2*D(DD123) + f3*D(DD133) + c2sum))
+ D(DD0022) = 1/3D0*(m1*D(DD22) -
+ & .5D0*(f1*D(DD122) + f2*D(DD222) + f3*D(DD223) -
+ & C234(CC11)))
+ D(DD0023) = 1/3D0*(m1*D(DD23) -
+ & .5D0*(f1*D(DD123) + f2*D(DD223) + f3*D(DD233) -
+ & C234(CC12)))
+ D(DD0033) = 1/3D0*(m1*D(DD33) -
+ & .5D0*(f1*D(DD133) + f2*D(DD233) + f3*D(DD333) -
+ & C234(CC22)))
c1sum = c1sum + c11sum + c12sum
c2sum = c2sum + c12sum + c22sum
csum = csum + c1sum + c2sum
- IN(1) = f1*D(dd111) + csum - 6*D(dd0011)
- IN(2) = f2*D(dd111) + csum + Cval(cc111,C124)
- IN(3) = f3*D(dd111) + csum + Cval(cc111,C123)
- call SOLVE(in)
- D(dd1111) = in(1)
- D(dd1112) = in(2)
- D(dd1113) = in(3)
+ IN(1) = f1*D(DD111) + csum - 6*D(DD0011)
+ IN(2) = f2*D(DD111) + csum + C124(CC111)
+ IN(3) = f3*D(DD111) + csum + C123(CC111)
+ call SOLVER(in)
+ D(DD1111) = OUT(1)
+ D(DD1112) = OUT(2)
+ D(DD1113) = OUT(3)
- IN(1) = f1*D(dd113) - c2sum - 4*D(dd0013)
- IN(2) = f2*D(dd113) - c2sum + Cval(cc112,C124)
- IN(3) = f3*D(dd113) - c2sum - 2*D(dd0011)
- call SOLVE(in)
- D(dd1113) = .5D0*(D(dd1113) + in(1))
- D(dd1123) = in(2)
- D(dd1133) = in(3)
+ IN(1) = f1*D(DD113) - c2sum - 4*D(DD0013)
+ IN(2) = f2*D(DD113) - c2sum + C124(CC112)
+ IN(3) = f3*D(DD113) - c2sum - 2*D(DD0011)
+ call SOLVER(in)
+ D(DD1113) = .5D0*(D(DD1113) + OUT(1))
+ D(DD1123) = OUT(2)
+ D(DD1133) = OUT(3)
- IN(1) = f1*D(dd122) + c11sum - 2*D(dd0022)
- IN(2) = f2*D(dd122) + c11sum - 4*D(dd0012)
- IN(3) = f3*D(dd122) + c11sum + Cval(cc122,C123)
- call SOLVE(in)
- D(dd1122) = in(1)
- D(dd1222) = in(2)
- D(dd1223) = in(3)
+ IN(1) = f1*D(DD122) + c11sum - 2*D(DD0022)
+ IN(2) = f2*D(DD122) + c11sum - 4*D(DD0012)
+ IN(3) = f3*D(DD122) + c11sum + C123(CC122)
+ call SOLVER(in)
+ D(DD1122) = OUT(1)
+ D(DD1222) = OUT(2)
+ D(DD1223) = OUT(3)
- IN(1) = f1*D(dd222) - Cval(cc111,C234) + Cval(cc111,C134)
- IN(2) = f2*D(dd222) - Cval(cc111,C234) - 6*D(dd0022)
- IN(3) = f3*D(dd222) - Cval(cc111,C234) + Cval(cc222,C123)
- call SOLVE(in)
- D(dd1222) = .5D0*(D(dd1222) + in(1))
- D(dd2222) = in(2)
- D(dd2223) = in(3)
+ IN(1) = f1*D(DD222) - C234(CC111) + C134(CC111)
+ IN(2) = f2*D(DD222) - C234(CC111) - 6*D(DD0022)
+ IN(3) = f3*D(DD222) - C234(CC111) + C123(CC222)
+ call SOLVER(in)
+ D(DD1222) = .5D0*(D(DD1222) + OUT(1))
+ D(DD2222) = OUT(2)
+ D(DD2223) = OUT(3)
- IN(1) = f1*D(dd233) - Cval(cc122,C234) + Cval(cc122,C134)
- IN(2) = f2*D(dd233) - Cval(cc122,C234) - 2*D(dd0033)
- IN(3) = f3*D(dd233) - Cval(cc122,C234) - 4*D(dd0023)
- call SOLVE(in)
- D(dd1233) = in(1)
- D(dd2233) = in(2)
- D(dd2333) = in(3)
+ IN(1) = f1*D(DD233) - C234(CC122) + C134(CC122)
+ IN(2) = f2*D(DD233) - C234(CC122) - 2*D(DD0033)
+ IN(3) = f3*D(DD233) - C234(CC122) - 4*D(DD0023)
+ call SOLVER(in)
+ D(DD1233) = OUT(1)
+ D(DD2233) = OUT(2)
+ D(DD2333) = OUT(3)
- IN(1) = f1*D(dd333) - Cval(cc222,C234) + Cval(cc222,C134)
- IN(2) = f2*D(dd333) - Cval(cc222,C234) + Cval(cc222,C124)
- IN(3) = f3*D(dd333) - Cval(cc222,C234) - 6*D(dd0033)
- call SOLVE(in)
- D(dd1333) = in(1)
- D(dd2333) = .5D0*(D(dd2333) + in(2))
- D(dd3333) = in(3)
+ IN(1) = f1*D(DD333) - C234(CC222) + C134(CC222)
+ IN(2) = f2*D(DD333) - C234(CC222) + C124(CC222)
+ IN(3) = f3*D(DD333) - C234(CC222) - 6*D(DD0033)
+ call SOLVER(in)
+ D(DD1333) = OUT(1)
+ D(DD2333) = .5D0*(D(DD2333) + OUT(2))
+ D(DD3333) = OUT(3)
c00sum = c00sum +
- & Cval(cc001,C234) + Cval(cc0011,C234) + Cval(cc0012,C234) +
- & Cval(cc002,C234) + Cval(cc0012,C234) + Cval(cc0022,C234)
+ & C234(CC001) + C234(CC0011) + C234(CC0012) +
+ & C234(CC002) + C234(CC0012) + C234(CC0022)
c11sum = c11sum +
- & Cval(cc111,C234) + Cval(cc1111,C234) + Cval(cc1112,C234) +
- & Cval(cc112,C234) + Cval(cc1112,C234) + Cval(cc1122,C234)
+ & C234(CC111) + C234(CC1111) + C234(CC1112) +
+ & C234(CC112) + C234(CC1112) + C234(CC1122)
c12sum = c12sum +
- & Cval(cc112,C234) + Cval(cc1112,C234) + Cval(cc1122,C234) +
- & Cval(cc122,C234) + Cval(cc1122,C234) + Cval(cc1222,C234)
+ & C234(CC112) + C234(CC1112) + C234(CC1122) +
+ & C234(CC122) + C234(CC1122) + C234(CC1222)
c22sum = c22sum +
- & Cval(cc122,C234) + Cval(cc1122,C234) + Cval(cc1222,C234) +
- & Cval(cc222,C234) + Cval(cc1222,C234) + Cval(cc2222,C234)
+ & C234(CC122) + C234(CC1122) + C234(CC1222) +
+ & C234(CC222) + C234(CC1222) + C234(CC2222)
c1sum = c1sum + c11sum + c12sum
c2sum = c2sum + c12sum + c22sum
csum = csum + c1sum + c2sum
- IN(1) = f1*D(dd0000) - Cval(cc0000,C234) + Cval(cc0000,C134)
- IN(2) = f2*D(dd0000) - Cval(cc0000,C234) + Cval(cc0000,C124)
- IN(3) = f3*D(dd0000) - Cval(cc0000,C234) + Cval(cc0000,C123)
- call SOLVE(in)
- D(dd00001) = in(1)
- D(dd00002) = in(2)
- D(dd00003) = in(3)
+ IN(1) = f1*D(DD0000) - C234(CC0000) + C134(CC0000)
+ IN(2) = f2*D(DD0000) - C234(CC0000) + C124(CC0000)
+ IN(3) = f3*D(DD0000) - C234(CC0000) + C123(CC0000)
+ call SOLVER(in)
+ D(DD00001) = OUT(1)
+ D(DD00002) = OUT(2)
+ D(DD00003) = OUT(3)
- IN(1) = f1*D(dd0011) - c00sum - 4*D(dd00001)
- IN(2) = f2*D(dd0011) - c00sum + Cval(cc0011,C124)
- IN(3) = f3*D(dd0011) - c00sum + Cval(cc0011,C123)
- call SOLVE(in)
- D(dd00111) = in(1)
- D(dd00112) = in(2)
- D(dd00113) = in(3)
+ IN(1) = f1*D(DD0011) - c00sum - 4*D(DD00001)
+ IN(2) = f2*D(DD0011) - c00sum + C124(CC0011)
+ IN(3) = f3*D(DD0011) - c00sum + C123(CC0011)
+ call SOLVER(in)
+ D(DD00111) = OUT(1)
+ D(DD00112) = OUT(2)
+ D(DD00113) = OUT(3)
- IN(1) = f1*D(dd0022) - Cval(cc0011,C234) + Cval(cc0011,C134)
- IN(2) = f2*D(dd0022) - Cval(cc0011,C234) - 4*D(dd00002)
- IN(3) = f3*D(dd0022) - Cval(cc0011,C234) + Cval(cc0022,C123)
- call SOLVE(in)
- D(dd00122) = in(1)
- D(dd00222) = in(2)
- D(dd00223) = in(3)
+ IN(1) = f1*D(DD0022) - C234(CC0011) + C134(CC0011)
+ IN(2) = f2*D(DD0022) - C234(CC0011) - 4*D(DD00002)
+ IN(3) = f3*D(DD0022) - C234(CC0011) + C123(CC0022)
+ call SOLVER(in)
+ D(DD00122) = OUT(1)
+ D(DD00222) = OUT(2)
+ D(DD00223) = OUT(3)
- IN(1) = f1*D(dd0033) - Cval(cc0022,C234) + Cval(cc0022,C134)
- IN(2) = f2*D(dd0033) - Cval(cc0022,C234) + Cval(cc0022,C124)
- IN(3) = f3*D(dd0033) - Cval(cc0022,C234) - 4*D(dd00003)
- call SOLVE(in)
- D(dd00133) = in(1)
- D(dd00233) = in(2)
- D(dd00333) = in(3)
+ IN(1) = f1*D(DD0033) - C234(CC0022) + C134(CC0022)
+ IN(2) = f2*D(DD0033) - C234(CC0022) + C124(CC0022)
+ IN(3) = f3*D(DD0033) - C234(CC0022) - 4*D(DD00003)
+ call SOLVER(in)
+ D(DD00133) = OUT(1)
+ D(DD00233) = OUT(2)
+ D(DD00333) = OUT(3)
- IN(1) = f1*D(dd0023) - Cval(cc0012,C234) + Cval(cc0012,C134)
- IN(2) = f2*D(dd0023) - Cval(cc0012,C234) - 2*D(dd00003)
- IN(3) = f3*D(dd0023) - Cval(cc0012,C234) - 2*D(dd00002)
- call SOLVE(in)
- D(dd00123) = in(1)
- D(dd00223) = .5D0*(D(dd00223) + in(2))
- D(dd00233) = .5D0*(D(dd00233) + in(3))
+ IN(1) = f1*D(DD0023) - C234(CC0012) + C134(CC0012)
+ IN(2) = f2*D(DD0023) - C234(CC0012) - 2*D(DD00003)
+ IN(3) = f3*D(DD0023) - C234(CC0012) - 2*D(DD00002)
+ call SOLVER(in)
+ D(DD00123) = OUT(1)
+ D(DD00223) = .5D0*(D(DD00223) + OUT(2))
+ D(DD00233) = .5D0*(D(DD00233) + OUT(3))
- IN(1) = f1*D(dd1111) - csum - 8*D(dd00111)
- IN(2) = f2*D(dd1111) - csum + Cval(cc1111,C124)
- IN(3) = f3*D(dd1111) - csum + Cval(cc1111,C123)
- call SOLVE(in)
- D(dd11111) = in(1)
- D(dd11112) = in(2)
- D(dd11113) = in(3)
+ IN(1) = f1*D(DD1111) - csum - 8*D(DD00111)
+ IN(2) = f2*D(DD1111) - csum + C124(CC1111)
+ IN(3) = f3*D(DD1111) - csum + C123(CC1111)
+ call SOLVER(in)
+ D(DD11111) = OUT(1)
+ D(DD11112) = OUT(2)
+ D(DD11113) = OUT(3)
- IN(1) = f1*D(dd2222) - Cval(cc1111,C234) + Cval(cc1111,C134)
- IN(2) = f2*D(dd2222) - Cval(cc1111,C234) - 8*D(dd00222)
- IN(3) = f3*D(dd2222) - Cval(cc1111,C234) + Cval(cc2222,C123)
- call SOLVE(in)
- D(dd12222) = in(1)
- D(dd22222) = in(2)
- D(dd22223) = in(3)
+ IN(1) = f1*D(DD2222) - C234(CC1111) + C134(CC1111)
+ IN(2) = f2*D(DD2222) - C234(CC1111) - 8*D(DD00222)
+ IN(3) = f3*D(DD2222) - C234(CC1111) + C123(CC2222)
+ call SOLVER(in)
+ D(DD12222) = OUT(1)
+ D(DD22222) = OUT(2)
+ D(DD22223) = OUT(3)
- IN(1) = f1*D(dd3333) - Cval(cc2222,C234) + Cval(cc2222,C134)
- IN(2) = f2*D(dd3333) - Cval(cc2222,C234) + Cval(cc2222,C124)
- IN(3) = f3*D(dd3333) - Cval(cc2222,C234) - 8*D(dd00333)
- call SOLVE(in)
- D(dd13333) = in(1)
- D(dd23333) = in(2)
- D(dd33333) = in(3)
+ IN(1) = f1*D(DD3333) - C234(CC2222) + C134(CC2222)
+ IN(2) = f2*D(DD3333) - C234(CC2222) + C124(CC2222)
+ IN(3) = f3*D(DD3333) - C234(CC2222) - 8*D(DD00333)
+ call SOLVER(in)
+ D(DD13333) = OUT(1)
+ D(DD23333) = OUT(2)
+ D(DD33333) = OUT(3)
- IN(1) = f1*D(dd1122) - c11sum - 4*D(dd00122)
- IN(2) = f2*D(dd1122) - c11sum - 4*D(dd00112)
- IN(3) = f3*D(dd1122) - c11sum + Cval(cc1122,C123)
- call SOLVE(in)
- D(dd11122) = in(1)
- D(dd11222) = in(2)
- D(dd11223) = in(3)
+ IN(1) = f1*D(DD1122) - c11sum - 4*D(DD00122)
+ IN(2) = f2*D(DD1122) - c11sum - 4*D(DD00112)
+ IN(3) = f3*D(DD1122) - c11sum + C123(CC1122)
+ call SOLVER(in)
+ D(DD11122) = OUT(1)
+ D(DD11222) = OUT(2)
+ D(DD11223) = OUT(3)
- IN(1) = f1*D(dd1133) - c22sum - 4*D(dd00133)
- IN(2) = f2*D(dd1133) - c22sum + Cval(cc1122,C124)
- IN(3) = f3*D(dd1133) - c22sum - 4*D(dd00113)
- call SOLVE(in)
- D(dd11133) = in(1)
- D(dd11233) = in(2)
- D(dd11333) = in(3)
+ IN(1) = f1*D(DD1133) - c22sum - 4*D(DD00133)
+ IN(2) = f2*D(DD1133) - c22sum + C124(CC1122)
+ IN(3) = f3*D(DD1133) - c22sum - 4*D(DD00113)
+ call SOLVER(in)
+ D(DD11133) = OUT(1)
+ D(DD11233) = OUT(2)
+ D(DD11333) = OUT(3)
- IN(1) = f1*D(dd2233) - Cval(cc1122,C234) + Cval(cc1122,C134)
- IN(2) = f2*D(dd2233) - Cval(cc1122,C234) - 4*D(dd00233)
- IN(3) = f3*D(dd2233) - Cval(cc1122,C234) - 4*D(dd00223)
- call SOLVE(in)
- D(dd12233) = in(1)
- D(dd22233) = in(2)
- D(dd22333) = in(3)
+ IN(1) = f1*D(DD2233) - C234(CC1122) + C134(CC1122)
+ IN(2) = f2*D(DD2233) - C234(CC1122) - 4*D(DD00233)
+ IN(3) = f3*D(DD2233) - C234(CC1122) - 4*D(DD00223)
+ call SOLVER(in)
+ D(DD12233) = OUT(1)
+ D(DD22233) = OUT(2)
+ D(DD22333) = OUT(3)
- IN(1) = f1*D(dd1123) - c12sum - 4*D(dd00123)
- IN(2) = f2*D(dd1123) - c12sum - 2*D(dd00113)
- IN(3) = f3*D(dd1123) - c12sum - 2*D(dd00112)
- call SOLVE(in)
- D(dd11123) = in(1)
- D(dd11223) = .5D0*(D(dd11223) + in(2))
- D(dd11233) = .5D0*(D(dd11233) + in(3))
+ IN(1) = f1*D(DD1123) - c12sum - 4*D(DD00123)
+ IN(2) = f2*D(DD1123) - c12sum - 2*D(DD00113)
+ IN(3) = f3*D(DD1123) - c12sum - 2*D(DD00112)
+ call SOLVER(in)
+ D(DD11123) = OUT(1)
+ D(DD11223) = .5D0*(D(DD11223) + OUT(2))
+ D(DD11233) = .5D0*(D(DD11233) + OUT(3))
- IN(1) = f1*D(dd2223) - Cval(cc1112,C234) + Cval(cc1112,C134)
- IN(2) = f2*D(dd2223) - Cval(cc1112,C234) - 6*D(dd00223)
- IN(3) = f3*D(dd2223) - Cval(cc1112,C234) - 2*D(dd00222)
- call SOLVE(in)
- D(dd12223) = in(1)
- D(dd22223) = .5D0*(D(dd22223) + in(2))
- D(dd22233) = .5D0*(D(dd22233) + in(3))
+ IN(1) = f1*D(DD2223) - C234(CC1112) + C134(CC1112)
+ IN(2) = f2*D(DD2223) - C234(CC1112) - 6*D(DD00223)
+ IN(3) = f3*D(DD2223) - C234(CC1112) - 2*D(DD00222)
+ call SOLVER(in)
+ D(DD12223) = OUT(1)
+ D(DD22223) = .5D0*(D(DD22223) + OUT(2))
+ D(DD22233) = .5D0*(D(DD22233) + OUT(3))
- IN(1) = f1*D(dd2333) - Cval(cc1222,C234) + Cval(cc1222,C134)
- IN(2) = f2*D(dd2333) - Cval(cc1222,C234) - 2*D(dd00333)
- IN(3) = f3*D(dd2333) - Cval(cc1222,C234) - 6*D(dd00233)
- call SOLVE(in)
- D(dd12333) = in(1)
- D(dd22333) = .5D0*(D(dd22333) + in(2))
- D(dd23333) = .5D0*(D(dd23333) + in(3))
+ IN(1) = f1*D(DD2333) - C234(CC1222) + C134(CC1222)
+ IN(2) = f2*D(DD2333) - C234(CC1222) - 2*D(DD00333)
+ IN(3) = f3*D(DD2333) - C234(CC1222) - 6*D(DD00233)
+ call SOLVER(in)
+ D(DD12333) = OUT(1)
+ D(DD22333) = .5D0*(D(DD22333) + OUT(2))
+ D(DD23333) = .5D0*(D(DD23333) + OUT(3))
if( dump ) call XDumpCoeff(4, D)
end
diff --git a/Looptools/D/ffRn.F b/Looptools/D/ffRn.F
--- a/Looptools/D/ffRn.F
+++ b/Looptools/D/ffRn.F
@@ -1,130 +1,131 @@
* ffRn.F
* calculate Rn = \int_0^1 dx (x - cz - I signz) (x - cy - I signy)
* Input: cy, cz, signz, signy
* i*sign=-i*eps is needed in the case of real masses
* this file is part of LoopTools
* last modified 8 Dec 10 th
* Written by Le Duc Ninh, MPI, Munich (Dec 15, 2008).
* Spence, log and eta functions are taken from FF.
* 14 Aug 2009: changed ieps of cdyza to "signy" (before used "signza").
#include "externals.h"
+#include "types.h"
- double complex function ffRn(cy, signy, cz, signz, ier)
+ ComplexType function ffRn(cy, signy, cz, signz, ier)
implicit none
- double complex cy, cz
- double precision signy, signz
+ ComplexType cy, cz
+ RealType signy, signz
integer ier
#include "ff.h"
- double complex c1, c2, c1yz, cab1, cab2, dummy
- double precision sz, syz, sab1, sab2
+ ComplexType c1, c2, c1yz, cab1, cab2, dummy
+ RealType sz, syz, sab1, sab2
integer n
- double complex zfflog
+ ComplexType zfflog
integer nffet1
external zfflog, nffet1
if( abs(cy - cz) .lt. precx ) then
* cy == cza and check for singularities
* be careful with log(0) singularity.
sz = signz
c1 = 0
c2 = 0
- if( abs(DIMAG(cy)) .lt. precx .and. signy*sz .lt. 0 ) then
+ if( abs(Im(cy)) .lt. precx .and. signy*sz .lt. 0 ) then
sz = signy
- if( DBLE(cy) .ge. 0 ) then
+ if( Re(cy) .ge. 0 ) then
c2 = sign(2D0, signz)*c2ipi
- if( DBLE(cy) .le. 1 ) then
+ if( Re(cy) .le. 1 ) then
call ffwarn(255, ier, 1D0, 0D0)
- c1 = c2*(zfflog(-cy, 1, DCMPLX(-sz), ier) -
- & zfflog(DCMPLX(-1D-16), 1, DCMPLX(-sz), ier))
+ c1 = c2*(zfflog(-cy, 1, ToComplex(-sz), ier) -
+ & zfflog(ToComplex(-1D-16), 1, ToComplex(-sz), ier))
c2 = 0
endif
endif
endif
ffRn = .5D0*(c1 +
- & zfflog((cy - 1)/cy, 1, DCMPLX(sz), ier)*(
- & zfflog(1 - cy, 1, DCMPLX(-sz), ier) +
- & zfflog(-cy, 1, DCMPLX(-sz), ier) - c2 ))
+ & zfflog((cy - 1)/cy, 1, ToComplex(sz), ier)*(
+ & zfflog(1 - cy, 1, ToComplex(-sz), ier) +
+ & zfflog(-cy, 1, ToComplex(-sz), ier) - c2 ))
return
endif
* calculate the sign of imaginary parts and eta functions
* we do not need the ieps for y0
* if im(y0) == im(y1) we may need the ieps for the logs
- sz = DIMAG(cz)
+ sz = Im(cz)
if( sz .eq. 0 ) sz = signz
- syz = DIMAG(cy - cz)
+ syz = Im(cy - cz)
if( syz .eq. 0 ) syz = signy
c1yz = 1/(cy - cz)
- sab1 = DIMAG(-cz*c1yz)
+ sab1 = Im(-cz*c1yz)
if( sab1 .eq. 0 ) then
- sab1 = DBLE(cz)*signy
+ sab1 = Re(cz)*signy
c if( sab1 .eq. 0 ) call ffwarn(256, ier, 1D0, 0D0)
* this step: not checked but same as below
* choose +signy since this ieps is relevant if cza in (0,1)
if( sab1 .eq. 0 ) sab1 = signy
endif
- sab2 = DIMAG((1 - cz)*c1yz)
+ sab2 = Im((1 - cz)*c1yz)
if( sab2 .eq. 0 ) then
- sab2 = -DBLE(1 - cz)*signy
+ sab2 = -Re(1 - cz)*signy
c if( sab2 .eq. 0 ) call ffwarn(257, ier, 1D0, 0D0)
* this step: checked and worked
* choose -signy since this ieps is relevant if cza in (0,1)
if( sab2 .eq. 0 ) sab2 = -signy
endif
* calculate R-func from Sp-func
* def: R(y0, y1) =
* Sp(y0/(y0-y1)) + ln(y0/(y0-y1))*eta(-y1,1/(y0-y1)) -
* Sp((y0-1)/(y0-y1)) - ln((y0-1)/(y0-y1))*eta(1-y1,1/(y0-y1))
* calculate the two dilogs
* calls "ffzzdl(zdilog,ipi12,zlog,cx,ier)" in "ffcli2.F" or Li2C(z)
cab1 = cy*c1yz
- if( DIMAG(cab1) .eq. 0 .and. DBLE(cab1) .ge. 1 ) then
+ if( Im(cab1) .eq. 0 .and. Re(cab1) .ge. 1 ) then
call ffzzdl(c1, n, dummy, 1/cab1, ier)
c1 = -c1 - n*pi12 - pi6 -
- & .5D0*zfflog(-cab1, 1, DCMPLX(sab1), ier)**2
+ & .5D0*zfflog(-cab1, 1, ToComplex(sab1), ier)**2
else
call ffzzdl(c1, n, dummy, cab1, ier)
c1 = c1 + n*pi12
endif
cab2 = (cy - 1)*c1yz
- if( DIMAG(cab2) .eq. 0 .and. DBLE(cab2) .ge. 1 ) then
+ if( Im(cab2) .eq. 0 .and. Re(cab2) .ge. 1 ) then
call ffzzdl(c2, n, dummy, 1/cab2, ier)
c2 = -c2 - n*pi12 - pi6 -
- & .5D0*zfflog(-cab2, 1, DCMPLX(sab2), ier)**2
+ & .5D0*zfflog(-cab2, 1, ToComplex(sab2), ier)**2
else
call ffzzdl(c2, n, dummy, cab2, ier)
c2 = c2 + n*pi12
endif
* calculate the two logs
* ieps=1 to choose the cut along the real axis,
- n = nffet1(DCMPLX(0D0, -sz), DCMPLX(0D0, -syz),
- & DCMPLX(0D0, sab1), ier)
+ n = nffet1(ToComplex(0D0, -sz), ToComplex(0D0, -syz),
+ & ToComplex(0D0, sab1), ier)
if( n .ne. 0 )
- & c1 = c1 + n*c2ipi*zfflog(cab1, 1, DCMPLX(-sab1), ier)
+ & c1 = c1 + n*c2ipi*zfflog(cab1, 1, ToComplex(-sab1), ier)
- n = nffet1(DCMPLX(0D0, -sz), DCMPLX(0D0, -syz),
- & DCMPLX(0D0, sab2), ier)
+ n = nffet1(ToComplex(0D0, -sz), ToComplex(0D0, -syz),
+ & ToComplex(0D0, sab2), ier)
if( n .ne. 0 )
- & c2 = c2 + n*c2ipi*zfflog(cab2, 1, DCMPLX(-sab2), ier)
+ & c2 = c2 + n*c2ipi*zfflog(cab2, 1, ToComplex(-sab2), ier)
ffRn = c1 - c2 +
- & zfflog((cy - 1)/cy, 1, DCMPLX(signy), ier)*
- & zfflog(cy - cz, 1, DCMPLX(signy), ier)
+ & zfflog((cy - 1)/cy, 1, ToComplex(signy), ier)*
+ & zfflog(cy - cz, 1, ToComplex(signy), ier)
end
diff --git a/Looptools/D/ffS2.F b/Looptools/D/ffS2.F
--- a/Looptools/D/ffS2.F
+++ b/Looptools/D/ffS2.F
@@ -1,130 +1,131 @@
* ffS2.F
* calculate S2 = \int_0^1 dy ln(a y^2 + b y + c),
* where a is real and can be zero; b and c complex
* input: ra=a (real), cb=b, cc=c
* signc=sign(img(c)) in case c is real.
* cza and czb are the 2 roots of: a y^2 + b y + c == 0
* remarks: ieps is needed for cza, czb.
* this file is part of LoopTools
* last modified 8 Dec 10 th
* Written by Le Duc Ninh, MPI, Munich (2008).
* Spence, log and eta functions are taken from FF.
* Oct 28 2008
#include "externals.h"
+#include "types.h"
- double complex function ffS2(ra, cb, cc, signc, ier)
+ ComplexType function ffS2(ra, cb, cc, signc, ier)
implicit none
- double precision ra, signc
- double complex cb, cc
+ RealType ra, signc
+ ComplexType cb, cc
integer ier
#include "ff.h"
- double complex crdisc, cza, czb
- double precision sza, szb, sy1, sy2, sc
+ ComplexType crdisc, cza, czb
+ RealType sza, szb, sy1, sy2, sc
- double complex ffS2_linr, zfflog
+ ComplexType ffS2_linr, zfflog
integer nffet1
external ffS2_linr, zfflog, nffet1
- sc = DIMAG(cc)
+ sc = Im(cc)
if( sc .eq. 0 ) sc = signc
if( abs(ra) .lt. precx ) then
if( abs(cb) .lt. precx ) then
* 0 roots:
if( abs(cc) .lt. precx ) then
call fferr(89, ier)
ffS2 = 0
return
endif
- ffS2 = zfflog(cc, 1, DCMPLX(signc), ier)
+ ffS2 = zfflog(cc, 1, ToComplex(signc), ier)
return
endif
* 1 root:
cza = -cc/cb
- sza = -signc*DBLE(cb)
+ sza = -signc*Re(cb)
if( sza .eq. 0 ) sza = -signc
- ffS2 = zfflog(cb, 1, DCMPLX(sc), ier) +
+ ffS2 = zfflog(cb, 1, ToComplex(sc), ier) +
& ffS2_linr(cza, sza, ier)
- if( abs(DIMAG(cb)) .lt. precx ) return
+ if( abs(Im(cb)) .lt. precx ) return
* complex b
- szb = DIMAG(cza)
+ szb = Im(cza)
if( szb .eq. 0 ) szb = sza
ffS2 = ffS2 +
- & c2ipi*nffet1(cb, DCMPLX(0D0, -szb), DCMPLX(0D0, sc), ier)
+ & c2ipi*nffet1(cb, ToComplex(0D0, -szb), ToComplex(0D0, sc), ier)
return
endif
* 2 roots: cza = y1, czb = y2
* eq.: y**2 + (b/a) y + (c/a) = 0
* the ieps is irrelevant here since we take into account
* the contributions of both roots
*** Ninh changed: 14 Aug 2009
crdisc = sqrt(cb**2/ra**2 - 4*cc/ra)
cza = -.5D0*(cb/ra + crdisc)
czb = -.5D0*(cb/ra - crdisc)
if( abs(cza) .gt. abs(czb) ) then
czb = cc/(ra*cza)
else
cza = cc/(ra*czb)
endif
* calculate the sign of im(cza) and im(czb) which are related to ieps
sza = signc/ra
- if( abs(DBLE(crdisc)) .gt. precx ) sza = sza/DBLE(crdisc)
+ if( abs(Re(crdisc)) .gt. precx ) sza = sza/Re(crdisc)
szb = -sza
- sy1 = DIMAG(cza)
+ sy1 = Im(cza)
if( sy1 .eq. 0 ) sy1 = sza
- sy2 = DIMAG(czb)
+ sy2 = Im(czb)
if( sy2 .eq. 0 ) sy2 = szb
* calculate the log and etas
* ieps=1 to choose the cut along the real axis
ffS2 =
- & zfflog(DCMPLX(ra), 1, DCMPLX(sc), ier) +
- & c2ipi*nffet1(DCMPLX(0D0, -sy1), DCMPLX(0D0, -sy2),
- & DCMPLX(0D0, sc/ra), ier) +
+ & zfflog(ToComplex(ra), 1, ToComplex(sc), ier) +
+ & c2ipi*nffet1(ToComplex(0D0, -sy1), ToComplex(0D0, -sy2),
+ & ToComplex(0D0, sc/ra), ier) +
& ffS2_linr(cza, sza, ier) +
& ffS2_linr(czb, szb, ier)
end
************************************************************************
* calculate S2 = \int_0^1 dy ln(y - z),
* where z is complex
* input: cz, signz = sign(im(z)) in case z is real.
* remarks: ieps is needed.
- double complex function ffS2_linr(cz, signz, ier)
+ ComplexType function ffS2_linr(cz, signz, ier)
implicit none
- double complex cz
- double precision signz
+ ComplexType cz
+ RealType signz
integer ier
#include "ff.h"
- double complex zfflog
+ ComplexType zfflog
external zfflog
if( abs(cz) .lt. precx ) then
ffS2_linr = -1
else if( abs(cz - 1) .lt. precx ) then
- ffS2_linr = zfflog(-cz, 1, DCMPLX(-signz), ier) - 1
+ ffS2_linr = zfflog(-cz, 1, ToComplex(-signz), ier) - 1
else
ffS2_linr =
- & zfflog(1 - cz, 1, DCMPLX(-signz), ier)*(1 - cz) +
- & zfflog(-cz, 1, DCMPLX(-signz), ier)*cz - 1
+ & zfflog(1 - cz, 1, ToComplex(-signz), ier)*(1 - cz) +
+ & zfflog(-cz, 1, ToComplex(-signz), ier)*cz - 1
endif
end
diff --git a/Looptools/D/ffS3n.F b/Looptools/D/ffS3n.F
--- a/Looptools/D/ffS3n.F
+++ b/Looptools/D/ffS3n.F
@@ -1,111 +1,112 @@
* ffS3n.F
* calculate S3n = \int_0^1 dy (ra y^2 + cb y + cc + I signc)/(y - cy)
* where ra can be zero.
* input: cy=y0, ra=a (real), cb=b, cc=c
* signc=sign(im(c)), signy=sign(im(cy)) in case they are real.
* cza and czb are the 2 roots of: a y^2 + b y + c == 0
* remarks: ieps is needed for cza, czb and y0.
* this file is part of LoopTools
* last modified 8 Dec 10 th
* Written by Le Duc Ninh, MPI, Munich (2008).
* Spence, log and eta functions are taken from FF.
* Oct 27 2008
#include "externals.h"
+#include "types.h"
- double complex function ffS3n(cy, signy, ra, cb, cc, signc,
+ ComplexType function ffS3n(cy, signy, ra, cb, cc, signc,
& ier)
implicit none
- double precision ra, signy, signc
- double complex cy, cb, cc
+ RealType ra, signy, signc
+ ComplexType cy, cb, cc
integer ier
#include "ff.h"
- double complex cl, crdisc, cza, czb
- double precision sza, szb, sy1, sy2, sc
+ ComplexType cl, crdisc, cza, czb
+ RealType sza, szb, sy1, sy2, sc
- double complex ffRn, zfflog
+ ComplexType ffRn, zfflog
integer nffet1
external ffRn, zfflog, nffet1
* check for end-point sing.
if( abs(cy) .lt. precx .or. abs(cy - 1) .lt. precx ) then
call fferr(90, ier)
ffS3n = 0
return
endif
- cl = zfflog((cy - 1)/cy, 1, DCMPLX(signy), ier)
+ cl = zfflog((cy - 1)/cy, 1, ToComplex(signy), ier)
- sc = DIMAG(cc)
+ sc = Im(cc)
if( sc .eq. 0 ) sc = signc
if( abs(ra) .lt. precx ) then
if( abs(cb) .lt. precx ) then
* 0 roots:
if( abs(cc) .lt. precx ) then
call fferr(91, ier)
ffS3n = 0
return
endif
- ffS3n = cl*zfflog(cc, 1, DCMPLX(signc), ier)
+ ffS3n = cl*zfflog(cc, 1, ToComplex(signc), ier)
return
endif
* 1 root:
* eq.: b y + c == 0
cza = -cc/cb
- sza = -signc*DBLE(cb)
+ sza = -signc*Re(cb)
if( sza .eq. 0 ) sza = -signc
- ffS3n = cl*zfflog(cb, 1, DCMPLX(signc), ier) +
+ ffS3n = cl*zfflog(cb, 1, ToComplex(signc), ier) +
& ffRn(cy, signy, cza, sza, ier)
- if( abs(DIMAG(cb)) .gt. precx ) then
- szb = DIMAG(cza)
+ if( abs(Im(cb)) .gt. precx ) then
+ szb = Im(cza)
if( szb .eq. 0 ) szb = sza
ffS3n = ffS3n + cl*c2ipi*
- & nffet1(cb, DCMPLX(0D0, -szb), DCMPLX(0D0, sc), ier)
+ & nffet1(cb, ToComplex(0D0, -szb), ToComplex(0D0, sc), ier)
endif
return
endif
* 2 roots: cza = y1, czb = y2
* eq.: y**2 + (b/a) y + (c/a) = 0
* the ieps is irrelevant here since we take into account
* the contributions of both roots
*** Ninh changed: 14 Aug 2009
crdisc = sqrt(cb**2/ra**2 - 4*cc/ra)
cza = -.5D0*(cb/ra + crdisc)
czb = -.5D0*(cb/ra - crdisc)
if( abs(cza) .gt. abs(czb) ) then
czb = cc/(ra*cza)
else if( abs(czb) .gt. 1D-13 ) then
cza = cc/(ra*czb)
endif
* calculate the sign of im(cza) and im(czb) which are related to ieps
sza = sc/ra
- if( abs(DBLE(crdisc)) .gt. precx ) sza = sza/DBLE(crdisc)
+ if( abs(Re(crdisc)) .gt. precx ) sza = sza/Re(crdisc)
szb = -sza
- sy1 = DIMAG(cza)
+ sy1 = Im(cza)
if( sy1 .eq. 0 ) sy1 = sza
- sy2 = DIMAG(czb)
+ sy2 = Im(czb)
if( sy2 .eq. 0 ) sy2 = szb
* calculate the log, etas, and the 2 R-functions
* ieps=1 to choose the cut along the real axis
ffS3n =
- & cl*( zfflog(DCMPLX(ra), 1, DCMPLX(sc), ier) +
- & c2ipi*nffet1(DCMPLX(0D0, -sy1), DCMPLX(0D0, -sy2),
- & DCMPLX(0D0, sc/ra), ier) ) +
+ & cl*( zfflog(ToComplex(ra), 1, ToComplex(sc), ier) +
+ & c2ipi*nffet1(ToComplex(0D0, -sy1), ToComplex(0D0, -sy2),
+ & ToComplex(0D0, sc/ra), ier) ) +
& ffRn(cy, signy, cza, sza, ier) +
& ffRn(cy, signy, czb, szb, ier)
end
diff --git a/Looptools/D/ffT13.F b/Looptools/D/ffT13.F
--- a/Looptools/D/ffT13.F
+++ b/Looptools/D/ffT13.F
@@ -1,125 +1,126 @@
* ffT13.F
* part of the complex four-point function
* this file is part of LoopTools
* last modified 8 Dec 10 th
#include "externals.h"
+#include "types.h"
* T13 = \int_0^1 dx \int_0^x dy
* y/( (rg y^2 + rh xy + cd x + cj y + cf + I signf) *
* (ra y^2 + rc xy + cd x + ce y + cf + I signf) )
* with signf = -eps
* variables "signX" is the sign of im(X) in case X becomes real.
* No extra term is needed.
* Nov 11 2008
- double complex function ffT13(ra, rc, rg, rh,
+ ComplexType function ffT13(ra, rc, rg, rh,
& cd, ce, cf, signf, cj, ier)
implicit none
- double precision ra, rc, rg, rh, signf
- double complex cd, ce, cf, cj
+ RealType ra, rc, rg, rh, signf
+ ComplexType cd, ce, cf, cj
integer ier
#include "ff.h"
- double complex ck, cl, cn, cy(2), crdetq4
- double complex cbj(4), ccj(4)
- double complex ffS3nAll1, ffS3nAll2
- double precision sn, scj, sy(2), raj(4)
+ ComplexType ck, cl, cn, cy(2), crdetq4
+ ComplexType cbj(4), ccj(4)
+ ComplexType ffS3nAll1, ffS3nAll2
+ RealType sn, scj, sy(2), raj(4)
- double complex ffS2, ffS3n
+ ComplexType ffS2, ffS3n
external ffS2, ffS3n
* the coefficients of the 4 log arguments
raj(1) = ra
raj(2) = rg
raj(3) = rg + rh
raj(4) = ra + rc
cbj(1) = ce + rc
cbj(2) = cj + rh
cbj(3) = cd + cj
cbj(4) = ce + cd
ccj(1) = cf + cd
ccj(2) = cf + cd
ccj(3) = cf
ccj(4) = cf
* the ieps is the same for all
scj = signf
* the prefactor 1/(S V - T U)
* eq. (S V - T U) = K y^2 + L y + N == 0
* Leading Landau singularity can occur if y1 = y2 and eps -> 0
* the ieps is needed for the roots
ck = rh*ra - rc*rg
cl = (ra - rg)*cd + rh*ce - rc*cj
cn = (rh - rc)*cf + cd*(ce - cj)
* the ieps for cn
sn = signf*(rh - rc)
* if (rh - rc) = 0 then we are at the boundary of phase space
* and sn is irrelevant
if( abs(ck) .lt. precx ) then
if( abs(cl) .lt. precx ) then
if( abs(cn) .lt. precx ) then
call fferr(99, ier)
ffT13 = 0
return
endif
* the case ny = 0, (SV - TU) = N = constant
* no extra term is needed
ffT13 = -1/cn*(
& ffS2(raj(1), cbj(1), ccj(1), scj, ier) -
& ffS2(raj(2), cbj(2), ccj(2), scj, ier) +
& ffS2(raj(3), cbj(3), ccj(3), scj, ier) -
& ffS2(raj(4), cbj(4), ccj(4), scj, ier) )
return
endif
* the case ny = 1, (S V - T U) = L y + N
cy(1) = -cn/cl
* ieps for this root
- sy(1) = -sn*DBLE(cl)
+ sy(1) = -sn*Re(cl)
if( sy(1) .eq. 0 ) sy(1) = signf
ffS3nAll1 =
& ffS3n(cy(1), sy(1), raj(1), cbj(1), ccj(1), scj, ier) -
& ffS3n(cy(1), sy(1), raj(2), cbj(2), ccj(2), scj, ier) +
& ffS3n(cy(1), sy(1), raj(3), cbj(3), ccj(3), scj, ier) -
& ffS3n(cy(1), sy(1), raj(4), cbj(4), ccj(4), scj, ier)
ffT13 = -ffS3nAll1/cl
return
endif
* the case ny = 2, (SV - TU) = K y^2 + L y + N
crdetq4 = sqrt(cl**2 - 4*ck*cn)
cy(1) = -.5D0/ck*(cl + crdetq4)
cy(2) = -.5D0/ck*(cl - crdetq4)
if( abs(cy(1)) .gt. abs(cy(2)) ) then
cy(2) = cn/(ck*cy(1))
else
cy(1) = cn/(ck*cy(2))
endif
* calculate the signs of img(cy1) and img(cy2) which are related to ieps
- sy(1) = sn*DBLE(crdetq4)
+ sy(1) = sn*Re(crdetq4)
if( sy(1) .eq. 0 ) sy(1) = signf
sy(2) = -sy(1)
ffS3nAll1 =
& ffS3n(cy(1), sy(1), raj(1), cbj(1), ccj(1), scj, ier) -
& ffS3n(cy(1), sy(1), raj(2), cbj(2), ccj(2), scj, ier) +
& ffS3n(cy(1), sy(1), raj(3), cbj(3), ccj(3), scj, ier) -
& ffS3n(cy(1), sy(1), raj(4), cbj(4), ccj(4), scj, ier)
ffS3nAll2 =
& ffS3n(cy(2), sy(2), raj(1), cbj(1), ccj(1), scj, ier) -
& ffS3n(cy(2), sy(2), raj(2), cbj(2), ccj(2), scj, ier) +
& ffS3n(cy(2), sy(2), raj(3), cbj(3), ccj(3), scj, ier) -
& ffS3n(cy(2), sy(2), raj(4), cbj(4), ccj(4), scj, ier)
ffT13 = (ffS3nAll1 - ffS3nAll2)/crdetq4
end
diff --git a/Looptools/D/ffTn.F b/Looptools/D/ffTn.F
--- a/Looptools/D/ffTn.F
+++ b/Looptools/D/ffTn.F
@@ -1,467 +1,469 @@
* ffTn.F
* calculate T(ra, rb, rc, rg, rh; cd, ce, cf, cj) defined as:
* T = \int_0^1 dx \int_0^x dy
* 1/((rg x + rh y + cj)
* (ra x^2 + rb y^2 + rc x y + cd x + ce y + cf + I signf))
* with signf = -eps,
* {ra,rb,rc,rg,rh} are real, {cd,ce,cf,cj} are complex.
* important: variables "signX" is the sign of im(X) in case X becomes real.
* this file is part of LoopTools
* last modified 8 Dec 10 th
* Written by Le Duc Ninh, MPI, Munich (2008).
* Spence, log and eta functions are taken from FF.
* Oct 27 2008
+#include "externals.h"
+#include "types.h"
#include "defs.h"
- double complex function ffTn(ra, rb, rc, rgx, rhx,
+ ComplexType function ffTn(ra, rb, rc, rgx, rhx,
& cd, ce, cf, signf, cjx, signj, key, ier)
implicit none
- double precision ra, rb, rc, rgx, rhx, signf, signj
- double complex cd, ce, cf, cjx
+ RealType ra, rb, rc, rgx, rhx, signf, signj
+ ComplexType cd, ce, cf, cjx
integer key, ier
#include "ff.h"
- double complex cj, crdetq4, crdetq42, cy(2), cy2(2)
- double complex crdisc, cbeta1, cbeta2, cbeta
- double complex ctv, ctemp, cresd, cyij
- double complex cbj(6), ccj(6), cbk(6), cck(6)
- double precision rg, rh, reps
- double precision sj, scj, sy(2), sy2(2), stv, syij
- double precision rminuv, rminuv2, raj(6)
+ ComplexType cj, crdetq4, crdetq42, cy(2), cy2(2)
+ ComplexType crdisc, cbeta1, cbeta2, cbeta
+ ComplexType ctv, ctemp, cresd, cyij
+ ComplexType cbj(6), ccj(6), cbk(6), cck(6)
+ RealType rg, rh, reps
+ RealType sj, scj, sy(2), sy2(2), stv, syij
+ RealType rminuv, rminuv2, raj(6)
integer i, j, ny, ny2, chketa(2), chketa2(2)
- double complex ffT_lin, ffS2, ffS3n, zfflog
+ ComplexType ffT_lin, ffS2, ffS3n, zfflog
integer nffet1
external ffT_lin, ffS2, ffS3n, zfflog, nffet1
ier = 0
* calculate ieps and the sign of im(J)
- reps = DIMAG(cf)
+ reps = Im(cf)
if( reps .eq. 0 ) reps = signf
reps = sign(1D0, -reps)
- sj = DIMAG(cjx)
+ sj = Im(cjx)
if( sj .eq. 0 ) sj = signj
sj = sign(1D0, sj*reps)
* change the sign of G,H,J
* sj = 1 or -1
rg = -sj*rgx
rh = -sj*rhx
cj = -sj*cjx
if( abs(rb) .lt. precx ) then
ffTn = sj*ffT_lin(ra, rc, rg, rh, cd, ce, cf, cj,
& signf, reps, ier)
return
endif
if( abs(ra) .lt. precx ) then
* change the integration variables to get rb = 0 as above
ffTn = sj*ffT_lin(rb + rc, -rc, -rg - rh, rg,
& -2*(rb + rc) - cd - ce,
& rc + cd,
& rb + rc + cd + ce + cf,
& rg + rh + cj,
& signf, reps, ier)
return
endif
* calculate beta
* beta is one root of: B beta^2 + C beta + A = 0
* we do not need the ieps for beta
- crdisc = sqrt(DCMPLX(rc**2 - 4*rb*ra))
+ crdisc = sqrt(ToComplex(rc**2 - 4*rb*ra))
cbeta1 = -.5D0/rb*(rc + crdisc)
cbeta2 = -.5D0/rb*(rc - crdisc)
if( abs(cbeta1) .gt. abs(cbeta2) ) then
cbeta2 = ra/(rb*cbeta1)
else
cbeta1 = cbeta2
cbeta2 = ra/(rb*cbeta2)
endif
* Ninh added: 14 Aug 2009
* be careful with this approximation, IMG can be wrong
if( abs(1 - cbeta1) .lt. precx ) cbeta1 = 1
if( abs(1 - cbeta2) .lt. precx ) cbeta2 = 1
* which one for beta?
if( abs(cbeta1) .gt. abs(cbeta2) ) then
ctemp = cbeta1
cbeta1 = cbeta2
cbeta2 = ctemp
endif
* look at the prefactor 1/(S V - T U)
* eq. (S V - T U) = K y^2 + L y + N == 0
* to decide which beta is the best.
* The two roots are calculated.
* Leading Landau Sing. can occur if y1 = y2 and eps -> 0
* the ieps is needed for the roots
cbeta = cbeta1
if( abs(cbeta2 - 1) .lt. precx ) then
cbeta = cbeta2
cbeta2 = cbeta1
endif
call ffwbeta(rb, rc, rg, rh, cd, ce, cf, cj, signf,
& cbeta, crdetq4, ny, cy, sy, chketa, rminuv, key, ier)
* to check whether there is numerical cancellation
* at the border of the triangle
if( rminuv .lt. 1D-10 ) then
call ffwbeta(rb, rc, rg, rh, cd, ce, cf, cj, signf,
& cbeta2, crdetq42, ny2, cy2, sy2, chketa2, rminuv2,
& key, ier)
if( rminuv2 .lt. rminuv ) then
call ffwarn(254, ier, 1D0, 0D0)
else
* choose the beta2-parameters
cbeta = cbeta2
crdetq4 = crdetq42
ny = ny2
do i = 1, ny
sy(i) = sy2(i)
cy(i) = cy2(i)
chketa(i) = chketa2(i)
enddo
endif
endif
* the coefficients of the 6 log arguments
raj(1) = 0
raj(2) = 0
raj(3) = 0
raj(4) = rb
raj(5) = ra + rb + rc
raj(6) = ra
cbj(1) = rh
cbj(2) = rg + rh
cbj(3) = rg
cbj(4) = rc + ce
cbj(5) = ce + cd
cbj(6) = cd
ccj(1) = rg + cj
ccj(2) = cj
ccj(3) = cj
ccj(4) = ra + cd + cf
ccj(5) = cf
ccj(6) = cf
* the ieps for the log arguments
scj = -reps
* the cck(6)-coefficients before the logs
cck(1) = 1
cck(2) = -1 + cbeta
cck(3) = -cbeta
cck(4) = -1
cck(5) = 1 - cbeta
cck(6) = cbeta
if( ny .eq. 0 ) then
* no extra term is needed
ffTn = -sj/crdetq4*(
& cck(1)*ffS2(raj(1), cbj(1), ccj(1), scj, ier) +
& cck(2)*ffS2(raj(2), cbj(2), ccj(2), scj, ier) +
& cck(3)*ffS2(raj(3), cbj(3), ccj(3), scj, ier) +
& cck(4)*ffS2(raj(4), cbj(4), ccj(4), scj, ier) +
& cck(5)*ffS2(raj(5), cbj(5), ccj(5), scj, ier) +
& cck(6)*ffS2(raj(6), cbj(6), ccj(6), scj, ier) )
return
endif
* cbk(6)-coefficients of cj/(aj y - bj - yi)
cbk(1) = cbeta
cbk(2) = 0
cbk(3) = 0
cbk(4) = cbeta
cbk(5) = 0
cbk(6) = 0
ffTn = 0
do i = 1, ny
cresd = 0
if( chketa(i) .ne. 0 ) then
* extra term needed
* calculate the residue
* the denominator was checked above in ffS3n therefore the (V/T)_pole
* should be safe now:
ctv = (rh*cy(i) + cj)/(cy(i)*(rb*cy(i) + ce) + cf)
ctemp = (rg + cbeta*rh)/
& ((rc + 2*cbeta*rb)*cy(i) + cd + ce*cbeta)
- if( abs(DIMAG(ctemp)) .gt. abs(DIMAG(ctv)) ) ctv = ctemp
+ if( abs(Im(ctemp)) .gt. abs(Im(ctv)) ) ctv = ctemp
* if im(ctv) = 0 then take the ieps from T/V
- stv = -signf*DBLE(rh*cy(i) + cj)
+ stv = -signf*Re(rh*cy(i) + cj)
if( stv .eq. 0 ) stv = -signf
- ctv = zfflog(ctv, 1, DCMPLX(stv), ier)
+ ctv = zfflog(ctv, 1, ToComplex(stv), ier)
if( abs(ctv) .gt. precx ) then
do j = 1, 3
if( abs(cck(j)) .gt. precx ) then
cyij = -Sgn(j)*(cy(i) + cbk(j))/cck(j)
- syij = -Sgn(j)*sy(i)*DBLE(cck(j))
+ syij = -Sgn(j)*sy(i)*Re(cck(j))
if( syij .eq. 0 ) syij = sy(i)
cresd = cresd - Sgn(i+j)*
- & zfflog((cyij - 1)/cyij, 1, DCMPLX(syij), ier)
+ & zfflog((cyij - 1)/cyij, 1, ToComplex(syij), ier)
endif
enddo
cresd = cresd*ctv
endif
endif
* calculate the main part
do j = 1, 6
if( abs(cck(j)) .gt. precx ) then
cyij = -Sgn(j)*(cy(i) + cbk(j))/cck(j)
- syij = -Sgn(j)*sy(i)*DBLE(cck(j))
+ syij = -Sgn(j)*sy(i)*Re(cck(j))
if( syij .eq. 0 ) syij = sy(i)
cresd = cresd + Sgn(i+j)*
& ffS3n(cyij, syij, raj(j), cbj(j), ccj(j), scj, ier)
endif
enddo
ffTn = ffTn + cresd
enddo
* the prefactor of Landau det.
ffTn = sj/crdetq4*ffTn
end
************************************************************************
* calculate the roots of the eq. ck x^2 + cl x + cn = 0
* and check if the roots are inside the triangle [0, -cbeta, 1 - cbeta]
* the ieps part for the roots is needed.
* Nov 17 2008
* input: rb, rc, rg, rh, cd, ce, cf, cj, signf, cbeta
* output: ru, rv, ny, cy, signy, ck, cl, cn
subroutine ffwbeta(rb, rc, rg, rh, cd, ce, cf, cj, signf,
& cbeta, crdetq4, ny, cy, signy, chketa, rminuv, key, ier)
implicit none
- double precision rb, rc, rg, rh, signf, signy(2), rminuv
- double complex cd, ce, cf, cj, cbeta, cy(2), crdetq4
+ RealType rb, rc, rg, rh, signf, signy(2), rminuv
+ ComplexType cd, ce, cf, cj, cbeta, cy(2), crdetq4
integer ny, chketa(2), key, ier
#include "lt.h"
- double complex ck, cl, cn
- double complex cab, cac, cay
- double precision dotyc, dotyb, dotbc, dotbb, dotcc
- double precision sn, ru, rv, abc2
+ ComplexType ck, cl, cn
+ ComplexType cab, cac, cay
+ RealType dotyc, dotyb, dotbc, dotbb, dotcc
+ RealType sn, ru, rv, abc2
integer i
chketa(1) = 0
chketa(2) = 0
rminuv = 1D300
ck = rb*rg - rh*(rc + cbeta*rb)
cl = rg*ce - rh*cd - cj*(rc + 2*rb*cbeta)
cn = (rg + rh*cbeta)*cf - cj*(cd + ce*cbeta)
* the ieps for cn
- sn = signf*DBLE(rg + rh*cbeta)
+ sn = signf*Re(rg + rh*cbeta)
if( sn .eq. 0 ) sn = signf
if( abs(ck) .lt. precx ) then
if( abs(cl) .lt. precx ) then
* the case ny = 0, (S V - T U) = N = constant
if( abs(cn) .lt. precx ) then
call fferr(104, ier)
cbeta = 0
return
endif
ny = 0
crdetq4 = cn
else
* the case ny = 1, (S V - T U) = L y + N
ny = 1
cy(1) = -cn/cl
* ieps for this pole
- signy(1) = -sn*DBLE(cl)
+ signy(1) = -sn*Re(cl)
if( signy(1) .eq. 0 ) signy(1) = signf
crdetq4 = cl
endif
else
* the case ny = 2, (S V - T U) = K y^2 + L y + N
ny = 2
crdetq4 = sqrt(cl**2 - 4*ck*cn)
cy(1) = -.5D0/ck*(cl + crdetq4)
cy(2) = -.5D0/ck*(cl - crdetq4)
if( abs(cy(1)) .gt. abs(cy(2)) ) then
cy(2) = cn/(ck*cy(1))
else
cy(1) = cn/(ck*cy(2))
endif
* calculate the sign of img(cy1) and img(cy2) which are related to ieps
- signy(1) = sn*DBLE(crdetq4)
+ signy(1) = sn*Re(crdetq4)
if( signy(1) .eq. 0 ) signy(1) = signf
signy(2) = -signy(1)
endif
- if( ny .eq. 0 .or. abs(DIMAG(cbeta)) .lt. precx ) return
+ if( ny .eq. 0 .or. abs(Im(cbeta)) .lt. precx ) return
if( key .eq. 1 ) then
chketa(1) = 1
chketa(2) = 1
else
* check if the poles are inside the triangle [0, -cbeta, 1 - cbeta]
* using the barycentric technique
- abc2 = 1/DIMAG(cbeta)**2
+ abc2 = 1/Im(cbeta)**2
do i = 1, ny
cay = cy(i) + cbeta
cac = cbeta
cab = 1
- dotyc = DBLE(cay)*DBLE(cac) + DIMAG(cay)*DIMAG(cac)
- dotyb = DBLE(cay)*DBLE(cab) + DIMAG(cay)*DIMAG(cab)
- dotbc = DBLE(cab)*DBLE(cac) + DIMAG(cab)*DIMAG(cac)
- dotcc = DBLE(cac)*DBLE(cac) + DIMAG(cac)*DIMAG(cac)
+ dotyc = Re(cay)*Re(cac) + Im(cay)*Im(cac)
+ dotyb = Re(cay)*Re(cab) + Im(cay)*Im(cab)
+ dotbc = Re(cab)*Re(cac) + Im(cab)*Im(cac)
+ dotcc = Re(cac)*Re(cac) + Im(cac)*Im(cac)
dotbb = 1
ru = (dotyc*dotbb - dotbc*dotyb)*abc2
rv = (dotcc*dotyb - dotyc*dotbc)*abc2
if( ru .ge. 0 .and. rv .ge. 0 .and. ru + rv .le. 1 )
& chketa(i) = 1
rminuv = min(rminuv, abs(ru), abs(rv))
enddo
endif
end
************************************************************************
* calculate T(ra, rc, rg, rh; cd, ce, cf, cj) defined as:
* T = \int_0^1 dx \int_0^x dy
* 1/( (rg x + rh y + cj)
* (ra x^2 + rc x y + cd x + ce y + cf + I signf) )
* with signf = -eps,
* {ra, rc, rg, rh} are real, {cd, ce, cf, cj} are complex.
* important: variables "signX" is the sign of img(X) in case X becomes real.
* No extra term is needed.
* Written by Le Duc Ninh, MPI, Munich (2008).
* Spence, log and eta functions are taken from FF.
* Nov 10 2008
- double complex function ffT_lin(ra, rc, rg, rh,
+ ComplexType function ffT_lin(ra, rc, rg, rh,
& cd, ce, cf, cj, signf, reps, ier)
implicit none
- double precision ra, rc, rg, rh, signf, reps
- double complex cd, ce, cf, cj
+ RealType ra, rc, rg, rh, signf, reps
+ ComplexType cd, ce, cf, cj
integer ier
#include "ff.h"
- double complex ck, cl, cn, cy(2), crdetq4
- double complex cbj(4), ccj(4)
- double complex ffS3nAll1, ffS3nAll2
- double precision sn, scj, sy(2), raj(4)
+ ComplexType ck, cl, cn, cy(2), crdetq4
+ ComplexType cbj(4), ccj(4)
+ ComplexType ffS3nAll1, ffS3nAll2
+ RealType sn, scj, sy(2), raj(4)
- double complex ffS2, ffS3n
+ ComplexType ffS2, ffS3n
external ffS2, ffS3n
* the coefficients of the 4 log arguments
raj(1) = rc + ra
raj(2) = 0
raj(3) = 0
raj(4) = ra
cbj(1) = ce + cd
cbj(2) = rh + rg
cbj(3) = rg
cbj(4) = cd
ccj(1) = cf
ccj(2) = cj
ccj(3) = cj
ccj(4) = cf
* the ieps is the same for all
scj = -reps
* the prefactor 1/(S V - T U)
* eq. (S V - T U) = K y^2 + L y + N = 0
* Leading Landau Sing. can occur if y1 == y2 and eps -> 0
* the ieps is needed for the roots
ck = rh*ra - rc*rg
cl = rh*cd - rc*cj - ce*rg
cn = rh*cf - ce*cj
* the ieps for cn
sn = -reps*rh
if( sn .eq. 0 ) sn = -reps
if( abs(ck) .lt. precx ) then
if( abs(cl) .lt. precx ) then
if( abs(cn) .lt. precx ) then
call fferr(105, ier)
ffT_lin = 0
return
endif
* the case ny = 0, (S V - T U) = N = constant
ffT_lin = 1/cn*(
& ffS2(raj(1), cbj(1), ccj(1), scj, ier) -
& ffS2(raj(2), cbj(2), ccj(2), scj, ier) +
& ffS2(raj(3), cbj(3), ccj(3), scj, ier) -
& ffS2(raj(4), cbj(4), ccj(4), scj, ier) )
return
endif
* the case ny = 1, (S V - T U) = L y + N
cy(1) = -cn/cl
* ieps for this pole
- sy(1) = -sn*DBLE(cl)
+ sy(1) = -sn*Re(cl)
if( sy(1) .eq. 0 ) sy(1) = signf
ffS3nAll1 =
& ffS3n(cy(1), sy(1), raj(1), cbj(1), ccj(1), scj, ier) -
& ffS3n(cy(1), sy(1), raj(2), cbj(2), ccj(2), scj, ier) +
& ffS3n(cy(1), sy(1), raj(3), cbj(3), ccj(3), scj, ier) -
& ffS3n(cy(1), sy(1), raj(4), cbj(4), ccj(4), scj, ier)
ffT_lin = -ffS3nAll1/cl
return
endif
* the case ny = 2, (S V - T U) = K y^2 + L y + N
crdetq4 = sqrt(cl**2 - 4*ck*cn)
cy(1) = -.5D0/ck*(cl + crdetq4)
cy(2) = -.5D0/ck*(cl - crdetq4)
if( abs(cy(1)) .gt. abs(cy(2)) ) then
cy(2) = cn/(ck*cy(1))
else
cy(1) = cn/(ck*cy(2))
endif
* calculate the sign of im(cy1) and im(cy2) which are related to ieps
- sy(1) = sn*DBLE(crdetq4)
+ sy(1) = sn*Re(crdetq4)
if( sy(1) .eq. 0 ) sy(1) = signf
sy(2) = -sy(1)
ffS3nAll1 =
& ffS3n(cy(1), sy(1), raj(1), cbj(1), ccj(1), scj, ier) -
& ffS3n(cy(1), sy(1), raj(2), cbj(2), ccj(2), scj, ier) +
& ffS3n(cy(1), sy(1), raj(3), cbj(3), ccj(3), scj, ier) -
& ffS3n(cy(1), sy(1), raj(4), cbj(4), ccj(4), scj, ier)
ffS3nAll2 =
& ffS3n(cy(2), sy(2), raj(1), cbj(1), ccj(1), scj, ier) -
& ffS3n(cy(2), sy(2), raj(2), cbj(2), ccj(2), scj, ier) +
& ffS3n(cy(2), sy(2), raj(3), cbj(3), ccj(3), scj, ier) -
& ffS3n(cy(2), sy(2), raj(4), cbj(4), ccj(4), scj, ier)
ffT_lin = (ffS3nAll2 - ffS3nAll1)/crdetq4
end
diff --git a/Looptools/D/ffcd0.F b/Looptools/D/ffcd0.F
deleted file mode 100644
--- a/Looptools/D/ffcd0.F
+++ /dev/null
@@ -1,639 +0,0 @@
-* $Id: ffcd0.f,v 1.3 1995/12/08 10:50:35 gj Exp $
-*###[ ffcd0:
- subroutine ffcd0(cd0,cpi,ier)
-***#[*comment:***********************************************************
-* *
-* 1 / *
-* calculate d0 = ----- \dq [(q^2 + 2*s_1.q)*(q^2 + 2*s2.q) *
-* ipi^2 / *(q^2 + 2*s3.q)*(q^2 + 2*s4.q)]^-1 *
-* *
-* |p9 *
-* \p8 V p7/ *
-* \ / *
-* \________/ *
-* | m4 | *
-* = | | /____ *
-* m1| |m3 \ p10 *
-* | | all momenta are incoming *
-* |________| *
-* / m2 \ *
-* / \ *
-* /p5 p6\ *
-* *
-* *
-* input: cpi(1-10) (complex) 1-4: m_i^2, 5-10 p_i^2 (B&D metric)
-* cpi(11)=u (complex) u=p5.p5+..-p9.p9-p10.10 or 0 *
-* cpi(12)=v (complex) v=-p5.p5+p6.p6-p7.p7+.. or 0 *
-* cpi(13)=w (complex) w=p5.p5-p6.p6+p7.p7-p8.p8+.. *
-* output: cd0 (complex) D0 *
-* ier (integer) <50: #digits lost, >100: error *
-* calls: ffcd0a,ffxd0 *
-* *
-***#]*comment:***********************************************************
-* #[ declarations:
- implicit none
-*
-* arguments:
-*
- DOUBLE COMPLEX cd0,cpi(13)
- integer ier
-*
-* local variables
-*
- DOUBLE COMPLEX cs,cfac
- integer i,ier0,init
- logical luvw(3)
- DOUBLE PRECISION xpi(13),sprec
- DOUBLE COMPLEX cpipj(10,13)
- save init
-*
-* common blocks:
-*
- include 'ff.h'
-*
-* data
-*
- data init /0/
-* #] declarations:
-* #[ the real case:
-*
- if ( nschem.ge.2 ) then
- if ( DIMAG(cpi(1)).ne.0 .or. DIMAG(cpi(2)).ne.0 .or.
- + DIMAG(cpi(3)).ne.0 .or. DIMAG(cpi(4)).ne.0 ) goto 40
- elseif ( init .eq. 0 ) then
- init = 1
- print *,'ffcd0: disregarding complex masses, nschem= ',
- + nschem
- endif
- do 10 i=1,13
- xpi(i) = DBLE(cpi(i))
- 10 continue
- sprec = precx
- precx = precc
- call ffxd0(cd0,xpi,ier)
- if ( ldot ) then
- ier0 = 0
- call ffcif4(cpi,luvw,cpipj,ier0)
- call ffcod4(cpi,cpipj)
- if ( luvw(1) ) cpi(11) = 0
- if ( luvw(2) ) cpi(12) = 0
- if ( luvw(3) ) cpi(13) = 0
- endif
- precx = sprec
- return
- 40 continue
-*
-* #] the real case:
-* #[ check input:
-*
- idsub = 0
-*
-* #] check input:
-* #[ call ffcif4,ffcd0a:
-*
- call ffcif4(cpipj,luvw,cpi,ier)
- call ffcd0b(cs,cfac,cpi,cpipj,0,ier)
- cd0 = cs*cfac
-*
-* restore the zeros for u,v,w as we have calculated them
-* ourselves and the user is unlikely to do this...
-*
- if ( luvw(1) ) cpi(11) = 0
- if ( luvw(2) ) cpi(12) = 0
- if ( luvw(3) ) cpi(13) = 0
-*
-* #] call ffcif4,ffcd0a:
-*###] ffcd0:
- end
-*###[ ffcd0a:
- subroutine ffcd0a(cd0,cpi,cpipj,ier)
-***#[*comment:***********************************************************
-* *
-* Dummy routine. *
-* *
-***#]*comment:***********************************************************
-* #[ declarations:
- implicit none
-*
-* arguments
-*
- integer ier
- DOUBLE COMPLEX cd0,cpi(13),cpipj(10,13)
-*
-* local variables
-*
- DOUBLE COMPLEX cs,cfac
-*
-* #] declarations:
-* #[ call ffcd0b:
-*
- call ffcd0b(cs,cfac,cpi,cpipj,0,ier)
- cd0 = cs*cfac
-*
-* #] call ffcd0b:
-*###] ffcd0a:
- end
-*###[ ffcd0b:
- subroutine ffcd0b(cs,cfac,cpi,cpipj,ndiv,ier)
-***#[*comment:***********************************************************
-* *
-* See ffcd0, the differences between the input parameters are *
-* also input. This routines has the big nschem switchyard. *
-* *
-***#]*comment:***********************************************************
-* #[ declarations:
- implicit none
-*
-* arguments
-*
- integer ier,ndiv
- DOUBLE COMPLEX cs,cfac,cpi(13),cpipj(10,13)
-*
-* local variables
-*
- integer i,j,initlo,iir(2,4),ithres(4,4)
- logical ldone
- DOUBLE PRECISION xpi(13),dpipj(10,13),sprec
- save initlo
-*
-* common blocks
-*
- include 'ff.h'
-*
-* data
-*
- data initlo /0/
-* #] declarations:
-* #[ the real case:
-*
- if ( DIMAG(cpi(1)).eq.0 .and. DIMAG(cpi(2)).eq.0 .and.
- + DIMAG(cpi(3)).eq.0 .and. DIMAG(cpi(4)).eq.0 .or.
- + nschem.le.1 ) then
- if ( initlo.eq.0 .and. nschem.le.1 ) then
- initlo = 1
- print *,'ffcd0b: disregarding all complex masses'
- endif
- if ( onshel .and. ndiv.gt.0 ) then
- cs = 0
- cfac = 1
- return
- endif
- do 5 i=1,13
- xpi(i) = DBLE(cpi(i))
- do 4 j=1,10
- dpipj(j,i) = DBLE(cpipj(j,i))
- 4 continue
- 5 continue
- sprec = precx
- precx = precc
- call ffxd0b(cs,cfac,xpi,dpipj,ndiv,ier)
- if ( ldot ) call ffcod4(cpi,cpipj)
- precx = sprec
- return
- endif
-*
-* #] the real case:
-* #[ handle poles-only approach:
- if ( nschem.le.6 ) then
- if ( initlo .eq. 0 ) then
- initlo = 1
- if ( nschem.eq.2 ) then
- print *,'ffcd0b: disregarding complex masses ',
- + 'except in linearly divergent terms'
- elseif ( nschem.eq.3 ) then
- print *,'ffcd0b: undefined nschem=3'
- elseif ( nschem.eq.4 ) then
- print *,'ffcd0b: using the scheme in which ',
- + 'complex masses are used everywhere when ',
- + 'there is a divergent log'
- elseif ( nschem.eq.5 ) then
- print *,'ffcd0b: using the scheme in which ',
- + 'complex masses are used everywhere when ',
- + 'there is a divergent or almost divergent log'
- elseif ( nschem.eq.6 ) then
- print *,'ffcd0b: using the scheme in which ',
- + 'complex masses are used everywhere when ',
- + 'there is a singular log'
- elseif ( nschem.eq.7 ) then
- print *,'ffcd0b: using complex masses'
- endif
- if ( nschem.ge.3 ) then
- print *,'ffcd0b: switching to complex when on',
- + 'shell or |p^2-Re(m^2)| < ',nwidth,'*|Im(m^2)|'
- endif
- endif
-*
-* ffcdir computes all linearly onshell singular cases,
-* returns 0 if ndiv too large
-* and returns the other IR divergences in iir as a bonus
-*
- call ffcdir(cs,cfac,ldone,iir,cpi,cpipj,4,ndiv,ier)
- if ( ldone ) return
-*
-* use a subtraction method, or just the real case.
-* for both we need the real vars.
-*
- sprec = precx
- precx = precc
- do 16 i=1,13
- xpi(i) = DBLE(cpi(i))
- do 15 j=1,10
- dpipj(j,i) = DBLE(cpipj(j,i))
- 15 continue
- 16 continue
- if ( nschem.le.3 .or. iir(1,1).eq.0 .and. nschem.eq.4 ) then
- else
-*
-* finally, search for threshold terms
-*
- do 20 i=1,3
- do 19 j=i+1,4
- call ffthre(ithres(j,i),cpi,cpipj,10,i,j,
- + inx(i,j))
- ithres(i,j) = ithres(j,i)
- 19 continue
- 20 continue
- endif
- call ffcd0c(cs,cfac,cpi,cpipj,xpi,dpipj,iir,ithres,ier)
- precx = sprec
-*
-* #] handle poles-only approach:
-* #[ complex case:
- else
- print *,'ffcd0b: complex D0 not implemented'
- stop
- endif
-* #] complex case:
-*###] ffcd0b:
- end
-*###[ ffcd0c:
- subroutine ffcd0c(cs,cfac,cpi,cpipj,xpi,dpipj,iir,ithres,ier)
-***#[*comment:***********************************************************
-* *
-* computes the complex D0 by adding and subtracting the complex *
-* C0 (for ir divergences in iir) and B0 (for threshold effects in *
-* ithres). *
-* *
-***#]*comment:***********************************************************
-* #[ declarations:
- implicit none
-*
-* arguments
-*
- integer iir(2,4),ithres(4,4),ier
- DOUBLE PRECISION xpi(13),dpipj(10,13)
- DOUBLE COMPLEX cs,cfac,cpi(13),cpipj(10,13)
-*
-* local variables
-*
- integer ir,i,i1,j,j1,ier1,ier0,nscsav,ij,notij(4,4),
- + notijk(4,4,4),k,l
- logical ldotsa
- DOUBLE PRECISION xpi3(6),dpipj3(6,6),a(2),p1,p2,xmax,del2
- DOUBLE COMPLEX csr,cc0r,cc0c,cb0r,cb0c,cpi3(6),cpipj3(6,6)
- save notij,notijk
-*
-* common blocks
-*
- include 'ff.h'
-*
-* data
-*
- data notij/0,3,2,2, 3,0,1,1, 2,1,0,1, 2,1,1,0/
- data notijk/
- + 0,0,0,0,0,0,4,3,0,4,0,2,0,3,2,0,0,0,4,3,0,0,0,0,4,0,0,1,3,0,1,0,
- + 0,4,0,2,4,0,0,1,0,0,0,0,2,1,0,0,0,3,2,0,3,0,1,0,2,1,0,0,0,0,0,0/
-*
-* #] declarations:
-* #[ D0:
-*
- ier1 = ier
- ldotsa = ldot
- ldot = .TRUE.
- call ffxd0b(csr,cfac,xpi,dpipj,0,ier1)
- cs = csr
-*
-* #] D0:
-* #[ bookkeeping:
- if ( nschem.eq.5 .or. nschem.eq.6 ) then
-*
-* first weed out the thresholds already included in the IR terms
-*
- do 15 i=1,2
- if ( iir(i,1).eq.0 ) goto 16
- ithres(iir(i,1),iir(i,2)) = 0
- ithres(iir(i,2),iir(i,1)) = 0
- ithres(iir(i,1),iir(i,3)) = 0
- ithres(iir(i,3),iir(i,1)) = 0
- 15 continue
- 16 continue
-*
-* next - we need a complete complex C0 for a (m,m,0) type
-* vertex; the B0 does not contain the 2i\pi^2 jump
-*
- ir = 1
- if ( iir(1,1) .ne. 0 ) ir = 2
- if ( iir(2,1) .ne. 0 ) goto 19
- do 18 i=1,3
- do 17 j=i+1,4
- if ( ithres(i,j).eq.2 ) then
- if ( xpi(i).lt.xpi(j) ) then
- iir(ir,1) = i
- iir(ir,2) = j
- else
- iir(ir,1) = j
- iir(ir,2) = i
- endif
- k = notij(i,j)
- l = notijk(i,j,k)
- if ( abs(fpij4(iir(ir,1),k)) .lt.
- + abs(fpij4(iir(ir,1),l)) ) then
- iir(ir,3) = k
- iir(ir,4) = l
- else
- iir(ir,3) = l
- iir(ir,4) = k
- endif
-* throw out the vertices connected with this C0
- ithres(i,j) = 0
- ithres(j,i) = 0
- ithres(iir(ir,1),iir(ir,3)) = 0
- ithres(iir(ir,3),iir(ir,1)) = 0
- ir = ir + 1
- endif
- 17 continue
- 18 continue
- 19 continue
- endif
-*
-* #] bookkeeping:
-* #[ IR:
-*
-* get the IR parts correct
-*
- if ( nschem.le.3 ) goto 31
- do 30 ir=1,2
- if ( iir(ir,1).eq.0 ) goto 31
- do 25 i=1,3
- i1 = mod(i,3) + 1
- xpi3(i) = xpi(iir(ir,i))
- cpi3(i) = cpi(iir(ir,i))
- xpi3(i+3) = xpi(inx(iir(ir,i),iir(ir,i1)))
- cpi3(i+3) = cpi(inx(iir(ir,i),iir(ir,i1)))
- do 24 j=1,3
- j1 = mod(j,3) + 1
- dpipj3(j,i) = dpipj(iir(ir,j),iir(ir,i))
- cpipj3(j,i) = cpipj(iir(ir,j),iir(ir,i))
- dpipj3(j,i+3) = dpipj(iir(ir,j),
- + inx(iir(ir,i),iir(ir,i1)))
- dpipj3(i+3,j) = -dpipj3(j,i+3)
- cpipj3(j,i+3) = cpipj(iir(ir,j),
- + inx(iir(ir,i),iir(ir,i1)))
- cpipj3(i+3,j) = -cpipj3(j,i+3)
- dpipj3(j+3,i+3) = dpipj(
- + inx(iir(ir,j),iir(ir,j1)),
- + inx(iir(ir,i),iir(ir,i1)))
- cpipj3(j+3,i+3) = cpipj(
- + inx(iir(ir,j),iir(ir,j1)),
- + inx(iir(ir,i),iir(ir,i1)))
- 24 continue
- 25 continue
- ier0 = ier
- ldot = .TRUE.
- call ffxc0a(cc0r,xpi3,dpipj3,ier0)
- ier1 = max(ier1,ier0)
- del2 = fdel2
- nscsav = nschem
- nschem = 7
- ldot = .FALSE.
- call ffcc0a(cc0c,cpi3,cpipj3,ier0)
- nschem = nscsav
- ier1 = max(ier1,ier0)
- p1 = 1/dpipj(inx(iir(ir,4),iir(ir,1)),iir(ir,4))
-* this can not cause problems because p1 flips sign when the
-* function is linearly divergent, and that region should
-* never come here
- p1 = sign(sqrt(-del2/fdel4s)/2,p1)
- cc0r=cc0r/cfac*DBLE(p1)
- cc0c=cc0c/cfac*DBLE(p1)
- cs = cs - cc0r + cc0c
- 30 continue
- 31 continue
-*
-* #] IR:
-* #[ threshold:
-*
-* and the threshold terms
-*
- if ( nschem.le.4 ) goto 41
-*
-* next add and subtract the complex/real B0
-*
- do 40 i=1,3
- do 39 j=i+1,4
- if ( ithres(j,i).eq.0 ) goto 39
- ij = inx(i,j)
- if ( xpi(ij) .lt. 0 ) then
- goto 39
- endif
-*
-* else just add and subtract the B0
-*
- ier0 = ier
- call ffxb0p(cb0r,xpi(ij),xpi(i),xpi(j),dpipj(i,ij),
- + dpipj(j,ij),dpipj(i,j),ier0)
- ier1 = max(ier1,ier0)
-*
- ier0 = ier
- call ffcb0p(cb0c,cpi(ij),cpi(i),cpi(j),cpipj(i,ij),
- + cpipj(j,ij),cpipj(i,j),ier0)
- ier1 = max(ier1,ier0)
-*
-* get the coefficients which are given by Q=a*p(1)
-*
- a(1) = xpi(i)*(xpi(j)*dpipj(j,i) - xpi(ij)*(xpi(i)+
- + xpi(j)))/(xpi(ij)*(xpi(i)+xpi(j))**2)
-* a(2) = 1+a(1):
- a(2) = xpi(j)*(xpi(i)*dpipj(j,i) + xpi(ij)*(xpi(i)+
- + xpi(j)))/(xpi(ij)*(xpi(i)+xpi(j))**2)
-*
- k = notij(i,j)
- if ( abs(a(1)) .lt. abs(a(2)) ) then
- p1 = dpipj(inx(i,k),k) + a(1)**2*xpi(ij) +
- + 2*a(1)*fpij4(ij,inx(i,k)) *
- + isgn(i,j)*isgn(i,k)
- xmax = max(abs(dpipj(inx(i,k),k)),a(1)**2*xpi(ij))
- else
- p1 = dpipj(inx(j,k),k) + a(2)**2*xpi(ij) +
- + 2*a(2)*fpij4(ij,inx(j,k)) *
- + isgn(i,j)*isgn(j,k)
- xmax = max(abs(dpipj(inx(j,k),k)),a(2)**2*xpi(ij))
- endif
- if ( abs(p1) .lt. xloss*xmax )
- + call ffwarn(212,ier1,p1,xmax)
-*
- l = notijk(i,j,k)
- if ( abs(a(1)) .lt. abs(a(2)) ) then
- p2 = dpipj(inx(i,l),l) + a(1)**2*xpi(ij) +
- + 2*a(1)*fpij4(ij,inx(i,l)) *
- + isgn(i,j)*isgn(i,l)
- xmax = max(abs(dpipj(inx(i,l),l)),a(1)**2*xpi(ij))
- else
- p2 = dpipj(inx(j,l),l) + a(2)**2*xpi(ij) +
- + 2*a(2)*fpij4(ij,inx(j,l)) *
- + isgn(i,j)*isgn(j,l)
- xmax = max(abs(dpipj(inx(j,l),l)),a(2)**2*xpi(ij))
- endif
- if ( abs(p2) .lt. xloss*xmax )
- + call ffwarn(213,ier1,p2,xmax)
-*
- cb0r = cb0r/cfac/(p1*p2)
- cb0c = cb0c/cfac/(p1*p2)
-* minus because we computed B', not B
- cs = cs + cb0r - cb0c
- 39 continue
- 40 continue
- 41 continue
-* #] threshold:
-* #[ dotproducts:
-*
-* and the dot products if requested
-*
- ldot = ldotsa
-ccc if ( ldot ) then
-ccc call ffcod4(cpi,cpipj)
-ccc endif
-* #] dotproducts:
-* #[ finito:
-*
-* clean up
-*
- ier = ier1
-* #] finito:
-*###] ffcd0c:
- end
-*###[ ffcod4:
- subroutine ffcod4(cpi,cpipj)
-***#[*comment:***********************************************************
-* *
-* Convert real dotproducts into complex ones, adding the *
-* imaginary parts where appropriate. *
-* For the time being just recompute them... *
-* *
-* Input: cpi(13) complex m^2, p^2 *
-* cpipj(10,13) complex diffs *
-* *
-* Output: /ffcots/cfpij4(10,10) complex p.p complex *
-* *
-***#]*comment:***********************************************************
-* #[ declarations:
- implicit none
-*
-* arguments
-*
- DOUBLE COMPLEX cpi(13),cpipj(10,13)
-*
-* local variables
-*
- integer i,j,ier0,ii(6)
- DOUBLE PRECISION piDpj(10,10),sprec
-*
-* common blocks
-*
- include 'ff.h'
-*
-* #] declarations:
-* #[ compute dotproducts and determinants:
-*
- print *, "ffcod4: cannot do ffcot4 yet"
- ier0 = 100
- return
-
- ier0 = 0
-ccc call ffcot4(cfpij4,cpi,cpipj,10,ier0)
- call ffcel4(cfdl4s,cpi,cfpij4,10,ier0)
- if ( abs(idot).lt.2 ) then
- if ( onshel ) then
-* we have to recompute the overall \Delta_3
- do 10 i=1,6
- ii(i) = i+4
- 10 continue
- do 30 i=1,10
- do 20 j=1,10
- piDpj(j,i) = DBLE(cfpij4(j,i))
- 20 continue
- 30 continue
-* this prec-juggling should not be necessary, but it is...
- sprec = precx
- precx = precc
- call ffdl3p(fodel3,piDpj,10,ii,ii)
- precx = sprec
- else
- fodel3 = fdel3
- endif
- endif
-*
-* #] compute dotproducts and determinants:
-*###] ffcod4:
- end
-*###[ ffcif4:
- subroutine ffcif4(cpipj,luvw,cpi,ier)
-***#[*comment:***********************************************************
-* *
-* Compute the elements 11-13 in xpi and the differences cpipj *
-* Note that the digits lost in cpipj are not counted towards *
-* the total. *
-* *
-* Input: cpi(1:10) complex masses, momenta^2 *
-* *
-* Output: cpi(11:13) complex u and similar vars v,w *
-* luvw(3) logical TRUE if xpi(10+i) has *
-* been computed here *
-* cpipj(10,13) complex xpi(i) - xpi(j) *
-* *
-***#]*comment:***********************************************************
-* #[ declarations:
- implicit none
-*
-* arguments
-*
- integer ier
- logical luvw(3)
- DOUBLE COMPLEX cpi(13),cpipj(10,13)
-*
-* local variables
-*
- integer i,j
-*
-* common blocks
-*
- include 'ff.h'
-* #] declarations:
-* #[ get differences:
-* simulate the differences in the masses etc..
- if ( cpi(11) .eq. 0 ) then
- cpi(11) = cpi(5)+cpi(6)+cpi(7)+cpi(8)-cpi(9)-cpi(10)
- luvw(1) = .TRUE.
- else
- luvw(1) = .FALSE.
- endif
- if ( cpi(12) .eq. 0 ) then
- cpi(12) = -cpi(5)+cpi(6)-cpi(7)+cpi(8)+cpi(9)+cpi(10)
- luvw(2) = .TRUE.
- else
- luvw(2) = .FALSE.
- endif
- if ( cpi(13) .eq. 0 ) then
- cpi(13) = cpi(5)-cpi(6)+cpi(7)-cpi(8)+cpi(9)+cpi(10)
- luvw(3) = .TRUE.
- else
- luvw(3) = .FALSE.
- endif
- do 100 i=1,13
- do 90 j=1,10
- cpipj(j,i) = cpi(j) - cpi(i)
- 90 continue
- 100 continue
-* #] get differences:
-*###] ffcif4:
- end
diff --git a/Looptools/D/ffcdbd.F b/Looptools/D/ffcdbd.F
deleted file mode 100644
--- a/Looptools/D/ffcdbd.F
+++ /dev/null
@@ -1,419 +0,0 @@
-*--#[ log:
-* $Id: ffcdbd.f,v 1.4 1997/03/27 21:28:07 gj Exp $
-* $Log: ffcdbd.f,v $
-* Revision 1.4 1997/03/27 21:28:07 gj
-* Added explicit check for mass-divergent boxes
-*
-c Revision 1.3 1995/12/12 12:48:13 gj
-c When ndiv=-1 the D0 returns how divergent it was; E0 and F0 use this info to
-c set the non-divergent ones to zero on output when ndiv>0. Same for E0 in F0.
-c
-c Revision 1.2 1995/11/10 18:53:55 gj
-c Added nasty D0 call
-c
-*--#] log:
-*###[ ffcdir:
- subroutine ffcdir(cs,cfac,ldone,iir,cpi,cdpipj,ipoin,ndiv,ier)
-***#[*comment:***********************************************************
-* *
-* Check if this 4point function is IRdivergent and if so, get it *
-* using ffcdbd and set ldone to .TRUE., otherwise .FALSE. *
-* the place of the IR divergences is returned in iir: *
-* when iir(i,0) != 0 then iir(i,1) is the photon, iir(i,2-3) the *
-* IR particles and iir(i,4) the other one *
-* *
-***#]*comment:***********************************************************
-* #[ declarations:
- implicit none
-*
-* arguments
-*
- integer iir(2,4),ipoin,ier,ndiv
- logical ldone
- DOUBLE COMPLEX cs,cfac,cpi(13),cdpipj(10,13)
-*
-* local variables
-*
- integer i,j,k,l,m,ier0,ii(6),notijk(4,4,4),ir
- DOUBLE COMPLEX dl3p
- save notijk
-*
-* common blocks
-*
- include 'ff.h'
-*
-* data
-*
- data notijk/
- + 0,0,0,0,0,0,4,3,0,4,0,2,0,3,2,0,0,0,4,3,0,0,0,0,4,0,0,1,3,0,1,0,
- + 0,4,0,2,4,0,0,1,0,0,0,0,2,1,0,0,0,3,2,0,3,0,1,0,2,1,0,0,0,0,0,0/
-*
-* #] declarations:
-* #[ work:
-*
- ir = 1
- iir(ir,1) = 0
-*
- do 25 i=1,4
- do 24 j=1,4
- if ( j .eq. i ) goto 24
- if ( abs(DBLE(cdpipj(j,inx(j,i)))) .gt. -nwidth*
- + DIMAG(cpi(j)) ) goto 24
- do 23 k=j+1,4
- if ( k .eq. i ) goto 23
- if ( abs(DBLE(cdpipj(k,inx(k,i)))) .gt. -nwidth*
- + DIMAG(cpi(k)) ) goto 23
- l = notijk(k,j,i)
- if ( abs(DBLE(cpi(i))) .gt. -xloss*(DIMAG(cpi(k)) +
- + DIMAG(cpi(j))+DIMAG(cpi(l))) ) goto 25
-*
- if ( abs(DBLE(cdpipj(l,inx(l,i)))) .le. -nwidth*
- + DIMAG(cpi(l)) ) then
- if ( ndiv.eq.-1 ) ndiv = 1
-*
-* if possible use Wim & Ansgar's formulae
-*
- if ( cpi(i).eq.0 ) then
- if ( cdpipj(inx(i,j),j).eq.0 .and.
- + cdpipj(inx(i,k),k).eq.0 ) then
- call ffcdbd(cs,cfac,cpi,cdpipj,i,j,k,l,
- + ier)
- goto 99
- endif
- if ( cdpipj(inx(i,j),j).eq.0 .and.
- + cdpipj(inx(i,l),l).eq.0 ) then
- call ffcdbd(cs,cfac,cpi,cdpipj,i,j,l,k,
- + ier)
- goto 99
- endif
- if ( cdpipj(inx(i,k),k).eq.0 .and.
- + cdpipj(inx(i,l),l).eq.0 ) then
- call ffcdbd(cs,cfac,cpi,cdpipj,i,k,l,j,
- + ier)
- goto 99
- endif
- else
- print *,'ffcdir: error: cannot handle ',
- + 'finite photon mass yet'
- ier = ier + 100
- cs = 0
- cfac = 1
- goto 99
- endif
-*
-* it is thus nasty...
-*
- print *, "ffcdir: cannot handle this case"
- ier = ier + 100
-ccc call ffcdna(cs,cfac,cpi,cdpipj,ier)
- goto 99
- elseif ( onshel .and. ndiv.ge.1 ) then
- cs = 0
- cfac = 1
- goto 99
- endif
- if ( ndiv.eq.-1 ) ndiv = 0
-*
-* it may be doable by W&A algorithm
-*
- if ( cdpipj(inx(i,j),j).eq.0 .and.
- + cdpipj(inx(i,k),k).eq.0 ) then
- call ffcdbd(cs,cfac,cpi,cdpipj,i,j,k,l,ier)
- goto 99
- endif
-*
-* it is just a normal logarithmically divergent D0
-*
- if ( ir.gt.2 ) then
- call fferr(70,ier)
- ir = ir-1
- endif
- if ( DIMAG(cpi(j)).ne.0 .or. DIMAG(cpi(k)).ne.0 )
- + then
- iir(ir,1) = i
- iir(ir,2) = j
- iir(ir,3) = k
- iir(ir,4) = l
- ir = ir + 1
- if ( ir.le.2 ) iir(ir,1) = 0
- endif
- 23 continue
- 24 continue
- 25 continue
- ldone = .FALSE.
- if ( ndiv.eq.-1 ) ndiv = 0
- return
- 99 continue
- if ( ldot .and. ipoin .eq. 4 ) then
- ier0 = 100
- print *, "ffcdbd: cannot do ffcot4 yet"
- return
- ier0 = 0
-ccc call ffcot4(cfpij4,cpi,cdpipj,10,ier0)
- do 122 l=1,10
- do 121 m=1,10
- fpij4(m,l) = DBLE(cfpij4(m,l))
- 121 continue
- 122 continue
- ii(1)= 5
- ii(2)= 6
- ii(3)= 7
- ii(4)= 8
- ii(5)= 9
- ii(6)= 10
- call ffcl3p(dl3p,cfpij4,10,ii,ii,ier0)
- fodel3 = DBLE(dl3p)
- fdel3 = fodel3
- endif
-*
-* and finito
-*
- ldone = .TRUE.
- return
-* #] work:
-*###] ffcdir:
- end
-*###[ ffcdbd:
- subroutine ffcdbd(cs,cfac,cpi,cpipj,ilam,i1,i4,ic,ier)
-***#[*comment:***********************************************************
-* *
-* The IR divergent fourpoint function with one complex mass *
-* according to Beenakker & Denner, Nucl.Phys.B338(1990)349. *
-* *
-* Input: cpi(13) complex momenta^2 *
-* cpipj(10,13) complex cpi(i)-cpi(j) *
-* ilam integer position of m=0 *
-* i1,i4 integer position of other 2 IR masses *
-* ic integer position of complex mass *
-* /ffregul/ lambda real cutoff to use instead of lam^2 *
-* *
-* Output: cs,cfac complex D0 = cs*cfac *
-* ier integer number of digits lost *
-* *
-* *
-***#]*comment:***********************************************************
-* #[ declarations:
- implicit none
-*
-* arguments
-*
- integer ilam,i1,i4,ic,ier
- DOUBLE COMPLEX cs,cfac,cpi(13),cpipj(10,13)
-*
-* local variables
-*
- integer ier0,ier1,ipi12,ip,init,is,i2,i3,i,j,iepss
- DOUBLE PRECISION absc,xmax,xpi(13),dpipj(10,13),xxs(3),xp,xma,
- + xmb,d,dfflo1
- DOUBLE COMPLEX c,xxt(3),xx2(3),xx3(3),xm0,xm1,xm4,xlam,
- + csi(21),z,zlg,zfflog,zxfflg
- save init
-*for Absoft
-* DOUBLE COMPLEX csqrt
-* external csqrt
-*
-* common blocks
-*
- include 'ff.h'
-*
-* statement function
-*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
-*
-* data
-*
- data init /0/
-*
-* #] declarations:
-* #[ check input:
-*
- if ( init .eq. 0 ) then
- init = 1
- print *,'ffcdbd: using IR cutoff ',lambda
- endif
- if ( cpi(i1).eq.0 .or. cpi(i4).eq.0 ) then
- call fferr(98,ier)
- return
- endif
-* #] check input:
-* #[ real case:
- if ( nschem.le.3 ) then
- do 20 i=1,13
- xpi(i) = DBLE(cpi(i))
- do 10 j=1,10
- dpipj(j,i) = DBLE(cpipj(j,i))
- 10 continue
- 20 continue
- lsmug = .TRUE.
- c2sisj(ilam,ic) = cpipj(ic,inx(ilam,ic))
- c2sisj(ic,ilam) = cpipj(ic,inx(ilam,ic))
- c2sisj(i1,ilam) = 0
- c2sisj(ilam,i1) = 0
- c2sisj(i4,ilam) = 0
- c2sisj(ilam,i4) = 0
- call ffxdbd(cs,cfac,xpi,dpipj,ilam,i1,i4,ic,ier)
- lsmug = .FALSE.
- return
- endif
-* #] real case:
-* #[ get dimensionless vars:
-*
- xm0 = sqrt(cpi(ic))
- xm1 = sqrt(cpi(i1))
- xm4 = sqrt(cpi(i4))
- xlam = sqrt(lambda)
-*
-* we follow the notation of Wim & Ansgar closely
-*
- xxt(1) = xm0*xlam/cpipj(ic,inx(ilam,ic))
- xxt(2) = 1-xxt(1)
- xxt(3) = 1+xxt(1)
- ier1 = 0
- ier0 = 0
-* this one is real!
- xp = DBLE(cpi(inx(i1,i4)))
- xma = DBLE(xm1)
- xmb = DBLE(xm4)
- call ffxkfn(xxs,iepss,xp,xma,xmb,ier0)
- ier1 = max(ier0,ier1)
- ier0 = 0
- call ffckfn(xx2,cpi(inx(i1,ic)),xm1,xm0,ier0)
- ier1 = max(ier0,ier1)
- ier0 = 0
- call ffckfn(xx3,cpi(inx(i4,ic)),xm4,xm0,ier0)
- ier1 = max(ier0,ier1)
- ier = ier + ier1
-*
-* #] get dimensionless vars:
-* #[ fill array:
-*
- ipi12 = 0
- ier1 = 0
- ier0 = 0
- zlg = zxfflg(xxs(1),iepss,0D0,ier)
- d = xxs(1)**2
- if ( abs(d) .lt. xloss ) then
- csi(1) = 2*zlg*DBLE(dfflo1(d,ier0))
- else
- csi(1) = 2*zlg*zxfflg(xxs(2)*xxs(3),-iepss,0D0,ier0)
- endif
- ier1 = max(ier0,ier1)
- ier0 = 0
- csi(2) = -2*zlg*log(xxt(1))
- ier1 = max(ier0,ier1)
-*
- ipi12 = ipi12 + 6
-*
- ier0 = 0
- call ffzxdl(csi(3),ip,zlg,xxs(1)**2,iepss,ier0)
- ipi12 = ipi12 + ip
- ier1 = max(ier0,ier1)
-*
- ier0 = 0
- z = zfflog(xx2(1),0,czero,ier0)
- csi(4) = z**2
- ier1 = max(ier0,ier1)
-*
- ier0 = 0
- z = zfflog(xx3(1),0,czero,ier0)
- csi(5) = z**2
- ier1 = max(ier0,ier1)
-*
- is = 6
- do 110 i2=-1,+1,2
- do 100 i3=-1,+1,2
-*
- ier0 = 0
- call ffzzdl(csi(is),ip,zlg,DBLE(xxs(1))*xx2(1)**i2*
- + xx3(1)**i3,ier0)
- csi(is) = -csi(is)
- ipi12 = ipi12 - ip
- is = is + 1
- ier1 = max(ier0,ier1)
-*
- ier0 = 0
- if ( abs(xxs(2)) .gt. xloss ) then
- csi(is) = -zlg*zxfflg(xxs(1),iepss,0D0,ier0)
- else
- csi(is) = -zlg*DBLE(dfflo1(xxs(2),ier0))
- endif
- is = is + 1
- ier1 = max(ier0,ier1)
-*
- ier0 = 0
- csi(is) = -zlg*zfflog(xx2(1)**i2,0,czero,ier0)
- is = is + 1
- ier1 = max(ier0,ier1)
-*
- ier0 = 0
- csi(is) = -zlg*zfflog(xx3(1)**i3,0,czero,ier0)
- is = is + 1
- ier1 = max(ier0,ier1)
-*
- 100 continue
- 110 continue
- ier = ier + ier1
-*
-* #] fill array:
-* #[ sum:
-*
- cs = 0
- xmax = 0
- is = is - 1
- do 200 i=1,is
- cs = cs + csi(i)
- xmax = max(xmax,absc(csi(i)))
- 200 continue
- cs = cs + ipi12*DBLE(pi12)
-*
-* #] sum:
-* #[ overall factors:
-*
- cfac = DBLE(xxs(1))/(xm1*xm4*cpipj(inx(ilam,ic),ic)*
- + DBLE(xxs(2)*xxs(3)))
-*
-* #] overall factors:
-*###] ffcdbd:
- end
-*###[ ffckfn:
- subroutine ffckfn(x,cpi,xm,xmp,ier)
-***#[*comment:***********************************************************
-* *
-* Calculate the K-function in this paper: *
-* *
-* 1-sqrt(1-4*m*mp/(z-(m-mp)^2)) *
-* K(p^2,m,mp) = ----------------------------- *
-* 1+sqrt(1-4*m*mp/(z-(m-mp)^2)) *
-* *
-* and fill x(1) = -K, x(2) = 1+K, x(3) = 1-K *
-* *
-***#]*comment:***********************************************************
-* #[ declarations:
- implicit none
-*
-* arguments
-*
- integer ier
- DOUBLE COMPLEX x(3),cpi,xm,xmp
-*
-* local variables
-*
- DOUBLE COMPLEX wortel,cc1,cc2,cc3
-*
-* common blocks
-*
- include 'ff.h'
-* #] declarations:
-* #[ work:
-*
- cc1 = cpi - (xm-xmp)**2
- cc2 = 1 - 4*xm*xmp/cc1
- wortel = sqrt(cc2)
- cc3 = 1/(1+wortel)
- x(1) = -4*xm*xmp*cc3**2/cc1
- x(2) = 2*cc3
- x(3) = 2*wortel*cc3
-*
-* #] work:
-*###] ffckfn:
- end
diff --git a/Looptools/D/ffcel4.F b/Looptools/D/ffcel4.F
deleted file mode 100644
--- a/Looptools/D/ffcel4.F
+++ /dev/null
@@ -1,293 +0,0 @@
-*###[ ffcel4:
- subroutine ffcel4(del4,xpi,piDpj,ns,ier)
-***#[*comment:***********************************************************
-* *
-* Calculate del4(piDpj) = det(si.sj) with *
-* the momenta as follows: *
-* p(1-4) = s(i) *
-* p(4-10) = p(i) *
-* *
-* Input: xpi(ns) (real) m^2(i),i=1,3; p^2(i-3),i=4,10 *
-* piDpj(ns,ns) (real) *
-* ns (integer) *
-* ier (integer) *
-* *
-* Output: del4 (real) det(si.sj) *
-* *
-***#]*comment:***********************************************************
-* #[ declarations:
- implicit none
-*
-* arguments:
-*
- integer ns,ier
- DOUBLE COMPLEX del4,xpi(10),piDpj(10,10)
-*
-* local variables:
-*
- integer mem,nperm
- parameter(mem=10,nperm=125)
- integer i,jj(8),iperm(4,nperm),imem,jmem,memarr(mem,4),memind,
- + inow,jnow,icount
- DOUBLE PRECISION xmax,xmaxp,absc
- DOUBLE COMPLEX s(24),del4p,c
- save iperm,memind,memarr,inow,jnow
-*
-* common blocks:
-*
- include 'ff.h'
-*
-* statement functions:
-*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
-* #] declarations:
-* #[ data:
- data memind /0/
- data memarr /mem*0,mem*0,mem*1,mem*1/
- data inow /1/
- data jnow /1/
-*
-* these are all permutations that give a non-zero result with the
-* correct sign. This list was generated with getperm4.
-* (note: this used to be well-ordened, but then it had more than
-* 19 continuation lines)
-*
- data iperm/
- + 1,2,3,4,1,2,3,7,1,2,8,3,1,2,3,10,1,2,6,4,1,2,4,7,1,2,4,9,1,2,6,7
- + ,1,2,8,6,1,2,6,10,1,2,7,8,1,2,7,9,1,2,10,7,1,2,9,8,1,2,10,9,1,3,
- + 4,5,1,3,6,4,1,3,10,4,1,3,7,5,1,3,5,8,1,3,10,5,1,3,6,7,1,3,8,6,1,
- + 3,6,10,1,3,10,7,1,3,8,10,1,4,5,6,1,4,7,5,1,4,9,5,1,4,6,7,1,4,6,9
- + ,1,4,6,10,1,4,10,7,1,4,10,9,1,5,6,7,1,5,8,6,1,5,6,10,1,5,7,8,1,5
- + ,7,9,1,5,10,7,1,5,9,8,1,5,10,9,1,6,8,7,1,6,9,7,1,6,8,9,1,6,8,10,
- + 1,6,9,10,1,7,10,8,1,7,10,9,1,8,9,10,2,3,4,5,2,3,8,4,2,3,9,4,2,3,
- + 7,5,2,3,5,8,2,3,10,5,2,3,8,7,2,3,9,7,2,3,8,9,2,3,8,10,2,3,9,10,2
- + ,4,5,6,2,4,7,5,2,4,9,5,2,4,6,8,2,4,6,9,2,4,8,7,2,4,9,7,2,4,8,9,2
- + ,5,6,7,2,5,8,6,2,5,6,10,2,5,7,8,2,5,7,9,2,5,10,7,2,5,9,8,2,5,10,
- + 9,2,6,8,7,2,6,9,7,2,6,8,9,2,6,8,10,2,6,9,10,2,7,10,8,2,7,10,9,2,
- + 8,9,10,3,4,5,6,3,4,8,5,3,4,9,5,3,4,5,10,3,4,6,8,3,4,6,9,3,4,10,8
- + ,3,4,10,9,3,5,6,7,3,5,8,6,3,5,6,10,3,5,7,8,3,5,7,9,3,5,10,7,3,5,
- + 9,8,3,5,10,9,3,6,8,7,3,6,9,7,3,6,8,9,3,6,8,10,3,6,9,10,3,7,10,8,
- + 3,7,10,9,3,8,9,10,4,5,6,7,4,5,8,6,4,5,6,10,4,5,7,8,4,5,7,9,4,5,1
- + 0,7,4,5,9,8,4,5,10,9,4,6,8,7,4,6,9,7,4,6,8,9,4,6,8,10,4,6,9,10,4
- + ,7,10,8,4,7,10,9,4,8,9,10/
-* #] data:
-* #[ get starting point from memory:
-*
-* see if we know were to start, if not: go on as last time
-*
- do 5 i=1,mem
- if ( id .eq. memarr(i,1) .and. idsub .eq. memarr(i,2) ) then
- inow = memarr(i,3)
- jnow = memarr(i,4)
- goto 6
- endif
- 5 continue
- 6 continue
-* #] get starting point from memory:
-* #[ calculations:
- imem = inow
- jmem = jnow
- del4 = 0
- xmax = 0
- icount = 0
-*
- 10 continue
-
- jj(1) = iperm(1,inow)
- jj(3) = iperm(2,inow)
- jj(5) = iperm(3,inow)
- jj(7) = iperm(4,inow)
-
- jj(2) = iperm(1,jnow)
- jj(4) = iperm(2,jnow)
- jj(6) = iperm(3,jnow)
- jj(8) = iperm(4,jnow)
-
- s( 1) = +piDpj(jj(1),jj(2))*piDpj(jj(3),jj(4))*
- + piDpj(jj(5),jj(6))*piDpj(jj(7),jj(8))
- s( 2) = +piDpj(jj(1),jj(4))*piDpj(jj(3),jj(6))*
- + piDpj(jj(5),jj(2))*piDpj(jj(7),jj(8))
- s( 3) = +piDpj(jj(1),jj(6))*piDpj(jj(3),jj(2))*
- + piDpj(jj(5),jj(4))*piDpj(jj(7),jj(8))
- s( 4) = -piDpj(jj(1),jj(2))*piDpj(jj(3),jj(6))*
- + piDpj(jj(5),jj(4))*piDpj(jj(7),jj(8))
- s( 5) = -piDpj(jj(1),jj(6))*piDpj(jj(3),jj(4))*
- + piDpj(jj(5),jj(2))*piDpj(jj(7),jj(8))
- s( 6) = -piDpj(jj(1),jj(4))*piDpj(jj(3),jj(2))*
- + piDpj(jj(5),jj(6))*piDpj(jj(7),jj(8))
-
- s( 7) = -piDpj(jj(1),jj(2))*piDpj(jj(3),jj(4))*
- + piDpj(jj(7),jj(6))*piDpj(jj(5),jj(8))
- s( 8) = -piDpj(jj(1),jj(4))*piDpj(jj(3),jj(6))*
- + piDpj(jj(7),jj(2))*piDpj(jj(5),jj(8))
- s( 9) = -piDpj(jj(1),jj(6))*piDpj(jj(3),jj(2))*
- + piDpj(jj(7),jj(4))*piDpj(jj(5),jj(8))
- s(10) = +piDpj(jj(1),jj(2))*piDpj(jj(3),jj(6))*
- + piDpj(jj(7),jj(4))*piDpj(jj(5),jj(8))
- s(11) = +piDpj(jj(1),jj(6))*piDpj(jj(3),jj(4))*
- + piDpj(jj(7),jj(2))*piDpj(jj(5),jj(8))
- s(12) = +piDpj(jj(1),jj(4))*piDpj(jj(3),jj(2))*
- + piDpj(jj(7),jj(6))*piDpj(jj(5),jj(8))
-
- s(13) = -piDpj(jj(1),jj(2))*piDpj(jj(7),jj(4))*
- + piDpj(jj(5),jj(6))*piDpj(jj(3),jj(8))
- s(14) = -piDpj(jj(1),jj(4))*piDpj(jj(7),jj(6))*
- + piDpj(jj(5),jj(2))*piDpj(jj(3),jj(8))
- s(15) = -piDpj(jj(1),jj(6))*piDpj(jj(7),jj(2))*
- + piDpj(jj(5),jj(4))*piDpj(jj(3),jj(8))
- s(16) = +piDpj(jj(1),jj(2))*piDpj(jj(7),jj(6))*
- + piDpj(jj(5),jj(4))*piDpj(jj(3),jj(8))
- s(17) = +piDpj(jj(1),jj(6))*piDpj(jj(7),jj(4))*
- + piDpj(jj(5),jj(2))*piDpj(jj(3),jj(8))
- s(18) = +piDpj(jj(1),jj(4))*piDpj(jj(7),jj(2))*
- + piDpj(jj(5),jj(6))*piDpj(jj(3),jj(8))
-
- s(19) = -piDpj(jj(7),jj(2))*piDpj(jj(3),jj(4))*
- + piDpj(jj(5),jj(6))*piDpj(jj(1),jj(8))
- s(20) = -piDpj(jj(7),jj(4))*piDpj(jj(3),jj(6))*
- + piDpj(jj(5),jj(2))*piDpj(jj(1),jj(8))
- s(21) = -piDpj(jj(7),jj(6))*piDpj(jj(3),jj(2))*
- + piDpj(jj(5),jj(4))*piDpj(jj(1),jj(8))
- s(22) = +piDpj(jj(7),jj(2))*piDpj(jj(3),jj(6))*
- + piDpj(jj(5),jj(4))*piDpj(jj(1),jj(8))
- s(23) = +piDpj(jj(7),jj(6))*piDpj(jj(3),jj(4))*
- + piDpj(jj(5),jj(2))*piDpj(jj(1),jj(8))
- s(24) = +piDpj(jj(7),jj(4))*piDpj(jj(3),jj(2))*
- + piDpj(jj(5),jj(6))*piDpj(jj(1),jj(8))
-
- del4p = 0
- xmaxp = 0
- do 20 i=1,24
- del4p = del4p + s(i)
- xmaxp = max(xmaxp,absc(s(i)))
- 20 continue
- if ( absc(del4p) .lt. xloss*xmaxp ) then
- if ( inow .eq. imem .or. xmaxp .lt. xmax ) then
- del4 = del4p
- xmax = xmaxp
- endif
-* as the list is ordered we may have more luck stepping
-* through with large steps
- inow = inow + 43
- jnow = jnow + 49
- if ( inow .gt. nperm ) inow = inow - nperm
- if ( jnow .gt. nperm ) jnow = jnow - nperm
- icount = icount + 1
- if ( icount.gt.15 .or. inow.eq.imem .or. jnow.eq.jmem
- + ) then
- goto 800
- endif
- goto 10
- endif
- del4 = del4p
- xmax = xmaxp
-* #] calculations:
-* #[ into memory:
- memind = memind + 1
- if ( memind .gt. mem ) memind = 1
- memarr(memind,1) = id
- memarr(memind,2) = idsub
- memarr(memind,3) = inow
- memarr(memind,4) = jnow
- 800 continue
-* #] into memory:
-*###] ffcel4:
- end
-*###[ ffcl3p:
- subroutine ffcl3p(dl3p,piDpj,ns,ii,jj,ier)
-***#[*comment:***********************************************************
-* calculate in a numerically stable way *
-* *
-* p1 p2 p3 *
-* delta *
-* p1' p2' p3' *
-* *
-* with pn = xpi(ii(n)), p4 = -p1-p2-p3, p5 = -p1-p2, p6 = p2+p3 *
-* with pn'= xpi(jj(n)), p4'= etc. (when ns=15 p5=p1+p2) *
-* *
-* Input: piDpj complex(ns,ns) dotpruducts *
-* ns integer either 10 or 15 *
-* ii,jj integer(6) location of pi in piDpj *
-* ier integer number of digits lost so far *
-* Output: dl3p complex see above *
-* ier integer number of digits lost so far *
-* *
-***#]*comment:***********************************************************
-* #[ declarations:
- implicit none
-*
-* arguments:
-*
- integer ns,ii(6),jj(6),ier
- DOUBLE COMPLEX dl3p,piDpj(ns,ns)
-*
-* local variables
-*
- integer i,j,k,l,iperm(3,16),ii1,ii2,ii3,jj1,jj2,jj3,nl
- DOUBLE PRECISION xmax,smax,absc
- DOUBLE COMPLEX s(6),som,c
-*
-* common blocks
-*
- include 'ff.h'
-*
-* statement functions:
-*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
-*
-* data
-*
- data iperm /1,2,3, 2,4,3, 3,4,1, 4,2,1,
- + 1,2,6, 6,4,3, 3,1,6, 2,4,6,
- + 2,5,3, 5,4,1, 1,3,5, 2,4,5,
- + 1,6,5, 2,5,6, 3,6,5, 4,5,6/
-* #] declarations:
-* #[ calculations:
- if ( ii(1).eq.jj(1) .and. ii(2).eq.jj(2) .and. ii(3).eq.jj(3) )
- + then
-*
-* symmetric - fewer possibilities
-*
- nl = 1
- else
- nl = 16
- endif
-*
-* try all (1,16)*16 permutations
-*
- xmax = 0
- do 101 l=1,nl
- do 100 i=1,16
- ii1 = ii(iperm(1,i))
- ii2 = ii(iperm(2,i))
- ii3 = ii(iperm(3,i))
- j = i+l-1
- if ( j .gt. 16 ) j=j-16
- jj1 = jj(iperm(1,j))
- jj2 = jj(iperm(2,j))
- jj3 = jj(iperm(3,j))
- s(1) = +piDpj(ii1,jj1)*piDpj(ii2,jj2)*piDpj(ii3,jj3)
- s(2) = +piDpj(ii2,jj1)*piDpj(ii3,jj2)*piDpj(ii1,jj3)
- s(3) = +piDpj(ii3,jj1)*piDpj(ii1,jj2)*piDpj(ii2,jj3)
- s(4) = -piDpj(ii1,jj1)*piDpj(ii3,jj2)*piDpj(ii2,jj3)
- s(5) = -piDpj(ii3,jj1)*piDpj(ii2,jj2)*piDpj(ii1,jj3)
- s(6) = -piDpj(ii2,jj1)*piDpj(ii1,jj2)*piDpj(ii3,jj3)
- som = 0
- smax = 0
- do 80 k=1,6
- som = som + s(k)
- smax = max(smax,absc(som))
- 80 continue
- if ( ns .eq. 15 .and. (i.gt.8 .neqv. j.gt.8) )
- + som = -som
- if ( i .eq. 1 .or. smax .lt. xmax ) then
- dl3p = som
- xmax = smax
- endif
- if ( absc(dl3p) .ge. xloss*smax ) goto 110
- 100 continue
- 101 continue
- 110 continue
-* #] calculations:
-*###] ffcl3p:
- end
diff --git a/Looptools/D/ffd0c.F b/Looptools/D/ffd0c.F
--- a/Looptools/D/ffd0c.F
+++ b/Looptools/D/ffd0c.F
@@ -1,190 +1,188 @@
* ffd0c.F
* the scalar four-point function with complex masses
* this file is part of LoopTools
-* last modified 8 Dec 10 th
+* last modified 26 Jan 14 th
* Written by Le Duc Ninh, MPI, Munich (2008).
* Spence, log and eta functions are taken from FF.
-* Please cite arXiV:0902.0325 [hep-ph] if you use this function.
+* Please cite arXiv:0902.0325 [hep-ph] if you use this function.
#include "externals.h"
+#include "types.h"
subroutine ffd0c(cd0c, cpi, key, ier)
implicit none
- double complex cd0c, cpi(10)
+ ComplexType cd0c, cpi(10)
integer key, ier
#include "ff.h"
+#include "perm.h"
integer o
- double precision ra, rb, rg, rc, rh, rj
- double precision d, a
- double complex cd, ce, ck, cfx
+ RealType ra, rb, rg, rc, rh, rj
+ RealType d, a
+ ComplexType cd, ce, ck, cfx
- double precision signf
+ RealType signf
parameter (signf = -1)
- double complex ffT13, ffTn
+ ComplexType ffT13, ffTn
external ffT13, ffTn
-#define PP(i) DBLE(cpi(i+4))
+#define PP(i) Re(cpi(i+4))
#define LightLike(i) abs(PP(i)) .lt. precx
* 2 lightlike momenta
if( LightLike(1) .and.
& LightLike(3) ) then
- o = O'1234561234'
+ o = p1234
else if( LightLike(2) .and.
& LightLike(4) ) then
- o = O'4123654123'
+ o = p4123
else if( LightLike(5) .and.
& LightLike(6) ) then
- o = O'5361421342'
+ o = p1342
else if( LightLike(1) .and.
& LightLike(2) ) then
- o = O'1234561234'
+ o = p1234
else if( LightLike(2) .and.
& LightLike(3) ) then
- o = O'2341652341'
+ o = p2341
else if( LightLike(3) .and.
& LightLike(4) ) then
- o = O'3412563412'
+ o = p3412
else if( LightLike(4) .and.
& LightLike(1) ) then
- o = O'4123654123'
+ o = p4123
* 1 lightlike momentum
else if( LightLike(1) ) then
- o = O'1234561234'
+ o = p1234
else if( LightLike(2) ) then
- o = O'2341652341'
+ o = p2341
else if( LightLike(3) ) then
- o = O'3412563412'
+ o = p3412
else if( LightLike(4) ) then
- o = O'4123654123'
+ o = p4123
else if( LightLike(5) ) then
-c WRONG? 8 Jan 10 th
-c o = O'5361422413'
- o = O'5361421342'
+ o = p1342
else if( LightLike(6) ) then
-c WRONG? 8 Jan 10 th
-c o = O'6452132431'
- o = O'6452132413'
+ o = p2413
* kallen(pi, pj, pk) >= 0
#define SIDE(i,j) PP(i)*(PP(i) - 2*PP(j))
else if( SIDE(5,1) +
& SIDE(1,2) +
& SIDE(2,5) .ge. 0 ) then
- o = O'1234561234'
+ o = p1234
else if( SIDE(6,2) +
& SIDE(2,3) +
& SIDE(3,6) .ge. 0 ) then
- o = O'2341652341'
+ o = p2341
else if( SIDE(5,3) +
& SIDE(3,4) +
& SIDE(4,5) .ge. 0 ) then
- o = O'3412563412'
+ o = p3412
else if( SIDE(6,4) +
& SIDE(4,1) +
& SIDE(1,6) .ge. 0 ) then
- o = O'4123654123'
+ o = p4123
else
call fferr(103, ier)
return
endif
#define RP(i) PP(ibits(o,3*(10-i),3))
#define CM(i) cpi(ibits(o,3*(4-i),3))
rg = RP(1)
rb = RP(2)
rj = RP(5) - rb
ra = RP(3)
rc = RP(6) - ra
rh = RP(4) - RP(6)
cfx = CM(4)
cd = CM(3) - cfx - ra
ce = CM(2) - CM(3) - rc
ck = CM(1) - CM(2) - rh
rc = rc - rb
rh = rh - rj
rj = rj - rg
* D0C = \int_0^1 dx \int_0^x dy \int_0^y dz
* 1/(ra x^2 + rb y^2 + rg z^2 + rc xy + rh xz + rj yz +
* cd x + ce y + ck z + cfx + I signf)
* with signf = -eps.
* important: variables "signX" is the sign of img(X) in case X becomes real.
* 2 opposite lightlike momenta
if( ra .eq. 0 .and. rg .eq. 0 ) then
cd0c = ffT13(rb + rj, rc + rh, rb, rc,
& cd, ce + ck, cfx, signf, ce, ier)
return
endif
* 2 adjacent lightlike momenta
if( rb .eq. 0 .and. rg .eq. 0 ) then
cd0c = ffTn(ra, rb, rc, rh, rj,
& cd, ce, cfx, signf, ck, signf, key, ier) -
& ffTn(ra, rj, rc + rh, rh, rj,
& cd, ce + ck, cfx, signf, ck, signf, key, ier)
return
endif
* 1 lightlike momentum
if( rg .eq. 0 ) then
cd0c = ffTn(ra, rb, rc, rh, rj,
& cd, ce, cfx, signf, ck, signf, key, ier) -
& ffTn(ra, rj + rb, rc + rh, rh, rj,
& cd, ce + ck, cfx, signf, ck, signf, key, ier)
return
endif
* alpha is one root of: rg*alpha^2 + rj*alpha + rb == 0
* we do not need the ieps for alpha
d = rj**2 - 4*rg*rb
d = sqrt(d)
a = -.5D0/rg*(rj + d)
d = -.5D0/rg*(rj - d)
* choose the bigger root or unity
if( abs(a) .gt. abs(d) ) then
d = rb/(rg*a)
else
a = rb/(rg*d)
endif
* which one for alpha?
if( abs(d) .lt. abs(a) ) a = d
cd0c = ffTn(ra + rb + rc, rg, rj + rh,
& -rc - 2*rb - (rj + rh)*a, -rj - 2*a*rg,
& cd + ce, ck, cfx, signf, -ce - ck*a, -signf, key, ier)
if( a .ne. 1 ) then
d = 1/(1 - a)
cd0c = cd0c + ffTn(ra, rg + rj + rb, rc + rh,
& d*(rc + rh*a), rj + 2*a*rg,
& cd, ce + ck, cfx, signf, d*(ce + ck*a), d*signf, key, ier)
endif
if( abs(a) .lt. precx ) then
call ffwarn(253, ier, 1D0, 0D0)
else
d = 1/a
cd0c = cd0c + ffTn(ra, rb, rc,
& d*rc + rh, -rj - 2*a*rg,
& cd, ce, cfx, signf, d*ce + ck, d*signf, key, ier)
endif
end
diff --git a/Looptools/D/ffdcc0.F b/Looptools/D/ffdcc0.F
--- a/Looptools/D/ffdcc0.F
+++ b/Looptools/D/ffdcc0.F
@@ -1,319 +1,320 @@
#include "externals.h"
+#include "types.h"
*###[ ffdcc0:
subroutine ffdcc0(cs3,ipi12,isoort,clogi,ilogi,xpi,piDpj,
+ xqi,qiDqj,sdel2,del2s,etalam,etami,delpsi,alph,
+ ddel2s,ldel2s,npoin,ier)
***#[*comment:***********************************************************
* *
* Calculates the difference of two threepoint functions *
* C(3,...a) - C(4,...b) *
* *
* Input: xpi(6,3:4) (complex) transformed mi,pi squared in Ci *
* piDpj(6,6,3:4)(complex) pi(i).pi(j) *
* xqi(10,10) (complex) transformed mi,pi squared in D *
* qiDqj(10,10) (complex) qi(i).qi(j) *
* sdel2 (complex) sqrt(delta_{p_1 p_2}^{p_1 p_2}) *
* del2s(3,3:4) (complex) delta_{p_i s_i}^{p_i s_i} *
* etalam(3:4) (complex) delta_{s_1 s_2 s_3}^{s_1 s_2 s_3}
* /delta_{p_1 p_2}^{p_1 p_2} *
* etami(6,3:4) (complex) m_i^2 - etalam *
* ddel2s(2:3) (complex) del2s(i,3) - del2s(i,4) *
* alph(3) (complex) alph(1)=alpha, alph(3)=1-alpha *
* *
* Output: cs3 (complex)(160) C0(3)-C0(4), not yet summed. *
* ipi12 (integer)(6) factors pi^2/12, not yet summed *
* slam (complex) lambda(p1,p2,p3). *
* isoort (integer)(16) indication of he method used *
* clogi (complex)(6) log(-dyz(2,1,i)/dyz(2,2,i)) *
* ilogi (integer)(6) factors i*pi in this *
* ier (integer) 0=ok, 1=inaccurate, 2=error *
* *
* Calls: ... *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ipi12(16),isoort(16),ilogi(6),npoin,ier
logical ldel2s
- DOUBLE COMPLEX cs3(160),clogi(6)
- DOUBLE COMPLEX xqi(10),qiDqj(10,10),
+ ComplexType cs3(160),clogi(6)
+ ComplexType xqi(10),qiDqj(10,10),
+ xpi(6,3:4),piDpj(6,6,3:4),
+ sdel2,del2s(3,3:4),etalam(3:4),etami(6,3:4),alph(3),
+ ddel2s(2:3),delpsi(3,3:4)
*
* local variables:
*
integer i,j,k,ip,ii,ifirst,ieri(8)
- DOUBLE COMPLEX c,cc
- DOUBLE COMPLEX sdel2i(3,3:4),s(5),som,zfflo1,
+ ComplexType c,cc
+ ComplexType sdel2i(3,3:4),s(5),som,zfflo1,
+ y(4,3:4,3),z(4,3:4,3),dyz(2,2,3:4,3),d2yzz(3:4,3),
+ dyzzy(4,3),dsdel2,dyyzz(2,3)
- DOUBLE PRECISION smax,absc,xmax
- DOUBLE COMPLEX zfflog
+ RealType smax,absc,xmax
+ ComplexType zfflog
external zfflo1,zfflog
*
* common blocks:
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ get y,z-roots:
do 20 k=3,4
do 10 i=1,3
*
* get roots (y,z)
*
ip = i+3
sdel2i(i,k) = sqrt(-del2s(i,k))
* then handle the special case Si = 0
if ( xpi(ip,k) .eq. 0 ) then
if ( i .eq. 1 .and. alph(3) .eq. 0 .or.
+ i .eq. 3 .and. alph(1) .eq. 0 ) then
isoort(2*i-1+8*(k-3)) = 0
isoort(2*i+8*(k-3)) = 0
goto 10
endif
endif
call ffccyz(y(1,k,i),z(1,k,i),dyz(1,1,k,i),d2yzz(k,i),i,
+ sdel2,sdel2i(i,k),etalam(k),etami(1,k),delpsi(i,k),
+ xpi(1,k),piDpj(1,1,k),isoort(2*i-1+8*(k-3)),ier)
10 continue
20 continue
* #] get y,z-roots:
* #[ get differences:
*
* the only important differences are y4z3-z3y4 and (1-y4)(1-z3)-
* (1-y3)(1-z4). Note that the errors work in parallel.
*
do 199 i=1,8
ieri(i) = 0
199 continue
if ( isoort(1) .eq. isoort(9) ) then
* #[ vertices (1):
som = qiDqj(7,2)/sdel2
*
* flag if we have a cancellation
*
if ( absc(som) .lt. xloss ) then
isoort(1) = isoort(1) - 10
isoort(9) = isoort(9) - 10
endif
do 201 k=1,4
dyzzy(k,1) = som*z(k,3,1)
if ( k .gt. 2 ) dyzzy(k,1) = -dyzzy(k,1)
201 continue
dyyzz(1,1) = som
dyyzz(2,1) = som
* #] vertices (1):
endif
if ( isoort(3) .eq. isoort(11) ) then
* #[ vertices (2):
ifirst = 0
do 22 j=1,2
do 21 k=1,2
ii = 2*(j-1) + k
dyzzy(ii,2) = y(2*j,4,2)*z(ii,3,2)-y(2*j,3,2)*z(ii,4,2)
xmax = absc(y(2*j,4,2)*z(ii,3,2))
if ( absc(dyzzy(ii,2)) .ge. xmax ) goto 21
isoort(3) = isoort(3) - 10
isoort(11) = isoort(11) - 10
if ( ifirst .eq. 0 ) then
if ( ddel2s(2) .eq. 0 ) then
dsdel2 = 0
else
dsdel2 = ddel2s(2)/(sdel2i(2,3)+sdel2i(2,4))
endif
endif
if ( ifirst .le. 1 ) then
if ( j .eq. 1 ) then
s(1) = xqi(6)*qiDqj(7,4)*qiDqj(5,4)/sdel2
s(2) = -qiDqj(7,4)*sdel2i(2,3)
s(3) = +qiDqj(6,4)*dsdel2
else
s(1) = xqi(6)*qiDqj(7,2)*qiDqj(5,2)/sdel2
s(2) = -qiDqj(7,2)*sdel2i(2,3)
s(3) = +qiDqj(6,2)*dsdel2
endif
endif
if ( ifirst .le. 0 ) then
ifirst = 2
s(4) = -qiDqj(5,10)*qiDqj(7,4)*sdel2i(2,3)/sdel2
s(5) = delpsi(2,3)*dsdel2/sdel2
endif
if ( k .eq. 1 ) then
som = s(1) + s(2) + s(3) + s(4) + s(5)
else
som = s(1) - s(2) - s(3) - s(4) - s(5)
endif
smax = max(absc(s(1)),absc(s(2)),absc(s(3)),absc(s(4)),
- + absc(s(5)))/DBLE(xqi(6))**2
+ + absc(s(5)))/Re(xqi(6))**2
if ( smax .lt. xmax ) then
- dyzzy(ii,2) = som*(1/DBLE(xqi(6))**2)
+ dyzzy(ii,2) = som*(1/Re(xqi(6))**2)
xmax = smax
endif
21 continue
*
* get dyyzz
*
if ( ldel2s ) then
dyyzz(j,2) = dyz(2,j,4,2) - dyz(2,j,3,2)
xmax = absc(dyz(2,j,4,2))
if ( absc(dyyzz(j,2)) .ge. xloss*xmax ) goto 22
print *,'ffdcc0: under construction!'
*
* (could be copied from real case)
*
endif
*
* bookkeeping
*
ifirst = ifirst - 1
22 continue
* #] vertices (2):
endif
if ( isoort(5) .eq. isoort(13) ) then
* #[ vertices (3):
ifirst = 0
do 26 j=1,2
do 25 k=1,2
ii = 2*(j-1) + k
dyzzy(ii,3) = y(2*j,4,3)*z(ii,3,3)-y(2*j,3,3)*z(ii,4,3)
xmax = absc(y(2*j,4,3)*z(ii,3,3))
if ( absc(dyzzy(ii,3)) .ge. xmax ) goto 25
isoort(5) = isoort(5) - 10
isoort(13) = isoort(13) - 10
if ( ifirst .eq. 0 ) then
if ( ddel2s(2) .eq. 0 ) then
dsdel2 = 0
else
dsdel2 = ddel2s(3)/(sdel2i(3,3)+sdel2i(3,4))
endif
endif
if ( ifirst .le. 1 ) then
if ( j .eq. 1 ) then
s(1) = xqi(8)*qiDqj(7,1)*qiDqj(5,1)/sdel2
s(2) = +qiDqj(7,1)*sdel2i(3,3)
s(3) = +qiDqj(9,1)*dsdel2
else
s(1) = xqi(8)*qiDqj(7,4)*qiDqj(5,4)/sdel2
s(2) = +qiDqj(7,4)*sdel2i(3,3)
s(3) = +qiDqj(9,4)*dsdel2
endif
endif
if ( ifirst .le. 0 ) then
ifirst = 2
s(4) = -qiDqj(5,9)*qiDqj(7,1)*sdel2i(3,3)/sdel2
s(5) = delpsi(3,3)*dsdel2/sdel2
endif
if ( k .eq. 1 ) then
som = s(1) + s(2) + s(3) + s(4) + s(5)
else
som = s(1) - s(2) - s(3) - s(4) - s(5)
endif
smax = max(absc(s(1)),absc(s(2)),absc(s(3)),absc(s(4)),
- + absc(s(5)))/DBLE(xqi(8))**2
+ + absc(s(5)))/Re(xqi(8))**2
if ( smax .lt. xmax ) then
- dyzzy(ii,3) = som*(1/DBLE(xqi(8))**2)
+ dyzzy(ii,3) = som*(1/Re(xqi(8))**2)
xmax = smax
endif
25 continue
*
* get dyyzz
*
if ( ldel2s ) then
dyyzz(j,3) = dyz(2,j,4,3) - dyz(2,j,3,3)
xmax = absc(dyz(2,j,4,3))
if ( absc(dyyzz(j,3)) .ge. xloss*xmax ) goto 24
print *,'ffdcc0: under construction!'
*
* (could be copied from real case)
*
endif
*
* bookkeeping
*
24 continue
ifirst = ifirst - 1
26 continue
* #] vertices (3):
endif
ier = ier + max(ieri(1),ieri(2),ieri(3),ieri(4),ieri(5),ieri(6),
+ ieri(7),ieri(8))
* #] get differences:
* #[ logarithms for 4point function:
if ( npoin .eq. 4 ) then
do 96 k = 3,4
do 95 i = 1,3
ii = i+3*(k-3)
if ( ilogi(ii) .ne. -999 ) goto 95
if ( isoort(2*i+8*(k-3)) .ne. 0 ) then
* maybe add sophisticated factors i*pi later
c = -dyz(2,1,i,k)/dyz(2,2,i,k)
cc = c-1
if ( absc(cc) .lt. xloss ) then
s(1) = d2yzz(i,k)/dyz(2,2,i,k)
clogi(ii) = zfflo1(s(1),ier)
ilogi(ii) = 0
- elseif ( DBLE(c) .gt. 0 ) then
+ elseif ( Re(c) .gt. 0 ) then
clogi(ii) = zfflog(c,0,czero,ier)
ilogi(ii) = 0
else
cc = c+1
if ( absc(cc) .lt. xloss ) then
s(1) = -2*sdel2i(i,k)/dyz(2,2,i,k)/
- + DBLE(xpi(i+3,k))
+ + Re(xpi(i+3,k))
clogi(ii) = zfflo1(s(1),ier)
else
s(1) = 0
clogi(ii) = zfflog(-c,0,czero,ier)
endif
- if ( DIMAG(c) .lt. -precc*absc(c) .or. DIMAG(s(1))
+ if ( Im(c) .lt. -precc*absc(c) .or. Im(s(1))
+ .lt. -precc*absc(s(1)) ) then
ilogi(ii) = -1
- elseif ( DIMAG(c) .gt. precc*absc(c) .or.
- + DIMAG(s(1)) .gt. precc*absc(s(1)) ) then
+ elseif ( Im(c) .gt. precc*absc(c) .or.
+ + Im(s(1)) .gt. precc*absc(s(1)) ) then
ilogi(ii) = +1
- elseif ( DBLE(dyz(2,2,i,k)) .eq. 0 ) then
- ilogi(ii) = -nint(sign(1D0,DBLE(xpi(i+3,k))))
+ elseif ( Re(dyz(2,2,i,k)) .eq. 0 ) then
+ ilogi(ii) = -nint(sign(1D0,Re(xpi(i+3,k))))
ier = ier + 50
print *,'doubtful imaginary part ',ilogi(ii)
else
call fferr(78,ier)
print *,'c = ',c
endif
endif
endif
95 continue
96 continue
endif
* #] logarithms for 4point function:
* #[ integrals:
do 100 i=1,3
j = 2*i-1
if ( isoort(j) .eq. 0 ) then
if ( isoort(j+8) .ne. 0 ) then
call ffcs3(cs3(20*i+61),ipi12(j+8),y(1,4,i),
+ z(1,4,i),dyz(1,1,4,i),d2yzz(4,i),
+ xpi(1,4),piDpj(1,1,4),i,6,isoort(j+8),ier)
endif
elseif ( isoort(j+8) .eq. 0 ) then
call ffcs3(cs3(20*i-19),ipi12(j),y(1,3,i),
+ z(1,3,i),dyz(1,1,3,i),d2yzz(3,i),
+ xpi(1,3),piDpj(1,1,3),i,6,isoort(j),ier)
else
call ffdcs(cs3(20*i-19),ipi12(j),y(1,3,i),z(1,3,i),
+ dyz(1,1,3,i),d2yzz(3,i),dyzzy(1,i),dyyzz(1,i),
+ xpi,piDpj,i,6,isoort(j),ier)
endif
100 continue
* #] integrals:
*###] ffdcc0:
end
diff --git a/Looptools/D/ffdel4.F b/Looptools/D/ffdel4.F
--- a/Looptools/D/ffdel4.F
+++ b/Looptools/D/ffdel4.F
@@ -1,291 +1,292 @@
#include "externals.h"
+#include "types.h"
*###[ ffdel4:
subroutine ffdel4(del4,piDpj)
***#[*comment:***********************************************************
* *
* Calculate del4(piDpj) = det(si.sj) with *
* the momenta as follows: *
* p(1-4) = s(i) *
* p(4-10) = p(i) *
* *
* Input: piDpj(ns,ns) (real) *
* *
* Output: del4 (real) det(si.sj) *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
- DOUBLE PRECISION del4,piDpj(10,10)
+ RealType del4,piDpj(10,10)
*
* local variables:
*
integer mem,nperm
parameter(mem=10,nperm=125)
integer i,jj(8),iperm(4,nperm),imem,jmem,memarr(mem,4),memind,
+ inow,jnow,icount
- DOUBLE PRECISION s(24),xmax,del4p,xmaxp
+ RealType s(24),xmax,del4p,xmaxp
save iperm,memind,memarr,inow,jnow
*
* common blocks:
*
#include "ff.h"
* #] declarations:
* #[ data:
data memind /0/
data memarr /mem*0,mem*0,mem*1,mem*1/
data inow /1/
data jnow /1/
*
* these are all permutations that give a non-zero result with the
* correct sign. This list was generated with getperm4.
* (note: this used to be well-ordened, but then it had more than
* 19 continuation lines)
*
data iperm/
+ 1,2,3,4,1,2,3,7,1,2,8,3,1,2,3,10,1,2,6,4,1,2,4,7,1,2,4,9,1,2,6,7
+ ,1,2,8,6,1,2,6,10,1,2,7,8,1,2,7,9,1,2,10,7,1,2,9,8,1,2,10,9,1,3,
+ 4,5,1,3,6,4,1,3,10,4,1,3,7,5,1,3,5,8,1,3,10,5,1,3,6,7,1,3,8,6,1,
+ 3,6,10,1,3,10,7,1,3,8,10,1,4,5,6,1,4,7,5,1,4,9,5,1,4,6,7,1,4,6,9
+ ,1,4,6,10,1,4,10,7,1,4,10,9,1,5,6,7,1,5,8,6,1,5,6,10,1,5,7,8,1,5
+ ,7,9,1,5,10,7,1,5,9,8,1,5,10,9,1,6,8,7,1,6,9,7,1,6,8,9,1,6,8,10,
+ 1,6,9,10,1,7,10,8,1,7,10,9,1,8,9,10,2,3,4,5,2,3,8,4,2,3,9,4,2,3,
+ 7,5,2,3,5,8,2,3,10,5,2,3,8,7,2,3,9,7,2,3,8,9,2,3,8,10,2,3,9,10,2
+ ,4,5,6,2,4,7,5,2,4,9,5,2,4,6,8,2,4,6,9,2,4,8,7,2,4,9,7,2,4,8,9,2
+ ,5,6,7,2,5,8,6,2,5,6,10,2,5,7,8,2,5,7,9,2,5,10,7,2,5,9,8,2,5,10,
+ 9,2,6,8,7,2,6,9,7,2,6,8,9,2,6,8,10,2,6,9,10,2,7,10,8,2,7,10,9,2,
+ 8,9,10,3,4,5,6,3,4,8,5,3,4,9,5,3,4,5,10,3,4,6,8,3,4,6,9,3,4,10,8
+ ,3,4,10,9,3,5,6,7,3,5,8,6,3,5,6,10,3,5,7,8,3,5,7,9,3,5,10,7,3,5,
+ 9,8,3,5,10,9,3,6,8,7,3,6,9,7,3,6,8,9,3,6,8,10,3,6,9,10,3,7,10,8,
+ 3,7,10,9,3,8,9,10,4,5,6,7,4,5,8,6,4,5,6,10,4,5,7,8,4,5,7,9,4,5,1
+ 0,7,4,5,9,8,4,5,10,9,4,6,8,7,4,6,9,7,4,6,8,9,4,6,8,10,4,6,9,10,4
+ ,7,10,8,4,7,10,9,4,8,9,10/
* #] data:
* #[ get starting point from memory:
*
* see if we know were to start, if not: go on as last time
*
do 5 i=1,mem
if ( id .eq. memarr(i,1) .and. idsub .eq. memarr(i,2) ) then
inow = memarr(i,3)
jnow = memarr(i,4)
goto 6
endif
5 continue
6 continue
* #] get starting point from memory:
* #[ calculations:
imem = inow
jmem = jnow
del4 = 0
xmax = 0
icount = 0
10 continue
jj(1) = iperm(1,inow)
jj(3) = iperm(2,inow)
jj(5) = iperm(3,inow)
jj(7) = iperm(4,inow)
jj(2) = iperm(1,jnow)
jj(4) = iperm(2,jnow)
jj(6) = iperm(3,jnow)
jj(8) = iperm(4,jnow)
s( 1) = +piDpj(jj(1),jj(2))*piDpj(jj(3),jj(4))*
+ piDpj(jj(5),jj(6))*piDpj(jj(7),jj(8))
s( 2) = +piDpj(jj(1),jj(4))*piDpj(jj(3),jj(6))*
+ piDpj(jj(5),jj(2))*piDpj(jj(7),jj(8))
s( 3) = +piDpj(jj(1),jj(6))*piDpj(jj(3),jj(2))*
+ piDpj(jj(5),jj(4))*piDpj(jj(7),jj(8))
s( 4) = -piDpj(jj(1),jj(2))*piDpj(jj(3),jj(6))*
+ piDpj(jj(5),jj(4))*piDpj(jj(7),jj(8))
s( 5) = -piDpj(jj(1),jj(6))*piDpj(jj(3),jj(4))*
+ piDpj(jj(5),jj(2))*piDpj(jj(7),jj(8))
s( 6) = -piDpj(jj(1),jj(4))*piDpj(jj(3),jj(2))*
+ piDpj(jj(5),jj(6))*piDpj(jj(7),jj(8))
s( 7) = -piDpj(jj(1),jj(2))*piDpj(jj(3),jj(4))*
+ piDpj(jj(7),jj(6))*piDpj(jj(5),jj(8))
s( 8) = -piDpj(jj(1),jj(4))*piDpj(jj(3),jj(6))*
+ piDpj(jj(7),jj(2))*piDpj(jj(5),jj(8))
s( 9) = -piDpj(jj(1),jj(6))*piDpj(jj(3),jj(2))*
+ piDpj(jj(7),jj(4))*piDpj(jj(5),jj(8))
s(10) = +piDpj(jj(1),jj(2))*piDpj(jj(3),jj(6))*
+ piDpj(jj(7),jj(4))*piDpj(jj(5),jj(8))
s(11) = +piDpj(jj(1),jj(6))*piDpj(jj(3),jj(4))*
+ piDpj(jj(7),jj(2))*piDpj(jj(5),jj(8))
s(12) = +piDpj(jj(1),jj(4))*piDpj(jj(3),jj(2))*
+ piDpj(jj(7),jj(6))*piDpj(jj(5),jj(8))
s(13) = -piDpj(jj(1),jj(2))*piDpj(jj(7),jj(4))*
+ piDpj(jj(5),jj(6))*piDpj(jj(3),jj(8))
s(14) = -piDpj(jj(1),jj(4))*piDpj(jj(7),jj(6))*
+ piDpj(jj(5),jj(2))*piDpj(jj(3),jj(8))
s(15) = -piDpj(jj(1),jj(6))*piDpj(jj(7),jj(2))*
+ piDpj(jj(5),jj(4))*piDpj(jj(3),jj(8))
s(16) = +piDpj(jj(1),jj(2))*piDpj(jj(7),jj(6))*
+ piDpj(jj(5),jj(4))*piDpj(jj(3),jj(8))
s(17) = +piDpj(jj(1),jj(6))*piDpj(jj(7),jj(4))*
+ piDpj(jj(5),jj(2))*piDpj(jj(3),jj(8))
s(18) = +piDpj(jj(1),jj(4))*piDpj(jj(7),jj(2))*
+ piDpj(jj(5),jj(6))*piDpj(jj(3),jj(8))
s(19) = -piDpj(jj(7),jj(2))*piDpj(jj(3),jj(4))*
+ piDpj(jj(5),jj(6))*piDpj(jj(1),jj(8))
s(20) = -piDpj(jj(7),jj(4))*piDpj(jj(3),jj(6))*
+ piDpj(jj(5),jj(2))*piDpj(jj(1),jj(8))
s(21) = -piDpj(jj(7),jj(6))*piDpj(jj(3),jj(2))*
+ piDpj(jj(5),jj(4))*piDpj(jj(1),jj(8))
s(22) = +piDpj(jj(7),jj(2))*piDpj(jj(3),jj(6))*
+ piDpj(jj(5),jj(4))*piDpj(jj(1),jj(8))
s(23) = +piDpj(jj(7),jj(6))*piDpj(jj(3),jj(4))*
+ piDpj(jj(5),jj(2))*piDpj(jj(1),jj(8))
s(24) = +piDpj(jj(7),jj(4))*piDpj(jj(3),jj(2))*
+ piDpj(jj(5),jj(6))*piDpj(jj(1),jj(8))
del4p = 0
xmaxp = 0
do 20 i=1,24
del4p = del4p + s(i)
xmaxp = max(xmaxp,abs(s(i)))
20 continue
if ( abs(del4p) .lt. xloss*xmaxp ) then
if ( inow .eq. imem .or. xmaxp .lt. xmax ) then
del4 = del4p
xmax = xmaxp
endif
* as the list is ordered we may have more luck stepping
* through with large steps
inow = inow + 43
jnow = jnow + 49
if ( inow .gt. nperm ) inow = inow - nperm
if ( jnow .gt. nperm ) jnow = jnow - nperm
icount = icount + 1
if ( icount.gt.15 .or. inow.eq.imem .or. jnow.eq.jmem
+ ) goto 800
goto 10
endif
del4 = del4p
xmax = xmaxp
* #] calculations:
* #[ into memory:
memind = memind + 1
if ( memind .gt. mem ) memind = 1
memarr(memind,1) = id
memarr(memind,2) = idsub
memarr(memind,3) = inow
memarr(memind,4) = jnow
800 continue
* #] into memory:
*###] ffdel4:
end
*###[ ffdl3p:
subroutine ffdl3p(dl3p,piDpj,ns,ii,jj)
***#[*comment:***********************************************************
* calculate in a numerically stable way *
* *
* p1 p2 p3 *
* delta *
* p1' p2' p3' *
* *
* with pn = xpi(ii(n)), p4 = -p1-p2-p3, p5 = -p1-p2, p6 = p2+p3 *
* with pn'= xpi(jj(n)), p4'= etc. (when ns=15 p5=p1+p2) *
* *
* Input: piDpj real(ns,ns) dotpruducts *
* ns integer either 10 or 15 *
* ii,jj integer(6) location of pi in piDpj *
* Output: dl3p real see above *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ns,ii(6),jj(6)
- DOUBLE PRECISION dl3p,piDpj(ns,ns)
+ RealType dl3p,piDpj(ns,ns)
*
* local variables
*
integer i,j,k,l,iperm(3,16),ii1,ii2,ii3,jj1,jj2,jj3,i0
logical lsymm
- DOUBLE PRECISION s(6),som,xmax,smax,trylos
+ RealType s(6),som,xmax,smax,trylos
*
* common blocks
*
#include "ff.h"
*
* data
*
data iperm /1,2,3, 2,4,3, 3,4,1, 4,2,1,
+ 1,2,6, 6,4,3, 3,1,6, 2,4,6,
+ 2,5,3, 5,4,1, 1,3,5, 2,4,5,
+ 1,6,5, 2,5,6, 3,6,5, 4,5,6/
* #] declarations:
* #[ calculations:
if ( ii(1).eq.jj(1) .and. ii(2).eq.jj(2) .and. ii(3).eq.jj(3) )
+ then
*
* symmetric - fewer possibilities
*
lsymm = .TRUE.
else
lsymm = .FALSE.
endif
*
* try all (8.5,16)*16 permutations
*
xmax = 0
trylos = 1
do 101 l=1,16
if ( lsymm ) then
i0 = l
else
i0 = 1
endif
do 100 i=i0,16
ii1 = ii(iperm(1,i))
ii2 = ii(iperm(2,i))
ii3 = ii(iperm(3,i))
j = i+l-1
if ( j .gt. 16 ) j=j-16
jj1 = jj(iperm(1,j))
jj2 = jj(iperm(2,j))
jj3 = jj(iperm(3,j))
s(1) = +piDpj(ii1,jj1)*piDpj(ii2,jj2)*piDpj(ii3,jj3)
s(2) = +piDpj(ii2,jj1)*piDpj(ii3,jj2)*piDpj(ii1,jj3)
s(3) = +piDpj(ii3,jj1)*piDpj(ii1,jj2)*piDpj(ii2,jj3)
s(4) = -piDpj(ii1,jj1)*piDpj(ii3,jj2)*piDpj(ii2,jj3)
s(5) = -piDpj(ii3,jj1)*piDpj(ii2,jj2)*piDpj(ii1,jj3)
s(6) = -piDpj(ii2,jj1)*piDpj(ii1,jj2)*piDpj(ii3,jj3)
som = 0
smax = 0
do 80 k=1,6
som = som + s(k)
smax = max(smax,abs(som))
80 continue
if ( ns .eq. 15 .and. (i.gt.8 .neqv. j.gt.8) )
+ som = -som
if ( i .eq. 1 .or. smax .lt. xmax ) then
dl3p = som
xmax = smax
endif
if ( abs(dl3p) .ge. xloss*smax ) goto 110
* give up a bit more easily if I have tried many times
if ( trylos*abs(dl3p) .ge. xloss*smax ) goto 109
trylos = trylos*1.3D0
100 continue
101 continue
109 continue
110 continue
* #] calculations:
*###] ffdl3p:
end
diff --git a/Looptools/D/ffxd0.F b/Looptools/D/ffxd0.F
--- a/Looptools/D/ffxd0.F
+++ b/Looptools/D/ffxd0.F
@@ -1,787 +1,788 @@
#include "externals.h"
+#include "types.h"
*--#[ log:
* $Id: ffxd0.f,v 1.4 1996/01/22 13:32:52 gj Exp $
* $Log: ffxd0.f,v $
c Revision 1.4 1996/01/22 13:32:52 gj
c Added sanity check on ier; if it is larger than 16 some routines will not
c compute anything.
c
c Revision 1.3 1995/11/28 13:37:47 gj
c Found wrong sign in ffcdna, fixed typo in ffcrp.
c Killed first cancellation in ffcdna - more to follow
c Added warnings to ffwarn.dat; slightly changed debug output in ffxd0.f
c
c Revision 1.2 1995/10/17 06:55:12 gj
c Fixed ieps error in ffdcrr (ffcxs4.f), added real case in ffcrr, debugging
c info in ffxd0, and warned against remaining errors for del2=0 in ffrot4
c (ffxd0h.f)
c
*--#] log:
*###[ ffxd0:
subroutine ffxd0(cd0,xpi,ier)
***#[*comment:***********************************************************
* *
* 1 / *
* calculate cd0 = ----- \dq [(q^2 + 2*s_1.q)*(q^2 + 2*s2.q) *
* ipi^2 / *(q^2 + 2*s3.q)*(q^2 + 2*s4.q)]^-1 *
* *
* |p9 *
* \p8 V p7/ *
* \ / *
* \________/ *
* | m4 | *
* = | | /____ *
* m1| |m3 \ p10 *
* | | all momenta are incoming *
* |________| *
* / m2 \ *
* / \ *
* /p5 p6\ *
* *
* *
* following the two-three-point-function method in 't hooft & *
* veltman. this is only valid if there is a lambda(pij,mi,mj)>0 *
* *
* Input: xpi = mi^2 (real) i=1,4 *
* xpi = pi.pi (real) i=5,8 (note: B&D metric) *
* xpi(9)=s (real) (=p13) *
* xpi(10)=t (real) (=p24) *
* xpi(11)=u (real) u=p5.p5+..-p9.p9-p10.10 or 0 *
* xpi(12)=v (real) v=-p5.p5+p6.p6-p7.p7+.. or 0 *
* xpi(13)=w (real) w=p5.p5-p6.p6+p7.p7-p8.p8+.. *
* output: cd0 (complex) *
* ier (integer) <50:lost # digits 100=error *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE PRECISION xpi(13)
- DOUBLE COMPLEX cd0
+ RealType xpi(13)
+ ComplexType cd0
integer ier
*
* local variables
*
logical luvw(3)
- DOUBLE PRECISION dpipj(10,13)
+ RealType dpipj(10,13)
*
* common blocks:
*
#include "ff.h"
* #] declarations:
* #[ catch totally massless case:
*
if (abs(xpi(1) + xpi(2) + xpi(3) + xpi(4)) .lt. 1D-10) then
call ffxd0m0(cd0,xpi,ier)
return
endif
*
* #] catch totally massless case:
* #[ call ffdif4, ffxd0a:
*
call ffdif4(dpipj,luvw,xpi)
call ffxd0a(cd0,xpi,dpipj,ier)
*
* restore the zeros for u,v,w as we have calculated them
* ourselves and the user is unlikely to do this...
*
if ( luvw(1) ) xpi(11) = 0
if ( luvw(2) ) xpi(12) = 0
if ( luvw(3) ) xpi(13) = 0
*
* #] call ffdif4, ffxd0a:
*###] ffxd0:
end
*###[ ffxd0a:
subroutine ffxd0a(cd0,xpi,dpipj,ier)
*
* glue routine which calls ffxd0b with ndiv=0
*
implicit none
*
* arguments
*
integer ier
- DOUBLE PRECISION xpi(13),dpipj(10,13)
- DOUBLE COMPLEX cd0
+ RealType xpi(13),dpipj(10,13)
+ ComplexType cd0
*
* locals
*
- DOUBLE COMPLEX cs,cfac
+ ComplexType cs,cfac
*
* and go!
*
call ffxd0b(cs,cfac,xpi,dpipj,0,ier)
cd0 = cs*cfac
*
*###] ffxd0a:
end
*###[ ffxd0b:
subroutine ffxd0b(cs,cfac,xpi,dpipj,ndiv,ier)
***#[*comment:***********************************************************
* *
* 1 / *
* calculate cd0 = ----- \dq [(q^2 + 2*s_1.q)*(q^2 + 2*s2.q) *
* ipi^2 / *(q^2 + 2*s3.q)*(q^2 + 2*s4.q)]^-1 *
* *
* |p9 *
* \p8 V p7/ *
* \ / *
* \________/ *
* | m4 | *
* = | | /____ *
* m1| |m3 \ p10 *
* | | all momenta are incoming *
* |________| *
* / m2 \ *
* / \ *
* /p5 p6\ *
* *
* *
* following the two-three-point-function method in 't hooft & *
* veltman. this is only valid if there is a lambda(pij,mi,mj)>0 *
* *
* Input: xpi = mi^2 (real) i=1,4 *
* xpi = pi.pi (real) i=5,8 (note: B&D metric) *
* xpi(9)=s (real) (=p13) *
* xpi(10)=t (real) (=p24) *
* xpi(11)=u (real) u=p5.p5+..-p9.p9-p10.10 *
* xpi(12)=v (real) v=-p5.p5+p6.p6-p7.p7+.. *
* xpi(13)=w (real) w=p5.p5-p6.p6+p7.p7-p8.p8+.. *
* dpipj(10,13) (real) = pi(i) - pi(j) *
* output: cs,cfac (complex) cd0 = cs*cfac *
* ier (integr) 0=ok 1=inaccurate 2=error *
* calls: ffcxs3,ffcxr,ffcrr,... *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ndiv,ier
- DOUBLE PRECISION xpi(13),dpipj(10,13)
- DOUBLE COMPLEX cs,cfac
+ RealType xpi(13),dpipj(10,13)
+ ComplexType cs,cfac
*
* local variables
*
integer i,j,itype,ini2ir,ier2,idone,ier0
logical ldel2s
- DOUBLE COMPLEX c,cs1,cs2
- DOUBLE PRECISION absc,xmax,xpip(13),dpipjp(10,13),piDpjp(10,10),
+ ComplexType c,cs1,cs2
+ RealType absc,xmax,xpip(13),dpipjp(10,13),piDpjp(10,10),
+ qiDqj(10,10),del2s,lambda0
save ini2ir,lambda0
*
* common blocks:
*
#include "ff.h"
*
* memory
*
integer iermem(memory),ialmem(memory),memind,ierini,nscsav,
+ isgnsa
logical onssav
- DOUBLE PRECISION xpimem(10,memory),dl4mem(memory)
- DOUBLE COMPLEX csmem(memory),cfcmem(memory)
+ RealType xpimem(10,memory),dl4mem(memory)
+ ComplexType csmem(memory),cfcmem(memory)
save memind,iermem,ialmem,xpimem,dl4mem,nscsav,onssav,csmem,
+ cfcmem
*
* statement function:
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
*
* data
*
data memind /0/
data ini2ir /0/
data lambda0 /1D0/
*
* #] declarations:
* #[ initialisations:
cs = 0
cfac = 1
idsub = 0
idone = 0
* #] initialisations:
* #[ check for IR 4point function:
*
call ffxdir(cs,cfac,idone,xpi,dpipj,4,ndiv,ier)
if ( idone .le. 0 .and. ndiv .gt. 0 ) then
cs = 0
cfac = 1
ier = 0
return
endif
if ( idone .gt. 0 ) then
return
endif
*
* #] check for IR 4point function:
* #[ rotate to calculable position:
call ffrot4(irota4,del2s,xpip,dpipjp,piDpjp,xpi,dpipj,qiDqj,4,
+ itype,ier)
if ( itype .lt. 0 ) then
print *,'ffxd0b: error: Cannot handle this ',
+ ' masscombination yet:'
print *,(xpi(i),i=1,13)
return
endif
if ( itype .eq. 1 ) then
ldel2s = .TRUE.
isgnal = +1
else
ldel2s = .FALSE.
endif
* #] rotate to calculable position:
* #[ treat doubly IR divergent case:
if ( itype .eq. 2 ) then
*
* double IR divergent diagram, i.e. xpi(3)=xpi(4)=xpi(7)=0
*
if ( ini2ir .eq. 0 ) then
ini2ir = 1
print *,'ffxd0b: using the log(lam) prescription to'
print *,' regulate the 2 infrared poles to match'
print *,' with soft gluon massive, lam^2 =',lambda
endif
ier2 = 0
call ffx2ir(cs1,cs2,xpip,dpipjp,ier2)
del2s = -lambda**2/4
*
* correct for the wrongly treated IR pole
*
cs = cs + (cs1 + cs2)/cfac
ier = max(ier,ier2)
xmax = max(absc(cs1),absc(cs2))/absc(cfac)
if ( absc(cs) .lt. xloss*xmax )
+ call ffwarn(172,ier,absc(cs),xmax)
if ( .not.ldot ) return
endif
if( itype .eq. 3 ) then
call ffd0tra(cs,
& xpi(iold(9,irota4)), xpi(iold(10,irota4)),
& xpi(iold(1,irota4)), xpi(iold(8,irota4)), ier)
return
endif
*
* #] treat doubly IR divergent case:
* #[ look in memory:
ierini = ier
isgnsa = isgnal
*
* initialise memory
*
if ( lmem .and. idone .eq. 0 .and. (memind .eq. 0 .or. nschem
+ .ne. nscsav .or. (onshel .neqv. onssav) ) ) then
memind = 0
nscsav = nschem
onssav = onshel
do 2 i=1,memory
do 1 j=1,10
xpimem(j,i) = 0
1 continue
ialmem(i) = 0
2 continue
endif
*
if ( lmem .and. idone .eq. 0 .and. lambda .eq. lambda0 ) then
do 150 i=1,memory
do 130 j=1,10
if ( xpip(j) .ne. xpimem(j,i) ) goto 150
130 continue
* we use ialmem(i)==0 to signal that both are covered as
* the sign was flipped during the computation
if ( ialmem(i).ne.isgnal .and. ialmem(i).ne.0 ) goto 150
* we found an already calculated masscombination ..
* (maybe check differences as well)
cs = csmem(i)
cfac = cfcmem(i)
ier = ier+iermem(i)
if ( ldot ) then
fdel4s = dl4mem(i)
* we forgot to calculate the dotproducts
idone = 1
goto 51
endif
return
150 continue
elseif ( lmem ) then
lambda0 = lambda
endif
51 continue
* #] look in memory:
* #[ get dotproducts:
*
* Calculate the dotproducts (in case it comes out of memory the
* error is already included in ier)
*
ier0 = ier
call ffgdt4(piDpjp,xpip,dpipjp,xpi,ier0)
if ( idone .gt. 0 ) return
ier = ier0
if ( ier.ge.100 ) then
cs = 0
cfac = 1
return
endif
*
* #] get dotproducts:
* #[ calculations:
*
call ffxd0e(cs,cfac,xmax, .FALSE.,ndiv,xpip,dpipjp,piDpjp,del2s,
+ ldel2s,ier)
*
* #] calculations:
* #[ add to memory:
*
* memory management :-)
*
if ( lmem ) then
memind = memind + 1
if ( memind .gt. memory ) memind = 1
do 200 j=1,10
xpimem(j,memind) = xpip(j)
200 continue
csmem(memind) = cs
cfcmem(memind) = cfac
iermem(memind) = ier-ierini
ialmem(memind) = isgnal
dl4mem(memind) = fdel4s
if ( isgnal.ne.isgnsa ) then
ialmem(memind) = 0
endif
endif
* #] add to memory:
*###] ffxd0b:
end
*###[ ffxd0e:
subroutine ffxd0e(cs,cfac,xmax,lir,ndiv,xpip,dpipjp,piDpjp,
+ del2s,ldel2s,ier)
***#[*comment:***********************************************************
* *
* Break in the calculation of D0 to allow the E0 to tie in in a *
* logical position. This part gets untransformed momenta but *
* rotated momenta in and gives the D0 (in two pieces) and the *
* maximum term back. *
* *
* Input xpip real(13) *
* dpipjp real(10,13) *
* piDpjp real(10,10) *
* del2s real *
* ldel2s logical *
* lir logical if TRUE it can still be IR-div *
* ndiv integer number of required divergences *
* *
* Output: cs complex the fourpoint function without *
* overall factor (sum of dilogs) *
* cfac complex this overall factor *
* xmax real largest term in summation *
* ier integer usual error flag *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ndiv,ier
logical lir,ldel2s
- DOUBLE PRECISION xpip(13),dpipjp(10,13),piDpjp(10,10),xmax,del2s
- DOUBLE COMPLEX cs,cfac
+ RealType xpip(13),dpipjp(10,13),piDpjp(10,10),xmax,del2s
+ ComplexType cs,cfac
*
* local variables
*
- DOUBLE COMPLEX c,cs4(175),cs3(2)
+ ComplexType c,cs4(175),cs3(2)
logical laai
integer i,ier0,itime,maxlos,init,isoort(16),ipi12(28),
+ ipi123(2),ipi12t,idone
- DOUBLE PRECISION absc,sdel2s,ai(4),daiaj(4,4),aai(4),
+ RealType absc,sdel2s,ai(4),daiaj(4,4),aai(4),
+ dt3t4,xqi(10),dqiqj(10,10),qiDqj(10,10),xfac
save maxlos
*
* common blocks:
*
#include "ff.h"
*
* statement function:
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
*
* data
*
data init /0/
* #] declarations:
* #[ check for IR 4point function:
if ( lir ) then
*
ier0 = ier
call ffxdir(cs,cfac,idone,xpip,dpipjp,4,0,ier)
if ( idone .le. 0 .and. ndiv .gt. 0 ) then
cs = 0
cfac = 1
xmax = 0
ier = 0
return
endif
if ( idone .gt. 0 ) then
xmax = abs(cs)*10d0**(-mod((ier0-ier),50))
return
endif
endif
*
* #] check for IR 4point function:
* #[ init:
*
* initialize cs4:
*
do 80 i=1,175
cs4(i) = 0
80 continue
do 90 i=1,28
ipi12(i) = 0
90 continue
cs = 0
*
* #] init:
* #[ transform the masses and momenta:
itime = 1
25 continue
*
* Transform with the A's of gerard 't hooft's transformation:
*
* NOTE: for some odd reason I cannot vary isgnal,isgn34
* independently!
*
isgn34 = isgnal
sdel2s = isgn34*sqrt(-del2s)
ier0 = ier
call ffai(ai,daiaj,aai,laai,del2s,sdel2s,xpip,dpipjp,piDpjp,
+ ier0)
if ( ier0 .ge. 100 ) goto 70
call fftran(ai,daiaj,aai,laai,xqi,dqiqj,qiDqj,del2s,sdel2s,
+ xpip,dpipjp,piDpjp,ier0)
if ( ier0 .ge. 100 ) goto 70
if ( .not.ldel2s ) then
dt3t4 = -2*ai(3)*ai(4)*sdel2s
if ( dt3t4 .eq. 0 ) then
* don't know what to do...
call fferr(85,ier)
return
endif
else
* this value is modulo the delta of xpip(4)=xpip(3)(1+2delta)
dt3t4 = -2*ai(4)**2*xpip(3)
endif
70 continue
*
* If we lost too much accuracy try the other root...
* (to do: build in a mechanism for remembering this later)
*
if ( init .eq. 0 ) then
init = 1
* go ahead if we have half the digits left
maxlos = -int(log10(precx))/2
endif
if ( ier0-ier .gt. maxlos ) then
if ( itime .eq. 1 ) then
itime = 2
if ( ier0-ier .ge. 100 ) itime = 100
isgnal = -isgnal
goto 25
else
if ( ier0-ier .lt. 100 ) then
* it does not make any sense to go on, but do it anyway
elseif ( itime.eq.100 ) then
call fferr(72,ier)
cfac = 1
return
elseif ( itime.le.2 ) then
* the first try was better
isgnal = -isgnal
itime = 3
goto 25
endif
endif
endif
ier = ier0
* #] transform the masses and momenta:
* #[ calculations:
call ffxd0p(cs4,ipi12,isoort,cfac,xpip,dpipjp,piDpjp,
+ xqi,dqiqj,qiDqj,ai,daiaj,ldel2s,ier)
xfac = -ai(1)*ai(2)*ai(3)*ai(4)/dt3t4
*
* see the note at the end of this section about the sign
*
- if ( DIMAG(cfac) .eq. 0 ) then
- cfac = xfac/DBLE(cfac)
+ if ( Im(cfac) .eq. 0 ) then
+ cfac = xfac/Re(cfac)
else
- cfac = DBLE(xfac)/cfac
+ cfac = Re(xfac)/cfac
endif
*
* sum'em up:
*
cs3(1) = 0
cs3(2) = 0
xmax = 0
do 110 i=1,80
cs3(1) = cs3(1) + cs4(i)
xmax = max(xmax,absc(cs3(1)))
110 continue
do 111 i=81,160
cs3(2) = cs3(2) + cs4(i)
xmax = max(xmax,absc(cs3(2)))
111 continue
cs = cs3(1) - cs3(2)
do 112 i=161,175
cs = cs + cs4(i)
xmax = max(xmax,absc(cs))
112 continue
ipi123(1) = 0
ipi123(2) = 0
do 113 i=1,8
ipi123(1) = ipi123(1) + ipi12(i)
113 continue
do 114 i=9,16
ipi123(2) = ipi123(2) + ipi12(i)
114 continue
ipi12t = ipi123(1) - ipi123(2)
do 120 i=17,28
ipi12t = ipi12t + ipi12(i)
120 continue
- cs = cs + ipi12t*DBLE(pi12)
+ cs = cs + ipi12t*Re(pi12)
*
* If the imaginary part is very small it most likely is zero
* (can be removed, just esthetically more pleasing)
*
- if ( abs(DIMAG(cs)) .lt. precc*abs(DBLE(cs)) )
- + cs = DCMPLX(DBLE(cs))
+ if ( abs(Im(cs)) .lt. precc*abs(Re(cs)) )
+ + cs = ToComplex(Re(cs))
*
* it is much nicer to have the sign of cfac fixed, say positive
*
- if ( DBLE(cfac) .lt. 0 .or. (DBLE(cfac) .eq. 0 .and. DIMAG(cfac)
+ if ( Re(cfac) .lt. 0 .or. (Re(cfac) .eq. 0 .and. Im(cfac)
+ .lt. 0 ) ) then
cfac = -cfac
cs = -cs
endif
* #] calculations:
*###] ffxd0e:
end
*###[ ffxd0r:
subroutine ffxd0r(cd0,xpi,ier)
***#[*comment:***********************************************************
* *
* Tries all 12 permutations of the 4pointfunction *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
integer ier
- DOUBLE PRECISION xpi(13),xqi(13)
- DOUBLE COMPLEX cd0,cd0p
+ RealType xpi(13),xqi(13)
+ ComplexType cd0,cd0p
integer inew(13,6),irota,ier0,ier1,i,j,ialsav
save inew
#include "ff.h"
data inew /1,2,3,4,5,6,7,8,9,10,11,12,13,
+ 4,1,2,3,8,5,6,7,10,9,11,13,12,
+ 3,4,1,2,7,8,5,6,9,10,11,12,13,
+ 2,3,4,1,6,7,8,5,10,9,11,13,12,
+ 4,2,3,1,10,6,9,8,7,5,12,11,13,
+ 1,3,2,4,9,6,10,8,5,7,12,11,13/
* #] declarations:
* #[ calculations:
cd0 = 0
ier0 = ier
ier = 999
ialsav = isgnal
do 30 j = -1,1,2
do 20 irota=1,6
do 10 i=1,13
xqi(inew(i,irota)) = xpi(i)
10 continue
ier1 = ier0
ner = 0
id = id + 1
isgnal = ialsav
print '(a,i1,a,i2)','---#[ rotation ',irota,': isgnal ',
+ isgnal
call ffxd0(cd0p,xqi,ier1)
ier1 = ier1 + ner
print '(a,i1,a,i2,a)','---#] rotation ',irota,
+ ': isgnal ',isgnal,' '
print '(a,2g28.16,i3)','d0 = ',cd0p,ier1
if ( ier1 .lt. ier ) then
cd0 = cd0p
ier = ier1
endif
20 continue
ialsav = -ialsav
30 continue
* #] calculations:
*###] ffxd0r:
end
*###[ ffxd0d:
subroutine ffxd0d(cd0,xpi,piDpj,del3p,del4s,info,ier)
***#[*comment:***********************************************************
* *
* Entry point to the four point function with dotproducts given. *
* Necessary to avoid cancellations near the borders of phase *
* space. *
* *
* Input: xpi(13) real 1-4: mi^2, 5-10: pi^2,s,t *
* optional: 11:u, 12:v, 13:w *
* info integer 0: no extra info *
* 1: piDpj(i,j), i,j>4 is defined *
* 2: del3p is also defined *
* 3: all piDpj are given *
* 4: del4s is also given *
* piDpj(10,10) real pi.pj in B&D metric; *
* 1-4:si.sj=(m_i^2+m_j^2-p_ij^2)/2*
* cross: si.pjk=si.pj-si.pk *
* 5-10: pi.pj *
* del3p real det(pi.pj) *
* del4s real det(si.sj) (~square overall fac)*
* ier integer #digits accuracy lost in input *
* Output: cd0 complex D0 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer info,ier
- DOUBLE PRECISION xpi(13),piDpj(10,10),del3p,del4s
- DOUBLE COMPLEX cd0
+ RealType xpi(13),piDpj(10,10),del3p,del4s
+ ComplexType cd0
*
* local vars
*
integer i,j
*
* common blocks
*
#include "ff.h"
*
* #] declarations:
* #[ hide information in common blocks:
*
idot = info
if ( idot.ne.0 ) then
if ( idot.gt.0 .and. idot.le.2 ) then
do 20 i=5,10
do 10 j=5,10
fpij4(j,i) = piDpj(j,i)
10 continue
20 continue
elseif ( idot.ge.3 ) then
do 40 i=1,10
do 30 j=1,10
fpij4(j,i) = piDpj(j,i)
30 continue
40 continue
endif
if ( abs(idot).ge.2 ) then
fdel3 = del3p
endif
if ( abs(idot).ge.4 ) then
fdel4s = del4s
endif
endif
*
* #] hide information in common blocks:
* #[ call ffxd0:
*
call ffxd0(cd0,xpi,ier)
*
* invalidate all the common blocks for the next call
*
idot = 0
*
* #] call ffxd0:
*###] ffxd0d:
end
*###[ ffdif4:
subroutine ffdif4(dpipj,luvw,xpi)
***#[*comment:***********************************************************
* *
* Compute the elements 11-13 in xpi and the differences dpipj *
* Note that the digits lost in dpipj are not counted towards *
* the total. *
* *
* Input: xpi(1:10) real masses, momenta^2 *
* *
* Output: xpi(11:13) real u and similar vars v,w *
* luvw(3) logical TRUE if xpi(10+i) has *
* been computed here *
* dpipj(10,13) real xpi(i) - xpi(j) *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
logical luvw(3)
- DOUBLE PRECISION xpi(13),dpipj(10,13)
+ RealType xpi(13),dpipj(10,13)
*
* local variables
*
integer i,j
*
* common blocks
*
#include "ff.h"
*
* #] declarations:
* #[ get differences:
* simulate the differences in the masses etc..
if ( xpi(11) .eq. 0 ) then
xpi(11) = xpi(5)+xpi(6)+xpi(7)+xpi(8)-xpi(9)-xpi(10)
luvw(1) = .TRUE.
else
luvw(1) = .FALSE.
endif
if ( xpi(12) .eq. 0 ) then
xpi(12) = -xpi(5)+xpi(6)-xpi(7)+xpi(8)+xpi(9)+xpi(10)
luvw(2) = .TRUE.
else
luvw(2) = .FALSE.
endif
if ( xpi(13) .eq. 0 ) then
if ( max(abs(xpi(5)),abs(xpi(7))) .gt.
+ max(abs(xpi(9)),abs(xpi(10))) ) then
xpi(13) = -xpi(12) + 2*(xpi(9)+xpi(10))
else
xpi(13) = -xpi(11) + 2*(xpi(5)+xpi(7))
endif
* xpi(13) = xpi(5)-xpi(6)+xpi(7)-xpi(8)+xpi(9)+xpi(10)
luvw(3) = .TRUE.
else
luvw(3) = .FALSE.
endif
do 20 i=1,13
do 19 j=1,10
dpipj(j,i) = xpi(j) - xpi(i)
19 continue
20 continue
* #] get differences:
*###] ffdif4:
end
diff --git a/Looptools/D/ffxd0h.F b/Looptools/D/ffxd0h.F
--- a/Looptools/D/ffxd0h.F
+++ b/Looptools/D/ffxd0h.F
@@ -1,668 +1,669 @@
#include "externals.h"
+#include "types.h"
*--#[ log:
* $Id: ffxd0h.f,v 1.6 1996/01/22 13:33:49 gj Exp $
* $Log: ffxd0h.f,v $
c Revision 1.6 1996/01/22 13:33:49 gj
c Added the word 'error' to print statements in ffxuvw that u,v,w were wrong
c
c Revision 1.5 1995/12/08 10:48:32 gj
c Changed xloss to xlosn to prevent spurious error messages.
c
c Revision 1.4 1995/11/10 18:55:46 gj
c JUst added some comments in ffrot4
c
c Revision 1.3 1995/10/29 15:37:43 gj
c Revision 1.2 1995/10/17 06:55:13 gj
c Fixed ieps error in ffdcrr (ffcxs4.f), added real case in ffcrr, debugging
c info in ffxd0, and warned against remaining errors for del2=0 in ffrot4
c (ffxd0h.f)
c
*--#] log:
*###[ ffrot4:
subroutine ffrot4(irota,del2,xqi,dqiqj,qiDqj,xpi,dpipj,piDpj,ii,
+ itype,ier)
***#[*comment:***********************************************************
* *
* rotates the arrays xpi, dpipj into xqi,dqiqj over irota places *
* such that del2(s3,s4)<=0. itype=0 unless del2(s3,s4)=0 (itype=1)*
* itype=2 if the 4pointfunction is doubly IR-divergent *
* ((0,0,0)vertex) *
* *
* Input: xpi(13) real momenta squared *
* dpipj(10,13) real xpi(i) - xpi(j) *
* piDpj(10,10) real if ( ii>4) pi.pj *
* ii integer 4: from Do, 5: from E0 *
* Output: irota integer # of positions rotated + 1 *
* del2 real delta(s3,s4,s3,s4) chosen * *
* xqi,dqiqj,qiDqj real rotated (q->p) *
* itype integer 0:normal, -1:failure, 1:del2=0 *
* 2:doubly IR *
* ier integer usual error flag *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer irota,ier,ii,itype
- DOUBLE PRECISION del2,xpi(13),dpipj(10,13),piDpj(10,10),
+ RealType del2,xpi(13),dpipj(10,13),piDpj(10,10),
+ xqi(13),dqiqj(10,13),qiDqj(10,10)
*
* local variables
*
integer i,j,izero,ier0,init
- DOUBLE COMPLEX chulp(4,4)
+ ComplexType chulp(4,4)
save init
*
* common blocks
*
#include "ff.h"
*
* data
*
data init /0/
*
* #] declarations:
* #[ find out which del2 is negative: (or zero)
izero = 0
do 40 irota = 1,12
*
* first check if we have a doubly IR divergent diagram
*
if ( xpi(iold(3,irota)) .eq. 0 .and.
+ xpi(iold(4,irota)) .eq. 0 .and.
+ xpi(iold(7,irota)) .eq. 0 .and.
+ dpipj(iold(1,irota),iold(8,irota)) .eq. 0 .and.
+ dpipj(iold(2,irota),iold(6,irota)) .eq. 0 ) then
del2 = 0
goto 41
endif
*
* We can at this moment only handle s3^2 = 0
* (Hope to include two masses 0 later)
* I hope nothing goes wrong if we leave out:
* >xpi(iold(1,irota)) .eq. 0 .or.
* + xpi(iold(2,irota)) .eq. 0 .or.
* + <
* 'cause I can't see why it was included in the first place..
*
if ( xpi(iold(4,irota)) .eq. 0 ) goto 40
*
* Well, the combination s2=0, p6=s3, p10=s4 gives 1/A2=0 twice
*
if ( xpi(iold(2,irota)) .eq. 0 .and.
+ dpipj(iold( 6,irota),iold(3,irota)) .eq. 0 .and.
+ dpipj(iold(10,irota),iold(4,irota)) .eq. 0)
+ goto 40
*
* phenomenologically this combo also gives an infinite result
*
if ( xpi(iold(1,irota)) .eq. 0 .and.
+ xpi(iold(2,irota)) .eq. 0 .and.
+ dpipj(iold( 8,irota),iold(4,irota)) .eq. 0 .and.
+ dpipj(iold( 9,irota),iold(3,irota)) .eq. 0)
+ goto 40
*
* I just found out that this gives two times 1/A1 = 0
*
if ( xpi(iold(7,irota)) .eq. 0 .and.
+ dpipj(iold(9,irota),iold(3,irota))+
+ dpipj(iold(4,irota),iold(8,irota)) .eq. 0 )
+ goto 40
if ( xpi(iold(1,irota)) .eq. 0 .and.
+ dpipj(iold(9,irota),iold(3,irota)) .eq. 0 .and.
+ dpipj(iold(4,irota),iold(8,irota)) .eq. 0 .and.
+ .not.lnasty )
+ goto 40
*
* the nasty case wants xpi(1)=0, xpi(2) real:
*
if ( lnasty ) then
- if ( xpi(iold(1,irota)).ne.0 .or. DIMAG(
+ if ( xpi(iold(1,irota)).ne.0 .or. Im(
+ c2sisj(iold(1,irota),iold(2,irota))).ne.0 ) then
print *,'no good: nasty but s1!=0 or s2 not real'
goto 40
endif
endif
*
* all masses equal, three momenta zero:
* added by TH 24 Dec 09
*
#if 0
if( xpi(iold(5,irota)) .eq. 0 .and.
& xpi(iold(6,irota)) .eq. 0 .and.
& xpi(iold(7,irota)) .eq. 0 .and.
& abs(xpi(iold(1,irota)) - xpi(iold(2,irota))) +
& abs(xpi(iold(1,irota)) - xpi(iold(3,irota))) +
& abs(xpi(iold(1,irota)) - xpi(iold(4,irota)))
& .lt. precx ) then
itype = 3
return
endif
#endif
*
ier0 = 0
call ffxlam(del2,xpi,dpipj,10,
+ iold(3,irota),iold(4,irota),iold(7,irota))
*
* we can only handle del2=0 if p_i^2 = 0 (and thus m_i=m_{i+1})
*
if ( del2 .lt. 0 ) then
itype = 0
goto 50
endif
if ( del2 .eq. 0 .and. izero .eq. 0 .and. xpi(iold(7,irota))
+ .eq. 0 ) then
izero = irota
endif
40 continue
ier = ier + ier0
if ( izero .eq. 0 ) then
call fferr(54,ier)
itype = -1
irota = 1
else
irota = izero
del2 = 0
itype = 1
if ( init.lt.10 ) then
init = init + 1
print *,'ffrota: warning: the algorithms for del2=0 have not '
print *,' yet been tested thoroughly, and in fact are '
print *,' known to contain bugs.'
print *,' ==> DOUBLECHECK EVERYTHING WITH SMALL SPACELIKE p^2'
endif
endif
goto 50
41 continue
itype = 2
50 continue
* #] find out which del2 is negative:
* #[ rotate:
do 20 i=1,13
xqi(i) = xpi(iold(i,irota))
do 10 j=1,10
dqiqj(j,i) = dpipj(iold(j,irota),iold(i,irota))
10 continue
20 continue
if ( ii .eq. 5 ) then
do 120 i=1,10
do 110 j=1,10
qiDqj(j,i) = isgrot(iold(j,irota),irota)*
+ isgrot(iold(i,irota),irota)*
+ piDpj(iold(j,irota),iold(i,irota))
110 continue
120 continue
endif
if ( lsmug .or. lnasty ) then
do 220 j=1,4
do 210 i=1,4
chulp(i,j) = c2sisj(i,j)
210 continue
220 continue
do 240 j=1,4
do 230 i=1,4
c2sisj(i,j) = chulp(iold(i,irota),iold(j,irota))
230 continue
240 continue
endif
* #] rotate:
*###] ffrot4:
end
*###[ ffxlam:
subroutine ffxlam(xlam,xpi,dpipj,ns,i1,i2,i3)
*************************************************************************
* *
* calculate in a numerically stable way *
* xlam(xpi(i1),xpi(i2),xpi(i3)) = *
* = -((xpi(i1)+xpi(i2)-xpi(i3))/2)^2 + xpi(i1)*xpi(i2) *
* or a permutation *
* ier is the usual error flag. *
* *
*************************************************************************
implicit none
*
* arguments:
*
integer ns,i1,i2,i3
- DOUBLE PRECISION xlam,xpi(ns),dpipj(ns,ns)
+ RealType xlam,xpi(ns),dpipj(ns,ns)
*
* local variables
*
- DOUBLE PRECISION s1,s2
+ RealType s1,s2
*
* common blocks
*
#include "ff.h"
*
* calculations
*
if ( abs(xpi(i1)) .gt. max(abs(xpi(i2)),abs(xpi(i3))) ) then
s1 = xpi(i2)*xpi(i3)
if ( abs(dpipj(i1,i2)) .lt. abs(dpipj(i1,i3)) ) then
s2 = ((dpipj(i1,i2) - xpi(i3))/2)**2
else
s2 = ((dpipj(i1,i3) - xpi(i2))/2)**2
endif
elseif ( abs(xpi(i2)) .gt. abs(xpi(i3)) ) then
s1 = xpi(i1)*xpi(i3)
if ( abs(dpipj(i1,i2)) .lt. abs(dpipj(i2,i3)) ) then
s2 = ((dpipj(i1,i2) + xpi(i3))/2)**2
else
s2 = ((dpipj(i2,i3) - xpi(i1))/2)**2
endif
else
s1 = xpi(i1)*xpi(i2)
if ( abs(dpipj(i1,i3)) .lt. abs(dpipj(i2,i3)) ) then
s2 = ((dpipj(i1,i3) + xpi(i2))/2)**2
else
s2 = ((dpipj(i2,i3) + xpi(i1))/2)**2
endif
endif
xlam = s1 - s2
*###] ffxlam:
end
*###[ ffdot4:
subroutine ffdot4(piDpj,xpi,dpipj,ns,ier)
***#[*comment:***********************************************************
* *
* calculate the dotproducts pi.pj with *
* *
* pi = si i1=1,4 *
* pi = p(i-3) i1=5,10 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
integer ns,ier
- DOUBLE PRECISION xpi(13),dpipj(10,13),piDpj(10,10)
+ RealType xpi(13),dpipj(10,13),piDpj(10,10)
integer is1,is2,is3,ip1,ip2,ip3,i,j,ier0,ier1
- DOUBLE PRECISION xmax,som,xmxp
+ RealType xmax,som,xmxp
#include "ff.h"
* #] declarations:
* #[ check input:
if ( ns .ne. 10 ) print *,'ffdot4: error: ns <> 10 '
* #] check input:
* #[ special case: already known:
if ( idot.ge.3 ) then
do 2 i=1,10
do 1 j=1,10
piDpj(j,i) = isgrot(iold(j,irota4),irota4)*
+ isgrot(iold(i,irota4),irota4)*
+ fpij4(iold(j,irota4),iold(i,irota4))
1 continue
2 continue
return
endif
* #] special case: already known:
* #[ indices:
ier1 = ier
do 10 is1=1,4
is2 = is1 + 1
if ( is2 .eq. 5 ) is2 = 1
is3 = is2 + 1
if ( is3 .eq. 5 ) is3 = 1
ip1 = is1 + 4
ip2 = is2 + 4
if ( mod(is1,2) .eq. 1 ) then
ip3 = 9
else
ip3 = 10
endif
* #] indices:
* #[ all in one vertex:
*
* pi.pj, si.sj
*
piDpj(is1,is1) = xpi(is1)
piDpj(ip1,ip1) = xpi(ip1)
*
* si.s(i+1)
*
if ( xpi(is2) .le. xpi(is1) ) then
piDpj(is1,is2) = (dpipj(is1,ip1) + xpi(is2))/2
else
piDpj(is1,is2) = (dpipj(is2,ip1) + xpi(is1))/2
endif
piDpj(is2,is1) = piDpj(is1,is2)
ier0 = ier
ier1 = max(ier1,ier0)
*
* si.s(i+2)
*
if ( is1 .le. 2 ) then
if ( xpi(is1) .le. xpi(is3) ) then
piDpj(is3,is1) = (dpipj(is3,ip3) + xpi(is1))/2
else
piDpj(is3,is1) = (dpipj(is1,ip3) + xpi(is3))/2
endif
piDpj(is1,is3) = piDpj(is3,is1)
ier0 = ier
ier1 = max(ier1,ier0)
endif
*
* pi.si
*
if ( abs(xpi(ip1)) .le. xpi(is1) ) then
piDpj(ip1,is1) = (dpipj(is2,is1) - xpi(ip1))/2
else
piDpj(ip1,is1) = (dpipj(is2,ip1) - xpi(is1))/2
endif
piDpj(is1,ip1) = piDpj(ip1,is1)
ier0 = ier
ier1 = max(ier1,ier0)
*
* pi.s(i+1)
*
if ( abs(xpi(ip1)) .le. xpi(is2) ) then
piDpj(ip1,is2) = (dpipj(is2,is1) + xpi(ip1))/2
else
piDpj(ip1,is2) = (dpipj(ip1,is1) + xpi(is2))/2
endif
piDpj(is2,ip1) = piDpj(ip1,is2)
ier0 = ier
ier1 = max(ier1,ier0)
*
* p(i+2).s(i)
*
if ( abs(xpi(ip3)) .le. xpi(is1) ) then
piDpj(ip3,is1) = (dpipj(is1,is3) + xpi(ip3))/2
else
piDpj(ip3,is1) = (dpipj(ip3,is3) + xpi(is1))/2
endif
if ( is1 .eq. 2 .or. is1 .eq. 3 )
+ piDpj(ip3,is1) = -piDpj(ip3,is1)
piDpj(is1,ip3) = piDpj(ip3,is1)
ier0 = ier
ier1 = max(ier1,ier0)
*
* #] all in one vertex:
* #[ all in one 3point:
*
* pi.s(i+2)
*
if ( min(abs(dpipj(is2,is1)),abs(dpipj(ip3,ip2))) .le.
+ min(abs(dpipj(ip3,is1)),abs(dpipj(is2,ip2))) ) then
piDpj(ip1,is3) = (dpipj(ip3,ip2) + dpipj(is2,is1))/2
else
piDpj(ip1,is3) = (dpipj(ip3,is1) + dpipj(is2,ip2))/2
endif
piDpj(is3,ip1) = piDpj(ip1,is3)
ier0 = ier
ier1 = max(ier1,ier0)
*
* p(i+1).s(i)
*
if ( min(abs(dpipj(is3,is2)),abs(dpipj(ip1,ip3))) .le.
+ min(abs(dpipj(ip1,is2)),abs(dpipj(is3,ip3))) ) then
piDpj(ip2,is1) = (dpipj(ip1,ip3) + dpipj(is3,is2))/2
else
piDpj(ip2,is1) = (dpipj(ip1,is2) + dpipj(is3,ip3))/2
endif
piDpj(is1,ip2) = piDpj(ip2,is1)
ier0 = ier
ier1 = max(ier1,ier0)
*
* p(i+2).s(i+1)
*
if ( min(abs(dpipj(is1,is3)),abs(dpipj(ip2,ip1))) .le.
+ min(abs(dpipj(ip2,is3)),abs(dpipj(is1,ip1))) ) then
piDpj(ip3,is2) = (dpipj(ip2,ip1) + dpipj(is1,is3))/2
else
piDpj(ip3,is2) = (dpipj(ip2,is3) + dpipj(is1,ip1))/2
endif
if ( is1 .eq. 2 .or. is1 .eq. 3 )
+ piDpj(ip3,is2) = -piDpj(ip3,is2)
piDpj(is2,ip3) = piDpj(ip3,is2)
ier0 = ier
ier1 = max(ier1,ier0)
*
* #] all in one 3point:
* #[ all external 3point:
if ( idot.le.0 ) then
*
* pi.p(i+1)
*
if ( abs(xpi(ip2)) .le. abs(xpi(ip1)) ) then
piDpj(ip1,ip2) = (dpipj(ip3,ip1) - xpi(ip2))/2
else
piDpj(ip1,ip2) = (dpipj(ip3,ip2) - xpi(ip1))/2
endif
piDpj(ip2,ip1) = piDpj(ip1,ip2)
ier0 = ier
ier1 = max(ier1,ier0)
*
* p(i+1).p(i+2)
*
if ( abs(xpi(ip3)) .le. abs(xpi(ip2)) ) then
piDpj(ip2,ip3) = (dpipj(ip1,ip2) - xpi(ip3))/2
else
piDpj(ip2,ip3) = (dpipj(ip1,ip3) - xpi(ip2))/2
endif
if ( is1 .eq. 2 .or. is1 .eq. 3 )
+ piDpj(ip2,ip3) = -piDpj(ip2,ip3)
piDpj(ip3,ip2) = piDpj(ip2,ip3)
ier0 = ier
ier1 = max(ier1,ier0)
*
* p(i+2).p(i)
*
if ( abs(xpi(ip1)) .le. abs(xpi(ip3)) ) then
piDpj(ip3,ip1) = (dpipj(ip2,ip3) - xpi(ip1))/2
else
piDpj(ip3,ip1) = (dpipj(ip2,ip1) - xpi(ip3))/2
endif
if ( is1 .eq. 2 .or. is1 .eq. 3 )
+ piDpj(ip3,ip1) = -piDpj(ip3,ip1)
piDpj(ip1,ip3) = piDpj(ip3,ip1)
ier0 = ier
ier1 = max(ier1,ier0)
*
else
*
* idot > 0: copy the dotproducts from fpij4
*
piDpj(ip1,ip2) = isgrot(iold(ip1,irota4),irota4)*
+ isgrot(iold(ip2,irota4),irota4)*
+ fpij4(iold(ip1,irota4),iold(ip2,irota4))
piDpj(ip2,ip1) = piDpj(ip1,ip2)
piDpj(ip1,ip3) = isgrot(iold(ip1,irota4),irota4)*
+ isgrot(iold(ip3,irota4),irota4)*
+ fpij4(iold(ip1,irota4),iold(ip3,irota4))
piDpj(ip3,ip1) = piDpj(ip1,ip3)
piDpj(ip2,ip3) = isgrot(iold(ip2,irota4),irota4)*
+ isgrot(iold(ip3,irota4),irota4)*
+ fpij4(iold(ip2,irota4),iold(ip3,irota4))
piDpj(ip3,ip2) = piDpj(ip2,ip3)
endif
10 continue
* #] all external 3point:
* #[ real 4point:
*
* the awkward 4point dotproducts:
*
piDpj(9,9) = xpi(9)
piDpj(10,10) = xpi(10)
if ( idot.le.0 ) then
*--#[ p5.p7:
if ( abs(xpi(7)) .lt. abs(xpi(5)) ) then
piDpj(5,7) = (-xpi(7) - dpipj(5,11))/2
else
piDpj(5,7) = (-xpi(5) - dpipj(7,11))/2
endif
xmax = min(abs(xpi(5)),abs(xpi(7)))
if ( abs(piDpj(5,7)) .lt. xloss*xmax ) then
*
* second try (old algorithm)
*
if ( min(abs(dpipj(6,9)),abs(dpipj(8,10))) .le.
+ min(abs(dpipj(8,9)),abs(dpipj(6,10))) ) then
som = (dpipj(6,9) + dpipj(8,10))/2
else
som = (dpipj(8,9) + dpipj(6,10))/2
endif
xmxp = min(abs(dpipj(6,9)),abs(dpipj(8,9)))
if ( xmxp.lt.xmax ) then
piDpj(5,7) = som
xmax = xmxp
endif
ier0 = ier
ier1 = max(ier1,ier0)
endif
piDpj(7,5) = piDpj(5,7)
*--#] p5.p7:
*--#[ p6.p8:
if ( abs(xpi(6)) .lt. abs(xpi(8)) ) then
piDpj(6,8) = (-xpi(6) - dpipj(8,11))/2
else
piDpj(6,8) = (-xpi(8) - dpipj(6,11))/2
endif
xmax = min(abs(xpi(6)),abs(xpi(8)))
if ( abs(piDpj(6,8)) .lt. xloss*xmax ) then
*
* second try (old algorithm)
*
if ( min(abs(dpipj(5,9)),abs(dpipj(7,10))) .le.
+ min(abs(dpipj(7,9)),abs(dpipj(5,10))) ) then
som = (dpipj(5,9) + dpipj(7,10))/2
else
som = (dpipj(7,9) + dpipj(5,10))/2
endif
xmxp = min(abs(dpipj(5,9)),abs(dpipj(7,9)))
if ( xmxp.lt.xmax ) then
piDpj(6,8) = som
xmax = xmxp
endif
ier0 = ier
ier1 = max(ier1,ier0)
endif
piDpj(8,6) = piDpj(6,8)
*--#] p6.p8:
*--#[ p9.p10:
if ( abs(xpi(9)) .lt. abs(xpi(10)) ) then
piDpj(9,10) = (-xpi(9) - dpipj(10,13))/2
else
piDpj(9,10) = (-xpi(10) - dpipj(9,13))/2
endif
xmax = min(abs(xpi(9)),abs(xpi(10)))
if ( abs(piDpj(9,10)) .lt. xloss*xmax ) then
*
* second try (old algorithm)
*
if ( min(abs(dpipj(5,6)),abs(dpipj(7,8))) .le.
+ min(abs(dpipj(7,6)),abs(dpipj(5,8))) ) then
som = (dpipj(5,6) + dpipj(7,8))/2
else
som = (dpipj(7,6) + dpipj(5,8))/2
endif
xmxp = min(abs(dpipj(5,6)),abs(dpipj(7,6)))
if ( xmxp.lt.xmax ) then
piDpj(9,10) = som
xmax = xmxp
endif
ier0 = ier
ier1 = max(ier1,ier0)
endif
piDpj(10,9) = piDpj(9,10)
*--#] p9.p10:
else
*--#[ copy:
*
* idot > 1: just copy from fpij4...
*
piDpj(5,7) = isgrot(iold(5,irota4),irota4)*
+ isgrot(iold(7,irota4),irota4)*
+ fpij4(iold(5,irota4),iold(7,irota4))
piDpj(7,5) = piDpj(5,7)
piDpj(6,8) = isgrot(iold(6,irota4),irota4)*
+ isgrot(iold(8,irota4),irota4)*
+ fpij4(iold(6,irota4),iold(8,irota4))
piDpj(8,6) = piDpj(6,8)
piDpj(9,10)= isgrot(iold(9,irota4),irota4)*
+ isgrot(iold(10,irota4),irota4)*
+ fpij4(iold(9,irota4),iold(10,irota4))
piDpj(10,9) = piDpj(9,10)
*--#] copy:
endif
ier = ier1
* #] real 4point:
*###] ffdot4:
end
*###[ ffgdt4:
subroutine ffgdt4(piDpj,xpip,dpipjp,xpi,ier)
***#[*comment:***********************************************************
* *
* calculate the dotproducts pi.pj with *
* and store results in common when asked for *
* *
* pi = si i1=1,4 *
* pi = p(i-3) i1=5,10 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE PRECISION piDpj(10,10),xpip(13),dpipjp(10,13),xpi(13)
+ RealType piDpj(10,10),xpip(13),dpipjp(10,13),xpi(13)
integer ier
*
* local variables
*
integer i,j,ii(6)
- DOUBLE PRECISION dl3p
+ RealType dl3p
*
* common blocks:
*
#include "ff.h"
*
* #] declarations:
* #[ get dotproducts:
*
* Calculate the dotproducts
*
call ffdot4(piDpj,xpip,dpipjp,10,ier)
if ( ldot .and. idot.lt.3 ) then
do 65 i=1,10
do 64 j=1,10
fpij4(iold(j,irota4),iold(i,irota4)) =
+ isgrot(iold(j,irota4),irota4)*
+ isgrot(iold(i,irota4),irota4)*piDpj(j,i)
64 continue
65 continue
endif
if ( ldot ) then
if ( abs(idot).lt.2 ) then
ii(1)= 5
ii(2)= 6
ii(3)= 7
ii(4)= 8
ii(5)= 9
ii(6)= 10
fidel3 = ier
call ffdl3p(dl3p,piDpj,10,ii,ii)
fdel3 = dl3p
else
dl3p = fdel3
endif
if ( dl3p .lt. 0 ) then
call fferr(44,ier)
print *,'overall vertex has del3 ',dl3p
print *,'xpi = ',xpi
endif
endif
* #] get dotproducts:
*###] ffgdt4:
end
diff --git a/Looptools/D/ffxd0i.F b/Looptools/D/ffxd0i.F
--- a/Looptools/D/ffxd0i.F
+++ b/Looptools/D/ffxd0i.F
@@ -1,162 +1,163 @@
#include "externals.h"
+#include "types.h"
*###[ ffx2ir:
subroutine ffx2ir(cs1,cs2,xpip,dpipjp,ier)
***#[*comment:***********************************************************
* *
* Get the terms to correct for the second IR pole which is *
* treated incorrectly if the first one is regulated with a small *
* mass lam and they are adjacent. It is assumed that xpi(3)= *
* xpi(4)=xpi(7)=0, xpi(1)=xpi(8), xpi(2)=xpi(6). The correction *
* terms are *
* *
* cs1 = -C0(m2^2,0,lam^2;m2^2,0,p10^2)/(s-m1^2) *
* cs2 = +C0(m2^2,lam^2,0;m2^2,0,p10^2)/(s-m1^2) *
* *
* when xpi(4) = lambda is taken in the D0, *
* *
* cs1 = -C0(lam^2,0,m1^2;0,m1^2,p9^2)/(t-m2^2) *
* cs2 = +C0(0,lam^2,m1^2;0,m1^2,p9^2)/(t-m2^2) *
* *
* when xpi(3) = lambda. Not yet tested. *
* *
* 10-oct-1991 Geert Jan van Oldenborgh *
* *
* Input: xpip(13) (real) usual 4point pi.pi *
* dpipjp(10,13) (real) xpip(i) - xpip(j) *
* output: xpip(13) (real) usual 4point pi.pi modified *
* dpipjp(10,13) (real) xpip(i) - xpip(j) modified *
* cs1,cs2 (complex) *
* ier (integer) *
* calls: ffxc0 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE COMPLEX cs1,cs2
- DOUBLE PRECISION xpip(13),dpipjp(10,13)
+ ComplexType cs1,cs2
+ RealType xpip(13),dpipjp(10,13)
*
* local vars
*
integer itest,ier0,ier1,i,j,iinx(6,4)
- DOUBLE COMPLEX cc0
- DOUBLE PRECISION xpi3(6),dpipj3(6,6)
+ ComplexType cc0
+ RealType xpi3(6),dpipj3(6,6)
save itest,iinx
*
* common
*
#include "ff.h"
*
* data
*
* 3=put mass on xpi(3)
* 4=put mass on xpi(4)
data itest /4/
data iinx /2,3,4,6,7,10,
+ 1,3,4,9,7,8,
+ 1,2,4,5,10,8,
+ 1,2,3,5,6,9/
*
* #] declarations:
* #[ work 3:
if ( itest .eq. 3 ) then
*
* modify xpip,dpipjp
*
xpip(3) = lambda
do 10 i=1,10
dpipjp(i,3) = dpipjp(i,3) - lambda
10 continue
do 20 i=1,13
dpipjp(3,i) = dpipjp(3,i) + lambda
20 continue
*
* call first C0
*
do 120 i=1,6
xpi3(i) = xpip(iinx(i,2))
do 110 j=1,6
dpipj3(j,i) = dpipjp(iinx(j,2),iinx(i,2))
110 continue
120 continue
idsub = idsub + 1
ier1 = 0
call ffxc0a(cc0,xpi3,dpipj3,ier1)
- cs1 = -cc0/DBLE(dpipjp(9,2))
+ cs1 = -cc0/Re(dpipjp(9,2))
*
* call second C0
*
xpi3(2) = 0
xpi3(3) = lambda
do 130 i=1,6
dpipj3(i,2) = dpipj3(i,2) + lambda
dpipj3(i,3) = dpipj3(i,3) - lambda
130 continue
do 140 i=1,6
dpipj3(2,i) = dpipj3(2,i) - lambda
dpipj3(3,i) = dpipj3(3,i) + lambda
140 continue
idsub = idsub + 1
ier0 = 0
call ffxc0a(cc0,xpi3,dpipj3,ier0)
- cs2 = +cc0/DBLE(dpipjp(9,2))
+ cs2 = +cc0/Re(dpipjp(9,2))
ier1 = max(ier1,ier0)
ier = ier + ier1
* #] work 3:
* #[ work 4:
elseif ( itest .eq. 4 ) then
*
* modify xpip,dpipjp
*
xpip(4) = lambda
do 210 i=1,10
dpipjp(i,4) = dpipjp(i,4) - lambda
210 continue
do 220 i=1,13
dpipjp(4,i) = dpipjp(4,i) + lambda
220 continue
*
* call first C0
*
do 320 i=1,6
xpi3(i) = xpip(iinx(i,1))
do 310 j=1,6
dpipj3(j,i) = dpipjp(iinx(j,1),iinx(i,1))
310 continue
320 continue
idsub = idsub + 1
ier1 = 0
call ffxc0a(cc0,xpi3,dpipj3,ier1)
- cs1 = -cc0/DBLE(dpipjp(10,1))
+ cs1 = -cc0/Re(dpipjp(10,1))
*
* call second C0
*
xpi3(3) = 0
xpi3(2) = lambda
do 330 i=1,6
dpipj3(i,3) = dpipj3(i,3) + lambda
dpipj3(i,2) = dpipj3(i,2) - lambda
330 continue
do 340 i=1,6
dpipj3(3,i) = dpipj3(3,i) - lambda
dpipj3(2,i) = dpipj3(2,i) + lambda
340 continue
idsub = idsub + 1
ier0 = 0
call ffxc0a(cc0,xpi3,dpipj3,ier0)
- cs2 = +cc0/DBLE(dpipjp(10,1))
+ cs2 = +cc0/Re(dpipjp(10,1))
ier1 = max(ier1,ier0)
ier = ier + ier1
* #] work 4:
* #[ error:
else
print *,'ffx2ir: error: itest should be either 3 or 4!',itest
endif
* #] error:
*###] ffx2ir:
end
diff --git a/Looptools/D/ffxd0m0.F b/Looptools/D/ffxd0m0.F
--- a/Looptools/D/ffxd0m0.F
+++ b/Looptools/D/ffxd0m0.F
@@ -1,73 +1,74 @@
#include "externals.h"
+#include "types.h"
*###[ ffxd0m0:
subroutine ffxd0m0(cd0, xpi, ier)
***#[*comment:***********************************************************
* *
* D0 function for 4 masses = 0 *
* input parameters as for ffxd0 *
* *
* algorithm taken from *
* Denner, Nierste, Scharf, Nucl. Phys. B367 (1991) 637-656 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE PRECISION xpi(13)
- DOUBLE COMPLEX cd0
+ RealType xpi(13)
+ ComplexType cd0
integer ier
- DOUBLE PRECISION a, b, c, d
- DOUBLE COMPLEX x(2), z(2), k1, k2, t1, t2
- DOUBLE COMPLEX dl1, dl2, zl, ww, tlg
- DOUBLE COMPLEX k12, k23, k34, k14, k13, k24
+ RealType a, b, c, d
+ ComplexType x(2), z(2), k1, k2, t1, t2
+ ComplexType dl1, dl2, zl, ww, tlg
+ ComplexType k12, k23, k34, k14, k13, k24
integer j, ipi1(2), ipi2(2), nffeta
#include "ff.h"
a = xpi(10)*xpi(7)
b = xpi(9)*xpi(10) + xpi(5)*xpi(7) - xpi(8)*xpi(6)
c = xpi(5)*xpi(9)
d = -xpi(6)
- k1 = DCMPLX(c, precx*d)
+ k1 = ToComplex(c, precx*d)
k2 = sqrt(b*b - 4*a*k1)
x(1) = (-b - k2)/2D0/a
x(2) = (-b + k2)/2D0/a
if( abs(x(1)) .gt. abs(x(2)) ) then
x(2) = k1/(a*x(1))
else
x(1) = k1/(a*x(2))
endif
- k12 = DCMPLX(-xpi(5), -precx)
- k13 = DCMPLX(-xpi(9), -precx)
- k23 = DCMPLX(-xpi(6), -precx)
- k34 = DCMPLX(-xpi(7), -precx)
- k14 = DCMPLX(-xpi(8), -precx)
- k24 = DCMPLX(-xpi(10), -precx)
+ k12 = ToComplex(-xpi(5), -precx)
+ k13 = ToComplex(-xpi(9), -precx)
+ k23 = ToComplex(-xpi(6), -precx)
+ k34 = ToComplex(-xpi(7), -precx)
+ k14 = ToComplex(-xpi(8), -precx)
+ k24 = ToComplex(-xpi(10), -precx)
k1 = k34/k13
k2 = k24/k12
ww = log(k12) + log(k13) - log(k14) - log(k23)
do 100 j = 1, 2
t1 = 1 + k1*x(j)
t2 = 1 + k2*x(j)
call ffzzdl(dl1, ipi1(j), zl, t1, ier)
call ffzzdl(dl2, ipi2(j), zl, t2, ier)
tlg = log(-x(j))
z(j) = tlg*(ww - .5D0*tlg) - dl1 - dl2 -
+ c2ipi*( nffeta(-x(j), k1, ier)*log(t1) +
+ nffeta(-x(j), k2, ier)*log(t2) )
100 continue
ww = z(2) - z(1) +
+ (ipi1(1) + ipi2(1) - ipi1(2) - ipi2(2))*pi12
cd0 = ww/(a*(x(1) - x(2)))
end
diff --git a/Looptools/D/ffxd0p.F b/Looptools/D/ffxd0p.F
--- a/Looptools/D/ffxd0p.F
+++ b/Looptools/D/ffxd0p.F
@@ -1,677 +1,678 @@
#include "externals.h"
+#include "types.h"
*(##[ ffxd0p:
subroutine ffxd0p(cs4,ipi12,isoort,cfac,xpi,dpipj,piDpj,
+ xqi,dqiqj,qiDqj,ai,daiaj,ldel2s,ier)
***#[*comment:***********************************************************
* *
* calculate D0/pi^2/(A1*A2*A3*A4/dt3t4) *
* *
* = C0(t1,t2,t3) - C0(t1,t2,t4) *
* *
* The transformed momenta of the fourpoint functions are *
* input. *
* *
* Input: xpi(10) untransformed fourpoint momenta *
* dpipj(10,10) differences of xpi *
* piDpj(10,10) dotproducts of xpi *
* xqi(10) transformed fourpoint momenta *
* dqiqj(10,10) differences of xqi *
* qiDqj(10,10) dotproducts of xqi *
* ai(4) the transformation parameters *
* daiaj(4,4) their deifferences *
* ldel2s if .TRUE. we took out factors delta *
* *
* Output: cs4(170) not added (assumed 0 on input) *
* cfac the factor of cs4 from C0 (ie lam(pi)) *
* ier 0=ok 1=inaccurate 2=error *
* *
* Calls: ffxc0p,ffpi34,ffxhck,ffdl3m,ffdel2,... *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE COMPLEX cs4(175),cfac
+ ComplexType cs4(175),cfac
integer ipi12(28),isoort(16),ier
logical ldel2s
- DOUBLE PRECISION xpi(10),dpipj(10,10),piDpj(10,10),
+ RealType xpi(10),dpipj(10,10),piDpj(10,10),
+ xqi(10),dqiqj(10,10),qiDqj(10,10),ai(4),daiaj(4,4)
*
* local variables
*
integer i,j,k,ip,jp,m,ilogi(6),ii(6,2),jj(6,2),ier0,ier1
- DOUBLE COMPLEX c,clogi(6),cipi
- DOUBLE PRECISION xpi3(6,3:4),dpipj3(6,6,3:4),piDpj3(6,6,3:4),
+ ComplexType c,clogi(6),cipi
+ RealType xpi3(6,3:4),dpipj3(6,6,3:4),piDpj3(6,6,3:4),
+ del2,del2s(3,3:4),del3(3:4),del3mi(6,3:4),
+ del4,etalam(3:4),etami(6,3:4),ddel2s(2:3),delpsi(3,3:4),
+ alph(3),blph(3),sdel2,hulp,som,s(4),smax,xmax
- DOUBLE COMPLEX cpi(6,3:4),cpiDpj(6,6,3:4),cdpipj(6,6,3:4),
+ ComplexType cpi(6,3:4),cpiDpj(6,6,3:4),cdpipj(6,6,3:4),
+ cetalm(3:4),cetami(6,3:4),calph(3),csdel2,
+ cel2s(3,3:4),celpsi(3,3:4),zqi(10),zqiDqj(10,10),
+ cddl2s(2:3)
logical lcroot
save ii,jj
*
* common blocks:
*
#include "ff.h"
*
* data
*
data ii/1,2,3,5,6,9,1,2,3,5,6,9/
data jj/1,2,4,5,10,8,1,2,4,5,10,8/
*
* #] declarations:
* #[ preparation:
* Note that the piDpj3(,,3) contain now the threepoint function
* with s3, (,,4) with s4 (and NOT *without* as before)
call ffpi43(xpi3(1,3),dpipj3(1,1,3),piDpj3(1,1,3),
+ xqi,dqiqj,qiDqj,7-3)
call ffpi43(xpi3(1,4),dpipj3(1,1,4),piDpj3(1,1,4),
+ xqi,dqiqj,qiDqj,7-4)
*
* set the logarithms to be calculated to -999
*
do 40 i=1,6
clogi(i) = 0
ilogi(i) = 0
40 continue
if ( ai(1) .lt. 0 .neqv. ai(2) .lt. 0 ) then
ilogi(1) = -999
ilogi(4) = -999
endif
if ( ai(2) .lt. 0 .neqv. ai(3) .lt. 0 ) then
ilogi(2) = -999
endif
if ( ai(3) .lt. 0 .neqv. ai(1) .lt. 0 ) then
ilogi(3) = -999
endif
if ( ai(2) .lt. 0 .neqv. ai(4) .lt. 0 ) then
ilogi(5) = -999
endif
if ( ai(4) .lt. 0 .neqv. ai(1) .lt. 0 ) then
ilogi(6) = -999
endif
*
* #] preparation:
* #[ determinants:
*
* some determinants
*
* note that not all errors are additive, only when a previous
* result is used as input do we need to add ther ier's, otherwise
* we can take the maximum value to get a decent estimate of the
* number of digits lost.
*
ier1 = ier
if ( .not.ldel2s ) then
ier0 = ier
call ffdel2(del2,qiDqj,10, 5,6,9, 0,ier0)
ier1 = max(ier1,ier0)
else
s(1) = xqi(5)*xqi(3)
s(2) = qiDqj(5,3)**2
del2 = s(1) - s(2)
if ( abs(del2) .lt. xloss*s(2) ) ier1 = 100
endif
if ( ier1 .ne. ier ) then
ier0 = ier
call ffdel4(del4,piDpj)
if ( ldel2s ) then
hulp = -(ai(1)*ai(2)*ai(3)*ai(4)/xqi(3))**2 * del4
else
hulp = -(2*ai(1)*ai(2)*ai(3)*ai(4)/dqiqj(3,4))**2 * del4
endif
del2 = hulp
ier1 = ier0
fdel4s = del4
else
if ( ldel2s ) then
fdel4s = -del2*(xqi(3)/ai(1)*ai(2)*ai(3)*ai(4))**2
else
fdel4s=-del2*(dqiqj(3,4)/(2*ai(1)*ai(2)*ai(3)*ai(4)))**2
endif
endif
if ( del2 .gt. 0 ) then
* use complex routines
* call fferr(44,ier)
lcroot = .TRUE.
sdel2 = isgnal*sqrt(del2)
- csdel2 = DCMPLX(0D0,sdel2)
+ csdel2 = ToComplex(0D0,sdel2)
elseif ( del2 .eq. 0 ) then
call fferr(45,ier)
else
lcroot = .FALSE.
sdel2 = isgnal*sqrt(-del2)
endif
ier0 = ier
call ffdl3s(del3(3),piDpj,ii,10)
ier1 = max(ier0,ier1)
ier0 = ier
call ffdl3s(del3(4),piDpj,jj,10)
ier1 = max(ier1,ier0)
del3(3) = ai(1)**2*ai(2)**2*ai(3)**2*del3(3)
del3(4) = ai(1)**2*ai(2)**2*ai(4)**2*del3(4)
do 108 m=3,4
ier0 = ier
if ( .not.ldel2s ) then
call ffdl3m(del3mi(1,m),.TRUE.,del3(m),del2,xpi3(1,m)
+ ,dpipj3(1,1,m),piDpj3(1,1,m), 6, 4,5,6,1,3)
else
*
* the special case del2s = 0. Note that del3mi(i) and
* del3mi(i+3) are used in S_{i-1}.
*
call ffdl3m(del3mi(1,m),.FALSE.,0D0,0D0,xpi3(1,m),
+ dpipj3(1,1,m),piDpj3(1,1,m), 6, 4,3,0, 1,2)
ier1= max(ier1,ier0)
ier0 = ier
call ffdl3m(del3mi(5,m),.FALSE.,0D0,0D0,xpi3(1,m),
+ dpipj3(1,1,m),piDpj3(1,1,m), 6, 4,3,0, 5,2)
del3mi(3,m) = 0
del3mi(4,m) = 0
endif
ier1 = max(ier1,ier0)
do 105 i=1,3
j = i+1
if ( j .eq. 4 ) j = 1
ip = i
jp = j
if ( m .eq. 4 ) then
if ( jp .eq. 3 ) jp = 4
if ( ip .eq. 3 ) ip = 4
endif
if ( i.eq.1 .and. m.eq.4 ) then
del2s(1,4) = del2s(1,3)
else
ier0 = ier
call ffdel2(del2s(i,m),piDpj,10,inx(ip,jp),ip,
+ jp,1,ier0)
del2s(i,m) = ai(ip)**2*ai(jp)**2*del2s(i,m)
ier1 = max(ier1,ier0)
endif
k = i-1
if ( k .eq. 0 ) k = 3
ier0 = ier
if ( .not.ldel2s ) then
call ffdl2p(delpsi(i,m),xpi3(1,m),dpipj3(1,1,m),
+ piDpj3(1,1,m),i+3,j+3,k+3,i,j,k,6)
else
call ffdl2t(delpsi(i,m),qiDqj, m,5, ip,jp,inx(ip,jp)
+ ,+1,+1, 10)
endif
ier1 = max(ier1,ier0)
etami(i,m) = del3mi(i,m)/del2
if ( ldel2s .and. i.gt.1 )
+ etami(i+3,m) = del3mi(i+3,m)/del2
105 continue
etalam(m) = del3(m)/del2
108 continue
*
* the error analysis
*
ier = ier1
*
* get alpha,1-alpha
*
if ( .not. lcroot ) then
if ( .not.ldel2s ) then
if ( xpi3(5,3).eq.0 .and. (piDpj3(5,6,3).gt.0 .eqv.
+ sdel2.gt.0) ) then
alph(1) = -xpi3(6,3)/(piDpj3(5,6,3)+sdel2)
alph(3) = -xpi3(4,3)/(piDpj3(5,4,3)-sdel2)
else
call ffroot(blph(1),alph(1),xpi3(5,3),
+ -piDpj3(5,6,3),xpi3(6,3),sdel2,ier)
call ffroot(alph(3),blph(3),xpi3(5,3),
+ -piDpj3(5,4,3),xpi3(4,3),sdel2,ier)
endif
* We cannot change the sign as it is fixed by the choice
* of sign in fftrans (sqrt(delta(s3,s4))) WRONG
* if ( l4also .and. ( alph(1) .gt. 1 .or. alph(1) .lt. 0
* + ) .and. abs(blph(1)-.5D0) .lt. abs(alph(1)-.5D0) ) then
* alph(1) = blph(1)
* alph(3) = blph(3)
* sdel2 = -sdel2
* isgnal = -isgnal
* endif
else
alph(1) = 1
alph(3) = 0
endif
cfac = 2*sdel2
else
do 4 k=3,4
do 3 i=1,6
cpi(i,k) = xpi3(i,k)
do 2 j=1,6
cdpipj(j,i,k) = dpipj3(j,i,k)
cpiDpj(j,i,k) = piDpj3(j,i,k)
2 continue
3 continue
4 continue
if ( .not.ldel2s ) then
call ffcoot(c,calph(1),cpi(5,3),-cpiDpj(5,6,3),
+ cpi(6,3),csdel2,ier)
call ffcoot(calph(3),c,cpi(5,3),-cpiDpj(5,4,3),
+ cpi(4,3),csdel2,ier)
else
calph(1) = 1
calph(3) = 0
endif
cfac = 2*csdel2
endif
* #] determinants:
* #[ convert to complex:
if ( lcroot ) then
do 110 k=3,4
cetalm(k) = etalam(k)
do 109 i=1,3
cel2s(i,k) = del2s(i,k)
celpsi(i,k) = delpsi(i,k)
cetami(i,k) = etami(i,k)
109 continue
110 continue
endif
* #] convert to complex:
* #[ simple case:
if ( ldel2s .or. abs(dqiqj(3,4)) .lt. xloss*abs(xqi(3)) ) then
if ( .not.lsmug .and. (ldel2s .or. ldc3c4) ) goto 500
endif
*
* and the calculations
*
ier0 = ier
ier1 = ier
if ( lcroot ) then
call ffcc0p(cs4( 1),ipi12(1),isoort(1),clogi(1),ilogi(1),
+ cpi(1,3),cdpipj(1,1,3),cpiDpj(1,1,3),csdel2,cel2s(1,3),
+ cetalm(3),cetami(1,3),celpsi(1,3),calph,4,ier0)
call ffcc0p(cs4(81),ipi12(9),isoort(9),clogi(4),ilogi(4),
+ cpi(1,4),cdpipj(1,1,4),cpiDpj(1,1,4),csdel2,cel2s(1,4),
+ cetalm(4),cetami(1,4),celpsi(1,4),calph,4,ier1)
else
if ( lsmug ) call ffsm43(xpi3(1,3),7-3)
call ffxc0p(cs4( 1),ipi12(1),isoort(1),clogi(1),ilogi(1),
+ xpi3(1,3),dpipj3(1,1,3),piDpj3(1,1,3),sdel2,del2s(1,3),
+ etalam(3),etami(1,3),delpsi(1,3),alph,4,ier0)
if ( lsmug ) call ffsm43(xpi3(1,4),7-4)
call ffxc0p(cs4(81),ipi12(9),isoort(9),clogi(4),ilogi(4),
+ xpi3(1,4),dpipj3(1,1,4),piDpj3(1,1,4),sdel2,del2s(1,4),
+ etalam(4),etami(1,4),delpsi(1,4),alph,4,ier1)
endif
ier = max(ier0,ier1)
goto 600
* #] simple case:
* #[ cancellations:
500 continue
*
* There are cancellations between the dilogarithms or the vertex
* is on threshold.
* we need the differences ddel2s(i) = del2s(i,3)-del2s(i,4)
*
do 510 i=2,3
if ( i .eq. 2 ) then
j = 2
else
j = 1
endif
ddel2s(i) = del2s(i,3) - del2s(i,4)
xmax = abs(del2s(i,3))
if ( abs(ddel2s(i)) .ge. xloss*xmax ) goto 510
*
* Very first try with transformation
*
s(1) = (ai(3)+ai(4))*daiaj(3,4)*del2s(i,3)/ai(3)**2
s(2) = ai(j)**2*ai(4)**2*xpi(j)*dpipj(3,4)
s(3) = ai(j)**2*ai(4)**2*piDpj(j,7)*piDpj(j,3)
s(4) = ai(j)**2*ai(4)**2*piDpj(j,7)*piDpj(j,4)
som = s(1) + s(2) + s(3) + s(4)
smax = max(abs(s(1)),abs(s(2)),abs(s(3)),abs(s(4)))
if ( abs(som) .ge. xloss*smax ) goto 510
if ( smax .lt. xmax ) then
ddel2s(i) = som
xmax = smax
endif
510 continue
if ( .not. lcroot ) then
call ffdxc0(cs4,ipi12,isoort,clogi,ilogi,xpi3,dpipj3,piDpj3,
+ xqi,qiDqj,sdel2,del2s,etalam,etami,delpsi,alph,
+ ddel2s,ldel2s,4,ier)
else
cddl2s(2) = ddel2s(2)
cddl2s(3) = ddel2s(3)
do 530 i=1,10
zqi(i) = xqi(i)
do 520 j=1,10
zqiDqj(j,i) = qiDqj(j,i)
520 continue
530 continue
call ffdcc0(cs4,ipi12,isoort,clogi,ilogi,cpi,cpiDpj,
+ zqi,zqiDqj,csdel2,cel2s,cetalm,cetami,celpsi,
+ calph,cddl2s,ldel2s,4,ier)
endif
600 continue
* #] cancellations:
* #[ Ai<0 terms:
- cipi = DCMPLX(0D0,pi)
+ cipi = ToComplex(0D0,pi)
if ( ai(3) .lt. 0 .neqv. ai(4) .lt. 0 ) then
* we need the S term
if ( ai(1) .lt. 0 .eqv. ai(2) .lt. 0 ) then
if ( lcroot ) then
call ffcxra(cs4(167),ipi12(23),xqi,qiDqj,sdel2,1,ier)
else
* call ffxtro(cs4(167),ipi12(23),xqi,qiDqj,sdel2,1,ier)
call ffxtra(cs4(167),ipi12(23),xqi,qiDqj,sdel2,1,ier)
endif
else
if ( lcroot ) then
call ffcxra(cs4(167),ipi12(23),xqi,qiDqj,sdel2,2,ier)
call ffcxra(cs4(169),ipi12(26),xqi,qiDqj,sdel2,3,ier)
else
call ffxtra(cs4(167),ipi12(23),xqi,qiDqj,sdel2,2,ier)
call ffxtra(cs4(169),ipi12(26),xqi,qiDqj,sdel2,3,ier)
* call ffxtro(cs4(167),ipi12(23),xqi,qiDqj,sdel2,2,ier)
* call ffxtro(cs4(169),ipi12(26),xqi,qiDqj,sdel2,3,ier)
endif
endif
endif
*
* The normal correction terms
*
if ( ai(1) .lt. 0 .neqv. ai(2) .lt. 0 ) then
cs4(161) = -cipi*clogi(1)
ipi12(17) = 12*ilogi(1)
if ( ilogi(1) .eq. -999 ) call fferr(46,ier)
cs4(164) = cipi*clogi(4)
ipi12(20) = -12*ilogi(4)
if ( ilogi(4) .eq. -999 ) call fferr(46,ier)
endif
if ( ai(2) .lt. 0 .neqv. ai(3) .lt. 0 ) then
cs4(162) = -cipi*clogi(2)
ipi12(18) = 12*ilogi(2)
if ( ilogi(2) .eq. -999 ) call fferr(46,ier)
endif
if ( ai(3) .lt. 0 .neqv. ai(1) .lt. 0 ) then
cs4(163) = -cipi*clogi(3)
ipi12(19) = 12*ilogi(3)
if ( ilogi(3) .eq. -999 ) call fferr(46,ier)
endif
if ( ai(2) .lt. 0 .neqv. ai(4) .lt. 0 ) then
cs4(165) = cipi*clogi(5)
ipi12(21) = -12*ilogi(5)
if ( ilogi(5) .eq. -999 ) call fferr(46,ier)
endif
if ( ai(4) .lt. 0 .neqv. ai(1) .lt. 0 ) then
cs4(166) = cipi*clogi(6)
ipi12(22) = -12*ilogi(6)
if ( ilogi(6) .eq. -999 ) call fferr(46,ier)
endif
* #] Ai<0 terms:
*###] ffxd0p:
end
*###[ ffpi43:
subroutine ffpi43(xpi3,dpipj3,piDpj3,xpi,dpipj,piDpj,imiss)
***#[*comment:***********************************************************
* *
* Fill the threepoint arrays xpi3 and dpipj3 with masses from the *
* the fourpoint array xpi with leg imiss cut out. *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE PRECISION xpi3(6),dpipj3(6,6),piDpj3(6,6)
- DOUBLE PRECISION xpi(10),dpipj(10,10),piDpj(10,10)
+ RealType xpi3(6),dpipj3(6,6),piDpj3(6,6)
+ RealType xpi(10),dpipj(10,10),piDpj(10,10)
integer imiss
*
* local variables
*
integer i,j
integer iinx(6,4)
save iinx
*
* common blocks
*
#include "ff.h"
*
* data
*
data iinx /2,3,4,6,7,10,
+ 1,3,4,9,7,8,
+ 1,2,4,5,10,8,
+ 1,2,3,5,6,9/
* #] declarations:
* #[ calculations:
do 20 i=1,6
xpi3(i) = xpi(iinx(i,imiss))
do 10 j=1,6
dpipj3(j,i) = dpipj(iinx(j,imiss),iinx(i,imiss))
piDpj3(j,i) = piDpj(iinx(j,imiss),iinx(i,imiss))
10 continue
20 continue
* #] calculations:
*###] ffpi43:
end
*###[ ffxtra:
subroutine ffxtra(cs4,ipi12,xqi,qiDqj,sdel2,ii,ier)
***#[*comment:***********************************************************
* *
* calculate the extra terms S_ii^{\infty\prime}, put them in *
* cs4 and ipi12. *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ipi12(3),ii,ier
- DOUBLE COMPLEX cs4(3)
- DOUBLE PRECISION xqi(10),qiDqj(10,10),sdel2
+ ComplexType cs4(3)
+ RealType xqi(10),qiDqj(10,10),sdel2
*
* local variables
*
integer i,ip(5)
- DOUBLE PRECISION x(2,3),dfflo1,s,s1
+ RealType x(2,3),dfflo1,s,s1
external dfflo1
*
* common blocks
*
#include "ff.h"
*
* data
*
data ip/5,6,8,5,6/
* #] declarations:
* #[ calculations:
if ( ii .eq. 3 ) return
do 10 i=1,3
if ( ii .eq. 1 .and. i .eq. 2 ) goto 10
call ffroot(x(1,i),x(2,i),xqi(ip(i)),-qiDqj(ip(i),
+ ip(i+1)),xqi(ip(i+1)),sdel2,ier)
s = -x(2,i)/x(1,i)
if ( abs(s-1) .lt. xloss ) then
s1 = dfflo1(-2*qiDqj(ip(i),ip(i+1))/(xqi(ip(i))*x(1,i)),
+ ier)
elseif ( s .gt. 0 ) then
s1 = log(s)
else
if ( abs(s+1) .lt. xloss ) then
s1 = dfflo1(-2*sdel2/(xqi(ip(i))*x(1,i)),ier)
else
s1 = log(-s)
endif
* also here an minus sign (-i*pi*log(-(p.p-sqrt)/(p.p+sqrt)))
if ( qiDqj(ip(i),ip(i+1))*xqi(ip(i))*sdel2 .gt. 0 ) then
ipi12(i) = +12
else
ipi12(i) = -12
endif
* ier = ier + 50
* print *,'ffxtra: imaginary part may well be wrong -> ',
* + 'n*pi^2 fout'
* print *,' ipi12(i) = ',ipi12(i)
* print *,' qiDqj = ',qiDqj(ip(i),ip(i+1))
* print *,' qi^2 = ',xqi(ip(i))
endif
* there is an overall minus compared with Veltman
- cs4(i) = DCMPLX(0D0,-pi*s1)
+ cs4(i) = ToComplex(0D0,-pi*s1)
if ( sdel2 .lt. 0 ) then
cs4(i) = -cs4(i)
ipi12(i) = -ipi12(i)
endif
if ( ii .ne. 1 ) then
cs4(i) = -cs4(i)
ipi12(i) = -ipi12(i)
endif
if ( i .eq. 2 ) then
cs4(i) = 2*cs4(i)
ipi12(i) = 2*ipi12(i)
endif
10 continue
* #] calculations:
*###] ffxtra:
end
*###[ ffcxra:
subroutine ffcxra(cs4,ipi12,xqi,qiDqj,sdel2,ii,ier)
***#[*comment:***********************************************************
* *
* calculate the extra terms S_ii^{\infty\prime}, put them in *
* cs4 and ipi12 for qi real but sdel2 complex. *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ipi12(3),ii,ier
- DOUBLE COMPLEX cs4(3)
- DOUBLE PRECISION xqi(10),qiDqj(10,10),sdel2
+ ComplexType cs4(3)
+ RealType xqi(10),qiDqj(10,10),sdel2
*
* local variables
*
integer i,ip(5)
- DOUBLE COMPLEX x(2,3),zfflo1,s,s1,c
- DOUBLE PRECISION absc
+ ComplexType x(2,3),zfflo1,s,s1,c
+ RealType absc
external zfflo1
*
* common blocks
*
#include "ff.h"
*
* data
*
data ip/5,6,8,5,6/
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ calculations:
if ( ii .eq. 3 ) return
do 10 i=1,3
if ( ii .eq. 1 .and. i .eq. 2 ) goto 10
- x(1,i) = DCMPLX(-qiDqj(ip(i),ip(i+1))/xqi(ip(i)),
+ x(1,i) = ToComplex(-qiDqj(ip(i),ip(i+1))/xqi(ip(i)),
+ -sdel2/xqi(ip(i)))
- x(2,i) = DCMPLX(-qiDqj(ip(i),ip(i+1))/xqi(ip(i)),
+ x(2,i) = ToComplex(-qiDqj(ip(i),ip(i+1))/xqi(ip(i)),
+ +sdel2/xqi(ip(i)))
s = -x(2,i)/x(1,i)
c = s-1
if ( absc(c) .lt. xloss ) then
- s1 = zfflo1(DBLE(-2*qiDqj(ip(i),ip(i+1))/xqi(ip(i)))/
+ s1 = zfflo1(Re(-2*qiDqj(ip(i),ip(i+1))/xqi(ip(i)))/
+ x(1,i),ier)
elseif ( abs(s+1) .lt. xloss ) then
- s1 = zfflo1(DCMPLX(0D0,-2*sdel2/xqi(ip(i)))/x(1,i),ier)
- if ( DIMAG(c).gt.0 ) then
+ s1 = zfflo1(ToComplex(0D0,-2*sdel2/xqi(ip(i)))/x(1,i),ier)
+ if ( Im(c).gt.0 ) then
ipi12(i) = +12
else
ipi12(i) = -12
endif
else
s1 = log(s)
endif
* there is an overall minus compared with Veltman
- cs4(i) = DCMPLX(pi*DIMAG(s1),-pi*DBLE(s1))
+ cs4(i) = ToComplex(pi*Im(s1),-pi*Re(s1))
if ( ii .ne. 1 ) then
cs4(i) = -cs4(i)
ipi12(i) = -ipi12(i)
endif
if ( sdel2 .lt. 0 ) then
cs4(i) = -cs4(i)
ipi12(i) = -ipi12(i)
endif
if ( i .eq. 2 ) then
cs4(i) = 2*cs4(i)
ipi12(i) = 2*ipi12(i)
endif
10 continue
* #] calculations:
*###] ffcxra:
end
*###[ ffsm43:
subroutine ffsm43(xpi3,imiss)
***#[*comment:***********************************************************
* *
* Distribute the smuggled 4point momenta to the 3point smuggled *
* momenta. Note that because of the common block smuggling this *
* cannot be included in ffpi43. *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer imiss
- DOUBLE PRECISION xpi3(6)
+ RealType xpi3(6)
*
* local variables
*
integer i,j,iinx(6,4)
save iinx
*
* common blocks
*
#include "ff.h"
*
* data
*
data iinx /2,3,4,6,7,10,
+ 1,3,4,9,7,8,
+ 1,2,4,5,10,8,
+ 1,2,3,5,6,9/
*
* #] declarations:
* #[ parcel out:
if ( lsmug ) then
*
* parcel out the smuggled diffs
*
do 30 i=1,3
j = mod(i,3)+1
if ( xpi3(j) .eq. 0 ) then
cmipj(i,i) = c2sisj(iinx(i,imiss),iinx(j,imiss))
elseif ( xpi3(i) .eq. 0 ) then
cmipj(j,i) = c2sisj(iinx(i,imiss),iinx(j,imiss))
endif
30 continue
endif
* #] parcel out:
*)##] ffsm43:
end
diff --git a/Looptools/D/ffxd0tra.F b/Looptools/D/ffxd0tra.F
--- a/Looptools/D/ffxd0tra.F
+++ b/Looptools/D/ffxd0tra.F
@@ -1,146 +1,136 @@
* ffd0tra.F
* a special case of the D0 function
* original code by Francesco Tramontano
* this file is part of LoopTools
-* last modified 8 Dec 10 th
+* last modified 13 Sep 12 th
#include "externals.h"
+#include "types.h"
subroutine ffd0tra(res, S, T, ML2, ME2, ier)
implicit none
- DOUBLE COMPLEX res
- DOUBLE PRECISION S, T, ML2, ME2
+ ComplexType res
+ RealType S, T, ML2, ME2
integer ier
c===============================c
c c
c p1 S p2 c
c \ / c
c \ / c S = (p1+p2)^2
c \========/ c T = (p2+p3)^2
c || || c ML2= mass-square of the particle in the loop
c || || T c ME2= mass-square of the external particle p4
c || || c
c E========\ c
c E ML2 \ c
c E \ c
c p3 c
c p4^2=ME2 c
c c
c===============================c
- DOUBLE COMPLEX xp, xm, ypS, ymS, ypT, ymT, ypE, ymE
- DOUBLE COMPLEX xr, yr
+ ComplexType xp, xm, ypS, ymS, ypT, ymT, ypE, ymE
+ ComplexType xr, yr
integer iepsS, iepsT, iepsE
- DOUBLE COMPLEX ffint3
+ ComplexType ffint3
external ffint3
-c PRINT *, "ML2=", ML2
-c PRINT *, "ME2=", ME2
-c PRINT *, "S=", S
-c PRINT *, "T=", T
-
call fftraroot(xm, xp, xr, -ML2*(ME2 - S - T)/(S*T))
call fftraroot(ymS, ypS, yr, ML2/S)
call fftraroot(ymT, ypT, yr, ML2/T)
call fftraroot(ymE, ypE, yr, ML2/ME2)
iepsS = 0
if( S .gt. 0 ) iepsS = 1
iepsT = 0
if( T .gt. 0 ) iepsT = 1
iepsE = 0
if( ME2 .gt. 0 ) iepsE = 1
res = (
& ffint3(ypS, xm, iepsS, ier) - ffint3(ypS, xp, iepsS, ier) +
& ffint3(ymS, xm, -iepsS, ier) - ffint3(ymS, xp, -iepsS, ier) +
& ffint3(ypT, xm, iepsT, ier) - ffint3(ypT, xp, iepsT, ier) +
& ffint3(ymT, xm, -iepsT, ier) - ffint3(ymT, xp, -iepsT, ier) -
& ffint3(ypE, xm, iepsE, ier) + ffint3(ypE, xp, iepsE, ier) -
& ffint3(ymE, xm, -iepsE, ier) + ffint3(ymE, xp, -iepsE, ier)
& )/(xr*S*T)
end
************************************************************************
subroutine fftraroot(xm, xp, r, c)
***#[*comment:***********************************************************
* *
* roots of quadratic equation x^2 + x + c == 0 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
- DOUBLE COMPLEX xm, xp, r
- DOUBLE PRECISION c
+ ComplexType xm, xp, r
+ RealType c
* #] declarations:
- r = sqrt(DCMPLX(1 - 4*c))
+ r = sqrt(ToComplex(1 - 4*c))
xp = .5D0*(1 + r)
xm = .5D0*(1 - r)
-c PRINT *, "c=", c
-c PRINT *, "r=", r
-c PRINT *, "xp=", xp
-c PRINT *, "xm=", xm
if( abs(xp) .gt. abs(xm) ) then
xm = c/xp
else
xp = c/xm
endif
-c PRINT *, "xp'=", xp
-c PRINT *, "xm'=", xm
end
************************************************************************
- DOUBLE COMPLEX function ffint3(y, x, ieps, ier)
+ ComplexType function ffint3(y, x, ieps, ier)
implicit none
- DOUBLE COMPLEX y, x
+ ComplexType y, x
integer ieps, ier
* compute \int_0^1 dz log(z - y)/(z - x)
#include "ff.h"
- DOUBLE COMPLEX arg1, arg2, dd1, dd2, zlog
+ ComplexType arg1, arg2, dd1, dd2, zlog
integer ipi121, ipi122
-c DOUBLE PRECISION rarg1, rarg2
+c RealType rarg1, rarg2
c equivalence (arg1, rarg1), (arg2, rarg2)
-c DOUBLE PRECISION ddilog
-c DOUBLE COMPLEX li2
+c RealType ddilog
+c ComplexType li2
c external ddilog, li2
- if( DIMAG(x) .ne. 0 ) call ffwarn(258, ier, 1D0, 0D0)
+ if( Im(x) .ne. 0 ) call ffwarn(258, ier, 1D0, 0D0)
arg1 = x/(x - y)
- if( abs(DIMAG(arg1)) .lt. 1D-15 ) then
+ if( abs(Im(arg1)) .lt. 1D-15 ) then
call ffzxdl(dd1, ipi121, zlog, arg1, ieps, ier)
c dd1 = ddilog(rarg1)
c if( rarg1 .gt. 1 )
c & dd1 = dd1 + eps*sign(pi, x)*log(rarg1)*cI
else
call ffzzdl(dd1, ipi121, zlog, arg1, ier)
c dd1 = li2(arg1)
endif
arg2 = (x - 1)/(x - y)
- if( abs(DIMAG(arg2)) .lt. 1D-15 ) then
+ if( abs(Im(arg2)) .lt. 1D-15 ) then
call ffzxdl(dd2, ipi122, zlog, arg2, ieps, ier)
c dd2 = ddilog(rarg2)
c if( rarg2 .gt. 1 )
c & dd2 = dd2 - eps*sign(pi, 1 - x)*log(rarg2)*cI
else
call ffzzdl(dd2, ipi122, zlog, arg2, ier)
c dd2 = li2(arg2)
endif
ffint3 = dd1 - dd2 + (ipi121 - ipi122)*pi12
end
diff --git a/Looptools/D/ffxdbd.F b/Looptools/D/ffxdbd.F
--- a/Looptools/D/ffxdbd.F
+++ b/Looptools/D/ffxdbd.F
@@ -1,835 +1,836 @@
#include "externals.h"
+#include "types.h"
*###[ ffxdir:
subroutine ffxdir(cs,cfac,idone,xpi,dpipj,ipoin,ndiv,ier)
***#[*comment:***********************************************************
* *
* Check if this 4point function is IRdivergent and if so, get it *
* using ffxdbd and set idone to 1 (or 2 if 2 IR poles) *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ipoin,idone,ndiv,ier
- DOUBLE COMPLEX cs,cfac
- DOUBLE PRECISION xpi(13),dpipj(10,13)
+ ComplexType cs,cfac
+ RealType xpi(13),dpipj(10,13)
*
* local variables
*
integer i,j,k,l,ier0,ii(6),notijk(4,4,4)
save notijk
*
* common blocks
*
#include "ff.h"
*
* data
*
data notijk/
+ 0,0,0,0,0,0,4,3,0,4,0,2,0,3,2,0,0,0,4,3,0,0,0,0,4,0,0,1,3,0,1,0,
+ 0,4,0,2,4,0,0,1,0,0,0,0,2,1,0,0,0,3,2,0,3,0,1,0,2,1,0,0,0,0,0,0/
*
* #] declarations:
* #[ work:
*
idone = 0
do 25 i=1,4
if ( xpi(i) .ne. 0 ) goto 25
do 24 j=1,3
if ( j .eq. i ) goto 24
if ( dpipj(j,inx(j,i)) .ne. 0 ) goto 24
do 23 k=j+1,4
if ( k .eq. i ) goto 23
if ( dpipj(k,inx(k,i)) .ne. 0 ) goto 23
*
* we found an IR divergent function;
* first check whether it is linearly divergent
*
l = notijk(k,j,i)
*
* do we have a linear divergence on our hands?
*
if ( dpipj(l,inx(l,i)) .eq. 0 ) then
if ( ndiv.eq.-1 ) ndiv = 1
elseif ( ndiv.gt.0 ) then
cs = 0
cfac = 1
idone = 1
return
endif
*
* the complex case
*
if ( lsmug ) then
*
* use Wim & Ansgard's formulae whenever possible
*
if ( c2sisj(i,j).eq.0 .and. c2sisj(i,k).eq.0 )
+ then
call ffxdbd(cs,cfac,xpi,dpipj,i,j,k,l,ier)
goto 98
endif
if ( c2sisj(i,j).eq.0 .and. dpipj(i,inx(i,l))
+ .eq.0 .and. c2sisj(i,l).eq.0 ) then
call ffxdbd(cs,cfac,xpi,dpipj,i,j,l,k,ier)
goto 98
endif
if ( c2sisj(i,k).eq.0 .and. dpipj(i,inx(i,l))
+ .eq.0 .and. c2sisj(i,l).eq.0 ) then
call ffxdbd(cs,cfac,xpi,dpipj,i,k,l,j,ier)
goto 98
endif
*
* is it nasty?
*
if ( dpipj(i,inx(i,l)).eq.0 ) then
if ( c2sisj(j,i).eq.0 ) then
goto 99
elseif ( c2sisj(k,i).eq.0 ) then
goto 99
elseif ( c2sisj(l,i).eq.0 ) then
goto 99
else
call fferr(71,ier)
return
endif
endif
*
* then it just is logarithmiocally divergent
* let the ffxc0i handle this
*
else
*
* the real case
*
if ( dpipj(i,inx(i,l)).eq.0 ) then
call fferr(73,ier)
idone = 1
return
endif
call ffxdbd(cs,cfac,xpi,dpipj,i,j,k,l,ier)
goto 98
endif
23 continue
24 continue
25 continue
idone = 0
lnasty = .FALSE.
if ( ndiv.eq.-1 ) ndiv = 0
return
*
* clean up
*
98 continue
if ( ldot .and. ipoin.eq.4 ) then
ier0 = 0
if ( idot.lt.1 ) then
call ffdot4(fpij4,xpi,dpipj,10,ier0)
endif
ii(1)= 5
ii(2)= 6
ii(3)= 7
ii(4)= 8
ii(5)= 9
ii(6)= 10
if ( abs(idot).lt.2 ) then
fidel3 = ier0
call ffdl3p(fdel3,fpij4,10,ii,ii)
endif
endif
*
* and finito
*
if ( ndiv.eq.-1 ) ndiv = 0
idone = 1
if ( xpi(j) .eq. 0 .or. xpi(k) .eq. 0 ) idone = 2
if ( xpi(j) .eq. 0 .and. xpi(k) .eq. 0 ) idone = 3
return
*
* nasty - set some flags
*
99 continue
lnasty = .TRUE.
return
*
* #] work:
*###] ffxdir:
end
*###[ ffxdbd:
subroutine ffxdbd(csom,cfac,xpi,dpipj,ilam,i1,i4,ic,ier)
***#[*comment:***********************************************************
* *
* The IR divergent fourpoint function with real masses *
* according to Beenakker & Denner, Nucl.Phys.B338(1990)349. *
* *
* Input: xpi(13) real momenta^2 *
* dpipj(10,13) real xpi(i)-xpi(j) *
* ilam integer position of m=0 *
* i1,i4 integer position of other 2 IR masses *
* ic integer position of complex mass *
* lambda real cutoff to use instead of lam^2 *
* *
* Output: csom,cfac complex D0 = csom*cfac *
* ier integer number of digits lost *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ilam,i1,i4,ic,ier
- DOUBLE COMPLEX csom,cfac
- DOUBLE PRECISION xpi(13),dpipj(10,13)
+ ComplexType csom,cfac
+ RealType xpi(13),dpipj(10,13)
*
* local variables
*
integer ier0,ier1,ipi12,ip,init,is,i2,i3,i,iepst,iepss,ieps2,
+ ieps3
- DOUBLE PRECISION absc,xmax
- DOUBLE PRECISION xxs(3),xxt(1),xx2(3),xx3(3),xm0,xm1,xm4,xlam,
+ RealType absc,xmax
+ RealType xxs(3),xxt(1),xx2(3),xx3(3),xm0,xm1,xm4,xlam,
+ d,dfflo1,fac
- DOUBLE COMPLEX c,cs(21),z,zlg,som,cxt
- DOUBLE COMPLEX zxfflg,zfflog
+ ComplexType c,cs(21),z,zlg,som,cxt
+ ComplexType zxfflg,zfflog
external dfflo1,zxfflg,zfflog
save init
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
*
* data
*
data init /0/
*
* #] declarations:
* #[ check input:
*
if ( init .eq. 0 ) then
init = 1
print *,'ffxdbd: using IR cutoff lambda^2 = ',lambda
endif
if ( xpi(i1).eq.0 .or. xpi(i4).eq.0 ) then
call fferr(98,ier)
return
endif
*
* #] check input:
* #[ preliminaries:
*
csom = 0
cfac = 1
xm0 = sqrt(xpi(ic))
xm1 = sqrt(xpi(i1))
xm4 = sqrt(xpi(i4))
xlam = sqrt(lambda)
*
* #] preliminaries:
* #[ special case m0=0, m1=m2, m3=m4:
if ( xpi(ic) .eq. 0 ) then
*
* even more special case: 2 points of IR divergence:
*
if ( dpipj(i1,inx(ic,i1)).eq.0 .and.
+ dpipj(i4,inx(ic,i4)).eq.0 ) then
ier0 = 0
call ffxkfn(xxs,iepss,xpi(inx(i1,i4)),xm1,xm4,ier0)
if ( ier0.ge.100 ) then
call fferr(44,ier)
return
endif
ier = ier + ier0
if ( abs(xxs(2)).gt.xloss ) then
zlg = zxfflg(xxs(1),iepss,0D0,ier)
else
- zlg = DBLE(dfflo1(xxs(2),ier))
+ zlg = Re(dfflo1(xxs(2),ier))
endif
csom = -2*zlg*
+ zxfflg(-lambda/xpi(inx(ilam,ic)),-2,0D0,ier)
fac = xxs(1)/(xm1*xm4*xpi(inx(ilam,ic))*xxs(2)*xxs(3))
cfac = fac
if ( ldot .and. abs(idot).lt.4 ) then
fdel4s = 1/(16*fac**2)
endif
return
endif
* #] special case m0=0, m1=m2, m3=m4:
* #[ special case m0=0, m1=m2, m3!=m4:
if ( dpipj(i1,inx(ic,i1)).eq.0 .or.
+ dpipj(i4,inx(ic,i4)).eq.0 ) then
if ( dpipj(i1,inx(ic,i1)).ne.0 ) then
i = i4
i4 = i1
i1 = i
endif
*
* From Wim Beenakker, Priv.Comm.
*
ier0 = 0
call ffxkfn(xxs,iepss,xpi(inx(i1,i4)),xm1,xm4,ier0)
if ( ier0.ge.100 ) then
call fferr(44,ier)
return
endif
ier = ier + ier0
ier0 = ier
ier1 = ier
if ( abs(xxs(2)).gt.xloss ) then
zlg = zxfflg(xxs(1),iepss,0D0,ier0)
else
- zlg = DBLE(dfflo1(xxs(2),ier0))
+ zlg = Re(dfflo1(xxs(2),ier0))
endif
cs(1) = zlg**2
ier1 = max(ier0,ier1)
ier0 = ier
if ( xxs(1)**2.lt.xloss ) then
- cs(2) = -2*DBLE(dfflo1(xxs(1)**2,ier0))*zlg
+ cs(2) = -2*Re(dfflo1(xxs(1)**2,ier0))*zlg
else
cs(2) = -2*zxfflg(xxs(2)*xxs(3),0,0D0,ier0)*zlg
endif
ier1 = max(ier0,ier1)
ier0 = ier
cs(3) = zxfflg(lambda/xpi(i4),0,0D0,ier0)*zlg
ier1 = max(ier0,ier1)
ier0 = ier
cs(4) = 2*zxfflg(dpipj(inx(ic,i4),i4)/xpi(inx(ilam,ic)),
+ -1,dpipj(inx(ic,i4),i4),ier0)*zlg
ier1 = max(ier0,ier1)
ier0 = ier
call ffzxdl(cs(5),ip,zlg,xxs(1)**2,iepss,ier0)
cs(5) = -cs(5)
ipi12 = -ip + 2
ier1 = max(ier0,ier1)
ier = ier1
som = cs(1) + cs(2) + cs(3) + cs(4) + cs(5) +
- + ipi12*DBLE(pi12)
+ + ipi12*Re(pi12)
xmax = max(absc(cs(1)),absc(cs(2)),absc(cs(3)),
+ absc(cs(4)),absc(cs(5)))
csom = som
fac = -xxs(1)/(xm1*xm4*xpi(inx(ilam,ic))*xxs(2)*xxs(3))
cfac = fac
if ( ldot .and. abs(idot).lt.4 ) then
fdel4s = 1/(16*fac**2)
endif
return
endif
* #] special case m0=0, m1=m2, m3!=m4:
* #[ special case m0=0, m1!=m2, m3!=m4:
*
* This also crashes...
*
xm0 = precx*max(xm1,xm4)
endif
* #] special case m0=0, m1!=m2, m3!=m4:
* #[ get dimensionless vars:
*
* we follow the notation of Wim & Ansgar closely
* remember that for -pi we have ieps=+2 and v.v.
*
if ( lsmug ) then
* all is not what it seems
if ( nschem .ge. 3 ) then
- cxt = DBLE(xm0*xlam)/c2sisj(ic,ilam)
+ cxt = Re(xm0*xlam)/c2sisj(ic,ilam)
else
- cxt = DBLE(xm0*xlam)/DBLE(c2sisj(ic,ilam))
+ cxt = Re(xm0*xlam)/Re(c2sisj(ic,ilam))
endif
else
if ( dpipj(ic,inx(ilam,ic)) .eq. 0 ) then
call fferr(73,ier)
return
endif
xxt(1) = xm0*xlam/dpipj(ic,inx(ilam,ic))
endif
iepst = -2
ier1 = 0
ier0 = 0
call ffxkfn(xxs,iepss,xpi(inx(i1,i4)),xm1,xm4,ier0)
ier1 = max(ier0,ier1)
ier0 = 0
call ffxkfn(xx2,ieps2,xpi(inx(i1,ic)),xm1,xm0,ier0)
ier1 = max(ier0,ier1)
ier0 = 0
call ffxkfn(xx3,ieps3,xpi(inx(i4,ic)),xm4,xm0,ier0)
ier1 = max(ier0,ier1)
if ( ier1 .ge. 100 ) then
call ffzdbd(csom,cfac,xpi,dpipj,ilam,i1,i4,ic,ier)
return
endif
ier = ier + ier1
*
* #] get dimensionless vars:
* #[ fill array:
*
ier1 = 0
ier0 = 0
zlg = zxfflg(xxs(1),iepss,0D0,ier)
d = xxs(1)**2
if ( abs(d) .lt. xloss ) then
- cs(1) = 2*zlg*DBLE(dfflo1(d,ier0))
+ cs(1) = 2*zlg*Re(dfflo1(d,ier0))
else
cs(1) = 2*zlg*zxfflg(xxs(2)*xxs(3),-iepss,0D0,ier0)
endif
ier1 = max(ier0,ier1)
ier0 = 0
if ( lsmug ) then
cs(2) = -2*zlg*zfflog(cxt,iepst,czero,ier0)
else
cs(2) = -2*zlg*zxfflg(xxt(1),iepst,0D0,ier0)
endif
ier1 = max(ier0,ier1)
*
ipi12 = 6
*
ier0 = 0
call ffzxdl(cs(3),ip,zlg,xxs(1)**2,iepss,ier0)
ipi12 = ipi12 + ip
ier1 = max(ier0,ier1)
ier0 = 0
if ( abs(xx2(2)) .gt. xloss ) then
z = zxfflg(xx2(1),ieps2,0D0,ier0)
else
z = dfflo1(xx2(2),ier0)
endif
cs(4) = z**2
ier1 = max(ier0,ier1)
ier0 = 0
if ( abs(xx3(2)) .gt. xloss ) then
z = zxfflg(xx3(1),ieps3,0D0,ier0)
else
z = dfflo1(xx3(2),ier0)
endif
cs(5) = z**2
ier1 = max(ier0,ier1)
*
is = 6
do 110 i2=-1,+1,2
do 100 i3=-1,+1,2
*
ier0 = 0
call ffzxdl(cs(is),ip,zlg,xxs(1)*xx2(1)**i2*xx3(1)**i3,
+ 0,ier0)
cs(is) = -cs(is)
ipi12 = ipi12 - ip
is = is + 1
ier1 = max(ier0,ier1)
*
ier0 = 0
if ( abs(xxs(2)) .gt. xloss ) then
cs(is) = -zlg*zxfflg(xxs(1),iepss,0D0,ier0)
else
- cs(is) = -zlg*DBLE(dfflo1(xxs(2),ier0))
+ cs(is) = -zlg*Re(dfflo1(xxs(2),ier0))
endif
is = is + 1
ier1 = max(ier0,ier1)
*
ier0 = 0
if ( abs(xx2(2)) .gt. xloss ) then
cs(is) = -zlg*zxfflg(xx2(1)**i2,i2*ieps2,0D0,ier0)
elseif ( i2.eq.1 ) then
- cs(is) = -zlg*DBLE(dfflo1(xx2(2),ier0))
+ cs(is) = -zlg*Re(dfflo1(xx2(2),ier0))
else
- cs(is) = -zlg*DBLE(dfflo1(-xx2(2)/xx2(1),ier0))
+ cs(is) = -zlg*Re(dfflo1(-xx2(2)/xx2(1),ier0))
endif
is = is + 1
ier1 = max(ier0,ier1)
*
ier0 = 0
if ( abs(xx3(2)) .gt. xloss ) then
cs(is) = -zlg*zxfflg(xx3(1)**i3,i3*ieps3,0D0,ier0)
elseif ( i3.eq.1 ) then
- cs(is) = -zlg*DBLE(dfflo1(xx3(2),ier0))
+ cs(is) = -zlg*Re(dfflo1(xx3(2),ier0))
else
- cs(is) = -zlg*DBLE(dfflo1(-xx3(2)/xx3(1),ier0))
+ cs(is) = -zlg*Re(dfflo1(-xx3(2)/xx3(1),ier0))
endif
is = is + 1
ier1 = max(ier0,ier1)
*
100 continue
110 continue
ier = ier + ier1
*
* #] fill array:
* #[ sum:
*
som = 0
xmax = 0
is = is - 1
do 200 i=1,is
som = som + cs(i)
xmax = max(xmax,absc(cs(i)))
200 continue
- som = som + ipi12*DBLE(pi12)
+ som = som + ipi12*Re(pi12)
*
* #] sum:
* #[ overall factors:
*
csom = som
if ( lsmug ) then
if ( nschem .ge. 2 ) then
- cfac = -DBLE(xxs(1)/((xm1*xm4*xxs(2)*xxs(3))))/
+ cfac = -Re(xxs(1)/((xm1*xm4*xxs(2)*xxs(3))))/
+ c2sisj(ilam,ic)
else
- cfac = -DBLE(xxs(1))/(DBLE(xm1*xm4*xxs(2)*xxs(3))*
- + DBLE(c2sisj(ilam,ic)))
+ cfac = -Re(xxs(1))/(Re(xm1*xm4*xxs(2)*xxs(3))*
+ + Re(c2sisj(ilam,ic)))
endif
if ( ldot .and. abs(idot).lt.4 ) then
fdel4s = 16*(xm1*xm4*dpipj(inx(ilam,ic),ic)*xxs(2)*
+ xxs(3)/xxs(1))**2
endif
else
fac = xxs(1)/(xm1*xm4*dpipj(inx(ilam,ic),ic)*xxs(2)*xxs(3))
cfac = fac
if ( ldot .and. abs(idot).lt.4 ) then
fdel4s = 1/(16*fac**2)
endif
endif
*
* #] overall factors:
*###] ffxdbd:
end
*###[ ffxkfn:
subroutine ffxkfn(x,ieps,xpi,xm,xmp,ier)
***#[*comment:***********************************************************
* *
* Calculate the K-function in this paper: *
* *
* 1-sqrt(1-4*m*mp/(z-(m-mp)^2)) *
* K(p^2,m,mp) = ----------------------------- *
* 1+sqrt(1-4*m*mp/(z-(m-mp)^2)) *
* *
* and fill x(1) = -K, x(2) = 1+K, x(3) = 1-K *
* ieps gives the sign of the imaginary part: -2 -> +ieps and v.v. *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ieps,ier
- DOUBLE PRECISION x(3),xpi,xm,xmp
+ RealType x(3),xpi,xm,xmp
*
* local variables
*
- DOUBLE PRECISION wortel,xx1,xx2,xx3
+ RealType wortel,xx1,xx2,xx3
*
* common blocks
*
#include "ff.h"
*
* #] declarations:
* #[ work:
*
* special case
*
if ( xpi.eq.0 .and. xm.eq.xmp ) then
x(1) = 1
x(2) = 0
x(3) = 2
return
endif
*
* normal case
*
xx1 = xpi - (xm-xmp)**2
xx2 = 1 - 4*xm*xmp/xx1
if ( xx2 .lt. 0 ) then
ier = ier + 100
return
endif
wortel = sqrt(xx2)
xx3 = 1/(1+wortel)
x(1) = -4*xm*xmp*xx3**2/xx1
x(2) = 2*xx3
x(3) = 2*wortel*xx3
*
ieps = -2
*
* #] work:
*###] ffxkfn:
end
*###[ ffzdbd:
subroutine ffzdbd(csom,cfac,xpi,dpipj,ilam,i1,i4,ic,ier)
***#[*comment:***********************************************************
* *
* The IR divergent fourpoint function with real masses *
* according to Beenakker & Denner, Nucl.Phys.B338(1990)349. *
* but in the case at least one of the roots is complex *
* *
* Input: xpi(13) real momenta^2 *
* dpipj(10,13) real xpi(i)-xpi(j) *
* ilam integer position of m=0 *
* i1,i4 integer position of other 2 IR masses *
* ic integer position of complex mass *
* lambda real cutoff to use instead of lam^2 *
* *
* Output: csom,cfac complex D0 = csom*cfac *
* ier integer number of digits lost *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ilam,i1,i4,ic,ier
- DOUBLE COMPLEX csom,cfac
- DOUBLE PRECISION xpi(13),dpipj(10,13)
+ ComplexType csom,cfac
+ RealType xpi(13),dpipj(10,13)
*
* local variables
*
integer ier0,ier1,ipi12,ip,init,is,i2,i3,i,iepst,iepss,ieps2,
+ ieps3
- DOUBLE PRECISION absc,xmax
- DOUBLE PRECISION xm0,xm1,xm4,xlam,xxt(1)
- DOUBLE COMPLEX c,cs(21),z,zlg,som,cxt,cxs(3),cx2(3),cx3(3)
- DOUBLE COMPLEX zxfflg,zfflog,zfflo1
+ RealType absc,xmax
+ RealType xm0,xm1,xm4,xlam,xxt(1)
+ ComplexType c,cs(21),z,zlg,som,cxt,cxs(3),cx2(3),cx3(3)
+ ComplexType zxfflg,zfflog,zfflo1
external zxfflg,zfflog,zfflo1
save init
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
*
* data
*
data init /0/
*
* #] declarations:
* #[ check input:
*
if ( init .eq. 0 ) then
init = 1
print *,'ffzdbd: using IR cutoff lambda^2 = ',lambda
endif
*
* #] check input:
* #[ preliminaries:
*
xm0 = sqrt(xpi(ic))
xm1 = sqrt(xpi(i1))
xm4 = sqrt(xpi(i4))
xlam = sqrt(lambda)
*
* #] preliminaries:
* #[ get dimensionless vars:
*
* we follow the notation of Wim & Ansgar closely
* remember that for -pi we have ieps=+2 and v.v.
*
if ( lsmug ) then
* all is not what it seems
if ( nschem .ge. 3 ) then
- cxt = DBLE(xm0*xlam)/c2sisj(ic,ilam)
+ cxt = Re(xm0*xlam)/c2sisj(ic,ilam)
else
- cxt = DBLE(xm0*xlam)/DBLE(c2sisj(ic,ilam))
+ cxt = Re(xm0*xlam)/Re(c2sisj(ic,ilam))
endif
else
xxt(1) = xm0*xlam/dpipj(ic,inx(ilam,ic))
endif
iepst = -2
ier1 = 0
ier0 = 0
call ffzkfn(cxs,iepss,xpi(inx(i1,i4)),xm1,xm4)
ier1 = max(ier0,ier1)
ier0 = 0
call ffzkfn(cx2,ieps2,xpi(inx(i1,ic)),xm1,xm0)
ier1 = max(ier0,ier1)
ier0 = 0
call ffzkfn(cx3,ieps3,xpi(inx(i4,ic)),xm4,xm0)
ier1 = max(ier0,ier1)
ier = ier + ier1
*
* #] get dimensionless vars:
* #[ fill array:
*
ier1 = 0
ier0 = 0
zlg = zfflog(cxs(1),iepss,czero,ier)
c = cxs(1)**2
if ( absc(c) .lt. xloss ) then
cs(1) = 2*zlg*zfflo1(c,ier0)
else
cs(1) = 2*zlg*zfflog(cxs(2)*cxs(3),-iepss,czero,ier0)
endif
ier1 = max(ier0,ier1)
ier0 = 0
if ( lsmug ) then
cs(2) = -2*zlg*zfflog(cxt,iepst,czero,ier0)
else
cs(2) = -2*zlg*zxfflg(xxt(1),iepst,0D0,ier0)
endif
ier1 = max(ier0,ier1)
*
ipi12 = 6
*
ier0 = 0
call ffzzdl(cs(3),ip,zlg,cxs(1)**2,ier0)
ipi12 = ipi12 + ip
ier1 = max(ier0,ier1)
ier0 = 0
z = zfflog(cx2(1),ieps2,czero,ier0)
cs(4) = z**2
ier1 = max(ier0,ier1)
ier0 = 0
z = zfflog(cx3(1),ieps3,czero,ier0)
cs(5) = z**2
ier1 = max(ier0,ier1)
*
is = 6
do 110 i2=-1,+1,2
do 100 i3=-1,+1,2
*
ier0 = 0
call ffzzdl(cs(is),ip,zlg,cxs(1)*cx2(1)**i2*cx3(1)**i3,
+ ier0)
cs(is) = -cs(is)
ipi12 = ipi12 - ip
is = is + 1
ier1 = max(ier0,ier1)
*
ier0 = 0
cs(is) = -zlg*zfflog(cxs(1),iepss,czero,ier0)
is = is + 1
ier1 = max(ier0,ier1)
*
ier0 = 0
cs(is) = -zlg*zfflog(cx2(1)**i2,i2*ieps2,czero,ier0)
is = is + 1
ier1 = max(ier0,ier1)
*
ier0 = 0
cs(is) = -zlg*zfflog(cx3(1)**i3,i3*ieps3,czero,ier0)
is = is + 1
ier1 = max(ier0,ier1)
*
100 continue
110 continue
ier = ier + ier1
*
* #] fill array:
* #[ sum:
*
som = 0
xmax = 0
is = is - 1
do 200 i=1,is
som = som + cs(i)
xmax = max(xmax,absc(cs(i)))
200 continue
- som = som + ipi12*DBLE(pi12)
+ som = som + ipi12*Re(pi12)
*
* #] sum:
* #[ overall factors:
*
csom = som
if ( lsmug ) then
if ( nschem .ge. 2 ) then
- cfac = -cxs(1)/(DBLE(xm1*xm4)*cxs(2)*cxs(3)*
+ cfac = -cxs(1)/(Re(xm1*xm4)*cxs(2)*cxs(3)*
+ c2sisj(ilam,ic))
else
- cfac = -cxs(1)/(DBLE(xm1*xm4)*cxs(2)*cxs(3)*
- + DBLE(c2sisj(ilam,ic)))
+ cfac = -cxs(1)/(Re(xm1*xm4)*cxs(2)*cxs(3)*
+ + Re(c2sisj(ilam,ic)))
endif
if ( ldot .and. abs(idot).lt.4 ) then
- c = 16*(DBLE(xm1*xm4*dpipj(inx(ilam,ic),ic))*
+ c = 16*(Re(xm1*xm4*dpipj(inx(ilam,ic),ic))*
+ cxs(2)*cxs(3)/cxs(1))**2
- fdel4s = DBLE(c)
- if ( xloss*DIMAG(c) .gt. precc*DBLE(c) ) then
+ fdel4s = Re(c)
+ if ( xloss*Im(c) .gt. precc*Re(c) ) then
print *,'ffzdbd: error: Del4s is not real ',c
endif
endif
else
- cfac = cxs(1)/(DBLE(xm1*xm4*dpipj(inx(ilam,ic),ic))*
+ cfac = cxs(1)/(Re(xm1*xm4*dpipj(inx(ilam,ic),ic))*
+ cxs(2)*cxs(3))
if ( ldot .and. abs(idot).lt.4 ) then
- fdel4s = 1/(16*DBLE(cfac)**2)
- if ( xloss*abs(DIMAG(cfac)) .gt. precc*abs(DBLE(cfac)) )
+ fdel4s = 1/(16*Re(cfac)**2)
+ if ( xloss*abs(Im(cfac)) .gt. precc*abs(Re(cfac)) )
+ then
print *,'ffzdbd: error: fac is not real: ',cfac
endif
endif
endif
*
* #] overall factors:
*###] ffzdbd:
end
*###[ ffzkfn:
subroutine ffzkfn(cx,ieps,xpi,xm,xmp)
***#[*comment:***********************************************************
* *
* Calculate the K-function in this paper: *
* *
* 1-sqrt(1-4*m*mp/(z-(m-mp)^2)) *
* K(p^2,m,mp) = ----------------------------- *
* 1+sqrt(1-4*m*mp/(z-(m-mp)^2)) *
* *
* and fill x(1) = -K, x(2) = 1+K, x(3) = 1-K *
* the roots are allowed to be imaginary *
* ieps gives the sign of the imaginary part: -2 -> +ieps and v.v. *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ieps
- DOUBLE PRECISION xpi,xm,xmp
- DOUBLE COMPLEX cx(3)
+ RealType xpi,xm,xmp
+ ComplexType cx(3)
*
* local variables
*
- DOUBLE PRECISION xx1,xx2
- DOUBLE COMPLEX wortel,cx3
+ RealType xx1,xx2
+ ComplexType wortel,cx3
*
* common blocks
*
#include "ff.h"
*
* #] declarations:
* #[ work:
*
xx1 = xpi - (xm-xmp)**2
xx2 = 1 - 4*xm*xmp/xx1
if ( xx2 .ge. 0 ) then
wortel = sqrt(xx2)
else
- wortel = DCMPLX(DBLE(0),DBLE(sqrt(-xx2)))
+ wortel = ToComplex(Re(0),Re(sqrt(-xx2)))
endif
cx3 = 1/(1+wortel)
if ( xx1.eq.0 ) then
print *, 'ffzkfn: error: xx1=0, contact author'
cx(1) = 1/xclogm
else
- cx(1) = DBLE(-4*xm*xmp/xx1)*cx3**2
+ cx(1) = Re(-4*xm*xmp/xx1)*cx3**2
endif
cx(2) = 2*cx3
cx(3) = 2*wortel*cx3
*
ieps = -2
*
* #] work:
*###] ffzkfn:
end
diff --git a/Looptools/E/E0.F b/Looptools/E/E0.F
deleted file mode 100644
--- a/Looptools/E/E0.F
+++ /dev/null
@@ -1,169 +0,0 @@
-* E0.F
-* the scalar four-point function
-* this file is part of LoopTools
-* written by M. Rauch
-* last modified 8 Dec 10 th
-
-#include "defs.h"
-
-
-#ifdef COMPLEXPARA
-#undef E0b
-#define E0b E0C
-#else
- double complex function E0(p1, p2, p3, p4, p5,
- & p1p2, p2p3, p3p4, p4p5, p5p1, m1, m2, m3, m4, m5)
- implicit none
- DVAR p1, p2, p3, p4, p5
- DVAR p1p2, p2p3, p3p4, p4p5, p5p1
- DVAR m1, m2, m3, m4, m5
-
-#include "lt.h"
-
- double complex E0b
- external E0b
-
- double complex res(0:1), d0(5)
- double precision xpi(20)
- integer key, ier
-
- key = ibits(versionkey, KeyE0, 2)
-
- if( key .ne. 0 ) then
- ier = 0
- xpi(1) = m1
- xpi(2) = m2
- xpi(3) = m3
- xpi(4) = m4
- xpi(5) = m5
- xpi(6) = p1
- xpi(7) = p2
- xpi(8) = p3
- xpi(9) = p4
- xpi(10) = p5
- xpi(11) = p1p2
- xpi(12) = p2p3
- xpi(13) = p3p4
- xpi(14) = p4p5
- xpi(15) = p5p1
-
- call ffxe0(res(1), d0, xpi, ier)
- if( ier .gt. warndigits ) key = ior(key, 2)
- endif
-
- if( key .ne. 1 ) then
- res(0) = E0b(p1, p2, p3, p4, p5,
- & p1p2, p2p3, p3p4, p4p5, p5p1, m1, m2, m3, m4, m5)
- if( key .gt. 1 .and.
- & abs(res(0) - res(1)) .gt. maxdev*abs(res(0)) ) then
- print *, "Discrepancy in E0:"
- print *, " p1 =", p1
- print *, " p2 =", p2
- print *, " p3 =", p3
- print *, " p4 =", p4
- print *, " p5 =", p5
- print *, " p1p2 =", p1p2
- print *, " p2p3 =", p2p3
- print *, " p3p4 =", p3p4
- print *, " p4p5 =", p4p5
- print *, " p5p1 =", p5p1
- print *, " m1 =", m1
- print *, " m2 =", m2
- print *, " m3 =", m3
- print *, " m4 =", m4
- print *, " m5 =", m5
- print *, "E0 a =", res(0)
- print *, "E0 b =", res(1)
- endif
- endif
-
- E0 = res(iand(key, 1))
- end
-#endif
-
-************************************************************************
-* adapter code for C++
-
- subroutine XE0sub(res, p1, p2, p3, p4, p5,
- & p1p2, p2p3, p3p4, p4p5, p5p1, m1, m2, m3, m4, m5)
- implicit none
- double complex res
- DVAR p1, p2, p3, p4, p5
- DVAR p1p2, p2p3, p3p4, p4p5, p5p1
- DVAR m1, m2, m3, m4, m5
-
- double complex XE0
- external XE0
-
- res = XE0(p1, p2, p3, p4, p5,
- & p1p2, p2p3, p3p4, p4p5, p5p1, m1, m2, m3, m4, m5)
- end
-
-************************************************************************
-
- double complex function E0b(p1, p2, p3, p4, p5,
- & p1p2, p2p3, p3p4, p4p5, p5p1, m1, m2, m3, m4, m5)
- implicit none
- DVAR p1, p2, p3, p4, p5
- DVAR p1p2, p2p3, p3p4, p4p5, p5p1
- DVAR m1, m2, m3, m4, m5
-
-#include "lt.h"
-
- QVAR Y(5,5), Yi(5,5), eta(5), detY
- integer i, j
-
- QVAR Yflat(25), Yiflat(25)
- equivalence (Y, Yflat)
- equivalence (Yi, Yiflat)
-
- double complex XD0
- external XD0
-
- Y(1,1) = 2*QPREC(m1)
- Y(2,2) = 2*QPREC(m2)
- Y(3,3) = 2*QPREC(m3)
- Y(4,4) = 2*QPREC(m4)
- Y(5,5) = 2*QPREC(m5)
- Y(1,2) = QPREC(m1) + QPREC(m2) - QPREC(p1)
- Y(2,1) = Y(1,2)
- Y(1,3) = QPREC(m1) + QPREC(m3) - QPREC(p1p2)
- Y(3,1) = Y(1,3)
- Y(1,4) = QPREC(m1) + QPREC(m4) - QPREC(p4p5)
- Y(4,1) = Y(1,4)
- Y(1,5) = QPREC(m1) + QPREC(m5) - QPREC(p5)
- Y(5,1) = Y(1,5)
- Y(2,3) = QPREC(m2) + QPREC(m3) - QPREC(p2)
- Y(3,2) = Y(2,3)
- Y(2,4) = QPREC(m2) + QPREC(m4) - QPREC(p2p3)
- Y(4,2) = Y(2,4)
- Y(2,5) = QPREC(m2) + QPREC(m5) - QPREC(p5p1)
- Y(5,2) = Y(2,5)
- Y(3,4) = QPREC(m3) + QPREC(m4) - QPREC(p3)
- Y(4,3) = Y(3,4)
- Y(3,5) = QPREC(m3) + QPREC(m5) - QPREC(p3p4)
- Y(5,3) = Y(3,5)
- Y(4,5) = QPREC(m4) + QPREC(m5) - QPREC(p4)
- Y(5,4) = Y(4,5)
-
- do i = 1, 5
- do j = 1, 25
- Yiflat(j) = Yflat(j)
- enddo
- do j = 1, 5
- Yi(j,i) = 1
- enddo
- call XDet(5, Yi,5, eta(i))
- enddo
-
- call XDet(5, Y,5, detY)
-
- E0b = -(
- & eta(1)*XD0(p2, p3, p4, p5p1, p2p3, p3p4, m2, m3, m4, m5) +
- & eta(2)*XD0(p1p2, p3, p4, p5, p4p5, p3p4, m1, m3, m4, m5) +
- & eta(3)*XD0(p1, p2p3, p4, p5, p4p5, p5p1, m1, m2, m4, m5) +
- & eta(4)*XD0(p1, p2, p3p4, p5, p1p2, p5p1, m1, m2, m3, m5) +
- & eta(5)*XD0(p1, p2, p3, p4p5, p1p2, p2p3, m1, m2, m3, m4)
- & )/detY
- end
-
diff --git a/Looptools/E/E0func.F b/Looptools/E/E0func.F
new file mode 100644
--- /dev/null
+++ b/Looptools/E/E0func.F
@@ -0,0 +1,192 @@
+* E0func.F
+* the scalar four-point function
+* this file is part of LoopTools
+* written by M. Rauch
+* last modified 21 Feb 14 th
+
+#include "externals.h"
+#include "types.h"
+
+#define npoint 5
+#include "defs.h"
+
+
+#ifndef COMPLEXPARA
+ subroutine E0func(res, para,
+ & D2345, D1345, D1245, D1235, D1234, dvalid)
+ implicit none
+ ComplexType res(0:2)
+ RealType para(1,*)
+ ComplexType D2345(*), D1345(*), D1245(*), D1235(*), D1234(*)
+ integer dvalid
+
+#include "lt.h"
+
+ ComplexType d0(5), alt
+ integer key, ier
+
+ key = ibits(versionkey, KeyE0, 2)
+
+ if( key .ne. 1 ) then
+ call E0funcb(res, para,
+ & D2345, D1345, D1245, D1235, D1234, dvalid)
+ if( key .eq. 0 ) return
+ alt = res(0)
+ endif
+
+ call ffxe0(res(0), d0, para, ier)
+ res(1) = 0
+ res(2) = 0
+
+ if( key .gt. 1 .and.
+ & abs(res(0) - alt) .gt. maxdev*abs(alt) ) then
+ print *, "Discrepancy in E0:"
+ print *, " p1 =", P(1)
+ print *, " p2 =", P(2)
+ print *, " p3 =", P(3)
+ print *, " p4 =", P(4)
+ print *, " p5 =", P(5)
+ print *, " p1p2 =", P(6)
+ print *, " p2p3 =", P(7)
+ print *, " p3p4 =", P(8)
+ print *, " p4p5 =", P(9)
+ print *, " p5p1 =", P(10)
+ print *, " m1 =", M(1)
+ print *, " m2 =", M(2)
+ print *, " m3 =", M(3)
+ print *, " m4 =", M(4)
+ print *, " m5 =", M(5)
+ print *, "E0 a =", alt
+ print *, "E0 b =", res(0)
+ if( ier .gt. errdigits ) alt = res(0)
+ endif
+
+ if( .not. btest(key, 0) ) res(0) = alt
+ end
+#endif
+
+************************************************************************
+
+#ifdef COMPLEXPARA
+ subroutine E0funcC(
+#else
+ subroutine E0funcb(
+#endif
+ & res, para, D2345, D1345, D1245, D1235, D1234, dvalid)
+ implicit none
+ ComplexType res(0:2)
+ DVAR para(1,*)
+ ComplexType D2345(*), D1345(*), D1245(*), D1235(*), D1234(*)
+ integer dvalid
+
+#include "lt.h"
+
+ DVAR p1, p2, p3, p4, p5
+ DVAR p1p2, p2p3, p3p4, p4p5, p5p1
+ DVAR m1, m2, m3, m4, m5
+
+ QVAR Y(5,5), Yi(5,5), eta(5), detY
+ integer i, j
+
+ QVAR Yflat(25), Yiflat(25)
+ equivalence (Y, Yflat)
+ equivalence (Yi, Yiflat)
+
+ m1 = M(1)
+ m2 = M(2)
+ m3 = M(3)
+ m4 = M(4)
+ m5 = M(5)
+ p1 = P(1)
+ p2 = P(2)
+ p3 = P(3)
+ p4 = P(4)
+ p5 = P(5)
+ p1p2 = P(6)
+ p2p3 = P(7)
+ p3p4 = P(8)
+ p4p5 = P(9)
+ p5p1 = P(10)
+
+ Y(1,1) = 2*m1
+ Y(2,2) = 2*m2
+ Y(3,3) = 2*m3
+ Y(4,4) = 2*m4
+ Y(5,5) = 2*m5
+ Y(1,2) = m1
+ Y(1,2) = Y(1,2) + m2
+ Y(1,2) = Y(1,2) - p1
+ Y(2,1) = Y(1,2)
+ Y(1,3) = m1
+ Y(1,3) = Y(1,3) + m3
+ Y(1,3) = Y(1,3) - p1p2
+ Y(3,1) = Y(1,3)
+ Y(1,4) = m1
+ Y(1,4) = Y(1,4) + m4
+ Y(1,4) = Y(1,4) - p4p5
+ Y(4,1) = Y(1,4)
+ Y(1,5) = m1
+ Y(1,5) = Y(1,5) + m5
+ Y(1,5) = Y(1,5) - p5
+ Y(5,1) = Y(1,5)
+ Y(2,3) = m2
+ Y(2,3) = Y(2,3) + m3
+ Y(2,3) = Y(2,3) - p2
+ Y(3,2) = Y(2,3)
+ Y(2,4) = m2
+ Y(2,4) = Y(2,4) + m4
+ Y(2,4) = Y(2,4) - p2p3
+ Y(4,2) = Y(2,4)
+ Y(2,5) = m2
+ Y(2,5) = Y(2,5) + m5
+ Y(2,5) = Y(2,5) - p5p1
+ Y(5,2) = Y(2,5)
+ Y(3,4) = m3
+ Y(3,4) = Y(3,4) + m4
+ Y(3,4) = Y(3,4) - p3
+ Y(4,3) = Y(3,4)
+ Y(3,5) = m3
+ Y(3,5) = Y(3,5) + m5
+ Y(3,5) = Y(3,5) - p3p4
+ Y(5,3) = Y(3,5)
+ Y(4,5) = m4
+ Y(4,5) = Y(4,5) + m5
+ Y(4,5) = Y(4,5) - p4
+ Y(5,4) = Y(4,5)
+
+ do i = 1, 5
+ do j = 1, 25
+ Yiflat(j) = Yflat(j)
+ enddo
+ do j = 1, 5
+ Yi(j,i) = 1
+ enddo
+ call XDet(5, Yi,5, eta(i))
+ enddo
+
+ call XDet(5, Y,5, detY)
+
+ if( dvalid .eq. 0 ) then
+ call XD0nocache(D2345, p2, p3, p4, p5p1, p2p3, p3p4,
+ & m2, m3, m4, m5)
+ call XD0nocache(D1345, p1p2, p3, p4, p5, p4p5, p3p4,
+ & m1, m3, m4, m5)
+ call XD0nocache(D1245, p1, p2p3, p4, p5, p4p5, p5p1,
+ & m1, m2, m4, m5)
+ call XD0nocache(D1235, p1, p2, p3p4, p5, p1p2, p5p1,
+ & m1, m2, m3, m5)
+ call XD0nocache(D1234, p1, p2, p3, p4p5, p1p2, p2p3,
+ & m1, m2, m3, m4)
+ endif
+
+ res(0) = -(
+ & eta(1)*D2345(dd0) +
+ & eta(2)*D1345(dd0) +
+ & eta(3)*D1245(dd0) +
+ & eta(4)*D1235(dd0) +
+ & eta(5)*D1234(dd0)
+ & )/detY
+ res(1) = 0
+ res(2) = 0
+ end
+
diff --git a/Looptools/E/Ecoeffa.F b/Looptools/E/Ecoeffa.F
--- a/Looptools/E/Ecoeffa.F
+++ b/Looptools/E/Ecoeffa.F
@@ -1,1472 +1,1461 @@
* Ecoeffa.F
* the five-point tensor coefficients
* this file is part of LoopTools
* written by M. Rauch
-* last modified 29 Sep 10 th
+* last modified 8 May 14 th
+#include "externals.h"
+#include "types.h"
+
+#define npoint 5
#include "defs.h"
- subroutine XEcoeffa(para, E, ldpara)
+ subroutine XEcoeffa(E, para, D2345, D1345, D1245, D1235, D1234)
implicit none
- integer ldpara
- DVAR para(ldpara,Pee)
- double complex E(Nee)
+ ComplexType E(*)
+ ComplexType D2345(*), D1345(*), D1245(*), D1235(*), D1234(*)
+ DVAR para(1,*)
#include "lt.h"
- integer XDget
- double complex XE0
- external XDget, XE0
-
DVAR p1, p2, p3, p4, p5
DVAR p1p2, p2p3, p3p4, p4p5, p5p1
DVAR m1, m2, m3, m4, m5
QVAR Y(5,5), Yi(5,5), Z(4,4), Zij(3,3)
QVAR eta(5), zeta(4,4), detY, detZ
- double precision del, del4
- integer i, j, k, l
- integer Di1, Di2, Di3, Di4, Di5
+ RealType del, del4
+ integer i, j, k, l, finite
logical dump
QVAR Yflat(25), Yiflat(25)
equivalence (Y, Yflat)
equivalence (Yi, Yiflat)
- double complex help1, help2, help3, help4
- double complex dabbr41, dabbr48, dabbr65, dabbr60, dabbr55
- double complex dabbr50, dabbr49, dabbr45, dabbr42, dabbr10
- double complex dabbr84, dabbr91, dabbr81, dabbr52, dabbr88
- double complex dabbr77, dabbr90, dabbr46, dabbr87, dabbr74
- double complex dabbr80, dabbr71, dabbr83, dabbr76, dabbr79
- double complex dabbr43, dabbr70, dabbr73, dabbr35, dabbr37
- double complex dabbr39, dabbr27, dabbr31, dabbr24, dabbr20
- double complex dabbr16, dabbr30, dabbr13, dabbr23, dabbr26
- double complex dabbr5, dabbr7, dabbr9, dabbr33, dabbr92
- double complex dabbr89, dabbr86, dabbr85, dabbr82, dabbr78
- double complex dabbr75, dabbr72, dabbr69, dabbr68, dabbr38
- double complex dabbr36, dabbr34, dabbr32, dabbr29, dabbr28
- double complex dabbr25, dabbr22, dabbr21, dabbr3, dabbr8
- double complex dabbr6, dabbr4, dabbr1, dabbr61, dabbr66
- double complex dabbr57, dabbr47, dabbr51, dabbr64, dabbr44
- double complex dabbr56, dabbr59, dabbr14, dabbr17, dabbr19
- double complex dabbr67, dabbr63, dabbr62, dabbr58, dabbr54
- double complex dabbr53, dabbr11, dabbr18, dabbr15, dabbr12
- double complex dabbr2, dabbr40
-
-#ifdef COMPLEXPARA
- if( abs(DIMAG(para(1,1))) +
- & abs(DIMAG(para(1,2))) +
- & abs(DIMAG(para(1,3))) +
- & abs(DIMAG(para(1,4))) +
- & abs(DIMAG(para(1,5))) +
- & abs(DIMAG(para(1,6))) +
- & abs(DIMAG(para(1,7))) +
- & abs(DIMAG(para(1,8))) +
- & abs(DIMAG(para(1,9))) +
- & abs(DIMAG(para(1,10))) .gt. 0 )
- & print *, "Warning: complex momenta not implemented"
- if( abs(DIMAG(para(1,11))) +
- & abs(DIMAG(para(1,12))) +
- & abs(DIMAG(para(1,13))) +
- & abs(DIMAG(para(1,14))) +
- & abs(DIMAG(para(1,15))) .eq. 0 ) then
- call Ecoeffa(para, E, 2)
- return
- endif
-#endif
-
- p1 = para(1,1)
- p2 = para(1,2)
- p3 = para(1,3)
- p4 = para(1,4)
- p5 = para(1,5)
- p1p2 = para(1,6)
- p2p3 = para(1,7)
- p3p4 = para(1,8)
- p4p5 = para(1,9)
- p5p1 = para(1,10)
- m1 = para(1,11)
- m2 = para(1,12)
- m3 = para(1,13)
- m4 = para(1,14)
- m5 = para(1,15)
-
- Di1 = XDget(p2, p3, p4, p5p1, p2p3, p3p4, m2, m3, m4, m5)
- Di1 = XDget(p2, p3, p4, p5p1, p2p3, p3p4, m2, m3, m4, m5)
- Di2 = XDget(p1p2, p3, p4, p5, p4p5, p3p4, m1, m3, m4, m5)
- Di3 = XDget(p1, p2p3, p4, p5, p4p5, p5p1, m1, m2, m4, m5)
- Di4 = XDget(p1, p2, p3p4, p5, p1p2, p5p1, m1, m2, m3, m5)
- Di5 = XDget(p1, p2, p3, p4p5, p1p2, p2p3, m1, m2, m3, m4)
+ ComplexType help1(0:2), help2(0:2), help3(0:2), help4(0:2)
+ ComplexType dabbr41(0:2), dabbr48(0:2), dabbr65(0:2)
+ ComplexType dabbr60(0:2), dabbr55(0:2), dabbr50(0:2)
+ ComplexType dabbr49(0:2), dabbr45(0:2), dabbr42(0:2)
+ ComplexType dabbr10(0:2), dabbr84(0:2), dabbr91(0:2)
+ ComplexType dabbr81(0:2), dabbr52(0:2), dabbr88(0:2)
+ ComplexType dabbr77(0:2), dabbr90(0:2), dabbr46(0:2)
+ ComplexType dabbr87(0:2), dabbr74(0:2), dabbr80(0:2)
+ ComplexType dabbr71(0:2), dabbr83(0:2), dabbr76(0:2)
+ ComplexType dabbr79(0:2), dabbr43(0:2), dabbr70(0:2)
+ ComplexType dabbr73(0:2), dabbr35(0:2), dabbr37(0:2)
+ ComplexType dabbr39(0:2), dabbr27(0:2), dabbr31(0:2)
+ ComplexType dabbr24(0:2), dabbr20(0:2), dabbr16(0:2)
+ ComplexType dabbr30(0:2), dabbr13(0:2), dabbr23(0:2)
+ ComplexType dabbr26(0:2), dabbr5(0:2), dabbr7(0:2)
+ ComplexType dabbr9(0:2), dabbr33(0:2), dabbr92(0:2)
+ ComplexType dabbr89(0:2), dabbr86(0:2), dabbr85(0:2)
+ ComplexType dabbr82(0:2), dabbr78(0:2), dabbr75(0:2)
+ ComplexType dabbr72(0:2), dabbr69(0:2), dabbr68(0:2)
+ ComplexType dabbr38(0:2), dabbr36(0:2), dabbr34(0:2)
+ ComplexType dabbr32(0:2), dabbr29(0:2), dabbr28(0:2)
+ ComplexType dabbr25(0:2), dabbr22(0:2), dabbr21(0:2)
+ ComplexType dabbr3(0:2), dabbr8(0:2), dabbr6(0:2)
+ ComplexType dabbr4(0:2), dabbr1(0:2), dabbr61(0:2)
+ ComplexType dabbr66(0:2), dabbr57(0:2), dabbr47(0:2)
+ ComplexType dabbr51(0:2), dabbr64(0:2), dabbr44(0:2)
+ ComplexType dabbr56(0:2), dabbr59(0:2), dabbr14(0:2)
+ ComplexType dabbr17(0:2), dabbr19(0:2), dabbr67(0:2)
+ ComplexType dabbr63(0:2), dabbr62(0:2), dabbr58(0:2)
+ ComplexType dabbr54(0:2), dabbr53(0:2), dabbr11(0:2)
+ ComplexType dabbr18(0:2), dabbr15(0:2), dabbr12(0:2)
+ ComplexType dabbr2(0:2), dabbr40(0:2)
serial = serial + 1
dump = ibits(debugkey, DebugE, 1) .ne. 0 .and.
& serial .ge. debugfrom .and. serial .le. debugto
- if( dump ) call XDumpPara(5, para, ldpara, "Ecoeffa")
+ if( dump ) call XDumpPara(5, para, "Ecoeffa")
- Y(1,1) = 2*QPREC(m1)
- Y(2,2) = 2*QPREC(m2)
- Y(3,3) = 2*QPREC(m3)
- Y(4,4) = 2*QPREC(m4)
- Y(5,5) = 2*QPREC(m5)
- Y(1,2) = QPREC(m1) + QPREC(m2) - QPREC(p1)
+ m1 = M(1)
+ m2 = M(2)
+ m3 = M(3)
+ m4 = M(4)
+ m5 = M(5)
+ p1 = P(1)
+ p2 = P(2)
+ p3 = P(3)
+ p4 = P(4)
+ p5 = P(5)
+ p1p2 = P(6)
+ p2p3 = P(7)
+ p3p4 = P(8)
+ p4p5 = P(9)
+ p5p1 = P(10)
+
+ finite = 0
+ del = 0
+ if( lambda .ge. 0 ) then
+ finite = 1
+ del = (delta + log(mudim))/24D0
+ else if( lambda .eq. -1 ) then
+ del = 1/24D0
+ endif
+ del4 = .25D0*del
+
+ Y(1,1) = 2*m1
+ Y(2,2) = 2*m2
+ Y(3,3) = 2*m3
+ Y(4,4) = 2*m4
+ Y(5,5) = 2*m5
+ Y(1,2) = m1
+ Y(1,2) = Y(1,2) + m2
+ Y(1,2) = Y(1,2) - p1
Y(2,1) = Y(1,2)
- Y(1,3) = QPREC(m1) + QPREC(m3) - QPREC(p1p2)
+ Y(1,3) = m1
+ Y(1,3) = Y(1,3) + m3
+ Y(1,3) = Y(1,3) - p1p2
Y(3,1) = Y(1,3)
- Y(1,4) = QPREC(m1) + QPREC(m4) - QPREC(p4p5)
+ Y(1,4) = m1
+ Y(1,4) = Y(1,4) + m4
+ Y(1,4) = Y(1,4) - p4p5
Y(4,1) = Y(1,4)
- Y(1,5) = QPREC(m1) + QPREC(m5) - QPREC(p5)
+ Y(1,5) = m1
+ Y(1,5) = Y(1,5) + m5
+ Y(1,5) = Y(1,5) - p5
Y(5,1) = Y(1,5)
- Y(2,3) = QPREC(m2) + QPREC(m3) - QPREC(p2)
+ Y(2,3) = m2
+ Y(2,3) = Y(2,3) + m3
+ Y(2,3) = Y(2,3) - p2
Y(3,2) = Y(2,3)
- Y(2,4) = QPREC(m2) + QPREC(m4) - QPREC(p2p3)
+ Y(2,4) = m2
+ Y(2,4) = Y(2,4) + m4
+ Y(2,4) = Y(2,4) - p2p3
Y(4,2) = Y(2,4)
- Y(2,5) = QPREC(m2) + QPREC(m5) - QPREC(p5p1)
+ Y(2,5) = m2
+ Y(2,5) = Y(2,5) + m5
+ Y(2,5) = Y(2,5) - p5p1
Y(5,2) = Y(2,5)
- Y(3,4) = QPREC(m3) + QPREC(m4) - QPREC(p3)
+ Y(3,4) = m3
+ Y(3,4) = Y(3,4) + m4
+ Y(3,4) = Y(3,4) - p3
Y(4,3) = Y(3,4)
- Y(3,5) = QPREC(m3) + QPREC(m5) - QPREC(p3p4)
+ Y(3,5) = m3
+ Y(3,5) = Y(3,5) + m5
+ Y(3,5) = Y(3,5) - p3p4
Y(5,3) = Y(3,5)
- Y(4,5) = QPREC(m4) + QPREC(m5) - QPREC(p4)
+ Y(4,5) = m4
+ Y(4,5) = Y(4,5) + m5
+ Y(4,5) = Y(4,5) - p4
Y(5,4) = Y(4,5)
* calculate the Y(i), their determinants, and eta(i)
do i = 1, 5
do j = 1, 25
Yiflat(j) = Yflat(j)
enddo
do j = 1, 5
Yi(j,i) = 1
enddo
call XDet(5, Yi,5, eta(i))
enddo
* Y is no longer needed, now calculate its determinant and
* add the missing factor 1/detY to eta
call XDet(5, Y,5, detY)
do i = 1, 5
eta(i) = eta(i)/detY
enddo
- Z(1,1) = 2*QPREC(p1)
- Z(2,2) = 2*QPREC(p1p2)
- Z(3,3) = 2*QPREC(p4p5)
- Z(4,4) = 2*QPREC(p5)
- Z(1,2) = QPREC(p1) + QPREC(p1p2) - QPREC(p2)
+ Z(1,1) = 2*p1
+ Z(2,2) = 2*p1p2
+ Z(3,3) = 2*p4p5
+ Z(4,4) = 2*p5
+ Z(1,2) = p1
+ Z(1,2) = Z(1,2) + p1p2
+ Z(1,2) = Z(1,2) - p2
Z(2,1) = Z(1,2)
- Z(1,3) = QPREC(p1) - QPREC(p2p3) + QPREC(p4p5)
+ Z(1,3) = p1
+ Z(1,3) = Z(1,3) - p2p3
+ Z(1,3) = Z(1,3) + p4p5
Z(3,1) = Z(1,3)
- Z(1,4) = QPREC(p1) - QPREC(p5p1) + QPREC(p5)
+ Z(1,4) = p1
+ Z(1,4) = Z(1,4) - p5p1
+ Z(1,4) = Z(1,4) + p5
Z(4,1) = Z(1,4)
- Z(2,3) = QPREC(p1p2) - QPREC(p3) + QPREC(p4p5)
+ Z(2,3) = p1p2
+ Z(2,3) = Z(2,3) - p3
+ Z(2,3) = Z(2,3) + p4p5
Z(3,2) = Z(2,3)
- Z(2,4) = QPREC(p1p2) - QPREC(p3p4) + QPREC(p5)
+ Z(2,4) = p1p2
+ Z(2,4) = Z(2,4) - p3p4
+ Z(2,4) = Z(2,4) + p5
Z(4,2) = Z(2,4)
- Z(3,4) = QPREC(p5) + QPREC(p4p5) - QPREC(p4)
+ Z(3,4) = p5
+ Z(3,4) = Z(3,4) + p4p5
+ Z(3,4) = Z(3,4) - p4
Z(4,3) = Z(3,4)
* calculate the zeta(i,j)
do i = 1, 4
do j = i, 4
* generate the submatrix Z_ij
do l = 1, 3
do k = 1, 3
Zij(k,l) = Z(k + ibits(not(k - i), 3, 1),
& l + ibits(not(l - j), 3, 1))
enddo
enddo
call XDet(3, Zij,3, detZ)
zeta(i,j) = Sgn(i + j)*detZ/detY
zeta(j,i) = zeta(i,j)
enddo
enddo
call XDet(4, Z,4, detZ)
- del = (delta + log(mudim))/24D0
- del4 = .25D0*del
+ help1 = D2345(DD003) + 2*D2345(DD0033) + D2345(DD00333)
+ help2 = D2345(DD002) + 2*D2345(DD0023) + D2345(DD00233)
+ help3 = D2345(DD001) + 2*D2345(DD0013) + D2345(DD00133)
+ help4 = D2345(DD00) + 2*D2345(DD003) + D2345(DD0033)
+ dabbr41 = D2345(DD00223) + D2345(DD00233)
+ dabbr48 = D2345(DD00113) + D2345(DD00133)
+ dabbr65 = D2345(DD0023) + D2345(DD00123)
+ dabbr60 = D2345(DD0013) + D2345(DD00123)
+ dabbr55 = D2345(DD0012) + D2345(DD00123)
+ dabbr50 = D2345(DD00112) + D2345(DD00122)
+ dabbr49 = D2345(DD2233) + D2345(DD2333)
+ dabbr45 = D2345(DD2223) + D2345(DD2233)
+ dabbr42 = D2345(DD1223) + D2345(DD1233)
+ dabbr10 = D2345(DD223) + D2345(DD233)
+ dabbr84 = D2345(DD0033) + D2345(DD00233) + D2345(DD00333)
+ dabbr91 = D2345(DD0033) + D2345(DD00133) + D2345(DD00333)
+ dabbr81 = dabbr41 + D2345(DD0023)
+ dabbr52 = D2345(DD0033) + D2345(DD00133) + D2345(DD00233)
+ dabbr88 = dabbr65 + D2345(DD00233)
+ dabbr77 = D2345(DD0022) + D2345(DD00222) + D2345(DD00223)
+ dabbr90 = dabbr65 + D2345(DD00223)
+ dabbr46 = D2345(DD0022) + D2345(DD00122) + D2345(DD00223)
+ dabbr87 = D2345(DD0022) + D2345(DD00122) + D2345(DD00222)
+ dabbr74 = dabbr60 + D2345(DD00133)
+ dabbr80 = dabbr48 + D2345(DD0013)
+ dabbr71 = dabbr55 + D2345(DD00122)
+ dabbr83 = dabbr60 + D2345(DD00113)
+ dabbr76 = dabbr55 + D2345(DD00112)
+ dabbr79 = dabbr50 + D2345(DD0012)
+ dabbr43 = D2345(DD0011) + D2345(DD00112) + D2345(DD00113)
+ dabbr70 = D2345(DD0011) + D2345(DD00111) + D2345(DD00113)
+ dabbr73 = D2345(DD0011) + D2345(DD00111) + D2345(DD00112)
+ dabbr35 = (D2345(DD0000) - del) +
+ & (D2345(DD00002) + del4) + (D2345(DD00003) + del4)
+ dabbr37 = (D2345(DD0000) - del) +
+ & (D2345(DD00001) + del4) + (D2345(DD00003) + del4)
+ dabbr39 = (D2345(DD0000) - del) +
+ & (D2345(DD00001) + del4) + (D2345(DD00002) + del4)
+ dabbr27 = D2345(DD003) + D2345(DD0023) + D2345(DD0033)
+ dabbr31 = D2345(DD003) + D2345(DD0013) + D2345(DD0033)
+ dabbr24 = D2345(DD002) + D2345(DD0022) + D2345(DD0023)
+ dabbr20 = D2345(DD003) + D2345(DD0013) + D2345(DD0023)
+ dabbr16 = D2345(DD002) + D2345(DD0012) + D2345(DD0023)
+ dabbr30 = D2345(DD002) + D2345(DD0012) + D2345(DD0022)
+ dabbr13 = D2345(DD001) + D2345(DD0012) + D2345(DD0013)
+ dabbr23 = D2345(DD001) + D2345(DD0011) + D2345(DD0013)
+ dabbr26 = D2345(DD001) + D2345(DD0011) + D2345(DD0012)
+ dabbr5 = D2345(DD00) + D2345(DD002) + D2345(DD003)
+ dabbr7 = D2345(DD00) + D2345(DD001) + D2345(DD003)
+ dabbr9 = D2345(DD00) + D2345(DD001) + D2345(DD002)
+ dabbr33 = dabbr35 + (D2345(DD00001) + del4)
+ dabbr92 = D2345(DD333) + D2345(DD1333) +
+ & D2345(DD2333) + D2345(DD3333)
+ dabbr89 = dabbr49 + D2345(DD233) + D2345(DD1233)
+ dabbr86 = dabbr45 + D2345(DD223) + D2345(DD1223)
+ dabbr85 = D2345(DD222) + D2345(DD1222) +
+ & D2345(DD2222) + D2345(DD2223)
+ dabbr82 = D2345(DD133) + D2345(DD1133) +
+ & D2345(DD1233) + D2345(DD1333)
+ dabbr78 = dabbr42 + D2345(DD123) + D2345(DD1123)
+ dabbr75 = D2345(DD122) + D2345(DD1122) +
+ & D2345(DD1222) + D2345(DD1223)
+ dabbr72 = D2345(DD113) + D2345(DD1113) +
+ & D2345(DD1123) + D2345(DD1133)
+ dabbr69 = D2345(DD112) + D2345(DD1112) +
+ & D2345(DD1122) + D2345(DD1123)
+ dabbr68 = D2345(DD111) + D2345(DD1111) +
+ & D2345(DD1112) + D2345(DD1113)
+ dabbr38 = dabbr27 + D2345(DD0013)
+ dabbr36 = dabbr24 + D2345(DD0012)
+ dabbr34 = dabbr13 + D2345(DD0011)
+ dabbr32 = D2345(DD33) + D2345(DD133) +
+ & D2345(DD233) + D2345(DD333)
+ dabbr29 = dabbr10 + D2345(DD23) + D2345(DD123)
+ dabbr28 = D2345(DD22) + D2345(DD122) +
+ & D2345(DD222) + D2345(DD223)
+ dabbr25 = D2345(DD13) + D2345(DD113) +
+ & D2345(DD123) + D2345(DD133)
+ dabbr22 = D2345(DD12) + D2345(DD112) +
+ & D2345(DD122) + D2345(DD123)
+ dabbr21 = D2345(DD11) + D2345(DD111) +
+ & D2345(DD112) + D2345(DD113)
+ dabbr3 = dabbr5 + D2345(DD001)
+ dabbr8 = D2345(DD3) + D2345(DD13) + D2345(DD23) + D2345(DD33)
+ dabbr6 = D2345(DD2) + D2345(DD12) + D2345(DD22) + D2345(DD23)
+ dabbr4 = D2345(DD1) + D2345(DD11) + D2345(DD12) + D2345(DD13)
+ dabbr1 = D2345(DD0) + D2345(DD1) + D2345(DD2) + D2345(DD3)
+ dabbr61 = help1 + 2*D2345(DD0023) +
+ & D2345(DD00223) + 2*D2345(DD00233)
+ dabbr66 = help1 + 2*D2345(DD0013) +
+ & D2345(DD00113) + 2*D2345(DD00133)
+ dabbr57 = help2 + 2*D2345(DD0022) +
+ & D2345(DD00222) + 2*D2345(DD00223)
+ dabbr47 = help2 + 2*D2345(DD0012) +
+ & D2345(DD00112) + 2*D2345(DD00123)
+ dabbr51 = D2345(DD003) + 2*D2345(DD0013) +
+ & 2*D2345(DD0023) + D2345(DD00113) +
+ & 2*D2345(DD00123) + D2345(DD00223)
+ dabbr64 = D2345(DD002) + 2*D2345(DD0012) +
+ & 2*D2345(DD0022) + D2345(DD00112) +
+ & 2*D2345(DD00122) + D2345(DD00222)
+ dabbr44 = help3 + 2*D2345(DD0012) +
+ & D2345(DD00122) + 2*D2345(DD00123)
+ dabbr56 = help3 + 2*D2345(DD0011) +
+ & D2345(DD00111) + 2*D2345(DD00113)
+ dabbr59 = D2345(DD001) + 2*D2345(DD0011) +
+ & 2*D2345(DD0012) + D2345(DD00111) +
+ & 2*D2345(DD00112) + D2345(DD00122)
+ dabbr14 = help4 + 2*D2345(DD002) +
+ & D2345(DD0022) + 2*D2345(DD0023)
+ dabbr17 = help4 + 2*D2345(DD001) +
+ & D2345(DD0011) + 2*D2345(DD0013)
+ dabbr19 = D2345(DD00) + 2*D2345(DD001) +
+ & 2*D2345(DD002) + D2345(DD0011) +
+ & 2*D2345(DD0012) + D2345(DD0022)
+ dabbr67 = D2345(DD33) + 2*D2345(DD133) +
+ & 2*D2345(DD233) + 2*D2345(DD333) +
+ & D2345(DD1133) + 2*D2345(DD1233) +
+ & 2*D2345(DD1333) + D2345(DD2233) +
+ & 2*D2345(DD2333) + D2345(DD3333)
+ dabbr63 = D2345(DD23) + 2*D2345(DD123) +
+ & 2*D2345(DD223) + 2*D2345(DD233) +
+ & D2345(DD1123) + 2*D2345(DD1223) +
+ & 2*D2345(DD1233) + D2345(DD2223) +
+ & 2*D2345(DD2233) + D2345(DD2333)
+ dabbr62 = D2345(DD22) + 2*D2345(DD122) +
+ & 2*D2345(DD222) + 2*D2345(DD223) +
+ & D2345(DD1122) + 2*D2345(DD1222) +
+ & 2*D2345(DD1223) + D2345(DD2222) +
+ & 2*D2345(DD2223) + D2345(DD2233)
+ dabbr58 = D2345(DD13) + 2*D2345(DD113) +
+ & 2*D2345(DD123) + 2*D2345(DD133) +
+ & D2345(DD1113) + 2*D2345(DD1123) +
+ & 2*D2345(DD1133) + D2345(DD1223) +
+ & 2*D2345(DD1233) + D2345(DD1333)
+ dabbr54 = D2345(DD12) + 2*D2345(DD112) +
+ & 2*D2345(DD122) + 2*D2345(DD123) +
+ & D2345(DD1112) + 2*D2345(DD1122) +
+ & 2*D2345(DD1123) + D2345(DD1222) +
+ & 2*D2345(DD1223) + D2345(DD1233)
+ dabbr53 = D2345(DD11) + 2*D2345(DD111) +
+ & 2*D2345(DD112) + 2*D2345(DD113) +
+ & D2345(DD1111) + 2*D2345(DD1112) +
+ & 2*D2345(DD1113) + D2345(DD1122) +
+ & 2*D2345(DD1123) + D2345(DD1133)
+ dabbr11 = dabbr14 + 2*D2345(DD001) +
+ & D2345(DD0011) + 2*D2345(DD0012) +
+ & 2*D2345(DD0013)
+ dabbr18 = D2345(DD3) + 2*D2345(DD13) +
+ & 2*D2345(DD23) + 2*D2345(DD33) +
+ & D2345(DD113) + 2*D2345(DD123) +
+ & 2*D2345(DD133) + D2345(DD223) +
+ & 2*D2345(DD233) + D2345(DD333)
+ dabbr15 = D2345(DD2) + 2*D2345(DD12) +
+ & 2*D2345(DD22) + 2*D2345(DD23) +
+ & D2345(DD112) + 2*D2345(DD122) +
+ & 2*D2345(DD123) + D2345(DD222) +
+ & 2*D2345(DD223) + D2345(DD233)
+ dabbr12 = D2345(DD1) + 2*D2345(DD11) +
+ & 2*D2345(DD12) + 2*D2345(DD13) +
+ & D2345(DD111) + 2*D2345(DD112) +
+ & 2*D2345(DD113) + D2345(DD122) +
+ & 2*D2345(DD123) + D2345(DD133)
+ dabbr2 = D2345(DD0) + 2*D2345(DD1) +
+ & 2*D2345(DD2) + 2*D2345(DD3) +
+ & D2345(DD11) + 2*D2345(DD12) +
+ & 2*D2345(DD13) + D2345(DD22) +
+ & 2*D2345(DD23) + D2345(DD33)
+ dabbr40 = D2345(DD0) + 4*D2345(DD1) +
+ & 4*D2345(DD2) + 4*D2345(DD3) +
+ & 6*D2345(DD11) + 12*D2345(DD12) +
+ & 12*D2345(DD13) + 6*D2345(DD22) +
+ & 12*D2345(DD23) + 6*D2345(DD33) +
+ & 4*D2345(DD111) + 12*D2345(DD112) +
+ & 12*D2345(DD113) + 12*D2345(DD122) +
+ & 24*D2345(DD123) + 12*D2345(DD133) +
+ & 4*D2345(DD222) + 12*D2345(DD223) +
+ & 12*D2345(DD233) + 4*D2345(DD333) +
+ & D2345(DD1111) + 4*D2345(DD1112) +
+ & 4*D2345(DD1113) + 6*D2345(DD1122) +
+ & 12*D2345(DD1123) + 6*D2345(DD1133) +
+ & 4*D2345(DD1222) + 12*D2345(DD1223) +
+ & 12*D2345(DD1233) + 4*D2345(DD1333) +
+ & D2345(DD2222) + 4*D2345(DD2223) +
+ & 6*D2345(DD2233) + 4*D2345(DD2333) +
+ & D2345(DD3333)
- help1 = Dval(dd003,Di1) + 2*Dval(dd0033,Di1) +
- & Dval(dd00333,Di1)
- help2 = Dval(dd002,Di1) + 2*Dval(dd0023,Di1) +
- & Dval(dd00233,Di1)
- help3 = Dval(dd001,Di1) + 2*Dval(dd0013,Di1) +
- & Dval(dd00133,Di1)
- help4 = Dval(dd00,Di1) + 2*Dval(dd003,Di1) +
- & Dval(dd0033,Di1)
- dabbr41 = Dval(dd00223,Di1) + Dval(dd00233,Di1)
- dabbr48 = Dval(dd00113,Di1) + Dval(dd00133,Di1)
- dabbr65 = Dval(dd0023,Di1) + Dval(dd00123,Di1)
- dabbr60 = Dval(dd0013,Di1) + Dval(dd00123,Di1)
- dabbr55 = Dval(dd0012,Di1) + Dval(dd00123,Di1)
- dabbr50 = Dval(dd00112,Di1) + Dval(dd00122,Di1)
- dabbr49 = Dval(dd2233,Di1) + Dval(dd2333,Di1)
- dabbr45 = Dval(dd2223,Di1) + Dval(dd2233,Di1)
- dabbr42 = Dval(dd1223,Di1) + Dval(dd1233,Di1)
- dabbr10 = Dval(dd223,Di1) + Dval(dd233,Di1)
- dabbr84 = Dval(dd0033,Di1) + Dval(dd00233,Di1) +
- & Dval(dd00333,Di1)
- dabbr91 = Dval(dd0033,Di1) + Dval(dd00133,Di1) +
- & Dval(dd00333,Di1)
- dabbr81 = dabbr41 + Dval(dd0023,Di1)
- dabbr52 = Dval(dd0033,Di1) + Dval(dd00133,Di1) +
- & Dval(dd00233,Di1)
- dabbr88 = dabbr65 + Dval(dd00233,Di1)
- dabbr77 = Dval(dd0022,Di1) + Dval(dd00222,Di1) +
- & Dval(dd00223,Di1)
- dabbr90 = dabbr65 + Dval(dd00223,Di1)
- dabbr46 = Dval(dd0022,Di1) + Dval(dd00122,Di1) +
- & Dval(dd00223,Di1)
- dabbr87 = Dval(dd0022,Di1) + Dval(dd00122,Di1) +
- & Dval(dd00222,Di1)
- dabbr74 = dabbr60 + Dval(dd00133,Di1)
- dabbr80 = dabbr48 + Dval(dd0013,Di1)
- dabbr71 = dabbr55 + Dval(dd00122,Di1)
- dabbr83 = dabbr60 + Dval(dd00113,Di1)
- dabbr76 = dabbr55 + Dval(dd00112,Di1)
- dabbr79 = dabbr50 + Dval(dd0012,Di1)
- dabbr43 = Dval(dd0011,Di1) + Dval(dd00112,Di1) +
- & Dval(dd00113,Di1)
- dabbr70 = Dval(dd0011,Di1) + Dval(dd00111,Di1) +
- & Dval(dd00113,Di1)
- dabbr73 = Dval(dd0011,Di1) + Dval(dd00111,Di1) +
- & Dval(dd00112,Di1)
- dabbr35 = (Dval(dd0000,Di1) - del) +
- & (Dval(dd00002,Di1) + del4) +
- & (Dval(dd00003,Di1) + del4)
- dabbr37 = (Dval(dd0000,Di1) - del) +
- & (Dval(dd00001,Di1) + del4) +
- & (Dval(dd00003,Di1) + del4)
- dabbr39 = (Dval(dd0000,Di1) - del) +
- & (Dval(dd00001,Di1) + del4) +
- & (Dval(dd00002,Di1) + del4)
- dabbr27 = Dval(dd003,Di1) + Dval(dd0023,Di1) +
- & Dval(dd0033,Di1)
- dabbr31 = Dval(dd003,Di1) + Dval(dd0013,Di1) +
- & Dval(dd0033,Di1)
- dabbr24 = Dval(dd002,Di1) + Dval(dd0022,Di1) +
- & Dval(dd0023,Di1)
- dabbr20 = Dval(dd003,Di1) + Dval(dd0013,Di1) +
- & Dval(dd0023,Di1)
- dabbr16 = Dval(dd002,Di1) + Dval(dd0012,Di1) +
- & Dval(dd0023,Di1)
- dabbr30 = Dval(dd002,Di1) + Dval(dd0012,Di1) +
- & Dval(dd0022,Di1)
- dabbr13 = Dval(dd001,Di1) + Dval(dd0012,Di1) +
- & Dval(dd0013,Di1)
- dabbr23 = Dval(dd001,Di1) + Dval(dd0011,Di1) +
- & Dval(dd0013,Di1)
- dabbr26 = Dval(dd001,Di1) + Dval(dd0011,Di1) +
- & Dval(dd0012,Di1)
- dabbr5 = Dval(dd00,Di1) + Dval(dd002,Di1) +
- & Dval(dd003,Di1)
- dabbr7 = Dval(dd00,Di1) + Dval(dd001,Di1) +
- & Dval(dd003,Di1)
- dabbr9 = Dval(dd00,Di1) + Dval(dd001,Di1) +
- & Dval(dd002,Di1)
- dabbr33 = dabbr35 + (Dval(dd00001,Di1) + del4)
- dabbr92 = Dval(dd333,Di1) + Dval(dd1333,Di1) +
- & Dval(dd2333,Di1) + Dval(dd3333,Di1)
- dabbr89 = dabbr49 + Dval(dd233,Di1) + Dval(dd1233,Di1)
- dabbr86 = dabbr45 + Dval(dd223,Di1) + Dval(dd1223,Di1)
- dabbr85 = Dval(dd222,Di1) + Dval(dd1222,Di1) +
- & Dval(dd2222,Di1) + Dval(dd2223,Di1)
- dabbr82 = Dval(dd133,Di1) + Dval(dd1133,Di1) +
- & Dval(dd1233,Di1) + Dval(dd1333,Di1)
- dabbr78 = dabbr42 + Dval(dd123,Di1) + Dval(dd1123,Di1)
- dabbr75 = Dval(dd122,Di1) + Dval(dd1122,Di1) +
- & Dval(dd1222,Di1) + Dval(dd1223,Di1)
- dabbr72 = Dval(dd113,Di1) + Dval(dd1113,Di1) +
- & Dval(dd1123,Di1) + Dval(dd1133,Di1)
- dabbr69 = Dval(dd112,Di1) + Dval(dd1112,Di1) +
- & Dval(dd1122,Di1) + Dval(dd1123,Di1)
- dabbr68 = Dval(dd111,Di1) + Dval(dd1111,Di1) +
- & Dval(dd1112,Di1) + Dval(dd1113,Di1)
- dabbr38 = dabbr27 + Dval(dd0013,Di1)
- dabbr36 = dabbr24 + Dval(dd0012,Di1)
- dabbr34 = dabbr13 + Dval(dd0011,Di1)
- dabbr32 = Dval(dd33,Di1) + Dval(dd133,Di1) +
- & Dval(dd233,Di1) + Dval(dd333,Di1)
- dabbr29 = dabbr10 + Dval(dd23,Di1) + Dval(dd123,Di1)
- dabbr28 = Dval(dd22,Di1) + Dval(dd122,Di1) +
- & Dval(dd222,Di1) + Dval(dd223,Di1)
- dabbr25 = Dval(dd13,Di1) + Dval(dd113,Di1) +
- & Dval(dd123,Di1) + Dval(dd133,Di1)
- dabbr22 = Dval(dd12,Di1) + Dval(dd112,Di1) +
- & Dval(dd122,Di1) + Dval(dd123,Di1)
- dabbr21 = Dval(dd11,Di1) + Dval(dd111,Di1) +
- & Dval(dd112,Di1) + Dval(dd113,Di1)
- dabbr3 = dabbr5 + Dval(dd001,Di1)
- dabbr8 = Dval(dd3,Di1) + Dval(dd13,Di1) +
- & Dval(dd23,Di1) + Dval(dd33,Di1)
- dabbr6 = Dval(dd2,Di1) + Dval(dd12,Di1) +
- & Dval(dd22,Di1) + Dval(dd23,Di1)
- dabbr4 = Dval(dd1,Di1) + Dval(dd11,Di1) +
- & Dval(dd12,Di1) + Dval(dd13,Di1)
- dabbr1 = Dval(dd0,Di1) + Dval(dd1,Di1) +
- & Dval(dd2,Di1) + Dval(dd3,Di1)
- dabbr61 = help1 + 2*Dval(dd0023,Di1) +
- & Dval(dd00223,Di1) + 2*Dval(dd00233,Di1)
- dabbr66 = help1 + 2*Dval(dd0013,Di1) +
- & Dval(dd00113,Di1) + 2*Dval(dd00133,Di1)
- dabbr57 = help2 + 2*Dval(dd0022,Di1) +
- & Dval(dd00222,Di1) + 2*Dval(dd00223,Di1)
- dabbr47 = help2 + 2*Dval(dd0012,Di1) +
- & Dval(dd00112,Di1) + 2*Dval(dd00123,Di1)
- dabbr51 = Dval(dd003,Di1) + 2*Dval(dd0013,Di1) +
- & 2*Dval(dd0023,Di1) + Dval(dd00113,Di1) +
- & 2*Dval(dd00123,Di1) + Dval(dd00223,Di1)
- dabbr64 = Dval(dd002,Di1) + 2*Dval(dd0012,Di1) +
- & 2*Dval(dd0022,Di1) + Dval(dd00112,Di1) +
- & 2*Dval(dd00122,Di1) + Dval(dd00222,Di1)
- dabbr44 = help3 + 2*Dval(dd0012,Di1) +
- & Dval(dd00122,Di1) + 2*Dval(dd00123,Di1)
- dabbr56 = help3 + 2*Dval(dd0011,Di1) +
- & Dval(dd00111,Di1) + 2*Dval(dd00113,Di1)
- dabbr59 = Dval(dd001,Di1) + 2*Dval(dd0011,Di1) +
- & 2*Dval(dd0012,Di1) + Dval(dd00111,Di1) +
- & 2*Dval(dd00112,Di1) + Dval(dd00122,Di1)
- dabbr14 = help4 + 2*Dval(dd002,Di1) +
- & Dval(dd0022,Di1) + 2*Dval(dd0023,Di1)
- dabbr17 = help4 + 2*Dval(dd001,Di1) +
- & Dval(dd0011,Di1) + 2*Dval(dd0013,Di1)
- dabbr19 = Dval(dd00,Di1) + 2*Dval(dd001,Di1) +
- & 2*Dval(dd002,Di1) + Dval(dd0011,Di1) +
- & 2*Dval(dd0012,Di1) + Dval(dd0022,Di1)
- dabbr67 = Dval(dd33,Di1) + 2*Dval(dd133,Di1) +
- & 2*Dval(dd233,Di1) + 2*Dval(dd333,Di1) +
- & Dval(dd1133,Di1) + 2*Dval(dd1233,Di1) +
- & 2*Dval(dd1333,Di1) + Dval(dd2233,Di1) +
- & 2*Dval(dd2333,Di1) + Dval(dd3333,Di1)
- dabbr63 = Dval(dd23,Di1) + 2*Dval(dd123,Di1) +
- & 2*Dval(dd223,Di1) + 2*Dval(dd233,Di1) +
- & Dval(dd1123,Di1) + 2*Dval(dd1223,Di1) +
- & 2*Dval(dd1233,Di1) + Dval(dd2223,Di1) +
- & 2*Dval(dd2233,Di1) + Dval(dd2333,Di1)
- dabbr62 = Dval(dd22,Di1) + 2*Dval(dd122,Di1) +
- & 2*Dval(dd222,Di1) + 2*Dval(dd223,Di1) +
- & Dval(dd1122,Di1) + 2*Dval(dd1222,Di1) +
- & 2*Dval(dd1223,Di1) + Dval(dd2222,Di1) +
- & 2*Dval(dd2223,Di1) + Dval(dd2233,Di1)
- dabbr58 = Dval(dd13,Di1) + 2*Dval(dd113,Di1) +
- & 2*Dval(dd123,Di1) + 2*Dval(dd133,Di1) +
- & Dval(dd1113,Di1) + 2*Dval(dd1123,Di1) +
- & 2*Dval(dd1133,Di1) + Dval(dd1223,Di1) +
- & 2*Dval(dd1233,Di1) + Dval(dd1333,Di1)
- dabbr54 = Dval(dd12,Di1) + 2*Dval(dd112,Di1) +
- & 2*Dval(dd122,Di1) + 2*Dval(dd123,Di1) +
- & Dval(dd1112,Di1) + 2*Dval(dd1122,Di1) +
- & 2*Dval(dd1123,Di1) + Dval(dd1222,Di1) +
- & 2*Dval(dd1223,Di1) + Dval(dd1233,Di1)
- dabbr53 = Dval(dd11,Di1) + 2*Dval(dd111,Di1) +
- & 2*Dval(dd112,Di1) + 2*Dval(dd113,Di1) +
- & Dval(dd1111,Di1) + 2*Dval(dd1112,Di1) +
- & 2*Dval(dd1113,Di1) + Dval(dd1122,Di1) +
- & 2*Dval(dd1123,Di1) + Dval(dd1133,Di1)
- dabbr11 = dabbr14 + 2*Dval(dd001,Di1) +
- & Dval(dd0011,Di1) + 2*Dval(dd0012,Di1) +
- & 2*Dval(dd0013,Di1)
- dabbr18 = Dval(dd3,Di1) + 2*Dval(dd13,Di1) +
- & 2*Dval(dd23,Di1) + 2*Dval(dd33,Di1) +
- & Dval(dd113,Di1) + 2*Dval(dd123,Di1) +
- & 2*Dval(dd133,Di1) + Dval(dd223,Di1) +
- & 2*Dval(dd233,Di1) + Dval(dd333,Di1)
- dabbr15 = Dval(dd2,Di1) + 2*Dval(dd12,Di1) +
- & 2*Dval(dd22,Di1) + 2*Dval(dd23,Di1) +
- & Dval(dd112,Di1) + 2*Dval(dd122,Di1) +
- & 2*Dval(dd123,Di1) + Dval(dd222,Di1) +
- & 2*Dval(dd223,Di1) + Dval(dd233,Di1)
- dabbr12 = Dval(dd1,Di1) + 2*Dval(dd11,Di1) +
- & 2*Dval(dd12,Di1) + 2*Dval(dd13,Di1) +
- & Dval(dd111,Di1) + 2*Dval(dd112,Di1) +
- & 2*Dval(dd113,Di1) + Dval(dd122,Di1) +
- & 2*Dval(dd123,Di1) + Dval(dd133,Di1)
- dabbr2 = Dval(dd0,Di1) + 2*Dval(dd1,Di1) +
- & 2*Dval(dd2,Di1) + 2*Dval(dd3,Di1) +
- & Dval(dd11,Di1) + 2*Dval(dd12,Di1) +
- & 2*Dval(dd13,Di1) + Dval(dd22,Di1) +
- & 2*Dval(dd23,Di1) + Dval(dd33,Di1)
- dabbr40 = Dval(dd0,Di1) + 4*Dval(dd1,Di1) +
- & 4*Dval(dd2,Di1) + 4*Dval(dd3,Di1) +
- & 6*Dval(dd11,Di1) + 12*Dval(dd12,Di1) +
- & 12*Dval(dd13,Di1) + 6*Dval(dd22,Di1) +
- & 12*Dval(dd23,Di1) + 6*Dval(dd33,Di1) +
- & 4*Dval(dd111,Di1) + 12*Dval(dd112,Di1) +
- & 12*Dval(dd113,Di1) + 12*Dval(dd122,Di1) +
- & 24*Dval(dd123,Di1) + 12*Dval(dd133,Di1) +
- & 4*Dval(dd222,Di1) + 12*Dval(dd223,Di1) +
- & 12*Dval(dd233,Di1) + 4*Dval(dd333,Di1) +
- & Dval(dd1111,Di1) + 4*Dval(dd1112,Di1) +
- & 4*Dval(dd1113,Di1) + 6*Dval(dd1122,Di1) +
- & 12*Dval(dd1123,Di1) + 6*Dval(dd1133,Di1) +
- & 4*Dval(dd1222,Di1) + 12*Dval(dd1223,Di1) +
- & 12*Dval(dd1233,Di1) + 4*Dval(dd1333,Di1) +
- & Dval(dd2222,Di1) + 4*Dval(dd2223,Di1) +
- & 6*Dval(dd2233,Di1) + 4*Dval(dd2333,Di1) +
- & Dval(dd3333,Di1)
+ call XE0func(E(EE0), para,
+ & D2345, D1345, D1245, D1235, D1234, 1)
- E(ee0) = XE0(p1, p2, p3, p4, p5, p1p2, p2p3, p3p4,
- & p4p5, p5p1, m1, m2, m3, m4, m5)
+ E(EE1) = dabbr1*eta(1) - eta(3)*D1245(DD1) -
+ & eta(4)*D1235(DD1) - eta(5)*D1234(DD1) +
+ & 2*(zeta(1,1)*D1345(DD00) +
+ & zeta(1,2)*D1245(DD00) +
+ & zeta(1,3)*D1235(DD00) +
+ & zeta(1,4)*D1234(DD00) -
+ & (zeta(1,1) + zeta(1,2) + zeta(1,3) + zeta(1,4))*
+ & D2345(DD00))
+ E(EE2) = -(eta(2)*D1345(DD1)) -
+ & eta(4)*D1235(DD2) - eta(5)*D1234(DD2) -
+ & eta(1)*D2345(DD1) +
+ & 2*zeta(1,2)*D1345(DD00) +
+ & 2*zeta(2,2)*D1245(DD00) +
+ & 2*zeta(2,3)*D1235(DD00) +
+ & 2*zeta(2,4)*D1234(DD00) -
+ & 2*(zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
+ & D2345(DD00)
+ E(EE3) = -(eta(2)*D1345(DD2)) -
+ & eta(3)*D1245(DD2) - eta(5)*D1234(DD3) -
+ & eta(1)*D2345(DD2) +
+ & 2*zeta(1,3)*D1345(DD00) +
+ & 2*zeta(2,3)*D1245(DD00) +
+ & 2*zeta(3,3)*D1235(DD00) +
+ & 2*zeta(3,4)*D1234(DD00) -
+ & 2*(zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
+ & D2345(DD00)
+ E(EE4) = -(eta(2)*D1345(DD3)) -
+ & eta(3)*D1245(DD3) - eta(4)*D1235(DD3) -
+ & eta(1)*D2345(DD3) +
+ & 2*zeta(1,4)*D1345(DD00) +
+ & 2*zeta(2,4)*D1245(DD00) +
+ & 2*zeta(3,4)*D1235(DD00) +
+ & 2*zeta(4,4)*D1234(DD00) -
+ & 2*(zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
+ & D2345(DD00)
- E(ee1) = dabbr1*eta(1) - eta(3)*Dval(dd1,Di3) -
- & eta(4)*Dval(dd1,Di4) - eta(5)*Dval(dd1,Di5) +
- & 2*(zeta(1,1)*Dval(dd00,Di2) +
- & zeta(1,2)*Dval(dd00,Di3) +
- & zeta(1,3)*Dval(dd00,Di4) +
- & zeta(1,4)*Dval(dd00,Di5) -
+ E(EE00) = -(eta(2)*D1345(DD00)) -
+ & eta(3)*D1245(DD00) - eta(4)*D1235(DD00) -
+ & eta(5)*D1234(DD00) - eta(1)*D2345(DD00)
+ E(EE11) = -(dabbr2*eta(1)) - eta(3)*D1245(DD11) -
+ & eta(4)*D1235(DD11) - eta(5)*D1234(DD11) +
+ & 4*(dabbr3*(zeta(1,1) + zeta(1,2) + zeta(1,3) +
+ & zeta(1,4)) + zeta(1,2)*D1245(DD001) +
+ & zeta(1,3)*D1235(DD001) +
+ & zeta(1,4)*D1234(DD001))
+ E(EE12) = dabbr4*eta(1) - eta(4)*D1235(DD12) -
+ & eta(5)*D1234(DD12) +
+ & 2*(dabbr5*(zeta(1,2) + zeta(2,2) + zeta(2,3) +
+ & zeta(2,4)) + zeta(1,1)*D1345(DD001) +
+ & zeta(2,2)*D1245(DD001) +
+ & zeta(2,3)*D1235(DD001) +
+ & zeta(2,4)*D1234(DD001) +
+ & zeta(1,3)*D1235(DD002) +
+ & zeta(1,4)*D1234(DD002) -
+ & (zeta(1,1) + zeta(1,3) + zeta(1,4) - zeta(2,2) -
+ & zeta(2,3) - zeta(2,4))*D2345(DD001))
+ E(EE13) = dabbr6*eta(1) - eta(3)*D1245(DD12) -
+ & eta(5)*D1234(DD13) +
+ & 2*(dabbr7*(zeta(1,3) + zeta(2,3) + zeta(3,3) +
+ & zeta(3,4)) + zeta(2,3)*D1245(DD001) +
+ & zeta(3,3)*D1235(DD001) +
+ & zeta(3,4)*D1234(DD001) +
+ & zeta(1,1)*D1345(DD002) +
+ & zeta(1,2)*D1245(DD002) +
+ & zeta(1,4)*D1234(DD003) -
+ & (zeta(1,1) + zeta(1,2) + zeta(1,4) - zeta(2,3) -
+ & zeta(3,3) - zeta(3,4))*D2345(DD002))
+ E(EE14) = dabbr8*eta(1) - eta(3)*D1245(DD13) -
+ & eta(4)*D1235(DD13) +
+ & 2*(dabbr9*(zeta(1,4) + zeta(2,4) + zeta(3,4) +
+ & zeta(4,4)) + zeta(2,4)*D1245(DD001) +
+ & zeta(3,4)*D1235(DD001) +
+ & zeta(4,4)*D1234(DD001) +
+ & zeta(1,1)*D1345(DD003) +
+ & zeta(1,2)*D1245(DD003) +
+ & zeta(1,3)*D1235(DD003) -
+ & (zeta(1,1) + zeta(1,2) + zeta(1,3) - zeta(2,4) -
+ & zeta(3,4) - zeta(4,4))*D2345(DD003))
+ E(EE22) = -(eta(2)*D1345(DD11)) -
+ & eta(4)*D1235(DD22) - eta(5)*D1234(DD22) -
+ & eta(1)*D2345(DD11) +
+ & 4*zeta(1,2)*D1345(DD001) +
+ & 4*zeta(2,3)*D1235(DD002) +
+ & 4*zeta(2,4)*D1234(DD002) -
+ & 4*(zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
+ & D2345(DD001)
+ E(EE23) = -(eta(2)*D1345(DD12)) -
+ & eta(5)*D1234(DD23) - eta(1)*D2345(DD12) +
+ & 2*(zeta(1,3)*D1345(DD001) +
+ & zeta(1,2)*D1345(DD002) +
+ & zeta(2,2)*D1245(DD002) +
+ & zeta(3,3)*D1235(DD002) +
+ & zeta(3,4)*D1234(DD002) +
+ & zeta(2,4)*D1234(DD003) -
+ & (zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
+ & D2345(DD001) -
+ & (zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
+ & D2345(DD002))
+ E(EE24) = -(eta(2)*D1345(DD13)) -
+ & eta(4)*D1235(DD23) - eta(1)*D2345(DD13) +
+ & 2*(zeta(1,4)*D1345(DD001) +
+ & zeta(3,4)*D1235(DD002) +
+ & zeta(4,4)*D1234(DD002) +
+ & zeta(1,2)*D1345(DD003) +
+ & zeta(2,2)*D1245(DD003) +
+ & zeta(2,3)*D1235(DD003) -
+ & (zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
+ & D2345(DD001) -
+ & (zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
+ & D2345(DD003))
+ E(EE33) = -(eta(2)*D1345(DD22)) -
+ & eta(3)*D1245(DD22) - eta(5)*D1234(DD33) -
+ & eta(1)*D2345(DD22) +
+ & 4*zeta(1,3)*D1345(DD002) +
+ & 4*zeta(2,3)*D1245(DD002) +
+ & 4*zeta(3,4)*D1234(DD003) -
+ & 4*(zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
+ & D2345(DD002)
+ E(EE34) = -(eta(2)*D1345(DD23)) -
+ & eta(3)*D1245(DD23) - eta(1)*D2345(DD23) +
+ & 2*(zeta(1,4)*D1345(DD002) +
+ & zeta(2,4)*D1245(DD002) +
+ & zeta(1,3)*D1345(DD003) +
+ & zeta(2,3)*D1245(DD003) +
+ & zeta(3,3)*D1235(DD003) +
+ & zeta(4,4)*D1234(DD003) -
+ & (zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
+ & D2345(DD002) -
+ & (zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
+ & D2345(DD003))
+ E(EE44) = -(eta(2)*D1345(DD33)) -
+ & eta(3)*D1245(DD33) - eta(4)*D1235(DD33) -
+ & eta(1)*D2345(DD33) +
+ & 4*zeta(1,4)*D1345(DD003) +
+ & 4*zeta(2,4)*D1245(DD003) +
+ & 4*zeta(3,4)*D1235(DD003) -
+ & 4*(zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
+ & D2345(DD003)
+
+ E(EE001) = dabbr3*eta(1) - eta(3)*D1245(DD001) -
+ & eta(4)*D1235(DD001) - eta(5)*D1234(DD001) +
+ & 2*(zeta(1,1)*(D1345(DD0000) - del) +
+ & zeta(1,2)*(D1245(DD0000) - del) +
+ & zeta(1,3)*(D1235(DD0000) - del) +
+ & zeta(1,4)*(D1234(DD0000) - del) -
& (zeta(1,1) + zeta(1,2) + zeta(1,3) + zeta(1,4))*
- & Dval(dd00,Di1))
- E(ee2) = -(eta(2)*Dval(dd1,Di2)) -
- & eta(4)*Dval(dd2,Di4) - eta(5)*Dval(dd2,Di5) -
- & eta(1)*Dval(dd1,Di1) +
- & 2*zeta(1,2)*Dval(dd00,Di2) +
- & 2*zeta(2,2)*Dval(dd00,Di3) +
- & 2*zeta(2,3)*Dval(dd00,Di4) +
- & 2*zeta(2,4)*Dval(dd00,Di5) -
+ & (D2345(DD0000) - del))
+ E(EE002) = -(eta(2)*D1345(DD001)) -
+ & eta(4)*D1235(DD002) - eta(5)*D1234(DD002) -
+ & eta(1)*D2345(DD001) +
+ & 2*zeta(1,2)*(D1345(DD0000) - del) +
+ & 2*zeta(2,2)*(D1245(DD0000) - del) +
+ & 2*zeta(2,3)*(D1235(DD0000) - del) +
+ & 2*zeta(2,4)*(D1234(DD0000) - del) -
& 2*(zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & Dval(dd00,Di1)
- E(ee3) = -(eta(2)*Dval(dd2,Di2)) -
- & eta(3)*Dval(dd2,Di3) - eta(5)*Dval(dd3,Di5) -
- & eta(1)*Dval(dd2,Di1) +
- & 2*zeta(1,3)*Dval(dd00,Di2) +
- & 2*zeta(2,3)*Dval(dd00,Di3) +
- & 2*zeta(3,3)*Dval(dd00,Di4) +
- & 2*zeta(3,4)*Dval(dd00,Di5) -
+ & (D2345(DD0000) - del)
+ E(EE003) = -(eta(2)*D1345(DD002)) -
+ & eta(3)*D1245(DD002) - eta(5)*D1234(DD003) -
+ & eta(1)*D2345(DD002) +
+ & 2*zeta(1,3)*(D1345(DD0000) - del) +
+ & 2*zeta(2,3)*(D1245(DD0000) - del) +
+ & 2*zeta(3,3)*(D1235(DD0000) - del) +
+ & 2*zeta(3,4)*(D1234(DD0000) - del) -
& 2*(zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & Dval(dd00,Di1)
- E(ee4) = -(eta(2)*Dval(dd3,Di2)) -
- & eta(3)*Dval(dd3,Di3) - eta(4)*Dval(dd3,Di4) -
- & eta(1)*Dval(dd3,Di1) +
- & 2*zeta(1,4)*Dval(dd00,Di2) +
- & 2*zeta(2,4)*Dval(dd00,Di3) +
- & 2*zeta(3,4)*Dval(dd00,Di4) +
- & 2*zeta(4,4)*Dval(dd00,Di5) -
+ & (D2345(DD0000) - del)
+ E(EE004) = -(eta(2)*D1345(DD003)) -
+ & eta(3)*D1245(DD003) - eta(4)*D1235(DD003) -
+ & eta(1)*D2345(DD003) +
+ & 2*zeta(1,4)*(D1345(DD0000) - del) +
+ & 2*zeta(2,4)*(D1245(DD0000) - del) +
+ & 2*zeta(3,4)*(D1235(DD0000) - del) +
+ & 2*zeta(4,4)*(D1234(DD0000) - del) -
& 2*(zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd00,Di1)
-
- E(ee00) = -(eta(2)*Dval(dd00,Di2)) -
- & eta(3)*Dval(dd00,Di3) - eta(4)*Dval(dd00,Di4) -
- & eta(5)*Dval(dd00,Di5) - eta(1)*Dval(dd00,Di1)
- E(ee11) = -(dabbr2*eta(1)) - eta(3)*Dval(dd11,Di3) -
- & eta(4)*Dval(dd11,Di4) - eta(5)*Dval(dd11,Di5) +
- & 4*(dabbr3*(zeta(1,1) + zeta(1,2) + zeta(1,3) +
- & zeta(1,4)) + zeta(1,2)*Dval(dd001,Di3) +
- & zeta(1,3)*Dval(dd001,Di4) +
- & zeta(1,4)*Dval(dd001,Di5))
- E(ee12) = dabbr4*eta(1) - eta(4)*Dval(dd12,Di4) -
- & eta(5)*Dval(dd12,Di5) +
- & 2*(dabbr5*(zeta(1,2) + zeta(2,2) + zeta(2,3) +
- & zeta(2,4)) + zeta(1,1)*Dval(dd001,Di2) +
- & zeta(2,2)*Dval(dd001,Di3) +
- & zeta(2,3)*Dval(dd001,Di4) +
- & zeta(2,4)*Dval(dd001,Di5) +
- & zeta(1,3)*Dval(dd002,Di4) +
- & zeta(1,4)*Dval(dd002,Di5) -
- & (zeta(1,1) + zeta(1,3) + zeta(1,4) - zeta(2,2) -
- & zeta(2,3) - zeta(2,4))*Dval(dd001,Di1))
- E(ee13) = dabbr6*eta(1) - eta(3)*Dval(dd12,Di3) -
- & eta(5)*Dval(dd13,Di5) +
- & 2*(dabbr7*(zeta(1,3) + zeta(2,3) + zeta(3,3) +
- & zeta(3,4)) + zeta(2,3)*Dval(dd001,Di3) +
- & zeta(3,3)*Dval(dd001,Di4) +
- & zeta(3,4)*Dval(dd001,Di5) +
- & zeta(1,1)*Dval(dd002,Di2) +
- & zeta(1,2)*Dval(dd002,Di3) +
- & zeta(1,4)*Dval(dd003,Di5) -
- & (zeta(1,1) + zeta(1,2) + zeta(1,4) - zeta(2,3) -
- & zeta(3,3) - zeta(3,4))*Dval(dd002,Di1))
- E(ee14) = dabbr8*eta(1) - eta(3)*Dval(dd13,Di3) -
- & eta(4)*Dval(dd13,Di4) +
- & 2*(dabbr9*(zeta(1,4) + zeta(2,4) + zeta(3,4) +
- & zeta(4,4)) + zeta(2,4)*Dval(dd001,Di3) +
- & zeta(3,4)*Dval(dd001,Di4) +
- & zeta(4,4)*Dval(dd001,Di5) +
- & zeta(1,1)*Dval(dd003,Di2) +
- & zeta(1,2)*Dval(dd003,Di3) +
- & zeta(1,3)*Dval(dd003,Di4) -
- & (zeta(1,1) + zeta(1,2) + zeta(1,3) - zeta(2,4) -
- & zeta(3,4) - zeta(4,4))*Dval(dd003,Di1))
- E(ee22) = -(eta(2)*Dval(dd11,Di2)) -
- & eta(4)*Dval(dd22,Di4) - eta(5)*Dval(dd22,Di5) -
- & eta(1)*Dval(dd11,Di1) +
- & 4*zeta(1,2)*Dval(dd001,Di2) +
- & 4*zeta(2,3)*Dval(dd002,Di4) +
- & 4*zeta(2,4)*Dval(dd002,Di5) -
- & 4*(zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & Dval(dd001,Di1)
- E(ee23) = -(eta(2)*Dval(dd12,Di2)) -
- & eta(5)*Dval(dd23,Di5) - eta(1)*Dval(dd12,Di1) +
- & 2*(zeta(1,3)*Dval(dd001,Di2) +
- & zeta(1,2)*Dval(dd002,Di2) +
- & zeta(2,2)*Dval(dd002,Di3) +
- & zeta(3,3)*Dval(dd002,Di4) +
- & zeta(3,4)*Dval(dd002,Di5) +
- & zeta(2,4)*Dval(dd003,Di5) -
- & (zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & Dval(dd001,Di1) -
- & (zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & Dval(dd002,Di1))
- E(ee24) = -(eta(2)*Dval(dd13,Di2)) -
- & eta(4)*Dval(dd23,Di4) - eta(1)*Dval(dd13,Di1) +
- & 2*(zeta(1,4)*Dval(dd001,Di2) +
- & zeta(3,4)*Dval(dd002,Di4) +
- & zeta(4,4)*Dval(dd002,Di5) +
- & zeta(1,2)*Dval(dd003,Di2) +
- & zeta(2,2)*Dval(dd003,Di3) +
- & zeta(2,3)*Dval(dd003,Di4) -
- & (zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd001,Di1) -
- & (zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & Dval(dd003,Di1))
- E(ee33) = -(eta(2)*Dval(dd22,Di2)) -
- & eta(3)*Dval(dd22,Di3) - eta(5)*Dval(dd33,Di5) -
- & eta(1)*Dval(dd22,Di1) +
- & 4*zeta(1,3)*Dval(dd002,Di2) +
- & 4*zeta(2,3)*Dval(dd002,Di3) +
- & 4*zeta(3,4)*Dval(dd003,Di5) -
- & 4*(zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & Dval(dd002,Di1)
- E(ee34) = -(eta(2)*Dval(dd23,Di2)) -
- & eta(3)*Dval(dd23,Di3) - eta(1)*Dval(dd23,Di1) +
- & 2*(zeta(1,4)*Dval(dd002,Di2) +
- & zeta(2,4)*Dval(dd002,Di3) +
- & zeta(1,3)*Dval(dd003,Di2) +
- & zeta(2,3)*Dval(dd003,Di3) +
- & zeta(3,3)*Dval(dd003,Di4) +
- & zeta(4,4)*Dval(dd003,Di5) -
- & (zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd002,Di1) -
- & (zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & Dval(dd003,Di1))
- E(ee44) = -(eta(2)*Dval(dd33,Di2)) -
- & eta(3)*Dval(dd33,Di3) - eta(4)*Dval(dd33,Di4) -
- & eta(1)*Dval(dd33,Di1) +
- & 4*zeta(1,4)*Dval(dd003,Di2) +
- & 4*zeta(2,4)*Dval(dd003,Di3) +
- & 4*zeta(3,4)*Dval(dd003,Di4) -
- & 4*(zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd003,Di1)
-
- E(ee001) = dabbr3*eta(1) - eta(3)*Dval(dd001,Di3) -
- & eta(4)*Dval(dd001,Di4) - eta(5)*Dval(dd001,Di5) +
- & 2*(zeta(1,1)*(Dval(dd0000,Di2) - del) +
- & zeta(1,2)*(Dval(dd0000,Di3) - del) +
- & zeta(1,3)*(Dval(dd0000,Di4) - del) +
- & zeta(1,4)*(Dval(dd0000,Di5) - del) -
- & (zeta(1,1) + zeta(1,2) + zeta(1,3) + zeta(1,4))*
- & (Dval(dd0000,Di1) - del))
- E(ee002) = -(eta(2)*Dval(dd001,Di2)) -
- & eta(4)*Dval(dd002,Di4) - eta(5)*Dval(dd002,Di5) -
- & eta(1)*Dval(dd001,Di1) +
- & 2*zeta(1,2)*(Dval(dd0000,Di2) - del) +
- & 2*zeta(2,2)*(Dval(dd0000,Di3) - del) +
- & 2*zeta(2,3)*(Dval(dd0000,Di4) - del) +
- & 2*zeta(2,4)*(Dval(dd0000,Di5) - del) -
- & 2*(zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & (Dval(dd0000,Di1) - del)
- E(ee003) = -(eta(2)*Dval(dd002,Di2)) -
- & eta(3)*Dval(dd002,Di3) - eta(5)*Dval(dd003,Di5) -
- & eta(1)*Dval(dd002,Di1) +
- & 2*zeta(1,3)*(Dval(dd0000,Di2) - del) +
- & 2*zeta(2,3)*(Dval(dd0000,Di3) - del) +
- & 2*zeta(3,3)*(Dval(dd0000,Di4) - del) +
- & 2*zeta(3,4)*(Dval(dd0000,Di5) - del) -
- & 2*(zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & (Dval(dd0000,Di1) - del)
- E(ee004) = -(eta(2)*Dval(dd003,Di2)) -
- & eta(3)*Dval(dd003,Di3) - eta(4)*Dval(dd003,Di4) -
- & eta(1)*Dval(dd003,Di1) +
- & 2*zeta(1,4)*(Dval(dd0000,Di2) - del) +
- & 2*zeta(2,4)*(Dval(dd0000,Di3) - del) +
- & 2*zeta(3,4)*(Dval(dd0000,Di4) - del) +
- & 2*zeta(4,4)*(Dval(dd0000,Di5) - del) -
- & 2*(zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & (Dval(dd0000,Di1) - del)
- E(ee111) = -6*dabbr11*
+ & (D2345(DD0000) - del)
+ E(EE111) = -6*dabbr11*
& (zeta(1,1) + zeta(1,2) + zeta(1,3) + zeta(1,4)) -
- & eta(3)*Dval(dd111,Di3) - eta(4)*Dval(dd111,Di4) -
- & eta(5)*Dval(dd111,Di5) +
- & eta(1)*(3*dabbr10 + Dval(dd0,Di1) +
- & 3*Dval(dd1,Di1) + 3*Dval(dd2,Di1) +
- & 3*Dval(dd3,Di1) + 3*Dval(dd11,Di1) +
- & 6*Dval(dd12,Di1) + 6*Dval(dd13,Di1) +
- & 3*Dval(dd22,Di1) + 6*Dval(dd23,Di1) +
- & 3*Dval(dd33,Di1) + Dval(dd111,Di1) +
- & 3*Dval(dd112,Di1) + 3*Dval(dd113,Di1) +
- & 3*Dval(dd122,Di1) + 6*Dval(dd123,Di1) +
- & 3*Dval(dd133,Di1) + Dval(dd222,Di1) +
- & Dval(dd333,Di1)) +
- & 6*zeta(1,2)*Dval(dd0011,Di3) +
- & 6*zeta(1,3)*Dval(dd0011,Di4) +
- & 6*zeta(1,4)*Dval(dd0011,Di5)
- E(ee112) = -(dabbr12*eta(1)) -
+ & eta(3)*D1245(DD111) - eta(4)*D1235(DD111) -
+ & eta(5)*D1234(DD111) +
+ & eta(1)*(3*dabbr10 + D2345(DD0) +
+ & 3*D2345(DD1) + 3*D2345(DD2) +
+ & 3*D2345(DD3) + 3*D2345(DD11) +
+ & 6*D2345(DD12) + 6*D2345(DD13) +
+ & 3*D2345(DD22) + 6*D2345(DD23) +
+ & 3*D2345(DD33) + D2345(DD111) +
+ & 3*D2345(DD112) + 3*D2345(DD113) +
+ & 3*D2345(DD122) + 6*D2345(DD123) +
+ & 3*D2345(DD133) + D2345(DD222) +
+ & D2345(DD333)) +
+ & 6*zeta(1,2)*D1245(DD0011) +
+ & 6*zeta(1,3)*D1235(DD0011) +
+ & 6*zeta(1,4)*D1234(DD0011)
+ E(EE112) = -(dabbr12*eta(1)) -
& 2*dabbr14*(zeta(1,2) + zeta(2,2) + zeta(2,3) +
- & zeta(2,4)) - eta(4)*Dval(dd112,Di4) -
- & eta(5)*Dval(dd112,Di5) +
+ & zeta(2,4)) - eta(4)*D1235(DD112) -
+ & eta(5)*D1234(DD112) +
& 2*(2*dabbr13*(zeta(1,1) + zeta(1,3) + zeta(1,4) -
& zeta(2,2) - zeta(2,3) - zeta(2,4)) +
- & zeta(2,2)*Dval(dd0011,Di3) +
- & zeta(2,3)*Dval(dd0011,Di4) +
- & zeta(2,4)*Dval(dd0011,Di5) +
- & 2*zeta(1,3)*Dval(dd0012,Di4) +
- & 2*zeta(1,4)*Dval(dd0012,Di5) +
+ & zeta(2,2)*D1245(DD0011) +
+ & zeta(2,3)*D1235(DD0011) +
+ & zeta(2,4)*D1234(DD0011) +
+ & 2*zeta(1,3)*D1235(DD0012) +
+ & 2*zeta(1,4)*D1234(DD0012) +
& (2*zeta(1,1) + zeta(1,2) + 2*zeta(1,3) + 2*zeta(1,4) -
& zeta(2,2) - zeta(2,3) - zeta(2,4))*
- & Dval(dd0011,Di1))
- E(ee113) = -(dabbr15*eta(1)) -
+ & D2345(DD0011))
+ E(EE113) = -(dabbr15*eta(1)) -
& 2*dabbr17*(zeta(1,3) + zeta(2,3) + zeta(3,3) +
- & zeta(3,4)) - eta(3)*Dval(dd112,Di3) -
- & eta(5)*Dval(dd113,Di5) +
+ & zeta(3,4)) - eta(3)*D1245(DD112) -
+ & eta(5)*D1234(DD113) +
& 2*(2*dabbr16*(zeta(1,1) + zeta(1,2) + zeta(1,4) -
& zeta(2,3) - zeta(3,3) - zeta(3,4)) +
- & zeta(2,3)*Dval(dd0011,Di3) +
- & zeta(3,3)*Dval(dd0011,Di4) +
- & zeta(3,4)*Dval(dd0011,Di5) +
- & 2*zeta(1,2)*Dval(dd0012,Di3) +
- & 2*zeta(1,4)*Dval(dd0013,Di5) +
+ & zeta(2,3)*D1245(DD0011) +
+ & zeta(3,3)*D1235(DD0011) +
+ & zeta(3,4)*D1234(DD0011) +
+ & 2*zeta(1,2)*D1245(DD0012) +
+ & 2*zeta(1,4)*D1234(DD0013) +
& (2*zeta(1,1) + 2*zeta(1,2) + zeta(1,3) + 2*zeta(1,4) -
& zeta(2,3) - zeta(3,3) - zeta(3,4))*
- & Dval(dd0022,Di1))
- E(ee114) = -(dabbr18*eta(1)) -
+ & D2345(DD0022))
+ E(EE114) = -(dabbr18*eta(1)) -
& 2*dabbr19*(zeta(1,4) + zeta(2,4) + zeta(3,4) +
- & zeta(4,4)) - eta(3)*Dval(dd113,Di3) -
- & eta(4)*Dval(dd113,Di4) +
+ & zeta(4,4)) - eta(3)*D1245(DD113) -
+ & eta(4)*D1235(DD113) +
& 2*(2*dabbr20*(zeta(1,1) + zeta(1,2) + zeta(1,3) -
& zeta(2,4) - zeta(3,4) - zeta(4,4)) +
- & zeta(2,4)*Dval(dd0011,Di3) +
- & zeta(3,4)*Dval(dd0011,Di4) +
- & zeta(4,4)*Dval(dd0011,Di5) +
- & 2*zeta(1,2)*Dval(dd0013,Di3) +
- & 2*zeta(1,3)*Dval(dd0013,Di4) +
+ & zeta(2,4)*D1245(DD0011) +
+ & zeta(3,4)*D1235(DD0011) +
+ & zeta(4,4)*D1234(DD0011) +
+ & 2*zeta(1,2)*D1245(DD0013) +
+ & 2*zeta(1,3)*D1235(DD0013) +
& (2*zeta(1,1) + 2*zeta(1,2) + 2*zeta(1,3) + zeta(1,4) -
& zeta(2,4) - zeta(3,4) - zeta(4,4))*
- & Dval(dd0033,Di1))
- E(ee122) = dabbr21*eta(1) - eta(4)*Dval(dd122,Di4) -
- & eta(5)*Dval(dd122,Di5) +
+ & D2345(DD0033))
+ E(EE122) = dabbr21*eta(1) - eta(4)*D1235(DD122) -
+ & eta(5)*D1234(DD122) +
& 2*(2*dabbr13*(zeta(1,2) + zeta(2,2) + zeta(2,3) +
- & zeta(2,4)) + zeta(1,1)*Dval(dd0011,Di2) +
- & 2*zeta(2,3)*Dval(dd0012,Di4) +
- & 2*zeta(2,4)*Dval(dd0012,Di5) +
- & zeta(1,3)*Dval(dd0022,Di4) +
- & zeta(1,4)*Dval(dd0022,Di5) -
+ & zeta(2,4)) + zeta(1,1)*D1345(DD0011) +
+ & 2*zeta(2,3)*D1235(DD0012) +
+ & 2*zeta(2,4)*D1234(DD0012) +
+ & zeta(1,3)*D1235(DD0022) +
+ & zeta(1,4)*D1234(DD0022) -
& (zeta(1,1) - zeta(1,2) + zeta(1,3) + zeta(1,4) -
& 2*(zeta(2,2) + zeta(2,3) + zeta(2,4)))*
- & Dval(dd0011,Di1))
- E(ee123) = dabbr22*eta(1) - eta(5)*Dval(dd123,Di5) +
+ & D2345(DD0011))
+ E(EE123) = dabbr22*eta(1) - eta(5)*D1234(DD123) +
& 2*(dabbr24*(zeta(1,2) + zeta(2,2) + zeta(2,3) +
& zeta(2,4)) +
& dabbr23*(zeta(1,3) + zeta(2,3) + zeta(3,3) +
- & zeta(3,4)) + zeta(1,1)*Dval(dd0012,Di2) +
- & zeta(2,2)*Dval(dd0012,Di3) +
- & zeta(3,3)*Dval(dd0012,Di4) +
- & zeta(3,4)*Dval(dd0012,Di5) +
- & zeta(2,4)*Dval(dd0013,Di5) +
- & zeta(1,4)*Dval(dd0023,Di5) +
+ & zeta(3,4)) + zeta(1,1)*D1345(DD0012) +
+ & zeta(2,2)*D1245(DD0012) +
+ & zeta(3,3)*D1235(DD0012) +
+ & zeta(3,4)*D1234(DD0012) +
+ & zeta(2,4)*D1234(DD0013) +
+ & zeta(1,4)*D1234(DD0023) +
& (-zeta(1,1) - zeta(1,4) + zeta(2,2) + 2*zeta(2,3) +
& zeta(2,4) + zeta(3,3) + zeta(3,4))*
- & Dval(dd0012,Di1))
- E(ee124) = dabbr25*eta(1) - eta(4)*Dval(dd123,Di4) +
+ & D2345(DD0012))
+ E(EE124) = dabbr25*eta(1) - eta(4)*D1235(DD123) +
& 2*(dabbr27*(zeta(1,2) + zeta(2,2) + zeta(2,3) +
& zeta(2,4)) +
& dabbr26*(zeta(1,4) + zeta(2,4) + zeta(3,4) +
- & zeta(4,4)) + zeta(3,4)*Dval(dd0012,Di4) +
- & zeta(4,4)*Dval(dd0012,Di5) +
- & zeta(1,1)*Dval(dd0013,Di2) +
- & zeta(2,2)*Dval(dd0013,Di3) +
- & zeta(2,3)*Dval(dd0013,Di4) +
- & zeta(1,3)*Dval(dd0023,Di4) +
+ & zeta(4,4)) + zeta(3,4)*D1235(DD0012) +
+ & zeta(4,4)*D1234(DD0012) +
+ & zeta(1,1)*D1345(DD0013) +
+ & zeta(2,2)*D1245(DD0013) +
+ & zeta(2,3)*D1235(DD0013) +
+ & zeta(1,3)*D1235(DD0023) +
& (-zeta(1,1) - zeta(1,3) + zeta(2,2) + zeta(2,3) +
& 2*zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd0013,Di1))
- E(ee133) = dabbr28*eta(1) - eta(3)*Dval(dd122,Di3) -
- & eta(5)*Dval(dd133,Di5) +
+ & D2345(DD0013))
+ E(EE133) = dabbr28*eta(1) - eta(3)*D1245(DD122) -
+ & eta(5)*D1234(DD133) +
& 2*(2*dabbr16*(zeta(1,3) + zeta(2,3) + zeta(3,3) +
- & zeta(3,4)) + 2*zeta(2,3)*Dval(dd0012,Di3) +
- & 2*zeta(3,4)*Dval(dd0013,Di5) +
- & zeta(1,1)*Dval(dd0022,Di2) +
- & zeta(1,2)*Dval(dd0022,Di3) +
- & zeta(1,4)*Dval(dd0033,Di5) -
+ & zeta(3,4)) + 2*zeta(2,3)*D1245(DD0012) +
+ & 2*zeta(3,4)*D1234(DD0013) +
+ & zeta(1,1)*D1345(DD0022) +
+ & zeta(1,2)*D1245(DD0022) +
+ & zeta(1,4)*D1234(DD0033) -
& (zeta(1,1) + zeta(1,2) - zeta(1,3) + zeta(1,4) -
& 2*(zeta(2,3) + zeta(3,3) + zeta(3,4)))*
- & Dval(dd0022,Di1))
- E(ee134) = dabbr29*eta(1) - eta(3)*Dval(dd123,Di3) +
+ & D2345(DD0022))
+ E(EE134) = dabbr29*eta(1) - eta(3)*D1245(DD123) +
& 2*(dabbr31*(zeta(1,3) + zeta(2,3) + zeta(3,3) +
& zeta(3,4)) +
& dabbr30*(zeta(1,4) + zeta(2,4) + zeta(3,4) +
- & zeta(4,4)) + zeta(2,4)*Dval(dd0012,Di3) +
- & zeta(2,3)*Dval(dd0013,Di3) +
- & zeta(3,3)*Dval(dd0013,Di4) +
- & zeta(4,4)*Dval(dd0013,Di5) +
- & zeta(1,1)*Dval(dd0023,Di2) +
- & zeta(1,2)*Dval(dd0023,Di3) +
+ & zeta(4,4)) + zeta(2,4)*D1245(DD0012) +
+ & zeta(2,3)*D1245(DD0013) +
+ & zeta(3,3)*D1235(DD0013) +
+ & zeta(4,4)*D1234(DD0013) +
+ & zeta(1,1)*D1345(DD0023) +
+ & zeta(1,2)*D1245(DD0023) +
& (-zeta(1,1) - zeta(1,2) + zeta(2,3) + zeta(2,4) +
& zeta(3,3) + 2*zeta(3,4) + zeta(4,4))*
- & Dval(dd0023,Di1))
- E(ee144) = dabbr32*eta(1) - eta(3)*Dval(dd133,Di3) -
- & eta(4)*Dval(dd133,Di4) +
+ & D2345(DD0023))
+ E(EE144) = dabbr32*eta(1) - eta(3)*D1245(DD133) -
+ & eta(4)*D1235(DD133) +
& 2*(2*dabbr20*(zeta(1,4) + zeta(2,4) + zeta(3,4) +
- & zeta(4,4)) + 2*zeta(2,4)*Dval(dd0013,Di3) +
- & 2*zeta(3,4)*Dval(dd0013,Di4) +
- & zeta(1,1)*Dval(dd0033,Di2) +
- & zeta(1,2)*Dval(dd0033,Di3) +
- & zeta(1,3)*Dval(dd0033,Di4) -
+ & zeta(4,4)) + 2*zeta(2,4)*D1245(DD0013) +
+ & 2*zeta(3,4)*D1235(DD0013) +
+ & zeta(1,1)*D1345(DD0033) +
+ & zeta(1,2)*D1245(DD0033) +
+ & zeta(1,3)*D1235(DD0033) -
& (zeta(1,1) + zeta(1,2) + zeta(1,3) - zeta(1,4) -
& 2*(zeta(2,4) + zeta(3,4) + zeta(4,4)))*
- & Dval(dd0033,Di1))
- E(ee222) = -(eta(2)*Dval(dd111,Di2)) -
- & eta(4)*Dval(dd222,Di4) - eta(5)*Dval(dd222,Di5) -
- & eta(1)*Dval(dd111,Di1) +
- & 6*zeta(1,2)*Dval(dd0011,Di2) +
- & 6*zeta(2,3)*Dval(dd0022,Di4) +
- & 6*zeta(2,4)*Dval(dd0022,Di5) -
+ & D2345(DD0033))
+ E(EE222) = -(eta(2)*D1345(DD111)) -
+ & eta(4)*D1235(DD222) - eta(5)*D1234(DD222) -
+ & eta(1)*D2345(DD111) +
+ & 6*zeta(1,2)*D1345(DD0011) +
+ & 6*zeta(2,3)*D1235(DD0022) +
+ & 6*zeta(2,4)*D1234(DD0022) -
& 6*(zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & Dval(dd0011,Di1)
- E(ee223) = -(eta(2)*Dval(dd112,Di2)) -
- & eta(5)*Dval(dd223,Di5) - eta(1)*Dval(dd112,Di1) +
- & 2*zeta(1,3)*Dval(dd0011,Di2) +
- & 4*zeta(1,2)*Dval(dd0012,Di2) +
- & 2*zeta(3,3)*Dval(dd0022,Di4) +
- & 2*zeta(3,4)*Dval(dd0022,Di5) +
- & 4*zeta(2,4)*Dval(dd0023,Di5) -
+ & D2345(DD0011)
+ E(EE223) = -(eta(2)*D1345(DD112)) -
+ & eta(5)*D1234(DD223) - eta(1)*D2345(DD112) +
+ & 2*zeta(1,3)*D1345(DD0011) +
+ & 4*zeta(1,2)*D1345(DD0012) +
+ & 2*zeta(3,3)*D1235(DD0022) +
+ & 2*zeta(3,4)*D1234(DD0022) +
+ & 4*zeta(2,4)*D1234(DD0023) -
& 2*(zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & Dval(dd0011,Di1) -
+ & D2345(DD0011) -
& 4*(zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & Dval(dd0012,Di1)
- E(ee224) = -(eta(2)*Dval(dd113,Di2)) -
- & eta(4)*Dval(dd223,Di4) - eta(1)*Dval(dd113,Di1) +
- & 2*zeta(1,4)*Dval(dd0011,Di2) +
- & 4*zeta(1,2)*Dval(dd0013,Di2) +
- & 2*zeta(3,4)*Dval(dd0022,Di4) +
- & 2*zeta(4,4)*Dval(dd0022,Di5) +
- & 4*zeta(2,3)*Dval(dd0023,Di4) -
+ & D2345(DD0012)
+ E(EE224) = -(eta(2)*D1345(DD113)) -
+ & eta(4)*D1235(DD223) - eta(1)*D2345(DD113) +
+ & 2*zeta(1,4)*D1345(DD0011) +
+ & 4*zeta(1,2)*D1345(DD0013) +
+ & 2*zeta(3,4)*D1235(DD0022) +
+ & 2*zeta(4,4)*D1234(DD0022) +
+ & 4*zeta(2,3)*D1235(DD0023) -
& 2*(zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd0011,Di1) -
+ & D2345(DD0011) -
& 4*(zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & Dval(dd0013,Di1)
- E(ee233) = -(eta(2)*Dval(dd122,Di2)) -
- & eta(5)*Dval(dd233,Di5) - eta(1)*Dval(dd122,Di1) +
- & 4*zeta(1,3)*Dval(dd0012,Di2) +
- & 2*zeta(1,2)*Dval(dd0022,Di2) +
- & 2*zeta(2,2)*Dval(dd0022,Di3) +
- & 4*zeta(3,4)*Dval(dd0023,Di5) +
- & 2*zeta(2,4)*Dval(dd0033,Di5) -
+ & D2345(DD0013)
+ E(EE233) = -(eta(2)*D1345(DD122)) -
+ & eta(5)*D1234(DD233) - eta(1)*D2345(DD122) +
+ & 4*zeta(1,3)*D1345(DD0012) +
+ & 2*zeta(1,2)*D1345(DD0022) +
+ & 2*zeta(2,2)*D1245(DD0022) +
+ & 4*zeta(3,4)*D1234(DD0023) +
+ & 2*zeta(2,4)*D1234(DD0033) -
& 4*(zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & Dval(dd0012,Di1) -
+ & D2345(DD0012) -
& 2*(zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & Dval(dd0022,Di1)
- E(ee234) = -(eta(2)*Dval(dd123,Di2)) -
- & eta(1)*Dval(dd123,Di1) +
- & 2*(zeta(1,4)*Dval(dd0012,Di2) +
- & zeta(1,3)*Dval(dd0013,Di2) +
- & zeta(1,2)*Dval(dd0023,Di2) +
- & zeta(2,2)*Dval(dd0023,Di3) +
- & zeta(3,3)*Dval(dd0023,Di4) +
- & zeta(4,4)*Dval(dd0023,Di5) -
+ & D2345(DD0022)
+ E(EE234) = -(eta(2)*D1345(DD123)) -
+ & eta(1)*D2345(DD123) +
+ & 2*(zeta(1,4)*D1345(DD0012) +
+ & zeta(1,3)*D1345(DD0013) +
+ & zeta(1,2)*D1345(DD0023) +
+ & zeta(2,2)*D1245(DD0023) +
+ & zeta(3,3)*D1235(DD0023) +
+ & zeta(4,4)*D1234(DD0023) -
& (zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd0012,Di1) -
+ & D2345(DD0012) -
& (zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & Dval(dd0013,Di1) -
+ & D2345(DD0013) -
& (zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & Dval(dd0023,Di1))
- E(ee244) = -(eta(2)*Dval(dd133,Di2)) -
- & eta(4)*Dval(dd233,Di4) - eta(1)*Dval(dd133,Di1) +
- & 4*zeta(1,4)*Dval(dd0013,Di2) +
- & 4*zeta(3,4)*Dval(dd0023,Di4) +
- & 2*zeta(1,2)*Dval(dd0033,Di2) +
- & 2*zeta(2,2)*Dval(dd0033,Di3) +
- & 2*zeta(2,3)*Dval(dd0033,Di4) -
+ & D2345(DD0023))
+ E(EE244) = -(eta(2)*D1345(DD133)) -
+ & eta(4)*D1235(DD233) - eta(1)*D2345(DD133) +
+ & 4*zeta(1,4)*D1345(DD0013) +
+ & 4*zeta(3,4)*D1235(DD0023) +
+ & 2*zeta(1,2)*D1345(DD0033) +
+ & 2*zeta(2,2)*D1245(DD0033) +
+ & 2*zeta(2,3)*D1235(DD0033) -
& 4*(zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd0013,Di1) -
+ & D2345(DD0013) -
& 2*(zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & Dval(dd0033,Di1)
- E(ee333) = -(eta(2)*Dval(dd222,Di2)) -
- & eta(3)*Dval(dd222,Di3) - eta(5)*Dval(dd333,Di5) -
- & eta(1)*Dval(dd222,Di1) +
- & 6*zeta(1,3)*Dval(dd0022,Di2) +
- & 6*zeta(2,3)*Dval(dd0022,Di3) +
- & 6*zeta(3,4)*Dval(dd0033,Di5) -
+ & D2345(DD0033)
+ E(EE333) = -(eta(2)*D1345(DD222)) -
+ & eta(3)*D1245(DD222) - eta(5)*D1234(DD333) -
+ & eta(1)*D2345(DD222) +
+ & 6*zeta(1,3)*D1345(DD0022) +
+ & 6*zeta(2,3)*D1245(DD0022) +
+ & 6*zeta(3,4)*D1234(DD0033) -
& 6*(zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & Dval(dd0022,Di1)
- E(ee334) = -(eta(2)*Dval(dd223,Di2)) -
- & eta(3)*Dval(dd223,Di3) - eta(1)*Dval(dd223,Di1) +
- & 2*zeta(1,4)*Dval(dd0022,Di2) +
- & 2*zeta(2,4)*Dval(dd0022,Di3) +
- & 4*zeta(1,3)*Dval(dd0023,Di2) +
- & 4*zeta(2,3)*Dval(dd0023,Di3) +
- & 2*zeta(4,4)*Dval(dd0033,Di5) -
+ & D2345(DD0022)
+ E(EE334) = -(eta(2)*D1345(DD223)) -
+ & eta(3)*D1245(DD223) - eta(1)*D2345(DD223) +
+ & 2*zeta(1,4)*D1345(DD0022) +
+ & 2*zeta(2,4)*D1245(DD0022) +
+ & 4*zeta(1,3)*D1345(DD0023) +
+ & 4*zeta(2,3)*D1245(DD0023) +
+ & 2*zeta(4,4)*D1234(DD0033) -
& 2*(zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd0022,Di1) -
+ & D2345(DD0022) -
& 4*(zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & Dval(dd0023,Di1)
- E(ee344) = -(eta(2)*Dval(dd233,Di2)) -
- & eta(3)*Dval(dd233,Di3) - eta(1)*Dval(dd233,Di1) +
- & 4*zeta(1,4)*Dval(dd0023,Di2) +
- & 4*zeta(2,4)*Dval(dd0023,Di3) +
- & 2*zeta(1,3)*Dval(dd0033,Di2) +
- & 2*zeta(2,3)*Dval(dd0033,Di3) +
- & 2*zeta(3,3)*Dval(dd0033,Di4) -
+ & D2345(DD0023)
+ E(EE344) = -(eta(2)*D1345(DD233)) -
+ & eta(3)*D1245(DD233) - eta(1)*D2345(DD233) +
+ & 4*zeta(1,4)*D1345(DD0023) +
+ & 4*zeta(2,4)*D1245(DD0023) +
+ & 2*zeta(1,3)*D1345(DD0033) +
+ & 2*zeta(2,3)*D1245(DD0033) +
+ & 2*zeta(3,3)*D1235(DD0033) -
& 4*(zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd0023,Di1) -
+ & D2345(DD0023) -
& 2*(zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & Dval(dd0033,Di1)
- E(ee444) = -(eta(2)*Dval(dd333,Di2)) -
- & eta(3)*Dval(dd333,Di3) - eta(4)*Dval(dd333,Di4) -
- & eta(1)*Dval(dd333,Di1) +
- & 6*zeta(1,4)*Dval(dd0033,Di2) +
- & 6*zeta(2,4)*Dval(dd0033,Di3) +
- & 6*zeta(3,4)*Dval(dd0033,Di4) -
+ & D2345(DD0033)
+ E(EE444) = -(eta(2)*D1345(DD333)) -
+ & eta(3)*D1245(DD333) - eta(4)*D1235(DD333) -
+ & eta(1)*D2345(DD333) +
+ & 6*zeta(1,4)*D1345(DD0033) +
+ & 6*zeta(2,4)*D1245(DD0033) +
+ & 6*zeta(3,4)*D1235(DD0033) -
& 6*(zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd0033,Di1)
+ & D2345(DD0033)
- E(ee0000) = (-(detZ/detY) -
- & 48*(eta(2)*(Dval(dd0000,Di2) - del) +
- & eta(3)*(Dval(dd0000,Di3) - del) +
- & eta(4)*(Dval(dd0000,Di4) - del) +
- & eta(5)*(Dval(dd0000,Di5) - del) +
- & eta(1)*(Dval(dd0000,Di1) - del)))/48D0
- E(ee0011) = -(dabbr11*eta(1)) -
- & eta(3)*Dval(dd0011,Di3) -
- & eta(4)*Dval(dd0011,Di4) -
- & eta(5)*Dval(dd0011,Di5) +
+ E(EE0000) = (-finite*(detZ/detY) -
+ & 48*(eta(2)*(D1345(DD0000) - del) +
+ & eta(3)*(D1245(DD0000) - del) +
+ & eta(4)*(D1235(DD0000) - del) +
+ & eta(5)*(D1234(DD0000) - del) +
+ & eta(1)*(D2345(DD0000) - del)))/48D0
+ E(EE0011) = -(dabbr11*eta(1)) -
+ & eta(3)*D1245(DD0011) -
+ & eta(4)*D1235(DD0011) -
+ & eta(5)*D1234(DD0011) +
& 4*(dabbr33*(zeta(1,1) + zeta(1,2) + zeta(1,3) +
& zeta(1,4)) +
- & zeta(1,2)*(Dval(dd00001,Di3) + del4) +
- & zeta(1,3)*(Dval(dd00001,Di4) + del4) +
- & zeta(1,4)*(Dval(dd00001,Di5) + del4))
- E(ee0012) = dabbr34*eta(1) -
- & eta(4)*Dval(dd0012,Di4) -
- & eta(5)*Dval(dd0012,Di5) +
+ & zeta(1,2)*(D1245(DD00001) + del4) +
+ & zeta(1,3)*(D1235(DD00001) + del4) +
+ & zeta(1,4)*(D1234(DD00001) + del4))
+ E(EE0012) = dabbr34*eta(1) -
+ & eta(4)*D1235(DD0012) -
+ & eta(5)*D1234(DD0012) +
& 2*(dabbr35*(zeta(1,2) + zeta(2,2) + zeta(2,3) +
& zeta(2,4)) +
- & zeta(1,1)*(Dval(dd00001,Di2) + del4) +
- & zeta(2,2)*(Dval(dd00001,Di3) + del4) +
- & zeta(2,3)*(Dval(dd00001,Di4) + del4) +
- & zeta(2,4)*(Dval(dd00001,Di5) + del4) +
- & zeta(1,3)*(Dval(dd00002,Di4) + del4) +
- & zeta(1,4)*(Dval(dd00002,Di5) + del4) -
+ & zeta(1,1)*(D1345(DD00001) + del4) +
+ & zeta(2,2)*(D1245(DD00001) + del4) +
+ & zeta(2,3)*(D1235(DD00001) + del4) +
+ & zeta(2,4)*(D1234(DD00001) + del4) +
+ & zeta(1,3)*(D1235(DD00002) + del4) +
+ & zeta(1,4)*(D1234(DD00002) + del4) -
& (zeta(1,1) + zeta(1,3) + zeta(1,4) - zeta(2,2) -
& zeta(2,3) - zeta(2,4))*
- & (Dval(dd00001,Di1) + del4))
- E(ee0013) = dabbr36*eta(1) -
- & eta(3)*Dval(dd0012,Di3) -
- & eta(5)*Dval(dd0013,Di5) +
+ & (D2345(DD00001) + del4))
+ E(EE0013) = dabbr36*eta(1) -
+ & eta(3)*D1245(DD0012) -
+ & eta(5)*D1234(DD0013) +
& 2*(dabbr37*(zeta(1,3) + zeta(2,3) + zeta(3,3) +
& zeta(3,4)) +
- & zeta(2,3)*(Dval(dd00001,Di3) + del4) +
- & zeta(3,3)*(Dval(dd00001,Di4) + del4) +
- & zeta(3,4)*(Dval(dd00001,Di5) + del4) +
- & zeta(1,1)*(Dval(dd00002,Di2) + del4) +
- & zeta(1,2)*(Dval(dd00002,Di3) + del4) +
- & zeta(1,4)*(Dval(dd00003,Di5) + del4) -
+ & zeta(2,3)*(D1245(DD00001) + del4) +
+ & zeta(3,3)*(D1235(DD00001) + del4) +
+ & zeta(3,4)*(D1234(DD00001) + del4) +
+ & zeta(1,1)*(D1345(DD00002) + del4) +
+ & zeta(1,2)*(D1245(DD00002) + del4) +
+ & zeta(1,4)*(D1234(DD00003) + del4) -
& (zeta(1,1) + zeta(1,2) + zeta(1,4) - zeta(2,3) -
& zeta(3,3) - zeta(3,4))*
- & (Dval(dd00002,Di1) + del4))
- E(ee0014) = dabbr38*eta(1) -
- & eta(3)*Dval(dd0013,Di3) -
- & eta(4)*Dval(dd0013,Di4) +
+ & (D2345(DD00002) + del4))
+ E(EE0014) = dabbr38*eta(1) -
+ & eta(3)*D1245(DD0013) -
+ & eta(4)*D1235(DD0013) +
& 2*(dabbr39*(zeta(1,4) + zeta(2,4) + zeta(3,4) +
& zeta(4,4)) +
- & zeta(2,4)*(Dval(dd00001,Di3) + del4) +
- & zeta(3,4)*(Dval(dd00001,Di4) + del4) +
- & zeta(4,4)*(Dval(dd00001,Di5) + del4) +
- & zeta(1,1)*(Dval(dd00003,Di2) + del4) +
- & zeta(1,2)*(Dval(dd00003,Di3) + del4) +
- & zeta(1,3)*(Dval(dd00003,Di4) + del4) -
+ & zeta(2,4)*(D1245(DD00001) + del4) +
+ & zeta(3,4)*(D1235(DD00001) + del4) +
+ & zeta(4,4)*(D1234(DD00001) + del4) +
+ & zeta(1,1)*(D1345(DD00003) + del4) +
+ & zeta(1,2)*(D1245(DD00003) + del4) +
+ & zeta(1,3)*(D1235(DD00003) + del4) -
& (zeta(1,1) + zeta(1,2) + zeta(1,3) - zeta(2,4) -
& zeta(3,4) - zeta(4,4))*
- & (Dval(dd00003,Di1) + del4))
- E(ee0022) = -(eta(2)*Dval(dd0011,Di2)) -
- & eta(4)*Dval(dd0022,Di4) -
- & eta(5)*Dval(dd0022,Di5) -
- & eta(1)*Dval(dd0011,Di1) +
- & 4*zeta(1,2)*(Dval(dd00001,Di2) + del4) +
- & 4*zeta(2,3)*(Dval(dd00002,Di4) + del4) +
- & 4*zeta(2,4)*(Dval(dd00002,Di5) + del4) -
+ & (D2345(DD00003) + del4))
+ E(EE0022) = -(eta(2)*D1345(DD0011)) -
+ & eta(4)*D1235(DD0022) -
+ & eta(5)*D1234(DD0022) -
+ & eta(1)*D2345(DD0011) +
+ & 4*zeta(1,2)*(D1345(DD00001) + del4) +
+ & 4*zeta(2,3)*(D1235(DD00002) + del4) +
+ & 4*zeta(2,4)*(D1234(DD00002) + del4) -
& 4*(zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & (Dval(dd00001,Di1) + del4)
- E(ee0023) = -(eta(2)*Dval(dd0012,Di2)) -
- & eta(5)*Dval(dd0023,Di5) -
- & eta(1)*Dval(dd0012,Di1) +
- & 2*(zeta(1,3)*(Dval(dd00001,Di2) + del4) +
- & zeta(1,2)*(Dval(dd00002,Di2) + del4) +
- & zeta(2,2)*(Dval(dd00002,Di3) + del4) +
- & zeta(3,3)*(Dval(dd00002,Di4) + del4) +
- & zeta(3,4)*(Dval(dd00002,Di5) + del4) +
- & zeta(2,4)*(Dval(dd00003,Di5) + del4) -
+ & (D2345(DD00001) + del4)
+ E(EE0023) = -(eta(2)*D1345(DD0012)) -
+ & eta(5)*D1234(DD0023) -
+ & eta(1)*D2345(DD0012) +
+ & 2*(zeta(1,3)*(D1345(DD00001) + del4) +
+ & zeta(1,2)*(D1345(DD00002) + del4) +
+ & zeta(2,2)*(D1245(DD00002) + del4) +
+ & zeta(3,3)*(D1235(DD00002) + del4) +
+ & zeta(3,4)*(D1234(DD00002) + del4) +
+ & zeta(2,4)*(D1234(DD00003) + del4) -
& (zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & (Dval(dd00001,Di1) + del4) -
+ & (D2345(DD00001) + del4) -
& (zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & (Dval(dd00002,Di1) + del4))
- E(ee0024) = -(eta(2)*Dval(dd0013,Di2)) -
- & eta(4)*Dval(dd0023,Di4) -
- & eta(1)*Dval(dd0013,Di1) +
- & 2*(zeta(1,4)*(Dval(dd00001,Di2) + del4) +
- & zeta(3,4)*(Dval(dd00002,Di4) + del4) +
- & zeta(4,4)*(Dval(dd00002,Di5) + del4) +
- & zeta(1,2)*(Dval(dd00003,Di2) + del4) +
- & zeta(2,2)*(Dval(dd00003,Di3) + del4) +
- & zeta(2,3)*(Dval(dd00003,Di4) + del4) -
+ & (D2345(DD00002) + del4))
+ E(EE0024) = -(eta(2)*D1345(DD0013)) -
+ & eta(4)*D1235(DD0023) -
+ & eta(1)*D2345(DD0013) +
+ & 2*(zeta(1,4)*(D1345(DD00001) + del4) +
+ & zeta(3,4)*(D1235(DD00002) + del4) +
+ & zeta(4,4)*(D1234(DD00002) + del4) +
+ & zeta(1,2)*(D1345(DD00003) + del4) +
+ & zeta(2,2)*(D1245(DD00003) + del4) +
+ & zeta(2,3)*(D1235(DD00003) + del4) -
& (zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & (Dval(dd00001,Di1) + del4) -
+ & (D2345(DD00001) + del4) -
& (zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & (Dval(dd00003,Di1) + del4))
- E(ee0033) = -(eta(2)*Dval(dd0022,Di2)) -
- & eta(3)*Dval(dd0022,Di3) -
- & eta(5)*Dval(dd0033,Di5) -
- & eta(1)*Dval(dd0022,Di1) +
- & 4*zeta(1,3)*(Dval(dd00002,Di2) + del4) +
- & 4*zeta(2,3)*(Dval(dd00002,Di3) + del4) +
- & 4*zeta(3,4)*(Dval(dd00003,Di5) + del4) -
+ & (D2345(DD00003) + del4))
+ E(EE0033) = -(eta(2)*D1345(DD0022)) -
+ & eta(3)*D1245(DD0022) -
+ & eta(5)*D1234(DD0033) -
+ & eta(1)*D2345(DD0022) +
+ & 4*zeta(1,3)*(D1345(DD00002) + del4) +
+ & 4*zeta(2,3)*(D1245(DD00002) + del4) +
+ & 4*zeta(3,4)*(D1234(DD00003) + del4) -
& 4*(zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & (Dval(dd00002,Di1) + del4)
- E(ee0034) = -(eta(2)*Dval(dd0023,Di2)) -
- & eta(3)*Dval(dd0023,Di3) -
- & eta(1)*Dval(dd0023,Di1) +
- & 2*(zeta(1,4)*(Dval(dd00002,Di2) + del4) +
- & zeta(2,4)*(Dval(dd00002,Di3) + del4) +
- & zeta(1,3)*(Dval(dd00003,Di2) + del4) +
- & zeta(2,3)*(Dval(dd00003,Di3) + del4) +
- & zeta(3,3)*(Dval(dd00003,Di4) + del4) +
- & zeta(4,4)*(Dval(dd00003,Di5) + del4) -
+ & (D2345(DD00002) + del4)
+ E(EE0034) = -(eta(2)*D1345(DD0023)) -
+ & eta(3)*D1245(DD0023) -
+ & eta(1)*D2345(DD0023) +
+ & 2*(zeta(1,4)*(D1345(DD00002) + del4) +
+ & zeta(2,4)*(D1245(DD00002) + del4) +
+ & zeta(1,3)*(D1345(DD00003) + del4) +
+ & zeta(2,3)*(D1245(DD00003) + del4) +
+ & zeta(3,3)*(D1235(DD00003) + del4) +
+ & zeta(4,4)*(D1234(DD00003) + del4) -
& (zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & (Dval(dd00002,Di1) + del4) -
+ & (D2345(DD00002) + del4) -
& (zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & (Dval(dd00003,Di1) + del4))
- E(ee0044) = -(eta(2)*Dval(dd0033,Di2)) -
- & eta(3)*Dval(dd0033,Di3) -
- & eta(4)*Dval(dd0033,Di4) -
- & eta(1)*Dval(dd0033,Di1) +
- & 4*zeta(1,4)*(Dval(dd00003,Di2) + del4) +
- & 4*zeta(2,4)*(Dval(dd00003,Di3) + del4) +
- & 4*zeta(3,4)*(Dval(dd00003,Di4) + del4) -
+ & (D2345(DD00003) + del4))
+ E(EE0044) = -(eta(2)*D1345(DD0033)) -
+ & eta(3)*D1245(DD0033) -
+ & eta(4)*D1235(DD0033) -
+ & eta(1)*D2345(DD0033) +
+ & 4*zeta(1,4)*(D1345(DD00003) + del4) +
+ & 4*zeta(2,4)*(D1245(DD00003) + del4) +
+ & 4*zeta(3,4)*(D1235(DD00003) + del4) -
& 4*(zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & (Dval(dd00003,Di1) + del4)
- E(ee1111) = -(dabbr40*eta(1)) -
- & eta(3)*Dval(dd1111,Di3) -
- & eta(4)*Dval(dd1111,Di4) -
- & eta(5)*Dval(dd1111,Di5) +
- & 8*zeta(1,2)*Dval(dd00111,Di3) +
- & 8*zeta(1,3)*Dval(dd00111,Di4) +
- & 8*zeta(1,4)*Dval(dd00111,Di5) +
+ & (D2345(DD00003) + del4)
+ E(EE1111) = -(dabbr40*eta(1)) -
+ & eta(3)*D1245(DD1111) -
+ & eta(4)*D1235(DD1111) -
+ & eta(5)*D1234(DD1111) +
+ & 8*zeta(1,2)*D1245(DD00111) +
+ & 8*zeta(1,3)*D1235(DD00111) +
+ & 8*zeta(1,4)*D1234(DD00111) +
& 8*(zeta(1,1) + zeta(1,2) + zeta(1,3) + zeta(1,4))*
- & (3*dabbr41 + Dval(dd00,Di1) +
- & 3*Dval(dd001,Di1) + 3*Dval(dd002,Di1) +
- & 3*Dval(dd003,Di1) + 3*Dval(dd0011,Di1) +
- & 6*Dval(dd0012,Di1) + 6*Dval(dd0013,Di1) +
- & 3*Dval(dd0022,Di1) + 6*Dval(dd0023,Di1) +
- & 3*Dval(dd0033,Di1) + Dval(dd00111,Di1) +
- & 3*Dval(dd00112,Di1) + 3*Dval(dd00113,Di1) +
- & 3*Dval(dd00122,Di1) + 6*Dval(dd00123,Di1) +
- & 3*Dval(dd00133,Di1) + Dval(dd00222,Di1) +
- & Dval(dd00333,Di1))
- E(ee1112) = -6*dabbr44*
+ & (3*dabbr41 + D2345(DD00) +
+ & 3*D2345(DD001) + 3*D2345(DD002) +
+ & 3*D2345(DD003) + 3*D2345(DD0011) +
+ & 6*D2345(DD0012) + 6*D2345(DD0013) +
+ & 3*D2345(DD0022) + 6*D2345(DD0023) +
+ & 3*D2345(DD0033) + D2345(DD00111) +
+ & 3*D2345(DD00112) + 3*D2345(DD00113) +
+ & 3*D2345(DD00122) + 6*D2345(DD00123) +
+ & 3*D2345(DD00133) + D2345(DD00222) +
+ & D2345(DD00333))
+ E(EE1112) = -6*dabbr44*
& (zeta(1,1) + zeta(1,3) + zeta(1,4) - zeta(2,2) -
& zeta(2,3) - zeta(2,4)) -
& 6*dabbr43*(2*zeta(1,1) + zeta(1,2) + 2*zeta(1,3) +
& 2*zeta(1,4) - zeta(2,2) - zeta(2,3) - zeta(2,4)) -
- & eta(4)*Dval(dd1112,Di4) -
- & eta(5)*Dval(dd1112,Di5) +
- & eta(1)*(3*dabbr42 + Dval(dd1,Di1) +
- & 3*Dval(dd11,Di1) + 3*Dval(dd12,Di1) +
- & 3*Dval(dd13,Di1) + 3*Dval(dd111,Di1) +
- & 6*Dval(dd112,Di1) + 6*Dval(dd113,Di1) +
- & 3*Dval(dd122,Di1) + 6*Dval(dd123,Di1) +
- & 3*Dval(dd133,Di1) + Dval(dd1111,Di1) +
- & 3*Dval(dd1112,Di1) + 3*Dval(dd1113,Di1) +
- & 3*Dval(dd1122,Di1) + 6*Dval(dd1123,Di1) +
- & 3*Dval(dd1133,Di1) + Dval(dd1222,Di1) +
- & Dval(dd1333,Di1)) +
- & 2*(zeta(2,2)*Dval(dd00111,Di3) +
- & zeta(2,3)*Dval(dd00111,Di4) +
- & zeta(2,4)*Dval(dd00111,Di5) +
- & 3*zeta(1,3)*Dval(dd00112,Di4) +
- & 3*zeta(1,4)*Dval(dd00112,Di5) +
+ & eta(4)*D1235(DD1112) -
+ & eta(5)*D1234(DD1112) +
+ & eta(1)*(3*dabbr42 + D2345(DD1) +
+ & 3*D2345(DD11) + 3*D2345(DD12) +
+ & 3*D2345(DD13) + 3*D2345(DD111) +
+ & 6*D2345(DD112) + 6*D2345(DD113) +
+ & 3*D2345(DD122) + 6*D2345(DD123) +
+ & 3*D2345(DD133) + D2345(DD1111) +
+ & 3*D2345(DD1112) + 3*D2345(DD1113) +
+ & 3*D2345(DD1122) + 6*D2345(DD1123) +
+ & 3*D2345(DD1133) + D2345(DD1222) +
+ & D2345(DD1333)) +
+ & 2*(zeta(2,2)*D1245(DD00111) +
+ & zeta(2,3)*D1235(DD00111) +
+ & zeta(2,4)*D1234(DD00111) +
+ & 3*zeta(1,3)*D1235(DD00112) +
+ & 3*zeta(1,4)*D1234(DD00112) +
& (-3*zeta(1,1) - 2*zeta(1,2) - 3*zeta(1,3) -
& 3*zeta(1,4) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & Dval(dd00111,Di1)) +
+ & D2345(DD00111)) +
& 2*(zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & (3*dabbr41 + Dval(dd00,Di1) +
- & 3*Dval(dd002,Di1) + 3*Dval(dd003,Di1) +
- & 3*Dval(dd0022,Di1) + 6*Dval(dd0023,Di1) +
- & 3*Dval(dd0033,Di1) + Dval(dd00222,Di1) +
- & Dval(dd00333,Di1))
- E(ee1113) = -6*dabbr47*
+ & (3*dabbr41 + D2345(DD00) +
+ & 3*D2345(DD002) + 3*D2345(DD003) +
+ & 3*D2345(DD0022) + 6*D2345(DD0023) +
+ & 3*D2345(DD0033) + D2345(DD00222) +
+ & D2345(DD00333))
+ E(EE1113) = -6*dabbr47*
& (zeta(1,1) + zeta(1,2) + zeta(1,4) - zeta(2,3) -
& zeta(3,3) - zeta(3,4)) -
& 6*dabbr46*(2*zeta(1,1) + 2*zeta(1,2) + zeta(1,3) +
& 2*zeta(1,4) - zeta(2,3) - zeta(3,3) - zeta(3,4)) -
- & eta(3)*Dval(dd1112,Di3) -
- & eta(5)*Dval(dd1113,Di5) +
- & eta(1)*(3*dabbr45 + Dval(dd2,Di1) +
- & 3*Dval(dd12,Di1) + 3*Dval(dd22,Di1) +
- & 3*Dval(dd23,Di1) + 3*Dval(dd112,Di1) +
- & 6*Dval(dd122,Di1) + 6*Dval(dd123,Di1) +
- & 3*Dval(dd222,Di1) + 6*Dval(dd223,Di1) +
- & 3*Dval(dd233,Di1) + Dval(dd1112,Di1) +
- & 3*Dval(dd1122,Di1) + 3*Dval(dd1123,Di1) +
- & 3*Dval(dd1222,Di1) + 6*Dval(dd1223,Di1) +
- & 3*Dval(dd1233,Di1) + Dval(dd2222,Di1) +
- & Dval(dd2333,Di1)) +
- & 2*(zeta(2,3)*Dval(dd00111,Di3) +
- & zeta(3,3)*Dval(dd00111,Di4) +
- & zeta(3,4)*Dval(dd00111,Di5) +
- & 3*zeta(1,2)*Dval(dd00112,Di3) +
- & 3*zeta(1,4)*Dval(dd00113,Di5) +
+ & eta(3)*D1245(DD1112) -
+ & eta(5)*D1234(DD1113) +
+ & eta(1)*(3*dabbr45 + D2345(DD2) +
+ & 3*D2345(DD12) + 3*D2345(DD22) +
+ & 3*D2345(DD23) + 3*D2345(DD112) +
+ & 6*D2345(DD122) + 6*D2345(DD123) +
+ & 3*D2345(DD222) + 6*D2345(DD223) +
+ & 3*D2345(DD233) + D2345(DD1112) +
+ & 3*D2345(DD1122) + 3*D2345(DD1123) +
+ & 3*D2345(DD1222) + 6*D2345(DD1223) +
+ & 3*D2345(DD1233) + D2345(DD2222) +
+ & D2345(DD2333)) +
+ & 2*(zeta(2,3)*D1245(DD00111) +
+ & zeta(3,3)*D1235(DD00111) +
+ & zeta(3,4)*D1234(DD00111) +
+ & 3*zeta(1,2)*D1245(DD00112) +
+ & 3*zeta(1,4)*D1234(DD00113) +
& (-3*zeta(1,1) - 3*zeta(1,2) - 2*zeta(1,3) -
& 3*zeta(1,4) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & Dval(dd00222,Di1)) +
+ & D2345(DD00222)) +
& 2*(zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & (3*dabbr48 + Dval(dd00,Di1) +
- & 3*Dval(dd001,Di1) + 3*Dval(dd003,Di1) +
- & 3*Dval(dd0011,Di1) + 6*Dval(dd0013,Di1) +
- & 3*Dval(dd0033,Di1) + Dval(dd00111,Di1) +
- & Dval(dd00333,Di1))
- E(ee1114) = -6*dabbr51*
+ & (3*dabbr48 + D2345(DD00) +
+ & 3*D2345(DD001) + 3*D2345(DD003) +
+ & 3*D2345(DD0011) + 6*D2345(DD0013) +
+ & 3*D2345(DD0033) + D2345(DD00111) +
+ & D2345(DD00333))
+ E(EE1114) = -6*dabbr51*
& (zeta(1,1) + zeta(1,2) + zeta(1,3) - zeta(2,4) -
& zeta(3,4) - zeta(4,4)) -
& 6*dabbr52*(2*zeta(1,1) + 2*zeta(1,2) + 2*zeta(1,3) +
& zeta(1,4) - zeta(2,4) - zeta(3,4) - zeta(4,4)) -
- & eta(3)*Dval(dd1113,Di3) -
- & eta(4)*Dval(dd1113,Di4) +
- & eta(1)*(3*dabbr49 + Dval(dd3,Di1) +
- & 3*Dval(dd13,Di1) + 3*Dval(dd23,Di1) +
- & 3*Dval(dd33,Di1) + 3*Dval(dd113,Di1) +
- & 6*Dval(dd123,Di1) + 6*Dval(dd133,Di1) +
- & 3*Dval(dd223,Di1) + 6*Dval(dd233,Di1) +
- & 3*Dval(dd333,Di1) + Dval(dd1113,Di1) +
- & 3*Dval(dd1123,Di1) + 3*Dval(dd1133,Di1) +
- & 3*Dval(dd1223,Di1) + 6*Dval(dd1233,Di1) +
- & 3*Dval(dd1333,Di1) + Dval(dd2223,Di1) +
- & Dval(dd3333,Di1)) +
+ & eta(3)*D1245(DD1113) -
+ & eta(4)*D1235(DD1113) +
+ & eta(1)*(3*dabbr49 + D2345(DD3) +
+ & 3*D2345(DD13) + 3*D2345(DD23) +
+ & 3*D2345(DD33) + 3*D2345(DD113) +
+ & 6*D2345(DD123) + 6*D2345(DD133) +
+ & 3*D2345(DD223) + 6*D2345(DD233) +
+ & 3*D2345(DD333) + D2345(DD1113) +
+ & 3*D2345(DD1123) + 3*D2345(DD1133) +
+ & 3*D2345(DD1223) + 6*D2345(DD1233) +
+ & 3*D2345(DD1333) + D2345(DD2223) +
+ & D2345(DD3333)) +
& 2*(zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & (3*dabbr50 + Dval(dd00,Di1) +
- & 3*Dval(dd001,Di1) + 3*Dval(dd002,Di1) +
- & 3*Dval(dd0011,Di1) + 6*Dval(dd0012,Di1) +
- & 3*Dval(dd0022,Di1) + Dval(dd00111,Di1) +
- & Dval(dd00222,Di1)) +
- & 2*(zeta(2,4)*Dval(dd00111,Di3) +
- & zeta(3,4)*Dval(dd00111,Di4) +
- & zeta(4,4)*Dval(dd00111,Di5) +
- & 3*zeta(1,2)*Dval(dd00113,Di3) +
- & 3*zeta(1,3)*Dval(dd00113,Di4) +
+ & (3*dabbr50 + D2345(DD00) +
+ & 3*D2345(DD001) + 3*D2345(DD002) +
+ & 3*D2345(DD0011) + 6*D2345(DD0012) +
+ & 3*D2345(DD0022) + D2345(DD00111) +
+ & D2345(DD00222)) +
+ & 2*(zeta(2,4)*D1245(DD00111) +
+ & zeta(3,4)*D1235(DD00111) +
+ & zeta(4,4)*D1234(DD00111) +
+ & 3*zeta(1,2)*D1245(DD00113) +
+ & 3*zeta(1,3)*D1235(DD00113) +
& (-3*zeta(1,1) - 3*zeta(1,2) - 3*zeta(1,3) -
& 2*zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd00333,Di1))
- E(ee1122) = -(dabbr53*eta(1)) -
+ & D2345(DD00333))
+ E(EE1122) = -(dabbr53*eta(1)) -
& 4*dabbr44*(zeta(1,2) + zeta(2,2) + zeta(2,3) +
- & zeta(2,4)) - eta(4)*Dval(dd1122,Di4) -
- & eta(5)*Dval(dd1122,Di5) +
+ & zeta(2,4)) - eta(4)*D1235(DD1122) -
+ & eta(5)*D1234(DD1122) +
& 4*(-2*dabbr43*(zeta(2,2) + zeta(2,3) + zeta(2,4)) +
- & zeta(1,1)*Dval(dd0011,Di1) -
- & zeta(1,2)*Dval(dd0011,Di1) +
- & zeta(1,3)*Dval(dd0011,Di1) +
- & zeta(1,4)*Dval(dd0011,Di1) +
- & zeta(2,3)*Dval(dd00112,Di4) +
- & zeta(2,4)*Dval(dd00112,Di5) +
- & zeta(1,3)*Dval(dd00122,Di4) +
- & zeta(1,4)*Dval(dd00122,Di5) +
+ & zeta(1,1)*D2345(DD0011) -
+ & zeta(1,2)*D2345(DD0011) +
+ & zeta(1,3)*D2345(DD0011) +
+ & zeta(1,4)*D2345(DD0011) +
+ & zeta(2,3)*D1235(DD00112) +
+ & zeta(2,4)*D1234(DD00112) +
+ & zeta(1,3)*D1235(DD00122) +
+ & zeta(1,4)*D1234(DD00122) +
& (zeta(1,1) + zeta(1,3) + zeta(1,4) - zeta(2,2) -
- & zeta(2,3) - zeta(2,4))*Dval(dd00111,Di1) +
- & zeta(1,1)*Dval(dd00112,Di1) -
- & zeta(1,2)*Dval(dd00112,Di1) +
- & zeta(1,3)*Dval(dd00112,Di1) +
- & zeta(1,4)*Dval(dd00112,Di1) +
+ & zeta(2,3) - zeta(2,4))*D2345(DD00111) +
+ & zeta(1,1)*D2345(DD00112) -
+ & zeta(1,2)*D2345(DD00112) +
+ & zeta(1,3)*D2345(DD00112) +
+ & zeta(1,4)*D2345(DD00112) +
& (zeta(1,1) - zeta(1,2) + zeta(1,3) + zeta(1,4))*
- & Dval(dd00113,Di1))
- E(ee1123) = -(dabbr54*eta(1)) -
+ & D2345(DD00113))
+ E(EE1123) = -(dabbr54*eta(1)) -
& 2*dabbr57*(zeta(1,2) + zeta(2,2) + zeta(2,3) +
& zeta(2,4)) - 2*dabbr56*
& (zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4)) -
- & eta(5)*Dval(dd1123,Di5) +
+ & eta(5)*D1234(DD1123) +
& 2*(2*dabbr55*(zeta(1,1) + zeta(1,4) - zeta(2,2) -
& 2*zeta(2,3) - zeta(2,4) - zeta(3,3) - zeta(3,4)) +
- & zeta(2,2)*Dval(dd00112,Di3) +
- & zeta(3,3)*Dval(dd00112,Di4) +
- & zeta(3,4)*Dval(dd00112,Di5) +
- & zeta(2,4)*Dval(dd00113,Di5) +
- & 2*zeta(1,4)*Dval(dd00123,Di5) +
+ & zeta(2,2)*D1245(DD00112) +
+ & zeta(3,3)*D1235(DD00112) +
+ & zeta(3,4)*D1234(DD00112) +
+ & zeta(2,4)*D1234(DD00113) +
+ & 2*zeta(1,4)*D1234(DD00123) +
& (2*zeta(1,1) + zeta(1,2) + 2*zeta(1,4) - zeta(2,2) -
& 3*zeta(2,3) - zeta(2,4) - 2*zeta(3,3) - 2*zeta(3,4))
- & *Dval(dd00112,Di1) +
+ & *D2345(DD00112) +
& (2*zeta(1,1) + zeta(1,3) + 2*zeta(1,4) - 2*zeta(2,2) -
& 3*zeta(2,3) - 2*zeta(2,4) - zeta(3,3) - zeta(3,4))*
- & Dval(dd00122,Di1))
- E(ee1124) = -(dabbr58*eta(1)) -
+ & D2345(DD00122))
+ E(EE1124) = -(dabbr58*eta(1)) -
& 2*dabbr61*(zeta(1,2) + zeta(2,2) + zeta(2,3) +
& zeta(2,4)) - 2*dabbr59*
& (zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4)) -
- & eta(4)*Dval(dd1123,Di4) +
+ & eta(4)*D1235(DD1123) +
& 2*(2*dabbr60*(zeta(1,1) + zeta(1,3) - zeta(2,2) -
& zeta(2,3) - 2*zeta(2,4) - zeta(3,4) - zeta(4,4)) +
- & zeta(3,4)*Dval(dd00112,Di4) +
- & zeta(4,4)*Dval(dd00112,Di5) +
- & zeta(2,2)*Dval(dd00113,Di3) +
- & zeta(2,3)*Dval(dd00113,Di4) +
- & 2*zeta(1,3)*Dval(dd00123,Di4) +
+ & zeta(3,4)*D1235(DD00112) +
+ & zeta(4,4)*D1234(DD00112) +
+ & zeta(2,2)*D1245(DD00113) +
+ & zeta(2,3)*D1235(DD00113) +
+ & 2*zeta(1,3)*D1235(DD00123) +
& (2*zeta(1,1) + zeta(1,2) + 2*zeta(1,3) - zeta(2,2) -
& zeta(2,3) - 3*zeta(2,4) - 2*zeta(3,4) - 2*zeta(4,4))
- & *Dval(dd00113,Di1) +
+ & *D2345(DD00113) +
& (2*zeta(1,1) + 2*zeta(1,3) + zeta(1,4) - 2*zeta(2,2) -
& 2*zeta(2,3) - 3*zeta(2,4) - zeta(3,4) - zeta(4,4))*
- & Dval(dd00133,Di1))
- E(ee1133) = -(dabbr62*eta(1)) -
+ & D2345(DD00133))
+ E(EE1133) = -(dabbr62*eta(1)) -
& 4*dabbr47*(zeta(1,3) + zeta(2,3) + zeta(3,3) +
- & zeta(3,4)) - eta(3)*Dval(dd1122,Di3) -
- & eta(5)*Dval(dd1133,Di5) +
+ & zeta(3,4)) - eta(3)*D1245(DD1122) -
+ & eta(5)*D1234(DD1133) +
& 4*(-2*dabbr46*(zeta(2,3) + zeta(3,3) + zeta(3,4)) +
- & zeta(1,1)*Dval(dd0022,Di1) +
- & zeta(1,2)*Dval(dd0022,Di1) -
- & zeta(1,3)*Dval(dd0022,Di1) +
- & zeta(1,4)*Dval(dd0022,Di1) +
- & zeta(2,3)*Dval(dd00112,Di3) +
- & zeta(3,4)*Dval(dd00113,Di5) +
- & zeta(1,2)*Dval(dd00122,Di3) +
- & zeta(1,4)*Dval(dd00133,Di5) +
- & zeta(1,1)*Dval(dd00122,Di1) +
- & zeta(1,2)*Dval(dd00122,Di1) -
- & zeta(1,3)*Dval(dd00122,Di1) +
- & zeta(1,4)*Dval(dd00122,Di1) +
+ & zeta(1,1)*D2345(DD0022) +
+ & zeta(1,2)*D2345(DD0022) -
+ & zeta(1,3)*D2345(DD0022) +
+ & zeta(1,4)*D2345(DD0022) +
+ & zeta(2,3)*D1245(DD00112) +
+ & zeta(3,4)*D1234(DD00113) +
+ & zeta(1,2)*D1245(DD00122) +
+ & zeta(1,4)*D1234(DD00133) +
+ & zeta(1,1)*D2345(DD00122) +
+ & zeta(1,2)*D2345(DD00122) -
+ & zeta(1,3)*D2345(DD00122) +
+ & zeta(1,4)*D2345(DD00122) +
& (zeta(1,1) + zeta(1,2) + zeta(1,4) - zeta(2,3) -
- & zeta(3,3) - zeta(3,4))*Dval(dd00222,Di1) +
+ & zeta(3,3) - zeta(3,4))*D2345(DD00222) +
& (zeta(1,1) + zeta(1,2) - zeta(1,3) + zeta(1,4))*
- & Dval(dd00223,Di1))
- E(ee1134) = -(dabbr63*eta(1)) -
+ & D2345(DD00223))
+ E(EE1134) = -(dabbr63*eta(1)) -
& 2*dabbr66*(zeta(1,3) + zeta(2,3) + zeta(3,3) +
& zeta(3,4)) - 2*dabbr64*
& (zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4)) -
- & eta(3)*Dval(dd1123,Di3) +
+ & eta(3)*D1245(DD1123) +
& 2*(2*dabbr65*(zeta(1,1) + zeta(1,2) - zeta(2,3) -
& zeta(2,4) - zeta(3,3) - 2*zeta(3,4) - zeta(4,4)) +
- & zeta(2,4)*Dval(dd00112,Di3) +
- & zeta(2,3)*Dval(dd00113,Di3) +
- & zeta(3,3)*Dval(dd00113,Di4) +
- & zeta(4,4)*Dval(dd00113,Di5) +
- & 2*zeta(1,2)*Dval(dd00123,Di3) +
+ & zeta(2,4)*D1245(DD00112) +
+ & zeta(2,3)*D1245(DD00113) +
+ & zeta(3,3)*D1235(DD00113) +
+ & zeta(4,4)*D1234(DD00113) +
+ & 2*zeta(1,2)*D1245(DD00123) +
& (2*zeta(1,1) + 2*zeta(1,2) + zeta(1,3) - zeta(2,3) -
& 2*zeta(2,4) - zeta(3,3) - 3*zeta(3,4) - 2*zeta(4,4))
- & *Dval(dd00223,Di1) +
+ & *D2345(DD00223) +
& (2*zeta(1,1) + 2*zeta(1,2) + zeta(1,4) - 2*zeta(2,3) -
& zeta(2,4) - 2*zeta(3,3) - 3*zeta(3,4) - zeta(4,4))*
- & Dval(dd00233,Di1))
- E(ee1144) = -(dabbr67*eta(1)) -
+ & D2345(DD00233))
+ E(EE1144) = -(dabbr67*eta(1)) -
& 4*dabbr51*(zeta(1,4) + zeta(2,4) + zeta(3,4) +
- & zeta(4,4)) - eta(3)*Dval(dd1133,Di3) -
- & eta(4)*Dval(dd1133,Di4) +
+ & zeta(4,4)) - eta(3)*D1245(DD1133) -
+ & eta(4)*D1235(DD1133) +
& 4*(-2*dabbr52*(zeta(2,4) + zeta(3,4) + zeta(4,4)) +
- & zeta(1,1)*Dval(dd0033,Di1) +
- & zeta(1,2)*Dval(dd0033,Di1) +
- & zeta(1,3)*Dval(dd0033,Di1) -
- & zeta(1,4)*Dval(dd0033,Di1) +
- & zeta(2,4)*Dval(dd00113,Di3) +
- & zeta(3,4)*Dval(dd00113,Di4) +
- & zeta(1,2)*Dval(dd00133,Di3) +
- & zeta(1,3)*Dval(dd00133,Di4) +
- & zeta(1,1)*Dval(dd00133,Di1) +
- & zeta(1,2)*Dval(dd00133,Di1) +
- & zeta(1,3)*Dval(dd00133,Di1) -
- & zeta(1,4)*Dval(dd00133,Di1) +
+ & zeta(1,1)*D2345(DD0033) +
+ & zeta(1,2)*D2345(DD0033) +
+ & zeta(1,3)*D2345(DD0033) -
+ & zeta(1,4)*D2345(DD0033) +
+ & zeta(2,4)*D1245(DD00113) +
+ & zeta(3,4)*D1235(DD00113) +
+ & zeta(1,2)*D1245(DD00133) +
+ & zeta(1,3)*D1235(DD00133) +
+ & zeta(1,1)*D2345(DD00133) +
+ & zeta(1,2)*D2345(DD00133) +
+ & zeta(1,3)*D2345(DD00133) -
+ & zeta(1,4)*D2345(DD00133) +
& (zeta(1,1) + zeta(1,2) + zeta(1,3) - zeta(1,4))*
- & Dval(dd00233,Di1) +
+ & D2345(DD00233) +
& (zeta(1,1) + zeta(1,2) + zeta(1,3) - zeta(2,4) -
- & zeta(3,4) - zeta(4,4))*Dval(dd00333,Di1))
- E(ee1222) = dabbr68*eta(1) -
- & eta(4)*Dval(dd1222,Di4) -
- & eta(5)*Dval(dd1222,Di5) +
+ & zeta(3,4) - zeta(4,4))*D2345(DD00333))
+ E(EE1222) = dabbr68*eta(1) -
+ & eta(4)*D1235(DD1222) -
+ & eta(5)*D1234(DD1222) +
& 2*(3*dabbr43*(zeta(1,2) + zeta(2,2) + zeta(2,3) +
- & zeta(2,4)) + zeta(1,1)*Dval(dd00111,Di2) +
- & 3*zeta(2,3)*Dval(dd00122,Di4) +
- & 3*zeta(2,4)*Dval(dd00122,Di5) +
- & zeta(1,3)*Dval(dd00222,Di4) +
- & zeta(1,4)*Dval(dd00222,Di5) -
+ & zeta(2,4)) + zeta(1,1)*D1345(DD00111) +
+ & 3*zeta(2,3)*D1235(DD00122) +
+ & 3*zeta(2,4)*D1234(DD00122) +
+ & zeta(1,3)*D1235(DD00222) +
+ & zeta(1,4)*D1234(DD00222) -
& (zeta(1,1) - 2*zeta(1,2) + zeta(1,3) + zeta(1,4) -
& 3*(zeta(2,2) + zeta(2,3) + zeta(2,4)))*
- & Dval(dd00111,Di1))
- E(ee1223) = dabbr69*eta(1) -
- & eta(5)*Dval(dd1223,Di5) +
+ & D2345(DD00111))
+ E(EE1223) = dabbr69*eta(1) -
+ & eta(5)*D1234(DD1223) +
& 2*(2*dabbr71*(zeta(1,2) + zeta(2,2) + zeta(2,3) +
& zeta(2,4)) +
& dabbr70*(zeta(1,3) + zeta(2,3) + zeta(3,3) +
- & zeta(3,4)) + zeta(1,1)*Dval(dd00112,Di2) +
- & zeta(3,3)*Dval(dd00122,Di4) +
- & zeta(3,4)*Dval(dd00122,Di5) +
- & 2*zeta(2,4)*Dval(dd00123,Di5) +
- & zeta(1,4)*Dval(dd00223,Di5) +
+ & zeta(3,4)) + zeta(1,1)*D1345(DD00112) +
+ & zeta(3,3)*D1235(DD00122) +
+ & zeta(3,4)*D1234(DD00122) +
+ & 2*zeta(2,4)*D1234(DD00123) +
+ & zeta(1,4)*D1234(DD00223) +
& (-zeta(1,1) + zeta(1,2) - zeta(1,4) + 2*zeta(2,2) +
& 3*zeta(2,3) + 2*zeta(2,4) + zeta(3,3) + zeta(3,4))*
- & Dval(dd00112,Di1))
- E(ee1224) = dabbr72*eta(1) -
- & eta(4)*Dval(dd1223,Di4) +
+ & D2345(DD00112))
+ E(EE1224) = dabbr72*eta(1) -
+ & eta(4)*D1235(DD1223) +
& 2*(2*dabbr74*(zeta(1,2) + zeta(2,2) + zeta(2,3) +
& zeta(2,4)) +
& dabbr73*(zeta(1,4) + zeta(2,4) + zeta(3,4) +
- & zeta(4,4)) + zeta(1,1)*Dval(dd00113,Di2) +
- & zeta(3,4)*Dval(dd00122,Di4) +
- & zeta(4,4)*Dval(dd00122,Di5) +
- & 2*zeta(2,3)*Dval(dd00123,Di4) +
- & zeta(1,3)*Dval(dd00223,Di4) +
+ & zeta(4,4)) + zeta(1,1)*D1345(DD00113) +
+ & zeta(3,4)*D1235(DD00122) +
+ & zeta(4,4)*D1234(DD00122) +
+ & 2*zeta(2,3)*D1235(DD00123) +
+ & zeta(1,3)*D1235(DD00223) +
& (-zeta(1,1) + zeta(1,2) - zeta(1,3) + 2*zeta(2,2) +
& 2*zeta(2,3) + 3*zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd00113,Di1))
- E(ee1233) = dabbr75*eta(1) -
- & eta(5)*Dval(dd1233,Di5) +
+ & D2345(DD00113))
+ E(EE1233) = dabbr75*eta(1) -
+ & eta(5)*D1234(DD1233) +
& 2*(dabbr77*(zeta(1,2) + zeta(2,2) + zeta(2,3) +
& zeta(2,4)) +
& 2*dabbr76*(zeta(1,3) + zeta(2,3) + zeta(3,3) +
- & zeta(3,4)) + zeta(1,1)*Dval(dd00122,Di2) +
- & zeta(2,2)*Dval(dd00122,Di3) +
- & 2*zeta(3,4)*Dval(dd00123,Di5) +
- & zeta(2,4)*Dval(dd00133,Di5) +
- & zeta(1,4)*Dval(dd00233,Di5) +
+ & zeta(3,4)) + zeta(1,1)*D1345(DD00122) +
+ & zeta(2,2)*D1245(DD00122) +
+ & 2*zeta(3,4)*D1234(DD00123) +
+ & zeta(2,4)*D1234(DD00133) +
+ & zeta(1,4)*D1234(DD00233) +
& (-zeta(1,1) + zeta(1,3) - zeta(1,4) + zeta(2,2) +
& 3*zeta(2,3) + zeta(2,4) + 2*(zeta(3,3) + zeta(3,4)))
- & *Dval(dd00122,Di1))
- E(ee1234) = dabbr78*eta(1) +
+ & *D2345(DD00122))
+ E(EE1234) = dabbr78*eta(1) +
& 2*(dabbr81*(zeta(1,2) + zeta(2,2) + zeta(2,3) +
& zeta(2,4)) +
& dabbr80*(zeta(1,3) + zeta(2,3) + zeta(3,3) +
& zeta(3,4)) +
& dabbr79*(zeta(1,4) + zeta(2,4) + zeta(3,4) +
- & zeta(4,4)) + zeta(1,1)*Dval(dd00123,Di2) +
- & zeta(2,2)*Dval(dd00123,Di3) +
- & zeta(3,3)*Dval(dd00123,Di4) +
- & zeta(4,4)*Dval(dd00123,Di5) +
+ & zeta(4,4)) + zeta(1,1)*D1345(DD00123) +
+ & zeta(2,2)*D1245(DD00123) +
+ & zeta(3,3)*D1235(DD00123) +
+ & zeta(4,4)*D1234(DD00123) +
& (-zeta(1,1) + zeta(2,2) + 2*zeta(2,3) + 2*zeta(2,4) +
& zeta(3,3) + 2*zeta(3,4) + zeta(4,4))*
- & Dval(dd00123,Di1))
- E(ee1244) = dabbr82*eta(1) -
- & eta(4)*Dval(dd1233,Di4) +
+ & D2345(DD00123))
+ E(EE1244) = dabbr82*eta(1) -
+ & eta(4)*D1235(DD1233) +
& 2*(dabbr84*(zeta(1,2) + zeta(2,2) + zeta(2,3) +
& zeta(2,4)) +
& 2*dabbr83*(zeta(1,4) + zeta(2,4) + zeta(3,4) +
- & zeta(4,4)) + 2*zeta(3,4)*Dval(dd00123,Di4) +
- & zeta(1,1)*Dval(dd00133,Di2) +
- & zeta(2,2)*Dval(dd00133,Di3) +
- & zeta(2,3)*Dval(dd00133,Di4) +
- & zeta(1,3)*Dval(dd00233,Di4) +
+ & zeta(4,4)) + 2*zeta(3,4)*D1235(DD00123) +
+ & zeta(1,1)*D1345(DD00133) +
+ & zeta(2,2)*D1245(DD00133) +
+ & zeta(2,3)*D1235(DD00133) +
+ & zeta(1,3)*D1235(DD00233) +
& (-zeta(1,1) - zeta(1,3) + zeta(1,4) + zeta(2,2) +
& zeta(2,3) + 3*zeta(2,4) + 2*(zeta(3,4) + zeta(4,4)))
- & *Dval(dd00133,Di1))
- E(ee1333) = dabbr85*eta(1) -
- & eta(3)*Dval(dd1222,Di3) -
- & eta(5)*Dval(dd1333,Di5) +
+ & *D2345(DD00133))
+ E(EE1333) = dabbr85*eta(1) -
+ & eta(3)*D1245(DD1222) -
+ & eta(5)*D1234(DD1333) +
& 2*(3*dabbr46*(zeta(1,3) + zeta(2,3) + zeta(3,3) +
- & zeta(3,4)) + 3*zeta(2,3)*Dval(dd00122,Di3) +
- & 3*zeta(3,4)*Dval(dd00133,Di5) +
- & zeta(1,1)*Dval(dd00222,Di2) +
- & zeta(1,2)*Dval(dd00222,Di3) +
- & zeta(1,4)*Dval(dd00333,Di5) -
+ & zeta(3,4)) + 3*zeta(2,3)*D1245(DD00122) +
+ & 3*zeta(3,4)*D1234(DD00133) +
+ & zeta(1,1)*D1345(DD00222) +
+ & zeta(1,2)*D1245(DD00222) +
+ & zeta(1,4)*D1234(DD00333) -
& (zeta(1,1) + zeta(1,2) - 2*zeta(1,3) + zeta(1,4) -
& 3*(zeta(2,3) + zeta(3,3) + zeta(3,4)))*
- & Dval(dd00222,Di1))
- E(ee1334) = dabbr86*eta(1) -
- & eta(3)*Dval(dd1223,Di3) +
+ & D2345(DD00222))
+ E(EE1334) = dabbr86*eta(1) -
+ & eta(3)*D1245(DD1223) +
& 2*(2*dabbr88*(zeta(1,3) + zeta(2,3) + zeta(3,3) +
& zeta(3,4)) +
& dabbr87*(zeta(1,4) + zeta(2,4) + zeta(3,4) +
- & zeta(4,4)) + zeta(2,4)*Dval(dd00122,Di3) +
- & 2*zeta(2,3)*Dval(dd00123,Di3) +
- & zeta(4,4)*Dval(dd00133,Di5) +
- & zeta(1,1)*Dval(dd00223,Di2) +
- & zeta(1,2)*Dval(dd00223,Di3) +
+ & zeta(4,4)) + zeta(2,4)*D1245(DD00122) +
+ & 2*zeta(2,3)*D1245(DD00123) +
+ & zeta(4,4)*D1234(DD00133) +
+ & zeta(1,1)*D1345(DD00223) +
+ & zeta(1,2)*D1245(DD00223) +
& (-zeta(1,1) - zeta(1,2) + zeta(1,3) + 2*zeta(2,3) +
& zeta(2,4) + 2*zeta(3,3) + 3*zeta(3,4) + zeta(4,4))*
- & Dval(dd00223,Di1))
- E(ee1344) = dabbr89*eta(1) -
- & eta(3)*Dval(dd1233,Di3) +
+ & D2345(DD00223))
+ E(EE1344) = dabbr89*eta(1) -
+ & eta(3)*D1245(DD1233) +
& 2*(dabbr91*(zeta(1,3) + zeta(2,3) + zeta(3,3) +
& zeta(3,4)) +
& 2*dabbr90*(zeta(1,4) + zeta(2,4) + zeta(3,4) +
- & zeta(4,4)) + 2*zeta(2,4)*Dval(dd00123,Di3) +
- & zeta(2,3)*Dval(dd00133,Di3) +
- & zeta(3,3)*Dval(dd00133,Di4) +
- & zeta(1,1)*Dval(dd00233,Di2) +
- & zeta(1,2)*Dval(dd00233,Di3) +
+ & zeta(4,4)) + 2*zeta(2,4)*D1245(DD00123) +
+ & zeta(2,3)*D1245(DD00133) +
+ & zeta(3,3)*D1235(DD00133) +
+ & zeta(1,1)*D1345(DD00233) +
+ & zeta(1,2)*D1245(DD00233) +
& (-zeta(1,1) - zeta(1,2) + zeta(1,4) + zeta(2,3) +
& 2*zeta(2,4) + zeta(3,3) + 3*zeta(3,4) + 2*zeta(4,4))
- & *Dval(dd00233,Di1))
- E(ee1444) = dabbr92*eta(1) -
- & eta(3)*Dval(dd1333,Di3) -
- & eta(4)*Dval(dd1333,Di4) +
+ & *D2345(DD00233))
+ E(EE1444) = dabbr92*eta(1) -
+ & eta(3)*D1245(DD1333) -
+ & eta(4)*D1235(DD1333) +
& 2*(3*dabbr52*(zeta(1,4) + zeta(2,4) + zeta(3,4) +
- & zeta(4,4)) + 3*zeta(2,4)*Dval(dd00133,Di3) +
- & 3*zeta(3,4)*Dval(dd00133,Di4) +
- & zeta(1,1)*Dval(dd00333,Di2) +
- & zeta(1,2)*Dval(dd00333,Di3) +
- & zeta(1,3)*Dval(dd00333,Di4) -
+ & zeta(4,4)) + 3*zeta(2,4)*D1245(DD00133) +
+ & 3*zeta(3,4)*D1235(DD00133) +
+ & zeta(1,1)*D1345(DD00333) +
+ & zeta(1,2)*D1245(DD00333) +
+ & zeta(1,3)*D1235(DD00333) -
& (zeta(1,1) + zeta(1,2) + zeta(1,3) - 2*zeta(1,4) -
& 3*(zeta(2,4) + zeta(3,4) + zeta(4,4)))*
- & Dval(dd00333,Di1))
- E(ee2222) = -(eta(2)*Dval(dd1111,Di2)) -
- & eta(4)*Dval(dd2222,Di4) -
- & eta(5)*Dval(dd2222,Di5) -
- & eta(1)*Dval(dd1111,Di1) +
- & 8*zeta(1,2)*Dval(dd00111,Di2) +
- & 8*zeta(2,3)*Dval(dd00222,Di4) +
- & 8*zeta(2,4)*Dval(dd00222,Di5) -
+ & D2345(DD00333))
+ E(EE2222) = -(eta(2)*D1345(DD1111)) -
+ & eta(4)*D1235(DD2222) -
+ & eta(5)*D1234(DD2222) -
+ & eta(1)*D2345(DD1111) +
+ & 8*zeta(1,2)*D1345(DD00111) +
+ & 8*zeta(2,3)*D1235(DD00222) +
+ & 8*zeta(2,4)*D1234(DD00222) -
& 8*(zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & Dval(dd00111,Di1)
- E(ee2223) = -(eta(2)*Dval(dd1112,Di2)) -
- & eta(5)*Dval(dd2223,Di5) -
- & eta(1)*Dval(dd1112,Di1) +
- & 2*zeta(1,3)*Dval(dd00111,Di2) +
- & 6*zeta(1,2)*Dval(dd00112,Di2) +
- & 2*zeta(3,3)*Dval(dd00222,Di4) +
- & 2*zeta(3,4)*Dval(dd00222,Di5) +
- & 6*zeta(2,4)*Dval(dd00223,Di5) -
+ & D2345(DD00111)
+ E(EE2223) = -(eta(2)*D1345(DD1112)) -
+ & eta(5)*D1234(DD2223) -
+ & eta(1)*D2345(DD1112) +
+ & 2*zeta(1,3)*D1345(DD00111) +
+ & 6*zeta(1,2)*D1345(DD00112) +
+ & 2*zeta(3,3)*D1235(DD00222) +
+ & 2*zeta(3,4)*D1234(DD00222) +
+ & 6*zeta(2,4)*D1234(DD00223) -
& 2*(zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & Dval(dd00111,Di1) -
+ & D2345(DD00111) -
& 6*(zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & Dval(dd00112,Di1)
- E(ee2224) = -(eta(2)*Dval(dd1113,Di2)) -
- & eta(4)*Dval(dd2223,Di4) -
- & eta(1)*Dval(dd1113,Di1) +
- & 2*zeta(1,4)*Dval(dd00111,Di2) +
- & 6*zeta(1,2)*Dval(dd00113,Di2) +
- & 2*zeta(3,4)*Dval(dd00222,Di4) +
- & 2*zeta(4,4)*Dval(dd00222,Di5) +
- & 6*zeta(2,3)*Dval(dd00223,Di4) -
+ & D2345(DD00112)
+ E(EE2224) = -(eta(2)*D1345(DD1113)) -
+ & eta(4)*D1235(DD2223) -
+ & eta(1)*D2345(DD1113) +
+ & 2*zeta(1,4)*D1345(DD00111) +
+ & 6*zeta(1,2)*D1345(DD00113) +
+ & 2*zeta(3,4)*D1235(DD00222) +
+ & 2*zeta(4,4)*D1234(DD00222) +
+ & 6*zeta(2,3)*D1235(DD00223) -
& 2*(zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd00111,Di1) -
+ & D2345(DD00111) -
& 6*(zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & Dval(dd00113,Di1)
- E(ee2233) = -(eta(2)*Dval(dd1122,Di2)) -
- & eta(5)*Dval(dd2233,Di5) -
- & eta(1)*Dval(dd1122,Di1) +
- & 4*(zeta(1,3)*Dval(dd00112,Di2) +
- & zeta(1,2)*Dval(dd00122,Di2) +
- & zeta(3,4)*Dval(dd00223,Di5) +
- & zeta(2,4)*Dval(dd00233,Di5) -
+ & D2345(DD00113)
+ E(EE2233) = -(eta(2)*D1345(DD1122)) -
+ & eta(5)*D1234(DD2233) -
+ & eta(1)*D2345(DD1122) +
+ & 4*(zeta(1,3)*D1345(DD00112) +
+ & zeta(1,2)*D1345(DD00122) +
+ & zeta(3,4)*D1234(DD00223) +
+ & zeta(2,4)*D1234(DD00233) -
& (zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & Dval(dd00112,Di1) -
+ & D2345(DD00112) -
& (zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & Dval(dd00122,Di1))
- E(ee2234) = -(eta(2)*Dval(dd1123,Di2)) -
- & eta(1)*Dval(dd1123,Di1) +
- & 2*(zeta(1,4)*Dval(dd00112,Di2) +
- & zeta(1,3)*Dval(dd00113,Di2) +
- & 2*zeta(1,2)*Dval(dd00123,Di2) +
- & zeta(3,3)*Dval(dd00223,Di4) +
- & zeta(4,4)*Dval(dd00223,Di5) -
+ & D2345(DD00122))
+ E(EE2234) = -(eta(2)*D1345(DD1123)) -
+ & eta(1)*D2345(DD1123) +
+ & 2*(zeta(1,4)*D1345(DD00112) +
+ & zeta(1,3)*D1345(DD00113) +
+ & 2*zeta(1,2)*D1345(DD00123) +
+ & zeta(3,3)*D1235(DD00223) +
+ & zeta(4,4)*D1234(DD00223) -
& (zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd00112,Di1) -
+ & D2345(DD00112) -
& (zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & Dval(dd00113,Di1) -
+ & D2345(DD00113) -
& 2*(zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & Dval(dd00123,Di1))
- E(ee2244) = -(eta(2)*Dval(dd1133,Di2)) -
- & eta(4)*Dval(dd2233,Di4) -
- & eta(1)*Dval(dd1133,Di1) +
- & 4*(zeta(1,4)*Dval(dd00113,Di2) +
- & zeta(1,2)*Dval(dd00133,Di2) +
- & zeta(3,4)*Dval(dd00223,Di4) +
- & zeta(2,3)*Dval(dd00233,Di4) -
+ & D2345(DD00123))
+ E(EE2244) = -(eta(2)*D1345(DD1133)) -
+ & eta(4)*D1235(DD2233) -
+ & eta(1)*D2345(DD1133) +
+ & 4*(zeta(1,4)*D1345(DD00113) +
+ & zeta(1,2)*D1345(DD00133) +
+ & zeta(3,4)*D1235(DD00223) +
+ & zeta(2,3)*D1235(DD00233) -
& (zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd00113,Di1) -
+ & D2345(DD00113) -
& (zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & Dval(dd00133,Di1))
- E(ee2333) = -(eta(2)*Dval(dd1222,Di2)) -
- & eta(5)*Dval(dd2333,Di5) -
- & eta(1)*Dval(dd1222,Di1) +
- & 6*zeta(1,3)*Dval(dd00122,Di2) +
- & 2*zeta(1,2)*Dval(dd00222,Di2) +
- & 2*zeta(2,2)*Dval(dd00222,Di3) +
- & 6*zeta(3,4)*Dval(dd00233,Di5) +
- & 2*zeta(2,4)*Dval(dd00333,Di5) -
+ & D2345(DD00133))
+ E(EE2333) = -(eta(2)*D1345(DD1222)) -
+ & eta(5)*D1234(DD2333) -
+ & eta(1)*D2345(DD1222) +
+ & 6*zeta(1,3)*D1345(DD00122) +
+ & 2*zeta(1,2)*D1345(DD00222) +
+ & 2*zeta(2,2)*D1245(DD00222) +
+ & 6*zeta(3,4)*D1234(DD00233) +
+ & 2*zeta(2,4)*D1234(DD00333) -
& 6*(zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & Dval(dd00122,Di1) -
+ & D2345(DD00122) -
& 2*(zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & Dval(dd00222,Di1)
- E(ee2334) = -(eta(2)*Dval(dd1223,Di2)) -
- & eta(1)*Dval(dd1223,Di1) +
- & 2*(zeta(1,4)*Dval(dd00122,Di2) +
- & 2*zeta(1,3)*Dval(dd00123,Di2) +
- & zeta(1,2)*Dval(dd00223,Di2) +
- & zeta(2,2)*Dval(dd00223,Di3) +
- & zeta(4,4)*Dval(dd00233,Di5) -
+ & D2345(DD00222)
+ E(EE2334) = -(eta(2)*D1345(DD1223)) -
+ & eta(1)*D2345(DD1223) +
+ & 2*(zeta(1,4)*D1345(DD00122) +
+ & 2*zeta(1,3)*D1345(DD00123) +
+ & zeta(1,2)*D1345(DD00223) +
+ & zeta(2,2)*D1245(DD00223) +
+ & zeta(4,4)*D1234(DD00233) -
& (zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd00122,Di1) -
+ & D2345(DD00122) -
& 2*(zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & Dval(dd00123,Di1) -
+ & D2345(DD00123) -
& (zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & Dval(dd00223,Di1))
- E(ee2344) = -(eta(2)*Dval(dd1233,Di2)) -
- & eta(1)*Dval(dd1233,Di1) +
- & 2*(2*zeta(1,4)*Dval(dd00123,Di2) +
- & zeta(1,3)*Dval(dd00133,Di2) +
- & zeta(1,2)*Dval(dd00233,Di2) +
- & zeta(2,2)*Dval(dd00233,Di3) +
- & zeta(3,3)*Dval(dd00233,Di4) -
+ & D2345(DD00223))
+ E(EE2344) = -(eta(2)*D1345(DD1233)) -
+ & eta(1)*D2345(DD1233) +
+ & 2*(2*zeta(1,4)*D1345(DD00123) +
+ & zeta(1,3)*D1345(DD00133) +
+ & zeta(1,2)*D1345(DD00233) +
+ & zeta(2,2)*D1245(DD00233) +
+ & zeta(3,3)*D1235(DD00233) -
& 2*(zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd00123,Di1) -
+ & D2345(DD00123) -
& (zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & Dval(dd00133,Di1) -
+ & D2345(DD00133) -
& (zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & Dval(dd00233,Di1))
- E(ee2444) = -(eta(2)*Dval(dd1333,Di2)) -
- & eta(4)*Dval(dd2333,Di4) -
- & eta(1)*Dval(dd1333,Di1) +
- & 6*zeta(1,4)*Dval(dd00133,Di2) +
- & 6*zeta(3,4)*Dval(dd00233,Di4) +
- & 2*zeta(1,2)*Dval(dd00333,Di2) +
- & 2*zeta(2,2)*Dval(dd00333,Di3) +
- & 2*zeta(2,3)*Dval(dd00333,Di4) -
+ & D2345(DD00233))
+ E(EE2444) = -(eta(2)*D1345(DD1333)) -
+ & eta(4)*D1235(DD2333) -
+ & eta(1)*D2345(DD1333) +
+ & 6*zeta(1,4)*D1345(DD00133) +
+ & 6*zeta(3,4)*D1235(DD00233) +
+ & 2*zeta(1,2)*D1345(DD00333) +
+ & 2*zeta(2,2)*D1245(DD00333) +
+ & 2*zeta(2,3)*D1235(DD00333) -
& 6*(zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd00133,Di1) -
+ & D2345(DD00133) -
& 2*(zeta(1,2) + zeta(2,2) + zeta(2,3) + zeta(2,4))*
- & Dval(dd00333,Di1)
- E(ee3333) = -(eta(2)*Dval(dd2222,Di2)) -
- & eta(3)*Dval(dd2222,Di3) -
- & eta(5)*Dval(dd3333,Di5) -
- & eta(1)*Dval(dd2222,Di1) +
- & 8*zeta(1,3)*Dval(dd00222,Di2) +
- & 8*zeta(2,3)*Dval(dd00222,Di3) +
- & 8*zeta(3,4)*Dval(dd00333,Di5) -
+ & D2345(DD00333)
+ E(EE3333) = -(eta(2)*D1345(DD2222)) -
+ & eta(3)*D1245(DD2222) -
+ & eta(5)*D1234(DD3333) -
+ & eta(1)*D2345(DD2222) +
+ & 8*zeta(1,3)*D1345(DD00222) +
+ & 8*zeta(2,3)*D1245(DD00222) +
+ & 8*zeta(3,4)*D1234(DD00333) -
& 8*(zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & Dval(dd00222,Di1)
- E(ee3334) = -(eta(2)*Dval(dd2223,Di2)) -
- & eta(3)*Dval(dd2223,Di3) -
- & eta(1)*Dval(dd2223,Di1) +
- & 2*zeta(1,4)*Dval(dd00222,Di2) +
- & 2*zeta(2,4)*Dval(dd00222,Di3) +
- & 6*zeta(1,3)*Dval(dd00223,Di2) +
- & 6*zeta(2,3)*Dval(dd00223,Di3) +
- & 2*zeta(4,4)*Dval(dd00333,Di5) -
+ & D2345(DD00222)
+ E(EE3334) = -(eta(2)*D1345(DD2223)) -
+ & eta(3)*D1245(DD2223) -
+ & eta(1)*D2345(DD2223) +
+ & 2*zeta(1,4)*D1345(DD00222) +
+ & 2*zeta(2,4)*D1245(DD00222) +
+ & 6*zeta(1,3)*D1345(DD00223) +
+ & 6*zeta(2,3)*D1245(DD00223) +
+ & 2*zeta(4,4)*D1234(DD00333) -
& 2*(zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd00222,Di1) -
+ & D2345(DD00222) -
& 6*(zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & Dval(dd00223,Di1)
- E(ee3344) = -(eta(2)*Dval(dd2233,Di2)) -
- & eta(3)*Dval(dd2233,Di3) -
- & eta(1)*Dval(dd2233,Di1) +
- & 4*(zeta(1,4)*Dval(dd00223,Di2) +
- & zeta(2,4)*Dval(dd00223,Di3) +
- & zeta(1,3)*Dval(dd00233,Di2) +
- & zeta(2,3)*Dval(dd00233,Di3) -
+ & D2345(DD00223)
+ E(EE3344) = -(eta(2)*D1345(DD2233)) -
+ & eta(3)*D1245(DD2233) -
+ & eta(1)*D2345(DD2233) +
+ & 4*(zeta(1,4)*D1345(DD00223) +
+ & zeta(2,4)*D1245(DD00223) +
+ & zeta(1,3)*D1345(DD00233) +
+ & zeta(2,3)*D1245(DD00233) -
& (zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd00223,Di1) -
+ & D2345(DD00223) -
& (zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & Dval(dd00233,Di1))
- E(ee3444) = -(eta(2)*Dval(dd2333,Di2)) -
- & eta(3)*Dval(dd2333,Di3) -
- & eta(1)*Dval(dd2333,Di1) +
- & 6*zeta(1,4)*Dval(dd00233,Di2) +
- & 6*zeta(2,4)*Dval(dd00233,Di3) +
- & 2*zeta(1,3)*Dval(dd00333,Di2) +
- & 2*zeta(2,3)*Dval(dd00333,Di3) +
- & 2*zeta(3,3)*Dval(dd00333,Di4) -
+ & D2345(DD00233))
+ E(EE3444) = -(eta(2)*D1345(DD2333)) -
+ & eta(3)*D1245(DD2333) -
+ & eta(1)*D2345(DD2333) +
+ & 6*zeta(1,4)*D1345(DD00233) +
+ & 6*zeta(2,4)*D1245(DD00233) +
+ & 2*zeta(1,3)*D1345(DD00333) +
+ & 2*zeta(2,3)*D1245(DD00333) +
+ & 2*zeta(3,3)*D1235(DD00333) -
& 6*(zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd00233,Di1) -
+ & D2345(DD00233) -
& 2*(zeta(1,3) + zeta(2,3) + zeta(3,3) + zeta(3,4))*
- & Dval(dd00333,Di1)
- E(ee4444) = -(eta(2)*Dval(dd3333,Di2)) -
- & eta(3)*Dval(dd3333,Di3) -
- & eta(4)*Dval(dd3333,Di4) -
- & eta(1)*Dval(dd3333,Di1) +
- & 8*zeta(1,4)*Dval(dd00333,Di2) +
- & 8*zeta(2,4)*Dval(dd00333,Di3) +
- & 8*zeta(3,4)*Dval(dd00333,Di4) -
+ & D2345(DD00333)
+ E(EE4444) = -(eta(2)*D1345(DD3333)) -
+ & eta(3)*D1245(DD3333) -
+ & eta(4)*D1235(DD3333) -
+ & eta(1)*D2345(DD3333) +
+ & 8*zeta(1,4)*D1345(DD00333) +
+ & 8*zeta(2,4)*D1245(DD00333) +
+ & 8*zeta(3,4)*D1235(DD00333) -
& 8*(zeta(1,4) + zeta(2,4) + zeta(3,4) + zeta(4,4))*
- & Dval(dd00333,Di1)
+ & D2345(DD00333)
if( dump ) call XDumpCoeff(5, E)
end
diff --git a/Looptools/E/Ecoeffb.F b/Looptools/E/Ecoeffb.F
--- a/Looptools/E/Ecoeffb.F
+++ b/Looptools/E/Ecoeffb.F
@@ -1,515 +1,508 @@
* Ecoeffb.F
* the five-point tensor coefficients via Passarino-Veltman decomposition
* this file is part of LoopTools
* written by M. Rauch
-* last modified 29 Sep 10 th
+* last modified 20 Jan 16 th
+#include "externals.h"
+#include "types.h"
+
+#define npoint 5
#include "defs.h"
- subroutine XEcoeffb(para, E, ldpara)
+ subroutine XEcoeffb(E, para, D2345, D1345, D1245, D1235, D1234)
implicit none
- integer ldpara
- DVAR para(ldpara,Pee)
- double complex E(Nee)
+ ComplexType E(*)
+ ComplexType D2345(*), D1345(*), D1245(*), D1235(*), D1234(*)
+ DVAR para(1,*)
#include "lt.h"
- integer XDget
- double complex XE0
- external XDget, XE0
+ memindex XDget
+ external XDget
DVAR p1, p2, p3, p4, p5
DVAR p1p2, p2p3, p3p4, p4p5, p5p1
DVAR m1, m2, m3, m4, m5
DVAR f1, f2, f3, f4
- double complex di, d0sum
- double complex d1i, d1sum, d2i, d2sum, dii
- double complex d1ii, d2ii, diii
- double complex d00sum, d22sum, d33sum
- double complex in(4)
- integer Di1, Di2, Di3, Di4, Di5
+ ComplexType di, d0sum
+ ComplexType d1i, d1sum, d2i, d2sum, dii
+ ComplexType d1ii, d2ii, diii
+ ComplexType d00sum, d22sum, d33sum
+ ComplexType in(4)
logical dump
QVAR G(4,4), Ginv(4,4)
common /XInvGramE/ Ginv
#ifdef SOLVE_EIGEN
#define SOLVE_SETUP XInverse(4, G,4, Ginv,4)
-#define SOLVE(b) XSolve(4, G,4, Ginv,4, b)
+#define SOLVER(b) XSolve(4, G,4, Ginv,4, b)
#else
integer perm(4)
#define IN(i) in(perm(i))
#define SOLVE_SETUP XInverse(4, G,4, Ginv,4, perm)
-#define SOLVE(b) XSolve(4, G,4, b)
+#define SOLVER(b) XSolve(4, G,4, b)
#endif
- p1 = para(1,1)
- p2 = para(1,2)
- p3 = para(1,3)
- p4 = para(1,4)
- p5 = para(1,5)
- p1p2 = para(1,6)
- p2p3 = para(1,7)
- p3p4 = para(1,8)
- p4p5 = para(1,9)
- p5p1 = para(1,10)
- m1 = para(1,11)
- m2 = para(1,12)
- m3 = para(1,13)
- m4 = para(1,14)
- m5 = para(1,15)
-
-#ifdef COMPLEXPARA
- if( abs(DIMAG(para(1,1))) +
- & abs(DIMAG(para(1,2))) +
- & abs(DIMAG(para(1,3))) +
- & abs(DIMAG(para(1,4))) +
- & abs(DIMAG(para(1,5))) +
- & abs(DIMAG(para(1,6))) +
- & abs(DIMAG(para(1,7))) +
- & abs(DIMAG(para(1,8))) +
- & abs(DIMAG(para(1,9))) +
- & abs(DIMAG(para(1,10))) .gt. 0 )
- & print *, "Warning: complex momenta not implemented"
- if( abs(DIMAG(para(1,11))) +
- & abs(DIMAG(para(1,12))) +
- & abs(DIMAG(para(1,13))) +
- & abs(DIMAG(para(1,14))) +
- & abs(DIMAG(para(1,15))) .eq. 0 ) then
- call Ecoeffb(para, E, 2)
- return
- endif
-#endif
-
- Di1 = XDget(p2, p3, p4, p5p1, p2p3, p3p4, m2, m3, m4, m5)
- Di2 = XDget(p1p2, p3, p4, p5, p4p5, p3p4, m1, m3, m4, m5)
- Di3 = XDget(p1, p2p3, p4, p5, p4p5, p5p1, m1, m2, m4, m5)
- Di4 = XDget(p1, p2, p3p4, p5, p1p2, p5p1, m1, m2, m3, m5)
- Di5 = XDget(p1, p2, p3, p4p5, p1p2, p2p3, m1, m2, m3, m4)
-
serial = serial + 1
dump = ibits(debugkey, DebugE, 1) .ne. 0 .and.
& serial .ge. debugfrom .and. serial .le. debugto
- if( dump ) call XDumpPara(5, para, ldpara)
+ if( dump ) call XDumpPara(5, para)
- f1 = QPREC(m2) - QPREC(m1) - QPREC(p1)
- f2 = QPREC(m3) - QPREC(m1) - QPREC(p1p2)
- f3 = QPREC(m4) - QPREC(m1) - QPREC(p4p5)
- f4 = QPREC(m5) - QPREC(m1) - QPREC(p5)
+ m1 = M(1)
+ m2 = M(2)
+ m3 = M(3)
+ m4 = M(4)
+ m5 = M(5)
+ p1 = P(1)
+ p2 = P(2)
+ p3 = P(3)
+ p4 = P(4)
+ p5 = P(5)
+ p1p2 = P(6)
+ p2p3 = P(7)
+ p3p4 = P(8)
+ p4p5 = P(9)
+ p5p1 = P(10)
+
+ f1 = m2
+ f1 = f1 - m1
+ f1 = f1 - p1
+ f2 = m3
+ f2 = f2 - m1
+ f2 = f2 - p1p2
+ f3 = m4
+ f3 = f3 - m1
+ f3 = f3 - p4p5
+ f4 = m5
+ f4 = f4 - m1
+ f4 = f4 - p5
* build up G and calculate matrix decomposition and inverse Y
- G(1,1) = 2*QPREC(p1)
- G(2,2) = 2*QPREC(p1p2)
- G(3,3) = 2*QPREC(p4p5)
- G(4,4) = 2*QPREC(p5)
- G(1,2) = QPREC(p1) + QPREC(p1p2) - QPREC(p2)
+ G(1,1) = 2*p1
+ G(2,2) = 2*p1p2
+ G(3,3) = 2*p4p5
+ G(4,4) = 2*p5
+ G(1,2) = p1
+ G(1,2) = G(1,2) + p1p2
+ G(1,2) = G(1,2) - p2
G(2,1) = G(1,2)
- G(1,3) = QPREC(p1) - QPREC(p2p3) + QPREC(p4p5)
+ G(1,3) = p1
+ G(1,3) = G(1,3) - p2p3
+ G(1,3) = G(1,3) + p4p5
G(3,1) = G(1,3)
- G(1,4) = QPREC(p1) - QPREC(p5p1) + QPREC(p5)
+ G(1,4) = p1
+ G(1,4) = G(1,4) - p5p1
+ G(1,4) = G(1,4) + p5
G(4,1) = G(1,4)
- G(2,3) = QPREC(p1p2) - QPREC(p3) + QPREC(p4p5)
+ G(2,3) = p1p2
+ G(2,3) = G(2,3) - p3
+ G(2,3) = G(2,3) + p4p5
G(3,2) = G(2,3)
- G(2,4) = QPREC(p1p2) - QPREC(p3p4) + QPREC(p5)
+ G(2,4) = p1p2
+ G(2,4) = G(2,4) - p3p4
+ G(2,4) = G(2,4) + p5
G(4,2) = G(2,4)
- G(3,4) = QPREC(p5) + QPREC(p4p5) - QPREC(p4)
+ G(3,4) = p5
+ G(3,4) = G(3,4) + p4p5
+ G(3,4) = G(3,4) - p4
G(4,3) = G(3,4)
call SOLVE_SETUP
- di = Dval(dd1,Di1) + Dval(dd2,Di1) + Dval(dd3,Di1)
- d0sum = Dval(dd0,Di1) + di
+ di = D2345(dd1) + D2345(dd2) + D2345(dd3)
+ d0sum = D2345(dd0) + di
- d1i = Dval(dd11,Di1) + Dval(dd12,Di1) + Dval(dd13,Di1)
- d1sum = Dval(dd1,Di1) + d1i
- d2i = Dval(dd12,Di1) + Dval(dd22,Di1) + Dval(dd23,Di1)
- d2sum = Dval(dd2,Di1) + d2i
- dii = d1i + d2i +
- & Dval(dd13,Di1) + Dval(dd23,Di1) + Dval(dd33,Di1)
+ d1i = D2345(dd11) + D2345(dd12) + D2345(dd13)
+ d1sum = D2345(dd1) + d1i
+ d2i = D2345(dd12) + D2345(dd22) + D2345(dd23)
+ d2sum = D2345(dd2) + d2i
+ dii = d1i + d2i + D2345(dd13) + D2345(dd23) + D2345(dd33)
- d1ii = Dval(dd111,Di1) + Dval(dd122,Di1) +
- & Dval(dd133,Di1) + 2*(Dval(dd112,Di1) +
- & Dval(dd113,Di1) + Dval(dd123,Di1))
- d2ii = Dval(dd112,Di1) + Dval(dd222,Di1) +
- & Dval(dd233,Di1) + 2*(Dval(dd122,Di1) +
- & Dval(dd123,Di1) + Dval(dd223,Di1))
+ d1ii = D2345(dd111) + D2345(dd122) +
+ & D2345(dd133) + 2*(D2345(dd112) +
+ & D2345(dd113) + D2345(dd123))
+ d2ii = D2345(dd112) + D2345(dd222) +
+ & D2345(dd233) + 2*(D2345(dd122) +
+ & D2345(dd123) + D2345(dd223))
diii = d1ii + d2ii +
- & Dval(dd113,Di1) + Dval(dd223,Di1) +
- & Dval(dd333,Di1) + 2*(Dval(dd123,Di1) +
- & Dval(dd133,Di1) + Dval(dd233,Di1))
+ & D2345(dd113) + D2345(dd223) +
+ & D2345(dd333) + 2*(D2345(dd123) +
+ & D2345(dd133) + D2345(dd233))
- d00sum = Dval(dd00,Di1) +
- & Dval(dd001,Di1) + Dval(dd002,Di1) + Dval(dd003,Di1)
- d22sum = Dval(dd22,Di1) +
- & Dval(dd122,Di1) + Dval(dd222,Di1) + Dval(dd223,Di1)
- d33sum = Dval(dd33,Di1) +
- & Dval(dd133,Di1) + Dval(dd233,Di1) + Dval(dd333,Di1)
+ d00sum = D2345(dd00) +
+ & D2345(dd001) + D2345(dd002) + D2345(dd003)
+ d22sum = D2345(dd22) +
+ & D2345(dd122) + D2345(dd222) + D2345(dd223)
+ d33sum = D2345(dd33) +
+ & D2345(dd133) + D2345(dd233) + D2345(dd333)
- E(ee0) = XE0(p1, p2, p3, p4, p5,
- & p1p2, p2p3, p3p4, p4p5, p5p1, m1, m2, m3, m4, m5)
+ call XE0func(E(ee0), para,
+ & D2345, D1345, D1245, D1235, D1234, 1)
- IN(1) = f1*E(ee0) - Dval(dd0,Di1) + Dval(dd0,Di2)
- IN(2) = f2*E(ee0) - Dval(dd0,Di1) + Dval(dd0,Di3)
- IN(3) = f3*E(ee0) - Dval(dd0,Di1) + Dval(dd0,Di4)
- IN(4) = f4*E(ee0) - Dval(dd0,Di1) + Dval(dd0,Di5)
- call SOLVE(in)
+ IN(1) = f1*E(ee0) - D2345(dd0) + D1345(dd0)
+ IN(2) = f2*E(ee0) - D2345(dd0) + D1245(dd0)
+ IN(3) = f3*E(ee0) - D2345(dd0) + D1235(dd0)
+ IN(4) = f4*E(ee0) - D2345(dd0) + D1234(dd0)
+ call SOLVER(in)
E(ee1) = in(1)
E(ee2) = in(2)
E(ee3) = in(3)
E(ee4) = in(4)
E(ee00) = 0
IN(1) = f1*E(ee1) + d0sum
- IN(2) = f2*E(ee1) + d0sum + Dval(dd1,Di3)
- IN(3) = f3*E(ee1) + d0sum + Dval(dd1,Di4)
- IN(4) = f4*E(ee1) + d0sum + Dval(dd1,Di5)
- call SOLVE(in)
+ IN(2) = f2*E(ee1) + d0sum + D1245(dd1)
+ IN(3) = f3*E(ee1) + d0sum + D1235(dd1)
+ IN(4) = f4*E(ee1) + d0sum + D1234(dd1)
+ call SOLVER(in)
E(ee11) = in(1)
E(ee12) = in(2)
E(ee13) = in(3)
E(ee14) = in(4)
- IN(1) = f1*E(ee2) - Dval(dd1,Di1) + Dval(dd1,Di2)
- IN(2) = f2*E(ee2) - Dval(dd1,Di1)
- IN(3) = f3*E(ee2) - Dval(dd1,Di1) + Dval(dd2,Di4)
- IN(4) = f4*E(ee2) - Dval(dd1,Di1) + Dval(dd2,Di5)
- call SOLVE(in)
+ IN(1) = f1*E(ee2) - D2345(dd1) + D1345(dd1)
+ IN(2) = f2*E(ee2) - D2345(dd1)
+ IN(3) = f3*E(ee2) - D2345(dd1) + D1235(dd2)
+ IN(4) = f4*E(ee2) - D2345(dd1) + D1234(dd2)
+ call SOLVER(in)
E(ee12) = .5D0*(E(ee12) + in(1))
E(ee22) = in(2)
E(ee23) = in(3)
E(ee24) = in(4)
- IN(1) = f1*E(ee3) - Dval(dd2,Di1) + Dval(dd2,Di2)
- IN(2) = f2*E(ee3) - Dval(dd2,Di1) + Dval(dd2,Di3)
- IN(3) = f3*E(ee3) - Dval(dd2,Di1)
- IN(4) = f4*E(ee3) - Dval(dd2,Di1) + Dval(dd3,Di5)
- call SOLVE(in)
+ IN(1) = f1*E(ee3) - D2345(dd2) + D1345(dd2)
+ IN(2) = f2*E(ee3) - D2345(dd2) + D1245(dd2)
+ IN(3) = f3*E(ee3) - D2345(dd2)
+ IN(4) = f4*E(ee3) - D2345(dd2) + D1234(dd3)
+ call SOLVER(in)
E(ee13) = .5D0*(E(ee13) + in(1))
E(ee23) = .5D0*(E(ee23) + in(2))
E(ee33) = in(3)
E(ee34) = in(4)
- IN(1) = f1*E(ee4) - Dval(dd3,Di1) + Dval(dd3,Di2)
- IN(2) = f2*E(ee4) - Dval(dd3,Di1) + Dval(dd3,Di3)
- IN(3) = f3*E(ee4) - Dval(dd3,Di1) + Dval(dd3,Di4)
- IN(4) = f4*E(ee4) - Dval(dd3,Di1)
- call SOLVE(in)
+ IN(1) = f1*E(ee4) - D2345(dd3) + D1345(dd3)
+ IN(2) = f2*E(ee4) - D2345(dd3) + D1245(dd3)
+ IN(3) = f3*E(ee4) - D2345(dd3) + D1235(dd3)
+ IN(4) = f4*E(ee4) - D2345(dd3)
+ call SOLVER(in)
E(ee14) = .5D0*(E(ee14) + in(1))
E(ee24) = .5D0*(E(ee24) + in(2))
E(ee34) = .5D0*(E(ee34) + in(3))
E(ee44) = in(4)
E(ee001) = 0
E(ee002) = 0
E(ee003) = 0
E(ee004) = 0
d0sum = d0sum + di + dii
IN(1) = f1*E(ee11) - d0sum -
- & 2*Ginv(1,1)*(Dval(dd00,Di1) - Dval(dd00,Di2))
- IN(2) = f2*E(ee11) - d0sum + Dval(dd11,Di3) -
- & 2*Ginv(1,1)*(Dval(dd00,Di1) - Dval(dd00,Di3))
- IN(3) = f3*E(ee11) - d0sum + Dval(dd11,Di4) -
- & 2*Ginv(1,1)*(Dval(dd00,Di1) - Dval(dd00,Di4))
- IN(4) = f4*E(ee11) - d0sum + Dval(dd11,Di5) -
- & 2*Ginv(1,1)*(Dval(dd00,Di1) - Dval(dd00,Di5))
- call SOLVE(in)
+ & 2*Ginv(1,1)*(D2345(dd00) - D1345(dd00))
+ IN(2) = f2*E(ee11) - d0sum + D1245(dd11) -
+ & 2*Ginv(1,1)*(D2345(dd00) - D1245(dd00))
+ IN(3) = f3*E(ee11) - d0sum + D1235(dd11) -
+ & 2*Ginv(1,1)*(D2345(dd00) - D1235(dd00))
+ IN(4) = f4*E(ee11) - d0sum + D1234(dd11) -
+ & 2*Ginv(1,1)*(D2345(dd00) - D1234(dd00))
+ call SOLVER(in)
E(ee111) = in(1)
E(ee112) = in(2)
E(ee113) = in(3)
E(ee114) = in(4)
- IN(1) = f1*E(ee22) - Dval(dd11,Di1) + Dval(dd11,Di2) -
- & 2*Ginv(2,2)*(Dval(dd00,Di1) - Dval(dd00,Di2))
- IN(2) = f2*E(ee22) - Dval(dd11,Di1) -
- & 2*Ginv(2,2)*(Dval(dd00,Di1) - Dval(dd00,Di3))
- IN(3) = f3*E(ee22) - Dval(dd11,Di1) + Dval(dd22,Di4) -
- & 2*Ginv(2,2)*(Dval(dd00,Di1) - Dval(dd00,Di4))
- IN(4) = f4*E(ee22) - Dval(dd11,Di1) + Dval(dd22,Di5) -
- & 2*Ginv(2,2)*(Dval(dd00,Di1) - Dval(dd00,Di5))
- call SOLVE(in)
+ IN(1) = f1*E(ee22) - D2345(dd11) + D1345(dd11) -
+ & 2*Ginv(2,2)*(D2345(dd00) - D1345(dd00))
+ IN(2) = f2*E(ee22) - D2345(dd11) -
+ & 2*Ginv(2,2)*(D2345(dd00) - D1245(dd00))
+ IN(3) = f3*E(ee22) - D2345(dd11) + D1235(dd22) -
+ & 2*Ginv(2,2)*(D2345(dd00) - D1235(dd00))
+ IN(4) = f4*E(ee22) - D2345(dd11) + D1234(dd22) -
+ & 2*Ginv(2,2)*(D2345(dd00) - D1234(dd00))
+ call SOLVER(in)
E(ee122) = in(1)
E(ee222) = in(2)
E(ee223) = in(3)
E(ee224) = in(4)
- IN(1) = f1*E(ee33) - Dval(dd22,Di1) + Dval(dd22,Di2) -
- & 2*Ginv(3,3)*(Dval(dd00,Di1) - Dval(dd00,Di2))
- IN(2) = f2*E(ee33) - Dval(dd22,Di1) + Dval(dd22,Di3) -
- & 2*Ginv(3,3)*(Dval(dd00,Di1) - Dval(dd00,Di3))
- IN(3) = f3*E(ee33) - Dval(dd22,Di1) -
- & 2*Ginv(3,3)*(Dval(dd00,Di1) - Dval(dd00,Di4))
- IN(4) = f4*E(ee33) - Dval(dd22,Di1) + Dval(dd33,Di5) -
- & 2*Ginv(3,3)*(Dval(dd00,Di1) - Dval(dd00,Di5))
- call SOLVE(in)
+ IN(1) = f1*E(ee33) - D2345(dd22) + D1345(dd22) -
+ & 2*Ginv(3,3)*(D2345(dd00) - D1345(dd00))
+ IN(2) = f2*E(ee33) - D2345(dd22) + D1245(dd22) -
+ & 2*Ginv(3,3)*(D2345(dd00) - D1245(dd00))
+ IN(3) = f3*E(ee33) - D2345(dd22) -
+ & 2*Ginv(3,3)*(D2345(dd00) - D1235(dd00))
+ IN(4) = f4*E(ee33) - D2345(dd22) + D1234(dd33) -
+ & 2*Ginv(3,3)*(D2345(dd00) - D1234(dd00))
+ call SOLVER(in)
E(ee133) = in(1)
E(ee233) = in(2)
E(ee333) = in(3)
E(ee334) = in(4)
- IN(1) = f1*E(ee44) - Dval(dd33,Di1) + Dval(dd33,Di2) -
- & 2*Ginv(4,4)*(Dval(dd00,Di1) - Dval(dd00,Di2))
- IN(2) = f2*E(ee44) - Dval(dd33,Di1) + Dval(dd33,Di3) -
- & 2*Ginv(4,4)*(Dval(dd00,Di1) - Dval(dd00,Di3))
- IN(3) = f3*E(ee44) - Dval(dd33,Di1) + Dval(dd33,Di4) -
- & 2*Ginv(4,4)*(Dval(dd00,Di1) - Dval(dd00,Di4))
- IN(4) = f4*E(ee44) - Dval(dd33,Di1) -
- & 2*Ginv(4,4)*(Dval(dd00,Di1) - Dval(dd00,Di5))
- call SOLVE(in)
+ IN(1) = f1*E(ee44) - D2345(dd33) + D1345(dd33) -
+ & 2*Ginv(4,4)*(D2345(dd00) - D1345(dd00))
+ IN(2) = f2*E(ee44) - D2345(dd33) + D1245(dd33) -
+ & 2*Ginv(4,4)*(D2345(dd00) - D1245(dd00))
+ IN(3) = f3*E(ee44) - D2345(dd33) + D1235(dd33) -
+ & 2*Ginv(4,4)*(D2345(dd00) - D1235(dd00))
+ IN(4) = f4*E(ee44) - D2345(dd33) -
+ & 2*Ginv(4,4)*(D2345(dd00) - D1234(dd00))
+ call SOLVER(in)
E(ee144) = in(1)
E(ee244) = in(2)
E(ee344) = in(3)
E(ee444) = in(4)
IN(1) = f1*E(ee12) + d1sum -
- & 2*Ginv(1,2)*(Dval(dd00,Di1) - Dval(dd00,Di2))
+ & 2*Ginv(1,2)*(D2345(dd00) - D1345(dd00))
IN(2) = f2*E(ee12) + d1sum -
- & 2*Ginv(1,2)*(Dval(dd00,Di1) - Dval(dd00,Di3))
- IN(3) = f3*E(ee12) + d1sum + Dval(dd12,Di4) -
- & 2*Ginv(1,2)*(Dval(dd00,Di1) - Dval(dd00,Di4))
- IN(4) = f4*E(ee12) + d1sum + Dval(dd12,Di5) -
- & 2*Ginv(1,2)*(Dval(dd00,Di1) - Dval(dd00,Di5))
- call SOLVE(in)
+ & 2*Ginv(1,2)*(D2345(dd00) - D1245(dd00))
+ IN(3) = f3*E(ee12) + d1sum + D1235(dd12) -
+ & 2*Ginv(1,2)*(D2345(dd00) - D1235(dd00))
+ IN(4) = f4*E(ee12) + d1sum + D1234(dd12) -
+ & 2*Ginv(1,2)*(D2345(dd00) - D1234(dd00))
+ call SOLVER(in)
E(ee112) = .5D0*(E(ee112) + in(1))
E(ee122) = .5D0*(E(ee122) + in(2))
E(ee123) = in(3)
E(ee124) = in(4)
- IN(1) = f1*E(ee34) - Dval(dd23,Di1) + Dval(dd23,Di2) -
- & 2*Ginv(3,4)*(Dval(dd00,Di1) - Dval(dd00,Di2))
- IN(2) = f2*E(ee34) - Dval(dd23,Di1) + Dval(dd23,Di3) -
- & 2*Ginv(3,4)*(Dval(dd00,Di1) - Dval(dd00,Di3))
- IN(3) = f3*E(ee34) - Dval(dd23,Di1) -
- & 2*Ginv(3,4)*(Dval(dd00,Di1) - Dval(dd00,Di4))
- IN(4) = f4*E(ee34) - Dval(dd23,Di1) -
- & 2*Ginv(3,4)*(Dval(dd00,Di1) - Dval(dd00,Di5))
- call SOLVE(in)
+ IN(1) = f1*E(ee34) - D2345(dd23) + D1345(dd23) -
+ & 2*Ginv(3,4)*(D2345(dd00) - D1345(dd00))
+ IN(2) = f2*E(ee34) - D2345(dd23) + D1245(dd23) -
+ & 2*Ginv(3,4)*(D2345(dd00) - D1245(dd00))
+ IN(3) = f3*E(ee34) - D2345(dd23) -
+ & 2*Ginv(3,4)*(D2345(dd00) - D1235(dd00))
+ IN(4) = f4*E(ee34) - D2345(dd23) -
+ & 2*Ginv(3,4)*(D2345(dd00) - D1234(dd00))
+ call SOLVER(in)
E(ee134) = in(1)
E(ee234) = in(2)
E(ee334) = .5D0*(E(ee334) + in(3))
E(ee344) = .5D0*(E(ee344) + in(4))
E(ee0000) = 0
E(ee0011) = 0
E(ee0012) = 0
E(ee0013) = 0
E(ee0014) = 0
E(ee0022) = 0
E(ee0023) = 0
E(ee0024) = 0
E(ee0033) = 0
E(ee0034) = 0
E(ee0044) = 0
d0sum = d0sum + di + 2*dii + diii
IN(1) = f1*E(ee111) + d0sum +
& 6*Ginv(1,1)*d00sum
- IN(2) = f2*E(ee111) + d0sum + Dval(dd111,Di3) +
- & 6*Ginv(1,1)*(d00sum + Dval(dd001,Di3))
- IN(3) = f3*E(ee111) + d0sum + Dval(dd111,Di4) +
- & 6*Ginv(1,1)*(d00sum + Dval(dd001,Di4))
- IN(4) = f4*E(ee111) + d0sum + Dval(dd111,Di5) +
- & 6*Ginv(1,1)*(d00sum + Dval(dd001,Di5))
- call SOLVE(in)
+ IN(2) = f2*E(ee111) + d0sum + D1245(dd111) +
+ & 6*Ginv(1,1)*(d00sum + D1245(dd001))
+ IN(3) = f3*E(ee111) + d0sum + D1235(dd111) +
+ & 6*Ginv(1,1)*(d00sum + D1235(dd001))
+ IN(4) = f4*E(ee111) + d0sum + D1234(dd111) +
+ & 6*Ginv(1,1)*(d00sum + D1234(dd001))
+ call SOLVER(in)
E(ee1111) = in(1)
E(ee1112) = in(2)
E(ee1113) = in(3)
E(ee1114) = in(4)
- IN(1) = f1*E(ee222) - Dval(dd111,Di1) + Dval(dd111,Di2) -
- & 6*Ginv(2,2)*(Dval(dd001,Di1) - Dval(dd001,Di2))
- IN(2) = f2*E(ee222) - Dval(dd111,Di1) -
- & 6*Ginv(2,2)*Dval(dd001,Di1)
- IN(3) = f3*E(ee222) - Dval(dd111,Di1) + Dval(dd222,Di4) -
- & 6*Ginv(2,2)*(Dval(dd001,Di1) - Dval(dd002,Di4))
- IN(4) = f4*E(ee222) - Dval(dd111,Di1) + Dval(dd222,Di5) -
- & 6*Ginv(2,2)*(Dval(dd001,Di1) - Dval(dd002,Di5))
- call SOLVE(in)
+ IN(1) = f1*E(ee222) - D2345(dd111) + D1345(dd111) -
+ & 6*Ginv(2,2)*(D2345(dd001) - D1345(dd001))
+ IN(2) = f2*E(ee222) - D2345(dd111) -
+ & 6*Ginv(2,2)*D2345(dd001)
+ IN(3) = f3*E(ee222) - D2345(dd111) + D1235(dd222) -
+ & 6*Ginv(2,2)*(D2345(dd001) - D1235(dd002))
+ IN(4) = f4*E(ee222) - D2345(dd111) + D1234(dd222) -
+ & 6*Ginv(2,2)*(D2345(dd001) - D1234(dd002))
+ call SOLVER(in)
E(ee1222) = in(1)
E(ee2222) = in(2)
E(ee2223) = in(3)
E(ee2224) = in(4)
- IN(1) = f1*E(ee333) - Dval(dd222,Di1) + Dval(dd222,Di2) -
- & 6*Ginv(3,3)*(Dval(dd002,Di1) - Dval(dd002,Di2))
- IN(2) = f2*E(ee333) - Dval(dd222,Di1) + Dval(dd222,Di3) -
- & 6*Ginv(3,3)*(Dval(dd002,Di1) - Dval(dd002,Di3))
- IN(3) = f3*E(ee333) - Dval(dd222,Di1) -
- & 6*Ginv(3,3)*Dval(dd002,Di1)
- IN(4) = f4*E(ee333) - Dval(dd222,Di1) + Dval(dd333,Di5) -
- & 6*Ginv(3,3)*(Dval(dd002,Di1) - Dval(dd003,Di5))
- call SOLVE(in)
+ IN(1) = f1*E(ee333) - D2345(dd222) + D1345(dd222) -
+ & 6*Ginv(3,3)*(D2345(dd002) - D1345(dd002))
+ IN(2) = f2*E(ee333) - D2345(dd222) + D1245(dd222) -
+ & 6*Ginv(3,3)*(D2345(dd002) - D1245(dd002))
+ IN(3) = f3*E(ee333) - D2345(dd222) -
+ & 6*Ginv(3,3)*D2345(dd002)
+ IN(4) = f4*E(ee333) - D2345(dd222) + D1234(dd333) -
+ & 6*Ginv(3,3)*(D2345(dd002) - D1234(dd003))
+ call SOLVER(in)
E(ee1333) = in(1)
E(ee2333) = in(2)
E(ee3333) = in(3)
E(ee3334) = in(4)
- IN(1) = f1*E(ee444) - Dval(dd333,Di1) + Dval(dd333,Di2) -
- & 6*Ginv(4,4)*(Dval(dd003,Di1) - Dval(dd003,Di2))
- IN(2) = f2*E(ee444) - Dval(dd333,Di1) + Dval(dd333,Di3) -
- & 6*Ginv(4,4)*(Dval(dd003,Di1) - Dval(dd003,Di3))
- IN(3) = f3*E(ee444) - Dval(dd333,Di1) + Dval(dd333,Di4) -
- & 6*Ginv(4,4)*(Dval(dd003,Di1) - Dval(dd003,Di4))
- IN(4) = f4*E(ee444) - Dval(dd333,Di1) -
- & 6*Ginv(4,4)*Dval(dd003,Di1)
- call SOLVE(in)
+ IN(1) = f1*E(ee444) - D2345(dd333) + D1345(dd333) -
+ & 6*Ginv(4,4)*(D2345(dd003) - D1345(dd003))
+ IN(2) = f2*E(ee444) - D2345(dd333) + D1245(dd333) -
+ & 6*Ginv(4,4)*(D2345(dd003) - D1245(dd003))
+ IN(3) = f3*E(ee444) - D2345(dd333) + D1235(dd333) -
+ & 6*Ginv(4,4)*(D2345(dd003) - D1235(dd003))
+ IN(4) = f4*E(ee444) - D2345(dd333) -
+ & 6*Ginv(4,4)*D2345(dd003)
+ call SOLVER(in)
E(ee1444) = in(1)
E(ee2444) = in(2)
E(ee3444) = in(3)
E(ee4444) = in(4)
d1sum = d1sum + d1i + d1ii
IN(1) = f1*E(ee112) - d1sum -
- & 2*Ginv(1,1)*(Dval(dd001,Di1) - Dval(dd001,Di2)) +
+ & 2*Ginv(1,1)*(D2345(dd001) - D1345(dd001)) +
& 4*Ginv(1,2)*d00sum
IN(2) = f2*E(ee112) - d1sum -
- & 2*Ginv(1,1)*Dval(dd001,Di1) +
- & 4*Ginv(1,2)*(d00sum + Dval(dd001,Di3))
- IN(3) = f3*E(ee112) - d1sum + Dval(dd112,Di4) -
- & 2*Ginv(1,1)*(Dval(dd001,Di1) - Dval(dd002,Di4)) +
- & 4*Ginv(1,2)*(d00sum + Dval(dd001,Di4))
- IN(4) = f4*E(ee112) - d1sum + Dval(dd112,Di5) -
- & 2*Ginv(1,1)*(Dval(dd001,Di1) - Dval(dd002,Di5)) +
- & 4*Ginv(1,2)*(d00sum + Dval(dd001,Di5))
- call SOLVE(in)
+ & 2*Ginv(1,1)*D2345(dd001) +
+ & 4*Ginv(1,2)*(d00sum + D1245(dd001))
+ IN(3) = f3*E(ee112) - d1sum + D1235(dd112) -
+ & 2*Ginv(1,1)*(D2345(dd001) - D1235(dd002)) +
+ & 4*Ginv(1,2)*(d00sum + D1235(dd001))
+ IN(4) = f4*E(ee112) - d1sum + D1234(dd112) -
+ & 2*Ginv(1,1)*(D2345(dd001) - D1234(dd002)) +
+ & 4*Ginv(1,2)*(d00sum + D1234(dd001))
+ call SOLVER(in)
E(ee1112) = .5D0*(E(ee1112) + in(1))
E(ee1122) = in(2)
E(ee1123) = in(3)
E(ee1124) = in(4)
- IN(1) = f1*E(ee223) - Dval(dd112,Di1) + Dval(dd112,Di2) -
- & 2*Ginv(2,2)*(Dval(dd002,Di1) - Dval(dd002,Di2)) -
- & 4*Ginv(2,3)*(Dval(dd001,Di1) - Dval(dd001,Di2))
- IN(2) = f2*E(ee223) - Dval(dd112,Di1) -
- & 2*Ginv(2,2)*(Dval(dd002,Di1) - Dval(dd002,Di3)) -
- & 4*Ginv(2,3)*Dval(dd001,Di1)
- IN(3) = f3*E(ee223) - Dval(dd112,Di1) -
- & 2*Ginv(2,2)*Dval(dd002,Di1) -
- & 4*Ginv(2,3)*(Dval(dd001,Di1) - Dval(dd002,Di4))
- IN(4) = f4*E(ee223) - Dval(dd112,Di1) + Dval(dd223,Di5) -
- & 2*Ginv(2,2)*(Dval(dd002,Di1) - Dval(dd003,Di5)) -
- & 4*Ginv(2,3)*(Dval(dd001,Di1) - Dval(dd002,Di5))
- call SOLVE(in)
+ IN(1) = f1*E(ee223) - D2345(dd112) + D1345(dd112) -
+ & 2*Ginv(2,2)*(D2345(dd002) - D1345(dd002)) -
+ & 4*Ginv(2,3)*(D2345(dd001) - D1345(dd001))
+ IN(2) = f2*E(ee223) - D2345(dd112) -
+ & 2*Ginv(2,2)*(D2345(dd002) - D1245(dd002)) -
+ & 4*Ginv(2,3)*D2345(dd001)
+ IN(3) = f3*E(ee223) - D2345(dd112) -
+ & 2*Ginv(2,2)*D2345(dd002) -
+ & 4*Ginv(2,3)*(D2345(dd001) - D1235(dd002))
+ IN(4) = f4*E(ee223) - D2345(dd112) + D1234(dd223) -
+ & 2*Ginv(2,2)*(D2345(dd002) - D1234(dd003)) -
+ & 4*Ginv(2,3)*(D2345(dd001) - D1234(dd002))
+ call SOLVER(in)
E(ee1223) = in(1)
E(ee2223) = .5D0*(E(ee2223) + in(2))
E(ee2233) = in(3)
E(ee2234) = in(4)
- IN(1) = f1*E(ee334) - Dval(dd223,Di1) + Dval(dd223,Di2) -
- & 2*Ginv(3,3)*(Dval(dd003,Di1) - Dval(dd003,Di2)) -
- & 4*Ginv(3,4)*(Dval(dd002,Di1) - Dval(dd002,Di2))
- IN(2) = f2*E(ee334) - Dval(dd223,Di1) + Dval(dd223,Di3) -
- & 2*Ginv(3,3)*(Dval(dd003,Di1) - Dval(dd003,Di3)) -
- & 4*Ginv(3,4)*(Dval(dd002,Di1) - Dval(dd002,Di3))
- IN(3) = f3*E(ee334) - Dval(dd223,Di1) -
- & 2*Ginv(3,3)*(Dval(dd003,Di1) - Dval(dd003,Di4)) -
- & 4*Ginv(3,4)*Dval(dd002,Di1)
- IN(4) = f4*E(ee334) - Dval(dd223,Di1) -
- & 2*Ginv(3,3)*Dval(dd003,Di1) -
- & 4*Ginv(3,4)*(Dval(dd002,Di1) - Dval(dd003,Di5))
- call SOLVE(in)
+ IN(1) = f1*E(ee334) - D2345(dd223) + D1345(dd223) -
+ & 2*Ginv(3,3)*(D2345(dd003) - D1345(dd003)) -
+ & 4*Ginv(3,4)*(D2345(dd002) - D1345(dd002))
+ IN(2) = f2*E(ee334) - D2345(dd223) + D1245(dd223) -
+ & 2*Ginv(3,3)*(D2345(dd003) - D1245(dd003)) -
+ & 4*Ginv(3,4)*(D2345(dd002) - D1245(dd002))
+ IN(3) = f3*E(ee334) - D2345(dd223) -
+ & 2*Ginv(3,3)*(D2345(dd003) - D1235(dd003)) -
+ & 4*Ginv(3,4)*D2345(dd002)
+ IN(4) = f4*E(ee334) - D2345(dd223) -
+ & 2*Ginv(3,3)*D2345(dd003) -
+ & 4*Ginv(3,4)*(D2345(dd002) - D1234(dd003))
+ call SOLVER(in)
E(ee1334) = in(1)
E(ee2334) = in(2)
E(ee3334) = .5D0*(E(ee3334) + in(3))
E(ee3344) = in(4)
IN(1) = f1*E(ee144) + d33sum -
- & 4*Ginv(1,4)*(Dval(dd003,Di1) - Dval(dd003,Di2)) +
+ & 4*Ginv(1,4)*(D2345(dd003) - D1345(dd003)) +
& 2*Ginv(4,4)*d00sum
- IN(2) = f2*E(ee144) + d33sum + Dval(dd133,Di3) -
- & 4*Ginv(1,4)*(Dval(dd003,Di1) - Dval(dd003,Di3)) +
- & 2*Ginv(4,4)*(d00sum + Dval(dd001,Di3))
- IN(3) = f3*E(ee144) + d33sum + Dval(dd133,Di4) -
- & 4*Ginv(1,4)*(Dval(dd003,Di1) - Dval(dd003,Di4)) +
- & 2*Ginv(4,4)*(d00sum + Dval(dd001,Di4))
+ IN(2) = f2*E(ee144) + d33sum + D1245(dd133) -
+ & 4*Ginv(1,4)*(D2345(dd003) - D1245(dd003)) +
+ & 2*Ginv(4,4)*(d00sum + D1245(dd001))
+ IN(3) = f3*E(ee144) + d33sum + D1235(dd133) -
+ & 4*Ginv(1,4)*(D2345(dd003) - D1235(dd003)) +
+ & 2*Ginv(4,4)*(d00sum + D1235(dd001))
IN(4) = f4*E(ee144) + d33sum -
- & 4*Ginv(1,4)*Dval(dd003,Di1) +
- & 2*Ginv(4,4)*(d00sum + Dval(dd001,Di5))
- call SOLVE(in)
+ & 4*Ginv(1,4)*D2345(dd003) +
+ & 2*Ginv(4,4)*(d00sum + D1234(dd001))
+ call SOLVER(in)
E(ee1144) = in(1)
E(ee1244) = in(2)
E(ee1344) = in(3)
E(ee1444) = .5D0*(E(ee1444) + in(4))
d2sum = d2sum + d2i + d2ii
IN(1) = f1*E(ee113) - d2sum -
- & 2*Ginv(1,1)*(Dval(dd002,Di1) - Dval(dd002,Di2)) +
+ & 2*Ginv(1,1)*(D2345(dd002) - D1345(dd002)) +
& 4*Ginv(1,3)*d00sum
- IN(2) = f2*E(ee113) - d2sum + Dval(dd112,Di3) -
- & 2*Ginv(1,1)*(Dval(dd002,Di1) - Dval(dd002,Di3)) +
- & 4*Ginv(1,3)*(d00sum + Dval(dd001,Di3))
+ IN(2) = f2*E(ee113) - d2sum + D1245(dd112) -
+ & 2*Ginv(1,1)*(D2345(dd002) - D1245(dd002)) +
+ & 4*Ginv(1,3)*(d00sum + D1245(dd001))
IN(3) = f3*E(ee113) - d2sum -
- & 2*Ginv(1,1)*Dval(dd002,Di1) +
- & 4*Ginv(1,3)*(d00sum + Dval(dd001,Di4))
- IN(4) = f4*E(ee113) - d2sum + Dval(dd113,Di5) -
- & 2*Ginv(1,1)*(Dval(dd002,Di1) - Dval(dd003,Di5)) +
- & 4*Ginv(1,3)*(d00sum + Dval(dd001,Di5))
- call SOLVE(in)
+ & 2*Ginv(1,1)*D2345(dd002) +
+ & 4*Ginv(1,3)*(d00sum + D1235(dd001))
+ IN(4) = f4*E(ee113) - d2sum + D1234(dd113) -
+ & 2*Ginv(1,1)*(D2345(dd002) - D1234(dd003)) +
+ & 4*Ginv(1,3)*(d00sum + D1234(dd001))
+ call SOLVER(in)
E(ee1113) = .5D0*(E(ee1113) + in(1))
E(ee1123) = .5D0*(E(ee1123) + in(2))
E(ee1133) = in(3)
E(ee1134) = in(4)
- IN(1) = f1*E(ee224) - Dval(dd113,Di1) + Dval(dd113,Di2) -
- & 2*Ginv(2,2)*(Dval(dd003,Di1) - Dval(dd003,Di2)) -
- & 4*Ginv(2,4)*(Dval(dd001,Di1) - Dval(dd001,Di2))
- IN(2) = f2*E(ee224) - Dval(dd113,Di1) -
- & 2*Ginv(2,2)*(Dval(dd003,Di1) - Dval(dd003,Di3)) -
- & 4*Ginv(2,4)*Dval(dd001,Di1)
- IN(3) = f3*E(ee224) - Dval(dd113,Di1) + Dval(dd223,Di4) -
- & 2*Ginv(2,2)*(Dval(dd003,Di1) - Dval(dd003,Di4)) -
- & 4*Ginv(2,4)*(Dval(dd001,Di1) - Dval(dd002,Di4))
- IN(4) = f4*E(ee224) - Dval(dd113,Di1) -
- & 2*Ginv(2,2)*Dval(dd003,Di1) -
- & 4*Ginv(2,4)*(Dval(dd001,Di1) - Dval(dd002,Di5))
- call SOLVE(in)
+ IN(1) = f1*E(ee224) - D2345(dd113) + D1345(dd113) -
+ & 2*Ginv(2,2)*(D2345(dd003) - D1345(dd003)) -
+ & 4*Ginv(2,4)*(D2345(dd001) - D1345(dd001))
+ IN(2) = f2*E(ee224) - D2345(dd113) -
+ & 2*Ginv(2,2)*(D2345(dd003) - D1245(dd003)) -
+ & 4*Ginv(2,4)*D2345(dd001)
+ IN(3) = f3*E(ee224) - D2345(dd113) + D1235(dd223) -
+ & 2*Ginv(2,2)*(D2345(dd003) - D1235(dd003)) -
+ & 4*Ginv(2,4)*(D2345(dd001) - D1235(dd002))
+ IN(4) = f4*E(ee224) - D2345(dd113) -
+ & 2*Ginv(2,2)*D2345(dd003) -
+ & 4*Ginv(2,4)*(D2345(dd001) - D1234(dd002))
+ call SOLVER(in)
E(ee1224) = in(1)
E(ee2224) = .5D0*(E(ee2224) + in(2))
E(ee2234) = E(ee2234) + in(3)
E(ee2244) = in(4)
- IN(1) = f1*E(ee234) - Dval(dd123,Di1) + Dval(dd123,Di2) -
- & 2*Ginv(2,3)*(Dval(dd003,Di1) - Dval(dd003,Di2)) -
- & 2*Ginv(3,4)*(Dval(dd001,Di1) - Dval(dd001,Di2)) -
- & 2*Ginv(2,4)*(Dval(dd002,Di1) - Dval(dd002,Di2))
- IN(2) = f2*E(ee234) - Dval(dd123,Di1) -
- & 2*Ginv(2,3)*(Dval(dd003,Di1) - Dval(dd003,Di3)) -
- & 2*Ginv(3,4)*Dval(dd001,Di1) -
- & 2*Ginv(2,4)*(Dval(dd002,Di1) - Dval(dd002,Di3))
- IN(3) = f3*E(ee234) - Dval(dd123,Di1) -
- & 2*Ginv(2,3)*(Dval(dd003,Di1) - Dval(dd003,Di4)) -
- & 2*Ginv(3,4)*(Dval(dd001,Di1) - Dval(dd002,Di4)) -
- & 2*Ginv(2,4)*Dval(dd002,Di1)
- IN(4) = f4*E(ee234) - Dval(dd123,Di1) -
- & 2*Ginv(2,3)*Dval(dd003,Di1) -
- & 2*Ginv(3,4)*(Dval(dd001,Di1) - Dval(dd002,Di5)) -
- & 2*Ginv(2,4)*(Dval(dd002,Di1) - Dval(dd003,Di5))
- call SOLVE(in)
+ IN(1) = f1*E(ee234) - D2345(dd123) + D1345(dd123) -
+ & 2*Ginv(2,3)*(D2345(dd003) - D1345(dd003)) -
+ & 2*Ginv(3,4)*(D2345(dd001) - D1345(dd001)) -
+ & 2*Ginv(2,4)*(D2345(dd002) - D1345(dd002))
+ IN(2) = f2*E(ee234) - D2345(dd123) -
+ & 2*Ginv(2,3)*(D2345(dd003) - D1245(dd003)) -
+ & 2*Ginv(3,4)*D2345(dd001) -
+ & 2*Ginv(2,4)*(D2345(dd002) - D1245(dd002))
+ IN(3) = f3*E(ee234) - D2345(dd123) -
+ & 2*Ginv(2,3)*(D2345(dd003) - D1235(dd003)) -
+ & 2*Ginv(3,4)*(D2345(dd001) - D1235(dd002)) -
+ & 2*Ginv(2,4)*D2345(dd002)
+ IN(4) = f4*E(ee234) - D2345(dd123) -
+ & 2*Ginv(2,3)*D2345(dd003) -
+ & 2*Ginv(3,4)*(D2345(dd001) - D1234(dd002)) -
+ & 2*Ginv(2,4)*(D2345(dd002) - D1234(dd003))
+ call SOLVER(in)
E(ee1234) = in(1)
E(ee2234) = 1/3D0*(E(ee2234) + in(2))
E(ee2334) = .5D0*(E(ee2334) + in(3))
E(ee2344) = in(4)
IN(1) = f1*E(ee133) + d22sum -
- & 4*Ginv(1,3)*(Dval(dd002,Di1) - Dval(dd002,Di2)) +
+ & 4*Ginv(1,3)*(D2345(dd002) - D1345(dd002)) +
& 2*Ginv(3,3)*d00sum
- IN(2) = f2*E(ee133) + d22sum + Dval(dd122,Di3) -
- & 4*Ginv(1,3)*(Dval(dd002,Di1) - Dval(dd002,Di3)) +
- & 2*Ginv(3,3)*(d00sum + Dval(dd001,Di3))
+ IN(2) = f2*E(ee133) + d22sum + D1245(dd122) -
+ & 4*Ginv(1,3)*(D2345(dd002) - D1245(dd002)) +
+ & 2*Ginv(3,3)*(d00sum + D1245(dd001))
IN(3) = f3*E(ee133) + d22sum -
- & 4*Ginv(1,3)*Dval(dd002,Di1) +
- & 2*Ginv(3,3)*(d00sum + Dval(dd001,Di4))
- IN(4) = f4*E(ee133) + d22sum + Dval(dd133,Di5) -
- & 4*Ginv(1,3)*(Dval(dd002,Di1) - Dval(dd003,Di5)) +
- & 2*Ginv(3,3)*(d00sum + Dval(dd001,Di5))
- call SOLVE(in)
+ & 4*Ginv(1,3)*D2345(dd002) +
+ & 2*Ginv(3,3)*(d00sum + D1235(dd001))
+ IN(4) = f4*E(ee133) + d22sum + D1234(dd133) -
+ & 4*Ginv(1,3)*(D2345(dd002) - D1234(dd003)) +
+ & 2*Ginv(3,3)*(d00sum + D1234(dd001))
+ call SOLVER(in)
E(ee1133) = .5D0*(E(ee1133) + in(1))
E(ee1233) = in(2)
E(ee1333) = .5D0*(E(ee1333) + in(3))
E(ee1334) = .5D0*(E(ee1334) + in(4))
if( dump ) call XDumpCoeff(5, E)
end
diff --git a/Looptools/E/Eget.F b/Looptools/E/Eget.F
--- a/Looptools/E/Eget.F
+++ b/Looptools/E/Eget.F
@@ -1,309 +1,466 @@
* Eget.F
* retrieve the five-point tensor coefficients
* this file is part of LoopTools
* written by M. Rauch
-* last modified 24 Aug 09 th
+* last modified 23 Mar 15 th
+#include "externals.h"
+#include "types.h"
+
+#define npoint 5
#include "defs.h"
- integer function XEget(p1, p2, p3, p4, p5,
+ subroutine XEpara(para, p1, p2, p3, p4, p5,
+ & p1p2, p2p3, p3p4, p4p5, p5p1, m1, m2, m3, m4, m5)
+ implicit none
+ DVAR para(1,*)
+ DVAR p1, p2, p3, p4, p5
+ DVAR p1p2, p2p3, p3p4, p4p5, p5p1
+ DVAR m1, m2, m3, m4, m5
+
+#include "lt.h"
+
+ P(1) = p1
+ P(2) = p2
+ P(3) = p3
+ P(4) = p4
+ P(5) = p5
+ P(6) = p1p2
+ P(7) = p2p3
+ P(8) = p3p4
+ P(9) = p4p5
+ P(10) = p5p1
+
+ M(1) = m1
+ if( abs(M(1)) .lt. minmass ) M(1) = 0
+ M(2) = m2
+ if( abs(M(2)) .lt. minmass ) M(2) = 0
+ M(3) = m3
+ if( abs(M(3)) .lt. minmass ) M(3) = 0
+ M(4) = m4
+ if( abs(M(4)) .lt. minmass ) M(4) = 0
+ M(5) = m5
+ if( abs(M(5)) .lt. minmass ) M(5) = 0
+ end
+
+************************************************************************
+
+ memindex function XEget(p1, p2, p3, p4, p5,
& p1p2, p2p3, p3p4, p4p5, p5p1, m1, m2, m3, m4, m5)
implicit none
DVAR p1, p2, p3, p4, p5
DVAR p1p2, p2p3, p3p4, p4p5, p5p1
DVAR m1, m2, m3, m4, m5
#include "lt.h"
- integer cachelookup
- external cachelookup, XEcoeff
+ memindex cacheindex
+ external cacheindex, XEcoefx
- DVAR para(Pee)
+#ifdef COMPLEXPARA
+ memindex Eget
+ external Eget
+#endif
- para(1) = p1
- para(2) = p2
- para(3) = p3
- para(4) = p4
- para(5) = p5
- para(6) = p1p2
- para(7) = p2p3
- para(8) = p3p4
- para(9) = p4p5
- para(10) = p5p1
- para(11) = m1
- if( abs(para(11)) .lt. minmass ) para(11) = 0
- para(12) = m2
- if( abs(para(12)) .lt. minmass ) para(12) = 0
- para(13) = m3
- if( abs(para(13)) .lt. minmass ) para(13) = 0
- para(14) = m4
- if( abs(para(14)) .lt. minmass ) para(14) = 0
- para(15) = m5
- if( abs(para(15)) .lt. minmass ) para(15) = 0
+ DVAR para(1,Pee)
- XEget = cachelookup(para, Eval(1,0), XEcoeff, RC*Pee, Nee)
+#ifdef COMPLEXPARA
+ if( abs(Im(p1)) + abs(Im(p2)) +
+ & abs(Im(p3)) + abs(Im(p4)) +
+ & abs(Im(p5)) + abs(Im(p1p2)) +
+ & abs(Im(p2p3)) + abs(Im(p3p4)) +
+ & abs(Im(p4p5)) + abs(Im(p5p1)) .gt. 0 )
+ & print *, "Complex momenta not implemented"
+ if( abs(Im(m1)) + abs(Im(m2)) +
+ & abs(Im(m3)) + abs(Im(m4)) + abs(Im(m5)) .eq. 0 ) then
+ XEget = Eget(p1, p2, p3, p4, p1p2, p2p3,
+ & m1, m2, m3, m4) - offsetC
+ return
+ endif
+#endif
+
+ call XEpara(para, p1, p2, p3, p4, p5,
+ & p1p2, p2p3, p3p4, p4p5, p5p1, m1, m2, m3, m4, m5)
+ XEget = cacheindex(para, Eval(1,0), XEcoefx, RC*Pee, Nee, Eno)
end
************************************************************************
- double complex function XE0i(i, p1, p2, p3, p4, p5,
+ subroutine XEput(res, p1, p2, p3, p4, p5,
+ & p1p2, p2p3, p3p4, p4p5, p5p1, m1, m2, m3, m4, m5)
+ implicit none
+ ComplexType res(*)
+ DVAR p1, p2, p3, p4, p5
+ DVAR p1p2, p2p3, p3p4, p4p5, p5p1
+ DVAR m1, m2, m3, m4, m5
+
+#include "lt.h"
+
+ external XEcoefx
+
+ DVAR para(1,Pee)
+
+#ifdef COMPLEXPARA
+ if( abs(Im(p1)) + abs(Im(p2)) +
+ & abs(Im(p3)) + abs(Im(p4)) +
+ & abs(Im(p5)) + abs(Im(p1p2)) +
+ & abs(Im(p2p3)) + abs(Im(p3p4)) +
+ & abs(Im(p4p5)) + abs(Im(p5p1)) .gt. 0 )
+ & print *, "Complex momenta not implemented"
+ if( abs(Im(m1)) + abs(Im(m2)) +
+ & abs(Im(m3)) + abs(Im(m4)) + abs(Im(m5)) .eq. 0 ) then
+ call Eput(res, p1, p2, p3, p4, p1p2, p2p3,
+ & m1, m2, m3, m4)
+ return
+ endif
+#endif
+
+ call XEpara(para, p1, p2, p3, p4, p5,
+ & p1p2, p2p3, p3p4, p4p5, p5p1, m1, m2, m3, m4, m5)
+ call cachecopy(res, para, Eval(1,0), XEcoefx, RC*Pee, Nee, Eno)
+ end
+
+************************************************************************
+
+ subroutine XE0nocache(res, p1, p2, p3, p4, p5,
+ & p1p2, p2p3, p3p4, p4p5, p5p1, m1, m2, m3, m4, m5)
+ implicit none
+ ComplexType res(*)
+ DVAR p1, p2, p3, p4, p5
+ DVAR p1p2, p2p3, p3p4, p4p5, p5p1
+ DVAR m1, m2, m3, m4, m5
+
+#include "lt.h"
+
+ DVAR para(1,Pee)
+ ComplexType D2345(0:2), D1345(0:2), D1245(0:2)
+ ComplexType D1235(0:2), D1234(0:2)
+
+#ifdef COMPLEXPARA
+ if( abs(Im(p1)) + abs(Im(p2)) +
+ & abs(Im(p3)) + abs(Im(p4)) +
+ & abs(Im(p5)) + abs(Im(p1p2)) +
+ & abs(Im(p2p3)) + abs(Im(p3p4)) +
+ & abs(Im(p4p5)) + abs(Im(p5p1)) .gt. 0 )
+ & print *, "Complex momenta not implemented"
+ if( abs(Im(m1)) + abs(Im(m2)) +
+ & abs(Im(m3)) + abs(Im(m4)) + abs(Im(m5)) .eq. 0 ) then
+ call E0nocache(res, p1, p2, p3, p4, p1p2, p2p3,
+ & m1, m2, m3, m4)
+ return
+ endif
+#endif
+
+ call XEpara(para, p1, p2, p3, p4, p5,
+ & p1p2, p2p3, p3p4, p4p5, p5p1, m1, m2, m3, m4, m5)
+ call XE0func(res, para, D2345, D1345, D1245, D1235, D1234, 0)
+ end
+
+************************************************************************
+
+ ComplexType function XE0i(i, p1, p2, p3, p4, p5,
& p1p2, p2p3, p3p4, p4p5, p5p1, m1, m2, m3, m4, m5)
implicit none
integer i
DVAR p1, p2, p3, p4, p5
DVAR p1p2, p2p3, p3p4, p4p5, p5p1
DVAR m1, m2, m3, m4, m5
#include "lt.h"
- integer XEget
+ memindex XEget
external XEget
- integer b
+ memindex b
b = XEget(p1, p2, p3, p4, p5,
& p1p2, p2p3, p3p4, p4p5, p5p1, m1, m2, m3, m4, m5)
- XE0i = Eval(i,b)
+ XE0i = Eval(i+epsi,b)
end
************************************************************************
- subroutine XEcoeff(para, E, ldpara)
+ ComplexType function XE0(p1, p2, p3, p4, p5,
+ & p1p2, p2p3, p3p4, p4p5, p5p1, m1, m2, m3, m4, m5)
implicit none
- integer ldpara
- DVAR para(ldpara,Pee)
- double complex E(Nee)
+ DVAR p1, p2, p3, p4, p5
+ DVAR p1p2, p2p3, p3p4, p4p5, p5p1
+ DVAR m1, m2, m3, m4, m5
#include "lt.h"
- double complex Ecmp(Nee)
+ ComplexType XE0i
+ external XE0i
+
+ XE0 = XE0i(ee0, p1, p2, p3, p4, p5,
+ & p1p2, p2p3, p3p4, p4p5, p5p1, m1, m2, m3, m4, m5)
+ end
+
+************************************************************************
+
+ subroutine XEcoefx(res, para)
+ implicit none
+ ComplexType res(*)
+ DVAR para(1,*)
+
+#include "lt.h"
+
+ memindex d2345, d1345, d1245, d1235, d1234
+
+ memindex XDget
+ external XDget
+
+ d2345 = XDget(P(2), P(3), P(4), P(10), P(7), P(8),
+ & M(2), M(3), M(4), M(5))
+ d1345 = XDget(P(6), P(3), P(4), P(5), P(9), P(8),
+ & M(1), M(3), M(4), M(5))
+ d1245 = XDget(P(1), P(7), P(4), P(5), P(9), P(10),
+ & M(1), M(2), M(4), M(5))
+ d1235 = XDget(P(1), P(2), P(8), P(5), P(6), P(10),
+ & M(1), M(2), M(3), M(5))
+ d1234 = XDget(P(1), P(2), P(3), P(9), P(6), P(7),
+ & M(1), M(2), M(3), M(4))
+
+ call XEcoeff(res, para, Dval(1,d2345), Dval(1,d1345),
+ & Dval(1,d1245), Dval(1,d1235), Dval(1,d1234))
+ end
+
+************************************************************************
+
+ subroutine XEcoeff(res, para, D2345, D1345, D1245, D1235, D1234)
+ implicit none
+ ComplexType res(*)
+ ComplexType D2345(*), D1345(*), D1245(*), D1235(*), D1234(*)
+ DVAR para(1,*)
+
+#include "lt.h"
+
+ ComplexType cmp(Nee)
#ifdef COMPLEXPARA
goto (1, 2, 3) ibits(versionkey, KeyEgetC, 2)
#else
goto (1, 2, 3) ibits(versionkey, KeyEget, 2)
#endif
- call XEcoeffa(para, E, ldpara)
+ call XEcoeffa(res, para, D2345, D1345, D1245, D1235, D1234)
return
-1 call XEcoeffb(para, E, ldpara)
+1 call XEcoeffb(res, para, D2345, D1345, D1245, D1235, D1234)
return
-2 call XEcheck(para, E, Ecmp, ldpara)
+2 call XEcoeffa(res, para, D2345, D1345, D1245, D1235, D1234)
+ call XEcoeffb(cmp, para, D2345, D1345, D1245, D1235, D1234)
+ call XEcheck(res, cmp, para)
return
-3 call XEcheck(para, Ecmp, E, ldpara)
+3 call XEcoeffa(cmp, para, D2345, D1345, D1245, D1235, D1234)
+ call XEcoeffb(res, para, D2345, D1345, D1245, D1235, D1234)
+ call XEcheck(cmp, res, para)
end
************************************************************************
- subroutine XEcheck(para, Ea, Eb, ldpara)
+ subroutine XEcheck(Ea, Eb, para)
implicit none
- integer ldpara
- DVAR para(ldpara,Pee)
- double complex Ea(Nee), Eb(Nee)
+ ComplexType Ea(*), Eb(*)
+ DVAR para(1,*)
#include "lt.h"
+#include "ltnames.h"
- double complex dE(Nee)
+ ComplexType dE(Nee)
integer i
logical ini
QVAR Ginv(4,4)
common /XInvGramE/ Ginv
- character*8 coeffname(Nee,2:5)
- common /ltcoeffnames/ coeffname
-
- call XEcoeffa(para, Ea, ldpara)
- call XEcoeffb(para, Eb, ldpara)
-
- dE(ee0) = 0
- dE(ee1) = 0
- dE(ee2) = 0
- dE(ee3) = 0
- dE(ee4) = 0
- dE(ee11) = -2*Ea(ee00)*Ginv(1,1)
- dE(ee12) = -2*Ea(ee00)*Ginv(1,2)
- dE(ee13) = -2*Ea(ee00)*Ginv(1,3)
- dE(ee14) = -2*Ea(ee00)*Ginv(1,4)
- dE(ee22) = -2*Ea(ee00)*Ginv(2,2)
- dE(ee23) = -2*Ea(ee00)*Ginv(2,3)
- dE(ee24) = -2*Ea(ee00)*Ginv(2,4)
- dE(ee33) = -2*Ea(ee00)*Ginv(3,3)
- dE(ee34) = -2*Ea(ee00)*Ginv(3,4)
- dE(ee44) = -2*Ea(ee00)*Ginv(4,4)
- dE(ee00) = Ea(ee00)
- dE(ee111) = -6*Ea(ee001)*Ginv(1,1)
- dE(ee112) = -2*(Ea(ee002)*Ginv(1,1) +
- & Ea(ee001)*(Ginv(1,2) + Ginv(2,1)))
- dE(ee113) = -2*(Ea(ee003)*Ginv(1,1) +
- & Ea(ee001)*(Ginv(1,3) + Ginv(3,1)))
- dE(ee114) = -2*(Ea(ee004)*Ginv(1,1) +
- & Ea(ee001)*(Ginv(1,4) + Ginv(4,1)))
- dE(ee122) = -2*(Ea(ee002)*(Ginv(1,2) + Ginv(2,1)) +
- & Ea(ee001)*Ginv(2,2))
- dE(ee123) = -2*(Ea(ee003)*Ginv(1,2) + Ea(ee001)*Ginv(2,3) +
- & Ea(ee002)*Ginv(3,1))
- dE(ee124) = -2*(Ea(ee004)*Ginv(1,2) + Ea(ee001)*Ginv(2,4) +
- & Ea(ee002)*Ginv(4,1))
- dE(ee133) = -2*(Ea(ee003)*(Ginv(1,3) + Ginv(3,1)) +
- & Ea(ee001)*Ginv(3,3))
- dE(ee134) = -2*(Ea(ee004)*Ginv(1,3) + Ea(ee001)*Ginv(3,4) +
- & Ea(ee003)*Ginv(4,1))
- dE(ee144) = -2*(Ea(ee004)*(Ginv(1,4) + Ginv(4,1)) +
- & Ea(ee001)*Ginv(4,4))
- dE(ee222) = -6*Ea(ee002)*Ginv(2,2)
- dE(ee223) = -2*(Ea(ee003)*Ginv(2,2) +
- & Ea(ee002)*(Ginv(2,3) + Ginv(3,2)))
- dE(ee224) = -2*(Ea(ee004)*Ginv(2,2) +
- & Ea(ee002)*(Ginv(2,4) + Ginv(4,2)))
- dE(ee233) = -2*(Ea(ee003)*(Ginv(2,3) + Ginv(3,2)) +
- & Ea(ee002)*Ginv(3,3))
- dE(ee234) = -2*(Ea(ee004)*Ginv(2,3) + Ea(ee002)*Ginv(3,4) +
- & Ea(ee003)*Ginv(4,2))
- dE(ee244) = -2*(Ea(ee004)*(Ginv(2,4) + Ginv(4,2)) +
- & Ea(ee002)*Ginv(4,4))
- dE(ee333) = -6*Ea(ee003)*Ginv(3,3)
- dE(ee334) = -2*(Ea(ee004)*Ginv(3,3) +
- & Ea(ee003)*(Ginv(3,4) + Ginv(4,3)))
- dE(ee344) = -2*(Ea(ee004)*(Ginv(3,4) + Ginv(4,3)) +
- & Ea(ee003)*Ginv(4,4))
- dE(ee444) = -6*Ea(ee004)*Ginv(4,4)
- dE(ee001) = Ea(ee001)
- dE(ee002) = Ea(ee002)
- dE(ee003) = Ea(ee003)
- dE(ee004) = Ea(ee004)
- dE(ee1111) = -12*Ginv(1,1)*(Ea(ee0011) + Ea(ee0000)*Ginv(1,1))
- dE(ee1112) = -6*(Ea(ee0012)*Ginv(1,1) +
- & (Ea(ee0011) + 2*Ea(ee0000)*Ginv(1,1))*Ginv(1,2))
- dE(ee1113) = -6*(Ea(ee0013)*Ginv(1,1) +
- & (Ea(ee0011) + 2*Ea(ee0000)*Ginv(1,1))*Ginv(1,3))
- dE(ee1114) = -6*(Ea(ee0014)*Ginv(1,1) +
- & (Ea(ee0011) + 2*Ea(ee0000)*Ginv(1,1))*Ginv(1,4))
- dE(ee1122) = -2*(Ea(ee0022)*Ginv(1,1) +
- & 4*Ginv(1,2)*(Ea(ee0012) + Ea(ee0000)*Ginv(1,2)) +
- & (Ea(ee0011) + 2*Ea(ee0000)*Ginv(1,1))*Ginv(2,2))
- dE(ee1123) = -2*(Ea(ee0023)*Ginv(1,1) +
- & 2*Ea(ee0013)*Ginv(1,2) +
- & 2*(Ea(ee0012) + 2*Ea(ee0000)*Ginv(1,2))*Ginv(1,3) +
- & (Ea(ee0011) + 2*Ea(ee0000)*Ginv(1,1))*Ginv(2,3))
- dE(ee1124) = -2*(Ea(ee0024)*Ginv(1,1) +
- & 2*Ea(ee0014)*Ginv(1,2) +
- & 2*(Ea(ee0012) + 2*Ea(ee0000)*Ginv(1,2))*Ginv(1,4) +
- & (Ea(ee0011) + 2*Ea(ee0000)*Ginv(1,1))*Ginv(2,4))
- dE(ee1133) = -2*(Ea(ee0033)*Ginv(1,1) +
- & 4*Ginv(1,3)*(Ea(ee0013) + Ea(ee0000)*Ginv(1,3)) +
- & (Ea(ee0011) + 2*Ea(ee0000)*Ginv(1,1))*Ginv(3,3))
- dE(ee1134) = -2*(Ea(ee0034)*Ginv(1,1) +
- & 2*Ea(ee0014)*Ginv(1,3) +
- & 2*(Ea(ee0013) + 2*Ea(ee0000)*Ginv(1,3))*Ginv(1,4) +
- & (Ea(ee0011) + 2*Ea(ee0000)*Ginv(1,1))*Ginv(3,4))
- dE(ee1144) = -2*(Ea(ee0044)*Ginv(1,1) +
- & 4*Ginv(1,4)*(Ea(ee0014) + Ea(ee0000)*Ginv(1,4)) +
- & (Ea(ee0011) + 2*Ea(ee0000)*Ginv(1,1))*Ginv(4,4))
- dE(ee1222) = -6*(Ea(ee0022)*Ginv(1,2) +
- & (Ea(ee0012) + 2*Ea(ee0000)*Ginv(1,2))*Ginv(2,2))
- dE(ee1223) = -2*(2*Ea(ee0023)*Ginv(1,2) +
- & Ea(ee0022)*Ginv(1,3) +
- & (Ea(ee0013) + 2*Ea(ee0000)*Ginv(1,3))*Ginv(2,2) +
- & 2*(Ea(ee0012) + 2*Ea(ee0000)*Ginv(1,2))*Ginv(2,3))
- dE(ee1224) = -2*(2*Ea(ee0024)*Ginv(1,2) +
- & Ea(ee0022)*Ginv(1,4) +
- & (Ea(ee0014) + 2*Ea(ee0000)*Ginv(1,4))*Ginv(2,2) +
- & 2*(Ea(ee0012) + 2*Ea(ee0000)*Ginv(1,2))*Ginv(2,4))
- dE(ee1233) = -2*(Ea(ee0033)*Ginv(1,2) +
- & 2*Ea(ee0023)*Ginv(1,3) +
- & 2*(Ea(ee0013) + 2*Ea(ee0000)*Ginv(1,3))*Ginv(2,3) +
- & (Ea(ee0012) + 2*Ea(ee0000)*Ginv(1,2))*Ginv(3,3))
- dE(ee1234) = -2*(Ea(ee0023)*Ginv(1,4) +
- & (Ea(ee0014) + 2*Ea(ee0000)*Ginv(1,4))*Ginv(2,3) +
- & Ea(ee0013)*Ginv(2,4) +
- & Ginv(1,3)*(Ea(ee0024) + 2*Ea(ee0000)*Ginv(2,4)) +
- & Ea(ee0012)*Ginv(3,4) +
- & Ginv(1,2)*(Ea(ee0034) + 2*Ea(ee0000)*Ginv(3,4)))
- dE(ee1244) = -2*(Ea(ee0044)*Ginv(1,2) +
- & 2*Ea(ee0024)*Ginv(1,4) +
- & 2*(Ea(ee0014) + 2*Ea(ee0000)*Ginv(1,4))*Ginv(2,4) +
- & (Ea(ee0012) + 2*Ea(ee0000)*Ginv(1,2))*Ginv(4,4))
- dE(ee1333) = -6*(Ea(ee0033)*Ginv(1,3) +
- & (Ea(ee0013) + 2*Ea(ee0000)*Ginv(1,3))*Ginv(3,3))
- dE(ee1334) = -2*(2*Ea(ee0034)*Ginv(1,3) +
- & Ea(ee0033)*Ginv(1,4) +
- & (Ea(ee0014) + 2*Ea(ee0000)*Ginv(1,4))*Ginv(3,3) +
- & 2*(Ea(ee0013) + 2*Ea(ee0000)*Ginv(1,3))*Ginv(3,4))
- dE(ee1344) = -2*(Ea(ee0044)*Ginv(1,3) +
- & 2*Ea(ee0034)*Ginv(1,4) +
- & 2*(Ea(ee0014) + 2*Ea(ee0000)*Ginv(1,4))*Ginv(3,4) +
- & (Ea(ee0013) + 2*Ea(ee0000)*Ginv(1,3))*Ginv(4,4))
- dE(ee1444) = -6*(Ea(ee0044)*Ginv(1,4) +
- & (Ea(ee0014) + 2*Ea(ee0000)*Ginv(1,4))*Ginv(4,4))
- dE(ee2222) = -12*Ginv(2,2)*(Ea(ee0022) + Ea(ee0000)*Ginv(2,2))
- dE(ee2223) = -6*(Ea(ee0023)*Ginv(2,2) +
- & (Ea(ee0022) + 2*Ea(ee0000)*Ginv(2,2))*Ginv(2,3))
- dE(ee2224) = -6*(Ea(ee0024)*Ginv(2,2) +
- & (Ea(ee0022) + 2*Ea(ee0000)*Ginv(2,2))*Ginv(2,4))
- dE(ee2233) = -2*(Ea(ee0033)*Ginv(2,2) +
- & 4*Ginv(2,3)*(Ea(ee0023) + Ea(ee0000)*Ginv(2,3)) +
- & (Ea(ee0022) + 2*Ea(ee0000)*Ginv(2,2))*Ginv(3,3))
- dE(ee2234) = -2*(Ea(ee0034)*Ginv(2,2) +
- & 2*Ea(ee0024)*Ginv(2,3) +
- & 2*(Ea(ee0023) + 2*Ea(ee0000)*Ginv(2,3))*Ginv(2,4) +
- & (Ea(ee0022) + 2*Ea(ee0000)*Ginv(2,2))*Ginv(3,4))
- dE(ee2244) = -2*(Ea(ee0044)*Ginv(2,2) +
- & 4*Ginv(2,4)*(Ea(ee0024) + Ea(ee0000)*Ginv(2,4)) +
- & (Ea(ee0022) + 2*Ea(ee0000)*Ginv(2,2))*Ginv(4,4))
- dE(ee2333) = -6*(Ea(ee0033)*Ginv(2,3) +
- & (Ea(ee0023) + 2*Ea(ee0000)*Ginv(2,3))*Ginv(3,3))
- dE(ee2334) = -2*(2*Ea(ee0034)*Ginv(2,3) +
- & Ea(ee0033)*Ginv(2,4) +
- & (Ea(ee0024) + 2*Ea(ee0000)*Ginv(2,4))*Ginv(3,3) +
- & 2*(Ea(ee0023) + 2*Ea(ee0000)*Ginv(2,3))*Ginv(3,4))
- dE(ee2344) = -2*(Ea(ee0044)*Ginv(2,3) +
- & 2*Ea(ee0034)*Ginv(2,4) +
- & 2*(Ea(ee0024) + 2*Ea(ee0000)*Ginv(2,4))*Ginv(3,4) +
- & (Ea(ee0023) + 2*Ea(ee0000)*Ginv(2,3))*Ginv(4,4))
- dE(ee2444) = -6*(Ea(ee0044)*Ginv(2,4) +
- & (Ea(ee0024) + 2*Ea(ee0000)*Ginv(2,4))*Ginv(4,4))
- dE(ee3333) = -12*Ginv(3,3)*(Ea(ee0033) + Ea(ee0000)*Ginv(3,3))
- dE(ee3334) = -6*(Ea(ee0034)*Ginv(3,3) +
- & (Ea(ee0033) + 2*Ea(ee0000)*Ginv(3,3))*Ginv(3,4))
- dE(ee3344) = -2*(Ea(ee0044)*Ginv(3,3) +
- & 4*Ginv(3,4)*(Ea(ee0034) + Ea(ee0000)*Ginv(3,4)) +
- & (Ea(ee0033) + 2*Ea(ee0000)*Ginv(3,3))*Ginv(4,4))
- dE(ee3444) = -6*(Ea(ee0044)*Ginv(3,4) +
- & (Ea(ee0034) + 2*Ea(ee0000)*Ginv(3,4))*Ginv(4,4))
- dE(ee4444) = -12*Ginv(4,4)*(Ea(ee0044) + Ea(ee0000)*Ginv(4,4))
- dE(ee0000) = Ea(ee0000)
- dE(ee0011) = Ea(ee0011)
- dE(ee0012) = Ea(ee0012)
- dE(ee0013) = Ea(ee0013)
- dE(ee0014) = Ea(ee0014)
- dE(ee0022) = Ea(ee0022)
- dE(ee0023) = Ea(ee0023)
- dE(ee0024) = Ea(ee0024)
- dE(ee0033) = Ea(ee0033)
- dE(ee0034) = Ea(ee0034)
- dE(ee0044) = Ea(ee0044)
+ dE(EE0) = 0
+ dE(EE1) = 0
+ dE(EE2) = 0
+ dE(EE3) = 0
+ dE(EE4) = 0
+ dE(EE11) = -2*Ea(EE00)*Ginv(1,1)
+ dE(EE12) = -2*Ea(EE00)*Ginv(1,2)
+ dE(EE13) = -2*Ea(EE00)*Ginv(1,3)
+ dE(EE14) = -2*Ea(EE00)*Ginv(1,4)
+ dE(EE22) = -2*Ea(EE00)*Ginv(2,2)
+ dE(EE23) = -2*Ea(EE00)*Ginv(2,3)
+ dE(EE24) = -2*Ea(EE00)*Ginv(2,4)
+ dE(EE33) = -2*Ea(EE00)*Ginv(3,3)
+ dE(EE34) = -2*Ea(EE00)*Ginv(3,4)
+ dE(EE44) = -2*Ea(EE00)*Ginv(4,4)
+ dE(EE00) = Ea(EE00)
+ dE(EE111) = -6*Ea(EE001)*Ginv(1,1)
+ dE(EE112) = -2*(Ea(EE002)*Ginv(1,1) +
+ & Ea(EE001)*(Ginv(1,2) + Ginv(2,1)))
+ dE(EE113) = -2*(Ea(EE003)*Ginv(1,1) +
+ & Ea(EE001)*(Ginv(1,3) + Ginv(3,1)))
+ dE(EE114) = -2*(Ea(EE004)*Ginv(1,1) +
+ & Ea(EE001)*(Ginv(1,4) + Ginv(4,1)))
+ dE(EE122) = -2*(Ea(EE002)*(Ginv(1,2) + Ginv(2,1)) +
+ & Ea(EE001)*Ginv(2,2))
+ dE(EE123) = -2*(Ea(EE003)*Ginv(1,2) + Ea(EE001)*Ginv(2,3) +
+ & Ea(EE002)*Ginv(3,1))
+ dE(EE124) = -2*(Ea(EE004)*Ginv(1,2) + Ea(EE001)*Ginv(2,4) +
+ & Ea(EE002)*Ginv(4,1))
+ dE(EE133) = -2*(Ea(EE003)*(Ginv(1,3) + Ginv(3,1)) +
+ & Ea(EE001)*Ginv(3,3))
+ dE(EE134) = -2*(Ea(EE004)*Ginv(1,3) + Ea(EE001)*Ginv(3,4) +
+ & Ea(EE003)*Ginv(4,1))
+ dE(EE144) = -2*(Ea(EE004)*(Ginv(1,4) + Ginv(4,1)) +
+ & Ea(EE001)*Ginv(4,4))
+ dE(EE222) = -6*Ea(EE002)*Ginv(2,2)
+ dE(EE223) = -2*(Ea(EE003)*Ginv(2,2) +
+ & Ea(EE002)*(Ginv(2,3) + Ginv(3,2)))
+ dE(EE224) = -2*(Ea(EE004)*Ginv(2,2) +
+ & Ea(EE002)*(Ginv(2,4) + Ginv(4,2)))
+ dE(EE233) = -2*(Ea(EE003)*(Ginv(2,3) + Ginv(3,2)) +
+ & Ea(EE002)*Ginv(3,3))
+ dE(EE234) = -2*(Ea(EE004)*Ginv(2,3) + Ea(EE002)*Ginv(3,4) +
+ & Ea(EE003)*Ginv(4,2))
+ dE(EE244) = -2*(Ea(EE004)*(Ginv(2,4) + Ginv(4,2)) +
+ & Ea(EE002)*Ginv(4,4))
+ dE(EE333) = -6*Ea(EE003)*Ginv(3,3)
+ dE(EE334) = -2*(Ea(EE004)*Ginv(3,3) +
+ & Ea(EE003)*(Ginv(3,4) + Ginv(4,3)))
+ dE(EE344) = -2*(Ea(EE004)*(Ginv(3,4) + Ginv(4,3)) +
+ & Ea(EE003)*Ginv(4,4))
+ dE(EE444) = -6*Ea(EE004)*Ginv(4,4)
+ dE(EE001) = Ea(EE001)
+ dE(EE002) = Ea(EE002)
+ dE(EE003) = Ea(EE003)
+ dE(EE004) = Ea(EE004)
+ dE(EE1111) = -12*Ginv(1,1)*(Ea(EE0011) + Ea(EE0000)*Ginv(1,1))
+ dE(EE1112) = -6*(Ea(EE0012)*Ginv(1,1) +
+ & (Ea(EE0011) + 2*Ea(EE0000)*Ginv(1,1))*Ginv(1,2))
+ dE(EE1113) = -6*(Ea(EE0013)*Ginv(1,1) +
+ & (Ea(EE0011) + 2*Ea(EE0000)*Ginv(1,1))*Ginv(1,3))
+ dE(EE1114) = -6*(Ea(EE0014)*Ginv(1,1) +
+ & (Ea(EE0011) + 2*Ea(EE0000)*Ginv(1,1))*Ginv(1,4))
+ dE(EE1122) = -2*(Ea(EE0022)*Ginv(1,1) +
+ & 4*Ginv(1,2)*(Ea(EE0012) + Ea(EE0000)*Ginv(1,2)) +
+ & (Ea(EE0011) + 2*Ea(EE0000)*Ginv(1,1))*Ginv(2,2))
+ dE(EE1123) = -2*(Ea(EE0023)*Ginv(1,1) +
+ & 2*Ea(EE0013)*Ginv(1,2) +
+ & 2*(Ea(EE0012) + 2*Ea(EE0000)*Ginv(1,2))*Ginv(1,3) +
+ & (Ea(EE0011) + 2*Ea(EE0000)*Ginv(1,1))*Ginv(2,3))
+ dE(EE1124) = -2*(Ea(EE0024)*Ginv(1,1) +
+ & 2*Ea(EE0014)*Ginv(1,2) +
+ & 2*(Ea(EE0012) + 2*Ea(EE0000)*Ginv(1,2))*Ginv(1,4) +
+ & (Ea(EE0011) + 2*Ea(EE0000)*Ginv(1,1))*Ginv(2,4))
+ dE(EE1133) = -2*(Ea(EE0033)*Ginv(1,1) +
+ & 4*Ginv(1,3)*(Ea(EE0013) + Ea(EE0000)*Ginv(1,3)) +
+ & (Ea(EE0011) + 2*Ea(EE0000)*Ginv(1,1))*Ginv(3,3))
+ dE(EE1134) = -2*(Ea(EE0034)*Ginv(1,1) +
+ & 2*Ea(EE0014)*Ginv(1,3) +
+ & 2*(Ea(EE0013) + 2*Ea(EE0000)*Ginv(1,3))*Ginv(1,4) +
+ & (Ea(EE0011) + 2*Ea(EE0000)*Ginv(1,1))*Ginv(3,4))
+ dE(EE1144) = -2*(Ea(EE0044)*Ginv(1,1) +
+ & 4*Ginv(1,4)*(Ea(EE0014) + Ea(EE0000)*Ginv(1,4)) +
+ & (Ea(EE0011) + 2*Ea(EE0000)*Ginv(1,1))*Ginv(4,4))
+ dE(EE1222) = -6*(Ea(EE0022)*Ginv(1,2) +
+ & (Ea(EE0012) + 2*Ea(EE0000)*Ginv(1,2))*Ginv(2,2))
+ dE(EE1223) = -2*(2*Ea(EE0023)*Ginv(1,2) +
+ & Ea(EE0022)*Ginv(1,3) +
+ & (Ea(EE0013) + 2*Ea(EE0000)*Ginv(1,3))*Ginv(2,2) +
+ & 2*(Ea(EE0012) + 2*Ea(EE0000)*Ginv(1,2))*Ginv(2,3))
+ dE(EE1224) = -2*(2*Ea(EE0024)*Ginv(1,2) +
+ & Ea(EE0022)*Ginv(1,4) +
+ & (Ea(EE0014) + 2*Ea(EE0000)*Ginv(1,4))*Ginv(2,2) +
+ & 2*(Ea(EE0012) + 2*Ea(EE0000)*Ginv(1,2))*Ginv(2,4))
+ dE(EE1233) = -2*(Ea(EE0033)*Ginv(1,2) +
+ & 2*Ea(EE0023)*Ginv(1,3) +
+ & 2*(Ea(EE0013) + 2*Ea(EE0000)*Ginv(1,3))*Ginv(2,3) +
+ & (Ea(EE0012) + 2*Ea(EE0000)*Ginv(1,2))*Ginv(3,3))
+ dE(EE1234) = -2*(Ea(EE0023)*Ginv(1,4) +
+ & (Ea(EE0014) + 2*Ea(EE0000)*Ginv(1,4))*Ginv(2,3) +
+ & Ea(EE0013)*Ginv(2,4) +
+ & Ginv(1,3)*(Ea(EE0024) + 2*Ea(EE0000)*Ginv(2,4)) +
+ & Ea(EE0012)*Ginv(3,4) +
+ & Ginv(1,2)*(Ea(EE0034) + 2*Ea(EE0000)*Ginv(3,4)))
+ dE(EE1244) = -2*(Ea(EE0044)*Ginv(1,2) +
+ & 2*Ea(EE0024)*Ginv(1,4) +
+ & 2*(Ea(EE0014) + 2*Ea(EE0000)*Ginv(1,4))*Ginv(2,4) +
+ & (Ea(EE0012) + 2*Ea(EE0000)*Ginv(1,2))*Ginv(4,4))
+ dE(EE1333) = -6*(Ea(EE0033)*Ginv(1,3) +
+ & (Ea(EE0013) + 2*Ea(EE0000)*Ginv(1,3))*Ginv(3,3))
+ dE(EE1334) = -2*(2*Ea(EE0034)*Ginv(1,3) +
+ & Ea(EE0033)*Ginv(1,4) +
+ & (Ea(EE0014) + 2*Ea(EE0000)*Ginv(1,4))*Ginv(3,3) +
+ & 2*(Ea(EE0013) + 2*Ea(EE0000)*Ginv(1,3))*Ginv(3,4))
+ dE(EE1344) = -2*(Ea(EE0044)*Ginv(1,3) +
+ & 2*Ea(EE0034)*Ginv(1,4) +
+ & 2*(Ea(EE0014) + 2*Ea(EE0000)*Ginv(1,4))*Ginv(3,4) +
+ & (Ea(EE0013) + 2*Ea(EE0000)*Ginv(1,3))*Ginv(4,4))
+ dE(EE1444) = -6*(Ea(EE0044)*Ginv(1,4) +
+ & (Ea(EE0014) + 2*Ea(EE0000)*Ginv(1,4))*Ginv(4,4))
+ dE(EE2222) = -12*Ginv(2,2)*(Ea(EE0022) + Ea(EE0000)*Ginv(2,2))
+ dE(EE2223) = -6*(Ea(EE0023)*Ginv(2,2) +
+ & (Ea(EE0022) + 2*Ea(EE0000)*Ginv(2,2))*Ginv(2,3))
+ dE(EE2224) = -6*(Ea(EE0024)*Ginv(2,2) +
+ & (Ea(EE0022) + 2*Ea(EE0000)*Ginv(2,2))*Ginv(2,4))
+ dE(EE2233) = -2*(Ea(EE0033)*Ginv(2,2) +
+ & 4*Ginv(2,3)*(Ea(EE0023) + Ea(EE0000)*Ginv(2,3)) +
+ & (Ea(EE0022) + 2*Ea(EE0000)*Ginv(2,2))*Ginv(3,3))
+ dE(EE2234) = -2*(Ea(EE0034)*Ginv(2,2) +
+ & 2*Ea(EE0024)*Ginv(2,3) +
+ & 2*(Ea(EE0023) + 2*Ea(EE0000)*Ginv(2,3))*Ginv(2,4) +
+ & (Ea(EE0022) + 2*Ea(EE0000)*Ginv(2,2))*Ginv(3,4))
+ dE(EE2244) = -2*(Ea(EE0044)*Ginv(2,2) +
+ & 4*Ginv(2,4)*(Ea(EE0024) + Ea(EE0000)*Ginv(2,4)) +
+ & (Ea(EE0022) + 2*Ea(EE0000)*Ginv(2,2))*Ginv(4,4))
+ dE(EE2333) = -6*(Ea(EE0033)*Ginv(2,3) +
+ & (Ea(EE0023) + 2*Ea(EE0000)*Ginv(2,3))*Ginv(3,3))
+ dE(EE2334) = -2*(2*Ea(EE0034)*Ginv(2,3) +
+ & Ea(EE0033)*Ginv(2,4) +
+ & (Ea(EE0024) + 2*Ea(EE0000)*Ginv(2,4))*Ginv(3,3) +
+ & 2*(Ea(EE0023) + 2*Ea(EE0000)*Ginv(2,3))*Ginv(3,4))
+ dE(EE2344) = -2*(Ea(EE0044)*Ginv(2,3) +
+ & 2*Ea(EE0034)*Ginv(2,4) +
+ & 2*(Ea(EE0024) + 2*Ea(EE0000)*Ginv(2,4))*Ginv(3,4) +
+ & (Ea(EE0023) + 2*Ea(EE0000)*Ginv(2,3))*Ginv(4,4))
+ dE(EE2444) = -6*(Ea(EE0044)*Ginv(2,4) +
+ & (Ea(EE0024) + 2*Ea(EE0000)*Ginv(2,4))*Ginv(4,4))
+ dE(EE3333) = -12*Ginv(3,3)*(Ea(EE0033) + Ea(EE0000)*Ginv(3,3))
+ dE(EE3334) = -6*(Ea(EE0034)*Ginv(3,3) +
+ & (Ea(EE0033) + 2*Ea(EE0000)*Ginv(3,3))*Ginv(3,4))
+ dE(EE3344) = -2*(Ea(EE0044)*Ginv(3,3) +
+ & 4*Ginv(3,4)*(Ea(EE0034) + Ea(EE0000)*Ginv(3,4)) +
+ & (Ea(EE0033) + 2*Ea(EE0000)*Ginv(3,3))*Ginv(4,4))
+ dE(EE3444) = -6*(Ea(EE0044)*Ginv(3,4) +
+ & (Ea(EE0034) + 2*Ea(EE0000)*Ginv(3,4))*Ginv(4,4))
+ dE(EE4444) = -12*Ginv(4,4)*(Ea(EE0044) + Ea(EE0000)*Ginv(4,4))
+ dE(EE0000) = Ea(EE0000)
+ dE(EE0011) = Ea(EE0011)
+ dE(EE0012) = Ea(EE0012)
+ dE(EE0013) = Ea(EE0013)
+ dE(EE0014) = Ea(EE0014)
+ dE(EE0022) = Ea(EE0022)
+ dE(EE0023) = Ea(EE0023)
+ dE(EE0024) = Ea(EE0024)
+ dE(EE0033) = Ea(EE0033)
+ dE(EE0034) = Ea(EE0034)
+ dE(EE0044) = Ea(EE0044)
ini = .TRUE.
do i = 1, Nee
if( abs(Ea(i) - Eb(i) - dE(i)) .gt.
& .5D0*maxdev*abs(Ea(i) + Eb(i)) ) then
if( ini ) then
#ifdef COMPLEXPARA
- print *, "Discrepancy in CEget:"
+ print *, "Discrepancy in EgetC:"
#else
print *, "Discrepancy in Eget:"
#endif
- call XDumpPara(5, para, ldpara, " ")
+ call XDumpPara(5, para, " ")
ini = .FALSE.
endif
print *, coeffname(i,5), " a =", Ea(i)
print *, coeffname(i,5), " b =", Eb(i) + dE(i)
endif
enddo
end
diff --git a/Looptools/E/ffdel5.F b/Looptools/E/ffdel5.F
--- a/Looptools/E/ffdel5.F
+++ b/Looptools/E/ffdel5.F
@@ -1,550 +1,551 @@
#include "externals.h"
+#include "types.h"
*###[ ffdel5:
subroutine ffdel5(del5,xpi,pDp)
***#[*comment:***********************************************************
* *
* Calculate del5(pDp) = det(si.sj) with *
* the momenta as follows: *
* p(1-5) = s(i) *
* p(5-10) = p(i) *
* p(11-15) = p(i)+p(i+1) *
* *
* Input: xpi(15) (real) *
* pDp(15,15) (real) *
* *
* Output: del5 (real) det(si.sj) *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
- DOUBLE PRECISION del5,xpi(15),pDp(15,15)
+ RealType del5,xpi(15),pDp(15,15)
*
* local variables:
*
integer mem,nperm,nsi
parameter(mem=10,nperm=1296,nsi=73)
integer i,j1,j2,j3,j4,j5,iperm(5,nperm),
+ imem,memarr(mem,3),memind,inow
- DOUBLE PRECISION s(nsi),xmax,del5p,xmaxp
+ RealType s(nsi),xmax,del5p,xmaxp
save iperm,memind,memarr,inow
*
* common blocks:
*
#include "ff.h"
* #] declarations:
* #[ data:
data memind /0/
data memarr /mem*0,mem*0,mem*1/
data inow /1/
#include "ffperm5.h"
* #] data:
* #[ out of memory:
*
* see if we know were to start, if not: go on as last time
*
do 5 i=1,mem
if ( id .eq. memarr(i,1) .and. idsub .eq. memarr(i,2) ) then
inow = memarr(i,3)
goto 6
endif
5 continue
6 continue
* #] out of memory:
* #[ calculations:
imem = inow
del5 = 0
xmax = 0
10 continue
*
* we only try the diagonal elements: top==bottom
*
j1 = iperm(1,inow)
j2 = iperm(2,inow)
j3 = iperm(3,inow)
j4 = iperm(4,inow)
j5 = iperm(5,inow)
*
* The following was generated with the Form program
* V p1,p2,p3,p4,p5;
* L f = (e_(p1,p2,p3,p4,p5))**2;
* Contract;
* print +s;
* .end
* plus the substituion //p#@1\./p#@2/=/pDp(j@1,j@2)/
*
* #[ terms:
s(1)=+ xpi(j1)*xpi(j2)*xpi(j3)*xpi(j4)*xpi(j5)
s(2)=- xpi(j1)*xpi(j2)*xpi(j3)*pDp(j4,j5)**2
s(3)=- xpi(j1)*xpi(j2)*pDp(j3,j4)**2*xpi(j5)
s(4)=+2*xpi(j1)*xpi(j2)*pDp(j3,j4)*pDp(j3,j5)*pDp(j4,j5)
s(5)=- xpi(j1)*xpi(j2)*pDp(j3,j5)**2*xpi(j4)
s(6)=- xpi(j1)*pDp(j2,j3)**2*xpi(j4)*xpi(j5)
s(7)=+ xpi(j1)*pDp(j2,j3)**2*pDp(j4,j5)**2
s(8)=+2*xpi(j1)*pDp(j2,j3)*pDp(j2,j4)*pDp(j3,j4)*xpi(j5)
s(9)=-2*xpi(j1)*pDp(j2,j3)*pDp(j2,j4)*pDp(j3,j5)*pDp(j4,j5)
s(10)=-2*xpi(j1)*pDp(j2,j3)*pDp(j2,j5)*pDp(j3,j4)*pDp(j4,j5)
s(11)=+2*xpi(j1)*pDp(j2,j3)*pDp(j2,j5)*pDp(j3,j5)*xpi(j4)
s(12)=- xpi(j1)*pDp(j2,j4)**2*xpi(j3)*xpi(j5)
s(13)=+ xpi(j1)*pDp(j2,j4)**2*pDp(j3,j5)**2
s(14)=+2*xpi(j1)*pDp(j2,j4)*pDp(j2,j5)*xpi(j3)*pDp(j4,j5)
s(15)=-2*xpi(j1)*pDp(j2,j4)*pDp(j2,j5)*pDp(j3,j4)*pDp(j3,j5)
s(16)=- xpi(j1)*pDp(j2,j5)**2*xpi(j3)*xpi(j4)
s(17)=+ xpi(j1)*pDp(j2,j5)**2*pDp(j3,j4)**2
s(18)=- pDp(j1,j2)**2*xpi(j3)*xpi(j4)*xpi(j5)
s(19)=+ pDp(j1,j2)**2*xpi(j3)*pDp(j4,j5)**2
s(20)=+ pDp(j1,j2)**2*pDp(j3,j4)**2*xpi(j5)
s(21)=-2*pDp(j1,j2)**2*pDp(j3,j4)*pDp(j3,j5)*pDp(j4,j5)
s(22)=+ pDp(j1,j2)**2*pDp(j3,j5)**2*xpi(j4)
s(23)=+2*pDp(j1,j2)*pDp(j1,j3)*pDp(j2,j3)*xpi(j4)*xpi(j5)
s(24)=-2*pDp(j1,j2)*pDp(j1,j3)*pDp(j2,j3)*pDp(j4,j5)**2
s(25)=-2*pDp(j1,j2)*pDp(j1,j3)*pDp(j2,j4)*pDp(j3,j4)*xpi(j5)
s(26)=+2*pDp(j1,j2)*pDp(j1,j3)*pDp(j2,j4)*pDp(j3,j5)*pDp(j4,j5)
s(27)=+2*pDp(j1,j2)*pDp(j1,j3)*pDp(j2,j5)*pDp(j3,j4)*pDp(j4,j5)
s(28)=-2*pDp(j1,j2)*pDp(j1,j3)*pDp(j2,j5)*pDp(j3,j5)*xpi(j4)
s(29)=-2*pDp(j1,j2)*pDp(j1,j4)*pDp(j2,j3)*pDp(j3,j4)*xpi(j5)
s(30)=+2*pDp(j1,j2)*pDp(j1,j4)*pDp(j2,j3)*pDp(j3,j5)*pDp(j4,j5)
s(31)=+2*pDp(j1,j2)*pDp(j1,j4)*pDp(j2,j4)*xpi(j3)*xpi(j5)
s(32)=-2*pDp(j1,j2)*pDp(j1,j4)*pDp(j2,j4)*pDp(j3,j5)**2
s(33)=-2*pDp(j1,j2)*pDp(j1,j4)*pDp(j2,j5)*xpi(j3)*pDp(j4,j5)
s(34)=+2*pDp(j1,j2)*pDp(j1,j4)*pDp(j2,j5)*pDp(j3,j4)*pDp(j3,j5)
s(35)=+2*pDp(j1,j2)*pDp(j1,j5)*pDp(j2,j3)*pDp(j3,j4)*pDp(j4,j5)
s(36)=-2*pDp(j1,j2)*pDp(j1,j5)*pDp(j2,j3)*pDp(j3,j5)*xpi(j4)
s(37)=-2*pDp(j1,j2)*pDp(j1,j5)*pDp(j2,j4)*xpi(j3)*pDp(j4,j5)
s(38)=+2*pDp(j1,j2)*pDp(j1,j5)*pDp(j2,j4)*pDp(j3,j4)*pDp(j3,j5)
s(39)=+2*pDp(j1,j2)*pDp(j1,j5)*pDp(j2,j5)*xpi(j3)*xpi(j4)
s(40)=-2*pDp(j1,j2)*pDp(j1,j5)*pDp(j2,j5)*pDp(j3,j4)**2
s(41)=- pDp(j1,j3)**2*xpi(j2)*xpi(j4)*xpi(j5)
s(42)=+ pDp(j1,j3)**2*xpi(j2)*pDp(j4,j5)**2
s(43)=+ pDp(j1,j3)**2*pDp(j2,j4)**2*xpi(j5)
s(44)=-2*pDp(j1,j3)**2*pDp(j2,j4)*pDp(j2,j5)*pDp(j4,j5)
s(45)=+ pDp(j1,j3)**2*pDp(j2,j5)**2*xpi(j4)
s(46)=+2*pDp(j1,j3)*pDp(j1,j4)*xpi(j2)*pDp(j3,j4)*xpi(j5)
s(47)=-2*pDp(j1,j3)*pDp(j1,j4)*xpi(j2)*pDp(j3,j5)*pDp(j4,j5)
s(48)=-2*pDp(j1,j3)*pDp(j1,j4)*pDp(j2,j3)*pDp(j2,j4)*xpi(j5)
s(49)=+2*pDp(j1,j3)*pDp(j1,j4)*pDp(j2,j3)*pDp(j2,j5)*pDp(j4,j5)
s(50)=+2*pDp(j1,j3)*pDp(j1,j4)*pDp(j2,j4)*pDp(j2,j5)*pDp(j3,j5)
s(51)=-2*pDp(j1,j3)*pDp(j1,j4)*pDp(j2,j5)**2*pDp(j3,j4)
s(52)=-2*pDp(j1,j3)*pDp(j1,j5)*xpi(j2)*pDp(j3,j4)*pDp(j4,j5)
s(53)=+2*pDp(j1,j3)*pDp(j1,j5)*xpi(j2)*pDp(j3,j5)*xpi(j4)
s(54)=+2*pDp(j1,j3)*pDp(j1,j5)*pDp(j2,j3)*pDp(j2,j4)*pDp(j4,j5)
s(55)=-2*pDp(j1,j3)*pDp(j1,j5)*pDp(j2,j3)*pDp(j2,j5)*xpi(j4)
s(56)=-2*pDp(j1,j3)*pDp(j1,j5)*pDp(j2,j4)**2*pDp(j3,j5)
s(57)=+2*pDp(j1,j3)*pDp(j1,j5)*pDp(j2,j4)*pDp(j2,j5)*pDp(j3,j4)
s(58)=- pDp(j1,j4)**2*xpi(j2)*xpi(j3)*xpi(j5)
s(59)=+ pDp(j1,j4)**2*xpi(j2)*pDp(j3,j5)**2
s(60)=+ pDp(j1,j4)**2*pDp(j2,j3)**2*xpi(j5)
s(61)=-2*pDp(j1,j4)**2*pDp(j2,j3)*pDp(j2,j5)*pDp(j3,j5)
s(62)=+ pDp(j1,j4)**2*pDp(j2,j5)**2*xpi(j3)
s(63)=+2*pDp(j1,j4)*pDp(j1,j5)*xpi(j2)*xpi(j3)*pDp(j4,j5)
s(64)=-2*pDp(j1,j4)*pDp(j1,j5)*xpi(j2)*pDp(j3,j4)*pDp(j3,j5)
s(65)=-2*pDp(j1,j4)*pDp(j1,j5)*pDp(j2,j3)**2*pDp(j4,j5)
s(66)=+2*pDp(j1,j4)*pDp(j1,j5)*pDp(j2,j3)*pDp(j2,j4)*pDp(j3,j5)
s(67)=+2*pDp(j1,j4)*pDp(j1,j5)*pDp(j2,j3)*pDp(j2,j5)*pDp(j3,j4)
s(68)=-2*pDp(j1,j4)*pDp(j1,j5)*pDp(j2,j4)*pDp(j2,j5)*xpi(j3)
s(69)=- pDp(j1,j5)**2*xpi(j2)*xpi(j3)*xpi(j4)
s(70)=+ pDp(j1,j5)**2*xpi(j2)*pDp(j3,j4)**2
s(71)=+ pDp(j1,j5)**2*pDp(j2,j3)**2*xpi(j4)
s(72)=-2*pDp(j1,j5)**2*pDp(j2,j3)*pDp(j2,j4)*pDp(j3,j4)
s(73)=+ pDp(j1,j5)**2*pDp(j2,j4)**2*xpi(j3)
* #] terms:
*
del5p = 0
xmaxp = 0
do 20 i=1,nsi
del5p = del5p + s(i)
xmaxp = max(xmaxp,abs(s(i)))
20 continue
if ( abs(del5p) .lt. xloss**2*xmaxp ) then
if ( inow .eq. imem .or. xmaxp .lt. xmax ) then
del5 = del5p
xmax = xmaxp
endif
inow = inow + 1
if ( inow .gt. nperm ) inow = 1
if ( inow .eq. imem ) goto 800
goto 10
endif
del5 = del5p
xmax = xmaxp
* #] calculations:
* #[ into memory:
800 continue
memind = memind + 1
if ( memind .gt. mem ) memind = 1
memarr(memind,1) = id
memarr(memind,2) = idsub
memarr(memind,3) = inow
* #] into memory:
return
*###] ffdel5:
end
*###[ ffdl4p:
subroutine ffdl4p(dl4p,piDpj,ii)
***#[*comment:***********************************************************
* calculate in a numerically stable way *
* *
* p1 p2 p3 p4 *
* delta *
* p1 p2 p3 p4 *
* *
* with pn = xpi(ii(n)), n=1,4 *
* p5 = -p1-p2-p3-p4 *
* xpi(ii(n+5)) = pn+p(n+1), n=1,5 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ii(10)
- DOUBLE PRECISION dl4p,piDpj(15,15)
+ RealType dl4p,piDpj(15,15)
*
* local variables
*
integer i,j,k,jj(8),iperm(4,60)
- DOUBLE PRECISION s(24),som,xmax,smax
+ RealType s(24),som,xmax,smax
*
* common blocks
*
#include "ff.h"
*
* data (the permutations with 2 from each (1-5) and (6-10) are
* still lacking)
*
data ((iperm(j,i),j=1,4),i=1,35)
+ /1,2,3,4, 2,3,4,5, 3,4,5,1, 4,5,1,2, 5,1,2,3,
+ 6,2,3,4, 4,5,6,2, 5,6,2,3,
+ 1,6,3,4, 4,5,1,6, 5,1,6,3,
+ 1,7,3,4, 7,3,4,5, 5,1,7,3,
+ 1,2,7,4, 2,7,4,5, 5,1,2,7,
+ 1,2,8,4, 2,8,4,5, 8,4,5,1,
+ 1,2,3,8, 2,3,8,5, 3,8,5,1,
+ 2,3,9,5, 3,9,5,1, 9,5,1,2,
+ 2,3,4,9, 3,4,9,1, 4,9,1,2,
+ 3,4,10,1, 4,10,1,2, 10,1,2,3,
+ 3,4,5,10, 4,5,10,2, 5,10,2,3/
data ((iperm(j,i),j=1,4),i=36,60)
+ / 8,9,1,6, 1,6,7,8,
+ 8,9,10,1, 10,1,7,8,
+ 2,7,8,9, 9,10,2,7,
+ 6,2,8,9, 9,10,6,2,
+ 3,8,9,10, 10,6,3,8,
+ 7,3,9,10, 10,6,7,3,
+ 6,7,4,9, 4,9,10,6,
+ 6,7,8,4, 8,4,10,6,
+ 7,8,5,10, 5,10,6,7,
+ 7,8,9,5, 9,5,6,7,
+ 6,7,8,9, 7,8,9,10, 8,9,10,6, 9,10,6,7, 10,6,7,8/
* #] declarations:
* #[ calculations:
*
* for the time being we just try the (60) diagonal elemnts.
*
xmax = 0
do 100 i=1,60
jj(1) = ii(iperm(1,i))
jj(2) = ii(iperm(2,i))
jj(3) = ii(iperm(3,i))
jj(4) = ii(iperm(4,i))
s( 1) = +piDpj(jj(1),jj(1))*piDpj(jj(2),jj(2))*
+ piDpj(jj(3),jj(3))*piDpj(jj(4),jj(4))
s( 2) = +piDpj(jj(2),jj(1))*piDpj(jj(3),jj(2))*
+ piDpj(jj(1),jj(3))*piDpj(jj(4),jj(4))
s( 3) = s(2)
* s( 3) = +piDpj(jj(3),jj(1))*piDpj(jj(1),jj(2))*
* + piDpj(jj(2),jj(3))*piDpj(jj(4),jj(4))
s( 4) = -piDpj(jj(1),jj(1))*piDpj(jj(3),jj(2))*
+ piDpj(jj(2),jj(3))*piDpj(jj(4),jj(4))
s( 5) = -piDpj(jj(3),jj(1))*piDpj(jj(2),jj(2))*
+ piDpj(jj(1),jj(3))*piDpj(jj(4),jj(4))
s( 6) = -piDpj(jj(2),jj(1))*piDpj(jj(1),jj(2))*
+ piDpj(jj(3),jj(3))*piDpj(jj(4),jj(4))
s( 7) = -piDpj(jj(1),jj(1))*piDpj(jj(2),jj(2))*
+ piDpj(jj(4),jj(3))*piDpj(jj(3),jj(4))
s( 8) = -piDpj(jj(2),jj(1))*piDpj(jj(4),jj(2))*
+ piDpj(jj(1),jj(3))*piDpj(jj(3),jj(4))
s( 9) = -piDpj(jj(4),jj(1))*piDpj(jj(1),jj(2))*
+ piDpj(jj(2),jj(3))*piDpj(jj(3),jj(4))
s(10) = +piDpj(jj(1),jj(1))*piDpj(jj(4),jj(2))*
+ piDpj(jj(2),jj(3))*piDpj(jj(3),jj(4))
s(11) = +piDpj(jj(4),jj(1))*piDpj(jj(2),jj(2))*
+ piDpj(jj(1),jj(3))*piDpj(jj(3),jj(4))
s(12) = +piDpj(jj(2),jj(1))*piDpj(jj(1),jj(2))*
+ piDpj(jj(4),jj(3))*piDpj(jj(3),jj(4))
s(13) = -piDpj(jj(1),jj(1))*piDpj(jj(4),jj(2))*
+ piDpj(jj(3),jj(3))*piDpj(jj(2),jj(4))
s(14) = -piDpj(jj(4),jj(1))*piDpj(jj(3),jj(2))*
+ piDpj(jj(1),jj(3))*piDpj(jj(2),jj(4))
s(15) = s(8)
* s(15) = -piDpj(jj(3),jj(1))*piDpj(jj(1),jj(2))*
* + piDpj(jj(4),jj(3))*piDpj(jj(2),jj(4))
s(16) = s(10)
* s(16) = +piDpj(jj(1),jj(1))*piDpj(jj(3),jj(2))*
* + piDpj(jj(4),jj(3))*piDpj(jj(2),jj(4))
s(17) = +piDpj(jj(3),jj(1))*piDpj(jj(4),jj(2))*
+ piDpj(jj(1),jj(3))*piDpj(jj(2),jj(4))
s(18) = +piDpj(jj(4),jj(1))*piDpj(jj(1),jj(2))*
+ piDpj(jj(3),jj(3))*piDpj(jj(2),jj(4))
s(19) = -piDpj(jj(4),jj(1))*piDpj(jj(2),jj(2))*
+ piDpj(jj(3),jj(3))*piDpj(jj(1),jj(4))
s(20) = s(9)
* s(20) = -piDpj(jj(2),jj(1))*piDpj(jj(3),jj(2))*
* + piDpj(jj(4),jj(3))*piDpj(jj(1),jj(4))
s(21) = s(14)
* s(21) = -piDpj(jj(3),jj(1))*piDpj(jj(4),jj(2))*
* + piDpj(jj(2),jj(3))*piDpj(jj(1),jj(4))
s(22) = +piDpj(jj(4),jj(1))*piDpj(jj(3),jj(2))*
+ piDpj(jj(2),jj(3))*piDpj(jj(1),jj(4))
s(23) = s(11)
* s(23) = +piDpj(jj(3),jj(1))*piDpj(jj(2),jj(2))*
* + piDpj(jj(4),jj(3))*piDpj(jj(1),jj(4))
s(24) = s(18)
* s(24) = +piDpj(jj(2),jj(1))*piDpj(jj(4),jj(2))*
* + piDpj(jj(3),jj(3))*piDpj(jj(1),jj(4))
som = 0
smax = 0
do 80 k=1,24
som = som + s(k)
smax = max(smax,abs(som))
80 continue
if ( i .eq. 1 .or. smax .lt. xmax ) then
dl4p = som
xmax = smax
endif
if ( abs(dl4p) .ge. xloss**2*smax ) goto 110
100 continue
110 continue
* #] calculations:
*###] ffdl4p:
end
*###[ ffdl4r:
subroutine ffdl4r(dl4r,piDpj,miss)
***#[*comment:***********************************************************
* calculate in a numerically stable way *
* *
* s1 s2 s3 s4 *
* delta *
* p1 p2 p3 p4 *
* *
* with s(miss) NOT included *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer miss
- DOUBLE PRECISION dl4r,piDpj(15,15)
+ RealType dl4r,piDpj(15,15)
*
* local variables
*
integer i,j,k,ii(4),jj(4),ipermp(4,125),iperms(4,125),
+ iplace(11,5),minus(125),mem,msign
parameter(mem=45)
integer memarr(mem,4),inow,jnow,imem,jmem,memind
- DOUBLE PRECISION s(24),som,xmax,smax
+ RealType s(24),som,xmax,smax
save ipermp,iperms,iplace,minus,memarr,inow,jnow,memind
*
* common blocks
*
#include "ff.h"
* #] declarations:
* #[ data:
data memind /0/
data memarr /mem*0,mem*0,mem*1,mem*1/
data inow,jnow /1,1/
*
* data (see getpermp.for)
*
data ipermp/
+ 1,2,3,4,1,2,5,3,1,2,3,8,1,2,10,3,1,2,4,5,1,2,7,4,1,2,8,4,1,2,4,
+ 9,1,2,4,10,1,2,5,7,1,2,9,5,1,2,7,8,1,2,10,7,1,2,8,9,1,2,9,10,1,
+ 3,5,4,1,3,4,6,1,3,4,7,1,3,9,4,1,3,10,4,1,3,6,5,1,3,7,5,1,3,5,8,
+ 1,3,5,9,1,3,8,6,1,3,6,10,1,3,8,7,1,3,7,10,1,3,9,8,1,3,10,8,1,3,
+ 10,9,1,4,5,6,1,4,8,5,1,4,6,7,1,4,6,8,1,4,9,6,1,4,10,6,1,4,7,8,1,
+ 4,8,9,1,4,8,10,1,5,7,6,1,5,6,9,1,5,8,7,1,5,9,8,1,6,7,8,1,6,10,7,
+ 1,6,8,9,1,6,9,10,1,7,10,8,1,8,10,9,2,3,4,5,2,3,6,4,2,3,4,9,2,3,
+ 5,6,2,3,8,5,2,3,9,5,2,3,5,10,2,3,6,8,2,3,10,6,2,3,8,9,2,3,9,10,
+ 2,4,6,5,2,4,5,7,2,4,5,8,2,4,10,5,2,4,7,6,2,4,8,6,2,4,6,9,2,4,6,
+ 10,2,4,9,7,2,4,9,8,2,4,10,9,2,5,6,7,2,5,9,6,2,5,7,8,2,5,7,9,2,5,
+ 10,7,2,5,8,9,2,5,9,10,2,6,8,7,2,6,7,10,2,6,9,8,2,6,10,9,2,7,8,9,
+ 2,7,9,10,3,4,7,5,3,4,5,10,3,4,6,7,3,4,10,6,3,4,7,9,3,4,9,10,3,5,
+ 7,6,3,5,6,10,3,5,8,7,3,5,9,7,3,5,7,10,3,5,10,8,3,5,10,9,3,6,7,8,
+ 3,6,10,7,3,6,8,10,3,7,9,8,3,7,10,9,3,8,9,10,4,5,6,7,4,5,10,6,4,
+ 5,7,8,4,5,8,10,4,6,8,7,4,6,7,9,4,6,10,8,4,6,9,10,4,7,8,9,4,8,10,
+ 9,5,6,9,7,5,6,7,10,5,6,10,9,5,7,9,8,5,7,8,10,5,8,9,10,6,7,8,9,6,
+ 7,10,8,6,7,9,10,6,8,10,9,7,8,9,10/
data iperms/
+ 1,2,3,4,1,2,3,7,1,2,8,3,1,2,3,10,1,2,6,4,1,2,4,7,1,2,4,9,1,2,6,7
+ ,1,2,8,6,1,2,6,10,1,2,7,8,1,2,7,9,1,2,10,7,1,2,9,8,1,2,10,9,1,3,
+ 4,5,1,3,6,4,1,3,10,4,1,3,7,5,1,3,5,8,1,3,10,5,1,3,6,7,1,3,8,6,1,
+ 3,6,10,1,3,10,7,1,3,8,10,1,4,5,6,1,4,7,5,1,4,9,5,1,4,6,7,1,4,6,9
+ ,1,4,6,10,1,4,10,7,1,4,10,9,1,5,6,7,1,5,8,6,1,5,6,10,1,5,7,8,1,5
+ ,7,9,1,5,10,7,1,5,9,8,1,5,10,9,1,6,8,7,1,6,9,7,1,6,8,9,1,6,8,10,
+ 1,6,9,10,1,7,10,8,1,7,10,9,1,8,9,10,2,3,4,5,2,3,8,4,2,3,9,4,2,3,
+ 7,5,2,3,5,8,2,3,10,5,2,3,8,7,2,3,9,7,2,3,8,9,2,3,8,10,2,3,9,10,2
+ ,4,5,6,2,4,7,5,2,4,9,5,2,4,6,8,2,4,6,9,2,4,8,7,2,4,9,7,2,4,8,9,2
+ ,5,6,7,2,5,8,6,2,5,6,10,2,5,7,8,2,5,7,9,2,5,10,7,2,5,9,8,2,5,10,
+ 9,2,6,8,7,2,6,9,7,2,6,8,9,2,6,8,10,2,6,9,10,2,7,10,8,2,7,10,9,2,
+ 8,9,10,3,4,5,6,3,4,8,5,3,4,9,5,3,4,5,10,3,4,6,8,3,4,6,9,3,4,10,8
+ ,3,4,10,9,3,5,6,7,3,5,8,6,3,5,6,10,3,5,7,8,3,5,7,9,3,5,10,7,3,5,
+ 9,8,3,5,10,9,3,6,8,7,3,6,9,7,3,6,8,9,3,6,8,10,3,6,9,10,3,7,10,8,
+ 3,7,10,9,3,8,9,10,4,5,6,7,4,5,8,6,4,5,6,10,4,5,7,8,4,5,7,9,4,5,1
+ 0,7,4,5,9,8,4,5,10,9,4,6,8,7,4,6,9,7,4,6,8,9,4,6,8,10,4,6,9,10,4
+ ,7,10,8,4,7,10,9,4,8,9,10/
data iplace /
+ 2,3,4,5, 07,08,09,15, +12,+13, 17,
+ 1,3,4,5, 11,08,09,10, -14,+13, 18,
+ 1,2,4,5, 06,12,09,10, -14,-15, 19,
+ 1,2,3,5, 06,07,13,10, +11,-15, 20,
+ 1,2,3,4, 06,07,08,14, +11,+12, 16/
data minus /
+ +1,+1,+1,+1,+1,+1,-1,+1,+1,+1,+1,-1,+1,-1,-1,+1,
+ +1,+1,+1,+1,+1,+1,+1,+1,+1,+1,+1,+1,-1,+1,-1,+1,
+ +1,-1,+1,+1,+1,+1,-1,+1,-1,-1,+1,-1,-1,+1,-1,+1,
+ -1,-1,+1,+1,-1,+1,+1,+1,+1,-1,-1,+1,-1,+1,+1,-1,
+ +1,-1,+1,-1,-1,+1,+1,+1,+1,-1,+1,-1,-1,+1,-1,-1,
+ +1,-1,+1,-1,-1,+1,+1,-1,+1,+1,-1,+1,-1,+1,+1,+1,
+ +1,-1,+1,-1,-1,+1,-1,-1,+1,-1,+1,-1,-1,+1,+1,+1,
+ +1,-1,+1,-1,-1,+1,-1,-1,+1,-1,+1,-1,-1/
* #] data:
* #[ out of memory:
*
* see if we know were to start, if not: go on as last time
*
do 5 i=1,mem
if ( id .eq. memarr(i,1) .and. idsub .eq. memarr(i,2) ) then
inow = memarr(i,3)
jnow = memarr(i,4)
goto 6
endif
5 continue
6 continue
* #] out of memory:
* #[ calculations:
*
* loop over all permutations of the si and the pi -
* we have 125*125 = a lot of possibilities before we give up ....
* 15-feb-1993: well, let's only consider 25 at a time, otherwise
* the time spent here becomes ludicrous
*
imem = inow
jmem = jnow
dl4r = 0
xmax = 0
*
do 110 i=1,5
ii(1) = abs(iplace((iperms(1,inow)),miss))
ii(2) = abs(iplace((iperms(2,inow)),miss))
ii(3) = abs(iplace((iperms(3,inow)),miss))
ii(4) = abs(iplace((iperms(4,inow)),miss))
msign = sign(1,iplace((iperms(1,inow)),miss))*
+ sign(1,iplace((iperms(2,inow)),miss))*
+ sign(1,iplace((iperms(3,inow)),miss))*
+ sign(1,iplace((iperms(4,inow)),miss))
do 100 j=1,5
jj(1) = ipermp(1,jnow) + 5
jj(2) = ipermp(2,jnow) + 5
jj(3) = ipermp(3,jnow) + 5
jj(4) = ipermp(4,jnow) + 5
*
s( 1) = +piDpj(ii(1),jj(1))*piDpj(ii(2),jj(2))*
+ piDpj(ii(3),jj(3))*piDpj(ii(4),jj(4))
s( 2) = +piDpj(ii(2),jj(1))*piDpj(ii(3),jj(2))*
+ piDpj(ii(1),jj(3))*piDpj(ii(4),jj(4))
s( 3) = +piDpj(ii(3),jj(1))*piDpj(ii(1),jj(2))*
+ piDpj(ii(2),jj(3))*piDpj(ii(4),jj(4))
s( 4) = -piDpj(ii(1),jj(1))*piDpj(ii(3),jj(2))*
+ piDpj(ii(2),jj(3))*piDpj(ii(4),jj(4))
s( 5) = -piDpj(ii(3),jj(1))*piDpj(ii(2),jj(2))*
+ piDpj(ii(1),jj(3))*piDpj(ii(4),jj(4))
s( 6) = -piDpj(ii(2),jj(1))*piDpj(ii(1),jj(2))*
+ piDpj(ii(3),jj(3))*piDpj(ii(4),jj(4))
*
s( 7) = -piDpj(ii(1),jj(1))*piDpj(ii(2),jj(2))*
+ piDpj(ii(4),jj(3))*piDpj(ii(3),jj(4))
s( 8) = -piDpj(ii(2),jj(1))*piDpj(ii(4),jj(2))*
+ piDpj(ii(1),jj(3))*piDpj(ii(3),jj(4))
s( 9) = -piDpj(ii(4),jj(1))*piDpj(ii(1),jj(2))*
+ piDpj(ii(2),jj(3))*piDpj(ii(3),jj(4))
s(10) = +piDpj(ii(1),jj(1))*piDpj(ii(4),jj(2))*
+ piDpj(ii(2),jj(3))*piDpj(ii(3),jj(4))
s(11) = +piDpj(ii(4),jj(1))*piDpj(ii(2),jj(2))*
+ piDpj(ii(1),jj(3))*piDpj(ii(3),jj(4))
s(12) = +piDpj(ii(2),jj(1))*piDpj(ii(1),jj(2))*
+ piDpj(ii(4),jj(3))*piDpj(ii(3),jj(4))
*
s(13) = -piDpj(ii(1),jj(1))*piDpj(ii(4),jj(2))*
+ piDpj(ii(3),jj(3))*piDpj(ii(2),jj(4))
s(14) = -piDpj(ii(4),jj(1))*piDpj(ii(3),jj(2))*
+ piDpj(ii(1),jj(3))*piDpj(ii(2),jj(4))
s(15) = -piDpj(ii(3),jj(1))*piDpj(ii(1),jj(2))*
+ piDpj(ii(4),jj(3))*piDpj(ii(2),jj(4))
s(16) = +piDpj(ii(1),jj(1))*piDpj(ii(3),jj(2))*
+ piDpj(ii(4),jj(3))*piDpj(ii(2),jj(4))
s(17) = +piDpj(ii(3),jj(1))*piDpj(ii(4),jj(2))*
+ piDpj(ii(1),jj(3))*piDpj(ii(2),jj(4))
s(18) = +piDpj(ii(4),jj(1))*piDpj(ii(1),jj(2))*
+ piDpj(ii(3),jj(3))*piDpj(ii(2),jj(4))
*
s(19) = -piDpj(ii(4),jj(1))*piDpj(ii(2),jj(2))*
+ piDpj(ii(3),jj(3))*piDpj(ii(1),jj(4))
s(20) = -piDpj(ii(2),jj(1))*piDpj(ii(3),jj(2))*
+ piDpj(ii(4),jj(3))*piDpj(ii(1),jj(4))
s(21) = -piDpj(ii(3),jj(1))*piDpj(ii(4),jj(2))*
+ piDpj(ii(2),jj(3))*piDpj(ii(1),jj(4))
s(22) = +piDpj(ii(4),jj(1))*piDpj(ii(3),jj(2))*
+ piDpj(ii(2),jj(3))*piDpj(ii(1),jj(4))
s(23) = +piDpj(ii(3),jj(1))*piDpj(ii(2),jj(2))*
+ piDpj(ii(4),jj(3))*piDpj(ii(1),jj(4))
s(24) = +piDpj(ii(2),jj(1))*piDpj(ii(4),jj(2))*
+ piDpj(ii(3),jj(3))*piDpj(ii(1),jj(4))
*
som = 0
smax = 0
do 80 k=1,24
som = som + s(k)
smax = max(smax,abs(som))
80 continue
if ( ( inow .eq. imem .and. jnow .eq. jmem ) .or.
+ smax .lt. xmax ) then
dl4r = msign*minus(inow)*som
xmax = smax
endif
if ( abs(dl4r) .ge. xloss**2*smax ) goto 120
* increase with something that is relative prime to 125 so that
* eventually we cover all possibilities, but with a good
* scatter.
jnow = jnow + 49
if ( jnow .gt. 125 ) jnow = jnow - 125
100 continue
* again, a number relative prime to 125 and a few times smaller
inow = inow + 49
if ( inow .gt. 125 ) inow = inow - 125
110 continue
120 continue
* #] calculations:
* #[ into memory:
memind = memind + 1
if ( memind .gt. mem ) memind = 1
memarr(memind,1) = id
memarr(memind,2) = idsub
memarr(memind,3) = inow
memarr(memind,4) = jnow
* #] into memory:
*###] ffdl4r:
end
diff --git a/Looptools/E/ffxe0.F b/Looptools/E/ffxe0.F
--- a/Looptools/E/ffxe0.F
+++ b/Looptools/E/ffxe0.F
@@ -1,835 +1,836 @@
#include "externals.h"
+#include "types.h"
* $Id: ffxe0.f,v 1.4 1996/01/10 15:36:51 gj Exp $
*###[ ffxe0:
subroutine ffxe0(ce0,cd0i,xpi,ier)
***#[*comment:***********************************************************
* *
* calculate *
* *
* 1 / / \-1*
* e0= -----\dq |(q^2-m_1^2)((q+p_1)^2-m_2^2)...((q-p_5)^2-m_5^2| *
* ipi^2/ \ / *
* *
* following the five four-point-function method in .... *
* As an extra the five fourpoint function Di are also returned *
* if ( ldot ) the dotproducts are left behind in fpij5(15,15) in *
* /ffdot/ and the external determinants fdel4 and fdl3i(5) in *
* /ffdel/. *
* *
* Input: xpi = m_i^2 (real) i=1,5 *
* xpi = p_i.p_i (real) i=6,10 (note: B&D metric) *
* xpi = (p_i+p_{i+1})^2 (r) i=11,15 *
* xpi = (p_i+p_{i+2})^2 (r) i=16,20 OR 0 *
* *
* Output: ce0 (complex) *
* cd0i(5) (complex) D0 with s_i missing *
* ier (integr) 0=ok 1=inaccurate 2=error *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE PRECISION xpi(20)
- DOUBLE COMPLEX ce0,cd0i(5)
+ RealType xpi(20)
+ ComplexType ce0,cd0i(5)
integer ier
*
* local variables
*
integer i,j,NMIN,NMAX,ier0,i6,i7,i8,i9
parameter(NMIN=15,NMAX=20)
- DOUBLE PRECISION dpipj(NMIN,NMAX),xmax
+ RealType dpipj(NMIN,NMAX),xmax
logical lp5(NMAX-NMIN)
*
* common blocks:
*
#include "ff.h"
* #] declarations:
* #[ get differences:
*
* simulate the differences in the masses etc..
*
* first p16-p20
*
do 5 i=1,5
if ( xpi(i+15) .eq. 0 ) then
i6 = i+5
i7 = i6+1
if ( i7 .ge. 11 ) i7 = 6
i8 = i7+1
if ( i8 .ge. 11 ) i8 = 6
i9 = i8+1
if ( i9 .ge. 11 ) i9 = 6
xpi(i+15) = xpi(i6)+xpi(i7)+xpi(i8)-xpi(i6+5)-xpi(i7+5)+
+ xpi(i9+5)
xmax = max(abs(xpi(i6)),abs(xpi(i7)),abs(xpi(i8)),abs(
+ xpi(i6+5)),abs(xpi(i7+5)),abs(xpi(i9+5)))
if ( abs(xpi(i+15)) .lt. xloss*xmax )
+ call ffwarn(168,ier,xpi(i+15),xmax)
lp5(i) = .TRUE.
else
lp5(i) = .FALSE.
endif
5 continue
*
* next the differences
*
ier0 = 0
do 40 i=1,NMAX
do 30 j=1,NMIN
dpipj(j,i) = xpi(j) - xpi(i)
30 continue
40 continue
* #] get differences:
* #[ call ffxe0a:
call ffxe0a(ce0,cd0i,xpi,dpipj,ier)
* #] call ffxe0a:
* #[ clean up:
do 90 i=1,5
if ( lp5(i) ) then
xpi(i+NMIN) = 0
endif
90 continue
* #] clean up:
*###] ffxe0:
end
*###[ ffxe0a:
subroutine ffxe0a(ce0,cd0i,xpi,dpipj,ier)
***#[*comment:***********************************************************
* *
* calculate *
* *
* 1 / / \-1*
* e0= -----\dq |(q^2-m_1^2)((q+p_1)^2-m_2^2)...((q-p_5)^2-m_5^2| *
* ipi^2/ \ / *
* *
* following the five four-point-function method in .... *
* As an extra the five fourpoint function Di are also returned *
* if ( ldot ) the dotproducts are left behind in fpij5(15,15) in *
* /ffdot/ and the external determinants fdel4 and fdl3i(5) in *
* /ffdel/. *
* *
* Input: xpi = m_i^2 (real) i=1,5 *
* xpi = p_i.p_i (real) i=6,10 (note: B&D metric) *
* xpi = (p_i+p_{i+1})^2 (r) i=11,15 *
* xpi = (p_i+p_{i+2})^2 (r) i=16,20 *
* dpipj(15,20) (real) = pi(i) - pi(j) *
* *
* Output: ce0 (complex) *
* cd0i(5) (complex) D0 with s_i missing *
* ier (integer) <50:lost # digits 100=error *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE COMPLEX ce0,cd0i(5)
- DOUBLE PRECISION xpi(20),dpipj(15,20)
+ ComplexType ce0,cd0i(5)
+ RealType xpi(20),dpipj(15,20)
*
* local variables
*
integer i,j,ii(10),ii4(6),ieri(5),ier0,imin,itype,ndiv,idone,
+ ier1
logical ldel2s
- DOUBLE COMPLEX c,cfac,cs,csum
- DOUBLE PRECISION dl5s,dl4p,xpi4(13),dpipj4(10,13),piDpj4(10,10),
+ ComplexType c,cfac,cs,csum
+ RealType dl5s,dl4p,xpi4(13),dpipj4(10,13),piDpj4(10,10),
+ absc,xmax,piDpj(15,15),xqi4(13),dqiqj4(10,13),
+ qiDqj4(10,10),del2s,xmx5(5),dl4ri(5)
save ii4
*
* common blocks:
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
*
* data
*
data ii4 /5,6,7,8,9,10/
*
* #] declarations:
* #[ initialisations:
ndiv = 0
idsub = 0
ce0 = 0
do 1 i=1,5
cd0i(i) = 0
1 continue
* #] initialisations:
* #[ calculations:
*
idsub = idsub + 1
call ffdot5(piDpj,xpi,dpipj,ier)
if ( ldot ) then
do 6 i=1,15
do 5 j=1,15
fpij5(j,i) = piDpj(j,i)
5 continue
6 continue
do 10 i=1,10
ii(i) = i+5
10 continue
idsub = idsub + 1
ier0 = 0
call ffdl4p(dl4p,piDpj,ii)
* if ( dl4p .lt. 0 ) then
* call fferr(57,ier)
* endif
fdel4 = dl4p
endif
idsub = idsub + 1
call ffdel5(dl5s,xpi,piDpj)
*
do 40 i=1,5
ieri(i) = ier
40 continue
*
do 100 i=1,5
*
* get the coefficient determinant
*
idsub = idsub + 1
call ffdl4r(dl4ri(i),piDpj,i)
*
* get four-point momenta
*
call ffpi54(xpi4,dpipj4,piDpj4,xpi,dpipj,piDpj,i)
*
* first try IR divergent function to avoid error messages from ffrot4
*
ier1 = ieri(i)
call ffxdir(cs,cfac,idone,xpi4,dpipj4,6,ndiv,ier1)
if ( idone .gt. 0 ) then
* done
xmax = abs(cs)*10d0**(-mod((ier1-ieri(i)),50))
else
*
* rotate to calculable posistion
*
call ffrot4(irota4,del2s,xqi4,dqiqj4,qiDqj4,xpi4,dpipj4,
+ piDpj4,5,itype,ieri(i))
if ( itype .lt. 0 ) then
print *,'ffxe0: error: Cannot handle this ',
+ ' 4point masscombination yet:'
print *,(xpi(j),j=1,20)
return
endif
if ( itype .eq. 1 ) then
ldel2s = .TRUE.
isgnal = +1
print *,'ffxe0a: Cannot handle del2s = 0 yet'
stop
else
ldel2s = .FALSE.
endif
if ( itype .eq. 2 ) then
print *,'ffxe0a: no doubly IR divergent yet'
stop
endif
*
* get fourpoint function
*
ier0 = ieri(i)
call ffxd0e(cs,cfac,xmax, .FALSE.,ndiv,xqi4,dqiqj4,
+ qiDqj4,del2s,ldel2s,ieri(i))
if ( ieri(i).gt.10 ) then
isgnal = -isgnal
ieri(i) = ier0
call ffxd0e(cs,cfac,xmax, .TRUE.,ndiv,xqi4,dqiqj4,
+ qiDqj4,del2s,ldel2s,ieri(i))
isgnal = -isgnal
endif
endif
*
* Finally ...
*
cd0i(i) = cs*cfac
xmx5(i) = xmax*absc(cfac)
if ( ldot ) then
call ffdl3p(fdl3i(i),piDpj4,10,ii4,ii4)
* let's hope tha tthese have been set by ffxd0e...
fdl4si(i) = fdel4s
endif
100 continue
*
* #] calculations:
* #[ add all up:
*
csum = 0
xmax = 0
imin = 1
do 200 i=1,5
imin = -imin
- csum = csum + imin*DBLE(dl4ri(i))*cd0i(i)
+ csum = csum + imin*Re(dl4ri(i))*cd0i(i)
if ( ieri(i) .gt. 50 ) then
ieri(i) = mod(ieri(i),50)
endif
- xmax = max(xmax,dl4ri(i)*xmx5(i)*DBLE(10)**mod(ieri(i),50))
+ xmax = max(xmax,dl4ri(i)*xmx5(i)*Re(10)**mod(ieri(i),50))
200 continue
*
* If the imaginary part is very small it most likely is zero
* (can be removed, just esthetically more pleasing)
*
- if ( abs(DIMAG(csum)) .lt. precc*abs(DBLE(csum)) )
- + csum = DCMPLX(DBLE(csum))
+ if ( abs(Im(csum)) .lt. precc*abs(Re(csum)) )
+ + csum = ToComplex(Re(csum))
*
* Finally ...
*
- ce0 = csum*(1/DBLE(2*dl5s))
+ ce0 = csum*(1/Re(2*dl5s))
*
* #] add all up:
*###] ffxe0a:
end
*###[ ffxe00:
subroutine ffxe00(ce0,cd0i,dl4ri,xpi,piDpj)
***#[*comment:***********************************************************
* *
* calculate *
* *
* 1 / / \-1*
* e0= -----\dq |(q^2-m_1^2)((q+p_1)^2-m_2^2)...((q-p_5)^2-m_5^2| *
* ipi^2/ \ / *
* *
* following the five four-point-function method in .... *
* The four five fourpoint function Di are input in this version. *
* *
* Input: cd0i(5) (complex) D0 with s_i missing *
* dl4ri(5) (real) coeff of D0 *
* xpi = m_i^2 (real) i=1,5 *
* xpi = p_i.p_i (real) i=6,10 (note: B&D metric) *
* xpi = (p_i+p_{i+1})^2 (r) i=11,15 *
* xpi = (p_i+p_{i+2})^2 (r) i=16,20 *
* piDpj(15,15) (real) pi.pj *
* *
* Output: ce0 (complex) *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE COMPLEX ce0,cd0i(5)
- DOUBLE PRECISION dl4ri(5),xpi(20),piDpj(15,15)
+ ComplexType ce0,cd0i(5)
+ RealType dl4ri(5),xpi(20),piDpj(15,15)
*
* local variables
*
integer i,ii(10),imin
- DOUBLE COMPLEX c,csum
- DOUBLE PRECISION dl5s,dl4p,absc,xmax
+ ComplexType c,csum
+ RealType dl5s,dl4p,absc,xmax
*
* common blocks:
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ initialisations:
*
idsub = idsub + 1
ce0 = 0
*
* #] initialisations:
* #[ calculations:
*
if ( ldot ) then
do 10 i=1,10
ii(i) = i+5
10 continue
idsub = idsub + 1
call ffdl4p(dl4p,piDpj,ii)
fdel4 = dl4p
endif
idsub = idsub + 1
call ffdel5(dl5s,xpi,piDpj)
*
* #] calculations:
* #[ add all up:
*
csum = 0
xmax = 0
imin = 1
do 200 i=1,5
imin = -imin
- csum = csum + imin*DBLE(dl4ri(i))*cd0i(i)
+ csum = csum + imin*Re(dl4ri(i))*cd0i(i)
xmax = max(xmax,abs(dl4ri(i))*absc(cd0i(i)))
200 continue
*
* If the imaginary part is very small it most likely is zero
* (can be removed, just esthetically more pleasing)
*
- if ( abs(DIMAG(csum)) .lt. precc*abs(DBLE(csum)) )
- + csum = DCMPLX(DBLE(csum))
+ if ( abs(Im(csum)) .lt. precc*abs(Re(csum)) )
+ + csum = ToComplex(Re(csum))
*
* Finally ...
*
- ce0 = csum*(1/DBLE(2*dl5s))
+ ce0 = csum*(1/Re(2*dl5s))
*
* #] add all up:
*###] ffxe00:
end
*###[ ffdot5:
subroutine ffdot5(piDpj,xpi,dpipj,ier)
***#[*comment:***********************************************************
* *
* calculate the dotproducts pi.pj with *
* *
* xpi(i) = s_i i=1,5 *
* xpi(i) = p_i i=6,10 *
* xpi(i) = p_i+p_{i+1} i=11,15 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE PRECISION xpi(20),dpipj(15,20),piDpj(15,15)
+ RealType xpi(20),dpipj(15,20),piDpj(15,15)
*
* local variables
*
integer is1,is2,is3,is4,ip6,ip7,ip8,ip11,ip12,ip14,
+ itel,i1,i2,i3,i4,i5,i6,ierin
*
* common blocks
*
#include "ff.h"
*
* data
*
* #] declarations:
* #[ indices:
ierin = ier
do 10 is1=1,5
is2 = is1 + 1
if ( is2 .eq. 6 ) is2 = 1
is3 = is2 + 1
if ( is3 .eq. 6 ) is3 = 1
ip6 = is1 + 5
ip7 = is2 + 5
ip11 = ip6 + 5
*
* we have now defined a 3point function
*
* | -p11
* |
* / \
* s1/ \s3
* ___/_____\___
* p6 s2 p7
*
* #] indices:
* #[ all in one vertex:
*
* pi.pi, si.si
*
piDpj(is1,is1) = xpi(is1)
piDpj(ip6,ip6) = xpi(ip6)
piDpj(ip11,ip11) = xpi(ip11)
*
* si.s(i+1)
*
if ( xpi(is2) .le. xpi(is1) ) then
piDpj(is1,is2) = (dpipj(is1,ip6) + xpi(is2))/2
else
piDpj(is1,is2) = (dpipj(is2,ip6) + xpi(is1))/2
endif
piDpj(is2,is1) = piDpj(is1,is2)
*
* si.s(i+2)
*
if ( xpi(is1) .le. xpi(is3) ) then
piDpj(is3,is1) = (dpipj(is3,ip11) + xpi(is1))/2
else
piDpj(is3,is1) = (dpipj(is1,ip11) + xpi(is3))/2
endif
piDpj(is1,is3) = piDpj(is3,is1)
*
* pi.si
*
if ( abs(xpi(ip6)) .le. xpi(is1) ) then
piDpj(ip6,is1) = (dpipj(is2,is1) - xpi(ip6))/2
else
piDpj(ip6,is1) = (dpipj(is2,ip6) - xpi(is1))/2
endif
piDpj(is1,ip6) = piDpj(ip6,is1)
*
* pi.s(i+1)
*
if ( abs(xpi(ip6)) .le. xpi(is2) ) then
piDpj(ip6,is2) = (dpipj(is2,is1) + xpi(ip6))/2
else
piDpj(ip6,is2) = (dpipj(ip6,is1) + xpi(is2))/2
endif
piDpj(is2,ip6) = piDpj(ip6,is2)
*
* p(i+2).s(i)
*
if ( abs(xpi(ip11)) .le. xpi(is1) ) then
piDpj(ip11,is1) = -(dpipj(is1,is3) + xpi(ip11))/2
else
piDpj(ip11,is1) = -(dpipj(ip11,is3) + xpi(is1))/2
endif
piDpj(is1,ip11) = piDpj(ip11,is1)
*
* p(i+2).s(i+2)
*
if ( abs(xpi(ip11)) .le. xpi(is3) ) then
piDpj(ip11,is3) = -(dpipj(is1,is3) - xpi(ip11))/2
else
piDpj(ip11,is3) = -(dpipj(is1,ip11) - xpi(is3))/2
endif
piDpj(is3,ip11) = piDpj(ip11,is3)
* #] all in one vertex:
* #[ all in one 3point:
*
* pi.s(i+2)
*
if ( min(abs(dpipj(is2,is1)),abs(dpipj(ip11,ip7))) .le.
+ min(abs(dpipj(ip11,is1)),abs(dpipj(is2,ip7))) ) then
piDpj(ip6,is3) = (dpipj(ip11,ip7) + dpipj(is2,is1))/2
else
piDpj(ip6,is3) = (dpipj(ip11,is1) + dpipj(is2,ip7))/2
endif
piDpj(is3,ip6) = piDpj(ip6,is3)
*
* p(i+1).s(i)
*
if ( min(abs(dpipj(is3,is2)),abs(dpipj(ip6,ip11))) .le.
+ min(abs(dpipj(ip6,is2)),abs(dpipj(is3,ip11))) ) then
piDpj(ip7,is1) = (dpipj(ip6,ip11) + dpipj(is3,is2))/2
else
piDpj(ip7,is1) = (dpipj(ip6,is2) + dpipj(is3,ip11))/2
endif
piDpj(is1,ip7) = piDpj(ip7,is1)
*
* p(i+2).s(i+1)
*
if ( min(abs(dpipj(is1,is3)),abs(dpipj(ip7,ip6))) .le.
+ min(abs(dpipj(ip7,is3)),abs(dpipj(is1,ip6))) ) then
piDpj(ip11,is2) = -(dpipj(ip7,ip6) + dpipj(is1,is3))/2
else
piDpj(ip11,is2) = -(dpipj(ip7,is3) + dpipj(is1,ip6))/2
endif
piDpj(is2,ip11) = piDpj(ip11,is2)
* #] all in one 3point:
* #[ all external 3point:
*
* pi.p(i+1)
*
if ( abs(xpi(ip7)) .le. abs(xpi(ip6)) ) then
piDpj(ip6,ip7) = (dpipj(ip11,ip6) - xpi(ip7))/2
else
piDpj(ip6,ip7) = (dpipj(ip11,ip7) - xpi(ip6))/2
endif
piDpj(ip7,ip6) = piDpj(ip6,ip7)
*
* p(i+1).p(i+2)
*
if ( abs(xpi(ip11)) .le. abs(xpi(ip7)) ) then
piDpj(ip7,ip11) = -(dpipj(ip6,ip7) - xpi(ip11))/2
else
piDpj(ip7,ip11) = -(dpipj(ip6,ip11) - xpi(ip7))/2
endif
piDpj(ip11,ip7) = piDpj(ip7,ip11)
*
* p(i+2).p(i)
*
if ( abs(xpi(ip6)) .le. abs(xpi(ip11)) ) then
piDpj(ip11,ip6) = -(dpipj(ip7,ip11) - xpi(ip6))/2
else
piDpj(ip11,ip6) = -(dpipj(ip7,ip6) - xpi(ip11))/2
endif
piDpj(ip6,ip11) = piDpj(ip11,ip6)
* #] all external 3point:
* #[ the other 3point:
is4 = is3 + 1
if ( is4 .eq. 6 ) is4 = 1
ip8 = is3 + 5
ip14 = is4 + 10
*
* we now work with the threepoint configuration
*
* | p14
* |
* / \
* s1/ \s4
* ___/_____\___
* p11 s3 p8
*
* s1.p8
*
do 11 itel = 1,3
if ( itel .eq. 1 ) then
i1 = is1
i2 = is3
i3 = is4
i4 = ip11
i5 = ip8
i6 = ip14
elseif ( itel .eq. 2 ) then
i1 = is3
i2 = is4
i3 = is1
i4 = ip8
i5 = ip14
i6 = ip11
else
i1 = is4
i2 = is1
i3 = is3
i4 = ip14
i5 = ip11
i6 = ip8
endif
*
* in one go: the opposite sides
*
if ( min(abs(dpipj(i3,i2)),abs(dpipj(i4,i6))) .le.
+ min(abs(dpipj(i4,i2)),abs(dpipj(i3,i6))) ) then
piDpj(i5,i1) = (dpipj(i3,i2) + dpipj(i4,i6))/2
else
piDpj(i5,i1) = (dpipj(i4,i2) + dpipj(i3,i6))/2
endif
piDpj(i1,i5) = piDpj(i5,i1)
*
* and the remaining external ones
*
if ( abs(xpi(i5)) .le. abs(xpi(i4)) ) then
piDpj(i4,i5) = (dpipj(i6,i4) - xpi(i5))/2
else
piDpj(i4,i5) = (dpipj(i6,i5) - xpi(i4))/2
endif
piDpj(i5,i4) = piDpj(i4,i5)
11 continue
* #] the other 3point:
* #[ 4point indices:
ip12 = ip7+5
*
* we now have the fourpoint configuration
*
* \p14 /p8
* \____/
* | s4 |
* s1| |s3
* |____|
* p6/ s2 \p7
* / \
*
*
*
do 12 itel = 1,2
if ( itel .eq. 1 ) then
i1 = ip6
i2 = ip8
i3 = ip7
i4 = ip14
else
i1 = ip7
i2 = ip14
i3 = ip6
i4 = ip8
endif
if ( min(abs(dpipj(i3,ip11)),abs(dpipj(i4,ip12))) .le.
+ min(abs(dpipj(i4,ip11)),abs(dpipj(i3,ip12))) ) then
piDpj(i1,i2) = (dpipj(i3,ip11) + dpipj(i4,ip12))/2
else
piDpj(i1,i2) = (dpipj(i4,ip11) + dpipj(i3,ip12))/2
endif
piDpj(i2,i1) = piDpj(i1,i2)
12 continue
*
* we are only left with p11.p12 etc.
*
if ( min(abs(dpipj(ip14,ip8)),abs(dpipj(ip7,ip6))) .le.
+ min(abs(dpipj(ip7,ip8)),abs(dpipj(ip14,ip6))) ) then
piDpj(ip11,ip12) = (dpipj(ip7,ip6) + dpipj(ip14,ip8))/2
else
piDpj(ip11,ip12) = (dpipj(ip7,ip8) + dpipj(ip14,ip6))/2
endif
piDpj(ip12,ip11) = piDpj(ip11,ip12)
10 continue
* #] 4point indices:
*###] ffdot5:
end
*###[ ffpi54:
subroutine ffpi54(xpi4,dpipj4,piDpj4,xpi,dpipj,piDpj,inum)
***#[*comment:***********************************************************
* *
* Gets the dotproducts pertaining to the fourpoint function with *
* s_i missing out of the five point function dotproduct array. *
* *
* Input: xpi real(20) si.si,pi.pi *
* dpipj real(15,20) xpi(i) - xpi(j) *
* piDpj real(15,15) pi(i).pi(j) *
* inum integer 1--5 *
* *
* Output: xpi4 real(13) *
* dpipj4 real(10,13) *
* piDpj4 real(10,10) *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer inum
- DOUBLE PRECISION xpi(20),dpipj(15,20),piDpj(15,15),xpi4(13),
+ RealType xpi(20),dpipj(15,20),piDpj(15,15),xpi4(13),
+ dpipj4(10,13),piDpj4(10,10)
*
* local variables
*
integer i,j,iplace(11,5),isigns(11,5)
save iplace,isigns
*
* common blocks
*
#include "ff.h"
*
* data
*
data iplace /
+ 2,3,4,5, 07,08,09,15, 12,13, 17,
+ 1,3,4,5, 11,08,09,10, 14,13, 18,
+ 1,2,4,5, 06,12,09,10, 14,15, 19,
+ 1,2,3,5, 06,07,13,10, 11,15, 20,
+ 1,2,3,4, 06,07,08,14, 11,12, 16/
*
data isigns /
+ +1,+1,+1,+1, +1,+1,+1,+1, -1,+1, +1,
+ +1,+1,+1,+1, +1,+1,+1,+1, +1,+1, +1,
+ +1,+1,+1,+1, +1,+1,+1,+1, +1,-1, +1,
+ +1,+1,+1,+1, +1,+1,+1,+1, -1,-1, +1,
+ +1,+1,+1,+1, +1,+1,+1,+1, -1,+1, +1/
* #] declarations:
* #[ distribute:
*
* copy p5-p11
*
do 20 i=1,11
xpi4(i) = xpi(iplace(i,inum))
do 10 j=1,10
dpipj4(j,i) = dpipj(iplace(j,inum),iplace(i,inum))
10 continue
20 continue
*
* these cannot be simply copied I think
*
xpi4(12) = -xpi4(5)+xpi4(6)-xpi4(7)+xpi4(8)+xpi4(9)+xpi4(10)
xpi4(13) = xpi4(5)-xpi4(6)+xpi4(7)-xpi4(8)+xpi4(9)+xpi4(10)
*
* and the differences
*
do 40 i=12,13
do 30 j=1,10
dpipj4(j,i) = xpi4(j) - xpi4(i)
30 continue
40 continue
*
* copy the dotproducts (watch the signs of p9,p10!)
*
do 60 i=1,10
do 50 j=1,10
piDpj4(j,i) = isigns(j,inum)*isigns(i,inum)*
+ piDpj(iplace(j,inum),iplace(i,inum))
50 continue
60 continue
* #] distribute:
*###] ffpi54:
end
*###[ ffxe0r:
subroutine ffxe0r(ce0,cd0i,xpi,ier)
***#[*comment:***********************************************************
* *
* Tries all 12 permutations of the 5pointfunction *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
integer ier,nrot
parameter(nrot=12)
- DOUBLE PRECISION xpi(20),xqi(20)
- DOUBLE COMPLEX ce0,cd0i(5),ce0p,cd0ip(5),cd0ipp(5)
+ RealType xpi(20),xqi(20)
+ ComplexType ce0,cd0i(5),ce0p,cd0ip(5),cd0ipp(5)
integer inew(20,nrot),irota,ier1,i,j,k,icon,ialsav,init
logical lcon
parameter (icon=3)
save inew,init,lcon
#include "ff.h"
data inew
+ /1,2,3,4,5, 6,7,8,9,10,11,12,13,14,15, 16,17,18,19,20,
+ 2,1,3,4,5, 6,11,8,9,15,7,14,13,12,10, 16,18,17,19,-20,
+ 1,3,2,4,5, 11,7,12,9,10,6,8,15,14,13, -16,17,19,18,20,
+ 1,2,4,3,5, 6,12,8,13,10,14,7,9,11,15, 16,-17,18,20,19,
+ 1,2,3,5,4, 6,7,13,9,14,11,15,8,10,12, 20,17,-18,19,16,
+ 5,2,3,4,1, 15,7,8,14,10,13,12,11,9,6, 17,16,18,-19,20,
+ 2,1,4,3,5, 6,14,8,13,15,12,11,9,7,10, 16,-18,17,20,-19,
+ 1,3,2,5,4, 11,7,15,9,14,6,13,12,10,8, -20,17,-19,18,16,
+ 5,2,4,3,1, 15,12,8,11,10,9,7,14,13,6, 17,-16,18,-20,19,
+ 2,1,3,5,4, 6,11,13,9,12,7,10,8,15,14, 20,18,-17,19,-16,
+ 5,3,2,4,1, 13,7,12,14,10,15,8,6,9,11, -17,16,19,-18,20,
+ 1,3,5,2,4, 11,13,15,12,14,10,7,9,6,8,-20,-17,-19,-16,-18/
data init /0/
* #] declarations:
* #[ open console for some activity on screen:
if ( init .eq. 0 ) then
init = 1
lcon = .FALSE.
endif
* #] open console for some activity on screen:
* #[ calculations:
ce0 = 0
ier = 999
ialsav = isgnal
do 30 j = -1,1,2
do 20 irota=1,nrot
do 10 i=1,20
if ( inew(i,irota) .lt. 0 ) then
xqi(-inew(i,irota)) = 0
else
xqi(inew(i,irota)) = xpi(i)
endif
10 continue
print '(a,i2,a,i2)','---#[ rotation ',irota,
+ ': isgnal ',isgnal
if (lcon) write(icon,'(a,i2,a,i2)') 'rotation ',irota,
+ ', isgnal ',isgnal
ier1 = 0
ner = 0
id = id + 1
isgnal = ialsav
call ffxe0(ce0p,cd0ip,xqi,ier1)
ier1 = ier1 + ner
print '(a,i1,a,i2)','---#] rotation ',irota,': isgnal ',
+ isgnal
print '(a,2g28.16,i3)','e0 = ',ce0p,ier1
do 15 k=1,5
cd0ipp(k) = cd0ip(inew(k,irota))
print '(a,2g28.16,i3)','d0 = ',cd0ipp(k),k
15 continue
if (lcon) write(icon,'(a,2g28.16,i3)')'e0 = ',ce0p,ier1
if ( ier1 .lt. ier ) then
ce0 = ce0p
do 19 k=1,5
cd0i(k) = cd0ipp(k)
19 continue
ier = ier1
endif
20 continue
ialsav = -ialsav
30 continue
* #] calculations:
*###] ffxe0r:
end
diff --git a/Looptools/Makefile.am b/Looptools/Makefile.am
--- a/Looptools/Makefile.am
+++ b/Looptools/Makefile.am
@@ -1,61 +1,54 @@
-noinst_LTLIBRARIES = libHwLooptoolsXFC.la libHwLooptoolsCFC.la
+noinst_LTLIBRARIES = libHwLooptoolsXFC.la libHwLooptoolsCFC.la
noinst_LTLIBRARIES += libHwLooptools.la
EXTRA_DIST = include/lt.h include/ftypes.h include/ff.h include/ffwarn.h \
include/fferr.h include/defs.h include/looptools.h include/ffperm5.h \
include/clooptools.h include/cexternals.h include/externals.h \
util/solve-LU.F util/solve-LU.h util/solve-Eigen.F
theXFCSOURCES = \
-A/A0.F A/A00.F A/ffxa0.F A/ffca0.F B/Bget.F \
-B/Bcoeff.F B/BcoeffC.F B/Bcoeffa.F B/Bcoeffb.F B/ffxb0.F \
-B/ffcb0.F B/ffxb1.F B/ffcb1.F B/ffxb2p.F B/ffcb2p.F \
-B/ffxdb0.F B/ffcdb0.F B/ffxdb1.F B/ffdel2.F B/ffcel2.F \
-C/C0.F C/C0C.F C/Cget.F C/ffxc0.F C/ffcc0.F \
-C/ffxc0i.F C/ffxc0p.F C/ffxc0p0.F C/ffcc0p.F C/ffdxc0.F \
-C/ffdel3.F C/ffcel3.F D/D0.F D/D0C.F D/Dget.F \
-D/ffxd0.F D/ffxd0h.F D/ffxd0i.F D/ffxd0p.F D/ffxd0m0.F \
-D/ffxd0tra.F D/ffxdbd.F D/ffdcc0.F D/ffdel4.F D/ffd0c.F \
-D/ffTn.F D/ffT13.F D/ffS2.F D/ffS3n.F D/ffRn.F \
-E/E0.F E/Eget.F E/Ecoeffa.F E/Ecoeffb.F E/ffxe0.F \
-E/ffdel5.F util/ini.F util/auxCD.F util/solve.F util/Dump.F \
-util/Li2.F util/ffinit.F util/ffxli2.F util/ffcli2.F util/ffxxyz.F \
-util/ffcxyz.F util/ffcrr.F util/ffcxr.F util/fftran.F util/ffabcd.F \
-util/ff2dl2.F util/ffcxs3.F util/ffcxs4.F util/ffdcxs.F util/ffbndc.F
+A/Aget.F A/ffxa0.F A/ffca0.F \
+B/Bget.F B/Bcoeff.F B/BcoeffC.F B/BcoeffAD.F B/BcoeffFF.F \
+B/ffxb0.F B/ffcb0.F B/ffxb1.F B/ffcb1.F B/ffxb2p.F B/ffcb2p.F \
+B/ffxdb0.F B/ffcdb0.F B/ffxdb1.F B/ffdel2.F B/ffcel2.F \
+C/C0func.F C/C0funcC.F C/Cget.F C/ffxc0.F C/ffcc0.F \
+C/ffxc0i.F C/ffxc0p.F C/ffxc0p0.F C/ffcc0p.F C/ffdxc0.F \
+C/ffdel3.F C/ffcel3.F \
+D/D0func.F D/D0funcC.F D/Dget.F \
+D/ffxd0.F D/ffxd0h.F D/ffxd0i.F D/ffxd0p.F D/ffxd0m0.F \
+D/ffxd0tra.F D/ffxdbd.F D/ffdcc0.F D/ffdel4.F D/ffd0c.F \
+D/ffTn.F D/ffT13.F D/ffS2.F D/ffS3n.F D/ffRn.F \
+E/E0func.F E/Eget.F E/Ecoeffa.F E/Ecoeffb.F \
+E/ffxe0.F E/ffdel5.F \
+util/ini.F util/auxCD.F util/solve.F util/Dump.F \
+util/Li2.F util/Li2omx.F util/ffinit.F util/ffxli2.F util/ffcli2.F util/ffxxyz.F \
+util/ffcxyz.F util/ffcrr.F util/ffcxr.F util/fftran.F util/ffabcd.F \
+util/ff2dl2.F util/ffcxs3.F util/ffcxs4.F util/ffdcxs.F util/ffbndc.F
## the following need -DCOMPLEXPARA
theCFCSOURCES = \
-A/A0.F A/A00.F B/Bget.F B/Bcoeffa.F C/Cget.F D/Dget.F E/E0.F \
-E/Eget.F E/Ecoeffa.F E/Ecoeffb.F util/solve.F util/Dump.F util/Li2.F
+A/Aget.F B/Bget.F B/BcoeffFF.F C/Cget.F D/Dget.F \
+E/E0func.F E/Eget.F E/Ecoeffa.F E/Ecoeffb.F \
+util/solve.F util/Dump.F util/Li2.F util/Li2omx.F
commonCPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/include
libHwLooptoolsXFC_la_SOURCES = $(theXFCSOURCES)
libHwLooptoolsXFC_la_CPPFLAGS = $(commonCPPFLAGS)
-libHwLooptoolsXFC_la_FCFLAGS = $(AM_FCFLAGS) -O0 -ffixed-line-length-none
-libHwLooptoolsXFC_la_FFLAGS = $(AM_FFLAGS) -ffixed-line-length-none
+libHwLooptoolsXFC_la_FCFLAGS = $(AM_FCFLAGS) -ffixed-line-length-none
+libHwLooptoolsXFC_la_FFLAGS = $(AM_FFLAGS) -ffixed-line-length-none
libHwLooptoolsCFC_la_SOURCES = $(theCFCSOURCES)
libHwLooptoolsCFC_la_CPPFLAGS = $(commonCPPFLAGS) -DCOMPLEXPARA
libHwLooptoolsCFC_la_FCFLAGS = $(AM_FCFLAGS) -ffixed-line-length-none
-libHwLooptoolsCFC_la_FFLAGS = $(AM_FFLAGS) -ffixed-line-length-none
-
-## installed already from "include/Makefile.am"
-## noinst_HEADERS = include/clooptools.h
-
-##if NEED_APPLE_FIXES
-##libHwLooptoolsXFC_la_LDFLAGS = -Wl,-single_module
-##libHwLooptoolsCFC_la_LDFLAGS = -Wl,-single_module
-##endif
+libHwLooptoolsCFC_la_FFLAGS = $(AM_FFLAGS) -ffixed-line-length-none
libHwLooptools_la_SOURCES = util/cache.c clooptools.cc
libHwLooptools_la_CXXFLAGS = $(AM_CXXFLAGS) -Wno-strict-aliasing
libHwLooptools_la_CPPFLAGS = $(commonCPPFLAGS)
libHwLooptools_la_CFLAGS = $(AM_CFLAGS) -std=c99
libHwLooptools_la_LIBADD = libHwLooptoolsXFC.la libHwLooptoolsCFC.la
-
-## libHwLooptoolsHelper2_la_SOURCES = clooptools.cc
EXTRA_PROGRAMS = tester
tester_SOURCES = tester.cc
tester_LDADD = libHwLooptools.la $(FCLIBS) $(THEPEGLDFLAGS) $(THEPEGLIB)
diff --git a/Looptools/README b/Looptools/README
--- a/Looptools/README
+++ b/Looptools/README
@@ -1,20 +1,13 @@
-This subdirectory is based on version 2.6 of the Looptools package available at
+This subdirectory is based on version 2.13 of the Looptools package available at
http://www.feynarts.de/looptools/
-From their website, it seems that Looptools is licensed under the LGPL,
-although the tarball itself does not contain a reference to it.
-
-For reference, we have added the LGPL in the file COPYING.Looptools.
-Note that this licence only applies to the Looptools subdirectory.
-
-Our changes to LoopTools-2.6.tar.gz are listed here:
+Our changes to LoopTools-2.13.tar.gz are listed here:
* removed unused 'tools' and 'frontend' directories
* include/clooptools.h modified: definitions and 'extern' declarations moved to
Herwig's clooptools.cc
-* fixed 64bit int -> long problem in cache.c
* added Makefile.am; creates libHwLooptools.la to be linked into Herwig.so
* added tester.cc: a quick test whether c++ linking works
--
-2011-01-17 David Grellscheid <david.grellscheid@durham.ac.uk>
+2016-09-08 David Grellscheid <david.grellscheid@durham.ac.uk>
diff --git a/Looptools/clooptools.cc b/Looptools/clooptools.cc
--- a/Looptools/clooptools.cc
+++ b/Looptools/clooptools.cc
@@ -1,485 +1,624 @@
/* -*- C++ -*-
clooptools.cc
the C++ file with the definitions for fortran IO redirection
Output redirected to log file. 2007-07-18 dgrell
Definitions moved here from clooptools.h 2011-01-21 dgrell
*/
#include "Herwig/Looptools/clooptools.h"
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <cstdio>
#include <cassert>
#include <string>
#include "ThePEG/Repository/CurrentGenerator.h"
extern "C" {
#include <unistd.h>
+ extern memindex aget_(AARGS(_lt_Fr_));
+ extern memindex agetc_(AARGS(_lt_Fc_));
+ extern void aput_(COMPLEX *res, AARGS(_lt_Fr_));
+ extern void aputc_(COMPLEX *res, AARGS(_lt_Fc_));
+ extern void aputnocache_(COMPLEX *res, AARGS(_lt_Fr_));
+ extern void aputnocachec_(COMPLEX *res, AARGS(_lt_Fc_));
- extern void a0sub_(DOUBLE_COMPLEX *result, AARGS(_Fr_));
- extern void a0subc_(DOUBLE_COMPLEX *result, AARGS(_Fc_));
- extern void a00sub_(DOUBLE_COMPLEX *result, AARGS(_Fr_));
- extern void a00subc_(DOUBLE_COMPLEX *result, AARGS(_Fc_));
+ extern memindex bget_(BARGS(_lt_Fr_));
+ extern memindex bgetc_(BARGS(_lt_Fc_));
+ extern void bput_(COMPLEX *res, BARGS(_lt_Fr_));
+ extern void bputc_(COMPLEX *res, BARGS(_lt_Fc_));
+ extern void bputnocache_(COMPLEX *res, BARGS(_lt_Fr_));
+ extern void bputnocachec_(COMPLEX *res, BARGS(_lt_Fc_));
- extern long bget_(BARGS(_Fr_));
- extern long bgetc_(BARGS(_Fc_));
+ extern memindex cget_(CARGS(_lt_Fr_));
+ extern memindex cgetc_(CARGS(_lt_Fc_));
+ extern void cput_(COMPLEX *res, CARGS(_lt_Fr_));
+ extern void cputc_(COMPLEX *res, CARGS(_lt_Fc_));
+ extern void c0nocache_(COMPLEX *res, CARGS(_lt_Fr_));
+ extern void c0nocachec_(COMPLEX *res, CARGS(_lt_Fc_));
- extern void c0sub_(DOUBLE_COMPLEX *result, CARGS(_Fr_));
- extern void c0subc_(DOUBLE_COMPLEX *result, CARGS(_Fc_));
- extern long cget_(CARGS(_Fr_));
- extern long cgetc_(CARGS(_Fc_));
+ extern memindex dget_(DARGS(_lt_Fr_));
+ extern memindex dgetc_(DARGS(_lt_Fc_));
+ extern void dput_(COMPLEX *res, DARGS(_lt_Fr_));
+ extern void dputc_(COMPLEX *res, DARGS(_lt_Fc_));
+ extern void d0nocache_(COMPLEX *res, DARGS(_lt_Fr_));
+ extern void d0nocachec_(COMPLEX *res, DARGS(_lt_Fc_));
- extern void d0sub_(DOUBLE_COMPLEX *result, DARGS(_Fr_));
- extern void d0subc_(DOUBLE_COMPLEX *result, DARGS(_Fc_));
- extern long dget_(DARGS(_Fr_));
- extern long dgetc_(DARGS(_Fc_));
+ extern memindex eget_(EARGS(_lt_Fr_));
+ extern memindex egetc_(EARGS(_lt_Fc_));
+ extern void eput_(COMPLEX *res, EARGS(_lt_Fr_));
+ extern void eputc_(COMPLEX *res, EARGS(_lt_Fc_));
+ extern void e0nocache_(COMPLEX *res, EARGS(_lt_Fr_));
+ extern void e0nocachec_(COMPLEX *res, EARGS(_lt_Fc_));
- extern void e0sub_(DOUBLE_COMPLEX *result, EARGS(_Fr_));
- extern void e0subc_(DOUBLE_COMPLEX *result, EARGS(_Fc_));
- extern long eget_(EARGS(_Fr_));
- extern long egetc_(EARGS(_Fc_));
+ extern void li2sub_(COMPLEX *res, _lt_Fr_(x));
+ extern void li2csub_(COMPLEX *res, _lt_Fc_(x));
- extern void li2sub_(DOUBLE_COMPLEX *result, const double *x);
- extern void li2csub_(DOUBLE_COMPLEX *result, CDOUBLE_COMPLEX *x);
+ extern void li2omxsub_(COMPLEX *res, _lt_Fr_(x));
+ extern void li2omxcsub_(COMPLEX *res, _lt_Fc_(x));
extern void ltini_(void);
extern void ltexi_(void);
extern void clearcache_(void);
extern void markcache_(void);
extern void restorecache_(void);
- extern struct { /* MUST match common block ltvars in lt.h! */
- DOUBLE_COMPLEX cache[8][2];
- DOUBLE_COMPLEX savedptr[8];
- double maxdev;
- long warndigits, errdigits;
- long serial, versionkey;
- long debugkey, debugfrom, debugto;
+
+ extern struct { /* MUST match common block ltvars in lt.h! */
+ COMPLEX cache[10][2];
+ COMPLEX savedptr[10];
+ REAL maxdev;
+ INTEGER epsi, warndigits, errdigits;
+ INTEGER serial, versionkey;
+ INTEGER debugkey, debugfrom, debugto;
} ltvars_;
-
- extern struct { /* MUST match common block ltcache in lt.h! */
- long cmpbits;
+
+ extern struct { /* MUST match common block ltcache in lt.h! */
+ INTEGER cmpbits;
} ltcache_;
-
- extern struct { /* MUST match common block ltregul in ff.h! */
- double mudim, delta, lambda, minmass;
+
+ extern struct { /* MUST match common block ltregul in ff.h! */
+ REAL mudim, im_mudim, delta, uvdiv, lambda, minmass;
+ REAL diffeps, zeroeps;
} ltregul_;
}
+#define CACHEPTR(n,i) &ltvars_.cache[n][i]
+
+#define EPSINDEX(i) i+ltvars_.epsi
+
/****************************************************************/
namespace {
int start_redirection(std::string logfilename) {
if ( ! ThePEG::CurrentGenerator::isVoid()
&& ThePEG::CurrentGenerator::current().useStdOut() ) return -1;
// redirect C stdout --- unix specific solution,
// see C FAQ: http://c-faq.com/stdio/undofreopen.html
int fd;
fflush(stdout);
fd = dup(fileno(stdout));
freopen(logfilename.c_str(), "a", stdout);
return fd;
}
void stop_redirection(int fd) {
if ( ! ThePEG::CurrentGenerator::isVoid()
&& ThePEG::CurrentGenerator::current().useStdOut() ) return;
fflush(stdout);
close(fileno(stdout));
dup2(fd, fileno(stdout));
close(fd);
clearerr(stdout);
}
} // namespace
namespace Herwig {
namespace Looptools {
static int initcount = 0;
void ltini(std::string logfilename) {
assert( initcount >= 0 );
if ( initcount == 0 ) {
int rd = start_redirection(logfilename);
ltini_();
stop_redirection(rd);
}
++initcount;
}
void ltexi(std::string logfilename) {
assert( initcount > 0 );
--initcount;
if ( initcount == 0 ) {
int rd = start_redirection(logfilename);
ltexi_();
stop_redirection(rd);
}
}
- double_complex ToComplex(DOUBLE_COMPLEX c) {
- return double_complex(c.re, c.im);
- }
-
- double_complex A0(AARGS(_Cr_))
- {
- DOUBLE_COMPLEX result;
- a0sub_(&result, AARGS(_Frp_));
- return ToComplex(result);
- }
-
- double_complex A0C(AARGS(_Cc_))
- {
- DOUBLE_COMPLEX result;
- a0subc_(&result, AARGS(_Fcp_));
- return ToComplex(result);
- }
-
- double_complex A00(AARGS(_Cr_))
- {
- DOUBLE_COMPLEX result;
- a00sub_(&result, AARGS(_Frp_));
- return ToComplex(result);
- }
-
- double_complex A00C(AARGS(_Cc_))
- {
- DOUBLE_COMPLEX result;
- a00subc_(&result, AARGS(_Fcp_));
- return ToComplex(result);
+ ComplexType ToComplex(COMPLEX c) {
+ return ComplexType(c.re, c.im);
}
/****************************************************************/
- long Bget(BARGS(_Cr_))
+ memindex Aget(AARGS(_lt_Cr_))
{
- return bget_(BARGS(_Frp_));
+ return aget_(AARGS(_lt_Frp_));
}
- long BgetC(BARGS(_Cc_))
+ memindex AgetC(AARGS(_lt_Cc_))
{
- return bgetc_(BARGS(_Fcp_));
+ return agetc_(AARGS(_lt_Fcp_));
}
- DOUBLE_COMPLEX *Bcache(const long integral)
- { return &ltvars_.cache[0][integral]; }
+ void Aput(ComplexType *res, AARGS(_lt_Cr_))
+ {
+ aput_(_lt_Fap_(res), AARGS(_lt_Frp_));
+ }
- DOUBLE_COMPLEX *BcacheC(const long integral)
- { return &ltvars_.cache[1][integral]; }
+ void AputC(ComplexType *res, AARGS(_lt_Cc_))
+ {
+ aputc_(_lt_Fap_(res), AARGS(_lt_Fcp_));
+ }
- double_complex Bval(const int i, const long integral)
- { return ToComplex(Bcache(integral)[i]); }
+ void Aputnocache(ComplexType *res, AARGS(_lt_Cr_))
+ {
+ aputnocache_(_lt_Fap_(res), AARGS(_lt_Frp_));
+ }
+
+ void AputnocacheC(ComplexType *res, AARGS(_lt_Cc_))
+ {
+ aputnocachec_(_lt_Fap_(res), AARGS(_lt_Fcp_));
+ }
+
+ COMPLEX *Acache(const memindex integral)
+ { return CACHEPTR(0,integral); }
+
+ COMPLEX *AcacheC(const memindex integral)
+ { return CACHEPTR(1,integral); }
+
+ ComplexType Aval(const int i, const memindex integral)
+ { return ToComplex(Acache(integral)[i]); }
+
+ ComplexType AvalC(const int i, const memindex integral)
+ { return ToComplex(AcacheC(integral)[i]); }
+
+ ComplexType A0i(const int i, AARGS(_lt_Cr_))
+ { return Aval(EPSINDEX(i), Aget(AARGS(_lt_Id_))); }
+
+ ComplexType A0iC(const int i, AARGS(_lt_Cc_))
+ { return AvalC(EPSINDEX(i), AgetC(AARGS(_lt_Id_))); }
+
+ ComplexType A0(AARGS(_lt_Cr_))
+ { return A0i(aa0, AARGS(_lt_Id_)); }
+ ComplexType A00(AARGS(_lt_Cr_))
+ { return A0i(aa00, AARGS(_lt_Id_)); }
+
+ ComplexType A0C(AARGS(_lt_Cc_))
+ { return A0iC(aa0, AARGS(_lt_Id_)); }
+ ComplexType A00C(AARGS(_lt_Cc_))
+ { return A0iC(aa00, AARGS(_lt_Id_)); }
- double_complex BvalC(const int i, const long integral)
- { return ToComplex(BcacheC(integral)[i]); }
-
- double_complex B0i(const int i, BARGS(_Cr_))
- { return Bval(i, Bget(BARGS(_Id_))); }
-
- double_complex B0iC(const int i, BARGS(_Cc_))
- { return BvalC(i, BgetC(BARGS(_Id_))); }
-
- double_complex B0(BARGS(_Cr_))
- { return B0i(bb0, BARGS(_Id_)); }
- double_complex B1(BARGS(_Cr_))
- { return B0i(bb1, BARGS(_Id_)); }
- double_complex B00(BARGS(_Cr_))
- { return B0i(bb00, BARGS(_Id_)); }
- double_complex B11(BARGS(_Cr_))
- { return B0i(bb11, BARGS(_Id_)); }
- double_complex B001(BARGS(_Cr_))
- { return B0i(bb001, BARGS(_Id_)); }
- double_complex B111(BARGS(_Cr_))
- { return B0i(bb111, BARGS(_Id_)); }
- double_complex DB0(BARGS(_Cr_))
- { return B0i(dbb0, BARGS(_Id_)); }
- double_complex DB1(BARGS(_Cr_))
- { return B0i(dbb1, BARGS(_Id_)); }
- double_complex DB00(BARGS(_Cr_))
- { return B0i(dbb00, BARGS(_Id_)); }
- double_complex DB11(BARGS(_Cr_))
- { return B0i(dbb11, BARGS(_Id_)); }
-
- double_complex B0C(BARGS(_Cc_))
- { return B0iC(bb0, BARGS(_Id_)); }
- double_complex B1C(BARGS(_Cc_))
- { return B0iC(bb1, BARGS(_Id_)); }
- double_complex B00C(BARGS(_Cc_))
- { return B0iC(bb00, BARGS(_Id_)); }
- double_complex B11C(BARGS(_Cc_))
- { return B0iC(bb11, BARGS(_Id_)); }
- double_complex B001C(BARGS(_Cc_))
- { return B0iC(bb001, BARGS(_Id_)); }
- double_complex B111C(BARGS(_Cc_))
- { return B0iC(bb111, BARGS(_Id_)); }
- double_complex DB0C(BARGS(_Cc_))
- { return B0iC(dbb0, BARGS(_Id_)); }
- double_complex DB1C(BARGS(_Cc_))
- { return B0iC(dbb1, BARGS(_Id_)); }
- double_complex DB00C(BARGS(_Cc_))
- { return B0iC(dbb00, BARGS(_Id_)); }
- double_complex DB11C(BARGS(_Cc_))
- { return B0iC(dbb11, BARGS(_Id_)); }
/****************************************************************/
- double_complex C0(CARGS(_Cr_))
+ memindex Bget(BARGS(_lt_Cr_))
{
- DOUBLE_COMPLEX result;
- c0sub_(&result, CARGS(_Frp_));
- return ToComplex(result);
+ return bget_(BARGS(_lt_Frp_));
}
- double_complex C0C(CARGS(_Cc_))
+ memindex BgetC(BARGS(_lt_Cc_))
{
- DOUBLE_COMPLEX result;
- c0subc_(&result, CARGS(_Fcp_));
- return ToComplex(result);
+ return bgetc_(BARGS(_lt_Fcp_));
}
- long Cget(CARGS(_Cr_))
+ void Bput(ComplexType *res, BARGS(_lt_Cr_))
{
- return cget_(CARGS(_Frp_));
+ bput_(_lt_Fap_(res), BARGS(_lt_Frp_));
}
- long CgetC(CARGS(_Cc_))
+ void BputC(ComplexType *res, BARGS(_lt_Cc_))
{
- return cgetc_(CARGS(_Fcp_));
+ bputc_(_lt_Fap_(res), BARGS(_lt_Fcp_));
}
- DOUBLE_COMPLEX *Ccache(const long integral)
- { return &ltvars_.cache[2][integral]; }
+ void Bputnocache(ComplexType *res, BARGS(_lt_Cr_))
+ {
+ bputnocache_(_lt_Fap_(res), BARGS(_lt_Frp_));
+ }
+
+ void BputnocacheC(ComplexType *res, BARGS(_lt_Cc_))
+ {
+ bputnocachec_(_lt_Fap_(res), BARGS(_lt_Fcp_));
+ }
- DOUBLE_COMPLEX *CcacheC(const long integral)
- { return &ltvars_.cache[3][integral]; }
+ COMPLEX *Bcache(const memindex integral)
+ { return CACHEPTR(2,integral); }
- double_complex Cval(const int i, const long integral)
- { return ToComplex(Ccache(integral)[i]); }
+ COMPLEX *BcacheC(const memindex integral)
+ { return CACHEPTR(3,integral); }
- double_complex CvalC(const int i, const long integral)
- { return ToComplex(CcacheC(integral)[i]); }
+ ComplexType Bval(const int i, const memindex integral)
+ { return ToComplex(Bcache(integral)[i]); }
- double_complex C0i(const int i, CARGS(_Cr_))
- { return Cval(i, Cget(CARGS(_Id_))); }
+ ComplexType BvalC(const int i, const memindex integral)
+ { return ToComplex(BcacheC(integral)[i]); }
- double_complex C0iC(const int i, CARGS(_Cc_))
- { return CvalC(i, CgetC(CARGS(_Id_))); }
+ ComplexType B0i(const int i, BARGS(_lt_Cr_))
+ { return Bval(EPSINDEX(i), Bget(BARGS(_lt_Id_))); }
+
+ ComplexType B0iC(const int i, BARGS(_lt_Cc_))
+ { return BvalC(EPSINDEX(i), BgetC(BARGS(_lt_Id_))); }
+
+ ComplexType B0(BARGS(_lt_Cr_))
+ { return B0i(bb0, BARGS(_lt_Id_)); }
+ ComplexType B1(BARGS(_lt_Cr_))
+ { return B0i(bb1, BARGS(_lt_Id_)); }
+ ComplexType B00(BARGS(_lt_Cr_))
+ { return B0i(bb00, BARGS(_lt_Id_)); }
+ ComplexType B11(BARGS(_lt_Cr_))
+ { return B0i(bb11, BARGS(_lt_Id_)); }
+ ComplexType B001(BARGS(_lt_Cr_))
+ { return B0i(bb001, BARGS(_lt_Id_)); }
+ ComplexType B111(BARGS(_lt_Cr_))
+ { return B0i(bb111, BARGS(_lt_Id_)); }
+ ComplexType DB0(BARGS(_lt_Cr_))
+ { return B0i(dbb0, BARGS(_lt_Id_)); }
+ ComplexType DB1(BARGS(_lt_Cr_))
+ { return B0i(dbb1, BARGS(_lt_Id_)); }
+ ComplexType DB00(BARGS(_lt_Cr_))
+ { return B0i(dbb00, BARGS(_lt_Id_)); }
+ ComplexType DB11(BARGS(_lt_Cr_))
+ { return B0i(dbb11, BARGS(_lt_Id_)); }
+
+ ComplexType B0C(BARGS(_lt_Cc_))
+ { return B0iC(bb0, BARGS(_lt_Id_)); }
+ ComplexType B1C(BARGS(_lt_Cc_))
+ { return B0iC(bb1, BARGS(_lt_Id_)); }
+ ComplexType B00C(BARGS(_lt_Cc_))
+ { return B0iC(bb00, BARGS(_lt_Id_)); }
+ ComplexType B11C(BARGS(_lt_Cc_))
+ { return B0iC(bb11, BARGS(_lt_Id_)); }
+ ComplexType B001C(BARGS(_lt_Cc_))
+ { return B0iC(bb001, BARGS(_lt_Id_)); }
+ ComplexType B111C(BARGS(_lt_Cc_))
+ { return B0iC(bb111, BARGS(_lt_Id_)); }
+ ComplexType DB0C(BARGS(_lt_Cc_))
+ { return B0iC(dbb0, BARGS(_lt_Id_)); }
+ ComplexType DB1C(BARGS(_lt_Cc_))
+ { return B0iC(dbb1, BARGS(_lt_Id_)); }
+ ComplexType DB00C(BARGS(_lt_Cc_))
+ { return B0iC(dbb00, BARGS(_lt_Id_)); }
+ ComplexType DB11C(BARGS(_lt_Cc_))
+ { return B0iC(dbb11, BARGS(_lt_Id_)); }
/****************************************************************/
- double_complex D0(DARGS(_Cr_))
+ memindex Cget(CARGS(_lt_Cr_))
{
- DOUBLE_COMPLEX result;
- d0sub_(&result, DARGS(_Frp_));
- return ToComplex(result);
+ return cget_(CARGS(_lt_Frp_));
}
- double_complex D0C(DARGS(_Cc_))
+ memindex CgetC(CARGS(_lt_Cc_))
{
- DOUBLE_COMPLEX result;
- d0subc_(&result, DARGS(_Fcp_));
- return ToComplex(result);
+ return cgetc_(CARGS(_lt_Fcp_));
}
- long Dget(DARGS(_Cr_))
+ void Cput(ComplexType *res, CARGS(_lt_Cr_))
{
- return dget_(DARGS(_Frp_));
+ cput_(_lt_Fap_(res), CARGS(_lt_Frp_));
}
- long DgetC(DARGS(_Cc_))
+ void CputC(ComplexType *res, CARGS(_lt_Cc_))
{
- return dgetc_(DARGS(_Fcp_));
+ cputc_(_lt_Fap_(res), CARGS(_lt_Fcp_));
}
- DOUBLE_COMPLEX *Dcache(const long integral)
- { return &ltvars_.cache[4][integral]; }
+ void C0nocache(ComplexType *res, CARGS(_lt_Cr_))
+ {
+ c0nocache_(_lt_Fap_(res), CARGS(_lt_Frp_));
+ }
+
+ void C0nocacheC(ComplexType *res, CARGS(_lt_Cc_))
+ {
+ c0nocachec_(_lt_Fap_(res), CARGS(_lt_Fcp_));
+ }
- DOUBLE_COMPLEX *DcacheC(const long integral)
- { return &ltvars_.cache[5][integral]; }
+ COMPLEX *Ccache(const memindex integral)
+ { return CACHEPTR(4,integral); }
- double_complex Dval(const int i, const long integral)
- { return ToComplex(Dcache(integral)[i]); }
+ COMPLEX *CcacheC(const memindex integral)
+ { return CACHEPTR(5,integral); }
- double_complex DvalC(const int i, const long integral)
- { return ToComplex(DcacheC(integral)[i]); }
+ ComplexType Cval(const int i, const memindex integral)
+ { return ToComplex(Ccache(integral)[i]); }
- double_complex D0i(const int i, DARGS(_Cr_))
- { return Dval(i, Dget(DARGS(_Id_))); }
+ ComplexType CvalC(const int i, const memindex integral)
+ { return ToComplex(CcacheC(integral)[i]); }
- double_complex D0iC(const int i, DARGS(_Cc_))
- { return DvalC(i, DgetC(DARGS(_Id_))); }
+ ComplexType C0i(const int i, CARGS(_lt_Cr_))
+ { return Cval(EPSINDEX(i), Cget(CARGS(_lt_Id_))); }
+
+ ComplexType C0iC(const int i, CARGS(_lt_Cc_))
+ { return CvalC(EPSINDEX(i), CgetC(CARGS(_lt_Id_))); }
+
+ ComplexType C0(CARGS(_lt_Cr_))
+ { return C0i(cc0, CARGS(_lt_Id_)); }
+ ComplexType C0C(CARGS(_lt_Cc_))
+ { return C0iC(cc0, CARGS(_lt_Id_)); }
/****************************************************************/
- double_complex E0(EARGS(_Cr_))
+ memindex Dget(DARGS(_lt_Cr_))
{
- DOUBLE_COMPLEX result;
- e0sub_(&result, EARGS(_Frp_));
- return ToComplex(result);
+ return dget_(DARGS(_lt_Frp_));
}
- double_complex E0C(EARGS(_Cc_))
+ memindex DgetC(DARGS(_lt_Cc_))
{
- DOUBLE_COMPLEX result;
- e0subc_(&result, EARGS(_Fcp_));
- return ToComplex(result);
+ return dgetc_(DARGS(_lt_Fcp_));
}
- long Eget(EARGS(_Cr_))
+ void Dput(ComplexType *res, DARGS(_lt_Cr_))
{
- return eget_(EARGS(_Frp_));
+ dput_(_lt_Fap_(res), DARGS(_lt_Frp_));
}
- long EgetC(EARGS(_Cc_))
+ void DputC(ComplexType *res, DARGS(_lt_Cc_))
{
- return egetc_(EARGS(_Fcp_));
+ dputc_(_lt_Fap_(res), DARGS(_lt_Fcp_));
}
- DOUBLE_COMPLEX *Ecache(const long integral)
- { return &ltvars_.cache[6][integral]; }
+ void D0nocache(ComplexType *res, DARGS(_lt_Cr_))
+ {
+ d0nocache_(_lt_Fap_(res), DARGS(_lt_Frp_));
+ }
+
+ void D0nocacheC(ComplexType *res, DARGS(_lt_Cc_))
+ {
+ d0nocachec_(_lt_Fap_(res), DARGS(_lt_Fcp_));
+ }
- DOUBLE_COMPLEX *EcacheC(const long integral)
- { return &ltvars_.cache[7][integral]; }
+ COMPLEX *Dcache(const memindex integral)
+ { return CACHEPTR(6,integral); }
- double_complex Eval(const int i, const long integral)
- { return ToComplex(Ecache(integral)[i]); }
+ COMPLEX *DcacheC(const memindex integral)
+ { return CACHEPTR(7,integral); }
- double_complex EvalC(const int i, const long integral)
- { return ToComplex(EcacheC(integral)[i]); }
+ ComplexType Dval(const int i, const memindex integral)
+ { return ToComplex(Dcache(integral)[i]); }
- double_complex E0i(const int i, EARGS(_Cr_))
- { return Eval(i, Eget(EARGS(_Id_))); }
+ ComplexType DvalC(const int i, const memindex integral)
+ { return ToComplex(DcacheC(integral)[i]); }
- double_complex E0iC(const int i, EARGS(_Cc_))
- { return EvalC(i, EgetC(EARGS(_Id_))); }
+ ComplexType D0i(const int i, DARGS(_lt_Cr_))
+ { return Dval(EPSINDEX(i), Dget(DARGS(_lt_Id_))); }
+
+ ComplexType D0iC(const int i, DARGS(_lt_Cc_))
+ { return DvalC(EPSINDEX(i), DgetC(DARGS(_lt_Id_))); }
+
+ ComplexType D0(DARGS(_lt_Cr_))
+ { return D0i(dd0, DARGS(_lt_Id_)); }
+ ComplexType D0C(DARGS(_lt_Cc_))
+ { return D0iC(dd0, DARGS(_lt_Id_)); }
/****************************************************************/
- double_complex Li2(const double x)
+ memindex Eget(EARGS(_lt_Cr_))
{
- DOUBLE_COMPLEX result;
- li2sub_(&result, _Frp_(x));
- return ToComplex(result);
+ return eget_(EARGS(_lt_Frp_));
}
- double_complex Li2C(const double_complex x)
+ memindex EgetC(EARGS(_lt_Cc_))
{
- DOUBLE_COMPLEX result;
- li2csub_(&result, _Fcp_(x));
- return ToComplex(result);
+ return egetc_(EARGS(_lt_Fcp_));
+ }
+
+ void Eput(ComplexType *res, EARGS(_lt_Cr_))
+ {
+ eput_(_lt_Fap_(res), EARGS(_lt_Frp_));
+ }
+
+ void EputC(ComplexType *res, EARGS(_lt_Cc_))
+ {
+ eputc_(_lt_Fap_(res), EARGS(_lt_Fcp_));
+ }
+
+ void E0nocache(ComplexType *res, EARGS(_lt_Cr_))
+ {
+ e0nocache_(_lt_Fap_(res), EARGS(_lt_Frp_));
+ }
+
+ void E0nocacheC(ComplexType *res, EARGS(_lt_Cc_))
+ {
+ e0nocachec_(_lt_Fap_(res), EARGS(_lt_Fcp_));
+ }
+
+ COMPLEX *Ecache(const memindex integral)
+ { return CACHEPTR(8,integral); }
+
+ COMPLEX *EcacheC(const memindex integral)
+ { return CACHEPTR(9,integral); }
+
+ ComplexType Eval(const int i, const memindex integral)
+ { return ToComplex(Ecache(integral)[i]); }
+
+ ComplexType EvalC(const int i, const memindex integral)
+ { return ToComplex(EcacheC(integral)[i]); }
+
+ ComplexType E0i(const int i, EARGS(_lt_Cr_))
+ { return Eval(EPSINDEX(i), Eget(EARGS(_lt_Id_))); }
+
+ ComplexType E0iC(const int i, EARGS(_lt_Cc_))
+ { return EvalC(EPSINDEX(i), EgetC(EARGS(_lt_Id_))); }
+
+ ComplexType E0(EARGS(_lt_Cr_))
+ { return E0i(ee0, EARGS(_lt_Id_)); }
+ ComplexType E0C(EARGS(_lt_Cc_))
+ { return E0iC(ee0, EARGS(_lt_Id_)); }
+
+ /****************************************************************/
+
+ ComplexType Li2(_lt_Cr_(x))
+ {
+ COMPLEX res;
+ li2sub_(&res, _lt_Frp_(x));
+ return ToComplex(res);
+ }
+
+ ComplexType Li2C(_lt_Cc_(x))
+ {
+ COMPLEX res;
+ li2csub_(&res, _lt_Fcp_(x));
+ return ToComplex(res);
+ }
+
+ ComplexType Li2omx(_lt_Cr_(x))
+ {
+ COMPLEX res;
+ li2omxsub_(&res, _lt_Frp_(x));
+ return ToComplex(res);
+ }
+
+ ComplexType Li2omxC(_lt_Cc_(x))
+ {
+ COMPLEX res;
+ li2omxcsub_(&res, _lt_Fcp_(x));
+ return ToComplex(res);
}
/****************************************************************/
+ void clearcache() { clearcache_(); }
+ void markcache() { markcache_(); }
+ void restorecache() { restorecache_(); }
- void setmudim(const double mudim)
- {
- ltregul_.mudim = mudim;
- clearcache();
+#define _lt_set_(v) \
+ ltregul_.v = v
+
+#define _lt_setx_(v) \
+ if( fabs(ltregul_.v - v) > (ltregul_.diffeps) ) \
+ clearcache(); \
+ ltregul_.v = v
+
+#define _lt_get_(v) \
+ return ltregul_.v
+
+
+ void setmudim(cRealType mudim) { _lt_setx_(mudim); }
+
+ RealType getmudim() { _lt_get_(mudim); }
+
+
+ void setdelta(cRealType delta) { _lt_setx_(delta); }
+
+ RealType getdelta() { _lt_get_(delta); }
+
+
+ void setuvdiv(cRealType uvdiv) { _lt_setx_(uvdiv); }
+
+ RealType getuvdiv() { _lt_get_(uvdiv); }
+
+
+ void setlambda(RealType lambda) {
+ int epsi = 0;
+ if( lambda <= 0 ) {
+ if( lambda != 0 && lambda != -1 && lambda != -2 ) {
+ fprintf(stderr, "illegal value for lambda\n");
+ lambda = 0;
+ }
+ epsi = -(int)lambda;
+ }
+ _lt_setx_(lambda);
+ ltvars_.epsi = epsi;
}
- double getmudim() { return ltregul_.mudim; }
+ RealType getlambda() { _lt_get_(lambda); }
-
- void setdelta(const double delta)
- {
- ltregul_.delta = delta;
- clearcache();
+ int getepsi() {
+ return ltvars_.epsi;
}
- double getdelta() { return ltregul_.delta; }
+ void setminmass(cRealType minmass) { _lt_setx_(minmass); }
- void setlambda(const double lambda)
- {
- ltregul_.lambda = lambda;
- clearcache();
- }
+ RealType getminmass() { _lt_get_(minmass); }
- double getlambda() { return ltregul_.lambda; }
-
- void setminmass(const double minmass)
- {
- ltregul_.minmass = minmass;
- clearcache();
- }
-
- double getminmass() { return ltregul_.minmass; }
-
-
- void setmaxdev(const double maxdev)
- {
+ void setmaxdev(cRealType maxdev) {
ltvars_.maxdev = maxdev;
}
- double getmaxdev() { return ltvars_.maxdev; }
+ RealType getmaxdev() { return ltvars_.maxdev; }
- void setwarndigits(const long warndigits)
- {
+ void setwarndigits(const int warndigits) {
ltvars_.warndigits = warndigits;
}
- long getwarndigits() { return ltvars_.warndigits; }
+ int getwarndigits() { return ltvars_.warndigits; }
- void seterrdigits(const long errdigits)
- {
+ void seterrdigits(const int errdigits) {
ltvars_.errdigits = errdigits;
}
- long geterrdigits() { return ltvars_.errdigits; }
+ int geterrdigits() { return ltvars_.errdigits; }
- void setversionkey(const long versionkey)
- {
+ void setversionkey(const int versionkey) {
ltvars_.versionkey = versionkey;
clearcache();
}
- long getversionkey() { return ltvars_.versionkey; }
+ int getversionkey() { return ltvars_.versionkey; }
- void setdebugkey(const long debugkey)
- {
+ void setdebugkey(const int debugkey) {
ltvars_.debugkey = debugkey;
}
- long getdebugkey() { return ltvars_.debugkey; }
+ int getdebugkey() { return ltvars_.debugkey; }
- void setdebugrange(const long debugfrom, const long debugto)
+ void setdebugrange(const int debugfrom, const int debugto)
{
ltvars_.debugfrom = debugfrom;
ltvars_.debugto = debugto;
}
- void setcmpbits(const long cmpbits)
+ void setcmpbits(const int cmpbits)
{
ltcache_.cmpbits = cmpbits;
}
- long getcmpbits() { return ltcache_.cmpbits; }
+ int getcmpbits() { return ltcache_.cmpbits; }
- void clearcache() { clearcache_(); }
- void markcache() { markcache_(); }
- void restorecache() { restorecache_(); }
+ void setdiffeps(cRealType diffeps) { _lt_set_(diffeps); }
+
+ RealType getdiffeps() { _lt_get_(diffeps); }
+
+
+ void setzeroeps(cRealType zeroeps) { _lt_set_(zeroeps); }
+
+ RealType getzeroeps() { _lt_get_(zeroeps); }
} // namespace Looptools
} // namespace Herwig
diff --git a/Looptools/include/cexternals.h b/Looptools/include/cexternals.h
--- a/Looptools/include/cexternals.h
+++ b/Looptools/include/cexternals.h
@@ -1,6 +1,7 @@
#if 0
-This file was generated by mkexternalsh on Thu Dec 9 09:13:07 CET 2010.
+This file was generated by mkexternalsh on Fri Feb 21 10:42:16 CET 2014.
Do not edit.
#endif
-#define cachelookup_ ljcachelookup_
+#define cachecopy_ ljcachecopy_
+#define cacheindex_ ljcacheindex_
diff --git a/Looptools/include/clooptools.h b/Looptools/include/clooptools.h
--- a/Looptools/include/clooptools.h
+++ b/Looptools/include/clooptools.h
@@ -1,302 +1,525 @@
/* -*- C++ -*-
clooptools.h
the C/C++ header file with all definitions for LoopTools
this file is part of LoopTools
- last modified 9 Dec 10 th
+ last modified 2 Sep 14 th
dgrell 2011-01-21 for Herwig: moved definitions and extern declarations to our clooptools.cc
+ dgrell 2016-09-08 for Herwig: update to Looptols-2.13
*/
#ifndef HERWIG_clooptools_h_
#define HERWIG_clooptools_h_
+#include <complex>
+
+/****************************************************************/
+
+// Adapted version of ftypes.h
+
+
+typedef double RealType;
+typedef double REAL;
+
+typedef int INTEGER;
+typedef const REAL CREAL;
+
+struct COMPLEX { REAL re, im; };
+typedef const COMPLEX CCOMPLEX;
+
+typedef std::complex<RealType> ComplexType;
+
+typedef const RealType cRealType;
+typedef const ComplexType cComplexType;
+
//#define cachelookup_ ljcachelookup_
-/** complex defn for Looptools
- */
-struct DOUBLE_COMPLEX {
- /**
- * Real part
- */
- double re;
+// typedef const COMPLEX CCOMPLEX;
- /**
- * Imaginary part
- */
- double im;
-};
-typedef const DOUBLE_COMPLEX CDOUBLE_COMPLEX;
-
-#include <complex>
-typedef std::complex<double> double_complex;
+typedef long long int memindex;
/****************************************************************/
#define AARGS(t) t(m)
#define BARGS(t) t(p), t(m1), t(m2)
#define CARGS(t) t(p1), t(p2), t(p1p2), t(m1), t(m2), t(m3)
#define DARGS(t) t(p1), t(p2), t(p3), t(p4), t(p1p2), t(p2p3), \
t(m1), t(m2), t(m3), t(m4)
#define EARGS(t) t(p1), t(p2), t(p3), t(p4), t(p5), \
t(p1p2), t(p2p3), t(p3p4), t(p4p5), t(p5p1), \
t(m1), t(m2), t(m3), t(m4), t(m5)
-#define _Cr_(v) const double v
-#define _Cc_(v) const double_complex v
-#define _Fr_(v) const double *v
-#define _Fc_(v) CDOUBLE_COMPLEX *v
-#define _Frp_(v) &v
-#define _Fcp_(v) (CDOUBLE_COMPLEX *)&v
-#define _Id_(v) v
+/****************************************************************/
+
+#define _lt_Cr_(v) cRealType v
+#define _lt_Cc_(v) cComplexType v
+#define _lt_Fr_(v) CREAL *v
+#define _lt_Fc_(v) CCOMPLEX *v
+#define _lt_Id_(v) v
+#define _lt_Frp_(v) &v
+#define _lt_Fcp_(v) (CCOMPLEX *)&v
+#define _lt_Fap_(v) (COMPLEX *)v
+
+// #define _lt_Frd_(f)
+// #define _lt_Fcd_(f)
+// #define _lt_Fad_(v,n)
+// #define _lt_Fax_(v,n)
/****************************************************************/
namespace Herwig {
namespace Looptools {
enum {
- bb0, bb1, bb00, bb11, bb001, bb111, dbb0, dbb1, dbb00, dbb11,
- Nbb
+ aa0 = 0,
+ aa00 = 3,
+ Naa = 6
};
enum {
- cc0, cc1, cc2, cc00, cc11, cc12, cc22, cc001, cc002, cc111, cc112,
- cc122, cc222, cc0000, cc0011, cc0012, cc0022, cc1111, cc1112, cc1122,
- cc1222, cc2222,
- Ncc
+ bb0 = 0,
+ bb1 = 3,
+ bb00 = 6,
+ bb11 = 9,
+ bb001 = 12,
+ bb111 = 15,
+ dbb0 = 18,
+ dbb1 = 21,
+ dbb00 = 24,
+ dbb11 = 27,
+ dbb001 = 30,
+ Nbb = 33
};
enum {
- dd0, dd1, dd2, dd3, dd00, dd11, dd12, dd13, dd22, dd23, dd33,
- dd001, dd002, dd003, dd111, dd112, dd113, dd122, dd123, dd133, dd222,
- dd223, dd233, dd333, dd0000, dd0011, dd0012, dd0013, dd0022, dd0023,
- dd0033, dd1111, dd1112, dd1113, dd1122, dd1123, dd1133, dd1222,
- dd1223, dd1233, dd1333, dd2222, dd2223, dd2233, dd2333, dd3333,
- dd00001, dd00002, dd00003, dd00111, dd00112, dd00113, dd00122,
- dd00123, dd00133, dd00222, dd00223, dd00233, dd00333, dd11111,
- dd11112, dd11113, dd11122, dd11123, dd11133, dd11222, dd11223,
- dd11233, dd11333, dd12222, dd12223, dd12233, dd12333, dd13333,
- dd22222, dd22223, dd22233, dd22333, dd23333, dd33333,
- Ndd
+ cc0 = 0,
+ cc1 = 3,
+ cc2 = 6,
+ cc00 = 9,
+ cc11 = 12,
+ cc12 = 15,
+ cc22 = 18,
+ cc001 = 21,
+ cc002 = 24,
+ cc111 = 27,
+ cc112 = 30,
+ cc122 = 33,
+ cc222 = 36,
+ cc0000 = 39,
+ cc0011 = 42,
+ cc0012 = 45,
+ cc0022 = 48,
+ cc1111 = 51,
+ cc1112 = 54,
+ cc1122 = 57,
+ cc1222 = 60,
+ cc2222 = 63,
+ Ncc = 66
};
enum {
- ee0, ee1, ee2, ee3, ee4, ee00, ee11, ee12, ee13, ee14, ee22, ee23,
- ee24, ee33, ee34, ee44, ee001, ee002, ee003, ee004, ee111, ee112,
- ee113, ee114, ee122, ee123, ee124, ee133, ee134, ee144, ee222,
- ee223, ee224, ee233, ee234, ee244, ee333, ee334, ee344, ee444,
- ee0000, ee0011, ee0012, ee0013, ee0014, ee0022, ee0023, ee0024,
- ee0033, ee0034, ee0044, ee1111, ee1112, ee1113, ee1114, ee1122,
- ee1123, ee1124, ee1133, ee1134, ee1144, ee1222, ee1223, ee1224,
- ee1233, ee1234, ee1244, ee1333, ee1334, ee1344, ee1444, ee2222,
- ee2223, ee2224, ee2233, ee2234, ee2244, ee2333, ee2334, ee2344,
- ee2444, ee3333, ee3334, ee3344, ee3444, ee4444,
- Nee
+ dd0 = 0,
+ dd1 = 3,
+ dd2 = 6,
+ dd3 = 9,
+ dd00 = 12,
+ dd11 = 15,
+ dd12 = 18,
+ dd13 = 21,
+ dd22 = 24,
+ dd23 = 27,
+ dd33 = 30,
+ dd001 = 33,
+ dd002 = 36,
+ dd003 = 39,
+ dd111 = 42,
+ dd112 = 45,
+ dd113 = 48,
+ dd122 = 51,
+ dd123 = 54,
+ dd133 = 57,
+ dd222 = 60,
+ dd223 = 63,
+ dd233 = 66,
+ dd333 = 69,
+ dd0000 = 72,
+ dd0011 = 75,
+ dd0012 = 78,
+ dd0013 = 81,
+ dd0022 = 84,
+ dd0023 = 87,
+ dd0033 = 90,
+ dd1111 = 93,
+ dd1112 = 96,
+ dd1113 = 99,
+ dd1122 = 102,
+ dd1123 = 105,
+ dd1133 = 108,
+ dd1222 = 111,
+ dd1223 = 114,
+ dd1233 = 117,
+ dd1333 = 120,
+ dd2222 = 123,
+ dd2223 = 126,
+ dd2233 = 129,
+ dd2333 = 132,
+ dd3333 = 135,
+ dd00001 = 138,
+ dd00002 = 141,
+ dd00003 = 144,
+ dd00111 = 147,
+ dd00112 = 150,
+ dd00113 = 153,
+ dd00122 = 156,
+ dd00123 = 159,
+ dd00133 = 162,
+ dd00222 = 165,
+ dd00223 = 168,
+ dd00233 = 171,
+ dd00333 = 174,
+ dd11111 = 177,
+ dd11112 = 180,
+ dd11113 = 183,
+ dd11122 = 186,
+ dd11123 = 189,
+ dd11133 = 192,
+ dd11222 = 195,
+ dd11223 = 198,
+ dd11233 = 201,
+ dd11333 = 204,
+ dd12222 = 207,
+ dd12223 = 210,
+ dd12233 = 213,
+ dd12333 = 216,
+ dd13333 = 219,
+ dd22222 = 222,
+ dd22223 = 225,
+ dd22233 = 228,
+ dd22333 = 231,
+ dd23333 = 234,
+ dd33333 = 237,
+ Ndd = 240
+ };
+
+ enum {
+ ee0 = 0,
+ ee1 = 3,
+ ee2 = 6,
+ ee3 = 9,
+ ee4 = 12,
+ ee00 = 15,
+ ee11 = 18,
+ ee12 = 21,
+ ee13 = 24,
+ ee14 = 27,
+ ee22 = 30,
+ ee23 = 33,
+ ee24 = 36,
+ ee33 = 39,
+ ee34 = 42,
+ ee44 = 45,
+ ee001 = 48,
+ ee002 = 51,
+ ee003 = 54,
+ ee004 = 57,
+ ee111 = 60,
+ ee112 = 63,
+ ee113 = 66,
+ ee114 = 69,
+ ee122 = 72,
+ ee123 = 75,
+ ee124 = 78,
+ ee133 = 81,
+ ee134 = 84,
+ ee144 = 87,
+ ee222 = 90,
+ ee223 = 93,
+ ee224 = 96,
+ ee233 = 99,
+ ee234 = 102,
+ ee244 = 105,
+ ee333 = 108,
+ ee334 = 111,
+ ee344 = 114,
+ ee444 = 117,
+ ee0000 = 120,
+ ee0011 = 123,
+ ee0012 = 126,
+ ee0013 = 129,
+ ee0014 = 132,
+ ee0022 = 135,
+ ee0023 = 138,
+ ee0024 = 141,
+ ee0033 = 144,
+ ee0034 = 147,
+ ee0044 = 150,
+ ee1111 = 153,
+ ee1112 = 156,
+ ee1113 = 159,
+ ee1114 = 162,
+ ee1122 = 165,
+ ee1123 = 168,
+ ee1124 = 171,
+ ee1133 = 174,
+ ee1134 = 177,
+ ee1144 = 180,
+ ee1222 = 183,
+ ee1223 = 186,
+ ee1224 = 189,
+ ee1233 = 192,
+ ee1234 = 195,
+ ee1244 = 198,
+ ee1333 = 201,
+ ee1334 = 204,
+ ee1344 = 207,
+ ee1444 = 210,
+ ee2222 = 213,
+ ee2223 = 216,
+ ee2224 = 219,
+ ee2233 = 222,
+ ee2234 = 225,
+ ee2244 = 228,
+ ee2333 = 231,
+ ee2334 = 234,
+ ee2344 = 237,
+ ee2444 = 240,
+ ee3333 = 243,
+ ee3334 = 246,
+ ee3344 = 249,
+ ee3444 = 252,
+ ee4444 = 255,
+ Nee = 258
};
enum {
KeyA0 = 1,
KeyBget = 1<<2,
KeyC0 = 1<<4,
KeyD0 = 1<<6,
KeyE0 = 1<<8,
KeyEget = 1<<10,
KeyEgetC = 1<<12,
KeyAll = KeyA0 + KeyBget + KeyC0 + KeyD0 + KeyE0 + KeyEget + KeyEgetC
};
enum {
- DebugB = 1,
- DebugC = 1<<1,
- DebugD = 1<<2,
- DebugE = 1<<3,
- DebugAll = DebugB + DebugC + DebugD + DebugE
+ DebugA = 1,
+ DebugB = 1<<1,
+ DebugC = 1<<2,
+ DebugD = 1<<3,
+ DebugE = 1<<4,
+ DebugAll = DebugA + DebugB + DebugC + DebugD + DebugE
};
- double_complex ToComplex(DOUBLE_COMPLEX c);
+ ComplexType ToComplex(COMPLEX c);
/**
* Looptools initialisation
*/
void ltini(std::string logfilename = std::string("Looptools.log"));
/**
* Looptools termination
*/
void ltexi(std::string logfilename = std::string("Looptools.log"));
+ /****************************************************************/
- double_complex A0(AARGS(_Cr_));
- double_complex A0C(AARGS(_Cc_));
- double_complex A00(AARGS(_Cr_));
+ memindex Aget(AARGS(_lt_Cr_));
+ memindex AgetC(AARGS(_lt_Cc_));
- double_complex A00C(AARGS(_Cc_));
+ void Aput(ComplexType *res, AARGS(_lt_Cr_));
+ void AputC(ComplexType *res, AARGS(_lt_Cc_));
+
+ void Aputnocache(ComplexType *res, AARGS(_lt_Cr_));
+ void AputnocacheC(ComplexType *res, AARGS(_lt_Cc_));
+
+ COMPLEX *Acache(const memindex integral);
+ COMPLEX *AcacheC(const memindex integral);
+
+ ComplexType Aval(const int i, const memindex integral);
+ ComplexType AvalC(const int i, const memindex integral);
+
+ ComplexType A0i(const int i, AARGS(_lt_Cr_));
+ ComplexType A0iC(const int i, AARGS(_lt_Cc_));
+
+ ComplexType A0(AARGS(_lt_Cr_));
+ ComplexType A00(AARGS(_lt_Cr_));
+
+ ComplexType A0C(AARGS(_lt_Cc_));
+ ComplexType A00C(AARGS(_lt_Cc_));
/****************************************************************/
- long Bget(BARGS(_Cr_));
- long BgetC(BARGS(_Cc_));
- DOUBLE_COMPLEX *Bcache(const long integral);
- DOUBLE_COMPLEX *BcacheC(const long integral);
+ memindex Bget(BARGS(_lt_Cr_));
+ memindex BgetC(BARGS(_lt_Cc_));
- double_complex Bval(const int i, const long integral);
+ void Bput(ComplexType *res, BARGS(_lt_Cr_));
+ void BputC(ComplexType *res, BARGS(_lt_Cc_));
- double_complex BvalC(const int i, const long integral);
+ void Bputnocache(ComplexType *res, BARGS(_lt_Cr_));
+ void BputnocacheC(ComplexType *res, BARGS(_lt_Cc_));
- double_complex B0i(const int i, BARGS(_Cr_));
+ COMPLEX *Bcache(const memindex integral);
+ COMPLEX *BcacheC(const memindex integral);
- double_complex B0iC(const int i, BARGS(_Cc_));
+ ComplexType Bval(const int i, const memindex integral);
+ ComplexType BvalC(const int i, const memindex integral);
- double_complex B0(BARGS(_Cr_));
- double_complex B1(BARGS(_Cr_));
- double_complex B00(BARGS(_Cr_));
- double_complex B11(BARGS(_Cr_));
- double_complex B001(BARGS(_Cr_));
- double_complex B111(BARGS(_Cr_));
- double_complex DB0(BARGS(_Cr_));
- double_complex DB1(BARGS(_Cr_));
- double_complex DB00(BARGS(_Cr_));
- double_complex DB11(BARGS(_Cr_));
+ ComplexType B0i(const int i, BARGS(_lt_Cr_));
+ ComplexType B0iC(const int i, BARGS(_lt_Cc_));
- double_complex B0C(BARGS(_Cc_));
- double_complex B1C(BARGS(_Cc_));
- double_complex B00C(BARGS(_Cc_));
- double_complex B11C(BARGS(_Cc_));
- double_complex B001C(BARGS(_Cc_));
- double_complex B111C(BARGS(_Cc_));
- double_complex DB0C(BARGS(_Cc_));
- double_complex DB1C(BARGS(_Cc_));
- double_complex DB00C(BARGS(_Cc_));
- double_complex DB11C(BARGS(_Cc_));
+ ComplexType B0(BARGS(_lt_Cr_));
+ ComplexType B1(BARGS(_lt_Cr_));
+ ComplexType B00(BARGS(_lt_Cr_));
+ ComplexType B11(BARGS(_lt_Cr_));
+ ComplexType B001(BARGS(_lt_Cr_));
+ ComplexType B111(BARGS(_lt_Cr_));
+ ComplexType DB0(BARGS(_lt_Cr_));
+ ComplexType DB1(BARGS(_lt_Cr_));
+ ComplexType DB00(BARGS(_lt_Cr_));
+ ComplexType DB11(BARGS(_lt_Cr_));
+
+ ComplexType B0C(BARGS(_lt_Cc_));
+ ComplexType B1C(BARGS(_lt_Cc_));
+ ComplexType B00C(BARGS(_lt_Cc_));
+ ComplexType B11C(BARGS(_lt_Cc_));
+ ComplexType B001C(BARGS(_lt_Cc_));
+ ComplexType B111C(BARGS(_lt_Cc_));
+ ComplexType DB0C(BARGS(_lt_Cc_));
+ ComplexType DB1C(BARGS(_lt_Cc_));
+ ComplexType DB00C(BARGS(_lt_Cc_));
+ ComplexType DB11C(BARGS(_lt_Cc_));
/****************************************************************/
- double_complex C0(CARGS(_Cr_));
+ memindex Cget(CARGS(_lt_Cr_));
+ memindex CgetC(CARGS(_lt_Cc_));
- double_complex C0C(CARGS(_Cc_));
+ void Cput(ComplexType *res, CARGS(_lt_Cr_));
+ void CputC(ComplexType *res, CARGS(_lt_Cc_));
- long Cget(CARGS(_Cr_));
+ void C0nocache(ComplexType *res, CARGS(_lt_Cr_));
+ void C0nocacheC(ComplexType *res, CARGS(_lt_Cc_));
- long CgetC(CARGS(_Cc_));
+ COMPLEX *Ccache(const memindex integral);
+ COMPLEX *CcacheC(const memindex integral);
- DOUBLE_COMPLEX *Ccache(const long integral);
+ ComplexType Cval(const int i, const memindex integral);
+ ComplexType CvalC(const int i, const memindex integral);
- DOUBLE_COMPLEX *CcacheC(const long integral);
+ ComplexType C0i(const int i, CARGS(_lt_Cr_));
+ ComplexType C0iC(const int i, CARGS(_lt_Cc_));
- double_complex Cval(const int i, const long integral);
-
- double_complex CvalC(const int i, const long integral);
-
- double_complex C0i(const int i, CARGS(_Cr_));
-
- double_complex C0iC(const int i, CARGS(_Cc_));
+ ComplexType C0(CARGS(_lt_Cr_));
+ ComplexType C0C(CARGS(_lt_Cc_));
/****************************************************************/
- double_complex D0(DARGS(_Cr_));
+ memindex Dget(DARGS(_lt_Cr_));
+ memindex DgetC(DARGS(_lt_Cc_));
- double_complex D0C(DARGS(_Cc_));
+ void Dput(ComplexType *res, DARGS(_lt_Cr_));
+ void DputC(ComplexType *res, DARGS(_lt_Cc_));
- long Dget(DARGS(_Cr_));
+ void D0nocache(ComplexType *res, DARGS(_lt_Cr_));
+ void D0nocacheC(ComplexType *res, DARGS(_lt_Cc_));
- long DgetC(DARGS(_Cc_));
+ COMPLEX *Dcache(const memindex integral);
+ COMPLEX *DcacheC(const memindex integral);
- DOUBLE_COMPLEX *Dcache(const long integral);
+ ComplexType Dval(const int i, const memindex integral);
+ ComplexType DvalC(const int i, const memindex integral);
- DOUBLE_COMPLEX *DcacheC(const long integral);
+ ComplexType D0i(const int i, DARGS(_lt_Cr_));
+ ComplexType D0iC(const int i, DARGS(_lt_Cc_));
- double_complex Dval(const int i, const long integral);
-
- double_complex DvalC(const int i, const long integral);
-
- double_complex D0i(const int i, DARGS(_Cr_));
-
- double_complex D0iC(const int i, DARGS(_Cc_));
+ ComplexType D0(DARGS(_lt_Cr_));
+ ComplexType D0C(DARGS(_lt_Cc_));
/****************************************************************/
- double_complex E0(EARGS(_Cr_));
+ memindex Eget(EARGS(_lt_Cr_));
+ memindex EgetC(EARGS(_lt_Cc_));
- double_complex E0C(EARGS(_Cc_));
+ void Eput(ComplexType *res, EARGS(_lt_Cr_));
+ void EputC(ComplexType *res, EARGS(_lt_Cc_));
- long Eget(EARGS(_Cr_));
+ void E0nocache(ComplexType *res, EARGS(_lt_Cr_));
+ void E0nocacheC(ComplexType *res, EARGS(_lt_Cc_));
- long EgetC(EARGS(_Cc_));
+ COMPLEX *Ecache(const memindex integral);
+ COMPLEX *EcacheC(const memindex integral);
- DOUBLE_COMPLEX *Ecache(const long integral);
+ ComplexType Eval(const int i, const memindex integral);
+ ComplexType EvalC(const int i, const memindex integral);
- DOUBLE_COMPLEX *EcacheC(const long integral);
+ ComplexType E0i(const int i, EARGS(_lt_Cr_));
+ ComplexType E0iC(const int i, EARGS(_lt_Cc_));
- double_complex Eval(const int i, const long integral);
-
- double_complex EvalC(const int i, const long integral);
-
- double_complex E0i(const int i, EARGS(_Cr_));
-
- double_complex E0iC(const int i, EARGS(_Cc_));
+ ComplexType E0(EARGS(_lt_Cr_));
+ ComplexType E0C(EARGS(_lt_Cc_));
/****************************************************************/
- double_complex Li2(const double x);
-
- double_complex Li2C(const double_complex x);
+ ComplexType Li2(_lt_Cr_(x));
+ ComplexType Li2C(_lt_Cc_(x));
+ ComplexType Li2omx(_lt_Cr_(x));
+ ComplexType Li2omxC(_lt_Cc_(x));
/****************************************************************/
-
- void setmudim(const double mudim);
-
- double getmudim();
-
-
- void setdelta(const double delta);
-
- double getdelta();
-
-
- void setlambda(const double lambda);
- double getlambda();
-
-
- void setminmass(const double minmass);
- double getminmass();
-
-
- void setmaxdev(const double maxdev);
- double getmaxdev();
-
-
- void setwarndigits(const long warndigits);
- long getwarndigits();
-
-
- void seterrdigits(const long errdigits);
- long geterrdigits();
-
-
- void setversionkey(const long versionkey);
- long getversionkey();
-
- void setdebugkey(const long debugkey);
- long getdebugkey();
-
-
- void setdebugrange(const long debugfrom, const long debugto);
-
- void setcmpbits(const long cmpbits);
-
- long getcmpbits();
-
void clearcache();
void markcache();
void restorecache();
+ void setmudim(cRealType mudim);
+ RealType getmudim();
+
+ void setdelta(cRealType delta);
+ RealType getdelta();
+
+ void setuvdiv(cRealType uvdiv);
+ RealType getuvdiv();
+
+ void setlambda(cRealType lambda);
+ RealType getlambda();
+
+ void setminmass(cRealType minmass);
+ RealType getminmass();
+
+ void setmaxdev(cRealType maxdev);
+ RealType getmaxdev();
+
+ void setwarndigits(const int warndigits);
+ int getwarndigits();
+
+ void seterrdigits(const int errdigits);
+ int geterrdigits();
+
+ void setversionkey(const int versionkey);
+ int getversionkey();
+
+ void setdebugkey(const int debugkey);
+ int getdebugkey();
+
+ void setdebugrange(const int debugfrom, const int debugto);
+
+ void setcmpbits(const int cmpbits);
+ int getcmpbits();
+
+ void setdiffeps(cRealType diffeps);
+ RealType getdiffeps();
+
+ void setzeroeps(cRealType zeroeps);
+ RealType getzeroeps();
+
} // namespace Looptools
} // namespace Herwig
#endif
diff --git a/Looptools/include/defs.h b/Looptools/include/defs.h
--- a/Looptools/include/defs.h
+++ b/Looptools/include/defs.h
@@ -1,379 +1,645 @@
* defs.h
* internal definitions for the LoopTools routines
* this file is part of LoopTools
-* last modified 7 Dec 10 th
-
-#include "externals.h"
+* last modified 28 Feb 14 th
#ifdef COMPLEXPARA
+#define XAget AgetC
+#define XAput AputC
+#define XAputnocache AputnocacheC
+#define XA0i A0iC
#define XA0 A0C
-#define XA0b A0bC
-#define XA0sub a0subc
#define XA00 A00C
-#define XA00sub a00subc
+#define XAcoeff AcoeffC
+#define XBpara BparaC
+#define XBget BgetC
+#define XBput BputC
+#define XBputnocache BputnocacheC
+#define XB0i B0iC
#define XB0 B0C
#define XB1 B1C
#define XB00 B00C
#define XB11 B11C
#define XB001 B001C
#define XB111 B111C
#define XDB0 DB0C
#define XDB1 DB1C
#define XDB00 DB00C
#define XDB11 DB11C
-#define XB0i B0iC
-#define XBget BgetC
+#define XDB001 DB001C
#define XBcoeff BcoeffC
-#define XBcoeffa BcoeffaC
+#define XBcoeffFF BcoeffFFC
+#define XC0func C0funcC
+#define XCpara CparaC
+#define XCget CgetC
+#define XCput CputC
+#define XC0nocache C0nocacheC
+#define XC0i C0iC
#define XC0 C0C
-#define XC0i C0iC
-#define XCget CgetC
+#define XCcoefx CcoefxC
#define XCcoeff CcoeffC
+#define XD0func D0funcC
+#define XDpara DparaC
+#define XDget DgetC
+#define XDput DputC
+#define XD0nocache D0nocacheC
+#define XD0i D0iC
#define XD0 D0C
-#define XD0i D0iC
-#define XDget DgetC
+#define XDcoefx DcoefxC
#define XDcoeff DcoeffC
+#define XE0func E0funcC
+#define XEpara EparaC
+#define XEget EgetC
+#define XEput EputC
+#define XE0nocache E0nocacheC
+#define XE0i E0iC
#define XE0 E0C
-#define XE0sub e0subc
-#define XE0i E0iC
-#define XEget EgetC
+#define XEcoefx EcoefxC
#define XEcoeff EcoeffC
#define XEcoeffa EcoeffaC
#define XEcoeffb EcoeffbC
#define XEcheck EcheckC
#define XInvGramE InvGramEC
#define XSolve SolveC
#define XEigen EigenC
#define XDecomp DecompC
#define XDet DetmC
#define XInverse InverseC
#define XDumpPara DumpParaC
#define XDumpCoeff DumpCoeffC
#define XLi2 Li2C
#define XLi2sub li2csub
+#define XLi2omx Li2omxC
+#define XLi2omxsub li2omxcsub
#define Xfpij2 cfpij2
#define Xffa0 ffca0
#define Xffb0 ffcb0
#define Xffb1 ffcb1
#define Xffb2p ffcb2p
#define Xffdb0 ffcdb0
#define RC 2
-#define DVAR double complex
-#define QVAR double complex
-#define QREAL double precision
+#define DVAR ComplexType
+#define QVAR ComplexType
+#define QREAL RealType
#define QPREC(x) x
-#define QCC(x) DCONJG(x)
-#define QRE(x) DBLE(x)
+#define QCC(x) Conjugate(x)
+#define QRE(x) Re(x)
#else
+#define XAget Aget
+#define XAput Aput
+#define XAputnocache Aputnocache
+#define XA0i A0i
#define XA0 A0
-#define XA0b A0b
-#define XA0sub a0sub
#define XA00 A00
-#define XA00sub a00sub
+#define XAcoeff Acoeff
+#define XBpara Bpara
+#define XBget Bget
+#define XBput Bput
+#define XBputnocache Bputnocache
+#define XB0i B0i
#define XB0 B0
#define XB1 B1
#define XB00 B00
#define XB11 B11
#define XB001 B001
#define XB111 B111
#define XDB0 DB0
#define XDB1 DB1
#define XDB00 DB00
#define XDB11 DB11
-#define XB0i B0i
-#define XBget Bget
+#define XDB001 DB001
#define XBcoeff Bcoeff
-#define XBcoeffa Bcoeffa
+#define XBcoeffFF BcoeffFF
+#define XC0func C0func
+#define XCpara Cpara
+#define XCget Cget
+#define XCput Cput
+#define XC0nocache C0nocache
+#define XC0i C0i
#define XC0 C0
-#define XC0i C0i
-#define XCget Cget
+#define XCcoefx Ccoefx
#define XCcoeff Ccoeff
+#define XD0func D0func
+#define XDpara Dpara
+#define XDget Dget
+#define XDput Dput
+#define XD0nocache D0nocache
+#define XD0i D0i
#define XD0 D0
-#define XD0i D0i
-#define XDget Dget
+#define XDcoefx Dcoefx
#define XDcoeff Dcoeff
+#define XE0func E0func
+#define XEpara Epara
+#define XEget Eget
+#define XEput Eput
+#define XE0nocache E0nocache
+#define XE0i E0i
#define XE0 E0
-#define XE0sub e0sub
-#define XE0i E0i
-#define XEget Eget
+#define XEcoefx Ecoefx
#define XEcoeff Ecoeff
#define XEcoeffa Ecoeffa
#define XEcoeffb Ecoeffb
#define XEcheck Echeck
#define XInvGramE InvGramE
#define XSolve Solve
#define XEigen Eigen
#define XDecomp Decomp
#define XDet Detm
#define XInverse Inverse
#define XDumpPara DumpPara
#define XDumpCoeff DumpCoeff
#define XLi2 Li2
#define XLi2sub li2sub
+#define XLi2omx Li2omx
+#define XLi2omxsub li2omxsub
#define Xfpij2 fpij2
#define Xffa0 ffxa0
#define Xffb0 ffxb0
#define Xffb1 ffxb1
#define Xffb2p ffxb2p
#define Xffdb0 ffxdb0
#define RC 1
-#define DVAR double precision
+#define DVAR RealType
#if QUAD
#define QVAR real*16
#define QPREC(x) QEXT(x)
#else
-#define QVAR double precision
+#define QVAR RealType
#define QPREC(x) x
#endif
#define QREAL QVAR
#define QCC(x) x
#define QRE(x) x
#endif
+#define Paa 1
+#define Pbb 3
+#define Pcc 6
+#define Pdd 10
+#define Pee 15
+
+#define aa0 1
+#define AA0 1:3
+#define aa00 4
+#define AA00 4:6
+#define Naa 6
+
#define bb0 1
-#define bb1 2
-#define bb00 3
-#define bb11 4
-#define bb001 5
-#define bb111 6
-#define dbb0 7
-#define dbb1 8
-#define dbb00 9
-#define dbb11 10
-#define Pbb 3
-#define Nbb 10
+#define BB0 1:3
+#define bb1 4
+#define BB1 4:6
+#define bb00 7
+#define BB00 7:9
+#define bb11 10
+#define BB11 10:12
+#define bb001 13
+#define BB001 13:15
+#define bb111 16
+#define BB111 16:18
+#define dbb0 19
+#define DBB0 19:21
+#define dbb1 22
+#define DBB1 22:24
+#define dbb00 25
+#define DBB00 25:27
+#define dbb11 28
+#define DBB11 28:30
+#define dbb001 31
+#define DBB001 31:33
+#define Nbb 33
#define cc0 1
-#define cc1 2
-#define cc2 3
-#define cc00 4
-#define cc11 5
-#define cc12 6
-#define cc22 7
-#define cc001 8
-#define cc002 9
-#define cc111 10
-#define cc112 11
-#define cc122 12
-#define cc222 13
-#define cc0000 14
-#define cc0011 15
-#define cc0012 16
-#define cc0022 17
-#define cc1111 18
-#define cc1112 19
-#define cc1122 20
-#define cc1222 21
-#define cc2222 22
-#define Pcc 6
-#define Ncc 22
+#define CC0 1:3
+#define cc1 4
+#define CC1 4:6
+#define cc2 7
+#define CC2 7:9
+#define cc00 10
+#define CC00 10:12
+#define cc11 13
+#define CC11 13:15
+#define cc12 16
+#define CC12 16:18
+#define cc22 19
+#define CC22 19:21
+#define cc001 22
+#define CC001 22:24
+#define cc002 25
+#define CC002 25:27
+#define cc111 28
+#define CC111 28:30
+#define cc112 31
+#define CC112 31:33
+#define cc122 34
+#define CC122 34:36
+#define cc222 37
+#define CC222 37:39
+#define cc0000 40
+#define CC0000 40:42
+#define cc0011 43
+#define CC0011 43:45
+#define cc0012 46
+#define CC0012 46:48
+#define cc0022 49
+#define CC0022 49:51
+#define cc1111 52
+#define CC1111 52:54
+#define cc1112 55
+#define CC1112 55:57
+#define cc1122 58
+#define CC1122 58:60
+#define cc1222 61
+#define CC1222 61:63
+#define cc2222 64
+#define CC2222 64:66
+#define Ncc 66
#define dd0 1
-#define dd1 2
-#define dd2 3
-#define dd3 4
-#define dd00 5
-#define dd11 6
-#define dd12 7
-#define dd13 8
-#define dd22 9
-#define dd23 10
-#define dd33 11
-#define dd001 12
-#define dd002 13
-#define dd003 14
-#define dd111 15
-#define dd112 16
-#define dd113 17
-#define dd122 18
-#define dd123 19
-#define dd133 20
-#define dd222 21
-#define dd223 22
-#define dd233 23
-#define dd333 24
-#define dd0000 25
-#define dd0011 26
-#define dd0012 27
-#define dd0013 28
-#define dd0022 29
-#define dd0023 30
-#define dd0033 31
-#define dd1111 32
-#define dd1112 33
-#define dd1113 34
-#define dd1122 35
-#define dd1123 36
-#define dd1133 37
-#define dd1222 38
-#define dd1223 39
-#define dd1233 40
-#define dd1333 41
-#define dd2222 42
-#define dd2223 43
-#define dd2233 44
-#define dd2333 45
-#define dd3333 46
-#define dd00001 47
-#define dd00002 48
-#define dd00003 49
-#define dd00111 50
-#define dd00112 51
-#define dd00113 52
-#define dd00122 53
-#define dd00123 54
-#define dd00133 55
-#define dd00222 56
-#define dd00223 57
-#define dd00233 58
-#define dd00333 59
-#define dd11111 60
-#define dd11112 61
-#define dd11113 62
-#define dd11122 63
-#define dd11123 64
-#define dd11133 65
-#define dd11222 66
-#define dd11223 67
-#define dd11233 68
-#define dd11333 69
-#define dd12222 70
-#define dd12223 71
-#define dd12233 72
-#define dd12333 73
-#define dd13333 74
-#define dd22222 75
-#define dd22223 76
-#define dd22233 77
-#define dd22333 78
-#define dd23333 79
-#define dd33333 80
-#define Pdd 10
-#define Ndd 80
+#define DD0 1:3
+#define dd1 4
+#define DD1 4:6
+#define dd2 7
+#define DD2 7:9
+#define dd3 10
+#define DD3 10:12
+#define dd00 13
+#define DD00 13:15
+#define dd11 16
+#define DD11 16:18
+#define dd12 19
+#define DD12 19:21
+#define dd13 22
+#define DD13 22:24
+#define dd22 25
+#define DD22 25:27
+#define dd23 28
+#define DD23 28:30
+#define dd33 31
+#define DD33 31:33
+#define dd001 34
+#define DD001 34:36
+#define dd002 37
+#define DD002 37:39
+#define dd003 40
+#define DD003 40:42
+#define dd111 43
+#define DD111 43:45
+#define dd112 46
+#define DD112 46:48
+#define dd113 49
+#define DD113 49:51
+#define dd122 52
+#define DD122 52:54
+#define dd123 55
+#define DD123 55:57
+#define dd133 58
+#define DD133 58:60
+#define dd222 61
+#define DD222 61:63
+#define dd223 64
+#define DD223 64:66
+#define dd233 67
+#define DD233 67:69
+#define dd333 70
+#define DD333 70:72
+#define dd0000 73
+#define DD0000 73:75
+#define dd0011 76
+#define DD0011 76:78
+#define dd0012 79
+#define DD0012 79:81
+#define dd0013 82
+#define DD0013 82:84
+#define dd0022 85
+#define DD0022 85:87
+#define dd0023 88
+#define DD0023 88:90
+#define dd0033 91
+#define DD0033 91:93
+#define dd1111 94
+#define DD1111 94:96
+#define dd1112 97
+#define DD1112 97:99
+#define dd1113 100
+#define DD1113 100:102
+#define dd1122 103
+#define DD1122 103:105
+#define dd1123 106
+#define DD1123 106:108
+#define dd1133 109
+#define DD1133 109:111
+#define dd1222 112
+#define DD1222 112:114
+#define dd1223 115
+#define DD1223 115:117
+#define dd1233 118
+#define DD1233 118:120
+#define dd1333 121
+#define DD1333 121:123
+#define dd2222 124
+#define DD2222 124:126
+#define dd2223 127
+#define DD2223 127:129
+#define dd2233 130
+#define DD2233 130:132
+#define dd2333 133
+#define DD2333 133:135
+#define dd3333 136
+#define DD3333 136:138
+#define dd00001 139
+#define DD00001 139:141
+#define dd00002 142
+#define DD00002 142:144
+#define dd00003 145
+#define DD00003 145:147
+#define dd00111 148
+#define DD00111 148:150
+#define dd00112 151
+#define DD00112 151:153
+#define dd00113 154
+#define DD00113 154:156
+#define dd00122 157
+#define DD00122 157:159
+#define dd00123 160
+#define DD00123 160:162
+#define dd00133 163
+#define DD00133 163:165
+#define dd00222 166
+#define DD00222 166:168
+#define dd00223 169
+#define DD00223 169:171
+#define dd00233 172
+#define DD00233 172:174
+#define dd00333 175
+#define DD00333 175:177
+#define dd11111 178
+#define DD11111 178:180
+#define dd11112 181
+#define DD11112 181:183
+#define dd11113 184
+#define DD11113 184:186
+#define dd11122 187
+#define DD11122 187:189
+#define dd11123 190
+#define DD11123 190:192
+#define dd11133 193
+#define DD11133 193:195
+#define dd11222 196
+#define DD11222 196:198
+#define dd11223 199
+#define DD11223 199:201
+#define dd11233 202
+#define DD11233 202:204
+#define dd11333 205
+#define DD11333 205:207
+#define dd12222 208
+#define DD12222 208:210
+#define dd12223 211
+#define DD12223 211:213
+#define dd12233 214
+#define DD12233 214:216
+#define dd12333 217
+#define DD12333 217:219
+#define dd13333 220
+#define DD13333 220:222
+#define dd22222 223
+#define DD22222 223:225
+#define dd22223 226
+#define DD22223 226:228
+#define dd22233 229
+#define DD22233 229:231
+#define dd22333 232
+#define DD22333 232:234
+#define dd23333 235
+#define DD23333 235:237
+#define dd33333 238
+#define DD33333 238:240
+#define Ndd 240
#define ee0 1
-#define ee1 2
-#define ee2 3
-#define ee3 4
-#define ee4 5
-#define ee00 6
-#define ee11 7
-#define ee12 8
-#define ee13 9
-#define ee14 10
-#define ee22 11
-#define ee23 12
-#define ee24 13
-#define ee33 14
-#define ee34 15
-#define ee44 16
-#define ee001 17
-#define ee002 18
-#define ee003 19
-#define ee004 20
-#define ee111 21
-#define ee112 22
-#define ee113 23
-#define ee114 24
-#define ee122 25
-#define ee123 26
-#define ee124 27
-#define ee133 28
-#define ee134 29
-#define ee144 30
-#define ee222 31
-#define ee223 32
-#define ee224 33
-#define ee233 34
-#define ee234 35
-#define ee244 36
-#define ee333 37
-#define ee334 38
-#define ee344 39
-#define ee444 40
-#define ee0000 41
-#define ee0011 42
-#define ee0012 43
-#define ee0013 44
-#define ee0014 45
-#define ee0022 46
-#define ee0023 47
-#define ee0024 48
-#define ee0033 49
-#define ee0034 50
-#define ee0044 51
-#define ee1111 52
-#define ee1112 53
-#define ee1113 54
-#define ee1114 55
-#define ee1122 56
-#define ee1123 57
-#define ee1124 58
-#define ee1133 59
-#define ee1134 60
-#define ee1144 61
-#define ee1222 62
-#define ee1223 63
-#define ee1224 64
-#define ee1233 65
-#define ee1234 66
-#define ee1244 67
-#define ee1333 68
-#define ee1334 69
-#define ee1344 70
-#define ee1444 71
-#define ee2222 72
-#define ee2223 73
-#define ee2224 74
-#define ee2233 75
-#define ee2234 76
-#define ee2244 77
-#define ee2333 78
-#define ee2334 79
-#define ee2344 80
-#define ee2444 81
-#define ee3333 82
-#define ee3334 83
-#define ee3344 84
-#define ee3444 85
-#define ee4444 86
-#define Pee 15
-#define Nee 86
+#define EE0 1:3
+#define ee1 4
+#define EE1 4:6
+#define ee2 7
+#define EE2 7:9
+#define ee3 10
+#define EE3 10:12
+#define ee4 13
+#define EE4 13:15
+#define ee00 16
+#define EE00 16:18
+#define ee11 19
+#define EE11 19:21
+#define ee12 22
+#define EE12 22:24
+#define ee13 25
+#define EE13 25:27
+#define ee14 28
+#define EE14 28:30
+#define ee22 31
+#define EE22 31:33
+#define ee23 34
+#define EE23 34:36
+#define ee24 37
+#define EE24 37:39
+#define ee33 40
+#define EE33 40:42
+#define ee34 43
+#define EE34 43:45
+#define ee44 46
+#define EE44 46:48
+#define ee001 49
+#define EE001 49:51
+#define ee002 52
+#define EE002 52:54
+#define ee003 55
+#define EE003 55:57
+#define ee004 58
+#define EE004 58:60
+#define ee111 61
+#define EE111 61:63
+#define ee112 64
+#define EE112 64:66
+#define ee113 67
+#define EE113 67:69
+#define ee114 70
+#define EE114 70:72
+#define ee122 73
+#define EE122 73:75
+#define ee123 76
+#define EE123 76:78
+#define ee124 79
+#define EE124 79:81
+#define ee133 82
+#define EE133 82:84
+#define ee134 85
+#define EE134 85:87
+#define ee144 88
+#define EE144 88:90
+#define ee222 91
+#define EE222 91:93
+#define ee223 94
+#define EE223 94:96
+#define ee224 97
+#define EE224 97:99
+#define ee233 100
+#define EE233 100:102
+#define ee234 103
+#define EE234 103:105
+#define ee244 106
+#define EE244 106:108
+#define ee333 109
+#define EE333 109:111
+#define ee334 112
+#define EE334 112:114
+#define ee344 115
+#define EE344 115:117
+#define ee444 118
+#define EE444 118:120
+#define ee0000 121
+#define EE0000 121:123
+#define ee0011 124
+#define EE0011 124:126
+#define ee0012 127
+#define EE0012 127:129
+#define ee0013 130
+#define EE0013 130:132
+#define ee0014 133
+#define EE0014 133:135
+#define ee0022 136
+#define EE0022 136:138
+#define ee0023 139
+#define EE0023 139:141
+#define ee0024 142
+#define EE0024 142:144
+#define ee0033 145
+#define EE0033 145:147
+#define ee0034 148
+#define EE0034 148:150
+#define ee0044 151
+#define EE0044 151:153
+#define ee1111 154
+#define EE1111 154:156
+#define ee1112 157
+#define EE1112 157:159
+#define ee1113 160
+#define EE1113 160:162
+#define ee1114 163
+#define EE1114 163:165
+#define ee1122 166
+#define EE1122 166:168
+#define ee1123 169
+#define EE1123 169:171
+#define ee1124 172
+#define EE1124 172:174
+#define ee1133 175
+#define EE1133 175:177
+#define ee1134 178
+#define EE1134 178:180
+#define ee1144 181
+#define EE1144 181:183
+#define ee1222 184
+#define EE1222 184:186
+#define ee1223 187
+#define EE1223 187:189
+#define ee1224 190
+#define EE1224 190:192
+#define ee1233 193
+#define EE1233 193:195
+#define ee1234 196
+#define EE1234 196:198
+#define ee1244 199
+#define EE1244 199:201
+#define ee1333 202
+#define EE1333 202:204
+#define ee1334 205
+#define EE1334 205:207
+#define ee1344 208
+#define EE1344 208:210
+#define ee1444 211
+#define EE1444 211:213
+#define ee2222 214
+#define EE2222 214:216
+#define ee2223 217
+#define EE2223 217:219
+#define ee2224 220
+#define EE2224 220:222
+#define ee2233 223
+#define EE2233 223:225
+#define ee2234 226
+#define EE2234 226:228
+#define ee2244 229
+#define EE2244 229:231
+#define ee2333 232
+#define EE2333 232:234
+#define ee2334 235
+#define EE2334 235:237
+#define ee2344 238
+#define EE2344 238:240
+#define ee2444 241
+#define EE2444 241:243
+#define ee3333 244
+#define EE3333 244:246
+#define ee3334 247
+#define EE3334 247:249
+#define ee3344 250
+#define EE3344 250:252
+#define ee3444 253
+#define EE3444 253:255
+#define ee4444 256
+#define EE4444 256:258
+#define Nee 258
#define KeyA0 0
#define KeyBget 2
#define KeyC0 4
#define KeyD0 6
#define KeyD0C 8
#define KeyE0 10
#define KeyEget 12
#define KeyEgetC 14
-#define DebugB 0
-#define DebugC 1
-#define DebugD 2
-#define DebugE 3
+#define DebugA 0
+#define DebugB 1
+#define DebugC 2
+#define DebugD 3
+#define DebugE 4
-#define Bval(id,p) cache(p+id,RC)
-#define Cval(id,p) cache(p+id,RC+2)
-#define Dval(id,p) cache(p+id,RC+4)
-#define Eval(id,p) cache(p+id,RC+6)
-#define Nval(n,id,p) cache(p+id,RC+2*n-4)
+#define memindex integer*8
-#define Sgn(i) (1 - 2*iand(i,1))
+#define Ano RC
+#define Bno RC+2
+#define Cno RC+4
+#define Dno RC+6
+#define Eno RC+8
+#define Aval(id,p) cache(p+id,Ano)
+#define Bval(id,p) cache(p+id,Bno)
+#define Cval(id,p) cache(p+id,Cno)
+#define Dval(id,p) cache(p+id,Dno)
+#define Eval(id,p) cache(p+id,Eno)
+#define offsetC 2
+
+#define M(i) para(1,i)
+#define P(i) para(1,i+npoint)
+
+#define Sgn(i) (1-2*iand(i,1))
+
+#define ln(x,s) log(x+(s)*cIeps)
+
+#define lnrat(x,y) log((x-cIeps)/(y-cIeps))
#define MAXDIM 8
#ifndef KIND
#define KIND 1
#endif
*#define WARNINGS
diff --git a/Looptools/include/externals.h b/Looptools/include/externals.h
--- a/Looptools/include/externals.h
+++ b/Looptools/include/externals.h
@@ -1,269 +1,291 @@
#if 0
-This file was generated by mkexternalsh on Thu Dec 9 09:13:07 CET 2010.
+This file was generated by mkexternalsh on Fri Feb 21 10:42:16 CET 2014.
Do not edit.
#endif
-#define A0b ljA0b
-#define A0bC ljA0bC
+#define AcoeffC ljAcoeffC
+#define Acoeff ljAcoeff
#define Bcheck ljBcheck
-#define Bcoeff ljBcoeff
-#define BcoeffC ljBcoeffC
-#define Bcoeffa ljBcoeffa
-#define BcoeffaC ljBcoeffaC
-#define Bcoeffb ljBcoeffb
+#define BcoeffAD ljBcoeffAD
+#define BcoeffFFC ljBcoeffFFC
+#define BcoeffFF ljBcoeffFF
+#define bdKC ljbdKC
+#define bdK ljbdK
+#define C0collDR ljC0collDR
#define C0coll ljC0coll
-#define C0collDR ljC0collDR
+#define C0funcC ljC0funcC
+#define C0func ljC0func
#define C0p0 ljC0p0
#define C0p1 ljC0p1
#define C0p2 ljC0p2
#define C0p3 ljC0p3
+#define C0softDR ljC0softDR
#define C0soft ljC0soft
-#define C0softDR ljC0softDR
+#define cachecopy ljcachecopy
+#define cacheindex ljcacheindex
+#define CcoefxC ljCcoefxC
+#define Ccoefx ljCcoefx
#define CDispatch ljCDispatch
-#define Ccoeff ljCcoeff
-#define CcoeffC ljCcoeffC
+#define CDump ljCDump
+#define cLi2omrat2 ljcLi2omrat2
+#define cLi2omrat ljcLi2omrat
+#define CparaC ljCparaC
+#define Cpara ljCpara
+#define cspence ljcspence
+#define D0CcollDR ljD0CcollDR
+#define D0Ccoll ljD0Ccoll
+#define D0Cm1p2 ljD0Cm1p2
+#define D0Cm1p3 ljD0Cm1p3
+#define D0Cm2p3 ljD0Cm2p3
+#define D0collDR ljD0collDR
#define D0coll ljD0coll
-#define D0collDR ljD0collDR
+#define D0CsoftDR ljD0CsoftDR
+#define D0Csoft ljD0Csoft
+#define D0funcC ljD0funcC
+#define D0func ljD0func
#define D0m0 ljD0m0
#define D0m0p0 ljD0m0p0
#define D0m0p1 ljD0m0p1
#define D0m0p2 ljD0m0p2
#define D0m0p3 ljD0m0p3
#define D0m1 ljD0m1
#define D0m1p2 ljD0m1p2
#define D0m1p3 ljD0m1p3
#define D0m2 ljD0m2
#define D0m2p3 ljD0m2p3
#define D0m3 ljD0m3
#define D0m4 ljD0m4
+#define D0softDR ljD0softDR
#define D0soft ljD0soft
-#define D0softDR ljD0softDR
+#define DB001C ljDB001C
+#define DB001 ljDB001
+#define DCDispatch ljDCDispatch
+#define DCDump ljDCDump
+#define DcoefxC ljDcoefxC
+#define Dcoefx ljDcoefx
#define DDispatch ljDDispatch
-#define Dcoeff ljDcoeff
-#define DcoeffC ljDcoeffC
+#define DDump ljDDump
+#define DecompC ljDecompC
#define Decomp ljDecomp
-#define DecompC ljDecompC
+#define DetmC ljDetmC
#define Detm ljDetm
-#define DetmC ljDetmC
-#define DumpCoeff ljDumpCoeff
-#define DumpCoeffC ljDumpCoeffC
-#define DumpPara ljDumpPara
-#define DumpParaC ljDumpParaC
-#define E0b ljE0b
-#define Echeck ljEcheck
-#define EcheckC ljEcheckC
-#define Ecoeff ljEcoeff
-#define EcoeffC ljEcoeffC
-#define Ecoeffa ljEcoeffa
-#define EcoeffaC ljEcoeffaC
-#define Ecoeffb ljEcoeffb
-#define EcoeffbC ljEcoeffbC
-#define InvGramE ljInvGramE
-#define InvGramEC ljInvGramEC
-#define Inverse ljInverse
-#define InverseC ljInverseC
-#define Li2omrat ljLi2omrat
-#define Li2omrat2 ljLi2omrat2
-#define Li2omx2 ljLi2omx2
-#define Li2omx3 ljLi2omx3
-#define Li2rat ljLi2rat
-#define Li2series ljLi2series
-#define RSolve ljRSolve
-#define Solve ljSolve
-#define SolveC ljSolveC
-#define bdK ljbdK
-#define cachelookup ljcachelookup
-#define cln ljcln
-#define cspence ljcspence
#define dfflo1 ljdfflo1
#define dfflo2 ljdfflo2
#define dfflo3 ljdfflo3
+#define DparaC ljDparaC
+#define Dpara ljDpara
+#define DumpCoeffC ljDumpCoeffC
+#define DumpCoeff ljDumpCoeff
+#define DumpParaC ljDumpParaC
+#define DumpPara ljDumpPara
+#define E0funcb ljE0funcb
+#define E0funcC ljE0funcC
+#define E0func ljE0func
+#define EcheckC ljEcheckC
+#define Echeck ljEcheck
+#define EcoeffaC ljEcoeffaC
+#define Ecoeffa ljEcoeffa
+#define EcoeffbC ljEcoeffbC
+#define Ecoeffb ljEcoeffb
+#define EcoefxC ljEcoefxC
+#define Ecoefx ljEcoefx
+#define EparaC ljEparaC
+#define Epara ljEpara
#define eta ljeta
#define etatilde ljetatilde
#define ff2d22 ljff2d22
#define ff2dl2 ljff2dl2
#define ff3dl2 ljff3dl2
-#define ffRn ljffRn
-#define ffS2 ljffS2
-#define ffS2_linr ljffS2_linr
-#define ffS3n ljffS3n
-#define ffT13 ljffT13
-#define ffT_lin ljffT_lin
-#define ffTn ljffTn
#define ffabcd ljffabcd
#define ffai ljffai
#define ffbglg ljffbglg
+#define ffbndc ljffbndc
#define ffbnd ljffbnd
-#define ffbndc ljffbndc
#define ffc1lg ljffc1lg
#define ffca0 ljffca0
#define ffcayl ljffcayl
#define ffcb0 ljffcb0
#define ffcb0p ljffcb0p
+#define ffcb1a ljffcb1a
#define ffcb1 ljffcb1
-#define ffcb1a ljffcb1a
#define ffcb2p ljffcb2p
#define ffcb2q ljffcb2q
-#define ffcc0 ljffcc0
#define ffcc0a ljffcc0a
#define ffcc0b ljffcc0b
+#define ffcc0 ljffcc0
#define ffcc0p ljffcc0p
#define ffcc0r ljffcc0r
#define ffccyz ljffccyz
#define ffcdb0 ljffcdb0
#define ffcdbp ljffcdbp
#define ffcdel ljffcdel
#define ffcdot ljffcdot
#define ffcdwz ljffcdwz
#define ffcel2 ljffcel2
#define ffcel3 ljffcel3
#define ffchck ljffchck
#define ffcl2p ljffcl2p
#define ffcl2t ljffcl2t
#define ffcl3m ljffcl3m
-#define ffcl3s ljffcl3s
#define ffclg2 ljffclg2
#define ffclgy ljffclgy
#define ffclmb ljffclmb
#define ffcnst ljffcnst
#define ffcod3 ljffcod3
#define ffcoot ljffcoot
#define ffcot2 ljffcot2
#define ffcot3 ljffcot3
#define ffcrr ljffcrr
#define ffcrt3 ljffcrt3
#define ffcs3 ljffcs3
#define ffcs4 ljffcs4
+#define ffcxra ljffcxra
#define ffcxr ljffcxr
-#define ffcxra ljffcxra
#define ffcxs3 ljffcxs3
#define ffcxs4 ljffcxs4
#define ffcxyz ljffcxyz
#define ffd0c ljffd0c
#define ffd0tra ljffd0tra
#define ffdcc0 ljffdcc0
#define ffdcrr ljffdcrr
#define ffdcs ljffdcs
#define ffdcxr ljffdcxr
#define ffdcxs ljffdcxs
-#define ffdel ljffdel
#define ffdel2 ljffdel2
#define ffdel3 ljffdel3
#define ffdel4 ljffdel4
#define ffdel5 ljffdel5
+#define ffdel ljffdel
#define ffdif4 ljffdif4
#define ffdl2p ljffdl2p
#define ffdl2s ljffdl2s
#define ffdl2t ljffdl2t
#define ffdl3m ljffdl3m
#define ffdl3p ljffdl3p
#define ffdl3s ljffdl3s
#define ffdl4p ljffdl4p
#define ffdl4r ljffdl4r
-#define ffdot ljffdot
#define ffdot2 ljffdot2
#define ffdot3 ljffdot3
#define ffdot4 ljffdot4
#define ffdot5 ljffdot5
+#define ffdot ljffdot
#define ffdwz ljffdwz
#define ffdxc0 ljffdxc0
#define fferr ljfferr
#define ffflag ljffflag
#define ffgdt4 ljffgdt4
#define ffgeta ljffgeta
#define ffidel ljffidel
#define ffieps ljffieps
#define ffint3 ljffint3
#define ffpi43 ljffpi43
#define ffpi54 ljffpi54
#define ffprec ljffprec
#define ffpvf ljffpvf
+#define ffRn ljffRn
#define ffroot ljffroot
#define ffroots ljffroots
#define ffrot3 ljffrot3
#define ffrot4 ljffrot4
#define ffrota ljffrota
#define ffrt3p ljffrt3p
+#define ffS2_linr ljffS2_linr
+#define ffS2 ljffS2
+#define ffS3n ljffS3n
#define ffset ljffset
#define ffsign ljffsign
#define ffsm43 ljffsm43
#define ffsmug ljffsmug
+#define ffT13 ljffT13
#define fftayl ljfftayl
#define ffthf ljffthf
#define ffthre ljffthre
+#define ffT_lin ljffT_lin
+#define ffTn ljffTn
#define fftran ljfftran
#define fftraroot ljfftraroot
#define ffwarn ljffwarn
#define ffwbeta ljffwbeta
#define ffx2ir ljffx2ir
#define ffxa0 ljffxa0
#define ffxb0 ljffxb0
#define ffxb0p ljffxb0p
-#define ffxb1 ljffxb1
#define ffxb111 ljffxb111
#define ffxb1a ljffxb1a
+#define ffxb1 ljffxb1
#define ffxb2p ljffxb2p
#define ffxb2q ljffxb2q
-#define ffxc0 ljffxc0
#define ffxc0a ljffxc0a
#define ffxc0b ljffxc0b
#define ffxc0i ljffxc0i
#define ffxc0j ljffxc0j
+#define ffxc0 ljffxc0
+#define ffxc0p0 ljffxc0p0
#define ffxc0p ljffxc0p
-#define ffxc0p0 ljffxc0p0
#define ffxc0r ljffxc0r
#define ffxclg ljffxclg
-#define ffxd0 ljffxd0
#define ffxd0a ljffxd0a
#define ffxd0b ljffxd0b
#define ffxd0d ljffxd0d
#define ffxd0e ljffxd0e
+#define ffxd0 ljffxd0
#define ffxd0m0 ljffxd0m0
#define ffxd0p ljffxd0p
#define ffxd0r ljffxd0r
#define ffxdb0 ljffxdb0
+#define ffxdb11 ljffxdb11
#define ffxdb1 ljffxdb1
-#define ffxdb11 ljffxdb11
#define ffxdbd ljffxdbd
#define ffxdbp ljffxdbp
#define ffxdir ljffxdir
-#define ffxe0 ljffxe0
#define ffxe00 ljffxe00
#define ffxe0a ljffxe0a
+#define ffxe0 ljffxe0
#define ffxe0r ljffxe0r
#define ffxhck ljffxhck
#define ffxkfn ljffxkfn
#define ffxl22 ljffxl22
#define ffxlam ljffxlam
#define ffxli2 ljffxli2
#define ffxlmb ljffxlmb
#define ffxlogx ljffxlogx
#define ffxtra ljffxtra
#define ffxxyz ljffxxyz
#define ffypvf ljffypvf
#define ffzdbd ljffzdbd
#define ffzkfn ljffzkfn
#define ffzli2 ljffzli2
#define ffzxdl ljffzxdl
#define ffzzdl ljffzzdl
#define fpv ljfpv
#define fth ljfth
-#define ln ljln
+#define InverseC ljInverseC
+#define Inverse ljInverse
+#define InvGramEC ljInvGramEC
+#define InvGramE ljInvGramE
+#define Li2omrat2 ljLi2omrat2
+#define Li2omrat ljLi2omrat
+#define Li2omx2 ljLi2omx2
+#define Li2omx3 ljLi2omx3
+#define Li2rat ljLi2rat
+#define Li2series ljLi2series
#define lndiv0 ljlndiv0
#define lndiv1 ljlndiv1
-#define lnrat ljlnrat
#define ltcoeffnames ljltcoeffnames
#define ltparanames ljltparanames
#define nffet1 ljnffet1
#define nffeta ljnffeta
+#define SolveC ljSolveC
+#define Solve ljSolve
#define spence ljspence
#define xeta ljxeta
#define xetatilde ljxetatilde
#define xlogx ljxlogx
#define xspence ljxspence
#define yfpv ljyfpv
#define zfflo1 ljzfflo1
#define zfflo2 ljzfflo2
#define zfflo3 ljzfflo3
#define zfflog ljzfflog
#define zxfflg ljzxfflg
diff --git a/Looptools/include/ff.h b/Looptools/include/ff.h
--- a/Looptools/include/ff.h
+++ b/Looptools/include/ff.h
@@ -1,179 +1,185 @@
* $Id: ff.h,v 1.1 1995/12/12 10:03:48 gj Exp $
* -------------------------------------------------------------
* INCLUDE FILE FOR THE FF ROUTINES.
* Geert Jan van Oldenborgh.
* -------------------------------------------------------------
* please do not change, and recompile _everything_ when you do.
* -------------------------------------------------------------
*
* this parameter determines how far the scalar npoint functions
* will look back to find the same parameters (when lmem is true)
*
integer memory
parameter (memory = 12)
*
* if .TRUE. then default (ffinit)
* l4also: in C0 (and higher), also consider the algorithm with 16
* dilogs .TRUE.
* ldc3c4: in D0 (and higher), also consider possible cancellations
* between the C0s .TRUE.
* lmem: before computing the C0 and higher, first check whether
* it has already been done recently .FALSE.
* ldot: leave the dotproducts and some determinants in common
* .FALSE.
* onshel: (in ffz?0 only): use onshell momenta .TRUE.
* lsmug: internal use
* lnasty: internal use
*
logical l4also,ldc3c4,lmem,ldot,onshel,lsmug,lnasty
*
* nwidth: number of widths within which the complex mass is used
* nschem: scheme to handle the complex mass (see ffinit.f)
* idot: internal flags to signal that some of the dotproducts
* are input: 0: none; 1: external pi.pj, 2: external +
* kinematical determinant, 3: all dotproducts + kindet.
*
integer nwidth,nschem,idot
*
* xloss: factor that the final result of a subtraction can be
* smaller than the terms without warning (default 1/8)
* precx: precision of real numbers, determined at runtime by
* ffinit (IEEE: 4.e-16)
* precc: same for complex numbers
* xalogm: smallest real number of which a log can be taken,
* determined at runtime by ffinit (IEEE: 2.e-308)
* xclogm: same for complex.
* xalog2: xalogm**2
* xclog2: xclogm**2
* reqprc: not used
* pi: pi
* pi6: pi**2/6
* pi12: pi**2/12
* xlg2: log(2)
* bf: factors in the expansion of dilog (~Bernouilli numbers)
* xninv: 1/n
* xn2inv: 1/n**2
* xinfac: 1/n!
* fpij2: vi.vj for 2point function 1-2: si, 3-3: pi
* fpij3: vi.vj for 3point function 1-3: si, 4-6: pi
* fpij4: vi.vj for 4point function 1-4: si, 5-10: pi
* fpij5: vi.vj for 5point function 1-5: si, 6-15: pi
* fpij6: vi.vj for 6point function 1-6: si, 7-21: pi
* fdel2: del2 = delta_(p1,p2)^(p1,p2) = p1^2.p2^2 - p1.p2^2 in C0
* fdel3: del3 = delta_(p1,p2,p3)^(p1,p2,p3) in D0
* fdel4s: del4s = delta_(s1,s2,s3,s4)^(s1,s2,s3,s4) in D0
* fdel4: del4 = delta_(p1,p2,p3,p4)^(p1,p2,p3,p4) in E0
* fdl3i: del3i = delta_(pj,pk,pl)^(pj,pk,pl) in E0, D0 without si
* fdl4si: dl4si = del4s in E0, D0 without si
* fdl3ij: same in F0 without si and sj.
* fd4sij: dl4si = del4s in E0, D0 without si
* fdl4i: delta4 in F0 without si.
* fodel2: same offshell (in case of complex or z-functions)
* fodel3: -''-
* cfdl4s: -''-
* fodel4: -''-
* fodl3i: -''-
* fod3ij: -''-
* fodl4i: -''-
* fidel3: ier of del3 (is not included in D0)
* fidel4: ier of del4 (is not included in E0)
* fidl3i: ier of dl3i (is not included in E0)
* fid3ij: ier of dl3ij (is not included in F0)
* fidl4i: ier of dl4i (is not included in F0)
*
- DOUBLE PRECISION xloss,precx,precc,xalogm,xclogm,xalog2,xclog2,
- & reqprc,pi,pi6,pi12,xlg2,bf(20),
+ RealType xloss,precx,precc,xalogm,xclogm,xalog2,xclog2,
+ & reqprc,pi,pi6,pi12,xlg2,sqrt2,bf(20),
& xninv(30),xn2inv(30),xinfac(30),
& fpij2(3,3),fpij3(6,6),fpij4(10,10),fpij5(15,15),
& fpij6(21,21),fdel2,fdel3,fdel4s,fdel4,fdl3i(5),
& fdl4si(5),fdl3ij(6,6),fd4sij(6,6),fdl4i(6),fodel2,
& fodel3,fodel4,fodl3i(5),fod3ij(6,6),fodl4i(6)
integer fidel3,fidel4,fidl3i(5),fid3ij(6,6),fidl4i(6)
*
* cI: imaginary unit
* c[zero1]:0,1 complex
* c2ipi: 2*i*pi
* cipi2: i*pi**2
* cfp..: complex version of fp..., only defined in ff[cz]*
* cmipj: (internal only) mi^2 - pj^2 in C0
* c2sisj: (internal only) 2*si.sj in D0
* cfdl4s: del4s in complex case (D0)
* ca1: (internal only) complex A1
* csdl2p: (internal only) complex transformed sqrt(del2)
*
- DOUBLE COMPLEX cI,czero,chalf,cone,c2ipi,cipi2,
+ ComplexType cI,czero,chalf,cone,c2ipi,cipi2,
& cfpij2(3,3),cfpij3(6,6),cfpij4(10,10),cfpij5(15,15),
& cfpij6(21,21),cmipj(3,3),c2sisj(4,4),cfdl4s,ca1
*
* nevent: number in integration loop (to be updated by user)
* ner: can be used to signal numerical problems (see ffrcvr)
* id: identifier of scalar function (to be set by user)
* idsub: internal identifier to pinpoint errors
* inx: in D0: p(inx(i,j)) = isgn(i,j)*(s(i)-s(j))
* inx5: in E0: p(inx5(i,j)) = isgn5(i,j)*(s(i)-s(j))
* inx6: in F0: p(inx6(i,j)) = isgn6(i,j)*(s(i)-s(j))
* isgn: see inx
* isgn5: see inx5
* isgn6: see inx6
* iold: rotation matrix for 4point function
* isgrot: signs to iold
* isgn34: +1 or -1: which root to choose in the transformation (D0)
* isgnal: +1 or -1: which root to choose in the alpha-trick (C0)
* irota3: save the number of positions the C0 configuration has been
* rotated over
* irota4: same for the D0
* irota5: same for the E0
* irota6: same for the F0
*
integer nevent,ner,id,idsub,inx(4,4),isgn(4,4),inx5(5,5),
& isgn5(5,5),inx6(6,6),isgn6(6,6),isgn34,isgnal,iold(13,
& 12),isgrot(10,12),irota3,irota4,irota5,irota6
integer idum93(2)
*
- DOUBLE PRECISION acc, eps
+ ComplexType cIeps
*
* parameters
*
parameter(
& cI = (0D0, 1D0),
& czero = (0D0,0D0),
& chalf = (.5D0,0D0),
& cone = (1D0,0D0),
& c2ipi = (0D0,6.28318530717958647692528676655896D0),
& cipi2 = (0D0,9.869604401089358618834490999876D0),
& pi = 3.14159265358979323846264338327948D0,
& pi6 = 1.644934066848226436472415166646D0,
& pi12 = .822467033424113218236207583323D0,
& xlg2 = .6931471805599453094172321214581D0,
- & acc = 1D-12,
- & eps = 1D-25 )
+ & sqrt2 = 1.4142135623730950488016887242096981D0,
+ & cIeps = (0D0,1D-50) )
*
* common
*
common /ffsign/isgn34,isgnal
common /ffprec/ xloss,precx,precc,xalogm,xclogm,xalog2,xclog2,
& reqprc
common /ffflag/ l4also,ldc3c4,lmem,ldot,
& nevent,ner,id,idsub,nwidth,nschem,onshel,idot
common /ffcnst/ bf,xninv,xn2inv,xinfac,inx,isgn,iold,isgrot,
& inx5,isgn5,inx6,isgn6
common /ffrota/ irota3,irota4,irota5,irota6
common /ffdot/ fpij2,fpij3,fpij4,fpij5,fpij6
common /ffdel/ fdel2,fdel3,fdel4s,fdel4,fdl3i,fdl4si,fdl3ij,
& fd4sij,fdl4i
common /ffidel/ fidel3,fidel4,fidl3i,fid3ij,fidl4i
common /ffcdot/ cfpij2,cfpij3,cfpij4,cfpij5,cfpij6
common /ffcdel/ fodel2,fodel3,cfdl4s,fodel4,fodl3i,fod3ij,fodl4i
common /ffsmug/ lsmug,lnasty,idum93,cmipj,c2sisj,ca1
*
* regularization parameters
*
- DOUBLE PRECISION mudim,delta,lambda,minmass
- common /ltregul/ mudim,delta,lambda,minmass
+ ComplexType mudimc
+ RealType delta, uvdiv, lambda, minmass
+ RealType diffeps, zeroeps
+ common /ltregul/ mudimc, delta, uvdiv, lambda, minmass,
+ & diffeps, zeroeps
+
+ RealType mudim
+ equivalence (mudimc, mudim)
*
* nan is used for undefined values and is supposed to
* "poison" a result, much as the IEEE NaN, which is just
* too unportable in Fortran
*
- DOUBLE COMPLEX nan
+ ComplexType nan
parameter (nan = (1D123, 1D123))
diff --git a/Looptools/include/ftypes.h b/Looptools/include/ftypes.h
--- a/Looptools/include/ftypes.h
+++ b/Looptools/include/ftypes.h
@@ -1,35 +1,85 @@
#ifndef FTYPES_H
#define FTYPES_H
#define FORTRAN(s) s##_
+#if QUAD
+
+#define RealType long double
+
+#pragma pack(push, 1)
+typedef struct {
+ unsigned long long frac;
+ unsigned short exp;
+} REAL10;
+typedef struct {
+ char zero[6];
+ unsigned long long frac;
+ unsigned short exp;
+} REAL16;
+#pragma pack(pop)
+
+typedef union {
+ long double r10;
+ REAL10 i10;
+ REAL16 i16;
+ unsigned long long i8[2];
+} REAL;
+
+static inline REAL ToREAL(const RealType r) {
+ REAL n;
+ n.i8[0] = 0;
+ n.i16.frac = ((REAL *)&r)->i10.frac << 1;
+ n.i16.exp = ((REAL *)&r)->i10.exp;
+ return n;
+}
+
+static inline RealType ToReal(const REAL r) {
+ REAL n;
+ const long long z = r.i16.frac | (r.i16.exp & 0x7fff);
+ n.i10.frac = (r.i16.frac >> 1) | ((z | -z) & 0x8000000000000000LL);
+ n.i10.exp = r.i16.exp;
+ return n.r10;
+}
+
+static inline void ToRealArray(RealType *out, const REAL *in, const int n) {
+ int i;
+ for( i = 0; i < n; ++i ) out[i] = ToReal(in[i]);
+}
+
+static inline void ToREALArray(REAL *out, const RealType *in, const int n) {
+ int i;
+ for( i = 0; i < n; ++i ) out[i] = ToREAL(in[i]);
+}
+
+#else
+
+#define RealType double
+typedef double REAL;
+
+#define ToReal(r) (r)
+#define ToREAL(r) (r)
+
+#endif
+
typedef int INTEGER;
typedef const INTEGER CINTEGER;
-typedef double DOUBLE_PRECISION;
-typedef const DOUBLE_PRECISION CDOUBLE_PRECISION;
-typedef struct { DOUBLE_PRECISION re, im; } DOUBLE_COMPLEX;
-typedef const DOUBLE_COMPLEX CDOUBLE_COMPLEX;
+typedef const REAL CREAL;
+typedef struct { REAL re, im; } COMPLEX;
+typedef const COMPLEX CCOMPLEX;
typedef char CHARACTER;
typedef const CHARACTER CCHARACTER;
-#ifdef __cplusplus
-
#include <complex>
-typedef std::complex<double> double_complex;
-#define ToComplex(c) double_complex(c.re, c.im)
-#define ToComplex2(r,i) double_complex(r, i)
+typedef std::complex<RealType> ComplexType;
+#define ToComplex(c) ComplexType(ToReal((c).re), ToReal((c).im))
+#define ToComplex2(r,i) ComplexType(r, i)
#define Re(x) std::real(x)
#define Im(x) std::imag(x)
+#define Conjugate(x) std::conj(x)
-#else
-
-typedef DOUBLE_COMPLEX double_complex;
-#define ToComplex(c) c
-#define ToComplex2(r,i) (double_complex){r, i}
-#define Re(x) (x).re
-#define Im(x) (x).im
+typedef const RealType cRealType;
+typedef const ComplexType cComplexType;
#endif
-#endif
-
diff --git a/Looptools/include/looptools-alt.h b/Looptools/include/looptools-alt.h
new file mode 100644
--- /dev/null
+++ b/Looptools/include/looptools-alt.h
@@ -0,0 +1,302 @@
+#if 0
+looptools.h
+the header file for Fortran with all definitions for LoopTools
+this file is part of LoopTools
+last modified 27 Feb 14 th
+#endif
+
+
+#ifndef LOOPTOOLS_H
+#define LOOPTOOLS_H
+
+#define aa0 1
+#define aa00 4
+#define Naa 6
+
+#define bb0 1
+#define bb1 4
+#define bb00 7
+#define bb11 10
+#define bb001 13
+#define bb111 16
+#define dbb0 19
+#define dbb1 22
+#define dbb00 25
+#define dbb11 28
+#define dbb001 31
+#define Nbb 33
+
+#define cc0 1
+#define cc1 4
+#define cc2 7
+#define cc00 10
+#define cc11 13
+#define cc12 16
+#define cc22 19
+#define cc001 22
+#define cc002 25
+#define cc111 28
+#define cc112 31
+#define cc122 34
+#define cc222 37
+#define cc0000 40
+#define cc0011 43
+#define cc0012 46
+#define cc0022 49
+#define cc1111 52
+#define cc1112 55
+#define cc1122 58
+#define cc1222 61
+#define cc2222 64
+#define Ncc 66
+
+#define dd0 1
+#define dd1 4
+#define dd2 7
+#define dd3 10
+#define dd00 13
+#define dd11 16
+#define dd12 19
+#define dd13 22
+#define dd22 25
+#define dd23 28
+#define dd33 31
+#define dd001 34
+#define dd002 37
+#define dd003 40
+#define dd111 43
+#define dd112 46
+#define dd113 49
+#define dd122 52
+#define dd123 55
+#define dd133 58
+#define dd222 61
+#define dd223 64
+#define dd233 67
+#define dd333 70
+#define dd0000 73
+#define dd0011 76
+#define dd0012 79
+#define dd0013 82
+#define dd0022 85
+#define dd0023 88
+#define dd0033 91
+#define dd1111 94
+#define dd1112 97
+#define dd1113 100
+#define dd1122 103
+#define dd1123 106
+#define dd1133 109
+#define dd1222 112
+#define dd1223 115
+#define dd1233 118
+#define dd1333 121
+#define dd2222 124
+#define dd2223 127
+#define dd2233 130
+#define dd2333 133
+#define dd3333 136
+#define dd00001 139
+#define dd00002 142
+#define dd00003 145
+#define dd00111 148
+#define dd00112 151
+#define dd00113 154
+#define dd00122 157
+#define dd00123 160
+#define dd00133 163
+#define dd00222 166
+#define dd00223 169
+#define dd00233 172
+#define dd00333 175
+#define dd11111 178
+#define dd11112 181
+#define dd11113 184
+#define dd11122 187
+#define dd11123 190
+#define dd11133 193
+#define dd11222 196
+#define dd11223 199
+#define dd11233 202
+#define dd11333 205
+#define dd12222 208
+#define dd12223 211
+#define dd12233 214
+#define dd12333 217
+#define dd13333 220
+#define dd22222 223
+#define dd22223 226
+#define dd22233 229
+#define dd22333 232
+#define dd23333 235
+#define dd33333 238
+#define Ndd 240
+
+#define ee0 1
+#define ee1 4
+#define ee2 7
+#define ee3 10
+#define ee4 13
+#define ee00 16
+#define ee11 19
+#define ee12 22
+#define ee13 25
+#define ee14 28
+#define ee22 31
+#define ee23 34
+#define ee24 37
+#define ee33 40
+#define ee34 43
+#define ee44 46
+#define ee001 49
+#define ee002 52
+#define ee003 55
+#define ee004 58
+#define ee111 61
+#define ee112 64
+#define ee113 67
+#define ee114 70
+#define ee122 73
+#define ee123 76
+#define ee124 79
+#define ee133 82
+#define ee134 85
+#define ee144 88
+#define ee222 91
+#define ee223 94
+#define ee224 97
+#define ee233 100
+#define ee234 103
+#define ee244 106
+#define ee333 109
+#define ee334 112
+#define ee344 115
+#define ee444 118
+#define ee0000 121
+#define ee0011 124
+#define ee0012 127
+#define ee0013 130
+#define ee0014 133
+#define ee0022 136
+#define ee0023 139
+#define ee0024 142
+#define ee0033 145
+#define ee0034 148
+#define ee0044 151
+#define ee1111 154
+#define ee1112 157
+#define ee1113 160
+#define ee1114 163
+#define ee1122 166
+#define ee1123 169
+#define ee1124 172
+#define ee1133 175
+#define ee1134 178
+#define ee1144 181
+#define ee1222 184
+#define ee1223 187
+#define ee1224 190
+#define ee1233 193
+#define ee1234 196
+#define ee1244 199
+#define ee1333 202
+#define ee1334 205
+#define ee1344 208
+#define ee1444 211
+#define ee2222 214
+#define ee2223 217
+#define ee2224 220
+#define ee2233 223
+#define ee2234 226
+#define ee2244 229
+#define ee2333 232
+#define ee2334 235
+#define ee2344 238
+#define ee2444 241
+#define ee3333 244
+#define ee3334 247
+#define ee3344 250
+#define ee3444 253
+#define ee4444 256
+#define Nee 258
+
+#define KeyA0 2**0
+#define KeyBget 2**2
+#define KeyC0 2**4
+#define KeyD0 2**6
+#define KeyD0C 2**8
+#define KeyE0 2**10
+#define KeyEget 2**12
+#define KeyEgetC 2**14
+#define KeyAll 21845
+
+#define DebugA 2**0
+#define DebugB 2**1
+#define DebugC 2**2
+#define DebugD 2**3
+#define DebugE 2**4
+#define DebugAll 31
+
+#define memindex integer*8
+
+#define Ccache 0
+#define Dcache 0
+
+#endif
+
+ integer ncaches
+ parameter (ncaches = 10)
+
+ ComplexType cache(2,ncaches)
+ common /ltvars/ cache
+
+ ComplexType Aval(1,1), AvalC(1,1)
+ ComplexType Bval(1,1), BvalC(1,1)
+ ComplexType Cval(1,1), CvalC(1,1)
+ ComplexType Dval(1,1), DvalC(1,1)
+ ComplexType Eval(1,1), EvalC(1,1)
+ equivalence (cache(2,1), Aval)
+ equivalence (cache(2,2), AvalC)
+ equivalence (cache(2,3), Bval)
+ equivalence (cache(2,4), BvalC)
+ equivalence (cache(2,5), Cval)
+ equivalence (cache(2,6), CvalC)
+ equivalence (cache(2,7), Dval)
+ equivalence (cache(2,8), DvalC)
+ equivalence (cache(2,9), Eval)
+ equivalence (cache(2,10), EvalC)
+
+ ComplexType A0, A0C, A00, A00C, B0i, B0iC
+ ComplexType B0, B1, B00, B11, B001, B111
+ ComplexType B0C, B1C, B00C, B11C, B001C, B111C
+ ComplexType DB0, DB1, DB00, DB11, DB001
+ ComplexType DB0C, DB1C, DB00C, DB11C, DB001C
+ ComplexType C0, C0C, C0i, C0iC
+ ComplexType D0, D0C, D0i, D0iC
+ ComplexType E0, E0C, E0i, E0iC
+ ComplexType Li2, Li2C, Li2omx, Li2omxC
+ memindex Aget, AgetC, Bget, BgetC, Cget, CgetC
+ memindex Dget, DgetC, Eget, EgetC
+ RealType getmudim, getdelta, getlambda, getminmass
+ RealType getmaxdev
+ integer getepsi, getwarndigits, geterrdigits
+ integer getversionkey, getdebugkey
+ integer getcachelast
+
+ external A0, A0C, A00, A00C, B0i, B0iC
+ external B0, B1, B00, B11, B001, B111
+ external B0C, B1C, B00C, B11C, B001C, B111C
+ external DB0, DB1, DB00, DB11, DB001
+ external DB0C, DB1C, DB00C, DB11C, DB001C
+ external C0, C0C, C0i, C0iC
+ external D0, D0C, D0i, D0iC
+ external E0, E0C, E0i, E0iC
+ external Li2, Li2C, Li2omx, Li2omxC
+ external Aget, AgetC, Bget, BgetC, Cget, CgetC
+ external Dget, DgetC, Eget, EgetC
+ external getmudim, getdelta, getlambda, getminmass
+ external getmaxdev
+ external getepsi, getwarndigits, geterrdigits
+ external getversionkey, getdebugkey
+ external getcachelast
+
diff --git a/Looptools/include/looptools.h b/Looptools/include/looptools.h
--- a/Looptools/include/looptools.h
+++ b/Looptools/include/looptools.h
@@ -1,277 +1,303 @@
-* looptools.h
-* the header file for Fortran with all definitions for LoopTools
-* this file is part of LoopTools
-* last modified 6 Jul 10 th
+#if 0
+looptools.h
+the header file for Fortran with all definitions for LoopTools
+this file is part of LoopTools
+last modified 27 Feb 14 th
+#endif
#ifndef LOOPTOOLS_H
#define LOOPTOOLS_H
+#define aa0 1
+#define aa00 4
+#define Naa 6
+
#define bb0 1
-#define bb1 2
-#define bb00 3
-#define bb11 4
-#define bb001 5
-#define bb111 6
-#define dbb0 7
-#define dbb1 8
-#define dbb00 9
-#define dbb11 10
+#define bb1 4
+#define bb00 7
+#define bb11 10
+#define bb001 13
+#define bb111 16
+#define dbb0 19
+#define dbb1 22
+#define dbb00 25
+#define dbb11 28
+#define dbb001 31
+#define Nbb 33
#define cc0 1
-#define cc1 2
-#define cc2 3
-#define cc00 4
-#define cc11 5
-#define cc12 6
-#define cc22 7
-#define cc001 8
-#define cc002 9
-#define cc111 10
-#define cc112 11
-#define cc122 12
-#define cc222 13
-#define cc0000 14
-#define cc0011 15
-#define cc0012 16
-#define cc0022 17
-#define cc1111 18
-#define cc1112 19
-#define cc1122 20
-#define cc1222 21
-#define cc2222 22
+#define cc1 4
+#define cc2 7
+#define cc00 10
+#define cc11 13
+#define cc12 16
+#define cc22 19
+#define cc001 22
+#define cc002 25
+#define cc111 28
+#define cc112 31
+#define cc122 34
+#define cc222 37
+#define cc0000 40
+#define cc0011 43
+#define cc0012 46
+#define cc0022 49
+#define cc1111 52
+#define cc1112 55
+#define cc1122 58
+#define cc1222 61
+#define cc2222 64
+#define Ncc 66
#define dd0 1
-#define dd1 2
-#define dd2 3
-#define dd3 4
-#define dd00 5
-#define dd11 6
-#define dd12 7
-#define dd13 8
-#define dd22 9
-#define dd23 10
-#define dd33 11
-#define dd001 12
-#define dd002 13
-#define dd003 14
-#define dd111 15
-#define dd112 16
-#define dd113 17
-#define dd122 18
-#define dd123 19
-#define dd133 20
-#define dd222 21
-#define dd223 22
-#define dd233 23
-#define dd333 24
-#define dd0000 25
-#define dd0011 26
-#define dd0012 27
-#define dd0013 28
-#define dd0022 29
-#define dd0023 30
-#define dd0033 31
-#define dd1111 32
-#define dd1112 33
-#define dd1113 34
-#define dd1122 35
-#define dd1123 36
-#define dd1133 37
-#define dd1222 38
-#define dd1223 39
-#define dd1233 40
-#define dd1333 41
-#define dd2222 42
-#define dd2223 43
-#define dd2233 44
-#define dd2333 45
-#define dd3333 46
-#define dd00001 47
-#define dd00002 48
-#define dd00003 49
-#define dd00111 50
-#define dd00112 51
-#define dd00113 52
-#define dd00122 53
-#define dd00123 54
-#define dd00133 55
-#define dd00222 56
-#define dd00223 57
-#define dd00233 58
-#define dd00333 59
-#define dd11111 60
-#define dd11112 61
-#define dd11113 62
-#define dd11122 63
-#define dd11123 64
-#define dd11133 65
-#define dd11222 66
-#define dd11223 67
-#define dd11233 68
-#define dd11333 69
-#define dd12222 70
-#define dd12223 71
-#define dd12233 72
-#define dd12333 73
-#define dd13333 74
-#define dd22222 75
-#define dd22223 76
-#define dd22233 77
-#define dd22333 78
-#define dd23333 79
-#define dd33333 80
+#define dd1 4
+#define dd2 7
+#define dd3 10
+#define dd00 13
+#define dd11 16
+#define dd12 19
+#define dd13 22
+#define dd22 25
+#define dd23 28
+#define dd33 31
+#define dd001 34
+#define dd002 37
+#define dd003 40
+#define dd111 43
+#define dd112 46
+#define dd113 49
+#define dd122 52
+#define dd123 55
+#define dd133 58
+#define dd222 61
+#define dd223 64
+#define dd233 67
+#define dd333 70
+#define dd0000 73
+#define dd0011 76
+#define dd0012 79
+#define dd0013 82
+#define dd0022 85
+#define dd0023 88
+#define dd0033 91
+#define dd1111 94
+#define dd1112 97
+#define dd1113 100
+#define dd1122 103
+#define dd1123 106
+#define dd1133 109
+#define dd1222 112
+#define dd1223 115
+#define dd1233 118
+#define dd1333 121
+#define dd2222 124
+#define dd2223 127
+#define dd2233 130
+#define dd2333 133
+#define dd3333 136
+#define dd00001 139
+#define dd00002 142
+#define dd00003 145
+#define dd00111 148
+#define dd00112 151
+#define dd00113 154
+#define dd00122 157
+#define dd00123 160
+#define dd00133 163
+#define dd00222 166
+#define dd00223 169
+#define dd00233 172
+#define dd00333 175
+#define dd11111 178
+#define dd11112 181
+#define dd11113 184
+#define dd11122 187
+#define dd11123 190
+#define dd11133 193
+#define dd11222 196
+#define dd11223 199
+#define dd11233 202
+#define dd11333 205
+#define dd12222 208
+#define dd12223 211
+#define dd12233 214
+#define dd12333 217
+#define dd13333 220
+#define dd22222 223
+#define dd22223 226
+#define dd22233 229
+#define dd22333 232
+#define dd23333 235
+#define dd33333 238
+#define Ndd 240
#define ee0 1
-#define ee1 2
-#define ee2 3
-#define ee3 4
-#define ee4 5
-#define ee00 6
-#define ee11 7
-#define ee12 8
-#define ee13 9
-#define ee14 10
-#define ee22 11
-#define ee23 12
-#define ee24 13
-#define ee33 14
-#define ee34 15
-#define ee44 16
-#define ee001 17
-#define ee002 18
-#define ee003 19
-#define ee004 20
-#define ee111 21
-#define ee112 22
-#define ee113 23
-#define ee114 24
-#define ee122 25
-#define ee123 26
-#define ee124 27
-#define ee133 28
-#define ee134 29
-#define ee144 30
-#define ee222 31
-#define ee223 32
-#define ee224 33
-#define ee233 34
-#define ee234 35
-#define ee244 36
-#define ee333 37
-#define ee334 38
-#define ee344 39
-#define ee444 40
-#define ee0000 41
-#define ee0011 42
-#define ee0012 43
-#define ee0013 44
-#define ee0014 45
-#define ee0022 46
-#define ee0023 47
-#define ee0024 48
-#define ee0033 49
-#define ee0034 50
-#define ee0044 51
-#define ee1111 52
-#define ee1112 53
-#define ee1113 54
-#define ee1114 55
-#define ee1122 56
-#define ee1123 57
-#define ee1124 58
-#define ee1133 59
-#define ee1134 60
-#define ee1144 61
-#define ee1222 62
-#define ee1223 63
-#define ee1224 64
-#define ee1233 65
-#define ee1234 66
-#define ee1244 67
-#define ee1333 68
-#define ee1334 69
-#define ee1344 70
-#define ee1444 71
-#define ee2222 72
-#define ee2223 73
-#define ee2224 74
-#define ee2233 75
-#define ee2234 76
-#define ee2244 77
-#define ee2333 78
-#define ee2334 79
-#define ee2344 80
-#define ee2444 81
-#define ee3333 82
-#define ee3334 83
-#define ee3344 84
-#define ee3444 85
-#define ee4444 86
+#define ee1 4
+#define ee2 7
+#define ee3 10
+#define ee4 13
+#define ee00 16
+#define ee11 19
+#define ee12 22
+#define ee13 25
+#define ee14 28
+#define ee22 31
+#define ee23 34
+#define ee24 37
+#define ee33 40
+#define ee34 43
+#define ee44 46
+#define ee001 49
+#define ee002 52
+#define ee003 55
+#define ee004 58
+#define ee111 61
+#define ee112 64
+#define ee113 67
+#define ee114 70
+#define ee122 73
+#define ee123 76
+#define ee124 79
+#define ee133 82
+#define ee134 85
+#define ee144 88
+#define ee222 91
+#define ee223 94
+#define ee224 97
+#define ee233 100
+#define ee234 103
+#define ee244 106
+#define ee333 109
+#define ee334 112
+#define ee344 115
+#define ee444 118
+#define ee0000 121
+#define ee0011 124
+#define ee0012 127
+#define ee0013 130
+#define ee0014 133
+#define ee0022 136
+#define ee0023 139
+#define ee0024 142
+#define ee0033 145
+#define ee0034 148
+#define ee0044 151
+#define ee1111 154
+#define ee1112 157
+#define ee1113 160
+#define ee1114 163
+#define ee1122 166
+#define ee1123 169
+#define ee1124 172
+#define ee1133 175
+#define ee1134 178
+#define ee1144 181
+#define ee1222 184
+#define ee1223 187
+#define ee1224 190
+#define ee1233 193
+#define ee1234 196
+#define ee1244 199
+#define ee1333 202
+#define ee1334 205
+#define ee1344 208
+#define ee1444 211
+#define ee2222 214
+#define ee2223 217
+#define ee2224 220
+#define ee2233 223
+#define ee2234 226
+#define ee2244 229
+#define ee2333 232
+#define ee2334 235
+#define ee2344 238
+#define ee2444 241
+#define ee3333 244
+#define ee3334 247
+#define ee3344 250
+#define ee3444 253
+#define ee4444 256
+#define Nee 258
#define KeyA0 2**0
#define KeyBget 2**2
#define KeyC0 2**4
#define KeyD0 2**6
#define KeyD0C 2**8
#define KeyE0 2**10
#define KeyEget 2**12
#define KeyEgetC 2**14
#define KeyAll 21845
-#define DebugB 2**0
-#define DebugC 2**1
-#define DebugD 2**2
-#define DebugE 2**3
-#define DebugAll 15
+#define DebugA 2**0
+#define DebugB 2**1
+#define DebugC 2**2
+#define DebugD 2**3
+#define DebugE 2**4
+#define DebugAll 31
-#define Bval(id,p) cache(p+id,1)
-#define BvalC(id,p) cache(p+id,2)
-#define Cval(id,p) cache(p+id,3)
-#define CvalC(id,p) cache(p+id,4)
-#define Dval(id,p) cache(p+id,5)
-#define DvalC(id,p) cache(p+id,6)
-#define Eval(id,p) cache(p+id,7)
-#define EvalC(id,p) cache(p+id,8)
+#define memindex integer*8
+#ifndef ComplexType
+#define ComplexType double complex
+#endif
+#ifndef RealType
+#define RealType double precision
+#endif
+
+#define Aval(id,p) cache(p+id,1)
+#define AvalC(id,p) cache(p+id,2)
+#define Bval(id,p) cache(p+id,3)
+#define BvalC(id,p) cache(p+id,4)
+#define Cval(id,p) cache(p+id,5)
+#define CvalC(id,p) cache(p+id,6)
+#define Dval(id,p) cache(p+id,7)
+#define DvalC(id,p) cache(p+id,8)
+#define Eval(id,p) cache(p+id,9)
+#define EvalC(id,p) cache(p+id,10)
#define Ccache 0
#define Dcache 0
#endif
integer ncaches
- parameter (ncaches = 8)
+ parameter (ncaches = 10)
- double complex cache(2,ncaches)
+ ComplexType cache(2,ncaches)
common /ltvars/ cache
- double complex A0, A0C, B0i, B0iC
- double complex B0, B1, B00, B11, B001, B111
- double complex B0C, B1C, B00C, B11C, B001C, B111C
- double complex DB0, DB1, DB00, DB11
- double complex DB0C, DB1C, DB00C, DB11C
- double complex C0, C0C, C0i, C0iC
- double complex D0, D0C, D0i, D0iC
- double complex E0, E0C, E0i, E0iC
- double complex Li2, Li2C
- integer Bget, BgetC, Cget, CgetC, Dget, DgetC, Eget, EgetC
- double precision getmudim, getdelta, getlambda, getmaxdev
- integer getwarndigits, geterrdigits
+ ComplexType A0, A0C, A00, A00C, B0i, B0iC
+ ComplexType B0, B1, B00, B11, B001, B111
+ ComplexType B0C, B1C, B00C, B11C, B001C, B111C
+ ComplexType DB0, DB1, DB00, DB11, DB001
+ ComplexType DB0C, DB1C, DB00C, DB11C, DB001C
+ ComplexType C0, C0C, C0i, C0iC
+ ComplexType D0, D0C, D0i, D0iC
+ ComplexType E0, E0C, E0i, E0iC
+ ComplexType Li2, Li2C, Li2omx, Li2omxC
+ memindex Aget, AgetC, Bget, BgetC, Cget, CgetC
+ memindex Dget, DgetC, Eget, EgetC
+ RealType getmudim, getdelta, getlambda, getminmass
+ RealType getmaxdev
+ integer getepsi, getwarndigits, geterrdigits
integer getversionkey, getdebugkey
integer getcachelast
- external A0, A0C, B0i, B0iC
+ external A0, A0C, A00, A00C, B0i, B0iC
external B0, B1, B00, B11, B001, B111
external B0C, B1C, B00C, B11C, B001C, B111C
- external DB0, DB1, DB00, DB11
- external DB0C, DB1C, DB00C, DB11C
+ external DB0, DB1, DB00, DB11, DB001
+ external DB0C, DB1C, DB00C, DB11C, DB001C
external C0, C0C, C0i, C0iC
external D0, D0C, D0i, D0iC
external E0, E0C, E0i, E0iC
- external Li2, Li2C
- external Bget, BgetC, Cget, CgetC, Dget, DgetC, Eget, EgetC
- external getmudim, getdelta, getlambda, getmaxdev
- external getwarndigits, geterrdigits
+ external Li2, Li2C, Li2omx, Li2omxC
+ external Aget, AgetC, Bget, BgetC, Cget, CgetC
+ external Dget, DgetC, Eget, EgetC
+ external getmudim, getdelta, getlambda, getminmass
+ external getmaxdev
+ external getepsi, getwarndigits, geterrdigits
external getversionkey, getdebugkey
- external setcachelast, getcachelast
+ external getcachelast
diff --git a/Looptools/include/lt.h b/Looptools/include/lt.h
--- a/Looptools/include/lt.h
+++ b/Looptools/include/lt.h
@@ -1,43 +1,42 @@
* lt.h
* internal common blocks for the LoopTools routines
* this file is part of LoopTools
-* last modified 21 Dec 10 th
+* last modified 6 Mar 14 th
#include "ff.h"
* the cache-pointer structure is (see cache.c):
* 1. int valid
* 2. Node *last
* 3. Node *first
* 4. (not used)
integer ncaches
- parameter (ncaches = 8)
+ parameter (ncaches = 10)
integer*8 cacheptr(4,KIND,ncaches)
integer*8 savedptr(2,ncaches)
- double precision maxdev
- integer warndigits, errdigits
+ RealType maxdev
+ integer epsi, warndigits, errdigits
integer serial, versionkey
integer debugkey, debugfrom, debugto
common /ltvars/
& cacheptr, savedptr,
& maxdev,
- & warndigits, errdigits,
+ & epsi, warndigits, errdigits,
& serial, versionkey,
& debugkey, debugfrom, debugto
integer cmpbits
common /ltcache/ cmpbits
- double complex cache(2,ncaches)
+ ComplexType cache(2,ncaches)
equivalence (cacheptr, cache)
-#ifndef sig
-#define sig(c) int(sign(1D0,DBLE(r))
+#ifndef DEBUGLEVEL
#define DEBUGLEVEL ibits(debugkey,8,2)
#endif
diff --git a/Looptools/include/ltnames.h b/Looptools/include/ltnames.h
new file mode 100644
--- /dev/null
+++ b/Looptools/include/ltnames.h
@@ -0,0 +1,5 @@
+ character*6 paraname(Pee,1:5)
+ common /ltparanames/ paraname
+
+ character*10 coeffname(Nee,1:5)
+ common /ltcoeffnames/ coeffname
diff --git a/Looptools/include/perm.h b/Looptools/include/perm.h
new file mode 100644
--- /dev/null
+++ b/Looptools/include/perm.h
@@ -0,0 +1,42 @@
+* perm.h
+* equivalent permutations for C and D functions
+* this file is part of LoopTools
+* last modified 9 Mar 11 th
+
+
+* C-permutations
+ integer p123, p231, p312
+ parameter (p123 = 83) ! O'123'
+ parameter (p231 = 153) ! O'231'
+ parameter (p312 = 202) ! O'312'
+
+* D-permutations
+ integer p1234, p1243, p2134, p2143, p1324, p1342
+ integer p3124, p3142, p1423, p1432, p4123, p4132
+ integer p2314, p2341, p3214, p3241, p2413, p2431
+ integer p4213, p4231, p3412, p3421, p4312, p4321
+ parameter (p1234 = 175301276) ! O'123456 1234'
+ parameter (p1243 = 242623139) ! O'163542 1243'
+ parameter (p2134 = 226051164) ! O'153624 2134'
+ parameter (p2143 = 208360547) ! O'143265 2143'
+ parameter (p1324 = 718320340) ! O'526413 1324'
+ parameter (p1342 = 734405346) ! O'536142 1342'
+ parameter (p3124 = 701318740) ! O'516324 3124'
+ parameter (p3142 = 751408738) ! O'546231 3142'
+ parameter (p1423 = 643085075) ! O'462513 1423'
+ parameter (p1432 = 591848218) ! O'432156 1432'
+ parameter (p4123 = 558848083) ! O'412365 4123'
+ parameter (p4132 = 626628698) ! O'452631 4132'
+ parameter (p2314 = 362329292) ! O'254613 2314'
+ parameter (p2341 = 327636193) ! O'234165 2341'
+ parameter (p3214 = 294577804) ! O'214356 3214'
+ parameter (p3241 = 378902177) ! O'264531 3241'
+ parameter (p2413 = 883471627) ! O'645213 2413'
+ parameter (p2431 = 866469145) ! O'635124 2431'
+ parameter (p4213 = 833497227) ! O'615342 4213'
+ parameter (p4231 = 850499737) ! O'625431 4231'
+ parameter (p3412 = 472573706) ! O'341256 3412'
+ parameter (p3421 = 506808081) ! O'361524 3421'
+ parameter (p4312 = 490350794) ! O'351642 4312'
+ parameter (p4321 = 439572689) ! O'321465 4321'
+
diff --git a/Looptools/include/types.h b/Looptools/include/types.h
new file mode 100644
--- /dev/null
+++ b/Looptools/include/types.h
@@ -0,0 +1,21 @@
+* types.h
+* real-based type declarations
+* this file is part of LoopTools
+* last modified 9 Jul 12 th
+
+
+#ifndef TYPES_H
+#define TYPES_H
+
+#define RealType double precision
+#define ComplexType double complex
+#define Re DBLE
+#define Im DIMAG
+#define Conjugate DCONJG
+#define ToComplex DCMPLX
+
+#define Sq(c) Re((c)*Conjugate(c))
+#define Sqrtc(c) sqrt(ToComplex(c))
+
+#endif
+
diff --git a/Looptools/makefile.original b/Looptools/makefile.original
new file mode 100644
--- /dev/null
+++ b/Looptools/makefile.original
@@ -0,0 +1,281 @@
+default: frontend mma$(ML)
+
+all: frontend mma1
+
+frontend: lib $(FE)
+
+mma1: lib $(MFE)
+
+mma0 lib: $(LIB) clooptools.h fcc
+
+
+.SUFFIXES:
+
+.SUFFIXES: .F .f90 .c
+
+
+OBJS = $(OBJS-quad) \
+ Aget.o AgetC.o \
+ ffxa0.o ffca0.o \
+ Bget.o BgetC.o Bcoeff.o BcoeffC.o \
+ BcoeffAD.o BcoeffFF.o BcoeffFFC.o \
+ ffxb0.o ffcb0.o ffxb1.o ffcb1.o \
+ ffxb2p.o ffcb2p.o \
+ ffxdb0.o ffcdb0.o ffxdb1.o \
+ ffdel2.o ffcel2.o \
+ C0func.o C0funcC.o Cget.o CgetC.o \
+ ffxc0.o ffcc0.o ffxc0i.o ffxc0p0.o \
+ ffxc0p.o ffcc0p.o ffdxc0.o ffdcc0.o \
+ ffdel3.o ffcel3.o \
+ D0func.o D0funcC.o Dget.o DgetC.o \
+ ffxd0.o ffxd0h.o ffxd0i.o ffxd0p.o \
+ ffxd0m0.o ffxd0tra.o ffxdbd.o ffdel4.o ffd0c.o \
+ ffTn.o ffT13.o ffS2.o ffS3n.o ffRn.o \
+ E0func.o E0funcC.o Eget.o EgetC.o \
+ Ecoeffa.o EcoeffaC.o Ecoeffb.o EcoeffbC.o \
+ ffxe0.o ffdel5.o \
+ ini.o auxCD.o solve.o solveC.o \
+ Dump.o DumpC.o Li2.o Li2C.o Li2omx.o Li2omxC.o \
+ cache.o ffinit.o \
+ ffxli2.o ffcli2.o ffxxyz.o ffcxyz.o \
+ ffcrr.o ffcxr.o fftran.o ffabcd.o ff2dl2.o \
+ ffcxs3.o ffcxs4.o ffdcxs.o ffbndc.o
+
+FFINC = ff.h $(OBJS-quad)
+
+LTINC = defs.h lt.h $(FFINC)
+
+CFC = $(XFC) $(DEF)COMPLEXPARA
+
+qcomplex.o qcomplex.mod: qcomplex.f90
+ $(F90) -O -c -o qcomplex.o qcomplex.f90
+
+Aget.o: Aget.F $(LTINC)
+ $(XFC) -c -o Aget.o Aget.F
+AgetC.o: Aget.F $(LTINC)
+ $(CFC) -c -o AgetC.o Aget.F
+ffxa0.o: ffxa0.F $(FFINC)
+ $(XFC) -c -o ffxa0.o ffxa0.F
+ffca0.o: ffca0.F $(FFINC)
+ $(XFC) -c -o ffca0.o ffca0.F
+
+Bget.o: Bget.F $(LTINC)
+ $(XFC) -c -o Bget.o Bget.F
+BgetC.o: Bget.F $(LTINC)
+ $(CFC) -c -o BgetC.o Bget.F
+Bcoeff.o: Bcoeff.F $(LTINC)
+ $(XFC) -c -o Bcoeff.o Bcoeff.F
+BcoeffC.o: BcoeffC.F $(LTINC)
+ $(XFC) -c -o BcoeffC.o BcoeffC.F
+BcoeffAD.o: BcoeffAD.F $(LTINC)
+ $(XFC) -c -o BcoeffAD.o BcoeffAD.F
+BcoeffFF.o: BcoeffFF.F $(LTINC)
+ $(XFC) -c -o BcoeffFF.o BcoeffFF.F
+BcoeffFFC.o: BcoeffFF.F $(LTINC)
+ $(CFC) -c -o BcoeffFFC.o BcoeffFF.F
+ffxb0.o: ffxb0.F $(FFINC)
+ $(XFC) -c -o ffxb0.o ffxb0.F
+ffcb0.o: ffcb0.F $(FFINC)
+ $(XFC) -c -o ffcb0.o ffcb0.F
+ffxb1.o: ffxb1.F $(FFINC)
+ $(XFC) -c -o ffxb1.o ffxb1.F
+ffcb1.o: ffcb1.F $(FFINC)
+ $(XFC) -c -o ffcb1.o ffcb1.F
+ffxb2p.o: ffxb2p.F $(FFINC)
+ $(XFC) -c -o ffxb2p.o ffxb2p.F
+ffcb2p.o: ffcb2p.F $(FFINC)
+ $(XFC) -c -o ffcb2p.o ffcb2p.F
+ffxdb0.o: ffxdb0.F $(FFINC)
+ $(XFC) -c -o ffxdb0.o ffxdb0.F
+ffcdb0.o: ffcdb0.F $(FFINC)
+ $(XFC) -c -o ffcdb0.o ffcdb0.F
+ffxdb1.o: ffxdb1.F $(FFINC)
+ $(XFC) -c -o ffxdb1.o ffxdb1.F
+ffdel2.o: ffdel2.F $(FFINC)
+ $(XFC) -c -o ffdel2.o ffdel2.F
+ffcel2.o: ffcel2.F $(FFINC)
+ $(XFC) -c -o ffcel2.o ffcel2.F
+
+C0func.o: C0func.F $(LTINC) perm.h
+ $(XFC) -c -o C0func.o C0func.F
+C0funcC.o: C0funcC.F $(LTINC)
+ $(XFC) -c -o C0funcC.o C0funcC.F
+Cget.o: Cget.F $(LTINC)
+ $(XFC) -c -o Cget.o Cget.F
+CgetC.o: Cget.F $(LTINC)
+ $(CFC) -c -o CgetC.o Cget.F
+ffxc0.o: ffxc0.F $(FFINC)
+ $(XFC) -c -o ffxc0.o ffxc0.F
+ffcc0.o: ffcc0.F $(FFINC)
+ $(XFC) -c -o ffcc0.o ffcc0.F
+ffxc0i.o: ffxc0i.F $(FFINC)
+ $(XFC) -c -o ffxc0i.o ffxc0i.F
+ffxc0p.o: ffxc0p.F $(FFINC)
+ $(XFC) -c -o ffxc0p.o ffxc0p.F
+ffxc0p0.o: ffxc0p0.F $(FFINC)
+ $(XFC) -c -o ffxc0p0.o ffxc0p0.F
+ffcc0p.o: ffcc0p.F $(FFINC)
+ $(XFC) -c -o ffcc0p.o ffcc0p.F
+ffdxc0.o: ffdxc0.F $(FFINC)
+ $(XFC) -c -o ffdxc0.o ffdxc0.F
+ffdel3.o: ffdel3.F $(FFINC)
+ $(XFC) -c -o ffdel3.o ffdel3.F
+ffcel3.o: ffcel3.F $(FFINC)
+ $(XFC) -c -o ffcel3.o ffcel3.F
+
+D0func.o: D0func.F $(LTINC) perm.h
+ $(XFC) -c -o D0func.o D0func.F
+D0funcC.o: D0funcC.F $(LTINC)
+ $(XFC) -c -o D0funcC.o D0funcC.F
+Dget.o: Dget.F $(LTINC)
+ $(XFC) -c -o Dget.o Dget.F
+DgetC.o: Dget.F $(LTINC)
+ $(CFC) -c -o DgetC.o Dget.F
+ffxd0.o: ffxd0.F $(FFINC)
+ $(XFC) -c -o ffxd0.o ffxd0.F
+ffxd0h.o: ffxd0h.F $(FFINC)
+ $(XFC) -c -o ffxd0h.o ffxd0h.F
+ffxd0i.o: ffxd0i.F $(FFINC)
+ $(XFC) -c -o ffxd0i.o ffxd0i.F
+ffxd0p.o: ffxd0p.F $(FFINC)
+ $(XFC) -c -o ffxd0p.o ffxd0p.F
+ffxd0m0.o: ffxd0m0.F $(FFINC)
+ $(XFC) -c -o ffxd0m0.o ffxd0m0.F
+ffxd0tra.o: ffxd0tra.F $(FFINC)
+ $(XFC) -c -o ffxd0tra.o ffxd0tra.F
+ffxdbd.o: ffxdbd.F $(FFINC)
+ $(XFC) -c -o ffxdbd.o ffxdbd.F
+ffdcc0.o: ffdcc0.F $(FFINC)
+ $(XFC) -c -o ffdcc0.o ffdcc0.F
+ffdel4.o: ffdel4.F $(FFINC)
+ $(XFC) -c -o ffdel4.o ffdel4.F
+ffd0c.o: ffd0c.F $(FFINC) perm.h
+ $(XFC) -c -o ffd0c.o ffd0c.F
+ffTn.o: ffTn.F $(FFINC)
+ $(XFC) -c -o ffTn.o ffTn.F
+ffT13.o: ffT13.F $(FFINC)
+ $(XFC) -c -o ffT13.o ffT13.F
+ffS2.o: ffS2.F $(FFINC)
+ $(XFC) -c -o ffS2.o ffS2.F
+ffS3n.o: ffS3n.F $(FFINC)
+ $(XFC) -c -o ffS3n.o ffS3n.F
+ffRn.o: ffRn.F $(FFINC)
+ $(XFC) -c -o ffRn.o ffRn.F
+
+E0func.o: E0func.F $(LTINC)
+ $(XFC) -c -o E0func.o E0func.F
+E0funcC.o: E0func.F $(LTINC)
+ $(CFC) -c -o E0funcC.o E0func.F
+Eget.o: Eget.F $(LTINC)
+ $(XFC) -c -o Eget.o Eget.F
+EgetC.o: Eget.F $(LTINC)
+ $(CFC) -c -o EgetC.o Eget.F
+Ecoeffa.o: Ecoeffa.F $(LTINC)
+ $(XFC) -c -o Ecoeffa.o Ecoeffa.F
+EcoeffaC.o: Ecoeffa.F $(LTINC)
+ $(CFC) -c -o EcoeffaC.o Ecoeffa.F
+Ecoeffb.o: Ecoeffb.F $(LTINC)
+ $(XFC) -c -o Ecoeffb.o Ecoeffb.F
+EcoeffbC.o: Ecoeffb.F $(LTINC)
+ $(CFC) -c -o EcoeffbC.o Ecoeffb.F
+ffxe0.o: ffxe0.F $(FFINC)
+ $(XFC) -c -o ffxe0.o ffxe0.F
+ffdel5.o: ffdel5.F $(FFINC)
+ $(XFC) -c -o ffdel5.o ffdel5.F
+
+ini.o: ini.F $(LTINC)
+ $(XFC) -c -o ini.o ini.F
+auxCD.o: auxCD.F $(LTINC)
+ $(XFC) -c -o auxCD.o auxCD.F
+solve.o: solve.F solve-LU.F solve-Eigen.F $(LTINC)
+ $(XFC) -c -o solve.o solve.F
+solveC.o: solve.F solve-LU.F solve-Eigen.F $(LTINC)
+ $(CFC) -c -o solveC.o solve.F
+Dump.o: Dump.F $(LTINC)
+ $(XFC) -c -o Dump.o Dump.F
+DumpC.o: Dump.F $(LTINC)
+ $(CFC) -c -o DumpC.o Dump.F
+Li2.o: Li2.F defs.h
+ $(XFC) -c -o Li2.o Li2.F
+Li2C.o: Li2.F defs.h
+ $(CFC) -c -o Li2C.o Li2.F
+Li2omx.o: Li2omx.F defs.h
+ $(XFC) -c -o Li2omx.o Li2omx.F
+Li2omxC.o: Li2omx.F defs.h
+ $(CFC) -c -o Li2omxC.o Li2omx.F
+cache.o: cache.c $(LTINC)
+ $(CC) $(CFLAGS) -c -o cache.o cache.c
+ffinit.o: ffinit.F $(LTINC) fferr.h ffwarn.h
+ $(XFC) -c -o ffinit.o ffinit.F
+ffxli2.o: ffxli2.F $(FFINC)
+ $(XFC) -c -o ffxli2.o ffxli2.F
+ffcli2.o: ffcli2.F $(FFINC)
+ $(XFC) -c -o ffcli2.o ffcli2.F
+ffxxyz.o: ffxxyz.F $(FFINC)
+ $(XFC) -c -o ffxxyz.o ffxxyz.F
+ffcxyz.o: ffcxyz.F $(FFINC)
+ $(XFC) -c -o ffcxyz.o ffcxyz.F
+ffcrr.o: ffcrr.F $(FFINC)
+ $(XFC) -c -o ffcrr.o ffcrr.F
+ffcxr.o: ffcxr.F $(FFINC)
+ $(XFC) -c -o ffcxr.o ffcxr.F
+fftran.o: fftran.F $(FFINC)
+ $(XFC) -c -o fftran.o fftran.F
+ffabcd.o: ffabcd.F $(FFINC)
+ $(XFC) -c -o ffabcd.o ffabcd.F
+ff2dl2.o: ff2dl2.F $(FFINC)
+ $(XFC) -c -o ff2dl2.o ff2dl2.F
+ffcxs3.o: ffcxs3.F $(FFINC)
+ $(XFC) -c -o ffcxs3.o ffcxs3.F
+ffcxs4.o: ffcxs4.F $(FFINC)
+ $(XFC) -c -o ffcxs4.o ffcxs4.F
+ffdcxs.o: ffdcxs.F $(FFINC)
+ $(XFC) -c -o ffdcxs.o ffdcxs.F
+ffbndc.o: ffbndc.F $(FFINC)
+ $(XFC) -c -o ffbndc.o ffbndc.F
+
+f77290: f77290.c
+ $(CC) $(CFLAGS) -o f77290 f77290.c
+looptools.h90: looptools.h f77290
+ f77290 looptools.h looptools.h90
+
+$(LIB): $(OBJS)
+ $(AR) cru $(LIB) $?
+ -$(RANLIB) $(LIB)
+
+
+$(FE): lt.F $(LTINC) $(LIB)
+ $(XFC) -o $(FE) lt.F $(LIB) -lpthread
+ -rm -f lt.o
+
+clooptools.h: clooptools.h.in ftypes.h
+ sed "s:NOUNDERSCORE:$(NOUNDERSCORE):" ftypes.h clooptools.h.in > clooptools.h
+
+fcc: fcc.in
+ sed -e 's|^fldflags=.*|fldflags="$(LDFLAGS)"|' fcc.in > fcc
+ chmod 755 fcc
+ rm -f f++
+ ln -s fcc f++
+
+LoopTools$(EXE): LoopTools.tm clooptools.h fortranflush.o $(LIB) fcc
+ NM="$(NM)" DLLTOOL="$(DLLTOOL)" \
+ CC="./fcc" REALCC="$(CC) $(CFLAGS)" \
+ CXX="./f++" REALCXX="$(CXX) $(CXXFLAGS)" \
+ PATH="$$PATH:." \
+ "$(MCC)" LoopTools.tm -o LoopTools$(EXE) $(MCFLAGS) \
+ fortranflush.o $(LIB) $(MCLIBS)
+ rm -f LoopTools.tm.c
+
+LoopTools-quad$(EXE): LoopTools.tm clooptools.h fortranflush.o $(LIB) fcc
+ sed '/:Begin:/,/:End:/ s/Real/Real128/g' LoopTools.tm > LoopTools-quad.tm
+ NM="$(NM)" DLLTOOL="$(DLLTOOL)" \
+ CC="./fcc" REALCC="$(CC) $(CFLAGS)" \
+ CXX="./f++" REALCXX="$(CXX) $(CXXFLAGS)" \
+ PATH="$$PATH:." \
+ "$(MCC)" LoopTools-quad.tm -o LoopTools-quad$(EXE) $(MCFLAGS) \
+ fortranflush.o $(LIB) -lpthread
+ rm -f LoopTools.tm.c
+
+fortranflush.o: fortranflush.F
+ $(XFC) -c -o fortranflush.o fortranflush.F
+
diff --git a/Looptools/util/Dump.F b/Looptools/util/Dump.F
--- a/Looptools/util/Dump.F
+++ b/Looptools/util/Dump.F
@@ -1,63 +1,66 @@
* Dump.F
* dumps the parameters and coefficients on screen
* this file is part of LoopTools
-* last modified 8 Dec 05 th
+* last modified 30 Jan 14 th
+
+#include "externals.h"
+#include "types.h"
#include "defs.h"
- subroutine XDumpPara(npoint, para, ldpara, origin)
+ subroutine XDumpPara(npoint, para, origin)
implicit none
- integer npoint, ldpara
- DVAR para(ldpara,*)
+ integer npoint
+ DVAR para(1,*)
character*(*) origin
#include "lt.h"
+#include "ltnames.h"
integer i
- character*6 paraname(Pee,2:5)
- common /ltparanames/ paraname
-
- integer npara(2:5)
- data npara /Pbb, Pcc, Pdd, Pee/
+ integer npara(5)
+ data npara /Paa, Pbb, Pcc, Pdd, Pee/
#ifdef COMPLEXPARA
- if( len(origin) .gt. 1 ) print *, "C", origin, serial
+ if( len(origin) .gt. 1 ) print *, origin, "C", serial
#else
if( len(origin) .gt. 1 ) print *, origin, serial
#endif
- do i = 1, npara(npoint)
+ do i = npoint + 1, npara(npoint)
+ print *, " ", paraname(i,npoint), "=", para(1,i)
+ enddo
+ do i = 1, npoint
print *, " ", paraname(i,npoint), "=", para(1,i)
enddo
call flush(6)
end
************************************************************************
subroutine XDumpCoeff(npoint, coeff)
implicit none
integer npoint
- double complex coeff(*)
+ ComplexType coeff(*)
#include "lt.h"
+#include "ltnames.h"
integer i
- character*8 coeffname(Nee,2:5)
- common /ltcoeffnames/ coeffname
-
- integer ncoeff(2:5)
- data ncoeff /Nbb, Ncc, Ndd, Nee/
+ integer ncoeff(5)
+ data ncoeff /Naa, Nbb, Ncc, Ndd, Nee/
do i = 1, ncoeff(npoint)
- print *, coeffname(i,npoint), "=", coeff(i)
+ if( coeff(i) .ne. 0 )
+ & print *, coeffname(i,npoint), "=", coeff(i)
enddo
print *, "===================================================="
call flush(6)
end
diff --git a/Looptools/util/Li2.F b/Looptools/util/Li2.F
--- a/Looptools/util/Li2.F
+++ b/Looptools/util/Li2.F
@@ -1,41 +1,43 @@
* Li2.F
* the dilogarithm function
* this file is part of LoopTools
* last modified 13 Apr 06 th
+#include "externals.h"
+#include "types.h"
#include "defs.h"
- double complex function XLi2(x)
+ ComplexType function XLi2(x)
implicit none
DVAR x
- double precision pi12
+ RealType pi12
parameter (pi12 = .822467033424113218236207583323D0)
- double complex res, dummy
+ ComplexType res, dummy
integer ier, ipi12
ier = 0
#ifdef COMPLEXPARA
call ffzzdl(res, ipi12, dummy, x, ier)
#else
call ffzxdl(res, ipi12, dummy, x, -1, ier)
#endif
XLi2 = res + ipi12*pi12
end
************************************************************************
* adapter code for C++
subroutine XLi2sub(res, x)
implicit none
- double complex res
+ ComplexType res
DVAR x
- double complex XLi2
+ ComplexType XLi2
external XLi2
res = XLi2(x)
end
diff --git a/Looptools/util/Li2omx.F b/Looptools/util/Li2omx.F
new file mode 100644
--- /dev/null
+++ b/Looptools/util/Li2omx.F
@@ -0,0 +1,34 @@
+* Li2omx.F
+* the dilogarithm function of 1 - x
+* this file is part of LoopTools
+* last modified 1 Aug 12 th
+
+#include "externals.h"
+#include "types.h"
+#include "defs.h"
+
+
+ ComplexType function XLi2omx(x)
+ implicit none
+ DVAR x
+
+ ComplexType spence
+ external spence
+
+ XLi2omx = spence(1, ToComplex(x), 0D0)
+ end
+
+************************************************************************
+* adapter code for C++
+
+ subroutine XLi2omxsub(res, x)
+ implicit none
+ ComplexType res
+ DVAR x
+
+ ComplexType spence
+ external spence
+
+ res = spence(1, ToComplex(x), 0D0)
+ end
+
diff --git a/Looptools/util/auxCD.F b/Looptools/util/auxCD.F
--- a/Looptools/util/auxCD.F
+++ b/Looptools/util/auxCD.F
@@ -1,399 +1,396 @@
* auxCD.F
* auxillary functions used by the three- and four-point integrals
* these functions are adapted from Ansgar Denner's bcanew.f
* to the conventions of LoopTools;
* they are used for double-checking the results of FF
-* last modified 1 Feb 10 th
+* last modified 1 Sep 14 th
+#include "externals.h"
+#include "types.h"
#include "defs.h"
- double complex function ln(x, s)
+ ComplexType function lndiv0(x, y)
implicit none
- double precision x, s
+ RealType x, y
#include "ff.h"
- if( x .le. 0 ) then
-#ifdef WARNINGS
- if( s .eq. 0 ) print *, "ln: argument on cut"
-#endif
- ln = log(-x) + cI*sign(pi, s)
- else
- ln = log(x)
- endif
- end
-
-************************************************************************
-
- double complex function cln(z, s)
- implicit none
- double complex z
- double precision s
-
-#include "ff.h"
-
- if( DIMAG(z) .eq. 0 .and. DBLE(z) .le. 0 ) then
-#ifdef WARNINGS
- if( s .eq. 0 ) print *, "cln: argument on cut"
-#endif
- cln = log(-z) + cI*sign(pi, s)
- else
- cln = log(z)
- endif
- end
-
-************************************************************************
-* lnrat(x, y) = log(x - i eps) - log(y - i eps)
-* original version by R.K. Ellis
-* this function is hardwired for the sign of epsilon
-* we must adjust the sign of x and y to get the right sign for epsilon
-
- double complex function lnrat(x, y)
- implicit none
- double precision x, y
-
-#include "ff.h"
-
- lnrat = log(abs(x/y)) +
- & cI*(sign(.5D0*pi, x) - sign(.5D0*pi, y))
- end
-
-************************************************************************
-
- double complex function lndiv0(x, y)
- implicit none
- double precision x, y
-
- double precision den
-
- double complex lnrat
- external lnrat
+ RealType den
den = 1 - x/y
if( abs(den) .lt. 1D-7 ) then
lndiv0 = -1 - den*(.5D0 + den/3D0)
else
lndiv0 = lnrat(x, y)/den
endif
end
************************************************************************
- double complex function lndiv1(x, y)
+ ComplexType function lndiv1(x, y)
implicit none
- double precision x, y
+ RealType x, y
- double precision den
+#include "ff.h"
- double complex lnrat
- external lnrat
+ RealType den
den = 1 - x/y
if( abs(den) .lt. 1D-7 ) then
lndiv1 = -.5D0 - den/3D0*(1 + .75D0*den)
else
lndiv1 = (lnrat(x, y)/den + 1)/den
endif
end
************************************************************************
* Li2omrat(x, y) = Li2(1 - (x - i eps)/(y - i eps)) for real x and y
* hence arguments are typically negative invariants
* original version by R.K. Ellis
- double complex function Li2omrat(x, y)
+ ComplexType function Li2omrat(x, y)
implicit none
- double precision x, y
+ RealType x, y
#include "ff.h"
- double precision omarg
+ ComplexType spence
+ external spence
- double complex spence, lnrat
- external spence, lnrat
+ ComplexType omarg
omarg = x/y
- if( omarg .lt. 0 ) then
- Li2omrat = pi6 - spence(DCMPLX(omarg), 0D0) -
+ if( Re(omarg) .lt. 0 ) then
+ Li2omrat = pi6 - spence(0, omarg, 0D0) -
& log(1 - omarg)*lnrat(x, y)
else
- Li2omrat = spence(DCMPLX(1 - omarg), 0D0)
+ Li2omrat = spence(1, omarg, 0D0)
+ endif
+ end
+
+************************************************************************
+
+ ComplexType function cLi2omrat(x, y)
+ implicit none
+ ComplexType x, y
+
+#include "ff.h"
+
+ ComplexType spence
+ external spence
+
+ ComplexType omarg
+
+ omarg = x/y
+ if( Im(omarg) .eq. 0 .and. Re(omarg) .lt. 0 ) then
+ cLi2omrat = pi6 - spence(0, omarg, 0D0) -
+ & log(1 - Re(omarg))*lnrat(Re(x), Re(y))
+ else
+ cLi2omrat = spence(1, omarg, 0D0)
endif
end
************************************************************************
* Li2omx2 = Li2(1 - (z1 + i eps1) (z2 + i eps2)) for complex z1, z2
* for z1 z2 < 1: +Li2(1 - z1 z2)
-* for z1 z2 > 1: -Li2(1 - 1/(z1 z2)) - 1/2 (ln(z1) + ln(z2))^2
+* for z1 z2 > 1: -Li2(1 - 1/(z1 z2)) - 1/2 (log(z1) + log(z2))^2
* original version by R.K. Ellis
- double complex function Li2omx2(z1, s1, z2, s2)
+ ComplexType function Li2omx2(z1, s1, z2, s2)
implicit none
- double complex z1, z2
- double precision s1, s2
+ ComplexType z1, z2
+ RealType s1, s2
#include "ff.h"
- double complex z12, l12
- double precision s12
+ ComplexType spence
+ external spence
- double complex cln, spence
- external cln, spence
+ ComplexType z12, l12
+ RealType s12
z12 = z1*z2
- if( abs(z12) .lt. eps ) then
+ if( abs(z12) .lt. zeroeps ) then
Li2omx2 = 0
- else if( abs(z12 - 1) .eq. acc ) then
+ else if( abs(z12 - 1) .eq. diffeps ) then
Li2omx2 = pi6
else
- l12 = cln(z1, s1) + cln(z2, s2)
- s12 = sign(1D0, DBLE(z2))*s1 + sign(1D0, DBLE(z1))*s2
+ l12 = ln(z1, s1) + ln(z2, s2)
+ s12 = sign(1D0, Re(z2))*s1 + sign(1D0, Re(z1))*s2
if( abs(z12) .le. 1 ) then
- Li2omx2 = pi6 - spence(z12, s12) -
- & l12*cln(1 - z12, -s12)
+ Li2omx2 = pi6 - spence(0, z12, s12) -
+ & l12*ln(1 - z12, -s12)
else
z12 = 1/z12
- Li2omx2 = -pi6 + spence(z12, s12) -
- & l12*(cln(1 - z12, -s12) + .5D0*l12)
+ Li2omx2 = -pi6 + spence(0, z12, s12) -
+ & l12*(ln(1 - z12, -s12) + .5D0*l12)
endif
endif
end
************************************************************************
* Li2omx3 = Li2(1 - (z1 + i eps1) (z2 + i eps2)) for complex z1, z2
* for z1 z2 < 1: +Li2(1 - z1 z2)
-* for z1 z2 > 1: -Li2(1 - 1/(z1 z2)) - 1/2 (ln(z1) + ln(z2))^2
+* for z1 z2 > 1: -Li2(1 - 1/(z1 z2)) - 1/2 (log(z1) + log(z2))^2
* original version by R.K. Ellis
- double complex function Li2omx3(z1, s1, z2, s2, z3, s3)
+ ComplexType function Li2omx3(z1, s1, z2, s2, z3, s3)
implicit none
- double complex z1, z2, z3
- double precision s1, s2, s3
+ ComplexType z1, z2, z3
+ RealType s1, s2, s3
#include "ff.h"
- double complex z123, l123
- double precision s123
+ ComplexType spence
+ external spence
- double complex cln, spence
- external cln, spence
+ ComplexType z123, l123
+ RealType s123
z123 = z1*z2*z3
- if( abs(DIMAG(z123)) .lt. eps )
+ if( abs(Im(z123)) .lt. zeroeps )
& s123 = sign(1D0,
- & DBLE(z2*z3)*s1 + DBLE(z1*z3)*s2 + DBLE(z1*z2)*s3)
+ & Re(z2*z3)*s1 + Re(z1*z3)*s2 + Re(z1*z2)*s3)
if( abs(z123) .le. 1 ) then
- Li2omx3 = pi6 - spence(z123, s123)
- if( abs(z123) .gt. eps .and. abs(z123 - 1) .gt. acc )
- & Li2omx3 = Li2omx3 - cln(1 - z123, 0D0)*
- & (cln(z1, s1) + cln(z2, s2) + cln(z3, s3))
+ Li2omx3 = pi6 - spence(0, z123, s123)
+ if( abs(z123) .gt. zeroeps .and. abs(z123 - 1) .gt. diffeps )
+ & Li2omx3 = Li2omx3 - ln(1 - z123, 0D0)*
+ & (ln(z1, s1) + ln(z2, s2) + ln(z3, s3))
else
z123 = 1/z123
- l123 = cln(z1, s1) + cln(z2, s2) + cln(z3, s3)
- Li2omx3 = -pi6 + spence(z123, s123) -
- & l123*(.5D0*l123 - cln(1 - z123, 0D0))
+ l123 = ln(z1, s1) + ln(z2, s2) + ln(z3, s3)
+ Li2omx3 = -pi6 + spence(0, z123, s123) -
+ & l123*(.5D0*l123 + ln(1 - z123, 0D0))
endif
end
************************************************************************
* Li2omrat2 = Li2(1 - (n1 - i eps) (n2 - i eps)/(d1 - i eps)/(d2 - i eps))
* for real n1, n2, d1, d2
* original version by R.K. Ellis
- double complex function Li2omrat2(n1, d1, n2, d2)
+ ComplexType function Li2omrat2(n1, d1, n2, d2)
implicit none
- double precision n1, d1, n2, d2
+ RealType n1, d1, n2, d2
#include "ff.h"
- double precision r12
- double complex l12
+ ComplexType spence
+ external spence
- double complex lnrat, spence
- external lnrat, spence
+ RealType r12
+ ComplexType l12
r12 = n1*n2/(d1*d2)
if( r12 .lt. 1 ) then
- Li2omrat2 = pi6 - spence(DCMPLX(r12), 0D0)
- if( abs(r12*(1 - r12)) .gt. acc )
+ Li2omrat2 = pi6 - spence(0, ToComplex(r12), 0D0)
+ if( abs(r12*(1 - r12)) .gt. diffeps )
& Li2omrat2 = Li2omrat2 -
& (lnrat(n1, d1) + lnrat(n2, d2))*log(1 - r12)
else
r12 = 1/r12
l12 = lnrat(n1, d1) + lnrat(n2, d2)
- Li2omrat2 = -pi6 + spence(DCMPLX(r12), 0D0) -
+ Li2omrat2 = -pi6 + spence(0, ToComplex(r12), 0D0) -
+ & l12*(.5D0*l12 + log(1 - r12))
+ endif
+ end
+
+************************************************************************
+
+ ComplexType function cLi2omrat2(n1, d1, n2, d2)
+ implicit none
+ ComplexType n1, d1, n2, d2
+
+#include "ff.h"
+
+ ComplexType spence
+ external spence
+
+ ComplexType r12, l12
+
+ r12 = n1*n2/(d1*d2)
+ if( abs(r12) .lt. 1 ) then
+ cLi2omrat2 = pi6 - spence(0, r12, 0D0)
+ if( abs(r12*(1 - r12)) .gt. diffeps )
+ & cLi2omrat2 = cLi2omrat2 -
+ & (lnrat(n1, d1) + lnrat(n2, d2))*log(1 - r12)
+ else
+ r12 = 1/r12
+ l12 = lnrat(n1, d1) + lnrat(n2, d2)
+ cLi2omrat2 = -pi6 + spence(0, r12, 0D0) -
& l12*(.5D0*l12 + log(1 - r12))
endif
end
************************************************************************
* original version by R.K. Ellis
- double complex function Li2rat(r1, s1, r2, s2)
+ ComplexType function Li2rat(r1, s1, r2, s2)
implicit none
- double complex r1, r2
- double precision s1, s2
+ ComplexType r1, r2
+ RealType s1, s2
#include "ff.h"
- double complex r12, l12
+ ComplexType Li2omx2, spence
+ external Li2omx2, spence
- double complex Li2omx2, cln, spence
- external Li2omx2, cln, spence
+ ComplexType r12, l12
- if( abs(DIMAG(r1)) + abs(DIMAG(r2)) .lt. eps ) then
+ if( abs(Im(r1)) + abs(Im(r2)) .lt. zeroeps ) then
Li2rat = Li2omx2(r1, s1, r2, s2)
return
endif
r12 = r1*r2
if( abs(r12) .lt. 1 ) then
- Li2rat = pi6 - spence(r12, 0D0)
- if( abs(r12*(1 - r12)) .gt. acc )
- & Li2rat = Li2rat - (cln(r1, s1) + cln(r2, s2))*log(1 - r12)
+ Li2rat = pi6 - spence(0, r12, 0D0)
+ if( abs(r12*(1 - r12)) .gt. diffeps ) Li2rat = Li2rat -
+ & (ln(r1, s1) + ln(r2, s2))*log(1 - r12)
else
r12 = 1/r12
- l12 = cln(r1, s1) + cln(r2, s2)
- Li2rat = -pi6 + spence(r12, 0D0) -
- & l12*(.5D0*l12 - log(1 - r12))
+ l12 = ln(r1, s1) + ln(r2, s2)
+ Li2rat = -pi6 + spence(0, r12, 0D0) -
+ & l12*(.5D0*l12 + log(1 - r12))
endif
end
************************************************************************
- double complex function spence(z, s)
+ ComplexType function spence(i_in, z_in, s)
implicit none
- double complex z
- double precision s
+ integer i_in
+ ComplexType z_in
+ RealType s
#include "ff.h"
- double complex z1
- double precision az1
+ ComplexType Li2series
+ external Li2series
- double complex Li2series, cln
- external Li2series, cln
+ ComplexType z(0:1)
+ RealType az1
- z1 = 1 - z
- az1 = abs(z1)
+ z(i_in) = z_in
+ z(1-i_in) = 1 - z_in
#ifdef WARNINGS
if( s .eq. 0 .and.
- & DIMAG(z) .eq. 0 .and. abs(DBLE(z1)) .lt. acc )
+ & Im(z) .eq. 0 .and. abs(Re(z1)) .lt. diffeps )
& print *, "spence: argument on cut"
#endif
- if( az1 .lt. acc ) then
- spence = pi6
- else if( DBLE(z) .lt. .5D0 ) then
- if( abs(z) .lt. 1 ) then
- spence = Li2series(z, s)
+ if( Re(z(0)) .lt. .5D0 ) then
+ if( abs(z(0)) .lt. 1 ) then
+ spence = Li2series(z(1), s)
else
spence = -pi6 -
- & .5D0*cln(-z, -s)**2 - Li2series(1/z, -s)
+ & .5D0*ln(-z(0), -s)**2 - Li2series(-z(1)/z(0), -s)
endif
else
- if( az1 .lt. 1 ) then
+ az1 = abs(z(1))
+ if( az1 .lt. 1D-15 ) then
+ spence = pi6
+ else if( az1 .lt. 1 ) then
spence = pi6 -
- & cln(z, s)*cln(z1, -s) - Li2series(z1, -s)
+ & ln(z(0), s)*ln(z(1), -s) - Li2series(z(0), -s)
else
spence = 2*pi6 +
- & .5D0*cln(-z1, -s)**2 - cln(z, s)*cln(z1, -s) +
- & Li2series(1/z1, s)
+ & .5D0*ln(-z(1), -s)**2 - ln(z(0), s)*ln(z(1), -s) +
+ & Li2series(-z(0)/z(1), s)
endif
endif
end
************************************************************************
- double complex function Li2series(z, s)
+ ComplexType function Li2series(z1, s)
implicit none
- double complex z
- double precision s
+ ComplexType z1
+ RealType s
- double complex xm, x2, new
+#include "ff.h"
+
+ ComplexType xm, x2, new
integer j
- double complex cln
- external cln
-
* these are the even-n Bernoulli numbers, already divided by (n + 1)!
* as in Table[BernoulliB[n]/(n + 1)!, {n, 2, 50, 2}]
- double precision b(25)
+ RealType b(25)
data b /
& 0.02777777777777777777777777777777777777777778774D0,
& -0.000277777777777777777777777777777777777777777778D0,
& 4.72411186696900982615268329554043839758125472D-6,
& -9.18577307466196355085243974132863021751910641D-8,
& 1.89788699889709990720091730192740293750394761D-9,
& -4.06476164514422552680590938629196667454705711D-11,
& 8.92169102045645255521798731675274885151428361D-13,
& -1.993929586072107568723644347793789705630694749D-14,
& 4.51898002961991819165047655285559322839681901D-16,
& -1.035651761218124701448341154221865666596091238D-17,
& 2.39521862102618674574028374300098038167894899D-19,
& -5.58178587432500933628307450562541990556705462D-21,
& 1.309150755418321285812307399186592301749849833D-22,
& -3.087419802426740293242279764866462431595565203D-24,
& 7.31597565270220342035790560925214859103339899D-26,
& -1.740845657234000740989055147759702545340841422D-27,
& 4.15763564461389971961789962077522667348825413D-29,
& -9.96214848828462210319400670245583884985485196D-31,
& 2.394034424896165300521167987893749562934279156D-32,
& -5.76834735536739008429179316187765424407233225D-34,
& 1.393179479647007977827886603911548331732410612D-35,
& -3.372121965485089470468473635254930958979742891D-37,
& 8.17820877756210262176477721487283426787618937D-39,
& -1.987010831152385925564820669234786567541858996D-40,
& 4.83577851804055089628705937311537820769430091D-42 /
- xm = -cln(1 - z, -s)
+ xm = -ln(z1, -s)
x2 = xm**2
Li2series = xm - x2/4D0
do j = 1, 25
xm = xm*x2
new = Li2series + xm*b(j)
if( new .eq. Li2series ) return
Li2series = new
enddo
#ifdef WARNINGS
print *, "Li2series: bad convergence"
#endif
end
************************************************************************
integer function eta(z1, s1, z2, s2, s12)
implicit none
- double complex z1, z2
- double precision s1, s2, s12
+ ComplexType z1, z2
+ RealType s1, s2, s12
- double precision im1, im2, im12
+ RealType im1, im2, im12
- im1 = DIMAG(z1)
+ im1 = Im(z1)
if( im1 .eq. 0 ) im1 = s1
- im2 = DIMAG(z2)
+ im2 = Im(z2)
if( im2 .eq. 0 ) im2 = s2
- im12 = DIMAG(z1*z2)
+ im12 = Im(z1*z2)
if( im12 .eq. 0 ) im12 = s12
if( im1 .lt. 0 .and. im2 .lt. 0 .and. im12 .gt. 0 ) then
eta = 1
else
& if( im1 .gt. 0 .and. im2 .gt. 0 .and. im12 .lt. 0 ) then
eta = -1
else
eta = 0
#ifdef WARNINGS
- if( .not. (im2 .eq. 0 .and. DBLE(z2) .gt. 0 .or.
- & im1 .eq. 0 .and. DBLE(z1) .gt. 0) .and.
- & (im1 .eq. 0 .and. DBLE(z1) .lt. 0 .or.
- & im2 .eq. 0 .and. DBLE(z2) .lt. 0 .or.
- & im12 .eq. 0 .and. DBLE(z1*z2) .lt. 0) )
+ if( .not. (im2 .eq. 0 .and. Re(z2) .gt. 0 .or.
+ & im1 .eq. 0 .and. Re(z1) .gt. 0) .and.
+ & (im1 .eq. 0 .and. Re(z1) .lt. 0 .or.
+ & im2 .eq. 0 .and. Re(z2) .lt. 0 .or.
+ & im12 .eq. 0 .and. Re(z1*z2) .lt. 0) )
& print *, "eta not defined"
#endif
endif
end
diff --git a/Looptools/util/cache.c b/Looptools/util/cache.c
--- a/Looptools/util/cache.c
+++ b/Looptools/util/cache.c
@@ -1,180 +1,223 @@
/*
cache.c
caching of tensor coefficients in
dynamically allocated memory
this file is part of LoopTools
- last modified 9 Dec 10 th
+ last modified 28 Feb 14 th
*/
+#define MUTEX
+
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <assert.h>
+#ifdef MUTEX
+#include <pthread.h>
+#endif
-#define cachelookup_ ljcachelookup_
-
-#define cachelookup cachelookup_
-#define ltcache ltcache_
+#define cachecopy_ ljcachecopy_
+#define cacheindex_ ljcacheindex_
#ifndef BIGENDIAN
#define BIGENDIAN 0
#endif
#ifndef KIND
#define KIND 1
#endif
#if KIND == 2
#define MSB (1-BIGENDIAN)
#else
#define MSB 0
#endif
typedef long long dblint;
typedef unsigned long long udblint;
-typedef struct { dblint part[KIND]; } Real;
+typedef struct { dblint part[KIND]; } RealType;
-typedef struct { Real re, im; } Complex;
+typedef const RealType cRealType;
-typedef long Integer;
+typedef struct { RealType re, im; } ComplexType;
+
+
+typedef long long memindex;
extern struct {
- long cmpbits;
-} ltcache;
+ int cmpbits;
+} ltcache_;
-/* (a < 0) ? -1 : 0 */
-#define NegQ(a) ((a) >> (sizeof(a)*8 - 1))
+enum { ncaches = 10 };
-/* (a < 0) ? 0 : a */
-#define IDim(a) ((a) & NegQ(-(a)))
+#ifdef MUTEX
+static pthread_mutex_t mutex[ncaches] = {
+ PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
+ PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
+ PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
+ PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER,
+ PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER
+};
+#endif
-static int SignBit(const dblint i)
-{
- return (udblint)i >> (8*sizeof(i) - 1);
+static inline int IDim(const int i) {
+ return i & (-i >> (8*sizeof i - 1));
}
-static Integer PtrDiff(const void *a, const void *b)
-{
+static inline int SignBit(const dblint i) {
+ return (udblint)i >> (8*sizeof i - 1);
+}
+
+
+static inline memindex PtrDiff(const void *a, const void *b) {
return (char *)a - (char *)b;
}
-static dblint CmpPara(const Real *para1, const Real *para2, int n,
- const dblint mask)
+static dblint CmpPara(cRealType *para1, cRealType *para2,
+ int n, const dblint mask)
{
while( n-- ) {
const dblint c = (mask & para1->part[MSB]) -
(mask & para2->part[MSB]);
if( c ) return c;
++para1;
++para2;
}
return 0;
}
#if KIND == 2
-static dblint CmpParaLo(const Real *para1, const Real *para2, int n,
- const dblint mask)
+static dblint CmpParaLo(cRealType *para1, cRealType *para2,
+ int n, const dblint mask)
{
while( n-- ) {
dblint c = para1->part[MSB] - para2->part[MSB];
if( c ) return c;
c = (mask & para1->part[1-MSB]) - (mask & para2->part[1-MSB]);
if( c ) return c;
++para1;
++para2;
}
return 0;
}
#endif
-Integer cachelookup(const Real *para, double *base,
- void (*calc)(const Real *, Real *, const long *),
- const int *pnpara, const int *pnval)
+static void *Lookup(cRealType *para, double *base,
+ void (*calc)(RealType *, cRealType *),
+ const int npara, const int nval, const int cacheno)
{
-
- const long one = 1;
- const Integer C_size = sizeof(Complex);
- const int npara = *pnpara, nval = *pnval;
-
typedef struct node {
struct node *next[2], *succ;
int serial;
- Real para[2];
+ RealType para[2];
} Node;
#define base_valid (int *)&base[0]
#define base_last (Node ***)&base[1]
#define base_first (Node **)&base[2]
const int valid = *base_valid;
Node **last = *base_last;
Node **next = base_first;
Node *node;
+#ifdef MUTEX
+ pthread_mutex_t *mx = &mutex[cacheno];
+#endif
+
if( last == NULL ) last = next;
- if( ltcache.cmpbits > 0 ) {
- dblint mask = -(1ULL << IDim(64 - ltcache.cmpbits));
+ {
+ dblint mask = -(1ULL << IDim(64 - ltcache_.cmpbits));
#if KIND == 2
- dblint (*cmp)(const Real *, const Real *, int, const dblint) = CmpPara;
- if( ltcache.cmpbits >= 64 ) {
- mask = -(1ULL << IDim(128 - ltcache.cmpbits));
+ dblint (*cmp)(cRealType *, cRealType *, int, const dblint) = CmpPara;
+ if( ltcache_.cmpbits >= 64 ) {
+ mask = -(1ULL << IDim(128 - ltcache_.cmpbits));
cmp = CmpParaLo;
}
#else
#define cmp CmpPara
#endif
while( (node = *next) && node->serial < valid ) {
const dblint i = cmp(para, node->para, npara, mask);
- if( i == 0 ) {
- goto found;
- }
+ if( i == 0 ) goto x0;
next = &node->next[SignBit(i)];
}
+
+#ifdef MUTEX
+ pthread_mutex_lock(mx);
+
+ while( (node = *next) && node->serial < valid ) {
+ const dblint i = cmp(para, node->para, npara, mask);
+ if( i == 0 ) goto x1;
+ next = &node->next[SignBit(i)];
+ }
+#endif
}
node = *last;
if( node == NULL ) {
- /* The "Real para[2]" bit in Node is effectively an extra
+ /* The "RealType para[2]" bit in Node is effectively an extra
Complex for alignment so that node can be reached with
an integer index into base */
- node = malloc(sizeof(Node) + npara*sizeof(Real) + nval*sizeof(Complex));
- if( node == NULL ) {
- fputs("Out of memory for LoopTools cache.\n", stderr);
- exit(1);
- }
+ assert( node = malloc(sizeof(Node) +
+ npara*sizeof(RealType) + nval*sizeof(ComplexType)) );
node = (Node *)((char *)node +
- (PtrDiff(base, &node->para[npara]) & (sizeof(Complex) - 1)));
+ (PtrDiff(base, &node->para[npara]) & (sizeof(ComplexType) - 1)));
node->succ = NULL;
node->serial = valid;
*last = node;
}
*next = node;
*base_last = &node->succ;
*base_valid = valid + 1;
node->next[0] = NULL;
node->next[1] = NULL;
- memcpy(node->para, para, npara*sizeof(Real));
- calc(node->para, &node->para[npara], &one);
+ memcpy(node->para, para, npara*sizeof(RealType));
+ calc(&node->para[npara], para);
-found:
- return PtrDiff(&node->para[npara], base)/C_size;
+#ifdef MUTEX
+x1:
+ pthread_mutex_unlock(mx);
+#endif
+
+x0:
+ return &node->para[npara];
}
+
+memindex cacheindex_(cRealType *para, double *base,
+ void (*calc)(RealType *, cRealType *),
+ const int *pnpara, const int *pnval, const int *pcacheno)
+{
+ ComplexType *val = Lookup(para, base, calc, *pnpara, *pnval, *pcacheno);
+ return PtrDiff(val, base)/(long)sizeof(ComplexType);
+}
+
+
+void cachecopy_(ComplexType *dest, cRealType *para, double *base,
+ void (*calc)(RealType *, cRealType *),
+ const int *pnpara, const int *pnval, const int *pcacheno)
+{
+ ComplexType *val = Lookup(para, base, calc, *pnpara, *pnval, *pcacheno);
+ memcpy(dest, val, *pnval*sizeof *dest);
+}
+
diff --git a/Looptools/util/ff2dl2.F b/Looptools/util/ff2dl2.F
--- a/Looptools/util/ff2dl2.F
+++ b/Looptools/util/ff2dl2.F
@@ -1,517 +1,518 @@
#include "externals.h"
+#include "types.h"
*###[ ff2dl2:
subroutine ff2dl2(del2d2,del2n,xpi,dpipj,piDpj, i,
+ j,k,kj,iskj,l, m,n,nm,isnm, ns, ier)
***#[*comment:***********************************************************
* *
* Calculate *
* *
* si mu mu sl *
* d d = si.sj*sk.sm*sl.sn - si.sk*sj.sm*sl.sn *
* sj sk sm sn - si.sj*sk.sn*sl.sm + si.sk*sj.sn*sl.sm *
* *
* with p(kj) = iskj*(sk-sj) *
* with p(nm) = isnm*(sn-sm) *
* *
* Input: xpi(ns) as usual *
* dpipj(ns,ns) -"- *
* piDpj(ns,ns) -"- *
* i,j,k,kj,iskj see above *
* l,m,n,nm,isnm -"- *
* *
* Output: del2d2 see above *
* del2n it is needed in fftran anyway *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer i,j,k,kj,iskj,l,m,n,nm,isnm,ns,ier
- DOUBLE PRECISION del2d2,del2n,xpi(10),dpipj(10,10),piDpj(10,10)
+ RealType del2d2,del2n,xpi(10),dpipj(10,10),piDpj(10,10)
*
* local variables:
*
integer isii,ii,ik,ij,im,in,ier0,ier1
- DOUBLE PRECISION s(5),del2m,del2nm,som,xmax,smax
+ RealType s(5),del2m,del2nm,som,xmax,smax
*
* common blocks:
*
#include "ff.h"
* #] declarations:
* #[ get del2n:
* we need this in any case !
ier1 = ier
if ( i .eq. n ) then
del2n = 0
elseif ( i .le. 4 ) then
ii = inx(n,i)
isii = isgn(n,i)
call ffdl2s(del2n,piDpj,i,n,ii,isii,j,k,kj,iskj,10)
else
call ffdl2t(del2n,piDpj,i,n,j,k,kj,iskj,+1,10)
endif
* #] get del2n:
* #[ special cases:
ier0 = ier
if ( i .eq. l .and. j .eq. m .and. k .eq. n ) then
call ffdl3m(s,.FALSE.,0D0,0D0,xpi,dpipj,piDpj,ns,j,k,kj,
+ i,1)
del2d2 = -s(1)
ier = max(ier0,ier1)
return
endif
if ( k .eq. l .and. j .le. 4 ) then
call ffdl2s(del2m,piDpj, j,l,inx(l,j),isgn(l,j),
+ m,n,nm,isnm, 10)
del2d2 = -piDpj(i,k)*del2m
ier = max(ier0,ier1)
return
endif
* #] special cases:
* #[ calculations:
ier0 = ier
if ( i .eq. m ) then
del2m = 0
elseif ( i .le. 4 ) then
ii = inx(m,i)
isii = isgn(m,i)
call ffdl2s(del2m,piDpj,i,m,ii,isii,j,k,kj,iskj,10)
else
call ffdl2t(del2m,piDpj,i,m,j,k,kj,iskj,+1,10)
endif
s(1) = del2m*piDpj(n,l)
s(2) = del2n*piDpj(m,l)
- smax = abs(s(1))*DBLE(10)**(ier0-ier)
+ smax = abs(s(1))*Re(10)**(ier0-ier)
del2d2 = s(1) - s(2)
if ( abs(del2d2) .ge. xloss*smax ) goto 60
som = del2d2
xmax = smax
ier0 = ier
call ffdl2t(del2nm,piDpj,i,nm,j,k,kj,iskj,+1,10)
s(1) = del2n*piDpj(nm,l)
s(2) = del2nm*piDpj(n,l)
del2d2 = isnm*(s(1) - s(2))
- smax = abs(s(2))*DBLE(10)**(ier0-ier)
+ smax = abs(s(2))*Re(10)**(ier0-ier)
if ( abs(del2d2) .ge. xloss*abs(s(1)) ) goto 60
if ( smax .lt. xmax ) then
som = del2d2
xmax = smax
endif
s(1) = del2m*piDpj(nm,l)
s(2) = del2nm*piDpj(m,l)
del2d2 = isnm*(s(1) - s(2))
- smax = abs(s(2))*DBLE(10)**(ier0-ier)
+ smax = abs(s(2))*Re(10)**(ier0-ier)
if ( abs(del2d2) .ge. xloss*abs(s(1)) ) goto 60
if ( smax .lt. xmax ) then
som = del2d2
xmax = smax
endif
* One more special case:
if ( k .eq. m ) then
isii = -1
ik = j
ij = k
im = m
in = n
elseif ( j .eq. m ) then
isii = +1
ik = k
ij = j
im = m
in = n
elseif ( j .eq. n ) then
isii = -1
ik = k
ij = j
im = n
in = m
elseif ( k .eq. n ) then
isii = +1
ik = j
ij = k
im = n
in = m
else
goto 50
endif
if ( ij .eq. im .and. i .le. 4 .and. ij .le. 4 .and. in .le. 4 )
+ then
if ( inx(ij,i) .gt. 0 .and. inx(im,l) .gt. 0 ) then
if ( abs(dpipj(i,inx(ij,i))) .lt. xloss*abs(xpi(ij))
+ .and. abs(dpipj(l,inx(im,l))) .lt. xloss*abs(xpi(im)) )
+ then
s(1) = piDpj(l,in)*piDpj(ik,ij)*dpipj(i,inx(ij,i))/2
s(2) = isgn(ij,i)*piDpj(l,in)*xpi(ij)*piDpj(ik,
+ inx(ij,i))/2
s(3) = -piDpj(i,ij)*piDpj(ik,in)*piDpj(l,im)
s(4) = piDpj(i,ik)*piDpj(im,in)*dpipj(l,inx(im,l))/2
s(5) = isgn(im,l)*piDpj(i,ik)*xpi(im)*piDpj(in,
+ inx(im,l))/2
del2d2 = s(1) + s(2) + s(3) + s(4) + s(5)
if ( isii .lt. 0 ) del2d2 = -del2d2
smax = max(abs(s(1)),abs(s(2)),abs(s(3)),abs(s(4)),
+ abs(s(5)))
if ( abs(del2d2) .ge. xloss**2*abs(smax) ) goto 60
if ( smax .lt. xmax ) then
som = del2d2
xmax = smax
endif
endif
endif
endif
50 continue
*
* give up
*
del2d2 = som
60 continue
* #] calculations:
*###] ff2dl2:
end
*###[ ff2d22:
subroutine ff2d22(dl2d22,xpi,dpipj,piDpj, i, j,k,kj,iskj,
+ m,n,nm,isnm)
***#[*comment:***********************************************************
* *
* Calculate *
* *
* / si mu mu nu \2 *
* |d d | *
* \ sj sk sm sn / *
* *
* = si.sj^2*sk.sm^2*sn.sn *
* - 2*si.sj^2*sk.sm*sk.sn*sm.sn *
* + si.sj^2*sk.sn^2*sm.sm *
* - 2*si.sj*si.sk*sj.sm*sk.sm*sn.sn *
* + 2*si.sj*si.sk*sj.sm*sk.sn*sm.sn *
* + 2*si.sj*si.sk*sj.sn*sk.sm*sm.sn *
* - 2*si.sj*si.sk*sj.sn*sk.sn*sm.sm *
* + si.sk^2*sj.sm^2*sn.sn *
* - 2*si.sk^2*sj.sm*sj.sn*sm.sn *
* + si.sk^2*sj.sn^2*sm.sm *
* *
* Input: xpi(ns) as usual *
* dpipj(ns,ns) -"- *
* piDpj(ns,ns) -"- *
* i,j,k,kj,iskj see above *
* m,n,nm,isnm -"- *
* *
* Output: dl2d22 see above *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer i,j,k,kj,iskj,m,n,nm,isnm
- DOUBLE PRECISION dl2d22,xpi(10),dpipj(10,10),piDpj(10,10)
+ RealType dl2d22,xpi(10),dpipj(10,10),piDpj(10,10)
*
* local variables:
*
integer ii,isii
- DOUBLE PRECISION s(10),del2s,del23,del24,del27,som,smax,xmax
+ RealType s(10),del2s,del23,del24,del27,som,smax,xmax
*
* common blocks:
*
#include "ff.h"
* #] declarations:
* #[ special cases:
if ( i .eq. n .or. i .eq. m ) then
call ffdl2s(del2s,piDpj, j,k,kj,iskj, m,n,nm,isnm, 10)
dl2d22 = xpi(i)*del2s**2
return
endif
* #] special cases:
* #[ calculations:
* We use the product form
if ( i .eq. 3 ) then
del23 = 0
elseif ( i .le. 4 ) then
ii = inx(3,i)
isii = isgn(3,i)
call ffdl2s(del23,piDpj,i,3,ii,isii,j,k,kj,iskj,10)
else
call ffdl2t(del23,piDpj,i,3,j,k,kj,iskj,+1,10)
endif
if ( i .eq. 4 ) then
del24 = 0
elseif ( i .le. 4 ) then
ii = inx(n,i)
isii = isgn(n,i)
call ffdl2s(del24,piDpj,i,4,ii,isii,j,k,kj,iskj,10)
else
call ffdl2t(del24,piDpj,i,4,j,k,kj,iskj,+1,10)
endif
s(1) = xpi(4)*del23**2
s(2) = -2*piDpj(3,4)*del23*del24
s(3) = xpi(3)*del24**2
dl2d22 = s(1) + s(2) + s(3)
smax = max(abs(s(1)),abs(s(2)),abs(s(3)))
if ( abs(dl2d22) .ge. xloss*smax ) goto 110
som = dl2d22
xmax = smax
* try the special case k=4 (for use in ee->mumu among others)
if ( i .lt. 4 .and. k .eq. 4 .and. abs(s(3)) .lt. xloss*smax
+ .and. ( abs(dpipj(i,inx(4,i))) .lt. xloss*xpi(i) .or.
+ abs(piDpj(j,inx(4,i))) .lt. xloss*abs(piDpj(j,4)) ) )
+ then
s(1) = -del23*piDpj(i,4)*piDpj(j,3)*xpi(4)
s(2) = del23*dpipj(i,inx(4,i))*piDpj(j,4)*piDpj(3,4)
s(4) = del23*piDpj(3,4)*xpi(4)*piDpj(j,inx(4,i))*isgn(4,i)
dl2d22 = s(1) + s(2) + s(3) + s(4)
smax = max(abs(s(1)),abs(s(2)),abs(s(3)),abs(s(4)))
if ( abs(dl2d22) .ge. xloss*smax ) goto 110
if ( smax .lt. xmax ) then
som = dl2d22
xmax = smax
endif
endif
call ffdl2t(del27,piDpj,i,7,j,k,kj,iskj,+1,10)
s(1) = xpi(7)*del24**2
s(2) = -2*piDpj(4,7)*del24*del27
s(3) = xpi(4)*del27**2
dl2d22 = s(1) + s(2) + s(3)
smax = max(abs(s(1)),abs(s(2)),abs(s(3)))
if ( abs(dl2d22) .ge. xloss*smax ) goto 110
if ( smax .lt. xmax ) then
som = dl2d22
xmax = smax
endif
s(1) = xpi(7)*del23**2
s(2) = -2*piDpj(3,7)*del23*del27
s(3) = xpi(3)*del27**2
dl2d22 = s(1) + s(2) + s(3)
smax = max(abs(s(1)),abs(s(2)),abs(s(3)))
if ( abs(dl2d22) .ge. xloss*smax ) goto 110
*
* We'll have to think of something more intelligent ...
*
if ( smax .lt. xmax ) then
som = dl2d22
xmax = smax
endif
dl2d22 = som
110 continue
* #] calculations:
*###] ff2d22:
end
*###[ ff3dl2:
subroutine ff3dl2(del3d2,xpi,dpipj,piDpj, i,
+ j,k,kj,iskj, l,m,ml,isml, n, o,p,po,ispo, ier)
***#[*comment:***********************************************************
* *
* Calculate *
* *
* si mu mu nu mu sn *
* d d d = ... *
* sj sk sl sm so sp *
* *
* with p(kj) = iskj*(sk-sj) *
* p(ml) = isml*(sm-sl) *
* p(po) = ispo*(sp-so) *
* *
* Input: xpi(ns) as usual *
* dpipj(ns,ns) -"- *
* piDpj(ns,ns) -"- *
* i,j,k,kj,iskj see above *
* l,m,ml,isml -"- *
* n,o,p,po,ispo -"- *
* *
* Output: del3d2 see above *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer i,j,k,kj,iskj,l,m,ml,isml,n,o,p,po,ispo,ier
- DOUBLE PRECISION del3d2,xpi(10),dpipj(10,10),piDpj(10,10)
+ RealType del3d2,xpi(10),dpipj(10,10),piDpj(10,10)
*
* local variables:
*
integer isii,ii
- DOUBLE PRECISION s(2),dl2il,dl2im,dl2ln,dl2mn,dl2iml,dl2mln
- DOUBLE PRECISION d2d2j,d2d2k,d2d2kj,dum,d2d2o,d2d2p,d2d2po
- DOUBLE PRECISION som,xmax
+ RealType s(2),dl2il,dl2im,dl2ln,dl2mn,dl2iml,dl2mln
+ RealType d2d2j,d2d2k,d2d2kj,dum,d2d2o,d2d2p,d2d2po
+ RealType som,xmax
*
* common blocks:
*
#include "ff.h"
* #] declarations:
* #[ split up l,m:
if ( i .eq. l ) then
dl2il = 0
elseif ( i .le. 4 ) then
ii = inx(l,i)
isii = isgn(l,i)
call ffdl2s(dl2il,piDpj,i,l,ii,isii,j,k,kj,iskj,10)
else
call ffdl2t(dl2il,piDpj,i,l,j,k,kj,iskj,+1,10)
endif
if ( m .eq. n ) then
dl2mn = 0
elseif ( i .le. 4 ) then
ii = inx(n,m)
isii = isgn(n,m)
call ffdl2s(dl2mn,piDpj,m,n,ii,isii,o,p,po,ispo,10)
else
call ffdl2t(dl2mn,piDpj,m,n,o,p,po,ispo,+1,10)
endif
s(1) = dl2il*dl2mn
if ( i .eq. m ) then
dl2im = 0
elseif ( i .le. 4 ) then
ii = inx(m,i)
isii = isgn(m,i)
call ffdl2s(dl2im,piDpj,i,m,ii,isii,j,k,kj,iskj,10)
else
call ffdl2t(dl2im,piDpj,i,m,j,k,kj,iskj,+1,10)
endif
if ( l .eq. n ) then
dl2ln = 0
elseif ( i .le. 4 ) then
ii = inx(n,l)
isii = isgn(n,l)
call ffdl2s(dl2ln,piDpj,l,n,ii,isii,o,p,po,ispo,10)
else
call ffdl2t(dl2ln,piDpj,l,n,o,p,po,ispo,+1,10)
endif
s(2) = dl2im*dl2ln
del3d2 = s(1) - s(2)
if ( abs(del3d2) .ge. xloss*abs(s(1)) ) return
som = del3d2
xmax = abs(s(1))
*
* rotate l,m
*
call ffdl2t(dl2mln,piDpj,ml,n,o,p,po,ispo,+1,10)
call ffdl2t(dl2iml,piDpj,i,ml,j,k,kj,iskj,+1,10)
s(1) = dl2im*dl2mln
s(2) = dl2iml*dl2mn
del3d2 = isml*(s(1) - s(2))
if ( abs(del3d2) .ge. xloss*abs(s(1)) ) return
if ( abs(s(1)) .lt. xmax ) then
som = del3d2
xmax = abs(s(1))
endif
s(1) = dl2il*dl2mln
s(2) = dl2iml*dl2ln
del3d2 = isml*(s(1) - s(2))
if ( abs(del3d2) .ge. xloss*abs(s(1)) ) return
if ( abs(s(1)) .lt. xmax ) then
som = del3d2
xmax = abs(s(1))
endif
* #] split up l,m:
* #[ split up j,k:
call ff2dl2(d2d2k,dum,xpi,dpipj,piDpj, k, l,m,ml,isml, n,
+ o,p,po,ispo, 10, ier)
call ff2dl2(d2d2j,dum,xpi,dpipj,piDpj, j, l,m,ml,isml, n,
+ o,p,po,ispo, 10, ier)
s(1) = piDpj(i,j)*d2d2k
s(2) = piDpj(i,k)*d2d2j
del3d2 = s(1) - s(2)
if ( abs(del3d2) .ge. xloss*abs(s(1)) ) return
if ( abs(s(1)) .lt. xmax ) then
som = del3d2
xmax = abs(s(1))
endif
call ff2dl2(d2d2kj,dum,xpi,dpipj,piDpj, kj, l,m,ml,isml, n,
+ o,p,po,ispo, 10, ier)
s(1) = piDpj(i,k)*d2d2kj
s(2) = piDpj(i,kj)*d2d2k
del3d2 = iskj*(s(1) - s(2))
if ( abs(del3d2) .ge. xloss*abs(s(1)) ) return
if ( abs(s(1)) .lt. xmax ) then
som = del3d2
xmax = abs(s(1))
endif
s(1) = piDpj(i,j)*d2d2kj
s(2) = piDpj(i,kj)*d2d2j
del3d2 = iskj*(s(1) - s(2))
if ( abs(del3d2) .ge. xloss*abs(s(1)) ) return
if ( abs(s(1)) .lt. xmax ) then
som = del3d2
xmax = abs(s(1))
endif
* #] split up j,k:
* #[ split up o,p:
call ff2dl2(d2d2o,dum,xpi,dpipj,piDpj, i, j,k,kj,iskj, o,
+ l,m,ml,isml, 10, ier)
call ff2dl2(d2d2p,dum,xpi,dpipj,piDpj, i, j,k,kj,iskj, p,
+ l,m,ml,isml, 10, ier)
s(1) = piDpj(p,n)*d2d2o
s(2) = piDpj(o,n)*d2d2p
del3d2 = s(1) - s(2)
if ( abs(del3d2) .ge. xloss*abs(s(1)) ) return
if ( abs(s(1)) .lt. xmax ) then
som = del3d2
xmax = abs(s(1))
endif
call ff2dl2(d2d2po,dum,xpi,dpipj,piDpj, i, j,k,kj,iskj, po,
+ l,m,ml,isml, 10, ier)
s(1) = piDpj(po,n)*d2d2p
s(2) = piDpj(p,n)*d2d2po
del3d2 = ispo*(s(1) - s(2))
if ( abs(del3d2) .ge. xloss*abs(s(1)) ) return
if ( abs(s(1)) .lt. xmax ) then
som = del3d2
xmax = abs(s(1))
endif
s(1) = piDpj(po,n)*d2d2o
s(2) = piDpj(o,n)*d2d2po
del3d2 = ispo*(s(1) - s(2))
if ( abs(del3d2) .ge. xloss*abs(s(1)) ) return
if ( abs(s(1)) .lt. xmax ) then
som = del3d2
xmax = abs(s(1))
endif
* #] split up o,p:
* #[ give up:
del3d2 = som
* #] give up:
*###] ff3dl2:
end
diff --git a/Looptools/util/ffabcd.F b/Looptools/util/ffabcd.F
--- a/Looptools/util/ffabcd.F
+++ b/Looptools/util/ffabcd.F
@@ -1,247 +1,248 @@
#include "externals.h"
+#include "types.h"
*###[ ffabcd:
subroutine ffabcd(aijkl,xpi,dpipj,piDpj,del2s,sdel2s,
+ in,jn,jin,isji, kn,ln,lkn,islk, ifirst, ier)
***#[*comment:***********************************************************
* *
* Calculate the a,b,c,d of the equation for qij.qkl *
* *
* a = s4.s4^2 *
* *
* si sj sk sl / sm sn sm sn sm sn mu ro\ *
* -b/2 = d d |d d - d s4 s4 | *
* mu nu nu ro \ mu s4 ro s4 sm sn / *
* *
* _ si sj sk sl / mu s4 ro mu s4 ro\ *
* vD/2 = d d |d s4 + d s4 | *
* mu nu nu ro \ s3 s4 s3 s4 / *
* *
* with sm = s3, sn = s4 *
* p(jin) = isji*(sj-si) *
* p(lkn) = islk*(sl-sk) *
* *
* Input: xpi(ns) as usual *
* dpipj(ns,ns) -"- *
* piDpj(ns,ns) -"- *
* in,jn,jin,isjn see above *
* kn,ln,lkn,islk see above *
* *
* Output: del4d2 see above *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer in,jn,jin,isji,kn,ln,lkn,islk,ifirst,
+ ier
- DOUBLE PRECISION aijkl,xpi(10),dpipj(10,10),piDpj(10,10),del2s
- DOUBLE PRECISION sdel2s
+ RealType aijkl,xpi(10),dpipj(10,10),piDpj(10,10),del2s
+ RealType sdel2s
*
* local variables:
*
integer i,j,ji,k,l,lk,isii
integer ii
integer iii(6,2)
save iii
logical ldet(4)
- DOUBLE PRECISION xa,xb,xc,xd,s(24),del3(4),som,somb,somd,
+ RealType xa,xb,xc,xd,s(24),del3(4),som,somb,somd,
+ smax,save,xmax,del2d2,dum,del2i,del2j,
+ del2ji,d2d2i,d2d2j,d2d2ji
save del3,ldet
*
* common blocks:
*
#include "ff.h"
*
* data
*
data iii / 0,3,4,0,7,0,
+ 0,3,4,0,7,0/
* #] declarations:
* #[ initialisaties:
if ( ifirst .eq. 0 ) then
ifirst = ifirst + 1
ldet(2) = .FALSE.
ldet(3) = .FALSE.
ldet(4) = .FALSE.
endif
xa = xpi(4)**2
* #] initialisaties:
* #[ prepare input:
i = in
j = jn
ji = jin
k = kn
l = ln
lk = lkn
* #] prepare input:
* #[ special cases:
if ( k .eq. 3 ) then
xb = 0
xc = 0
xd = 0
goto 990
elseif ( j .ge. 3 .and. l .ge. 3 ) then
* the whole thing collapses to factor*det3
* we have a good memory of things already calculated ...
if ( .not.ldet(i+k) ) then
ldet(i+k) = .TRUE.
iii(1,1) = i
iii(4,1) = isgn(3,i)*inx(3,i)
iii(6,1) = isgn(i,4)*inx(i,4)
iii(1,2) = k
iii(4,2) = isgn(3,k)*inx(3,k)
iii(6,2) = isgn(k,4)*inx(k,4)
call ffdl3s(del3(i+k),piDpj,iii,10)
endif
if ( l .eq. 4 .and. j .eq. 4 ) then
xb = xpi(4)**2*del3(i+k)/del2s
xd = 0
xc = xb**2/xa
elseif ( l .eq. 4 .or. j .eq. 4 ) then
xb = piDpj(3,4)*xpi(4)*del3(i+k)/del2s
xd = -xpi(4)*del3(i+k)/sdel2s
xc = xpi(4)*xpi(3)*del3(i+k)**2/del2s**2
else
* l .eq. 3 .and. j .eq. 3
xd = -2*piDpj(3,4)*del3(i+k)/sdel2s
s(1) = xpi(3)*xpi(4)
s(2) = 2*piDpj(3,4)**2
som = s(2) - s(1)
xb = som*del3(i+k)/del2s
xc = xpi(3)**2*del3(i+k)**2/del2s**2
endif
goto 900
endif
if ( j .eq. 2 .and. l .eq. 4 ) then
call ff3dl2(s(1),xpi,dpipj,piDpj, 4, 1,2,5,+1,
+ k,3,inx(3,k),isgn(3,k), 4, 3,4,7,+1, ier)
xb = -xpi(4)*s(1)/del2s
iii(1,1) = 1
iii(2,1) = 2
iii(4,1) = 5
iii(5,1) = 10
iii(6,1) = 8
iii(1,2) = k
iii(4,2) = isgn(3,k)*inx(3,k)
iii(6,2) = isgn(k,4)*inx(k,4)
call ffdl3s(s(1),piDpj,iii,10)
* restore values for other users
iii(2,1) = 3
iii(5,1) = 7
xd = -xpi(4)*s(1)/sdel2s
goto 800
endif
* #] special cases:
* #[ normal case b:
*
* First term:
*
call ff2dl2(del2d2,dum,xpi,dpipj,piDpj, 4,
+ i,j,ji,isji, 4, k,l,lk,islk, 10, ier)
s(1) = -del2d2*del2s
*
* Second and third term, split i,j
*
if ( i .eq. 4 ) then
del2i = 0
else
ii = inx(4,i)
isii = isgn(4,i)
call ffdl2s(del2i,piDpj,i,4,ii,isii,3,4,7,+1,10)
endif
if ( j .eq. 4 ) then
del2j = 0
else
ii = inx(4,j)
isii = isgn(4,j)
call ffdl2s(del2j,piDpj,j,4,ii,isii,3,4,7,+1,10)
endif
call ff2dl2(d2d2i,dum,xpi,dpipj,piDpj, i, k,l,lk,islk, 4,
+ 3,4,7,+1, 10, ier)
call ff2dl2(d2d2j,dum,xpi,dpipj,piDpj, j, k,l,lk,islk, 4,
+ 3,4,7,+1, 10, ier)
s(2) = +del2i*d2d2j
s(3) = -del2j*d2d2i
somb = s(1) + s(2) + s(3)
smax = max(abs(s(1)),abs(s(2)),abs(s(3)))
if ( abs(somb) .ge. xloss*smax ) goto 90
xmax = smax
save = somb
* if the first term is wrong ... forget about it
if ( abs(somb) .lt. xloss*abs(s(1)) ) goto 80
call ffdl2t(del2ji,piDpj, ji,4, 3,4,7,+1,+1, 10)
call ff2dl2(d2d2ji,dum,xpi,dpipj,piDpj, ji, k,l,lk,islk, 4,
+ 3,4,7,+1, 10, ier)
s(2) = +del2j*d2d2ji
s(3) = -del2ji*d2d2j
somb = s(1) + isji*(s(2) + s(3))
smax = max(abs(s(1)),abs(s(2)),abs(s(3)))
if ( abs(somb) .ge. xloss*smax ) goto 90
if ( smax .lt. xmax ) then
save = somb
xmax = smax
endif
s(2) = +del2i*d2d2ji
s(3) = -del2ji*d2d2i
somb = s(1) + isji*(s(2) + s(3))
smax = max(abs(s(1)),abs(s(2)),abs(s(3)))
if ( abs(somb) .ge. xloss*max(abs(s(1)),abs(s(2)),abs(s(3))) )
+ goto 90
if ( smax .lt. xmax ) then
save = somb
xmax = smax
endif
80 continue
*
* give up:
*
somb = save
90 continue
xb = somb/del2s
* #] normal case b:
* #[ normal case d:
call ff3dl2(s(1),xpi,dpipj,piDpj, 4, i,j,ji,isji, k,l,lk,islk,
+ 4, 3,4,7,+1, ier)
if ( i .eq. k .and. j .eq. l ) then
somd = -2*s(1)
else
call ff3dl2(s(2),xpi,dpipj,piDpj, 4, k,l,lk,islk,
+ i,j,ji,isji, 4, 3,4,7,+1, ier)
somd = - s(1) - s(2)
endif
xd = -somd/sdel2s
* #] normal case d:
* #[ normal case c:
800 continue
s(1) = xb - xd
s(2) = xb + xd
*** vvv Added 11 Feb 08:
smax = abs(abs(xb) - abs(xd))
xmax = xloss*max(abs(xb), abs(xd))
if( smax .lt. xmax .and. xmax .gt. 0 ) then
if( smax .ne. 0 ) then
ier = ier + int(log10(xmax/smax))
else
ier = ier + int(log10(xmax/xclogm))
endif
endif
*** ^^^
som = s(1)*s(2)
xc = som/xa
* #] normal case c:
900 continue
* #[ and the final answer:
990 continue
call ffroot(dum,aijkl,xa,xb,xc,xd,ier)
* #] and the final answer:
*###] ffabcd:
end
diff --git a/Looptools/util/ffbndc.F b/Looptools/util/ffbndc.F
--- a/Looptools/util/ffbndc.F
+++ b/Looptools/util/ffbndc.F
@@ -1,27 +1,28 @@
#include "externals.h"
+#include "types.h"
*###[ ffbndc:
- DOUBLE PRECISION function ffbndc(n1,n2,carray)
+ RealType function ffbndc(n1,n2,carray)
*************************************************************************
* *
* calculate bound = (precc*|a(n1)/a(n1+n2)|^(1/n2) which is the *
* maximum value of x in a series expansion sum_(i=n1)^(n1+n2) *
* a(i)*x(i) to give a result of accuracy precc (actually of |next *
* term| < prec *
* *
*************************************************************************
implicit none
integer n1,n2
- DOUBLE COMPLEX carray(n1+n2)
+ ComplexType carray(n1+n2)
#include "ff.h"
if ( carray(n1+n2) .eq. 0 ) then
print *,'ffbnd: fatal: array not intialized; did you call ',
+ 'ffini?'
stop
endif
- ffbndc = (precc*abs(carray(n1)/carray(n1+n2)))**(1/DBLE(n2))
+ ffbndc = (precc*abs(carray(n1)/carray(n1+n2)))**(1/Re(n2))
*###] ffbndc:
end
diff --git a/Looptools/util/ffcli2.F b/Looptools/util/ffcli2.F
--- a/Looptools/util/ffcli2.F
+++ b/Looptools/util/ffcli2.F
@@ -1,564 +1,565 @@
#include "externals.h"
+#include "types.h"
*###[ ffzli2:
subroutine ffzli2(zdilog,zlog,cx,ier)
***#[*comment:***********************************************************
* *
* Computes the dilogarithm (Li2, Sp) for any (complex) cx *
* to a precision precc. It assumes that cx is already in the *
* area |cx|<=1, Re(cx)<=1/2. As it is available it also returns *
* log(1-cx) = zlog. *
* *
* Input: cx (complex) *
* *
* Output: zdilog (complex) Li2(cx) *
* zlog (complex) log(1-cx) = -Li1(cx) *
* ier (integer) 0=OK,1=num,2=err *
* *
* Calls: log,zfflo1,(d/a)imag,real/dble *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE COMPLEX cx,zlog,zdilog
+ ComplexType cx,zlog,zdilog
*
* local variables
*
- DOUBLE PRECISION xprec,bdn02,bdn05,bdn10,bdn15,
+ RealType xprec,bdn02,bdn05,bdn10,bdn15,
+ xi,xr,xdilog,xlog,absc,xa,a,ffbnd
- DOUBLE COMPLEX cc,cz,cz2,zfflo1
+ ComplexType cc,cz,cz2,zfflo1
external ffbnd,zfflo1
save xprec,bdn02,bdn05,bdn10,bdn15
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(cc) = abs(DBLE(cc)) + abs(DIMAG(cc))
+ absc(cc) = abs(Re(cc)) + abs(Im(cc))
* #] declarations:
* #[ initialisations:
data xprec /-1D0/
if ( xprec .ne. precc ) then
xprec = precc
bdn02 = ffbnd(1,2,bf)
bdn05 = ffbnd(1,5,bf)
bdn10 = ffbnd(1,10,bf)
bdn15 = ffbnd(1,15,bf)
* we don't have bf(21) ...
endif
* #] initialisations:
* #[ exceptional cases:
- xi = DIMAG(cx)
- xr = DBLE(cx)
+ xi = Im(cx)
+ xr = Re(cx)
if ( xi .eq. 0) then
call ffxli2(xdilog,xlog,xr,ier)
zdilog = xdilog
zlog = xlog
return
endif
xa = abs(xi) + abs(xr)
if ( xa .lt. precc ) then
zdilog = cx
zlog = -cx
return
endif
* #] exceptional cases:
* #[ get log,dilog:
if ( xa .lt. xloss**2 ) then
zlog = zfflo1(cx,ier)
else
zlog = log(1-cx)
endif
cz = -zlog
if ( absc(cz) .lt. xclog2 ) then
zdilog = cz
else
cz2 = cz*cz
a = xa**2
if ( a .gt. bdn15 ) then
- zdilog = cz2*(DBLE(bf(16)) + cz2*(DBLE(bf(17))
- + + cz2*(DBLE(bf(18)) + cz2*(DBLE(bf(19))
- + + cz2*(DBLE(bf(20)))))))
+ zdilog = cz2*(Re(bf(16)) + cz2*(Re(bf(17))
+ + + cz2*(Re(bf(18)) + cz2*(Re(bf(19))
+ + + cz2*(Re(bf(20)))))))
else
zdilog = 0
endif
if ( a .gt. bdn10 ) then
- zdilog = cz2*(DBLE(bf(11)) + cz2*(DBLE(bf(12))
- + + cz2*(DBLE(bf(13)) + cz2*(DBLE(bf(14))
- + + cz2*(DBLE(bf(15)) + zdilog)))))
+ zdilog = cz2*(Re(bf(11)) + cz2*(Re(bf(12))
+ + + cz2*(Re(bf(13)) + cz2*(Re(bf(14))
+ + + cz2*(Re(bf(15)) + zdilog)))))
endif
if ( a .gt. bdn05 ) then
- zdilog = cz2*(DBLE(bf(6)) + cz2*(DBLE(bf(7))
- + + cz2*(DBLE(bf(8)) + cz2*(DBLE(bf(9))
- + + cz2*(DBLE(bf(10)) + zdilog)))))
+ zdilog = cz2*(Re(bf(6)) + cz2*(Re(bf(7))
+ + + cz2*(Re(bf(8)) + cz2*(Re(bf(9))
+ + + cz2*(Re(bf(10)) + zdilog)))))
endif
if ( a .gt. bdn02 ) then
- zdilog = cz2*(DBLE(bf(3)) + cz2*(DBLE(bf(4))
- + + cz2*(DBLE(bf(5)) + zdilog)))
+ zdilog = cz2*(Re(bf(3)) + cz2*(Re(bf(4))
+ + + cz2*(Re(bf(5)) + zdilog)))
endif
* watch the powers of z.
- zdilog = cz + cz2*(DBLE(bf(1)) + cz*(DBLE(bf(2)) + zdilog))
+ zdilog = cz + cz2*(Re(bf(1)) + cz*(Re(bf(2)) + zdilog))
endif
* #] get log,dilog:
*###] ffzli2:
end
*###[ ffzzdl:
subroutine ffzzdl(zdilog,ipi12,zlog,cx,ier)
***#[*comment:***************************************************
* *
* Computes the dilogarithm (Li2, Sp) for any (complex) cx *
* to about 15 significant figures. This can be improved *
* by adding more of the bf's. For real cx > 1 an error is *
* generated as the imaginary part is undefined then. *
* For use in ffcdbd zlog = log(1-cx) is also calculated *
* *
* Input: cx (complex) *
* *
* Output: zdilog (complex) Li2(cx) mod factors pi^2/12 *
* ipi12 (integer) these factors *
* zlog (complex) log(1-cx) *
* *
* Calls: log,zfflo1,(d/a)imag,real/dble *
* *
***#]*comment:***************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ipi12,ier
- DOUBLE COMPLEX zdilog,zlog,cx
+ ComplexType zdilog,zlog,cx
*
* local variables
*
integer jsgn
- DOUBLE PRECISION xprec,bdn02,bdn05,bdn10,bdn15,
+ RealType xprec,bdn02,bdn05,bdn10,bdn15,
+ xi,xr,s1,s2,xa,a,absc,ffbnd
- DOUBLE COMPLEX cfact,cx1,cy,cz,cz2,zfflo1,c
+ ComplexType cfact,cx1,cy,cz,cz2,zfflo1,c
external ffbnd,zfflo1
save xprec,bdn02,bdn05,bdn10,bdn15
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ initialisations:
data xprec /-1D0/
if ( xprec .ne. precc ) then
xprec = precc
bdn02 = ffbnd(1,2,bf)
bdn05 = ffbnd(1,5,bf)
bdn10 = ffbnd(1,10,bf)
bdn15 = ffbnd(1,15,bf)
endif
* #] initialisations:
* #[ exceptional cases:
- xi = DIMAG(cx)
- xr = DBLE(cx)
+ xi = Im(cx)
+ xr = Re(cx)
if ( xi .eq. 0 ) then
if ( xr .gt. 1 ) call fferr(31,ier)
call ffzxdl(zdilog,ipi12,zlog,xr,1,ier)
return
endif
if ( abs(xi) .lt. xalog2 ) then
s1 = 0
else
s1 = xi**2
endif
if ( abs(xr) .lt. xalog2 ) then
s2 = 0
else
s2 = xr**2
endif
xa = sqrt(s1 + s2)
if ( xa .lt. precc ) then
zdilog = cx
zlog = -cx
ipi12 = 0
return
endif
* #] exceptional cases:
* #[ transform to |x|<1, Re(x) < 0.5:
if ( xr .le. .5D0) then
if (xa .gt. 1) then
if ( 1/xa .lt. xalogm ) then
cfact = 0
elseif ( 1/xa .lt. xclogm ) then
- cx1 = cx*DBLE(1/xa)
- cfact = log(-cx1) + log(DBLE(xa))
+ cx1 = cx*Re(1/xa)
+ cfact = log(-cx1) + log(Re(xa))
else
cfact = log(-cx)
endif
cy = - cfact**2/2
ipi12 = -2
if ( xa*xloss**2 .gt. 1) then
if ( 1/xa .lt. xclogm ) then
- cx1 = cx*DBLE(1/xa)
+ cx1 = cx*Re(1/xa)
cx1 = 1/cx1
- cx1 = cx1*DBLE(1/xa)
+ cx1 = cx1*Re(1/xa)
else
cx1 = 1/cx
endif
cz = -zfflo1(cx1,ier)
else
cz = -log(1-1/cx)
endif
zlog = log(1-cx)
jsgn = -1
else
cy = 0
ipi12 = 0
if ( xa .lt. xloss**2 ) then
zlog = zfflo1(cx,ier)
else
zlog = log(1-cx)
endif
cz = -zlog
jsgn = 1
endif
else
if (xa .le. sqrt(2*xr)) then
cz = -log(cx)
if ( abs(xr-1) + abs(xi) .lt. xclogm ) then
cy = 0
else
zlog = log(1-cx)
cy = cz*zlog
endif
ipi12 = 2
jsgn = -1
else
if ( 1/xa .lt. xalogm ) then
cfact = 0
elseif ( 1/xa .lt. xclogm ) then
- cx1 = cx*DBLE(1/xa)
- cfact = log(-cx1) + log(DBLE(xa))
+ cx1 = cx*Re(1/xa)
+ cfact = log(-cx1) + log(Re(xa))
else
cfact = log(-cx)
endif
cy = - cfact**2/2
ipi12 = -2
if ( xa*xloss .gt. 1) then
if ( 1/xa .lt. xclogm ) then
- cx1 = cx*DBLE(1/xa)
+ cx1 = cx*Re(1/xa)
cx1 = 1/cx1
- cx1 = cx1*DBLE(1/xa)
+ cx1 = cx1*Re(1/xa)
else
cx1 = 1/cx
endif
cz = -zfflo1(cx1,ier)
else
cz = -log(1-1/cx)
endif
zlog = log(1-cx)
jsgn = -1
endif
endif
* #] transform to |x|<1, Re(x) < 0.5:
* #[ get dilog:
if ( absc(cz) .lt. xclogm ) then
zdilog = cz
else
cz2 = cz*cz
- a = DBLE(cz)**2 + DIMAG(cz)**2
+ a = Re(cz)**2 + Im(cz)**2
if ( a .gt. bdn15 ) then
- zdilog = cz2*(DBLE(bf(16)) + cz2*(DBLE(bf(17))
- + + cz2*(DBLE(bf(18)) + cz2*(DBLE(bf(19))
- + + cz2*(DBLE(bf(20)))))))
+ zdilog = cz2*(Re(bf(16)) + cz2*(Re(bf(17))
+ + + cz2*(Re(bf(18)) + cz2*(Re(bf(19))
+ + + cz2*(Re(bf(20)))))))
else
zdilog = 0
endif
if ( a .gt. bdn10 ) then
- zdilog = cz2*(DBLE(bf(11)) + cz2*(DBLE(bf(12))
- + + cz2*(DBLE(bf(13)) + cz2*(DBLE(bf(14))
- + + cz2*(DBLE(bf(15)) + zdilog)))))
+ zdilog = cz2*(Re(bf(11)) + cz2*(Re(bf(12))
+ + + cz2*(Re(bf(13)) + cz2*(Re(bf(14))
+ + + cz2*(Re(bf(15)) + zdilog)))))
endif
if ( a .gt. bdn05 ) then
- zdilog = cz2*(DBLE(bf(6)) + cz2*(DBLE(bf(7))
- + + cz2*(DBLE(bf(8)) + cz2*(DBLE(bf(9))
- + + cz2*(DBLE(bf(10)) + zdilog)))))
+ zdilog = cz2*(Re(bf(6)) + cz2*(Re(bf(7))
+ + + cz2*(Re(bf(8)) + cz2*(Re(bf(9))
+ + + cz2*(Re(bf(10)) + zdilog)))))
endif
if ( a .gt. bdn02 ) then
- zdilog = cz2*(DBLE(bf(3)) + cz2*(DBLE(bf(4))
- + + cz2*(DBLE(bf(5)) + zdilog)))
+ zdilog = cz2*(Re(bf(3)) + cz2*(Re(bf(4))
+ + + cz2*(Re(bf(5)) + zdilog)))
endif
* watch the powers of z.
- zdilog = cz + cz2*(DBLE(bf(1)) + cz*(DBLE(bf(2)) + zdilog))
+ zdilog = cz + cz2*(Re(bf(1)) + cz*(Re(bf(2)) + zdilog))
endif
if(jsgn.eq.1)then
zdilog = zdilog + cy
else
zdilog = -zdilog + cy
endif
* #] get dilog:
*###] ffzzdl:
end
*###[ zfflog:
- DOUBLE COMPLEX function zfflog(cx,ieps,cy,ier)
+ ComplexType function zfflog(cx,ieps,cy,ier)
***#[*comment:***********************************************************
* *
* Calculate the complex logarithm of cx. The following cases *
* are treted separately: *
* |cx| too small: give warning and return 0 *
* (for Absoft, Apollo DN300) *
* Im(cx) = 0, Re(cx) < 0: take sign according to ieps *
* *
***#]*comment:***********************************************************
* #[ declarations:
*
* arguments
*
implicit none
integer ieps,ier
- DOUBLE COMPLEX cx,cy
+ ComplexType cx,cy
*
* local variables
*
- DOUBLE COMPLEX c,ctroep
- DOUBLE PRECISION absc,xa,xlog1p
+ ComplexType c,ctroep
+ RealType absc,xa,xlog1p
*
* common blocks, statement function
*
#include "ff.h"
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ calculations:
xa = absc(cx)
if ( xa .lt. xalogm ) then
if ( cx .ne. 0 ) call fferr(23,ier)
zfflog = 0
- elseif ( DBLE(cx) .lt. 0 .and. DIMAG(cx) .eq. 0 ) then
-* + abs(DIMAG(cx)) .lt. precc*abs(DBLE(cx)) ) then
- xlog1p = log(-DBLE(cx))
+ elseif ( Re(cx) .lt. 0 .and. Im(cx) .eq. 0 ) then
+* + abs(Im(cx)) .lt. precc*abs(Re(cx)) ) then
+ xlog1p = log(-Re(cx))
* checked imaginary parts 19-May-1988
if ( abs(ieps) .eq. 1 ) then
- if ( ieps*DBLE(cy) .lt. 0 ) then
- zfflog = DCMPLX(xlog1p,-pi)
- elseif ( ieps*DBLE(cy) .gt. 0 ) then
- zfflog = DCMPLX(xlog1p,pi)
+ if ( ieps*Re(cy) .lt. 0 ) then
+ zfflog = ToComplex(xlog1p,-pi)
+ elseif ( ieps*Re(cy) .gt. 0 ) then
+ zfflog = ToComplex(xlog1p,pi)
else
call fferr(51,ier)
- zfflog = DCMPLX(xlog1p,pi)
+ zfflog = ToComplex(xlog1p,pi)
endif
elseif ( ieps .ge. 2 .and. ieps .le. 3 ) then
- zfflog = DCMPLX(xlog1p,-pi)
+ zfflog = ToComplex(xlog1p,-pi)
elseif ( ieps .le. -2 .and. ieps .ge. -3 ) then
- zfflog = DCMPLX(xlog1p,pi)
+ zfflog = ToComplex(xlog1p,pi)
else
call fferr(51,ier)
- zfflog = DCMPLX(xlog1p,pi)
+ zfflog = ToComplex(xlog1p,pi)
endif
elseif ( xa .lt. xclogm .or. 1/xa .lt. xclogm ) then
- ctroep = cx*DBLE(1/xa)
- zfflog = log(ctroep) + DBLE(log(xa))
+ ctroep = cx*Re(1/xa)
+ zfflog = log(ctroep) + Re(log(xa))
else
* print *,'zfflog: neem log van ',cx
zfflog = log(cx)
endif
* #] calculations:
*###] zfflog:
end
*###[ zfflo1:
- DOUBLE COMPLEX function zfflo1(cx,ier)
+ ComplexType function zfflo1(cx,ier)
***#[*comment:***************************************************
* calculates log(1-x) for |x|<.14 in a faster way to ~15 *
* significant figures. *
***#]*comment:***************************************************
* #[ declarations:
implicit none
integer ier
- DOUBLE COMPLEX cx,c,zfflog
- DOUBLE PRECISION xprec,bdn01,bdn05,bdn10,bdn15,bdn19,
+ ComplexType cx,c,zfflog
+ RealType xprec,bdn01,bdn05,bdn10,bdn15,bdn19,
+ absc,xa,ffbnd
external zfflog,ffbnd
save xprec,bdn01,bdn05,bdn10,bdn15,bdn19
#include "ff.h"
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ initialisations:
data xprec /-1D0/
if ( precc .ne. xprec ) then
xprec = precc
* determine the boundaries for 1,5,10,15 terms
bdn01 = ffbnd(1,1,xninv)
bdn05 = ffbnd(1,5,xninv)
bdn10 = ffbnd(1,10,xninv)
bdn15 = ffbnd(1,15,xninv)
bdn19 = ffbnd(1,19,xninv)
endif
* #] initialisations:
* #[ calculations:
xa = absc(cx)
if ( xa .gt. bdn19 ) then
c = cx-1
xa = absc(c)
zfflo1 = zfflog(1-cx,0,czero,ier)
return
endif
if ( xa .gt. bdn15 ) then
- zfflo1 = cx*( DBLE(xninv(16)) + cx*( DBLE(xninv(17))
- + + cx*( DBLE(xninv(18)) + cx*( DBLE(xninv(19))
- + + cx*( DBLE(xninv(20)) )))))
+ zfflo1 = cx*( Re(xninv(16)) + cx*( Re(xninv(17))
+ + + cx*( Re(xninv(18)) + cx*( Re(xninv(19))
+ + + cx*( Re(xninv(20)) )))))
else
zfflo1 = 0
endif
if ( xa .gt. bdn10 ) then
- zfflo1 = cx*( DBLE(xninv(11)) + cx*( DBLE(xninv(12))
- + + cx*( DBLE(xninv(13)) + cx*( DBLE(xninv(14))
- + + cx*( DBLE(xninv(15)) + zfflo1 )))))
+ zfflo1 = cx*( Re(xninv(11)) + cx*( Re(xninv(12))
+ + + cx*( Re(xninv(13)) + cx*( Re(xninv(14))
+ + + cx*( Re(xninv(15)) + zfflo1 )))))
endif
if ( xa .gt. bdn05 ) then
- zfflo1 = cx*( DBLE(xninv(6)) + cx*( DBLE(xninv(7))
- + + cx*( DBLE(xninv(8)) + cx*( DBLE(xninv(9))
- + + cx*( DBLE(xninv(10)) + zfflo1 )))))
+ zfflo1 = cx*( Re(xninv(6)) + cx*( Re(xninv(7))
+ + + cx*( Re(xninv(8)) + cx*( Re(xninv(9))
+ + + cx*( Re(xninv(10)) + zfflo1 )))))
endif
if ( xa .gt. bdn01 ) then
- zfflo1 = cx*( DBLE(xninv(2)) + cx*( DBLE(xninv(3))
- + + cx*( DBLE(xninv(4)) + cx*( DBLE(xninv(5))
+ zfflo1 = cx*( Re(xninv(2)) + cx*( Re(xninv(3))
+ + + cx*( Re(xninv(4)) + cx*( Re(xninv(5))
+ + zfflo1 ))))
endif
- zfflo1 = - cx*( DBLE(xninv(1)) + zfflo1 )
+ zfflo1 = - cx*( Re(xninv(1)) + zfflo1 )
* #] calculations:
*###] zfflo1:
end
*###[ zfflo2:
- DOUBLE COMPLEX function zfflo2(x,ier)
+ ComplexType function zfflo2(x,ier)
***#[*comment:***************************************************
* calculates log(1-x)+x for |x|<.14 in a faster way to *
* ~15 significant figures. *
***#]*comment:***************************************************
* #[ declarations:
implicit none
integer ier
- DOUBLE COMPLEX x,zfflo1,cc
- DOUBLE PRECISION bdn01,bdn05,bdn10,bdn15,bdn18,xprec,xa,
+ ComplexType x,zfflo1,cc
+ RealType bdn01,bdn05,bdn10,bdn15,bdn18,xprec,xa,
+ ffbnd,absc
external ffbnd,zfflo1
save xprec,bdn01,bdn05,bdn10,bdn15,bdn18
#include "ff.h"
- absc(cc) = abs(DBLE(cc)) + abs(DIMAG(cc))
+ absc(cc) = abs(Re(cc)) + abs(Im(cc))
* #] declarations:
* #[ initialisation:
data xprec /-1D0/
if ( xprec .ne. precc ) then
xprec = precx
precx = precc
* determine the boundaries for 1,5,10,15 terms
bdn01 = ffbnd(1,1,xninv(2))
bdn05 = ffbnd(1,5,xninv(2))
bdn10 = ffbnd(1,10,xninv(2))
bdn15 = ffbnd(1,15,xninv(2))
bdn18 = ffbnd(1,18,xninv(2))
precx = xprec
xprec = precc
endif
* #] initialisation:
* #[ calculations:
xa = absc(x)
if ( xa .gt. bdn18 ) then
zfflo2 = zfflo1(x,ier) + x
return
endif
if ( xa .gt. bdn15 ) then
- zfflo2 = x*( DBLE(xninv(17)) + x*( DBLE(xninv(18)) +
- + x*( DBLE(xninv(19)) + x*( DBLE(xninv(20)) ))))
+ zfflo2 = x*( Re(xninv(17)) + x*( Re(xninv(18)) +
+ + x*( Re(xninv(19)) + x*( Re(xninv(20)) ))))
else
zfflo2 = 0
endif
if ( xa .gt. bdn10 ) then
- zfflo2 = x*( DBLE(xninv(12)) + x*( DBLE(xninv(13)) +
- + x*( DBLE(xninv(14)) + x*( DBLE(xninv(15)) +
- + x*( DBLE(xninv(16)) + zfflo2 )))))
+ zfflo2 = x*( Re(xninv(12)) + x*( Re(xninv(13)) +
+ + x*( Re(xninv(14)) + x*( Re(xninv(15)) +
+ + x*( Re(xninv(16)) + zfflo2 )))))
endif
if ( xa .gt. bdn05 ) then
- zfflo2 = x*( DBLE(xninv(7)) + x*( DBLE(xninv(8)) +
- + x*( DBLE(xninv(9)) +x*( DBLE(xninv(10)) +
- + x*( DBLE(xninv(11)) + zfflo2 )))))
+ zfflo2 = x*( Re(xninv(7)) + x*( Re(xninv(8)) +
+ + x*( Re(xninv(9)) +x*( Re(xninv(10)) +
+ + x*( Re(xninv(11)) + zfflo2 )))))
endif
if ( xa .gt. bdn01 ) then
- zfflo2 = x*( DBLE(xninv(3)) + x*( DBLE(xninv(4)) +
- + x*( DBLE(xninv(5)) + x*( DBLE(xninv(6)) + zfflo2 ))))
+ zfflo2 = x*( Re(xninv(3)) + x*( Re(xninv(4)) +
+ + x*( Re(xninv(5)) + x*( Re(xninv(6)) + zfflo2 ))))
endif
- zfflo2 = - x**2*( DBLE(xninv(2)) + zfflo2 )
+ zfflo2 = - x**2*( Re(xninv(2)) + zfflo2 )
* #] calculations:
*###] zfflo2:
end
*###[ zfflo3:
- DOUBLE COMPLEX function zfflo3(x,ier)
+ ComplexType function zfflo3(x,ier)
***#[*comment:***************************************************
* calculates log(1-x)+x+x^2/2 for |x|<.14 in a faster *
* way to ~15 significant figures. *
***#]*comment:***************************************************
* #[ declarations:
implicit none
integer ier
- DOUBLE COMPLEX x,zfflo2,cc
- DOUBLE PRECISION bdn01,bdn05,bdn10,bdn15,xprec,xa,ffbnd,
+ ComplexType x,zfflo2,cc
+ RealType bdn01,bdn05,bdn10,bdn15,xprec,xa,ffbnd,
+ absc
external zfflo2,ffbnd
save xprec,bdn01,bdn05,bdn10,bdn15
#include "ff.h"
- absc(cc) = abs(DBLE(cc)) + abs(DIMAG(cc))
+ absc(cc) = abs(Re(cc)) + abs(Im(cc))
* #] declarations:
* #[ initialisation:
data xprec /-1D0/
if ( xprec .ne. precx ) then
xprec = precx
precx = precc
* determine the boundaries for 1,5,10,15 terms
bdn01 = ffbnd(1,1,xninv(3))
bdn05 = ffbnd(1,5,xninv(3))
bdn10 = ffbnd(1,10,xninv(3))
bdn15 = ffbnd(1,15,xninv(3))
precx = xprec
xprec = precc
endif
* #] initialisation:
* #[ calculations:
xa = absc(x)
if ( xa .gt. bdn15 ) then
zfflo3 = zfflo2(x,ier) + x**2/2
return
endif
if ( xa .gt. bdn10 ) then
- zfflo3 = x*( DBLE(xninv(13)) + x*( DBLE(xninv(14)) +
- + x*( DBLE(xninv(15)) + x*( DBLE(xninv(16)) +
- + x*( DBLE(xninv(17)) )))))
+ zfflo3 = x*( Re(xninv(13)) + x*( Re(xninv(14)) +
+ + x*( Re(xninv(15)) + x*( Re(xninv(16)) +
+ + x*( Re(xninv(17)) )))))
else
zfflo3 = 0
endif
if ( xa .gt. bdn05 ) then
- zfflo3 = x*( DBLE(xninv(8)) + x*( DBLE(xninv(9)) +
- + x*( DBLE(xninv(10)) + x*( DBLE(xninv(11)) +
- + x*( DBLE(xninv(12)) + zfflo3 )))))
+ zfflo3 = x*( Re(xninv(8)) + x*( Re(xninv(9)) +
+ + x*( Re(xninv(10)) + x*( Re(xninv(11)) +
+ + x*( Re(xninv(12)) + zfflo3 )))))
endif
if ( xa .gt. bdn01 ) then
- zfflo3 = x*( DBLE(xninv(4)) + x*( DBLE(xninv(5)) +
- + x*( DBLE(xninv(6)) + x*( DBLE(xninv(7)) + zfflo3 ))))
+ zfflo3 = x*( Re(xninv(4)) + x*( Re(xninv(5)) +
+ + x*( Re(xninv(6)) + x*( Re(xninv(7)) + zfflo3 ))))
endif
- zfflo3 = - x**3*( DBLE(xninv(3)) + zfflo3 )
+ zfflo3 = - x**3*( Re(xninv(3)) + zfflo3 )
* #] calculations:
*###] zfflo3:
end
diff --git a/Looptools/util/ffcrr.F b/Looptools/util/ffcrr.F
--- a/Looptools/util/ffcrr.F
+++ b/Looptools/util/ffcrr.F
@@ -1,655 +1,656 @@
#include "externals.h"
+#include "types.h"
*--#[ log:
* $Id: ffcrr.f,v 1.5 1995/11/10 19:04:23 gj Exp $
* $Log: ffcrr.f,v $
c Revision 1.5 1995/11/10 19:04:23 gj
c Added nicer logging header...
c
c Revision 1.4 1995/10/17 06:55:07 gj
c Fixed ieps error in ffdcrr (ffcxs4.f), added real case in ffcrr, debugging
c info in ffxd0, and warned against remaining errors for del2=0 in ffrot4
c (ffxd0h.f)
c
c Revision 1.3 1995/10/06 09:17:20 gj
c Found stupid typo in ffxc0p which caused the result to be off by pi^2/3 in
c some equal-mass cases. Added checks to ffcxs4.f ffcrr.f.
c
*--#] log:
*###[ ffcrr:
subroutine ffcrr(crr,ipi12,cy,cy1,cz,cz1,cdyz,ld2yzz,cd2yzz,czz,
+ czz1,isoort,ieps,ier)
***#[*comment:***********************************************************
* *
* calculates R as defined in appendix b: *
* *
* /1 log(y-y1+ieps) - log(y0-y1+ieps) *
* r(y0,y1,iesp) = \ dy -------------------------------- *
* /0 y-y0 *
* *
* = li2(c1) - li2(c2) *
* + eta(-y1,1/(y0-y1))*log(c1) *
* - eta(1-y1,1/(y0-y1))*log(c2) *
* with *
* c1 = y0 / (y0-y1), c2 = (y0-1) / (y0-y1) *
* *
* the factors pi^2/12 are passed separately in the integer ipi12 *
* ier is a status flag: 0=ok, 1=numerical problems, 2=error *
* *
* Input: cy (complex) *
* cy1 (complex) 1-y *
* cz (complex) *
* cz1 (complex) 1-z *
* cdyz (complex) y-z *
* ieps (integer) denotes sign imaginary part of *
* argument logs (0: don't care; *
* +/-1: add -ieps to z; +/-2: *
* direct in dilogs, no eta's) *
* *
* Output crr (complex) R modulo factors pi^2/12 *
* ipi12 (integer) these factors *
* ier (integer) lost ier digits, >100: error *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ipi12,isoort,ieps,ier
logical ld2yzz,lreal
- DOUBLE COMPLEX crr(7),cy,cy1,cz,cz1,cdyz,cd2yzz,czz,czz1
+ ComplexType crr(7),cy,cy1,cz,cz1,cdyz,cd2yzz,czz,czz1
*
* local variables
*
- DOUBLE COMPLEX cfact,cc1,cc2,cc1p,cc2p,carg1,carg2,carg3,
+ ComplexType cfact,cc1,cc2,cc1p,cc2p,carg1,carg2,carg3,
+ cli1,cli2,cli3,clo1,clo2,clo3,clog1p,clog2p,chill,
+ cd2,cd21,cd2n,cd21n1,cc1n,cterm,ctot,zfflo1,clog1,clog2,
+ cc,cli4,clo4
- DOUBLE COMPLEX ctroep,zfflog
- DOUBLE PRECISION xa,xr,absc,xprec,bndtay,ffbnd
- DOUBLE PRECISION y,y1,z,z1,dyz,d2yzz,zz,zz1
+ ComplexType ctroep,zfflog
+ RealType xa,xr,absc,xprec,bndtay,ffbnd
+ RealType y,y1,z,z1,dyz,d2yzz,zz,zz1
integer i,nffeta,nffet1,iclas1,iclas2,n1,n2,n3,ntot,
+ i2pi,n3p
external zfflog,zfflo1,ffbnd,nffeta,nffet1
save xprec,bndtay
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(cc) = abs(DBLE(cc)) + abs(DIMAG(cc))
+ absc(cc) = abs(Re(cc)) + abs(Im(cc))
* #] declarations:
* #[ initialisations:
data xprec /-1D0/
if ( xprec .ne. precx ) then
xprec = precx
bndtay = ffbnd(2,18,xn2inv)
* print *,'bndtay = ',bndtay
endif
* #] initialisations:
* #[ real case:
- if ( DIMAG(cy).eq.0 .and. DIMAG(cy1).eq.0 .and. DIMAG(cz).eq.0
- + .and. DIMAG(cz1).eq.0 ) then
- y = DBLE(cy)
- y1 = DBLE(cy1)
- z = DBLE(cz)
- z1 = DBLE(cz1)
- dyz = DBLE(cdyz)
- d2yzz = DBLE(cd2yzz)
- zz = DBLE(czz)
- zz1 = DBLE(czz1)
+ if ( Im(cy).eq.0 .and. Im(cy1).eq.0 .and. Im(cz).eq.0
+ + .and. Im(cz1).eq.0 ) then
+ y = Re(cy)
+ y1 = Re(cy1)
+ z = Re(cz)
+ z1 = Re(cz1)
+ dyz = Re(cdyz)
+ d2yzz = Re(cd2yzz)
+ zz = Re(czz)
+ zz1 = Re(czz1)
call ffcxr(crr,ipi12,y,y1,z,z1,dyz,ld2yzz,d2yzz,zz,zz1,
+ .FALSE.,0D0,ieps,ier)
return
endif
* #] real case:
* #[ arguments:
*
* get the arguments
*
xa = absc(cdyz)
if ( xa .eq. 0 ) then
return
* This line is for 68000 compilers that have a limited range for
* complex division (Absoft, Apollo, Gould NP1):
- elseif ( DBLE(cdyz) .lt. xclogm .or. DIMAG(cdyz) .lt. xclogm
+ elseif ( Re(cdyz) .lt. xclogm .or. Im(cdyz) .lt. xclogm
+ .or. 1/xa .lt. xclogm ) then
- ctroep = cdyz*DBLE(1/xa)
+ ctroep = cdyz*Re(1/xa)
cfact = 1/ctroep
- cfact = DBLE(1/xa)*cfact
+ cfact = Re(1/xa)*cfact
else
cfact = 1/cdyz
endif
cc1 = cy * cfact
cc2 = - cy1 * cfact
*
* see if we just need the real part
*
lreal = mod(isoort,5) .eq. 0
* #] arguments:
* #[ which area?:
*
* determine the area: 1={|x|<=1,Re(x)<=1/2},
* 2={|1-x|<=1,Re(x)>1/2}
* 3={|x|>1,|1-x|>1}
*
- xr = DBLE(cc1)
+ xr = Re(cc1)
xa = absc(cc1)
if ( xa .gt. 1 .and. xa .lt. 1+sqrt(2.) ) then
* we need a more accurate estimate
- xa = xr**2 + DIMAG(cc1)**2
+ xa = xr**2 + Im(cc1)**2
endif
if ( ld2yzz .and. absc(cc1+1) .lt. xloss/2 ) then
iclas1 = 4
cc1p = cc1
elseif ( xa .le. 1 .and. xr .le. 0.5 ) then
iclas1 = 1
cc1p = cc1
elseif ( xa .lt. 1+sqrt(2.) .and. xa .lt. 2*xr ) then
iclas1 = 2
cc1p = -cz * cfact
- if ( abs(DIMAG(cc1p)) .lt. precc*abs(DBLE(cc1p)) )
- + cc1p = DBLE(cc1p)
+ if ( abs(Im(cc1p)) .lt. precc*abs(Re(cc1p)) )
+ + cc1p = Re(cc1p)
else
iclas1 = 3
if ( 1/xa .lt. xclogm ) then
- ctroep = cc1*DBLE(1/xa)
+ ctroep = cc1*Re(1/xa)
ctroep = 1/ctroep
- cc1p = ctroep*DBLE(1/xa)
+ cc1p = ctroep*Re(1/xa)
else
cc1p = 1/cc1
endif
endif
- xr = DBLE(cc2)
+ xr = Re(cc2)
xa = absc(cc2)
if ( xa .gt. 1 .and. xa .lt. 1+sqrt(2.) ) then
- xa = xr**2 + DIMAG(cc2)**2
+ xa = xr**2 + Im(cc2)**2
endif
if ( ld2yzz .and. absc(cc2+1) .lt. xloss ) then
iclas2 = 4
cc2p = cc2
elseif ( xa .le. 1 .and. xr .le. 0.5 ) then
iclas2 = 1
cc2p = cc2
elseif ( xa .lt. 1+sqrt(2.) .and. xa .lt. 2*xr ) then
iclas2 = 2
cc2p = cz1 * cfact
- if ( abs(DIMAG(cc2p)) .lt. precc*abs(DBLE(cc2p)) )
- + cc2p = DBLE(cc2p)
+ if ( abs(Im(cc2p)) .lt. precc*abs(Re(cc2p)) )
+ + cc2p = Re(cc2p)
else
iclas2 = 3
if ( 1/xa .lt. xclogm ) then
- ctroep = cc2*DBLE(1/xa)
+ ctroep = cc2*Re(1/xa)
ctroep = 1/ctroep
- cc2p = ctroep*DBLE(1/xa)
+ cc2p = ctroep*Re(1/xa)
else
cc2p = 1/cc2
endif
endif
*
* throw together if they are close
*
if ( iclas1 .ne. iclas2 .and. absc(cc1-cc2) .lt. 2*xloss )
+ then
* we don't want trouble with iclasn = 4
if ( iclas1 .eq. 4 ) iclas1 = 1
if ( iclas2 .eq. 4 ) iclas2 = 1
if ( iclas1 .eq. iclas2 ) goto 5
* go on
if ( iclas1 .le. iclas2 ) then
iclas2 = iclas1
if ( iclas1 .eq. 1 ) then
cc2p = cc2
else
cc2p = cz1*cfact
endif
else
iclas1 = iclas2
if ( iclas1 .eq. 1 ) then
cc1p = cc1
else
cc1p = -cz*cfact
endif
endif
endif
5 continue
* #] which area?:
* #[ eta's:
*
* get eta1 and eta2
*
if ( abs(ieps) .ge. 2 .or. isoort .eq. -2 ) then
n1 = 0
n2 = 0
else
- if ( DIMAG(cz) .eq. 0 .or. DIMAG(cz1) .eq. 0 ) then
- if ( DIMAG(cz1) .eq. 0 ) then
- if ( DIMAG(cz) .eq. 0 ) then
+ if ( Im(cz) .eq. 0 .or. Im(cz1) .eq. 0 ) then
+ if ( Im(cz1) .eq. 0 ) then
+ if ( Im(cz) .eq. 0 ) then
* cz is really real, the hard case:
if ( cz .eq. 0 ) then
* multiplied with log(1), so don't care:
n1 = 0
* look at ieps for guidance
-* n2 = nffet1(DCMPLX(DBLE(0),DBLE(ieps)),cfact,cfact,ier) = 0
+* n2 = nffet1(ToComplex(Re(0),Re(ieps)),cfact,cfact,ier) = 0
n2 = 0
elseif ( cz1 .eq. 0 ) then
- n1 = nffet1(DCMPLX(DBLE(0),DBLE(ieps)),cfact,
+ n1 = nffet1(ToComplex(Re(0),Re(ieps)),cfact,
+ -cfact,ier)
n2 = 0
else
- n1 = nffet1(DCMPLX(DBLE(0),DBLE(ieps)),cfact,
+ n1 = nffet1(ToComplex(Re(0),Re(ieps)),cfact,
+ -cz*cfact,ier)
- n2 = nffet1(DCMPLX(DBLE(0),DBLE(ieps)),cfact,
+ n2 = nffet1(ToComplex(Re(0),Re(ieps)),cfact,
+ cz1*cfact,ier)
endif
else
n1 = nffet1(-cz,cfact,-cz*cfact,ier)
n2 = nffet1(-cz,cfact,cz1*cfact,ier)
endif
else
n1 = nffet1(cz1,cfact,-cz*cfact,ier)
n2 = nffet1(cz1,cfact,cz1*cfact,ier)
endif
else
* the imaginary part of cc1, cc1p is often very unstable.
* make sure it agrees with the actual sign used.
if ( iclas1 .eq. 2 ) then
- if ( DIMAG(cc1p) .eq. 0 ) then
+ if ( Im(cc1p) .eq. 0 ) then
* if y (or y1 further on) is purely imaginary
* give a random shift, this will also be used in
* the transformation terms. Checked 7-mar-94 that it
* is independent of the sign used.
- if ( DBLE(cy).eq.0 ) cy = cy +
- + isgnal*DBLE(precc)*DIMAG(cy)
- n1 = nffet1(-cz,cfact,DCMPLX(DBLE(0),ieps*DBLE(cy)),
+ if ( Re(cy).eq.0 ) cy = cy +
+ + isgnal*Re(precc)*Im(cy)
+ n1 = nffet1(-cz,cfact,ToComplex(Re(0),ieps*Re(cy)),
+ ier)
else
n1 = nffet1(-cz,cfact,cc1p,ier)
endif
else
- if ( DIMAG(cc1) .eq. 0 ) then
- if ( DBLE(cy1).eq.0 ) cy1 = cy1 +
- + isgnal*DBLE(precc)*DIMAG(cy)
- n1 = nffet1(-cz,cfact,DCMPLX(DBLE(0),
- + -ieps*DBLE(cy1)),ier)
+ if ( Im(cc1) .eq. 0 ) then
+ if ( Re(cy1).eq.0 ) cy1 = cy1 +
+ + isgnal*Re(precc)*Im(cy)
+ n1 = nffet1(-cz,cfact,ToComplex(Re(0),
+ + -ieps*Re(cy1)),ier)
else
n1 = nffet1(-cz,cfact,-cc1,ier)
endif
endif
if ( iclas2 .eq. 2 ) then
- if ( DIMAG(cc2p) .eq. 0 ) then
- if ( DBLE(cy).eq.0 ) cy = cy +
- + isgnal*DBLE(precc)*DIMAG(cy)
- n2 = nffet1(cz1,cfact,DCMPLX(DBLE(0),ieps*DBLE(cy)),
+ if ( Im(cc2p) .eq. 0 ) then
+ if ( Re(cy).eq.0 ) cy = cy +
+ + isgnal*Re(precc)*Im(cy)
+ n2 = nffet1(cz1,cfact,ToComplex(Re(0),ieps*Re(cy)),
+ ier)
else
n2 = nffet1(cz1,cfact,cc2p,ier)
endif
else
- if ( DIMAG(cc2) .eq. 0 ) then
- if ( DBLE(cy1).eq.0 ) cy1 = cy1 +
- + isgnal*DBLE(precc)*DIMAG(cy)
- n2 = nffet1(cz1,cfact,DCMPLX(DBLE(0),
- + -ieps*DBLE(cy1)),ier)
+ if ( Im(cc2) .eq. 0 ) then
+ if ( Re(cy1).eq.0 ) cy1 = cy1 +
+ + isgnal*Re(precc)*Im(cy)
+ n2 = nffet1(cz1,cfact,ToComplex(Re(0),
+ + -ieps*Re(cy1)),ier)
else
n2 = nffet1(cz1,cfact,-cc2,ier)
endif
endif
endif
endif
* #] eta's:
* #[ calculations:
* 3-oct-1995 changed code to only use second criterium if the
* Taylor expansion is used - otherwise the Hill identity will
* only make things worse
if ( iclas1 .eq. iclas2 .and. isoort .ne. -2 .and.
+ ( absc(cc1p-cc2p) .lt. 2*xloss*absc(cc1p)
- + .or. lreal .and. abs(DBLE(cc1p-cc2p)) .lt. 2*xloss*
- + abs(DBLE(cc1p)) .and. (abs(DBLE(cc2p)) +
- + DIMAG(cc2p)**2/4) .lt. xloss .and.
- + abs(DIMAG(cc2p)) .lt. bndtay ) ) then
+ + .or. lreal .and. abs(Re(cc1p-cc2p)) .lt. 2*xloss*
+ + abs(Re(cc1p)) .and. (abs(Re(cc2p)) +
+ + Im(cc2p)**2/4) .lt. xloss .and.
+ + abs(Im(cc2p)) .lt. bndtay ) ) then
* Close together:
* -#[ handle dilog's:
if ( .not. lreal .and. absc(cc2p) .gt. xloss
- + .or. lreal .and. ( (abs(DBLE(cc2p)) + DIMAG(cc2p)**2/4)
- + .gt. xloss .or. abs(DIMAG(cc2p)) .gt. bndtay ) )
+ + .or. lreal .and. ( (abs(Re(cc2p)) + Im(cc2p)**2/4)
+ + .gt. xloss .or. abs(Im(cc2p)) .gt. bndtay ) )
+ then
*--#[ Hill identity:
*
* Use the Hill identity to get rid of the cancellations.
*
*
* first get the arguments:
*
if ( iclas1 .eq. 1 .or. iclas1 .eq. 4 ) then
carg1 = 1/cy
carg2 = 1/cz1
carg3 = carg2/cc1p
elseif ( iclas1 .eq. 2 ) then
carg1 = 1/cz
carg2 = 1/cy1
carg3 = carg2/cc1p
elseif ( iclas1 .eq. 3 ) then
carg1 = 1/cy1
carg3 = 1/cz1
carg2 = carg3*cc1p
endif
call ffzli2(cli1,clo1,carg1,ier)
call ffzli2(cli2,clo2,carg2,ier)
call ffzli2(cli3,clo3,carg3,ier)
if ( absc(cc2p) .lt. xloss ) then
clog2p = zfflo1(cc2p,ier)
else
clog2p = zfflog(1-cc2p,0,czero,ier)
endif
chill = clo1*clog2p
*--#] Hill identity:
else
*--#[ Taylor expansion:
*
* if the points are close to zero do a Taylor
* expansion of the first and last dilogarithm
*
* Li2(cc1p) - Li2(cc2p)
* = sum cc1p^i ( 1-(1-cd2)^i ) /i^2
*
* with cd2 = 1-cc2p/cc1p = ...
*
if ( iclas1 .eq. 1 .or. iclas1 .eq. 4 ) then
cd2 = 1/cy
elseif ( iclas1 .eq. 2 ) then
cd2 = 1/cz
elseif ( iclas1 .eq. 3 ) then
cd2 = 1/cy1
endif
cd21 = 1-cd2
cd21n1 = 1
cc1n = cc1p
cd2n = cd2
ctot = cc1p*cd2
do 50 i=2,20
cc1n = cc1n*cc1p
cd21n1 = cd21n1*cd21
cd2n = cd2n + cd2*cd21n1
- cterm = cc1n*cd2n*DBLE(xn2inv(i))
+ cterm = cc1n*cd2n*Re(xn2inv(i))
ctot = ctot + cterm
if ( absc(cterm) .le. precc*absc(ctot) .or.
- + lreal .and. abs(DBLE(cterm)) .le. precc*
- + abs(DBLE(ctot)) ) goto 51
+ + lreal .and. abs(Re(cterm)) .le. precc*
+ + abs(Re(ctot)) ) goto 51
50 continue
51 continue
cli1 = ctot
cli2 = 0
cli3 = 0
chill = 0
* for the eta+transformation section we also need
if ( iclas1.ne.1 .or. n1.ne.0 .or. n2.ne.0 )
+ clo1 = zfflo1(cd2,ier)
if ( iclas1.eq.2 ) clo2 = zfflo1(1/cy1,ier)
*--#] Taylor expansion:
endif
*
* -#] handle dilog's:
* -#[ handle eta + transformation terms:
if ( iclas1.eq.1 .or. iclas1.eq.4 ) then
*--#[ no transformation:
*
* no transformation was made.
*
* crr(5) = 0
if ( n1 .ne. n2 ) then
if ( absc(cc1) .lt. xclogm ) then
call fferr(23,ier)
else
* imaginary part not checked
ier = ier + 50
crr(5) = (n1-n2)*c2ipi*zfflog(cc1,ieps,-cy,ier)
endif
endif
* crr(6) = 0
* crr(7) = 0
if ( n2.ne.0 ) then
crr(6) = - n2*c2ipi*clo1
n3 = nffeta(cc2,1/cc1,ier)
if ( n3 .ne. 0 ) then
crr(7) = n2*n3*c2ipi**2
* else
* crr(7) = 0
endif
endif
*--#] no transformation:
elseif ( iclas1 .eq. 2 ) then
*--#[ transform 1-x:
*
* we tranformed to 1-x for both dilogs
*
if ( absc(cc1p) .lt. xloss ) then
clog1 = zfflo1(cc1p,ier)
else
clog1 = zfflog(cc1,ieps,-cy,ier)
endif
- if ( DIMAG(cc2p).eq.0 ) then
- if ( DIMAG(cc1p).eq.0 ) then
+ if ( Im(cc2p).eq.0 ) then
+ if ( Im(cc1p).eq.0 ) then
* use the ieps instead
n3 = 0
else
- n3 = nffet1(DCMPLX(DBLE(0),ieps*DBLE(cy)),
+ n3 = nffet1(ToComplex(Re(0),ieps*Re(cy)),
+ 1/cc1p,cc2p/cc1p,ier)
endif
else
- if ( DIMAG(cc1p).eq.0 ) then
- n3 =nffet1(cc2p,DCMPLX(DBLE(0),-ieps*DBLE(cy1)),
+ if ( Im(cc1p).eq.0 ) then
+ n3 =nffet1(cc2p,ToComplex(Re(0),-ieps*Re(cy1)),
+ cc2p/cc1p,ier)
else
n3 = nffet1(cc2p,1/cc1p,cz,ier)
endif
endif
ntot = n1-n2-n3
crr(5) = (ntot*c2ipi + clo1)*clog1
clog2p = zfflog(cc2p,ieps,cy,ier)
crr(6) = clo2*(n2*c2ipi - clog2p)
*--#] transform 1-x:
elseif ( iclas1 .eq. 3 ) then
*--#[ transform 1/x:
*
* we transformed to 1/x for both dilogs
*
clog2p = zfflog(-cc2p,ieps,cy1,ier)
- if ( DIMAG(cc2p).eq.0 .or. DIMAG(cc1).eq.0 ) then
+ if ( Im(cc2p).eq.0 .or. Im(cc1).eq.0 ) then
* we chose the eta's already equal, no worry.
n3 = 0
n3p = 0
else
n3 = nffet1(-cc2p,-cc1,-cy/cy1,ier)
n3p = nffet1(cc2p,cc1,-cy/cy1,ier)
endif
if ( n3.ne.0 .or. n3p.ne.0 .or. n1.ne.n2 ) then
* for the time being the normal terms, I'll have to think of
* something smarter one day
clog1p = zfflog(-cc1p,ieps,-cy,ier)
crr(5) = -clog1p**2/2
crr(6) = +clog2p**2/2
crr(7) = (n1*zfflog(cc1,ieps,cy,ier) -
+ n2*zfflog(cc2,ieps,-cy1,ier))*c2ipi
else
crr(5) = clo1*(n2*c2ipi + clog2p - clo1/2)
endif
*--#] transform 1/x:
endif
* -#] handle eta + transformation terms:
* -#[ add up:
if ( iclas1 .eq. 1 .or. iclas1 .eq. 4 ) then
crr(1) = cli1
crr(2) = cli2
crr(3) = - cli3
crr(4) = chill
else
crr(1) = - cli1
crr(2) = - cli2
crr(3) = cli3
crr(4) = - chill
endif
* -#] add up:
else
* Normal case:
* -#[ handle dilogs:
*
* the dilogs will not come close together so just go on
* only the special case cc1p ~ (-1,0) needs special attention
*
if ( iclas1 .ne. 4 .or. .not. ld2yzz ) then
call ffzli2(cli1,clo1,cc1p,ier)
else
cd2 = cd2yzz + czz
if ( absc(cd2) .lt. xloss*absc(cd2yzz) ) then
cd2 = cy + cdyz
endif
cd2 = cd2/cdyz
cfact = 1/(2-cd2)
call ffzli2(cli1,clo1,cd2*cfact,ier)
call ffzli2(cli3,clo3,-cd2*cfact,ier)
call ffzli2(cli4,clo4,cd2,ier)
endif
if ( iclas2 .ne. 4 .or. .not. ld2yzz ) then
call ffzli2(cli2,clo2,cc2p,ier)
else
if ( iclas1 .eq. 4 ) call fferr(26,ier)
cd2 = cd2yzz - czz1
if ( absc(cd2) .lt. xloss*absc(cd2yzz) ) then
cd2 = cdyz - cy1
endif
cd2 = cd2/cdyz
cfact = 1/(2-cd2)
call ffzli2(cli2,clo2,cd2*cfact,ier)
call ffzli2(cli3,clo3,-cd2*cfact,ier)
call ffzli2(cli4,clo4,cd2,ier)
endif
* -#] handle dilogs:
* -#[ handle eta terms:
*
* the eta's
*
if ( n1 .ne. 0 ) then
if ( iclas1 .ne. 2 .or. absc(cc1p) .gt. xloss ) then
- if ( DBLE(cc1) .gt. -abs(DIMAG(cc1)) ) then
+ if ( Re(cc1) .gt. -abs(Im(cc1)) ) then
clog1 = zfflog(cc1,ieps,cy,ier)
else
* take apart the factor i*pi^2
if ( iclas1 .eq. 4 ) then
clog1 = zfflo1(cd2,ier)
else
clog1 = zfflog(-cc1,0,cy,ier)
endif
- if ( DIMAG(cc1) .lt. 0 ) then
+ if ( Im(cc1) .lt. 0 ) then
i2pi = -1
- elseif ( DIMAG(cc1) .gt. 0 ) then
+ elseif ( Im(cc1) .gt. 0 ) then
i2pi = +1
- elseif ( DBLE(cy)*ieps .lt. 0 ) then
+ elseif ( Re(cy)*ieps .lt. 0 ) then
i2pi = -1
- elseif ( DBLE(cy)*ieps .gt. 0 ) then
+ elseif ( Re(cy)*ieps .gt. 0 ) then
i2pi = +1
else
call fferr(51,ier)
i2pi = 0
endif
ipi12 = ipi12 - n1*24*i2pi
endif
else
clog1 = zfflo1(cc1p,ier)
endif
crr(5) = n1*c2ipi*clog1
* else
* crr(5) = 0
endif
if ( n2 .ne. 0 ) then
if ( iclas2 .ne. 2 .or. absc(cc2p) .gt. xloss ) then
- if ( DBLE(cc2) .gt. -abs(DIMAG(cc2)) ) then
+ if ( Re(cc2) .gt. -abs(Im(cc2)) ) then
clog2 = zfflog(cc2,ieps,cy,ier)
else
* take apart the factor i*pi^2
if ( iclas2 .eq. 4 ) then
clog2 = zfflo1(cd2,ier)
else
clog2 = zfflog(-cc2,0,czero,ier)
endif
- if ( DIMAG(cc2) .lt. 0 ) then
+ if ( Im(cc2) .lt. 0 ) then
i2pi = -1
- elseif ( DIMAG(cc2) .gt. 0 ) then
+ elseif ( Im(cc2) .gt. 0 ) then
i2pi = +1
- elseif ( DBLE(cy)*ieps .lt. 0 ) then
+ elseif ( Re(cy)*ieps .lt. 0 ) then
i2pi = -1
- elseif ( DBLE(cy)*ieps .gt. 0 ) then
+ elseif ( Re(cy)*ieps .gt. 0 ) then
i2pi = +1
else
call fferr(51,ier)
i2pi = 0
endif
ipi12 = ipi12 + n2*24*i2pi
endif
else
clog2 = zfflo1(cc2p,ier)
endif
crr(6) = n2*c2ipi*clog2
* else
* crr(6) = 0
endif
* -#] handle eta terms:
* -#[ handle transformation terms:
*
* transformation of cc1
*
if ( iclas1 .eq. 1 ) then
* crr(3) = 0
elseif( iclas1 .eq. 2 ) then
cli1 = -cli1
ipi12 = ipi12 + 2
crr(3) = - clo1*zfflog(cc1p,ieps,cy,ier)
elseif ( iclas1 .eq. 3 ) then
cli1 = -cli1
ipi12 = ipi12 - 2
clog1p = zfflog(-cc1p,ieps,cy1,ier)
crr(3) = - clog1p**2/2
elseif ( iclas1 .eq. 4 ) then
* Note that this sum does not cause problems as d2<<1
crr(3) = -cli3 - cli4 + clo4*zfflog(cfact,0,czero,ier)
ipi12 = ipi12 - 1
else
call fferr(25,ier)
endif
*
* transformation of cc2
*
if ( iclas2 .eq. 1 ) then
elseif( iclas2 .eq. 2 ) then
cli2 = -cli2
ipi12 = ipi12 - 2
crr(4) = clo2*zfflog(cc2p,ieps,cy,ier)
elseif ( iclas2 .eq. 3 ) then
cli2 = -cli2
ipi12 = ipi12 + 2
clog2p = zfflog(-cc2p,ieps,cy1,ier)
crr(4) = clog2p**2/2
elseif ( iclas2 .eq. 4 ) then
* Note that this sum does not cause problems as d2<<1
crr(4) = cli3 + cli4 - clo4*zfflog(cfact,0,czero,ier)
ipi12 = ipi12 + 1
else
call fferr(27,ier)
endif
* -#] handle transformation terms:
* -#[ sum:
crr(1) = cli1
crr(2) = - cli2
crr(6) = - crr(6)
* crr(7) = 0
* -#] sum:
endif
* #] calculations:
*###] ffcrr:
end
diff --git a/Looptools/util/ffcxr.F b/Looptools/util/ffcxr.F
--- a/Looptools/util/ffcxr.F
+++ b/Looptools/util/ffcxr.F
@@ -1,428 +1,429 @@
#include "externals.h"
+#include "types.h"
*--#[ log:
* $Id: ffcxr.f,v 1.2 1995/11/10 19:04:24 gj Exp $
* $Log: ffcxr.f,v $
c Revision 1.2 1995/11/10 19:04:24 gj
c Added nicer logging header...
c
*--#] log:
*###[ ffcxr:
subroutine ffcxr(crr,ipi12,y,y1,z,z1,dyz,ld2yzz,d2yzz,zz,zz1,
+ ldy2z,dy2z,ieps,ier)
***#[*comment:***********************************************************
* *
* calculates R as defined in appendix b: *
* *
* /1 log(x-z+i*eps) - log(y-z+i*eps) *
* r(y,z) = \ dx ----------------------------------- *
* /0 x-y *
* *
* = li2(y/(y-z)+i*eps') - li2((y-1)/(y-z)+i*eps') *
* *
* y,z are real, ieps integer denoting the sign of i*eps. *
* factors pi^2/12 are passed in the integer ipi12. *
* *
* Input: y (real) *
* y1 (real) 1-y *
* z (real) *
* z1 (real) 1-z *
* dyz (real) y-z *
* *
* ld2yzz (logical) if .TRUE. also defined are: *
* d2yzz (real) 2*y - z^+ - z^- *
* zz (real) the other z-root *
* zz1 (real) 1 - zz *
* *
* ieps (integer) if +/-1 denotes sign imaginary *
* part of argument logs *
* ieps (integer) if +/-2 denotes sign imaginary *
* part of argument dilogs *
* *
* Output crr (complex) R modulo factors pi^2/12 *
* ipi12 (integer) these factors *
* ier (intger) 0=ok, 1=num prob, 2=error *
* *
* Calls: ffxli2,(test: ffzxdl),dfflo1,zxfflg *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ipi12,ieps,ier
logical ld2yzz,ldy2z
- DOUBLE PRECISION y,y1,z,z1,dyz,d2yzz,zz,zz1,dy2z(3)
- DOUBLE COMPLEX crr(7)
+ RealType y,y1,z,z1,dyz,d2yzz,zz,zz1,dy2z(3)
+ ComplexType crr(7)
*
* local variables
*
integer i,iclas1,iclas2
- DOUBLE PRECISION fact,xx1,xx2,xx1p,xx2p,arg2,arg3,
+ RealType fact,xx1,xx2,xx1p,xx2p,arg2,arg3,
+ xli1,xli2,xli3,xlo1,xlo2,xlo3,xhill,xlog1,
+ xlog2p,xx1n,d2,d21,d2n,d21n1,term,tot,xtroep,xli4,
+ xlo4,som,xmax
- DOUBLE COMPLEX clog1p,clog2p
- DOUBLE PRECISION dfflo1
- DOUBLE COMPLEX zxfflg
+ ComplexType clog1p,clog2p
+ RealType dfflo1
+ ComplexType zxfflg
external dfflo1,zxfflg
*
* common blocks
*
#include "ff.h"
* #] declarations:
* #[ groundwork:
*
* get the arguments
*
if ( dyz .eq. 0 ) return
fact = 1/dyz
xx1 = y * fact
xx2 = - y1 * fact
*
* #] groundwork:
* #[ which area?:
*
* determine the area: 1 = [-1+xloss,1/2]
* 2 = (1/2,2-xloss]
* 3 = [2+xloss,->) U (<-,-1-xloss]
* 4 = [-1-xloss,-1+xloss]
* 5 = [2-xloss,2+xloss]
*
if ( xx1 .lt. -1-xloss/2 ) then
iclas1 = 3
xx1p = 1/xx1
elseif( xx1 .lt. -1+xloss/2 ) then
if ( ld2yzz ) then
iclas1 = 4
else
iclas1 = 1
endif
xx1p = xx1
elseif( xx1 .le. .5D0 ) then
iclas1 = 1
xx1p = xx1
elseif ( xx1 .lt. 2-xloss ) then
iclas1 = 2
xx1p = -z*fact
elseif ( ldy2z .and. xx1 .lt. 2+xloss ) then
iclas1 = 5
xx1p = dy2z(1)*fact
else
iclas1 = 3
xx1p = 1/xx1
endif
if ( xx2 .lt. -1-xloss/2 ) then
iclas2 = 3
xx2p = 1/xx2
elseif( xx2 .lt. -1+xloss/2 ) then
if ( ld2yzz ) then
iclas2 = 4
else
iclas2 = 1
endif
xx2p = xx2
elseif ( xx2 .le. .5D0 ) then
iclas2 = 1
xx2p = xx2
elseif ( xx2 .lt. 2-xloss ) then
iclas2 = 2
xx2p = z1*fact
elseif ( ldy2z .and. xx2 .lt. 2+xloss ) then
iclas2 = 5
xx2p = -dy2z(3)*fact
else
iclas2 = 3
xx2p = 1/xx2
endif
*
* throw together if they are close
*
if ( iclas1 .ne. iclas2 .and. abs(xx1-xx2) .lt. 2*xloss )
+ then
* we don't want trouble with iclasn = 4,5
if ( iclas1 .eq. 4 ) then
iclas1 = 1
elseif ( iclas1 .eq. 5 ) then
iclas1 = 3
xx1p = 1/xx1
endif
if ( iclas2 .eq. 4 ) then
iclas2 = 1
elseif ( iclas2 .eq. 5 ) then
iclas2 = 3
xx2p = 1/xx2
endif
if ( iclas1 .eq. iclas2 ) goto 5
* go on
if ( iclas1 .le. iclas2 ) then
iclas2 = iclas1
if ( iclas1 .eq. 1 ) then
xx2p = xx2
else
xx2p = z1*fact
endif
else
iclas1 = iclas2
if ( iclas1 .eq. 1 ) then
xx1p = xx1
else
xx1p = -z*fact
endif
endif
endif
* #] which area?:
* #[ calculations:
5 if ( iclas1 .eq. iclas2 .and.
+ abs(xx1p-xx2p) .lt. 2*xloss*max(abs(xx1p),abs(xx2p))
+ .and. iclas1 .ne. 5 ) then
* |----->temporary!
* Close together:
* -#[ handle dilog's:
if ( abs(xx2p) .gt. xloss ) then
*--#[ Hill identity:
*
* Use the Hill identity to get rid of the cancellations.
*
*
* first get the arguments:
*
if ( iclas1 .eq. 1 .or. iclas1 .eq. 4 ) then
d2 = 1/y
arg2 = 1/z1
arg3 = arg2/xx1p
elseif ( iclas1 .eq. 2 ) then
d2 = 1/z
arg2 = 1/y1
arg3 = arg2/xx1p
elseif ( iclas1 .eq. 3 ) then
d2 = 1/y1
arg3 = 1/z1
arg2 = arg3*xx1p
endif
call ffxli2(xli1,xlo1,d2,ier)
call ffxli2(xli2,xlo2,arg2,ier)
call ffxli2(xli3,xlo3,arg3,ier)
if ( abs(xx2p) .lt. xloss ) then
xlog2p = dfflo1(xx2p,ier)
else
- xlog2p = DBLE(zxfflg(1-xx2p,0,1D0,ier))
+ xlog2p = Re(zxfflg(1-xx2p,0,1D0,ier))
endif
xhill = xlo1*xlog2p
*--#] Hill identity:
else
*--#[ Taylor expansion:
*
* if the points are close to zero do a Taylor
* expansion of the first and last dilogarithm
*
* Li2(xx1p) - Li2(xx2p)
* = sum xx1p^i ( 1-(1-d2)^i ) /i^2
*
* with d2 = 1-xx2p/xx1p = ...
*
if ( iclas1 .eq. 1 .or. iclas1 .eq. 4 ) then
d2 = 1/y
elseif ( iclas1 .eq. 2 ) then
d2 = 1/z
elseif ( iclas1 .eq. 3 ) then
d2 = 1/y1
endif
* flag to the print section that we did a Taylor expansion
d21 = 1-d2
d21n1 = 1
xx1n = xx1p
d2n = d2
tot = xx1p*d2
* check for possible underflow on the next line
if ( abs(xx1p) .lt. xalog2 ) goto 51
do 50 i=2,20
xx1n = xx1n*xx1p
d21n1 = d21n1*d21
d2n = d2n + d2*d21n1
term = xx1n*d2n*xn2inv(i)
tot = tot + term
if ( abs(term) .le. precx*abs(tot) ) goto 51
50 continue
51 continue
xli1 = tot
xli2 = 0
xli3 = 0
xhill = 0
* for the eta+transformation section we also need
if ( iclas1 .ne. 1 ) then
if ( abs(d2) .lt. xloss ) then
xlo1 = dfflo1(d2,ier)
else
- xlo1 = DBLE(zxfflg(d21,0,1D0,ier))
+ xlo1 = Re(zxfflg(d21,0,1D0,ier))
endif
endif
if ( iclas1 .eq. 2 ) xlo2 = dfflo1(1/y1,ier)
*--#] Taylor expansion:
endif
*
* -#] handle dilog's:
* -#[ handle transformation terms:
if ( iclas1 .eq. 1 .or. iclas1 .eq. 4 ) then
*
* no transformation was made.
*
* crr(5) = 0
* crr(6) = 0
elseif ( iclas1 .eq. 2 ) then
*
* we tranformed to 1-x for both dilogs
*
if ( abs(xx1p) .lt. xloss ) then
xlog1 = dfflo1(xx1p,ier)
else
- xlog1 = DBLE(zxfflg(xx1,0,1D0,ier))
+ xlog1 = Re(zxfflg(xx1,0,1D0,ier))
endif
crr(5) = xlo1*xlog1
clog2p = zxfflg(xx2p,ieps,-y1,ier)
- crr(6) = -DBLE(xlo2)*clog2p
+ crr(6) = -Re(xlo2)*clog2p
elseif ( iclas1 .eq. 3 ) then
*
* we transformed to 1/x for both dilogs
*
clog2p = zxfflg(-xx2p,-ieps,-y1,ier)
- crr(5) = DBLE(xlo1)*(clog2p - DBLE(xlo1)/2)
+ crr(5) = Re(xlo1)*(clog2p - Re(xlo1)/2)
endif
* -#] handle transformation terms:
* -#[ add up and print out:
if ( iclas1 .eq. 1 .or. iclas1 .eq. 4 ) then
crr(1) = xli1
crr(2) = xli2
crr(3) = - xli3
crr(4) = xhill
else
crr(1) = - xli1
crr(2) = - xli2
crr(3) = xli3
crr(4) = - xhill
endif
* -#] add up and print out:
else
* Normal case:
* -#[ handle dilogs:
*
* the dilogs will not come close together so just go on
* only the special case xx1p ~ -1 needs special attention
* - and the special case xx1 ~ 2 also needs special attention
*
if ( iclas1 .eq. 4 ) then
d2 = d2yzz + zz
xmax = abs(d2yzz)
if ( abs(d2) .lt. xloss*xmax ) then
som = y + dyz
if ( abs(y).lt.xmax ) then
d2 = som
xmax = abs(y)
endif
endif
d2 = d2/dyz
fact = 1/(2-d2)
call ffxli2(xli1,xlo1,d2*fact,ier)
call ffxli2(xli3,xlo3,-d2*fact,ier)
call ffxli2(xli4,xlo4,d2,ier)
elseif ( iclas1 .eq. 5 ) then
call ffxl22(xli1,xx1p,ier)
ipi12 = ipi12 + 3
else
call ffxli2(xli1,xlo1,xx1p,ier)
endif
if ( iclas2 .eq. 4 ) then
if ( iclas1 .eq. 4 ) call fferr(26,ier)
d2 = d2yzz - zz1
xmax = abs(d2yzz)
if ( abs(d2) .lt. xloss*xmax ) then
som = dyz - y1
if ( abs(y1).lt.xmax ) then
d2 = som
xmax = abs(y1)
endif
endif
d2 = d2/dyz
fact = 1/(2-d2)
call ffxli2(xli2,xlo2,d2*fact,ier)
call ffxli2(xli3,xlo3,-d2*fact,ier)
call ffxli2(xli4,xlo4,d2,ier)
elseif ( iclas2 .eq. 5 ) then
call ffxl22(xli2,xx2p,ier)
ipi12 = ipi12 - 3
else
call ffxli2(xli2,xlo2,xx2p,ier)
endif
* -#] handle dilogs:
* -#[ handle transformation terms xx1:
*
* transformation of c1
*
if ( iclas1 .eq. 1 ) then
crr(1) = xli1
elseif( iclas1 .eq. 2 ) then
crr(1) = -xli1
ipi12 = ipi12 + 2
clog1p = zxfflg(xx1p,ieps,y,ier)
- crr(3) = - DBLE(xlo1)*clog1p
+ crr(3) = - Re(xlo1)*clog1p
elseif ( iclas1 .eq. 3 ) then
crr(1) = -xli1
ipi12 = ipi12 - 2
clog1p = zxfflg(-xx1p,-ieps,y,ier)
crr(3) = - clog1p**2/2
elseif ( iclas1 .eq. 4 ) then
crr(1) = xli1
* Note that this sum does not cause problems as d2<<1
- crr(3) = DBLE(-xli3-xli4) + DBLE(xlo4)*
+ crr(3) = Re(-xli3-xli4) + Re(xlo4)*
+ zxfflg(fact,0,0D0,ier)
ipi12 = ipi12 - 1
elseif ( iclas1 .eq. 5 ) then
crr(1) = xli1
* supply an imaginary part
clog1p = zxfflg(-1/xx1,-ieps,y,ier)
- xtroep = -DIMAG(clog1p)*DBLE(clog1p)
- crr(3) = DCMPLX(0D0,xtroep)
+ xtroep = -Im(clog1p)*Re(clog1p)
+ crr(3) = ToComplex(0D0,xtroep)
else
call fferr(26,ier)
endif
* -#] handle transformation terms xx1:
* -#[ handle transformation terms xx2:
*
* transformation of c2
*
if ( iclas2 .eq. 1 ) then
crr(2) = -xli2
elseif( iclas2 .eq. 2 ) then
crr(2) = +xli2
ipi12 = ipi12 - 2
clog2p = zxfflg(xx2p,ieps,-y1,ier)
- crr(4) = + DBLE(xlo2)*clog2p
+ crr(4) = + Re(xlo2)*clog2p
elseif ( iclas2 .eq. 3 ) then
crr(2) = +xli2
ipi12 = ipi12 + 2
clog2p = zxfflg(-xx2p,-ieps,-y1,ier)
crr(4) = clog2p**2/2
elseif ( iclas2 .eq. 4 ) then
crr(2) = -xli2
* Note that this sum does not cause problems as d2<<1
- crr(4) = DBLE(xli3+xli4) - DBLE(xlo4)*
+ crr(4) = Re(xli3+xli4) - Re(xlo4)*
+ zxfflg(fact,0,0D0,ier)
ipi12 = ipi12 + 1
elseif ( iclas2 .eq. 5 ) then
crr(2) = -xli2
* supply an imaginary part
clog2p = zxfflg(-1/xx2,-ieps,-y1,ier)
- xtroep = DIMAG(clog2p)*DBLE(clog2p)
- crr(4) = DCMPLX(0D0,xtroep)
+ xtroep = Im(clog2p)*Re(clog2p)
+ crr(4) = ToComplex(0D0,xtroep)
else
call fferr(28,ier)
endif
* -#] handle transformation terms xx2:
endif
* #] calculations:
*###] ffcxr:
end
diff --git a/Looptools/util/ffcxs3.F b/Looptools/util/ffcxs3.F
--- a/Looptools/util/ffcxs3.F
+++ b/Looptools/util/ffcxs3.F
@@ -1,653 +1,654 @@
#include "externals.h"
+#include "types.h"
*###[ ffcxs3:
subroutine ffcxs3(cs3,ipi12,y,z,dyz,d2yzz,dy2z,xpi,piDpj,ii,ns,
+ isoort,ier)
***#[*comment:***********************************************************
* *
* calculates the s3 as defined in appendix b. *
* (ip = ii+3, is1 = ii, is2 = ii+1) *
* *
* log( xk*y^2 + (-xk+xm1-xm2)*y + xm2 - i*eps ) *
* /1 - log( ... ) |y=yi *
* s3 = \ dy -------------------------------------------------- *
* /0 y - yi *
* *
* = r(yi,y-,+) + r(yi,y+,-) *
* *
* with y+- the roots of the argument of the logarithm. *
* the sign of the argument to the logarithms in r is passed *
* in ieps *
* *
* input: y(4),z(4) (real) roots in form (z-,z+,1-z-,1-z+) *
* dyz(2,2),d2yzz, (real) y() - z(), y+ - z- - z+ *
* dy2z(4) (real) y() - 2z() *
* xpi (real(ns)) p(i).p(i) (B&D metric) i=1,3 *
* m(i)^2 = si.si i=4,6 *
* ii (integer) xk = xpi(ii+3) etc *
* ns (integer) size of arrays *
* isoort (integer) returns kind of action taken *
* cs3 (complex)(20) assumed zero. *
* ccy (complex)(3) if i0 != 0: complex y *
* *
* output: cs3 (complex) mod factors pi^2/12, in array *
* ipi12 (integer) these factors *
* ier (integer) 0=ok 1=inaccurate 2=error *
* *
-* calls: ffcrr,ffcxr,real/dble,DCMPLX,log,ffadd1,ffadd2,ffadd3 *
+* calls: ffcrr,ffcxr,real/dble,ToComplex,log,ffadd1,ffadd2,ffadd3 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ipi12(2),ii,ns,isoort(2),ier
- DOUBLE COMPLEX cs3(20)
- DOUBLE PRECISION y(4),z(4),dyz(2,2),d2yzz,dy2z(4),
+ ComplexType cs3(20)
+ RealType y(4),z(4),dyz(2,2),d2yzz,dy2z(4),
+ xpi(ns),piDpj(ns,ns)
*
* local variables:
*
integer i,ip,ieps(2)
- DOUBLE PRECISION yy,yy1,zz,zz1,dyyzz,xdilog,xlog,x00(3)
+ RealType yy,yy1,zz,zz1,dyyzz,xdilog,xlog,x00(3)
logical ld2yzz
*
* common blocks
*
#include "ff.h"
*
* #] declarations:
* #[ get counters:
ip = ii+3
if ( isoort(2) .ne. 0 ) then
if ( (z(2).gt.z(1) .or. z(1).eq.z(2) .and. z(4).lt.z(3) )
+ .eqv. xpi(ip) .gt. 0 ) then
ieps(1) = +1
ieps(2) = -1
else
ieps(1) = -1
ieps(2) = +1
endif
else
if ( piDpj(ip,ii) .gt. 0 ) then
ieps(1) = +1
else
ieps(1) = -1
endif
endif
* #] get counters:
* #[ special case |z| >> |y|:
if ( xpi(ip).lt.0 .and. max(abs(y(2)),abs(y(4))) .lt.
+ xloss*min(abs(z(1)), abs(z(2)))/2 ) then
*
* we will obtain cancellations of the type Li_2(x) + Li_2(-x)
* with x small.
*
yy = dyz(2,1)/d2yzz
yy1 = dyz(2,2)/d2yzz
if ( y(2) .eq. 0 ) goto 10
zz = z(2)*yy/y(2)
zz1 = 1-zz
dyyzz = dyz(2,2)*yy/y(2)
call ffcxr(cs3(1),ipi12(1),yy,yy1,zz,zz1,dyyzz,.FALSE.,
+ 0D0,0D0,0D0,.FALSE.,x00,0,ier)
10 continue
if ( y(4) .eq. 0 ) goto 30
zz = yy*z(4)/y(4)
zz1 = 1-zz
dyyzz = -yy*dyz(2,2)/y(4)
call ffcxr(cs3(8),ipi12(2),yy,yy1,zz,zz1,dyyzz,.FALSE.,
+ 0D0,0D0,0D0,.FALSE.,x00,0,ier)
do 20 i=8,14
20 cs3(i) = -cs3(i)
30 continue
* And now the remaining Li_2(x^2) terms
call ffxli2(xdilog,xlog,(y(2)/dyz(2,1))**2,ier)
cs3(15) = +xdilog/2
call ffxli2(xdilog,xlog,(y(4)/dyz(2,1))**2,ier)
cs3(16) = -xdilog/2
goto 900
endif
* #] special case |z| >> |y|:
* #[ normal:
if ( xpi(ip) .eq. 0 ) then
ld2yzz = .FALSE.
else
ld2yzz = .TRUE.
endif
if ( isoort(1) .ne. 0 ) call ffcxr(cs3(1),ipi12(1),y(2),y(4),
+ z(1),z(3),dyz(2,1),ld2yzz,d2yzz,z(2),z(4),.TRUE.,dy2z(1),
+ ieps(1),ier)
if ( isoort(2) .ne. 0 ) then
if ( mod(isoort(2),10) .eq. 2 ) then
* both roots are equal: multiply by 2
do 60 i=1,7
- cs3(i) = 2*DBLE(cs3(i))
+ cs3(i) = 2*Re(cs3(i))
60 continue
ipi12(1) = 2*ipi12(1)
else
call ffcxr(cs3(8),ipi12(2),y(2),y(4),z(2),z(4),dyz(2,2),
+ ld2yzz,d2yzz,z(1),z(3),.TRUE.,dy2z(2),ieps(2),ier)
endif
endif
*
* #] normal:
900 continue
*###] ffcxs3:
end
*###[ ffcs3:
subroutine ffcs3(cs3,ipi12,cy,cz,cdyz,cd2yzz,cpi,cpiDpj,ii,ns,
+ isoort,ier)
***#[*comment:***********************************************************
* *
* calculates the s3 as defined in appendix b. *
* *
* log( cpi(ii+3)*y^2 + (cpi(ii+3)+cpi(ii)-cpi(ii+1))*y *
* /1 + cpi(ii+1)) - log( ... ) |y=cyi *
* s3 = \ dy ---------------------------------------------------- *
* /0 y - cyi *
* *
* = r(cyi,cy+) + r(cyi,cy-) + ( eta(-cy-,-cy+) - *
* eta(1-cy-,1-cy+) - eta(...) )*log(1-1/cyi) *
* *
* with y+- the roots of the argument of the logarithm. *
* *
* input: cy(4) (complex) cy(1)=y^-,cy(2)=y^+,cy(i+2)=1-cy(1) *
* cz(4) (complex) cz(1)=z^-,cz(2)=z^+,cz(i+2)=1-cz(1) *
* cpi(6) (complex) masses & momenta (B&D) *
* ii (integer) position of cp,cma,cmb in cpi *
* ns (integer) size of arrays *
* isoort(2)(integer) returns the kind of action taken *
* cs3 (complex)(14) assumed zero. *
* *
* output: cs3 (complex) mod factors ipi12 *
* ipi12(2) (integer) these factors *
* ier (integer) 0=ok, 1=numerical problems, 2=error *
* *
-* calls: ffcrr,DIMAG,DBLE,zfflog *
+* calls: ffcrr,Im,Re,zfflog *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ipi12(2),ii,ns,isoort(2),ier
- DOUBLE COMPLEX cs3(20),cpi(ns),cpiDpj(ns,ns)
- DOUBLE COMPLEX cy(4),cz(4),cdyz(2,2),cd2yzz
+ ComplexType cs3(20),cpi(ns),cpiDpj(ns,ns)
+ ComplexType cy(4),cz(4),cdyz(2,2),cd2yzz
*
* local variables:
*
integer i,ip,ieps(2),ieps0,ni(4),ntot
logical ld2yzz
- DOUBLE COMPLEX c,zdilog,zlog,cyy,cyy1,czz,czz1,cdyyzz
- DOUBLE PRECISION absc,y,y1,z,z1,dyz,d2yzz,zz,zz1,
+ ComplexType c,zdilog,zlog,cyy,cyy1,czz,czz1,cdyyzz
+ RealType absc,y,y1,z,z1,dyz,d2yzz,zz,zz1,
+ x00(3),sprec
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ get ieps:
ip = ii+3
call ffieps(ieps,cz(1),cpi(ip),cpiDpj(ip,ii),isoort)
* #] get ieps:
* #[ special case |cz| >> |cy|:
if ( isoort(2) .ne. 0 .and. max(absc(cy(2)),absc(cy(4))) .lt.
+ xloss*min(absc(cz(1)),absc(cz(2)))/2 ) then
*
* we will obtain cancellations of the type Li_2(x) + Li_2(-x)
* with x small.
*
cyy = cdyz(2,1)/cd2yzz
cyy1 = cdyz(2,2)/cd2yzz
if ( absc(cy(2)) .lt. xclogm ) then
- if ( DIMAG(cy(2)) .eq. 0 .and. abs(DBLE(cy(2))) .gt.
+ if ( Im(cy(2)) .eq. 0 .and. abs(Re(cy(2))) .gt.
+ xalogm ) then
- czz = cz(2)*cyy*DCMPLX(1/DBLE(cy(2)))
- cdyyzz = cyy*cdyz(2,2)*DCMPLX(1/DBLE(cy(2)))
+ czz = cz(2)*cyy*ToComplex(1/Re(cy(2)))
+ cdyyzz = cyy*cdyz(2,2)*ToComplex(1/Re(cy(2)))
elseif ( cy(2) .eq. 0 .and. cz(2) .ne. 0 .and. cyy
+ .ne. 0 ) then
* the answer IS zero
goto 30
endif
else
czz = cz(2)*cyy/cy(2)
cdyyzz = cyy*cdyz(2,2)/cy(2)
endif
czz1 = 1-czz
if ( isoort(1) .eq. -10 ) then
* no eta terms.
ieps0 = 99
else
* do not know the im part
ieps0 = 0
endif
call ffcrr(cs3(1),ipi12(1),cyy,cyy1,czz,czz1,cdyyzz,.FALSE.,
+ czero,czero,czero,-1,ieps0,ier)
30 continue
if ( absc(cy(4)) .lt. xclogm ) then
- if ( DIMAG(cy(4)) .eq. 0 .and. abs(DBLE(cy(4))) .gt.
+ if ( Im(cy(4)) .eq. 0 .and. abs(Re(cy(4))) .gt.
+ xalogm ) then
- czz = cz(4)*cyy*DCMPLX(1/DBLE(cy(4)))
- cdyyzz = -cyy*cdyz(2,2)*DCMPLX(1/DBLE(cy(4)))
+ czz = cz(4)*cyy*ToComplex(1/Re(cy(4)))
+ cdyyzz = -cyy*cdyz(2,2)*ToComplex(1/Re(cy(4)))
elseif ( cy(4) .eq. 0 .and. cz(4) .ne. 0 .and. cyy
+ .ne. 0 ) then
* the answer IS zero
goto 50
endif
else
czz = cz(4)*cyy/cy(4)
cdyyzz = -cyy*cdyz(2,2)/cy(4)
endif
czz1 = 1-czz
call ffcrr(cs3(8),ipi12(2),cyy,cyy1,czz,czz1,cdyyzz,.FALSE.,
+ czero,czero,czero,-1,ieps0,ier)
do 40 i=8,14
cs3(i) = -cs3(i)
40 continue
50 continue
*
* And now the remaining Li_2(x^2) terms
* stupid Gould NP1
*
c = cy(2)*cy(2)/(cdyz(2,1)*cdyz(2,1))
call ffzli2(zdilog,zlog,c,ier)
cs3(15) = +zdilog/2
* stupid Gould NP1
c = cy(4)*cy(4)/(cdyz(2,1)*cdyz(2,1))
call ffzli2(zdilog,zlog,c,ier)
cs3(16) = -zdilog/2
goto 900
endif
* #] special case |cz| >> |cy|:
* #[ normal:
if ( isoort(2) .eq. 0 ) then
ld2yzz = .FALSE.
else
ld2yzz = .TRUE.
endif
if ( isoort(1) .eq. 0 ) then
* do nothing
elseif ( mod(isoort(1),10).eq.0 .or. mod(isoort(1),10).eq.-1
+ .or. mod(isoort(1),10).eq.-3 ) then
call ffcrr(cs3(1),ipi12(1),cy(2),cy(4),cz(1),cz(3),
+ cdyz(2,1),ld2yzz,cd2yzz,cz(2),cz(4),isoort(1),
+ ieps(1),ier)
elseif ( mod(isoort(1),10) .eq. -5 .or. mod(isoort(1),10) .eq.
+ -6 ) then
- y = DBLE(cy(2))
- y1 = DBLE(cy(4))
- z = DBLE(cz(1))
- z1 = DBLE(cz(3))
- dyz = DBLE(cdyz(2,1))
- d2yzz = DBLE(cd2yzz)
- zz = DBLE(cz(2))
- zz1 = DBLE(cz(4))
+ y = Re(cy(2))
+ y1 = Re(cy(4))
+ z = Re(cz(1))
+ z1 = Re(cz(3))
+ dyz = Re(cdyz(2,1))
+ d2yzz = Re(cd2yzz)
+ zz = Re(cz(2))
+ zz1 = Re(cz(4))
sprec = precx
precx = precc
call ffcxr(cs3(1),ipi12(1),y,y1,z,z1,dyz,ld2yzz,d2yzz,zz,zz1
+ ,.FALSE.,x00,ieps(1),ier)
precx = sprec
else
call fferr(12,ier)
endif
if ( isoort(2) .eq. 0 ) then
* do nothing
elseif ( mod(isoort(2),5) .eq. 0 ) then
do 100 i=1,7
- 100 cs3(i) = 2*DBLE(cs3(i))
+ 100 cs3(i) = 2*Re(cs3(i))
ipi12(1) = 2*ipi12(1)
elseif ( mod(isoort(2),10).eq.-1 .or. mod(isoort(1),10).eq.-3 )
+ then
call ffcrr(cs3(8),ipi12(2),cy(2),cy(4),cz(2),cz(4),
+ cdyz(2,2),ld2yzz,cd2yzz,cz(1),cz(3),isoort(2),
+ ieps(2),ier)
elseif ( mod(isoort(2),10) .eq. -6 ) then
- y = DBLE(cy(2))
- y1 = DBLE(cy(4))
- z = DBLE(cz(2))
- z1 = DBLE(cz(4))
- dyz = DBLE(cdyz(2,2))
- d2yzz = DBLE(cd2yzz)
- zz = DBLE(cz(1))
- zz1 = DBLE(cz(3))
+ y = Re(cy(2))
+ y1 = Re(cy(4))
+ z = Re(cz(2))
+ z1 = Re(cz(4))
+ dyz = Re(cdyz(2,2))
+ d2yzz = Re(cd2yzz)
+ zz = Re(cz(1))
+ zz1 = Re(cz(3))
sprec = precx
precx = precc
call ffcxr(cs3(8),ipi12(2),y,y1,z,z1,dyz,ld2yzz,d2yzz,zz,zz1
+ ,.FALSE.,x00,ieps(2),ier)
precx = sprec
else
call fferr(13,ier)
endif
* #] normal:
* #[ eta's:
if ( mod(isoort(1),10).eq.-5 .or. mod(isoort(1),10).eq.-6 )
+ then
if ( mod(isoort(2),10).ne.-5 .and. mod(isoort(1),10).ne.-6
+ ) then
print *,'ffcxs3: error: I assumed both would be real!'
ier = ier + 50
endif
* we called ffcxr - no eta's
- elseif ( DIMAG(cpi(ip)).eq.0 ) then
+ elseif ( Im(cpi(ip)).eq.0 ) then
call ffgeta(ni,cz(1),cdyz(1,1),
+ cpi(ip),cpiDpj(ii,ip),ieps,isoort,ier)
ntot = ni(1) + ni(2) + ni(3) + ni(4)
if ( ntot .ne. 0 ) call ffclgy(cs3(15),ipi12(2),ntot,
+ cy(1),cz(1),cd2yzz,ier)
else
*
* cpi(ip) is really complex (occurs in transformed
* 4pointfunction)
*
print *,'THIS PART IS NOT READY ',
+ 'and should not be reached'
- stop
+c stop
endif
* #] eta's:
900 continue
*###] ffcs3:
end
*###[ ffclgy:
subroutine ffclgy(cs3,ipi12,ntot,cy,cz,cd2yzz,ier)
***#[*comment:***********************************************************
* *
* calculates the the difference of two S's with cy(3,4),cz(3,4), *
* cy(4)cz(3)-cy(3)cz(4) given. Note the difference with ffdcs4, *
* in which the cy's are the same and only the cz's different. *
* Here both can be different. Also we skip an intermediat *
* level. *
* *
* input: cy(4) (complex) cy,1-cy in S with s3,s4 *
* cz(4) (complex) cz,1-cz in S with s3,s4 *
* cdyz(2,2) (complex) cy - cz *
* cd2yzz (complex) 2*cy - cz+ - cz- *
* cdyzzy(4) (complex) cy(i,4)*cz(i,4)-cy(i,3)*cz(i,4) *
* cpiDpj(6,6) (complex) usual *
* cs3 (complex) assumed zero. *
* *
* output: cs3 (complex) mod factors pi^2/12, in array *
* ipi12 (integer) these factors *
* isoort (integer) returns kind of action taken *
* ier (integer) number of digits lost *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE COMPLEX cs3
- DOUBLE COMPLEX cy(4),cz(4),cd2yzz
+ ComplexType cs3
+ ComplexType cy(4),cz(4),cd2yzz
integer ipi12,ntot,ier
*
* local variables
*
integer ipi
- DOUBLE COMPLEX c,cc,clogy,c2y1,zfflog,zfflo1,csum
- DOUBLE PRECISION absc
+ ComplexType c,cc,clogy,c2y1,zfflog,zfflo1,csum
+ RealType absc
external zfflog,zfflo1
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ calculations:
ipi = 0
if ( 1 .lt. xloss*absc(cy(2)) ) then
clogy = zfflo1(1/cy(2),ier)
else
if ( absc(cy(2)) .lt. xclogm .or. absc(cy(4)) .lt. xclogm )
+ then
if ( ntot .ne. 0 ) call fferr(15,ier)
clogy = 0
else
c = -cy(4)/cy(2)
- if ( DBLE(c) .gt. -abs(DIMAG(c)) ) then
+ if ( Re(c) .gt. -abs(Im(c)) ) then
clogy = zfflog(c,0,czero,ier)
else
* take out the factor 2*pi^2
cc = c+1
if ( absc(cc) .lt. xloss ) then
c2y1 = -cd2yzz - cz(1) + cz(4)
if ( absc(c2y1) .lt. xloss*max(absc(cz(1)),
+ absc(cz(4))) ) then
c2y1 = -cd2yzz - cz(2) + cz(3)
endif
csum = -c2y1/cy(2)
clogy = zfflo1(csum,ier)
else
csum = 0
clogy = zfflog(-c,0,czero,ier)
endif
- if ( DIMAG(c) .lt. -precc*absc(c) .or.
- + DIMAG(csum) .lt. -precc*absc(csum) ) then
+ if ( Im(c) .lt. -precc*absc(c) .or.
+ + Im(csum) .lt. -precc*absc(csum) ) then
ipi = -1
- elseif ( DIMAG(c) .gt. precc*absc(c) .or.
- + DIMAG(csum) .gt. precc*absc(csum) ) then
+ elseif ( Im(c) .gt. precc*absc(c) .or.
+ + Im(csum) .gt. precc*absc(csum) ) then
ipi = +1
else
call fferr(51,ier)
ipi = 0
endif
endif
endif
endif
cs3 = cs3 + ntot*c2ipi*clogy
if ( ipi .ne. 0 ) then
ipi12 = ipi12 - 24*ntot*ipi
endif
* #] calculations:
*###] ffclgy:
end
*###[ ffieps:
subroutine ffieps(ieps,cz,cp,cpDs,isoort)
***#[*comment:***********************************************************
* *
* Get the ieps prescription in such a way that it is compatible *
* with the imaginary part of cz if non-zero, compatible with the *
* real case if zero. *
* *
* Input: cz complex(4) the roots z-,z+,1-z-,1-z+ *
* cp complex p^2 *
* cpDs complex p.s *
* isoort integer(2) which type of Ri *
* *
* Output: ieps integer(2) z -> z-ieps*i*epsilon *
* will give correct im part *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ieps(2),isoort(2)
- DOUBLE COMPLEX cp,cpDs,cz(4)
+ ComplexType cp,cpDs,cz(4)
*
* #] declarations:
* #[ work:
- if ( DIMAG(cp) .ne. 0 ) then
+ if ( Im(cp) .ne. 0 ) then
* do not calculate ANY eta terms, we'll do them ourselves.
ieps(1) = 99
ieps(2) = 99
elseif ( isoort(2) .ne. 0 ) then
- if ( DIMAG(cz(1)) .lt. 0 ) then
+ if ( Im(cz(1)) .lt. 0 ) then
ieps(1) = +1
- if ( DIMAG(cz(2)) .lt. 0 ) then
+ if ( Im(cz(2)) .lt. 0 ) then
ieps(2) = +1
else
ieps(2) = -1
endif
- elseif ( DIMAG(cz(1)) .gt. 0 ) then
+ elseif ( Im(cz(1)) .gt. 0 ) then
ieps(1) = -1
- if ( DIMAG(cz(2)) .le. 0 ) then
+ if ( Im(cz(2)) .le. 0 ) then
ieps(2) = +1
else
ieps(2) = -1
endif
else
- if ( DIMAG(cz(2)) .lt. 0 ) then
+ if ( Im(cz(2)) .lt. 0 ) then
ieps(1) = -1
ieps(2) = +1
- elseif ( DIMAG(cz(2)) .gt. 0 ) then
+ elseif ( Im(cz(2)) .gt. 0 ) then
ieps(1) = +1
ieps(2) = -1
else
- if ( (DBLE(cz(2)).gt.DBLE(cz(1))
- + .or. (DBLE(cz(1)).eq.DBLE(cz(2))
- + .and. DBLE(cz(4)).lt.DBLE(cz(3)))
- + ) .eqv. DBLE(cp).gt.0 ) then
+ if ( (Re(cz(2)).gt.Re(cz(1))
+ + .or. (Re(cz(1)).eq.Re(cz(2))
+ + .and. Re(cz(4)).lt.Re(cz(3)))
+ + ) .eqv. Re(cp).gt.0 ) then
ieps(1) = +1
ieps(2) = -1
else
ieps(1) = -1
ieps(2) = +1
endif
endif
endif
else
- if ( DIMAG(cz(1)) .lt. 0 ) then
+ if ( Im(cz(1)) .lt. 0 ) then
ieps(1) = +1
- elseif ( DIMAG(cz(1)) .gt. 0 ) then
+ elseif ( Im(cz(1)) .gt. 0 ) then
ieps(1) = -1
- elseif ( DBLE(cpDs) .gt. 0 ) then
+ elseif ( Re(cpDs) .gt. 0 ) then
ieps(1) = +1
else
ieps(1) = -1
endif
ieps(2) = -9999
endif
* #] work:
*###] ffieps:
end
*###[ ffgeta:
subroutine ffgeta(ni,cz,cdyz,cp,cpDs,ieps,isoort,ier)
***#[*comment:***********************************************************
* *
* Get the eta terms which arise from splitting up *
* log(p2(x-z-)(x-z+)) - log(p2(y-z-)(y-z+)) *
* *
* Input: cz complex(4) the roots z-,z+,1-z-,1-z+ *
* cdyz complex(2,2) y-z *
* cd2yzz complex(2) 2y-(z-)-(z+) *
* cp complex p^2 *
* cpDs complex p.s *
* ieps integer(2) the assumed im part if Im(z)=0 *
* isoort integer(2) which type of Ri *
* *
* Output: ni integer(4) eta()/(2*pi*i) *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ni(4),ieps(2),isoort(2),ier
- DOUBLE COMPLEX cp,cpDs,cz(4),cdyz(2,2)
+ ComplexType cp,cpDs,cz(4),cdyz(2,2)
*
* local variables
*
integer i,nffeta,nffet1
- DOUBLE COMPLEX cmip
+ ComplexType cmip
external nffeta,nffet1
*
* common
*
#include "ff.h"
*
* #] declarations:
* #[ complex masses or imaginary roots:
*
* only complex because of complex roots in y or z
* [checked and in agreement with ieps definition 23-sep-1991]
*
* isoort = +1: y is real, z is real
* isoort = -1-n*10: y is complex, possibly z as well
* isoort = -3-n*10: y,z complex, (y-z-)*(y-z+) real
* isoort = 0: y is complex, one z root only
* isoort = -10-n*10: y is real, z is complex
* isoort = -5,6-n*10: y,z real
*
if ( isoort(1) .gt. 0 ) then
*
* really a real case
*
ni(1) = 0
ni(2) = 0
ni(3) = 0
ni(4) = 0
elseif ( mod(isoort(1),10) .ne. 0 .and. isoort(2) .ne. 0 ) then
- cmip = DCMPLX(0D0,-DBLE(cp))
+ cmip = ToComplex(0D0,-Re(cp))
*
* ni(1) = eta(p2,(x-z-)(x-z+)) = 0 by definition (see ni(3))
* ni(2) = eta(x-z-,x-z+)
*
ni(1) = 0
if ( ieps(1) .gt. 0 .neqv. ieps(2) .gt. 0 ) then
ni(2) = 0
else
ni(2) = nffet1(-cz(1),-cz(2),cmip,ier)
if ( cz(3).ne.0 .and. cz(4).ne.0 ) then
i = nffet1(cz(3),cz(4),cmip,ier)
if ( i .ne. ni(2) ) call fferr(53,ier)
endif
endif
*
* ni(3) compensates for whatever convention we chose in ni(1)
* ni(4) = -eta(y-z-,y-z+)
*
if ( mod(isoort(1),10).eq.-3 ) then
* follow the i*epsilon prescription as (y-z-)(y-z+) real
ni(3) = 0
ni(4) = -nffet1(cdyz(2,1),cdyz(2,2),cmip,ier)
else
- if ( DBLE(cp) .lt. 0 .and. DIMAG(cdyz(2,1)*
+ if ( Re(cp) .lt. 0 .and. Im(cdyz(2,1)*
+ cdyz(2,2)) .lt. 0 ) then
ni(3) = -1
else
ni(3) = 0
endif
ni(4) = -nffeta(cdyz(2,1),cdyz(2,2),ier)
endif
elseif ( (mod(isoort(1),10).eq.-1 .or. mod(isoort(1),10).eq.-3)
+ .and. isoort(2) .eq. 0 ) then
ni(1) = 0
- if ( DIMAG(cz(1)) .ne. 0 ) then
- ni(2) = nffet1(-cpDs,-cz(1),DCMPLX(DBLE(0),
- + DBLE(-1)),ier)
+ if ( Im(cz(1)) .ne. 0 ) then
+ ni(2) = nffet1(-cpDs,-cz(1),ToComplex(Re(0),
+ + Re(-1)),ier)
else
- ni(2) = nffet1(-cpDs,DCMPLX(DBLE(0),DBLE(1)),
- + DCMPLX(DBLE(0),DBLE(-1)),ier)
+ ni(2) = nffet1(-cpDs,ToComplex(Re(0),Re(1)),
+ + ToComplex(Re(0),Re(-1)),ier)
endif
ni(3) = 0
ni(4) = -nffeta(-cpDs,cdyz(2,1),ier)
else
ni(1) = 0
ni(2) = 0
ni(3) = 0
ni(4) = 0
endif
* #] complex masses or imaginary roots:
*###] ffgeta:
end
diff --git a/Looptools/util/ffcxs4.F b/Looptools/util/ffcxs4.F
--- a/Looptools/util/ffcxs4.F
+++ b/Looptools/util/ffcxs4.F
@@ -1,777 +1,778 @@
#include "externals.h"
+#include "types.h"
* $Id: ffcxs4.f,v 1.3 1995/10/17 06:55:09 gj Exp $
* $Log: ffcxs4.f,v $
c Revision 1.3 1995/10/17 06:55:09 gj
c Fixed ieps error in ffdcrr (ffcxs4.f), added real case in ffcrr, debugging
c info in ffxd0, and warned against remaining errors for del2=0 in ffrot4
c (ffxd0h.f)
c
c Revision 1.2 1995/10/06 09:17:22 gj
c Found stupid typo in ffxc0p which caused the result to be off by pi^2/3 in
c some equal-mass cases. Added checks to ffcxs4.f ffcrr.f.
c
*###[ ffcxs4:
subroutine ffcxs4(cs3,ipi12,w,y,z,dwy,dwz,dyz,d2yww,d2yzz,
+ xpi,piDpj,ii,ns,isoort,ier)
***#[*comment:***********************************************************
* *
* Calculate the 8 Spence functions = 4 R's = 2 dR's *
* *
* *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ipi12(4),ii,ns,isoort(4),ier
- DOUBLE COMPLEX cs3(40)
- DOUBLE PRECISION w(4),y(4),z(4),dwy(2,2),dwz(2,2),dyz(2,2),
+ ComplexType cs3(40)
+ RealType w(4),y(4),z(4),dwy(2,2),dwz(2,2),dyz(2,2),
+ d2yww,d2yzz,xpi(ns),piDpj(ns,ns),x00(3)
*
* local variables:
*
integer iepz(2),iepw(2)
logical ld2yzz,ld2yww
*
* common blocks
*
#include "ff.h"
* #] declarations:
* #[ groundwork:
if ( isoort(2) .eq. 0 ) then
ld2yzz = .FALSE.
else
ld2yzz = .TRUE.
endif
if ( isoort(4) .eq. 0 ) then
ld2yww = .FALSE.
else
ld2yww = .TRUE.
endif
if ( isoort(2) .ne. 0 ) then
if ( z(2) .gt. z(1) .eqv. xpi(ii+3) .gt. 0 ) then
iepz(1) = +1
iepz(2) = -1
else
iepz(1) = -1
iepz(2) = +1
endif
else
print *,'ffcxs4: error: untested algorithm'
if ( piDpj(ii,ii+3) .gt. 0 ) then
iepz(1) = +1
else
iepz(1) = -1
endif
endif
if ( isoort(4) .ne. 0 ) then
if ( w(2) .gt. w(1) .eqv. xpi(5) .gt. 0 ) then
iepw(1) = 1
iepw(2) = -1
else
iepw(1) = -1
iepw(2) = 1
endif
else
print *,'ffcxs4: error: untested algorithm'
if ( piDpj(2,5) .gt. 0 ) then
iepw(1) = +1
else
iepw(1) = -1
endif
endif
* #] groundwork:
* #[ zm and wp:
if ( isoort(4) .eq. 0 ) then
call ffcxr(cs3(1),ipi12(1),y(2),y(4),z(1),z(3),dyz(2,1),
+ ld2yzz,d2yzz,z(2),z(4),.FALSE.,x00,iepz(1),ier)
else
if ( .not. ( dwz(2,1).eq.0 .and. iepz(1).eq.iepw(2) ) )
+ call ffdcxr(cs3( 1),ipi12(1),y(2),y(4),z(1),z(3),
+ z(2),z(4),d2yzz,w(2),w(4),w(1),w(3),d2yww,
+ dyz(2,1),dwy(2,2),dwz(2,1),iepz(1),iepw(2),ier)
endif
* #] zm and wp:
* #[ zp and wm:
if ( isoort(2) .eq. 0 ) then
call ffcxr(cs3(1),ipi12(1),y(2),y(4),w(1),w(3),-dwy(1,2),
+ ld2yww,d2yww,w(2),w(4),.FALSE.,x00,iepw(1),ier)
else
if ( .not. ( dwz(1,2).eq.0 .and. iepz(2).eq.iepw(1) ) )
+ call ffdcxr(cs3(21),ipi12(3),y(2),y(4),z(2),z(4),
+ z(1),z(3),d2yzz,w(1),w(3),w(2),w(4),d2yww,
+ dyz(2,2),dwy(1,2),dwz(1,2),iepz(2),iepw(1),ier)
endif
* #] zp and wm:
*###] ffcxs4:
end
*###[ ffcs4:
subroutine ffcs4(cs3,ipi12,cw,cy,cz,cdwy,cdwz,cdyz,cd2yww,cd2yzz
+ ,cpi,cpiDpj,cp2p,ii,ns,isoort,ier)
***#[*comment:***********************************************************
* *
* Calculate the 8 Spence functions = 4 R's = 2 dR's *
* *
* *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ipi12(4),ii,ns,isoort(4),ier
- DOUBLE COMPLEX cs3(40)
- DOUBLE COMPLEX cw(4),cy(4),cz(4),cdwy(2,2),cdwz(2,2),cdyz(2,2)
- DOUBLE COMPLEX cd2yww,cd2yzz,cpi(ns),cp2p,cpiDpj(ns,ns)
+ ComplexType cs3(40)
+ ComplexType cw(4),cy(4),cz(4),cdwy(2,2),cdwz(2,2),cdyz(2,2)
+ ComplexType cd2yww,cd2yzz,cpi(ns),cp2p,cpiDpj(ns,ns)
*
* local variables:
*
logical ld2yzz,ld2yww
integer i,j,ip,iepz(2),iepw(2),nz(4),nw(4),ntot,i2pi
- DOUBLE COMPLEX c,cc,clogy,c2y1,cdyw(2,2)
- DOUBLE COMPLEX zfflo1,zfflog
- DOUBLE PRECISION absc
+ ComplexType c,cc,clogy,c2y1,cdyw(2,2)
+ ComplexType zfflo1,zfflog
+ RealType absc
external zfflo1,zfflog
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ get counters:
ip = ii+3
if ( isoort(2) .eq. 0 ) then
ld2yzz = .FALSE.
else
ld2yzz = .TRUE.
endif
if ( isoort(4) .eq. 0 ) then
ld2yww = .FALSE.
else
ld2yww = .TRUE.
endif
call ffieps(iepz,cz,cpi(ip),cpiDpj(ip,ii),isoort)
call ffieps(iepw,cw,cp2p,cpiDpj(ip,ii),isoort(3))
if ( isoort(4) .eq. 0 ) then
print *,'ffcs4: error: case not implemented'
ier = ier + 50
endif
* #] get counters:
* #[ R's:
if ( isoort(4) .eq. 0 ) then
call ffcrr(cs3(1),ipi12(1),cy(2),cy(4),cz(1),cz(3),cdyz(2,1)
+ ,ld2yzz,cd2yzz,cz(2),cz(4),isoort(4),iepz(1),ier)
else
if ( .not. ( cdwz(2,1).eq.0 .and. iepz(1).eq.iepw(2) ) )
+ call ffdcrr(cs3( 1),ipi12(1),cy(2),cy(4),cz(1),cz(3),cz(2),
+ cz(4),cd2yzz,cw(2),cw(4),cw(1),cw(3),cd2yww,cdyz(2,1),
+ cdwy(2,2),cdwz(2,1),isoort(4),iepz(1),iepw(2),ier)
endif
if ( isoort(2) .eq. 0 ) then
call ffcrr(cs3(1),ipi12(1),cy(2),cy(4),cw(1),cw(3),-cdwy(1,2
+ ),ld2yww,cd2yww,cw(2),cw(4),isoort(2),iepw(1),ier)
else
if ( .not. ( cdwz(1,2).eq.0 .and. iepz(2).eq.iepw(1) ) )
+ call ffdcrr(cs3(21),ipi12(3),cy(2),cy(4),cz(2),cz(4),cz(1),
+ cz(3),cd2yzz,cw(1),cw(3),cw(2),cw(4),cd2yww,cdyz(2,2),
+ cdwy(1,2),cdwz(1,2),iepz(2),isoort(2),iepw(1),ier)
endif
* #] R's:
* #[ eta's:
- if ( DIMAG(cpi(ip)) .eq. 0 ) then
+ if ( Im(cpi(ip)) .eq. 0 ) then
call ffgeta(nz,cz,cdyz,
+ cpi(ip),cpiDpj(ii,ip),iepz,isoort,ier)
do 120 i=1,2
do 110 j=1,2
cdyw(i,j) = cdwy(j,i)
110 continue
120 continue
call ffgeta(nw,cw,cdyw,
+ cp2p,cpiDpj(ii,ip),iepw,isoort(3),ier)
else
print *,'ffcs4: error: not ready for complex D0 yet'
endif
ntot = nz(1)+nz(2)+nz(3)+nz(4)-nw(1)-nw(2)-nw(3)-nw(4)
if ( ntot .ne. 0 ) then
i2pi = 0
if ( 1/absc(cy(2)) .lt. xloss ) then
clogy = zfflo1(1/cy(2),ier)
else
c = -cy(4)/cy(2)
- if ( DBLE(c) .gt. -abs(DIMAG(c)) ) then
+ if ( Re(c) .gt. -abs(Im(c)) ) then
clogy = zfflog(c,0,czero,ier)
else
* take out the factor 2*pi^2
cc = c+1
if ( absc(cc) .lt. xloss ) then
c2y1 = -cd2yzz - cz(1) + cz(4)
if ( absc(c2y1) .lt. xloss*max(absc(cz(1)),
+ absc(cz(4))) ) then
c2y1 = -cd2yzz - cz(2) + cz(3)
endif
clogy = zfflo1(-c2y1/cy(2),ier)
else
clogy = zfflog(-c,0,czero,ier)
endif
- if ( DIMAG(c) .lt. 0 ) then
+ if ( Im(c) .lt. 0 ) then
i2pi = -1
- elseif ( DIMAG(c) .gt. 0 ) then
+ elseif ( Im(c) .gt. 0 ) then
i2pi = +1
else
call fferr(51,ier)
i2pi = 0
endif
ipi12(2) = ipi12(2) - ntot*24*i2pi
endif
endif
if ( cs3(40) .ne. 0 ) print *,'ffcs4: error: cs3(40) != 0'
cs3(40) = ntot*c2ipi*clogy
endif
* #] eta's:
*###] ffcs4:
end
*###[ ffdcxr:
subroutine ffdcxr(cs3,ipi12,y,y1,z,z1,zp,zp1,d2yzz,
+ w,w1,wp,wp1,d2yww,dyz,dwy,dwz,iepsz,iepsw,ier)
***#[*comment:***********************************************************
* *
* Calculate *
* *
* R(y,z,iepsz) - R(y,w,iepsw) *
* *
* Input: *
* a = [yzw] (real) see definition *
* a1 = 1 - a (real) *
* dab = a - b (real) *
* ieps[zw] (integer) sign of imaginary part *
* of argument logarithm *
* cs3(20) (complex) assumed zero *
* *
* Output: *
* cs3(20) (complex) the results, not added *
* ipi12(2) (integer) factors pi^2/12 *
* *
* Calls: ffcxr *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ipi12(2),iepsz,iepsw,ier
- DOUBLE COMPLEX cs3(20)
- DOUBLE PRECISION y,z,w,y1,z1,w1,dyz,dwy,dwz,zp,zp1,d2yzz,wp,wp1,
+ ComplexType cs3(20)
+ RealType y,z,w,y1,z1,w1,dyz,dwy,dwz,zp,zp1,d2yzz,wp,wp1,
+ d2yww
*
* local variables:
*
integer i,ieps
logical again
- DOUBLE PRECISION yy,yy1,zz,zz1,dyyzz,xx1,xx1n,term,tot,d2,d3,
+ RealType yy,yy1,zz,zz1,dyyzz,xx1,xx1n,term,tot,d2,d3,
+ d21,d31,d2n,d3n,d21n1,d31n1,dw,x00(3)
- DOUBLE COMPLEX chulp
- DOUBLE PRECISION dfflo1
+ ComplexType chulp
+ RealType dfflo1
external dfflo1
*
* common blocks
*
#include "ff.h"
* #] declarations:
* #[ groundwork:
if ( dwz .eq. 0 .and. iepsz .eq. iepsw ) return
if ( dyz .eq. 0 ) then
call fferr(75,ier)
return
endif
xx1 = y/dyz
dw = dwz/dyz
if ( xx1 .le. .5D0 .or. xx1 .gt. 2 ) then
d2 = 1/y
dw = dw*y/w
else
d2 = 1/z1
endif
again = .FALSE.
123 continue
* #] groundwork:
* #[ trivial case:
if ( dw .eq. 0 ) then
* #] trivial case:
* #[ normal case:
elseif ( abs(dw) .gt. xloss .or. again ) then
* nothing's the matter
call ffcxr(cs3( 1),ipi12(1),y,y1,z,z1,dyz,
+ .TRUE.,d2yzz,zp,zp1,.FALSE.,x00,iepsz,ier)
call ffcxr(cs3(11),ipi12(2),y,y1,w,w1,-dwy,
+ .TRUE.,d2yww,wp,wp1,.FALSE.,x00,iepsw,ier)
do 10 i=11,20
10 cs3(i) = -cs3(i)
ipi12(2) = -ipi12(2)
* #] normal case:
* #[ only cancellations in w, not in y:
elseif ( abs(d2) .gt. xloss ) then
* there are no cancellations the other way:
if ( iepsz .ne. iepsw .and. ( y/dyz .gt. 1 .or.-y/dwy .gt.
+ 1 ) ) then
again = .TRUE.
goto 123
endif
yy = dwy/dwz
zz = yy*z/y
yy1 = dyz/dwz
zz1 = yy1*w/y
dyyzz = yy*dyz/y
if ( y .lt. 0 ) then
ieps = iepsz
else
ieps = -iepsz
endif
call ffcxr(cs3( 1),ipi12(1),yy,yy1,zz,zz1,dyyzz,.FALSE.,
+ 0D0,0D0,0D0,.FALSE.,x00,2*ieps,ier)
zz = yy*z1/y1
zz1 = yy1*w1/y1
dyyzz = -yy*dyz/y1
if ( y1 .gt. 0 ) then
ieps = iepsz
else
ieps = -iepsz
endif
call ffcxr(cs3(11),ipi12(2),yy,yy1,zz,zz1,dyyzz,.FALSE.,
+ 0D0,0D0,0D0,.FALSE.,x00,2*ieps,ier)
do 20 i=11,20
cs3(i) = -cs3(i)
20 continue
ipi12(2) = -ipi12(2)
* #] only cancellations in w, not in y:
* #[ Hill identity:
elseif ( ( 1 .gt. xloss*abs(y) .or. abs(xx1) .gt. xloss )
+ .and. ( 1 .gt. xloss*abs(z) .or. abs(z/dyz) .gt. xloss )
+ .and. ( 1 .gt. xloss*abs(y) .or. abs(dyz/y) .gt. xloss )
+ ) then
* do a Hill identity on the y,y-1 direction
yy = -y*w1/dwy
yy1 = w*y1/dwy
zz = -z*w1/dwz
zz1 = w*z1/dwz
dyyzz = -w*w1*(dyz/(dwy*dwz))
if ( y*dwz .gt. 0 .eqv. (y+dwz) .gt. 0 ) then
ieps = 2*iepsw
else
ieps = -2*iepsw
endif
call ffcxr(cs3( 1),ipi12(1),yy,yy1,zz,zz1,dyyzz,.FALSE.,
+ 0D0,0D0,0D0,.FALSE.,x00,ieps,ier)
yy = w1
yy1 = w
zz = -w1*z/dwz
zz1 = w*z1/dwz
dyyzz = w*w1/dwz
call ffcxr(cs3( 9),ipi12(2),yy,yy1,zz,zz1,dyyzz,.FALSE.,
+ 0D0,0D0,0D0,.FALSE.,x00,ieps,ier)
do 30 i=9,16
30 cs3(i) = -cs3(i)
ipi12(2) = -ipi12(2)
* the extra logarithms ...
if ( 1 .lt. xloss*abs(w) ) then
chulp = dfflo1(1/w,ier)
elseif ( w1 .lt. 0 .or. w .lt. 0 ) then
chulp = log(-w1/w)
else
- chulp = DCMPLX(DBLE(log(w1/w)),DBLE(-iepsw*pi))
+ chulp = ToComplex(Re(log(w1/w)),Re(-iepsw*pi))
endif
- cs3(20) = -DBLE(dfflo1(dwz/dwy,ier))*chulp
+ cs3(20) = -Re(dfflo1(dwz/dwy,ier))*chulp
* #] Hill identity:
* #[ Taylor expansion:
elseif ( (w.lt.0..or.w1.lt.0) .and. (z.lt.0..or.z1.lt.0) ) then
* do a Taylor expansion
if ( abs(xx1) .lt. xloss ) then
d3 = dwz/dwy
xx1n = xx1
d2n = d2
d3n = d3
d21 = 1-d2
d21n1 = 1
d31 = 1-d3
d31n1 = 1
tot = xx1*d2*d3
do 50 i=2,20
xx1n = xx1n*xx1
d21n1 = d21n1*d21
d31n1 = d31n1*d31
d2n = d2n + d2*d21n1
d3n = d3n + d3*d31n1
term = xx1n*d2n*d3n*xn2inv(i)
tot = tot + term
if ( abs(term) .le. precx*abs(tot) ) goto 51
50 continue
51 continue
cs3(1) = tot
elseif ( abs(z/dyz) .lt. xloss ) then
call ffcxr(cs3( 1),ipi12(1),y,y1,z,z1,dyz,
+ .TRUE.,d2yzz,zp,zp1,.FALSE.,x00,iepsz,ier)
call ffcxr(cs3(11),ipi12(2),y,y1,w,w1,-dwy,
+ .TRUE.,d2yww,wp,wp1,.FALSE.,x00,iepsw,ier)
do 110 i=11,20
110 cs3(i) = -cs3(i)
else
call fferr(22,ier)
return
endif
else
call ffcxr(cs3( 1),ipi12(1),y,y1,z,z1,dyz,.FALSE.,
+ 0D0,0D0,0D0,.FALSE.,x00,iepsz,ier)
call ffcxr(cs3(11),ipi12(2),y,y1,w,w1,-dwy,.FALSE.,
+ 0D0,0D0,0D0,.FALSE.,x00,iepsw,ier)
do 40 i=11,20
40 cs3(i) = -cs3(i)
ipi12(2) = -ipi12(2)
endif
* #] Taylor expansion:
*###] ffdcxr:
end
*###[ ffdcrr:
subroutine ffdcrr(cs3,ipi12,cy,cy1,cz,cz1,czp,czp1,cd2yzz,cw,cw1
+ ,cwp,cwp1,cd2yww,cdyz,cdwy,cdwz,isoort,iepsz,iepsw,ier)
***#[*comment:***********************************************************
* *
* Calculate *
* *
* R(cy,cz,iepsz) - R(cy,cw,iepsw) *
* *
* Input: *
* a = [yzw] (real) see definition *
* a1 = 1 - a (real) *
* dab = a - b (real) *
* ieps[zw] (integer) sign of imaginary part *
* of argument logarithm *
* cs3(20) (complex) assumed zero *
* *
* Output: *
* cs3(20) (complex) the results, not added *
* ipi12(2) (integer) factors pi^2/12 *
* *
* Calls: ffcrr *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ipi12(2),isoort,iepsz,iepsw,ier
- DOUBLE COMPLEX cs3(20)
- DOUBLE COMPLEX cy,cz,czp,cw,cwp,cy1,cz1,czp1,cw1,cwp1,
+ ComplexType cs3(20)
+ ComplexType cy,cz,czp,cw,cwp,cy1,cz1,czp1,cw1,cwp1,
+ cdyz,cdwy,cdwz,cd2yzz,cd2yww
*
* local variables:
*
integer i,ieps,ieps1,ieps2,
+ nffeta,nffet1,n1,n2,n3,n4,n5,n6
logical ld2yyz
- DOUBLE COMPLEX cyy,cyy1,czz,czz1,cdyyzz,chulp,zfflo1,zfflog,
+ ComplexType cyy,cyy1,czz,czz1,cdyyzz,chulp,zfflo1,zfflog,
+ cc1,cdw,cc1n,cterm,ctot,cd2,cd3,
+ cd21,cd31,cd2n,cd3n,cd21n1,cd31n1,
+ cc2,cfactz,cfactw,czzp,czzp1,cd2yyz
- DOUBLE COMPLEX c
- DOUBLE PRECISION absc
+ ComplexType c
+ RealType absc
external nffeta,nffet1,zfflo1,zfflog
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ groundwork:
if ( cdwz .eq. 0 ) then
- if ( abs(DIMAG(cz)) .gt. precc*abs(DBLE(cz)) .or.
+ if ( abs(Im(cz)) .gt. precc*abs(Re(cz)) .or.
+ iepsz .eq. iepsw ) return
- if ( DBLE(cz) .ge. 0 .and. DBLE(cz1) .ge. 0 ) return
+ if ( Re(cz) .ge. 0 .and. Re(cz1) .ge. 0 ) return
call fferr(76,ier)
return
endif
if ( cdyz .eq. 0 ) then
call fferr(77,ier)
return
endif
cc1 = cy/cdyz
cdw = cdwz/cdyz
- if ( DBLE(cc1) .le. .5D0 .or. abs(cc1-1) .gt. 1 ) then
+ if ( Re(cc1) .le. .5D0 .or. abs(cc1-1) .gt. 1 ) then
cd2 = 1/cy
cdw = cdw*cy/cw
else
cd2 = 1/cz1
endif
* #] groundwork:
* #[ trivial case:
if ( absc(cdw) .eq. 0 ) then
* #] trivial case:
* #[ normal case:
*
* if no cancellations are expected OR the imaginary signs differ
* and are significant
*
elseif ( absc(cdw) .gt. xloss .or. (iepsz.ne.iepsw .and.
- + (DBLE(cy/cdyz).gt.1 .or. DBLE(-cy1/cdyz).gt.1) ) ) then
+ + (Re(cy/cdyz).gt.1 .or. Re(-cy1/cdyz).gt.1) ) ) then
* nothing's the matter
* special case to avoid bug found 15-oct=1995
if ( iepsz.eq.iepsw ) then
- if ( DIMAG(cz).eq.0 .and. DIMAG(cz1).eq.0 ) then
+ if ( Im(cz).eq.0 .and. Im(cz1).eq.0 ) then
print *,'ffdcrr: flipping sign iepsz'
iepsz = -iepsz
- elseif ( DIMAG(cw).eq.0 .and. DIMAG(cw1).eq.0 ) then
+ elseif ( Im(cw).eq.0 .and. Im(cw1).eq.0 ) then
print *,'ffdcrr: flipping sign iepsw'
iepsw = -iepsw
else
print *,'ffdcrr: error: missing eta terms!'
ier = ier + 100
endif
endif
call ffcrr(cs3(1),ipi12(1),cy,cy1,cz,cz1,cdyz,.TRUE.,
+ cd2yzz,czp,czp1,isoort,iepsz,ier)
call ffcrr(cs3(8),ipi12(2),cy,cy1,cw,cw1,-cdwy,.TRUE.,
+ cd2yww,cwp,cwp1,isoort,iepsw,ier)
do 10 i=8,14
cs3(i) = -cs3(i)
10 continue
ipi12(2) = -ipi12(2)
* #] normal case:
* #[ only cancellations in cw, not in cy:
elseif ( absc(cd2) .gt. xloss ) then
* there are no cancellations the other way:
cyy = cdwy/cdwz
czz = cz*cyy/cy
cyy1 = cdyz/cdwz
czz1 = cyy1*cw/cy
cdyyzz = cdyz*cyy/cy
- if ( DBLE(cy) .gt. 0 ) then
+ if ( Re(cy) .gt. 0 ) then
ieps1 = -3*iepsz
else
ieps1 = +3*iepsz
endif
* Often 2y-z-z is relevant, but 2*yy-zz-zz is not, solve by
* introducing zzp.
czzp = czp*cyy/cy
cd2yyz = cd2yzz*cyy/cy
czzp1 = 1 - czzp
if ( absc(czzp1) .lt. xloss ) then
* later try more possibilities
ld2yyz = .FALSE.
else
ld2yyz = .TRUE.
endif
call ffcrr(cs3(1),ipi12(1),cyy,cyy1,czz,czz1,cdyyzz,
+ ld2yyz,cd2yyz,czzp,czzp1,isoort,ieps1,ier)
czz = cyy*cz1/cy1
czz1 = cyy1*cw1/cy1
- if ( DBLE(-cy1) .gt. 0 ) then
+ if ( Re(-cy1) .gt. 0 ) then
ieps2 = -3*iepsz
else
ieps2 = +3*iepsz
endif
cdyyzz = -cyy*cdyz/cy1
czzp = czp1*cyy/cy1
cd2yyz = -cd2yzz*cyy/cy1
czzp1 = 1 - czzp
if ( absc(czzp1) .lt. xloss ) then
* later try more possibilities
ld2yyz = .FALSE.
else
ld2yyz = .TRUE.
endif
call ffcrr(cs3(8),ipi12(2),cyy,cyy1,czz,czz1,cdyyzz,
+ .TRUE.,cd2yyz,czzp,czzp1,isoort,ieps2,ier)
do 20 i=8,14
cs3(i) = -cs3(i)
20 continue
ipi12(2) = -ipi12(2)
* eta terms (are not calculated in ffcrr as ieps = 3)
cfactz = 1/cdyz
- if ( DIMAG(cz) .eq. 0 ) then
- if ( DIMAG(cy) .eq. 0 ) then
+ if ( Im(cz) .eq. 0 ) then
+ if ( Im(cy) .eq. 0 ) then
n1 = 0
n2 = 0
else
- n1 = nffet1(DCMPLX(DBLE(0),DBLE(iepsz)),cfactz,
+ n1 = nffet1(ToComplex(Re(0),Re(iepsz)),cfactz,
+ -cz*cfactz,ier)
- n2 = nffet1(DCMPLX(DBLE(0),DBLE(iepsz)),cfactz,
+ n2 = nffet1(ToComplex(Re(0),Re(iepsz)),cfactz,
+ cz1*cfactz,ier)
endif
else
n1 = nffeta(-cz,cfactz,ier)
n2 = nffeta(cz1,cfactz,ier)
endif
cfactw = -1/cdwy
- if ( DIMAG(cw) .eq. 0 ) then
- if ( DIMAG(cy) .eq. 0 ) then
+ if ( Im(cw) .eq. 0 ) then
+ if ( Im(cy) .eq. 0 ) then
n4 = 0
n5 = 0
else
- n4 = nffet1(DCMPLX(DBLE(0),DBLE(iepsw)),cfactw,
+ n4 = nffet1(ToComplex(Re(0),Re(iepsw)),cfactw,
+ -cw*cfactw,ier)
- n5 = nffet1(DCMPLX(DBLE(0),DBLE(iepsw)),cfactw,
+ n5 = nffet1(ToComplex(Re(0),Re(iepsw)),cfactw,
+ cw1*cfactw,ier)
endif
else
n4 = nffeta(-cw,cfactw,ier)
n5 = nffeta(cw1,cfactw,ier)
endif
*
* we assume that cs3(15-17) are not used, this is always true
*
n3 = 0
n6 = 0
if ( n1.eq.n4 ) then
if ( n1.eq.0 ) then
* nothing to do
else
cc1 = cdwz/cdyz
if ( absc(cc1) .lt. xloss ) then
cs3(15) = n1*c2ipi*zfflo1(cc1,ier)
else
cc1 = -cdwy/cdyz
cs3(15) = n1*c2ipi*zfflog(cc1,0,czero,ier)
endif
cc1 = cy*cfactz
cc2 = cy*cfactw
- if ( DIMAG(cc1).eq.0 .or. DIMAG(cc2).eq.0 ) then
+ if ( Im(cc1).eq.0 .or. Im(cc2).eq.0 ) then
n3 = 0
else
n3 = nffeta(cc1,1/cc2,ier)
endif
if ( n3.ne.0 ) then
print *,'ffdcrr: error: untested algorithm'
ier = ier + 50
ipi12(1) = ipi12(1) + 4*12*n1*n3
endif
endif
else
cc1 = cy*cfactz
cc2 = cy*cfactw
cs3(15) = (n1*zfflog(cc1,ieps1,czero,ier) +
+ n4*zfflog(cc2,ieps1,czero,ier))*c2ipi
endif
if ( n2.eq.n5 ) then
if ( n2.eq.0 ) then
* nothing to do
else
cc1 = cdwz/cdyz
if ( absc(cc1) .lt. xloss ) then
cs3(16) = n2*c2ipi*zfflo1(cc1,ier)
else
cc1 = -cdwy/cdyz
cs3(16) = n2*c2ipi*zfflog(cc1,0,czero,ier)
endif
cc1 = -cy1*cfactz
cc2 = -cy1*cfactw
- if ( DIMAG(cc1).eq.0 .or. DIMAG(cc2).eq.0 ) then
+ if ( Im(cc1).eq.0 .or. Im(cc2).eq.0 ) then
n6 = 0
else
n6 = nffeta(cc1,1/cc2,ier)
endif
if ( n6.ne.0 ) then
print *,'ffdcrr: error: untested algorithm'
ier = ier + 50
ipi12(2) = ipi12(2) + 4*12*n2*n6
endif
endif
else
cc1 = -cy1*cfactz
cc2 = -cy1*cfactw
cs3(15) = (n2*zfflog(cc1,ieps2,czero,ier) +
+ n5*zfflog(cc2,ieps2,czero,ier))*c2ipi
endif
* #] only cancellations in cw, not in cy:
* #[ Hill identity:
elseif ( ( 1.gt.xloss*absc(cy) .or. absc(cc1).gt.xloss )
+ .and. ( 1.gt.xloss*absc(cz) .or. absc(cz/cdyz).gt.xloss )
+ .and. ( 1.gt.xloss*absc(cy) .or. absc(cdyz/cy).gt.xloss )
+ ) then
* do a Hill identity on the cy,cy-1 direction
cyy = -cy*cw1/cdwy
cyy1 = cw*cy1/cdwy
czz = -cz*cw1/cdwz
czz1 = cw*cz1/cdwz
cdyyzz = -cw*cw1*(cdyz/(cdwy*cdwz))
ieps = -2*iepsz
call ffcrr(cs3(1),ipi12(1),cyy,cyy1,czz,czz1,cdyyzz,
+ .FALSE.,czero,czero,czero,isoort,ieps,ier)
cyy = cw1
cyy1 = cw
czz = -cw1*cz/cdwz
czz1 = cw*cz1/cdwz
cdyyzz = cw*cw1/cdwz
call ffcrr(cs3(8),ipi12(2),cyy,cyy1,czz,czz1,cdyyzz,
+ .FALSE.,czero,czero,czero,isoort,0,ier)
do 30 i=8,14
30 cs3(i) = -cs3(i)
ipi12(2) = -ipi12(2)
* the extra logarithms ...
if ( 1 .lt. xloss*absc(cw) ) then
chulp = zfflo1(1/cw,ier)
else
chulp = zfflog(-cw1/cw,0,czero,ier)
endif
cs3(15) = -zfflo1(cdwz/cdwy,ier)*chulp
* #] Hill identity:
* #[ Taylor expansion:
else
* Do a Taylor expansion
if ( absc(cc1) .lt. xloss ) then
cd3 = cdwz/cdwy
* isign = 1
cc1n = cc1
cd2n = cd2
cd3n = cd3
cd21 = 1-cd2
cd21n1 = 1
cd31 = 1-cd3
cd31n1 = 1
ctot = cc1*cd2*cd3
do 50 i=2,20
cc1n = cc1n*cc1
cd21n1 = cd21n1*cd21
cd31n1 = cd31n1*cd31
cd2n = cd2n + cd2*cd21n1
cd3n = cd3n + cd3*cd31n1
- cterm = cc1n*cd2n*cd3n*DBLE(xn2inv(i))
+ cterm = cc1n*cd2n*cd3n*Re(xn2inv(i))
ctot = ctot + cterm
if ( absc(cterm) .lt. precc*absc(ctot) ) goto 51
50 continue
51 continue
cs3(1) = ctot
elseif ( absc(cz/cdyz) .lt. xloss ) then
call ffcrr(cs3(1),ipi12(1),cy,cy1,cz,cz1,cdyz,.TRUE.,
+ cd2yzz,czp,czp1,isoort,iepsz,ier)
call ffcrr(cs3(8),ipi12(2),cy,cy1,cw,cw1,-cdwy,.TRUE.,
+ cd2yww,cwp,cwp1,isoort,iepsw,ier)
do 110 i=8,14
110 cs3(i) = -cs3(i)
ipi12(2) = -ipi12(2)
else
call fferr(20,ier)
return
endif
endif
* #] Taylor expansion:
*###] ffdcrr:
end
diff --git a/Looptools/util/ffcxyz.F b/Looptools/util/ffcxyz.F
--- a/Looptools/util/ffcxyz.F
+++ b/Looptools/util/ffcxyz.F
@@ -1,308 +1,309 @@
#include "externals.h"
+#include "types.h"
*###[ ffcxyz:
subroutine ffcxyz(cy,cz,cdyz,cd2yzz,ivert,sdelpp,sdelps,
+ etami,delps,xpi,piDpj,isoort,ldel2s,ns,ier)
***#[*comment:***********************************************************
* *
* calculate in a numerically stable way *
* *
* cz(1,2) = (-p(ip1).p(is2) +/- sdelpp)/xpi(ip1) *
* cy(1,2) = (-p(ip1).p(is2) +/- sdisc)/xpi(ip1) *
* disc = slam1 + 4*eta*xpi(ip)/slam *
* *
* cy(3,4) = 1-cy(1,2) *
* cz(3.4) = 1-cz(1,2) *
* cdyz(i,j) = cy(i) - cz(j) *
* *
* Input: ivert (integer) 1,2 of 3 *
* sdelpp (real) sqrt(lam(p1,p2,p3))/2 *
* sdelps (real) sqrt(-lam(p,ma,mb))/2 *
* etalam (real) det(si.sj)/det(pi.pj) *
* etami(6) (real) si.si - etalam *
* xpi(ns) (real) standard *
* piDpj(ns,ns) (real) standard *
* ns (integer) dim of xpi,piDpj *
* *
* Output: cy(4),cz(4),cdyz(4,4) (complex) see above *
* *
* Calls: ?? *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ivert,isoort(2),ns,ier
logical ldel2s
- DOUBLE COMPLEX cy(4),cz(4),cdyz(2,2),cd2yzz
- DOUBLE PRECISION sdelpp,sdelps,etami(6),delps,xpi(ns),
+ ComplexType cy(4),cz(4),cdyz(2,2),cd2yzz
+ RealType sdelpp,sdelps,etami(6),delps,xpi(ns),
+ piDpj(ns,ns)
*
* local variables:
*
integer ip1,is1,is2,is3
- DOUBLE COMPLEX c
- DOUBLE PRECISION absc,y(4)
- DOUBLE PRECISION disc,hulp
+ ComplexType c
+ RealType absc,y(4)
+ RealType disc,hulp
*
* common blocks:
*
#include "ff.h"
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ set up pointers:
if ( ldel2s .and. ivert .ne. 1 ) goto 100
is1 = ivert
is2 = ivert+1
if ( is2 .eq. 4 ) is2 = 1
is3 = ivert-1
if ( is3 .eq. 0 ) is3 = 3
ip1 = is1 + 3
* ip2 = is2 + 3
* ip3 = is3 + 3
isoort(1) = -10
isoort(2) = -10
* #] set up pointers:
* #[ get cypm,czpm:
hulp = sdelps/xpi(ip1)
- cz(1) = DCMPLX(piDpj(ip1,is2)/xpi(ip1),-hulp)
- cz(2) = DCMPLX(piDpj(ip1,is2)/xpi(ip1),+hulp)
+ cz(1) = ToComplex(piDpj(ip1,is2)/xpi(ip1),-hulp)
+ cz(2) = ToComplex(piDpj(ip1,is2)/xpi(ip1),+hulp)
disc = delps/sdelpp
call ffroot(y(1),y(2),xpi(ip1),piDpj(ip1,is2),etami(is2),disc,
+ ier)
cy(1) = y(1)
cy(2) = y(2)
* #] get cypm,czpm:
* #[ get cypm1,czpm1:
if ( xpi(is1) .eq. xpi(is2) ) then
cy(4) = cy(1)
cy(3) = cy(2)
cz(4) = cz(1)
cz(3) = cz(2)
else
cz(3) = 1 - cz(1)
cz(4) = 1 - cz(2)
if ( absc(cz(3)).lt.xloss .or. absc(cz(4)).lt.xloss ) then
- cz(3) =DCMPLX(-piDpj(ip1,is1)/xpi(ip1),+hulp)
- cz(4) =DCMPLX(-piDpj(ip1,is1)/xpi(ip1),-hulp)
+ cz(3) =ToComplex(-piDpj(ip1,is1)/xpi(ip1),+hulp)
+ cz(4) =ToComplex(-piDpj(ip1,is1)/xpi(ip1),-hulp)
endif
y(3) = 1 - y(1)
y(4) = 1 - y(2)
if ( abs(y(3)) .lt. xloss .or. abs(y(4)) .lt. xloss ) then
call ffroot(y(4),y(3),xpi(ip1),-piDpj(ip1,is1),
+ etami(is1),disc,ier)
endif
cy(3) = y(3)
cy(4) = y(4)
endif
* #] get cypm1,czpm1:
* #[ get cdypzp, cdypzm:
- cdyz(2,1) = DCMPLX(disc/xpi(ip1),+hulp)
- cdyz(2,2) = DCMPLX(disc/xpi(ip1),-hulp)
+ cdyz(2,1) = ToComplex(disc/xpi(ip1),+hulp)
+ cdyz(2,2) = ToComplex(disc/xpi(ip1),-hulp)
cdyz(1,1) = -cdyz(2,2)
cdyz(1,2) = -cdyz(2,1)
cd2yzz = 2*disc/xpi(ip1)
goto 200
* #] get cdypzp, cdypzm:
* #[ special case, get indices:
100 continue
if ( ivert.eq.2 ) then
is1 = 2
ip1 = 5
else
is1 = 1
ip1 = 6
endif
isoort(1) = -100
isoort(2) = -100
* #] special case, get indices:
* #[ get cypm,czpm:
*
* special case del2s = 0, hence the roots are not the real roots
* but z_2'' = (z_2'-1)/delta, z''_3 = -z'_3/delta
*
hulp = sdelps/xpi(3)
disc = delps/sdelpp
if ( ivert .eq. 3 ) then
hulp = -hulp
disc = -disc
endif
- cz(1) = DCMPLX(piDpj(is1,3)/xpi(3),-hulp)
- cz(2) = DCMPLX(piDpj(is1,3)/xpi(3),+hulp)
+ cz(1) = ToComplex(piDpj(is1,3)/xpi(3),-hulp)
+ cz(2) = ToComplex(piDpj(is1,3)/xpi(3),+hulp)
call ffroot(y(1),y(2),xpi(3),piDpj(is1,3),etami(is1),disc,ier)
cy(1) = y(1)
cy(2) = y(2)
* #] get cypm,czpm:
* #[ get cypm1,czpm1:
cz(3) = 1 - cz(1)
cz(4) = 1 - cz(2)
if ( absc(cz(3)).lt.xloss .or. absc(cz(4)).lt.xloss ) then
if ( ivert.eq.2 ) then
- cz(3) =DCMPLX(piDpj(ip1,3)/xpi(3),+hulp)
- cz(4) =DCMPLX(piDpj(ip1,3)/xpi(3),-hulp)
+ cz(3) =ToComplex(piDpj(ip1,3)/xpi(3),+hulp)
+ cz(4) =ToComplex(piDpj(ip1,3)/xpi(3),-hulp)
else
- cz(3) =DCMPLX(-piDpj(ip1,3)/xpi(3),+hulp)
- cz(4) =DCMPLX(-piDpj(ip1,3)/xpi(3),-hulp)
+ cz(3) =ToComplex(-piDpj(ip1,3)/xpi(3),+hulp)
+ cz(4) =ToComplex(-piDpj(ip1,3)/xpi(3),-hulp)
endif
endif
y(3) = 1 - y(1)
y(4) = 1 - y(2)
if ( abs(y(3)) .lt. xloss .or. abs(y(4)) .lt. xloss ) then
if ( ivert .eq. 2 ) then
call ffroot(y(4),y(3),xpi(3),piDpj(ip1,3),etami(ip1),
+ disc,ier)
else
call ffroot(y(4),y(3),xpi(3),-piDpj(ip1,3),etami(ip1),
+ disc,ier)
endif
endif
cy(3) = y(3)
cy(4) = y(4)
* #] get cypm1,czpm1:
* #[ get cdypzp, cdypzm:
- cdyz(2,1) = DCMPLX(disc/xpi(3),+hulp)
- cdyz(2,2) = DCMPLX(disc/xpi(3),-hulp)
+ cdyz(2,1) = ToComplex(disc/xpi(3),+hulp)
+ cdyz(2,2) = ToComplex(disc/xpi(3),-hulp)
cdyz(1,1) = -cdyz(2,2)
cdyz(1,2) = -cdyz(2,1)
cd2yzz = 2*disc/xpi(3)
* #] get cdypzp, cdypzm:
200 continue
*###] ffcxyz:
end
*###[ ffcdwz:
subroutine ffcdwz(cdwz,cz,i1,j1,l,calpha,calph1,cpi,cdpipj,
+ cpiDpj,csdeli,csdel2,ns,ier)
***#[*comment:***********************************************************
* *
* Recalculate cdwz(i1,j1) = cw(i1) - cz(j1) *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer i1,j1,l,ns,ier
- DOUBLE COMPLEX cdwz(2,2),cz(4),calpha,calph1,cpi(ns)
- DOUBLE COMPLEX cdpipj(ns,ns),cpiDpj(ns,ns),csdeli(3),csdel2
+ ComplexType cdwz(2,2),cz(4),calpha,calph1,cpi(ns)
+ ComplexType cdpipj(ns,ns),cpiDpj(ns,ns),csdeli(3),csdel2
*
* local variables:
*
integer i,n
- DOUBLE COMPLEX cs(8),csum,cfac,c,cddel
- DOUBLE PRECISION xmax,absc,afac
+ ComplexType cs(8),csum,cfac,c,cddel
+ RealType xmax,absc,afac
*
* common blocks:
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ calculations:
if ( l .eq. 1 ) then
if ( j1 .eq. 1 ) then
if ( absc(csdeli(1)+csdel2) .lt. xloss*absc(csdel2) )
+ then
* for example in e-> e g* with eeg loop
* first get the difference of csdeli(1) and csdel2:
cs(1) = cpi(4)*cdpipj(2,5)
cs(2) = -cpiDpj(4,3)*cpiDpj(4,2)
cs(3) = cpiDpj(4,3)*cpiDpj(4,5)
csum = cs(1)+cs(2)+cs(3)
xmax = max(absc(cs(1)),absc(cs(2)),absc(cs(3)))
if ( absc(csum) .lt. xloss*xmax ) then
ier = 1
goto 5
endif
cddel = csum/(csdel2-csdeli(1))
if ( i1 .eq. 1 ) then
cs(1) = cpi(4)*csdeli(2)
else
cs(1) = -cpi(4)*csdeli(2)
endif
cs(2) = cddel*cpiDpj(4,2)
cs(3) = -cpiDpj(4,3)*csdeli(1)
cs(4) = cpiDpj(4,3)*cpiDpj(4,5)
cs(5) = -cpi(4)*cpiDpj(5,3)
cs(6) = -cddel*csdel2
n = 6
else
ier = ier + 100
goto 5
endif
csum = 0
xmax = 0
do 1 i=1,n
csum = csum + cs(i)
xmax = max(xmax,absc(cs(i)))
1 continue
if ( absc(csum) .lt. xloss*xmax ) then
ier = ier + 1
endif
cdwz(i1,j1) = csum/calph1/cpi(4)/cpi(5)
if ( cdwz(i1,j1) .eq. 0 .and. csum .ne. 0 ) then
print *,'?#$&!! cdwz = 0 but csum != 0, try again'
afac = 1/absc(csum)
- csum = csum*DBLE(afac)
+ csum = csum*Re(afac)
cdwz(i1,j1) = csum/calph1/cpi(4)/cpi(5)
afac = 1/afac
- cdwz(i1,j1) = cdwz(i1,j1)*DBLE(afac)
+ cdwz(i1,j1) = cdwz(i1,j1)*Re(afac)
endif
else
ier = ier + 100
endif
5 continue
elseif ( l .eq. 3 ) then
if ( (i1.eq.2 .and. j1.eq.1) .or. (i1.eq.1 .and. j1.eq.2 ) )
+ then
cfac = 1/(csdeli(2) + csdeli(3))
cs(1) = cdpipj(6,5)*cz(j1)
cs(2) = -calph1*cpi(5)*cz(j1+2)
if ( max(absc(cdpipj(2,1)),absc(cdpipj(5,6))) .lt.
+ max(absc(cdpipj(2,6)),absc(cdpipj(5,1))) ) then
cs(3) = cdpipj(2,1)/2
cs(4) = cdpipj(5,6)/2
else
cs(3) = cdpipj(2,6)/2
cs(4) = cdpipj(5,1)/2
endif
cs(5) = cpiDpj(4,3)*cpiDpj(5,3)*cfac
cs(6) = -cpiDpj(4,3)*cpiDpj(6,3)*cfac
cs(7) = cpi(3)*cdpipj(5,6)*cfac
if ( i1 .eq. 1 ) then
csum = cs(1)+cs(2)+cs(3)+cs(4) - (cs(5)+cs(6)+cs(7))
else
csum = cs(1)+cs(2)+cs(3)+cs(4) + cs(5)+cs(6)+cs(7)
endif
xmax = absc(cs(1))
do 10 i=2,7
xmax = max(xmax,absc(cs(i)))
10 continue
if ( absc(csum) .lt. xloss*xmax ) then
* this result is not used if it is not accurate (see
* ffxc0p)
ier = ier + 1
xmax = xmax/absc(calpha*cpi(5))
if ( xmax .lt. min(absc(cz(j1)),absc(cz(j1+2))) )
+ then
cdwz(i1,j1) = csum/(calpha*cpi(5))
endif
else
cdwz(i1,j1) = csum/(calpha*cpi(5))
endif
else
ier = ier + 100
endif
else
ier = ier + 100
endif
* #] calculations:
*###] ffcdwz:
end
diff --git a/Looptools/util/ffdcxs.F b/Looptools/util/ffdcxs.F
--- a/Looptools/util/ffdcxs.F
+++ b/Looptools/util/ffdcxs.F
@@ -1,624 +1,625 @@
#include "externals.h"
+#include "types.h"
*--#[ log:
* $Id: ffdcxs.f,v 1.7 1996/03/22 08:13:30 gj Exp $
* $Log: ffdcxs.f,v $
c Revision 1.7 1996/03/22 08:13:30 gj
c Fixed bug in bugfix of ffdcxs.f
c
c Revision 1.6 1996/03/14 15:53:13 gj
c Fixed bug in ffcb0: cp in C, cma=cmb=0 was computed incorrectly.
c
c Revision 1.5 1996/03/13 15:43:36 gj
c Fixed bug, when ieps unknown already some things were computed and not zero'd.
c Now I first check ieps, and then compute.
c
c Revision 1.4 1995/12/08 10:38:16 gj
c Fixed too long line
c
*--#] log:
*###[ ffdcxs:
subroutine ffdcxs(cs3,ipi12,y,z,dyz,d2yzz,dy2z,dyzzy,xpi,piDpj,
+ ii,ns,isoort,ier)
***#[*comment:***********************************************************
* *
* calculates the the difference of two S's with y(3,4),z(3,4) and *
* y(4)z(3)-y(3)z(4) given. Note the difference with ffdcxs4, in *
* which the y's are the same and only the z's different. Here *
* both can be different. Also we skip an intermediate level. *
* Note also that this routine is much less conservative than *
* ffcxs3 in its expectations of the order of the roots: it knows *
* that it is (z-,z+,1-z-,1-z+)! *
* *
* input: y(4,3:4) (real) y,1-y in S with s3,s4 *
* z(4,3:4) (real) z,1-z in S with s3,s4 *
* dyz(2,2,3:4) (real) y - z *
* d2yzz(3:4) (real) 2*y - z+ - z- *
* dy2z(4,3:4) (real) y - 2*z *
* dyzzy(4) (real) y(i,4)*z(i,4)-y(i,3)*z(i,4) *
* xpi(6,3:4) (real) usual *
* piDpj(6,3:4) (real) usual *
* cs3(40) (complex) assumed zero. *
* *
* output: cs3(40) (complex) mod factors pi^2/12, in array *
* ipi12(6)(integer) these factors *
* isoort(6)(integer) returns kind of action taken *
* ier (integer) 0=ok 1=inaccurate 2=error *
* *
-* calls: ffcrr,ffcxr,real/dble,DCMPLX,log,ffadd1,ffadd2,ffadd3 *
+* calls: ffcrr,ffcxr,real/dble,ToComplex,log,ffadd1,ffadd2,ffadd3 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE COMPLEX cs3(100)
- DOUBLE PRECISION y(4,3:4),z(4,3:4),dyz(2,2,3:4),d2yzz(3:4),
+ ComplexType cs3(100)
+ RealType y(4,3:4),z(4,3:4),dyz(2,2,3:4),d2yzz(3:4),
+ dy2z(4,3:4),dyzzy(4),xpi(6,3:4),piDpj(6,6,3:4)
integer ipi12(10),ii,ns,isoort(10),ier
*
* local variables
*
integer i,j,k,l,m,iepsi(4),iepsj(2,2)
logical normal
- DOUBLE PRECISION yy,zz,yy1,zz1,dyyzz,hulp3,hulp4,x00(3)
+ RealType yy,zz,yy1,zz1,dyyzz,hulp3,hulp4,x00(3)
save iepsi
*
* common blocks
*
#include "ff.h"
*
* data
*
data iepsi /-2,+2,+2,-2/
*
* check constants
* #] declarations:
* #[ normal case:
normal = .FALSE.
10 continue
if ( normal .or. isoort(1) .ne. isoort(9) .or. isoort(1) .lt.
+ 10 ) then
call ffcxs3(cs3( 1),ipi12(1),y(1,3),z(1,3),dyz(1,1,3),
+ d2yzz(3),dy2z(1,3),xpi(1,3),piDpj(1,1,3),ii,6,
+ isoort(1),ier)
call ffcxs3(cs3(81),ipi12(9),y(1,4),z(1,4),dyz(1,1,4),
+ d2yzz(4),dy2z(1,4),xpi(1,4),piDpj(1,1,4),ii,6,
+ isoort(9),ier)
return
endif
* #] normal case:
* #[ rotate R's:
if ( abs(y(2,3)) .lt. 1/xloss ) then
do 102 i=1,2
do 101 j=1,2
* iepsi() = /-2,+2,+2,-2/
* BUT I AM NOT YET SURE OF THE SIGNS (29/6/89)
k = 2*(i-1)+j
if ( y(2*i,3) .gt. 0 ) then
iepsj(j,i) = iepsi(k)
else
iepsj(j,i) = -iepsi(k)
endif
if ( y(2*i,3) .gt. 0 .neqv. y(2*i,4) .gt. 0 ) then
* I have no clue to the ieps, take normal route
* iepsj(j,i) = 0
normal = .TRUE.
goto 10
endif
101 continue
102 continue
* loop over y,z , 1-y,1-z
do 120 i=1,2
* loop over z+ , z-
do 110 j=1,2
if ( j .eq. 2 ) then
* do not calculate if not there (isoort=0, one root)
* (this is probably not needed as this case should
* have been dealt with in ffdxc0)
if ( isoort(9) .eq. 0 ) goto 110
* or if not needed (isoort=2, two equal roots)
if ( mod(isoort(9),10) .eq. 2 ) then
* we use that l still contains the correct value
do 105 m=1,7
- cs3(10*(l-1)+m) = 2*DBLE(cs3(10*(l-1)+m))
+ cs3(10*(l-1)+m) = 2*Re(cs3(10*(l-1)+m))
105 continue
ipi12(l) = 2*ipi12(l)
goto 110
endif
endif
k = 2*(i-1)+j
l = 8*(i-1)+j
if ( dyzzy(k) .ne. 0 ) then
* minus sign wrong in thesis (2.78)
hulp3 = -dyz(2,j,3)/dyzzy(k)
hulp4 = +dyz(2,j,4)/dyzzy(k)
yy = y(2*i,3)*hulp4
yy1 = y(2*i,4)*hulp3
zz = z(k,3)*hulp4
zz1 = z(k,4)*hulp3
dyyzz = dyz(2,j,3)*hulp4
if ( i .eq. 2 ) then
yy = -yy
yy1 = -yy1
zz = -zz
zz1 = -zz1
endif
call ffcxr(cs3(10*l-9),ipi12(l),yy,yy1,zz,zz1,dyyzz,
+ .FALSE.,0D0,0D0,0D0,.FALSE.,x00,iepsj(j,i),ier)
endif
110 continue
120 continue
goto 800
endif
* #] rotate R's:
* #[ other cases (not ready):
call ffcxs3(cs3( 1),ipi12(1),y(1,3),z(1,3),dyz(1,1,3),
+ d2yzz(3),dy2z(1,3),xpi(1,3),piDpj(1,1,3),ii,ns,
+ isoort(1),ier)
call ffcxs3(cs3(81),ipi12(9),y(1,4),z(1,4),dyz(1,1,4),
+ d2yzz(4),dy2z(1,4),xpi(1,4),piDpj(1,1,4),ii,ns,
+ isoort(9),ier)
return
* #] other cases (not ready):
800 continue
*###] ffdcxs:
end
*###[ ffdcs:
subroutine ffdcs(cs3,ipi12,cy,cz,cdyz,cd2yzz,cdyzzy,cdyyzz,
+ cpi,cpiDpj,ii,ns,isoort,ier)
***#[*comment:***********************************************************
* *
* calculates the the difference of two S's with cy(3,4),cz(3,4), *
* cy(4)cz(3)-cy(3)cz(4) given. Note the difference with ffdcs4, *
* in which the cy's are the same and only the cz's different. *
* Here both can be different. Also we skip an intermediat *
* level. *
* *
* input: cy(4,3:4) (complex) cy,1-cy in S with s3,s4 *
* cz(4,3:4) (complex) cz,1-cz in S with s3,s4 *
* cdyz(2,2,3:4)(complex) cy - cz *
* cd2yzz(3:4) (complex) 2*cy - cz+ - cz- *
* cdyzzy(4) (complex) cy(i,4)*cz(i,4)-cy(i,3)*cz(i,4) *
* cdyyzz(2) (complex) cy(i,4)-cz(i,4)-cy(i,3)+cz(i,4) *
* cpi(6,3:4) (complex) usual *
* cpiDpj(6,3:4)(complex) usual *
* cs3(40) (complex) assumed zero. *
* *
* output: cs3(40) (complex) mod factors pi^2/12, in array *
* ipi12(6) (integer) these factors *
* isoort(6) (integer) returns kind of action taken *
* ier (integer) number of digits lost *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE COMPLEX cs3(100)
- DOUBLE COMPLEX cy(4,3:4),cz(4,3:4),cdyz(2,2,3:4),cd2yzz(3:4),
+ ComplexType cs3(100)
+ ComplexType cy(4,3:4),cz(4,3:4),cdyz(2,2,3:4),cd2yzz(3:4),
+ cdyzzy(4),cdyyzz(2),cpi(6,3:4),cpiDpj(6,6,3:4)
integer ipi12(10),ii,ns,isoort(10),ier
*
* local variables
*
integer i,j,k,l,m,n,ieps,ni(4,3:4),ntot(3:4),
+ n1a,nffeta,nffet1,ip
- DOUBLE COMPLEX c,cc,clogy,zfflog,
+ ComplexType c,cc,clogy,zfflog,
+ zfflo1,cmip,yy,zz,yy1,zz1,dyyzz,hulp3,hulp4
- DOUBLE PRECISION absc
+ RealType absc
external nffeta,nffet1,zfflo1,zfflog
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) +abs(DIMAG(c))
+ absc(c) = abs(Re(c)) +abs(Im(c))
*
* check constants
* #] declarations:
* #[ normal case:
if ( mod(isoort(1),5).ne.mod(isoort(9),5) .or. isoort(1).gt.-5
+ ) then
call ffcs3(cs3( 1),ipi12(1),cy(1,3),cz(1,3),cdyz(1,1,3),
+ cd2yzz(3),cpi(1,3),cpiDpj(1,1,3),ii,6,isoort(1),ier)
call ffcs3(cs3(81),ipi12(9),cy(1,4),cz(1,4),cdyz(1,1,4),
+ cd2yzz(4),cpi(1,4),cpiDpj(1,1,4),ii,6,isoort(9),ier)
return
endif
* #] normal case:
* #[ rotate R's:
if ( absc(cy(2,3)) .lt. 1/xloss .or. isoort(1) .le. -100 ) then
*
* loop over cy,cz , 1-cy,1-cz
do 190 i=1,2
if ( isoort(1).le.-100 .and. i.eq.2 ) then
*
* special case del2s=0, a limit has been taken
*
if ( ii .eq. 2 ) then
*
* we took the wrong sign for the dilogs...
*
do 110 j=1,20
cs3(j) = -cs3(j)
110 continue
ipi12(1) = -ipi12(1)
ipi12(2) = -ipi12(2)
endif
*
* now the remaining logs. take care to get the ieps
* correct!
*
- if ( i.eq.1 .eqv. DBLE(cy(2*i,3)).gt.0 ) then
+ if ( i.eq.1 .eqv. Re(cy(2*i,3)).gt.0 ) then
ieps = -3
else
ieps = +3
endif
call ffclg2(cs3(81),cdyz(2,1,3),cdyz(2,1,4),
+ cdyyzz(1),ieps,ier)
if ( ii .eq. 2 ) then
* we have the wrong sign
do 120 j=81,83
cs3(j) = -cs3(j)
120 continue
ipi12(9) = -ipi12(9)
endif
if ( mod(isoort(1),5).eq.0 .and. mod(isoort(9),5).eq.0
+ ) then
do 130 j=81,83
- cs3(j) = 2*DBLE(cs3(j))
+ cs3(j) = 2*Re(cs3(j))
130 continue
ipi12(9) = 2*ipi12(9)
else
print *,'ffdcs: error: not yet tested'
call ffclg2(cs3(91),cdyz(2,2,3),cdyz(2,2,4),
+ cdyyzz(2),-ieps,ier)
if ( ii .eq. 2 ) then
* we have the wrong sign
do 140 j=91,93
cs3(j) = -cs3(j)
140 continue
ipi12(10) = -ipi12(10)
endif
endif
goto 190
endif
*
* loop over cz- , cz+
do 180 j=1,2
if ( j .eq. 2 ) then
if ( isoort(9) .eq. 0 .or. isoort(1) .eq. 0 ) then
*
* (this is not correct as this case should
* have been dealt with in ffdxc0,ffdcc0)
*
call fferr(79,ier)
goto 180
elseif ( mod(isoort(9),5) .eq. 0 .and.
+ mod(isoort(1),5) .eq. 0 ) then
*
* or if not needed (isoort=-10, two conjugate roots)
*
* we use that l still contains the correct value
do 150 m=1,9
- cs3(10*(l-1)+m) = 2*DBLE(cs3(10*(l-1)+m))
+ cs3(10*(l-1)+m) = 2*Re(cs3(10*(l-1)+m))
150 continue
ipi12(l) = 2*ipi12(l)
goto 180
elseif ( mod(isoort(9),10) .eq. 2 ) then
* we use that l still contains the correct value
do 160 m=1,9
cs3(10*(l-1)+m) = 2*cs3(10*(l-1)+m)
160 continue
ipi12(l) = 2*ipi12(l)
goto 180
endif
endif
k = 2*(i-1)+j
l = 8*(i-1)+j
if ( cdyzzy(k) .ne. 0 ) then
hulp3 = -cdyz(2,j,3)/cdyzzy(k)
hulp4 = cdyz(2,j,4)/cdyzzy(k)
yy = cy(2*i,3)*hulp4
yy1 = cy(2*i,4)*hulp3
zz = cz(k,3)*hulp4
zz1 = cz(k,4)*hulp3
dyyzz = cdyz(2,j,3)*hulp4
if ( i .eq. 2 ) then
yy = -yy
yy1 = -yy1
zz = -zz
zz1 = -zz1
endif
*
* ieps = 3 means: dear ffcrr, do not use eta terms,
* they are calculated here. The sign gives the sign
* of the imag. part of the argument of the dilog, not
* y-z.
*
- if ( i.eq.1 .eqv. j.eq.1 .eqv. DBLE(cy(2*i,3)).gt.0
+ if ( i.eq.1 .eqv. j.eq.1 .eqv. Re(cy(2*i,3)).gt.0
+ ) then
ieps = -3
else
ieps = +3
endif
call ffcrr(cs3(10*l-9),ipi12(l),yy,yy1,zz,zz1,dyyzz,
+ .FALSE.,czero,czero,czero,isoort(j),ieps,ier)
*
* eta terms of the R's (eta(.)*log(c1)-eta(.)*log(c2))
*
do 170 m=3,4
* no eta terms in the real case
- if ( DIMAG(cz(k,m)) .eq. 0 .and.
- + DIMAG(cdyz(2,j,m)) .eq. 0 ) then
+ if ( Im(cz(k,m)) .eq. 0 .and.
+ + Im(cdyz(2,j,m)) .eq. 0 ) then
ni(k,m) = 0
elseif ( i .eq. 1 ) then
ni(k,m) = nffeta(-cz(k,m),1/cdyz(2,j,m),ier)
else
ni(k,m) = nffeta(cz(k,m),1/cdyz(2,j,m),ier)
endif
170 continue
if ( ni(k,3) .ne. 0 .or. ni(k,4) .ne. 0 ) then
if ( ni(k,3) .ne. ni(k,4) ) then
do 175 m=3,4
c = cy(2*i,m)/cdyz(2,j,m)
if ( i .eq. 2 ) c = -c
cc = c-1
if ( absc(cc) .lt. xloss ) then
c = cz(k,m)/cdyz(2,j,m)
clogy = zfflo1(c,ier)
else
clogy = zfflog(c,0,czero,ier)
endif
n = 10*l + (m-3) - 2
if ( m .eq. 3 ) then
cs3(n) = + ni(k,m)*c2ipi*clogy
else
cs3(n) = - ni(k,m)*c2ipi*clogy
endif
175 continue
else
if ( i .eq. 1 ) then
n1a = nffeta(cy(k,3)/cdyz(2,j,3),
+ cdyz(2,j,4)/cy(k,4),ier)
else
n1a = nffeta(-cy(k,3)/cdyz(2,j,3),
+ -cdyz(2,j,4)/cy(k,4),ier)
endif
if ( n1a .ne. 0 ) then
call fferr(80,ier)
endif
c =cy(k,3)*cdyz(2,j,4)/(cdyz(2,j,3)*cy(k,4))
cc = c-1
if ( absc(cc) .lt. xloss ) then
c = -cdyzzy(k)/(cdyz(2,j,3)*cy(k,4))
clogy = zfflo1(c,ier)
else
clogy = zfflog(c,0,czero,ier)
endif
n = 10*l - 2
if ( i .eq. 1 ) then
cs3(n) = +ni(k,3)*c2ipi*clogy
else
cs3(n) = -ni(k,3)*c2ipi*clogy
endif
endif
endif
endif
180 continue
190 continue
goto 700
endif
* #] rotate R's:
* #[ other cases (not ready):
call ffcs3(cs3( 1),ipi12(1),cy(1,3),cz(1,3),cdyz(1,1,3),
+ cd2yzz(3),cpi(1,3),cpiDpj(1,1,3),ii,ns,isoort(1),ier)
call ffcs3(cs3(81),ipi12(9),cy(1,4),cz(1,4),cdyz(1,1,4),
+ cd2yzz(4),cpi(1,4),cpiDpj(1,1,4),ii,ns,isoort(9),ier)
return
* #] other cases (not ready):
* #[ get eta's:
700 continue
ip = ii+3
do 740 k=3,4
l = 8*(k-3) + 1
- if ( DIMAG(cpi(ip,k)) .eq. 0 ) then
+ if ( Im(cpi(ip,k)) .eq. 0 ) then
*
* complex because of a complex root in y or z
*
if ( (mod(isoort(l),10).eq.-1 .or. mod(isoort(l),10).eq.-3)
+ .and. isoort(l+1) .ne. 0 ) then
*
* isoort = -1: y is complex, possibly z as well
* isoort = -3: y,z complex, but (y-z-)(y-z+) real
* isoort = 0: y is complex, one z root only
* isoort = -10: y is real, z is complex
* isoort = -5,-6: y,z both real
*
- cmip = DCMPLX(0D0,-DBLE(cpi(ip,k)))
- if ( DIMAG(cz(1,k)) .eq. 0 ) then
+ cmip = ToComplex(0D0,-Re(cpi(ip,k)))
+ if ( Im(cz(1,k)) .eq. 0 ) then
ni(1,k) = 0
else
ni(1,k) = nffet1(-cz(1,k),-cz(2,k),cmip,ier)
i = nffet1(cz(3,k),cz(4,k),cmip,ier)
if ( i .ne. ni(1,k) ) call fferr(53,ier)
endif
ni(2,k) = 0
- if ( DBLE(cd2yzz(k)).eq.0 .and. ( DIMAG(cz(1,k)).eq.0 .and.
- + DIMAG(cz(2,k)).eq.0 .or. DBLE(cdyz(2,1,k)).eq.0 .and.
- + DBLE(cdyz(2,2,k)) .eq. 0 ) ) then
+ if ( Re(cd2yzz(k)).eq.0 .and. ( Im(cz(1,k)).eq.0 .and.
+ + Im(cz(2,k)).eq.0 .or. Re(cdyz(2,1,k)).eq.0 .and.
+ + Re(cdyz(2,2,k)) .eq. 0 ) ) then
* follow the i*epsilon prescription as (y-z-)(y-z+) real
- if ( DBLE(cpi(ip,k)) .lt. 0 ) then
+ if ( Re(cpi(ip,k)) .lt. 0 ) then
ni(3,k) = -1
else
ni(3,k) = 0
endif
ni(4,k) = -nffet1(cdyz(2,1,k),cdyz(2,2,k),cmip,ier)
else
- if ( DBLE(cpi(ip,k)) .lt. 0 .and. DIMAG(cdyz(2,1,k)*
+ if ( Re(cpi(ip,k)) .lt. 0 .and. Im(cdyz(2,1,k)*
+ cdyz(2,2,k)) .lt. 0 ) then
ni(3,k) = -1
else
ni(3,k) = 0
endif
ni(4,k) = -nffeta(cdyz(2,1,k),cdyz(2,2,k),ier)
endif
elseif ( (mod(isoort(l),10).eq.-1 .or. mod(isoort(l),10).eq.-3)
+ .and. isoort(l+1).eq.0 ) then
ni(1,k) = 0
- if ( DIMAG(cz(1,k)) .ne. 0 ) then
- ni(2,k) = nffet1(-cpiDpj(ii,ip,k),-cz(1,k),DCMPLX(DBLE(0
- + ),DBLE(-1)),ier)
+ if ( Im(cz(1,k)) .ne. 0 ) then
+ ni(2,k) = nffet1(-cpiDpj(ii,ip,k),-cz(1,k),ToComplex(Re(0
+ + ),Re(-1)),ier)
else
- ni(2,k) = nffet1(-cpiDpj(ii,ip,k),DCMPLX(DBLE(0),
- + DBLE(1)),DCMPLX(DBLE(0),DBLE(-1)),ier)
+ ni(2,k) = nffet1(-cpiDpj(ii,ip,k),ToComplex(Re(0),
+ + Re(1)),ToComplex(Re(0),Re(-1)),ier)
endif
ni(3,k) = 0
ni(4,k) = -nffeta(-cpiDpj(ii,ip,k),cdyz(2,1,k),ier)
else
if ( mod(isoort(l),5).ne.0 .and. mod(isoort(l),5).ne.-1
+ .and. mod(isoort(l),5).ne.-3 ) then
call fferr(81,ier)
print *,'isoort(',l,') = ',isoort(l)
endif
ni(1,k) = 0
ni(2,k) = 0
ni(3,k) = 0
ni(4,k) = 0
endif
else
print *,'ffdcs: error: cpi complex should not occur'
stop
endif
740 continue
* #] get eta's:
* #[ add eta's:
do 750 k=3,4
ntot(k) = ni(1,k)+ni(2,k)+ni(3,k)+ni(4,k)
750 continue
do 760 k=3,4
if ( ntot(k) .ne. 0 ) call ffclgy(cs3(20+80*(k-3)),
+ ipi12(2+8*(k-3)),ni(1,k),cy(1,k),cz(1,k),cd2yzz(k),ier)
760 continue
* #] add eta's:
*###] ffdcs:
end
*###[ ffclg2:
subroutine ffclg2(cs3,cdyz3,cdyz4,cdyyzz,ieps,ier)
***#[*comment:***********************************************************
* *
* Calculate the finite part of the divergent dilogs in case *
* del2s=0. These are given by *
* *
* log^2(-cdyz3)/2 - log^2(-cdyz4)/2 *
* *
* Note that often we only need the imaginary part, which may be *
* very unstable even if the total is not. *
* *
* *
* Input: cy3,cz3,cdyz3 (complex) y,z,diff in C with s3 *
* cy4,cz4,cdyz4 (complex) y,z,diff in C with s4 *
* cdyyzz (complex) y4 - z4 - y3 + z3 *
* isort3,4 (integer) *
* *
* Output cs3(4) (complex) output *
* ipi12 (integer) terms pi^2/12 *
* ier (integer) error flag *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
- DOUBLE COMPLEX cs3(3),cdyz3,cdyz4,cdyyzz
+ ComplexType cs3(3),cdyz3,cdyz4,cdyyzz
integer ieps,ier
*
* local variables
*
integer n1,nffeta,nffet1,ipi3,ipi4
- DOUBLE COMPLEX c,cc,clog3,clog4,clog1,zfflo1,cipi
- DOUBLE PRECISION absc
+ ComplexType c,cc,clog3,clog4,clog1,zfflo1,cipi
+ RealType absc
external nffeta,nffet1,zfflo1
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ calculations:
- cipi = DCMPLX(0D0,pi)
- if ( DBLE(cdyz3) .lt. 0 ) then
+ cipi = ToComplex(0D0,pi)
+ if ( Re(cdyz3) .lt. 0 ) then
clog3 = log(-cdyz3)
ipi3 = 0
else
clog3 = log(cdyz3)
- if ( DIMAG(cdyz3) .gt. 0 ) then
+ if ( Im(cdyz3) .gt. 0 ) then
ipi3 = -1
- elseif ( DIMAG(cdyz3) .lt. 0 ) then
+ elseif ( Im(cdyz3) .lt. 0 ) then
ipi3 = +1
else
ipi3 = sign(1,-ieps)
endif
endif
- if ( DBLE(cdyz4) .lt. 0 ) then
+ if ( Re(cdyz4) .lt. 0 ) then
clog4 = log(-cdyz4)
ipi4 = 0
else
clog4 = log(cdyz4)
- if ( DIMAG(cdyz4) .gt. 0 ) then
+ if ( Im(cdyz4) .gt. 0 ) then
ipi4 = -1
- elseif ( DIMAG(cdyz4) .lt. 0 ) then
+ elseif ( Im(cdyz4) .lt. 0 ) then
ipi4 = +1
else
ipi4 = sign(1,-ieps)
endif
endif
cc = clog3-clog4
if ( absc(cc) .ge. xloss*absc(clog3) ) then
cs3(1) = -(clog3+ipi3*cipi)**2/2
cs3(2) = +(clog4+ipi4*cipi)**2/2
else
c = cdyyzz/cdyz4
clog1 = zfflo1(c,ier)
*
* notice that zfflog return log(a-ieps) (for compatibility
* with the dilog) ^
*
- if ( DIMAG(cdyz3) .eq. 0 ) then
- n1 = nffet1(DCMPLX(DBLE(0),DBLE(-ieps)),-1/cdyz4,-c,
+ if ( Im(cdyz3) .eq. 0 ) then
+ n1 = nffet1(ToComplex(Re(0),Re(-ieps)),-1/cdyz4,-c,
+ ier)
- elseif ( DIMAG(cdyz3) .eq. 0 ) then
- n1 = nffet1(-cdyz3,DCMPLX(DBLE(0),DBLE(ieps)),-c,ier)
+ elseif ( Im(cdyz3) .eq. 0 ) then
+ n1 = nffet1(-cdyz3,ToComplex(Re(0),Re(ieps)),-c,ier)
else
n1 = nffeta(-cdyz3,-1/cdyz4,ier)
endif
if ( n1 .ne. 0 ) then
clog1 = clog1 - n1*c2ipi
endif
cs3(1) = -clog3*clog1/2
cs3(2) = -clog4*clog1/2
cs3(3) = -(ipi3+ipi4)*cipi*clog1/2
* we could split off a factor 2*pi^2 if needed
endif
* ATTENTION: now (23-jul-1989) ffdcs assumes that only *3* cs are
* set. Change ffdcs as well if this is no longer true!
* #] calculations:
*###] ffclg2:
end
diff --git a/Looptools/util/ffinit.F b/Looptools/util/ffinit.F
--- a/Looptools/util/ffinit.F
+++ b/Looptools/util/ffinit.F
@@ -1,1134 +1,1159 @@
+#include "externals.h"
+#include "types.h"
#include "defs.h"
* $Id: ffinit.f,v 1.9 1996/04/26 10:39:03 gj Exp $
-*###[ ffini:
+*###[ ltini:
subroutine ltini
***#[*comment:***********************************************************
* calculate a lot of commonly-used constants in the common block *
* /ffcnst/. also set the precision, maximum loss of digits and *
* the minimum value the logarithm accepts in /prec/. *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
integer i,j,init,ioldp(13,12),isgrop(10,12),ji
save init
- DOUBLE PRECISION s,sold
- DOUBLE COMPLEX cs
+ RealType s,sold
+ ComplexType cs
#include "lt.h"
character*32 env
data init /0/
data ioldp/1,2,3,4, 5,6,7,8,9,10, 11,12,13,
+ 4,1,2,3, 8,5,6,7,10,9, 11,13,12,
+ 3,4,1,2, 7,8,5,6,9,10, 11,12,13,
+ 2,3,4,1, 6,7,8,5,10,9, 11,13,12,
+ 4,2,3,1, 10,6,9,8,7,5, 12,11,13,
+ 1,3,2,4, 9,6,10,8,5,7, 12,11,13,
+ 1,2,4,3, 5,10,7,9,8,6, 13,12,11,
+ 1,4,3,2, 8,7,6,5,9,10, 11,13,12,
+ 3,4,2,1, 7,10,5,9,6,8, 13,12,11,
+ 2,3,1,4, 6,9,8,10,5,7, 12,13,11,
+ 4,2,1,3, 10,5,9,7,8,6, 13,11,12,
+ 1,3,4,2, 9,7,10,5,8,6, 13,11,12/
data isgrop/
+ +1,+1,+1,+1, +1,+1,+1,+1, +1,+1,
+ +1,+1,+1,+1, +1,+1,+1,+1, -1,+1,
+ +1,+1,+1,+1, +1,+1,+1,+1, -1,-1,
+ +1,+1,+1,+1, +1,+1,+1,+1, +1,-1,
+ +1,+1,+1,+1, -1,+1,+1,-1, +1,-1,
+ +1,+1,+1,+1, -1,-1,+1,+1, -1,+1,
+ +1,+1,+1,+1, +1,+1,-1,+1, +1,+1,
+ +1,+1,+1,+1, -1,-1,-1,-1, +1,-1,
+ +1,+1,+1,+1, -1,+1,+1,+1, -1,-1,
+ +1,+1,+1,+1, +1,+1,+1,-1, +1,-1,
+ +1,+1,+1,+1, -1,+1,+1,-1, -1,-1,
+ +1,+1,+1,+1, -1,-1,+1,+1, -1,-1/
* #] declarations:
* #[ check:
* check whether there is anything to do
if ( init .ne. 0 ) return
init = 1
print *,'===================================================='
print *,' FF 2.0, a package to evaluate one-loop integrals'
print *,'written by G. J. van Oldenborgh, NIKHEF-H, Amsterdam'
print *,'===================================================='
print *,'for the algorithms used see preprint NIKHEF-H 89/17,'
print *,'''New Algorithms for One-loop Integrals'', by G.J. van'
print *,'Oldenborgh and J.A.M. Vermaseren, published in '
print *,'Zeitschrift fuer Physik C46(1990)425.'
print *,'===================================================='
* #] check:
* #[ LoopTools stuff
*
* we do this here because loading block data is unreliable
*
call clearcache
serial = 0
call getenv("LTMINMASS", env)
minmass = 0
read(env, *, end=90, err=90) minmass
- print *, "using minmass =", minmass
+ print *, "env LTMINMASS =", minmass
90 continue
call getenv("LTMAXDEV", env)
maxdev = 1D-10
read(env, *, end=91, err=91) maxdev
- print *, "using maxdev =", maxdev
+ print *, "env LTMAXDEV =", maxdev
91 continue
+ call getenv("LTDIFFEPS", env)
+ diffeps = 1D-12
+ read(env, *, end=92, err=92) diffeps
+ print *, "env LTDIFFEPS =", diffeps
+92 continue
+
+ call getenv("LTZEROEPS", env)
+ zeroeps = 1D-22
+ read(env, *, end=93, err=93) zeroeps
+ print *, "env LTZEROEPS =", zeroeps
+93 continue
+
call getenv("LTCMPBITS", env)
- cmpbits = 62 + (KIND-1)*4
- read(env, *, end=92, err=92) cmpbits
- print *, "using cmpbits =", cmpbits
-92 continue
+ cmpbits = 58 + KIND*4
+ read(env, *, end=94, err=94) cmpbits
+ print *, "env LTCMPBITS =", cmpbits
+ cmpbits = max(cmpbits, 8 + KIND*4)
+94 continue
call getenv("LTVERSION", env)
versionkey = 0
- read(env, *, end=93, err=93) versionkey
- print *, "using versionkey =", versionkey
-93 continue
+ read(env, *, end=95, err=95) versionkey
+ print *, "env LTVERSION =", versionkey
+95 continue
call getenv("LTDEBUG", env)
debugkey = 0
- read(env, *, end=94, err=94) debugkey
- print *, "using debugkey =", debugkey
-94 continue
+ read(env, *, end=96, err=96) debugkey
+ print *, "env LTDEBUG =", debugkey
+96 continue
call getenv("LTRANGE", env)
debugfrom = 0
debugto = 2**30
i = index(env, '-')
if( i .eq. 0 ) then
- read(env, *, end=95, err=95) debugfrom
+ read(env, *, end=97, err=97) debugfrom
debugto = debugfrom
else
- read(env(1:i-1), *, end=951, err=951) debugfrom
-951 read(env(i+1:), *, end=952, err=952) debugto
-952 continue
+ read(env(1:i-1), *, end=971, err=971) debugfrom
+971 read(env(i+1:), *, end=972, err=972) debugto
+972 continue
endif
- print *, "using debugrange =", debugfrom, debugto
-95 continue
+ print *, "env LTRANGE =", debugfrom, debugto
+97 continue
call getenv("LTWARN", env)
warndigits = 9
- read(env, *, end=96, err=96) warndigits
- print *, "using warndigits =", warndigits
-96 continue
+ read(env, *, end=98, err=98) warndigits
+ print *, "env LTWARN =", warndigits
+98 continue
call getenv("LTERR", env)
errdigits = 100
- read(env, *, end=97, err=97) errdigits
- print *, "using errdigits =", errdigits
-97 continue
+ read(env, *, end=99, err=99) errdigits
+ print *, "env LTERR =", errdigits
+99 continue
*
* regularization parameters
*
call getenv("LTDELTA", env)
delta = 0
read(env, *, end=100, err=100) delta
- print *, "using delta =", delta
+ print *, "env LTDELTA =", delta
100 continue
call getenv("LTMUDIM", env)
- mudim = 1
+ mudimc = 1
read(env, *, end=101, err=101) mudim
- print *, "using mudim =", mudim
+ print *, "env LTMUDIM =", mudim
101 continue
call getenv("LTLAMBDA", env)
lambda = 1
+ epsi = 0
read(env, *, end=102, err=102) lambda
- print *, "using lambda =", lambda
+ print *, "env LTLAMBDA =", lambda
+ call setlambda(lambda)
102 continue
+
+ call getenv("LTUVDIV", env)
+ uvdiv = 1
+ read(env, *, end=103, err=103) uvdiv
+ print *, "env LTUVDIV =", uvdiv
+103 continue
*
* #] LoopTools stuff
* #[ precision etc:
nevent = -1
*
* the loss of accuracy in any single subtraction at which
* (timeconsuming) corrective action is to be taken is
*
xloss = 0.125D0
*
* the precision to which real calculations are done is
*
precx = 1
sold = 0
do 1 i=1,1000
precx = precx/2
call ffset(s, 1 + precx)
s = exp(log(s))
if ( s .eq. sold ) goto 2
sold = s
1 continue
2 continue
precx = precx*8
* (take three bits for safety)
*
* the precision to which complex calculations are done is
*
precc = 1
sold = 0
do 3 i=1,1000
precc = precc/2
call ffset(s, 1 + precc)
- cs = exp(log(DCMPLX(s)))
- if ( DBLE(cs) .eq. sold ) goto 4
- sold = DBLE(cs)
+ cs = exp(log(ToComplex(s)))
+ if ( Re(cs) .eq. sold ) goto 4
+ sold = Re(cs)
3 continue
4 continue
precc = precc*8
* (take three bits for safety)
*
* for efficiency take them equal if they are not too different
*
if ( precx/precc .lt. 4 .and. precx/precc .gt. .25 ) then
precx = max(precc,precx)
precc = max(precc,precx)
endif
*
* and the minimum value the logarithm accepts without complaining
-* about arguments zero is (DOUBLE PRECISION cq DOUBLE COMPLEX)
+* about arguments zero is (RealType cq ComplexType)
*
s = 1
xalogm = 1
do 5 i=1,10000
call ffset(s, s/2)
if ( 2*s .ne. xalogm ) goto 6
xalogm = s
5 continue
6 continue
if ( xalogm.eq.0 ) xalogm = 1d-307
s = 1
- xclogm = abs(DCMPLX(s))
+ xclogm = abs(ToComplex(s))
do 7 i=1,10000
call ffset(s, s/2)
- if ( 2*abs(DCMPLX(s)) .ne. xclogm ) goto 8
- xclogm = abs(DCMPLX(s))
+ if ( 2*abs(ToComplex(s)) .ne. xclogm ) goto 8
+ xclogm = abs(ToComplex(s))
7 continue
8 continue
if ( xclogm.eq.0 ) xclogm = 1d-307
*
* These values are for Absoft, Apollo fortran (68000):
* xalogm = 1.D-308
* xclogm = 1.D-18
* These values are for VAX g_float
* xalogm = 1.D-308
* xclogm = 1.D-308
* These values are for Gould fort (because of div_zz)
* xalogm = 1.D-75
* xclogm = 1.D-36
xalog2 = sqrt(xalogm)
xclog2 = sqrt(xclogm)
* #] precision etc:
* #[ constants:
*
* calculate the coefficients of the series expansion
* li2(x) = sum bn*z^n/(n+1)!, z = -log(1-x), bn are the
* bernouilli numbers (zero for odd n>1).
*
bf(1) = - 1.D+0/4.D+0
bf(2) = + 1.D+0/36.D+0
bf(3) = - 1.D+0/36.D+2
bf(4) = + 1.D+0/21168.D+1
bf(5) = - 1.D+0/108864.D+2
bf(6) = + 1.D+0/52690176.D+1
bf(7) = - 691.D+0/16999766784.D+3
bf(8) = + 1.D+0/1120863744.D+3
bf(9) = - 3617.D+0/18140058832896.D+4
bf(10) = + 43867.D+0/97072790126247936.D+3
bf(11) = - 174611.D+0/168600109166641152.D+5
bf(12) = + 77683.D+0/32432530090601152512.D+4
bf(13) = - 236364091.D+0/4234560341829359173632.D+7
bf(14) = + 657931.D+0/5025632054039239458816.D+6
bf(15) = - 3392780147.D+0/109890470493622010006470656.D+7
bf(16)=+172.3168255201D+0/2355349904102724211909.3102313472D+6
bf(17)=-770.9321041217D+0/4428491985594062112714.2791446528D+8
bf(18)=( 0.4157635644614046176D-28)
bf(19)=(-0.9962148488284986022D-30)
bf(20)=( 0.2394034424896265390D-31)
*
* inverses of integers:
*
do 10 i=1,30
xninv(i) = 1D0/i
xn2inv(i) = 1D0/(i*i)
10 continue
*
* inverses of faculties of integers:
*
xinfac(1) = 1D0
do 20 i=2,30
xinfac(i) = xinfac(i-1)/i
20 continue
*
* inx: p(inx(i,j)) = isgn(i,j)*(s(i)-s(j))
*
inx(1,1) = -9999
inx(2,1) = 5
inx(3,1) = 9
inx(4,1) = 8
inx(1,2) = 5
inx(2,2) = -9999
inx(3,2) = 6
inx(4,2) = 10
inx(1,3) = 9
inx(2,3) = 6
inx(3,3) = -9999
inx(4,3) = 7
inx(1,4) = 8
inx(2,4) = 10
inx(3,4) = 7
inx(4,4) = -9999
isgn(1,1) = -9999
isgn(2,1) = +1
isgn(3,1) = -1
isgn(4,1) = -1
isgn(1,2) = -1
isgn(2,2) = -9999
isgn(3,2) = +1
isgn(4,2) = +1
isgn(1,3) = +1
isgn(2,3) = -1
isgn(3,3) = -9999
isgn(4,3) = +1
isgn(1,4) = +1
isgn(2,4) = -1
isgn(3,4) = -1
isgn(4,4) = -9999
do 40 i=1,12
do 30 j=1,13
iold(j,i) = ioldp(j,i)
30 continue
do 35 j=1,10
isgrot(j,i) = isgrop(j,i)
35 continue
40 continue
inx5(1,1) = -9999
inx5(1,2) = 6
inx5(1,3) = 11
inx5(1,4) = 14
inx5(1,5) = 10
inx5(2,1) = 6
inx5(2,2) = -9999
inx5(2,3) = 7
inx5(2,4) = 12
inx5(2,5) = 15
inx5(3,1) = 11
inx5(3,2) = 7
inx5(3,3) = -9999
inx5(3,4) = 8
inx5(3,5) = 13
inx5(4,1) = 14
inx5(4,2) = 12
inx5(4,3) = 8
inx5(4,4) = -9999
inx5(4,5) = 9
inx5(5,1) = 10
inx5(5,2) = 15
inx5(5,3) = 13
inx5(5,4) = 9
inx5(5,5) = -9999
* isgn5 is not yet used.
do i=1,5
do j=1,5
isgn5(i,j) = -9999
enddo
enddo
*
inx6(1,1) = -9999
inx6(1,2) = 7
inx6(1,3) = 13
inx6(1,4) = 19
inx6(1,5) = 17
inx6(1,6) = 12
inx6(2,1) = 7
inx6(2,2) = -9999
inx6(2,3) = 8
inx6(2,4) = 14
inx6(2,5) = 20
inx6(2,6) = 18
inx6(3,1) = 13
inx6(3,2) = 8
inx6(3,3) = -9999
inx6(3,4) = 9
inx6(3,5) = 15
inx6(3,6) = 21
inx6(4,1) = 19
inx6(4,2) = 14
inx6(4,3) = 9
inx6(4,4) = -9999
inx6(4,5) = 10
inx6(4,6) = 16
inx6(5,1) = 17
inx6(5,2) = 20
inx6(5,3) = 15
inx6(5,4) = 10
inx6(5,5) = -9999
inx6(5,6) = 11
inx6(6,1) = 12
inx6(6,2) = 18
inx6(6,3) = 21
inx6(6,4) = 16
inx6(6,5) = 11
inx6(6,6) = -9999
* isgn6 is used.
do i=1,6
do j=1,6
ji = j-i
if ( ji.gt.+3 ) ji = ji - 6
if ( ji.lt.-3 ) ji = ji + 6
if ( ji.eq.0 ) then
isgn6(j,i) = -9999
elseif ( abs(ji).eq.3 ) then
if ( i.lt.0 ) then
isgn6(j,i) = -1
else
isgn6(j,i) = +1
endif
elseif ( ji.gt.0 ) then
isgn6(j,i) = +1
elseif ( ji.lt.0 ) then
isgn6(j,i) = -1
else
- print *,'ffini: internal error in isgn6'
+ print *,'ltini: internal error in isgn6'
stop
endif
enddo
enddo
*
* #] constants:
* #[ defaults for flags:
nevent = 0
*
* the debugging flags.
*
ldc3c4 = .FALSE.
l4also = .FALSE.
lmem = .FALSE.
ldot = .FALSE.
idot = 0
*
* Specify which root to take in cases were two are possible
* it may be advantageous to change this to -1 (debugging hook)
*
isgn34 = 1
isgnal = 1
*
* the scheme used for the complex scalar functions:
*
* nschem = 1: do not use the complex mass at all
* 2: only use the complex mass in linearly divergent terms
* 3: also use the complex mass in divergent logs UNDEFINED
* 4: use the complex mass in the C0 if there are
* divergent logs
* 5: include the almost-divergent threshold terms from
* (m,m,0) vertices
* 6: include the (s-m^2)*log(s-m^2) threshold terms from
* (m1+m2),m1,m2) vertices
* 7: full complex computation
* (only in the ffz... functions):
* onshel = .FALSE.: use the offshell p^2 everywhere
* .TRUE.: use the onshell p^2 except in complex parts
*
nschem = 7
onshel = .TRUE.
*
* the precision wanted in the complex D0 (and hence E0) when
* nschem=7, these are calculated via Taylor expansion in the real
* one and hence expensive.
*
reqprc = 1.D-8
*
* in some schemes, for onshel=.FALSE.,
* when |p^2-Re(m^2)| < nwidth*|Im(m^2)| special action is taken
*
nwidth = 5
*
* a flag to indicate the validity of differences smuggled to the
* IR routines in the C0 (ff internal only)
*
lsmug = .FALSE.
*
* #] defaults for flags:
-*###] ffini:
+*###] ltini:
end
*###[ ffexi:
subroutine ltexi
***#[*comment:***********************************************************
* check a lot of commonly-used constants in the common block *
* /ffcnst/. *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
integer i,ier
#include "ff.h"
* #] declarations:
* #[ checks:
*
* calculate the coefficients of the series expansion
* li2(x) = sum bn*z^n/(n+1)!, z = -log(1-x), bn are the
* bernouilli numbers (zero for odd n>1).
*
if ( bf(1) .ne. - 1.D+0/4.D+0 )
+ print *,'ffexi: error: bf(1) is corrupted'
if ( bf(2) .ne. + 1.D+0/36.D+0 )
+ print *,'ffexi: error: bf(2) is corrupted'
if ( bf(3) .ne. - 1.D+0/36.D+2 )
+ print *,'ffexi: error: bf(3) is corrupted'
if ( bf(4) .ne. + 1.D+0/21168.D+1 )
+ print *,'ffexi: error: bf(4) is corrupted'
if ( bf(5) .ne. - 1.D+0/108864.D+2 )
+ print *,'ffexi: error: bf(5) is corrupted'
if ( bf(6) .ne. + 1.D+0/52690176.D+1 )
+ print *,'ffexi: error: bf(6) is corrupted'
if ( bf(7) .ne. - 691.D+0/16999766784.D+3 )
+ print *,'ffexi: error: bf(7) is corrupted'
if ( bf(8) .ne. + 1.D+0/1120863744.D+3 )
+ print *,'ffexi: error: bf(8) is corrupted'
if ( bf(9) .ne. - 3617.D+0/18140058832896.D+4 )
+ print *,'ffexi: error: bf(9) is corrupted'
if ( bf(10) .ne. + 43867.D+0/97072790126247936.D+3 )
+ print *,'ffexi: error: bf(10) is corrupted'
if ( bf(11) .ne. - 174611.D+0/168600109166641152.D+5 )
+ print *,'ffexi: error: bf(11) is corrupted'
if ( bf(12) .ne. + 77683.D+0/32432530090601152512.D+4 )
+ print *,'ffexi: error: bf(12) is corrupted'
if ( bf(13) .ne. - 236364091.D+0/4234560341829359173632.D+7 )
+ print *,'ffexi: error: bf(13) is corrupted'
if ( bf(14) .ne. + 657931.D+0/5025632054039239458816.D+6 )
+ print *,'ffexi: error: bf(14) is corrupted'
if ( bf(15) .ne. -3392780147.D+0/109890470493622010006470656.D+7
+ ) print *,'ffexi: error: bf(15) is corrupted'
if ( bf(16).ne.+172.3168255201D+0/2355349904102724211909.3102313
+ 472D+6 )
+ print *,'ffexi: error: bf(16) is corrupted'
if ( bf(17).ne.-770.9321041217D+0/4428491985594062112714.2791446
+ 528D+8 )
+ print *,'ffexi: error: bf(17) is corrupted'
if ( bf(18).ne.( 0.4157635644614046176D-28) )
+ print *,'ffexi: error: bf(18) is corrupted'
if ( bf(19).ne.(-0.9962148488284986022D-30) )
+ print *,'ffexi: error: bf(19) is corrupted'
if ( bf(20).ne.( 0.2394034424896265390D-31) )
+ print *,'ffexi: error: bf(20) is corrupted'
*
* inverses of integers:
*
do 10 i=1,20
if ( abs(xninv(i)-1D0/i) .gt. precx*xninv(i) ) print *,
+ 'ffexi: error: xninv(',i,') is not 1/',i,': ',
+ xninv(i),xninv(i)-1D0/i
10 continue
*
* #] checks:
* #[ print summary of errors and warning:
ier = 0
call fferr(999,ier)
* #] print summary of errors and warning:
*###] ffexi:
end
*###[ fferr:
subroutine fferr(nerr,ierr)
***#[*comment:***********************************************************
* *
* generates an error message #nerr with severity 2 *
* nerr=999 gives a frequency listing of all errors *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
integer nmax
parameter (nmax=105)
integer nerr,ierr
integer noccur(nmax),i,inone,nnerr
save error,noccur
#include "ff.h"
#include "fferr.h"
* #] declarations:
* #[ data:
data noccur /nmax*0/
* #] data:
* #[ nerr=999:
if ( nerr .eq. 999 ) then
* print out total numbers...
print '(a)',' '
print '(a)','total number of errors and warnings'
print '(a)','==================================='
inone = 1
do 10 i = 1, nmax
if ( noccur(i) .gt. 0 ) then
print '(a,i5,a,a)','fferr: ',noccur(i),
+ ' times ',error(i)
noccur(i) = 0
inone = 0
endif
10 continue
if ( inone.eq.1 ) print '(a)','fferr: no errors'
print '(a)',' '
return
endif
* #] nerr=999:
* #[ print error:
if ( nerr .lt. 1 .or. nerr .gt. nmax ) then
nnerr = nmax
else
nnerr = nerr
endif
noccur(nnerr) = noccur(nnerr) + 1
ierr = ierr + 100
print '(a,a)', 'error in ', error(nnerr)
* #] print error:
*###] fferr:
end
*###[ ffwarn:
subroutine ffwarn(nerr,ierr,som,xmax)
***#[*comment:***********************************************************
* *
* The warning routine. A warning is aloss of precision greater *
-* than xloss (which is default set in ffini), whenever in a *
+* than xloss (which is default set in ltini), whenever in a *
* subtraction the result is smaller than xloss*max(operands) this *
* routine is called. Now the strategy is to remember these *
* warnings until a 998 message is obtained; then all warnings of *
* the previous event are printed. The rationale is that one *
* makes this call if too much preciasion is lost only. *
* nerr=999 gives a frequency listing of all warnings *
* *
* Input: nerr integer the id of the warning message, see the *
* file ffwarn.h or 998 or 999 *
* ierr integer the usual error flag: number of digits *
* lost so far *
* som real the result of the addition *
* xmax real the largest operand *
* *
* Output: ierr integer is raised by the number of digits lost *
* the tolerated loss of xloss *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
integer nmax
parameter (nmax=300)
*
* arguments
*
integer nerr,ierr
- DOUBLE PRECISION som,xmax
+ RealType som,xmax
*
* local variables
*
integer memmax
parameter (memmax = 1000)
integer noccur(nmax),i,inone,nnerr,ilost,
+ nermem(memmax),losmem(memmax),idmem(memmax),
+ idsmem(memmax),laseve,imem
- DOUBLE PRECISION xlosti(nmax),xlost
+ RealType xlosti(nmax),xlost
save warn,noccur,xlosti,nermem,losmem,idmem,idsmem,
+ laseve,imem
*
* common blocks
*
#include "ff.h"
#include "ffwarn.h"
* #] declarations:
* #[ data:
data noccur /nmax*0/
* #] data:
* #[ nerr=999:
if ( nerr.eq.999 ) then
* print out total numbers...
inone = 1
do 10 i=1,nmax
if ( noccur(i) .gt. 0 ) then
print '(a,i8,a,i3,a,a)','ffwarn: ',noccur(i),
+ ' times ',i,': ',warn(i)
print '(a,g12.3,a)',
+ ' (lost at most a factor ',xlosti(i),')'
noccur(i) = 0
xlosti(i) = 0
inone = 0
endif
10 continue
if ( inone.eq.1 ) print '(a)','ffwarn: no warnings'
return
endif
* #] nerr=999:
* #[ print warning:
if ( nerr .eq. 998 ) then
if ( nevent .ne. laseve ) return
do 20 i=1,imem-1
if ( nermem(i).ne.0 ) then
print '(a,a)','warning in ',warn(nermem(i))
print '(a,i3,a)',' (lost ',losmem(i),' digits)'
endif
20 continue
imem = 1
return
endif
* #] print warning:
* #[ collect warnings:
*
* bring in range
*
if ( nerr .lt. 1 .or. nerr .gt. nmax ) then
nnerr = nmax
else
nnerr = nerr
endif
*
* bookkeeping
*
noccur(nnerr) = noccur(nnerr) + 1
if ( som .ne. 0 ) then
xlost = abs(xmax/som)
elseif ( xmax .ne. 0 ) then
xlost = 1/precx
else
xlost = 1
endif
xlosti(nnerr) = max(xlosti(nnerr),xlost)
if ( xlost*xloss .gt. xalogm ) then
ilost = 1 + int(abs(log10(xlost*xloss)))
else
ilost = 0
endif
ierr = ierr + ilost
*
* nice place to stop when debugging
*
if ( ilost.ge.10 ) then
ilost = ilost + 1
endif
*
* add to memory
*
if ( laseve .ne. nevent ) then
imem = 1
laseve = nevent
endif
if ( imem .le. memmax ) then
idmem(imem) = id
idsmem(imem) = idsub
nermem(imem) = nerr
losmem(imem) = ilost
imem = imem + 1
endif
* #] collect warnings:
*###] ffwarn:
end
*###[ ffbnd:
- DOUBLE PRECISION function ffbnd(n1,n2,array)
+ RealType function ffbnd(n1,n2,array)
*************************************************************************
* *
* calculate bound = (precx*|a(n1)/a(n1+n2)|^(1/n2) which is the *
* maximum value of x in a series expansion sum_(i=n1)^(n1+n2) *
* a(i)*x(i) to give a result of accuracy precx (actually of |next *
* term| < prec *
* *
*************************************************************************
implicit none
integer n1,n2
- DOUBLE PRECISION array(n1+n2)
+ RealType array(n1+n2)
#include "ff.h"
if ( array(n1+n2) .eq. 0 ) then
print *,'ffbnd: fatal: array not initialized; did you call ',
- + 'ffini?'
+ + 'ltini?'
stop
endif
- ffbnd = (precx*abs(array(n1)/array(n1+n2)))**(1/DBLE(n2))
+ ffbnd = (precx*abs(array(n1)/array(n1+n2)))**(1/Re(n2))
+* added 22 Mar 11: be a bit more conservative:
+ ffbnd = .8D0*ffbnd
*###] ffbnd:
end
*###[ ffroot:
subroutine ffroot(xm,xp,a,b,c,d,ier)
***#[*comment:***********************************************************
* *
* Calculate the roots of the equation *
* a*x^2 - 2*b*x + c = 0 *
* given by *
* x = (b +/- d )/a xp*xm = c/a *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ier
- DOUBLE PRECISION xm,xp,a,b,c,d
+ RealType xm,xp,a,b,c,d
*
* common blocks:
*
#include "ff.h"
* #] declarations:
* #[ check input:
if ( a .eq. 0 ) then
call fferr(39,ier)
if ( b.gt.0 .eqv. d.gt.0 ) then
xp = 1/xalogm
xm = c/(b+d)
else
xp = c/(b-d)
xm = 1/xalogm
endif
return
endif
* #] check input:
* #[ calculations:
if ( d .eq. 0 ) then
xm = b / a
xp = xm
elseif ( b .gt. 0 .eqv. d .gt. 0 ) then
xp = ( b + d ) / a
xm = c / (a*xp)
else
xm = ( b - d ) / a
xp = c / (a*xm)
endif
* #] calculations:
*###] ffroot:
end
*###[ ffcoot:
subroutine ffcoot(xm,xp,a,b,c,d,ier)
***#[*comment:***********************************************************
* *
* Calculate the roots of the equation *
* a*x^2 - 2*b*x + c = 0 *
* given by *
* x = (b +/- d )/a xp*xm = c/a *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ier
- DOUBLE COMPLEX xm,xp,a,b,c,d
+ ComplexType xm,xp,a,b,c,d
*
* local variables:
*
- DOUBLE COMPLEX cc
- DOUBLE PRECISION absc
+ ComplexType cc
+ RealType absc
*
* common blocks:
*
#include "ff.h"
*
* statement function
*
- absc(cc) = abs(DBLE(cc)) + abs(DIMAG(cc))
+ absc(cc) = abs(Re(cc)) + abs(Im(cc))
* #] declarations:
* #[ check input:
if ( a .eq. 0 ) then
call fferr(38,ier)
- if ( DBLE(b).gt.0 .eqv. DBLE(d).gt.0 ) then
+ if ( Re(b).gt.0 .eqv. Re(d).gt.0 ) then
xp = 1/xclogm
xm = c/(b+d)
else
xp = c/(b-d)
xm = 1/xclogm
endif
return
endif
* #] check input:
* #[ calculations:
cc = b+d
if ( d .eq. 0 ) then
xm = b / a
xp = xm
elseif ( absc(cc) .gt. xloss*absc(d) ) then
xp = ( b + d ) / a
xm = c / (a*xp)
else
xm = ( b - d ) / a
xp = c / (a*xm)
endif
* #] calculations:
*###] ffcoot:
end
*###[ ffxhck:
subroutine ffxhck(xpi,dpipj,ns,ier)
***#[*comment:***********************************************************
* *
* check whether the differences dpipj are compatible with xpi *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
integer ns,ier
- DOUBLE PRECISION xpi(ns),dpipj(ns,ns)
+ RealType xpi(ns),dpipj(ns,ns)
integer i,j
- DOUBLE PRECISION xheck,rloss
+ RealType xheck,rloss
#include "ff.h"
* #] declarations:
* #[ calculations:
if ( ier.lt.0 ) then
print *,'ffxhck: error: ier < 0 ',ier
ier=0
endif
- rloss = xloss**2*DBLE(10)**(-mod(ier,50))
+ rloss = xloss**2*Re(10)**(-mod(ier,50))
do 20 i=1,ns
do 10 j=1,ns
xheck = dpipj(j,i) - xpi(j) + xpi(i)
if ( rloss*abs(xheck) .gt. precx*max(abs(dpipj(j,i)),
+ abs(xpi(j)),abs(xpi(i))) ) then
print *,'ffxhck: error: dpipj(',j,i,') <> xpi(',j,
+ ') - xpi(',i,'):',dpipj(j,i),xpi(j),xpi(i),
+ xheck,ier
endif
10 continue
20 continue
* #] calculations:
*###] ffxhck:
end
*###[ ffchck:
subroutine ffchck(cpi,cdpipj,ns,ier)
***#[*comment:***********************************************************
* *
* check whether the differences cdpipj are compatible with cpi *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
integer ns,ier
- DOUBLE COMPLEX cpi(ns),cdpipj(ns,ns),c
+ ComplexType cpi(ns),cdpipj(ns,ns),c
integer i,j
- DOUBLE COMPLEX check
- DOUBLE PRECISION absc,rloss
+ ComplexType check
+ RealType absc,rloss
#include "ff.h"
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
* #] declarations:
* #[ calculations:
if ( ier.lt.0 ) then
print *,'ffchck: error: ier < 0 ',ier
ier=0
endif
- rloss = xloss**2*DBLE(10)**(-mod(ier,50))
+ rloss = xloss**2*Re(10)**(-mod(ier,50))
do 20 i=1,ns
do 10 j=1,ns
check = cdpipj(j,i) - cpi(j) + cpi(i)
if ( rloss*absc(check) .gt. precc*max(absc(
+ cdpipj(j,i)),absc(cpi(j)),absc(cpi(i))) ) then
print *,'ffchck: error: cdpipj(',j,i,') <> cpi(',j,
+ ') - cpi(',i,'):',cdpipj(j,i),cpi(j),cpi(i),
+ check,ier
endif
10 continue
20 continue
* #] calculations:
*###] ffchck:
end
*###[ nffeta:
integer function nffeta(ca,cb,ier)
***#[*comment:***********************************************************
* calculates *
* *
* eta(a,b)/(2*i*pi) = ( thIm(-a)*thIm(-b)*thIm(a*b) *
* - thIm(a)*thIm(b)*thIm(-a*b) ) *
* *
* with thIm(a) = theta(Im(a)) *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
integer ier
- DOUBLE COMPLEX ca,cb
- DOUBLE PRECISION a,b,ab,rab
+ ComplexType ca,cb
+ RealType a,b,ab,rab
#include "ff.h"
* #] declarations:
* #[ calculations:
- a = DIMAG(ca)
- b = DIMAG(cb)
+ a = Im(ca)
+ b = Im(cb)
if ( a*b .lt. 0 ) then
nffeta = 0
return
endif
- rab = DBLE(ca)*DBLE(cb) - a*b
- ab = DBLE(ca)*b + a*DBLE(cb)
- if ( abs(ab) .lt. precc*abs(DBLE(ca)*b) ) then
+ rab = Re(ca)*Re(cb) - a*b
+ ab = Re(ca)*b + a*Re(cb)
+ if ( abs(ab) .lt. precc*abs(Re(ca)*b) ) then
call fferr(32,ier)
endif
if ( a .lt. 0 .and. b .lt. 0 .and. ab .gt. 0 ) then
nffeta = 1
elseif ( a .gt. 0 .and. b .gt. 0 .and. ab .lt. 0 ) then
nffeta = -1
- elseif ( a .eq. 0 .and. DBLE(ca) .le. 0 .or.
- + b .eq. 0 .and. DBLE(cb) .le. 0 .or.
+ elseif ( a .eq. 0 .and. Re(ca) .le. 0 .or.
+ + b .eq. 0 .and. Re(cb) .le. 0 .or.
+ ab .eq. 0 .and. rab .le. 0 ) then
call fferr(32,ier)
nffeta = 0
else
nffeta = 0
endif
* #] calculations:
*###] nffeta:
end
*###[ nffet1:
integer function nffet1(ca,cb,cc,ier)
***#[*comment:***********************************************************
* calculates the same eta with three input variables *
* *
* et1(a,b)/(2*i*pi) = ( thIm(-a)*thIm(-b)*thIm(c) *
* - thIm(a)*thIm(b)*thIm(-c) ) *
* *
* with thIm(a) = theta(Im(a)) *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
integer ier
- DOUBLE COMPLEX ca,cb,cc
- DOUBLE PRECISION a,b,ab
+ ComplexType ca,cb,cc
+ RealType a,b,ab
#include "ff.h"
* #] declarations:
* #[ calculations:
- a = DIMAG(ca)
- b = DIMAG(cb)
+ a = Im(ca)
+ b = Im(cb)
if ( a .gt. 0 .neqv. b .gt. 0 ) then
nffet1 = 0
return
endif
- ab = DIMAG(cc)
+ ab = Im(cc)
if ( a .lt. 0 .and. b .lt. 0 .and. ab .gt. 0 ) then
nffet1 = 1
elseif ( a .gt. 0 .and. b .gt. 0 .and. ab .lt. 0 ) then
nffet1 = -1
- elseif ( a .eq. 0 .and. DBLE(ca) .le. 0 .or.
- + b .eq. 0 .and. DBLE(cb) .le. 0 .or.
- + ab .eq. 0 .and. DBLE(cc) .le. 0 ) then
+ elseif ( a .eq. 0 .and. Re(ca) .le. 0 .or.
+ + b .eq. 0 .and. Re(cb) .le. 0 .or.
+ + ab .eq. 0 .and. Re(cc) .le. 0 ) then
call fferr(33,ier)
nffet1 = 1
else
nffet1 = 0
endif
* #] calculations:
*###] nffet1:
end
*###[ ffcayl:
subroutine ffcayl(cs,z,coeff,n,ier)
***#[*comment:***********************************************************
* *
* Do a Taylor expansion in z with real coefficients coeff(i) *
* *
* Input: z complex *
* coeff(n) real *
* n integer *
* *
* Output cs complex \sum_{i=1} z^i coeff(i) *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer n,ier
- DOUBLE PRECISION coeff(n)
- DOUBLE COMPLEX z,cs
+ RealType coeff(n)
+ ComplexType z,cs
*
* local variables
*
integer i
- DOUBLE PRECISION absc
- DOUBLE COMPLEX c,zi,csi
+ RealType absc
+ ComplexType c,zi,csi
*
* common blocks
*
#include "ff.h"
*
* statement function
*
- absc(c) = abs(DBLE(c)) + abs(DIMAG(c))
+ absc(c) = abs(Re(c)) + abs(Im(c))
*
* #] declarations:
* #[ work:
- cs = z*DBLE(coeff(1))
+ cs = z*Re(coeff(1))
if ( absc(z) .lt. precc ) return
zi = z
do 10 i=2,n
zi = zi*z
- csi = zi*DBLE(coeff(i))
+ csi = zi*Re(coeff(i))
cs = cs + csi
if ( absc(csi) .lt. precc*absc(cs) ) goto 20
10 continue
call ffwarn(9,ier,precc,absc(csi))
20 continue
* #] work:
*###] ffcayl:
end
*###[ fftayl:
subroutine fftayl(s,z,coeff,n,ier)
***#[*comment:***********************************************************
* *
* Do a Taylor expansion in z with real coefficients coeff(i) *
* *
* Input: z real *
* coeff(n) real *
* n integer *
* *
* Output cs real \sum_{i=1} z^i coeff(i) *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer n,ier
- DOUBLE PRECISION coeff(n),z,s
+ RealType coeff(n),z,s
*
* local variables
*
integer i
- DOUBLE PRECISION zi,si
+ RealType zi,si
*
* common blocks
*
#include "ff.h"
*
* #] declarations:
* #[ work:
s = coeff(1)*z
if ( abs(z) .lt. precx ) return
zi = z
do 10 i=2,n
zi = zi*z
si = coeff(i)*zi
s = s + si
if ( abs(si) .lt. precx*abs(s) ) goto 20
10 continue
call ffwarn(9,ier,precx,si)
20 continue
* #] work:
*###] fftayl:
end
diff --git a/Looptools/util/fftran.F b/Looptools/util/fftran.F
--- a/Looptools/util/fftran.F
+++ b/Looptools/util/fftran.F
@@ -1,817 +1,818 @@
#include "externals.h"
+#include "types.h"
*###[ ffai:
subroutine ffai(ai,daiaj,aai,laai,del2s,sdel2s,xpi,dpipj,piDpj,
+ ier)
***#[*comment:***********************************************************
* *
* calculates the coefficients of the projective transformation *
* *
* xi = ai*ui / (som aj*uj ) *
* *
* such that the coefficients of z^2, z*x and z*y vanish: *
* *
* a2/a1 = ( lij +/- lam1/2(xp1,xm1,xm2) ) / (2*xm2) *
* a3 = ( xm2*a2 - xm1*a1 ) / ( xl23*a2 - xl13*a1 ) *
* a4 = ( xm2*a2 - xm1*a1 ) / ( xl24*a2 - xl14*a1 ) *
* *
* the differences ai-aj = daiaj(i,j) are also evaluated. *
* *
* Input: del2s real delta(s3,s4,s3,s4) *
* sdel2s real sqrt(-del2s) *
* xpi(10) real masses, momenta^2 *
* dpipj(10,10 real xpi(i) - xpi(j) *
* piDpj(10,10) real dotproducts *
* *
* Output: ai(4) real Ai of the transformation *
* daiaj(4,4) real Ai-Aj *
* aai(4) real the other roots *
* laai logical if .TRUE. aai are defined *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
logical laai
- DOUBLE PRECISION ai(4),daiaj(4,4),aai(4),del2s,sdel2s,xpi(10),
+ RealType ai(4),daiaj(4,4),aai(4),del2s,sdel2s,xpi(10),
+ dpipj(10,10),piDpj(10,10)
*
* local variables
*
integer i,j,ier0,ier1,ier2
- DOUBLE PRECISION del2sa,del2sb,del3mi(2),aim(4),aaim(4),delps,
+ RealType del2sa,del2sb,del3mi(2),aim(4),aaim(4),delps,
+ del3m(1),dum,da2a1m,da1a3m,da1a4m,da2a3m,da2a4m,da3a4m
* for debugging purposes
- DOUBLE COMPLEX ca1m
+ ComplexType ca1m
*
* common blocks
*
#include "ff.h"
*
* #] declarations:
* #[ get ai:
*
* A4: some arbitrary normalisation ...
*
ai(4) = 1
aai(4) = 1
ier2 = ier
if ( del2s .ne. 0 ) then
*
* A3: simple solution of quadratic equation
*
ier0 = ier
call ffroot(aaim(3),aim(3),xpi(4),piDpj(4,3),xpi(3),
+ sdel2s,ier0)
ier2 = max(ier2,ier0)
if ( aim(3) .eq. 0 ) then
* choose the other root
ier = ier + 100
return
endif
ai(3) = ai(4)/aim(3)
if ( aaim(3) .ne. 0 ) then
laai = .TRUE.
aai(3) = aai(4)/aaim(3)
else
laai = .FALSE.
endif
*
* A2: a bit more complicated quadratic equation
*
ier1 = ier
ier0 = ier
call ffdl2s(del2sa,piDpj, 2,4,10,1, 3,4,7,1, 10)
ier1 = max(ier1,ier0)
ier0 = ier
call ffdl3m(del3mi(2),.FALSE.,0D0,0D0,xpi,dpipj,piDpj,10,
+ 3,4,7, 2,1)
ier1 = max(ier1,ier0)
call ffroot(aim(2),aaim(2),xpi(4),piDpj(4,2),del3mi(2)/del2s
+ ,del2sa/sdel2s,ier1)
ier2 = max(ier2,ier1)
if ( aim(2) .eq. 0 ) then
ier = ier + 100
return
endif
ai(2) = ai(4)/aim(2)
if ( laai ) then
if ( aaim(2) .eq. 0 ) then
laai = .FALSE.
else
aai(2) = aai(4)/aaim(2)
endif
endif
*
* A1: same as A2, except for the special nasty case.
*
if ( .not.lnasty ) then
ier0 = ier
ier1 = ier
call ffdl2s(del2sb,piDpj, 1,4,8,-1, 3,4,7,1, 10)
ier1 = max(ier1,ier0)
ier0 = ier
call ffdl3m(del3mi(1),.FALSE.,0D0,0D0,xpi,dpipj,piDpj,10,
+ 3,4,7, 1,1)
ier1 = max(ier1,ier0)
call ffroot(aim(1),aaim(1),xpi(4),piDpj(4,1),del3mi(1)/del2s
+ ,del2sb/sdel2s,ier1)
ier2 = max(ier2,ier1)
if ( aim(1) .eq. 0 ) then
ier = ier + 100
return
endif
ai(1) = ai(4)/aim(1)
if ( laai ) then
if ( aaim(1) .eq. 0 ) then
laai = .FALSE.
else
aai(1) = aai(4)/aaim(1)
endif
endif
else
laai = .FALSE.
- ca1m = (c2sisj(1,4) - (c2sisj(1,3)*DBLE(xpi(4)) -
- + c2sisj(1,4)*DBLE(piDpj(3,4)))/DBLE(sdel2s))/
- + DBLE(2*xpi(4))
- ca1 = DBLE(ai(4))/ca1m
- ai(1) = ai(4)/DBLE(ca1m)
+ ca1m = (c2sisj(1,4) - (c2sisj(1,3)*Re(xpi(4)) -
+ + c2sisj(1,4)*Re(piDpj(3,4)))/Re(sdel2s))/
+ + Re(2*xpi(4))
+ ca1 = Re(ai(4))/ca1m
+ ai(1) = ai(4)/Re(ca1m)
endif
else
*
* the special case del2s=0 with xpi(3)=xpi(4),xpi(7)=0
*
laai = .FALSE.
ai(3) = ai(4)
if ( piDpj(7,2) .eq. 0 .or. piDpj(7,1) .eq. 0 ) then
call fferr(55,ier)
return
endif
ai(2) = ai(4)*xpi(3)/piDpj(7,2)
ai(1) = ai(4)*xpi(3)/piDpj(7,1)
endif
ier = ier2
* #] get ai:
* #[ get daiaj:
ier2 = ier
do 120 i=1,4
daiaj(i,i) = 0
do 110 j=i+1,4
daiaj(j,i) = ai(j) - ai(i)
if ( abs(daiaj(j,i)) .ge. xloss*abs(ai(i)) ) goto 105
if ( del2s .eq. 0 ) then
* #[ del2s=0:
if ( i .eq. 1 .and. j .eq. 2 ) then
daiaj(2,1) = -ai(1)*ai(2)*piDpj(5,7)/xpi(3)
goto 104
elseif ( i .eq. 3 .and. j .eq. 4 ) then
daiaj(4,3) = 0
goto 104
endif
ier1 = ier
call ffwarn(146,ier1,daiaj(j,i),ai(i))
goto 105
* #] del2s=0:
elseif ( lnasty .and. i.eq.1 ) then
ier1 = ier
call ffwarn(146,ier1,daiaj(j,i),ai(i))
goto 105
endif
ier0 = ier
if ( i .eq. 1 .and. j .eq. 2 ) then
* #[ daiaj(2,1):
*
* some determinants (as usual)
*
* as the vertex p1,s4,? does not exist we use ffdl2t
*
call ffdl2t(delps,piDpj, 5,4, 3,4,7,1,+1, 10)
ier1 = max(ier1,ier0)
ier0 = ier
call ffdl3m(del3m,.FALSE.,0D0,0D0,xpi,dpipj,piDpj,
+ 10, 3,4,7, 5,1)
ier1 = max(ier1,ier0)
call ffroot(dum,da2a1m,xpi(4),piDpj(4,5),
+ del3m(1)/del2s,-delps/sdel2s,ier1)
daiaj(2,1) = -ai(1)*ai(2)*da2a1m
goto 104
* #] daiaj(2,1):
elseif ( i .eq. 1 .and. j .eq. 3 ) then
* #[ daiaj(3,1):
*
* Again, the solution of a simple quadratic equation
*
call ffdl2t(delps,piDpj, 9,4, 3,4,7,1,+1, 10)
ier1 = ier0
ier0 = ier
call ffdl3m(del3m,.FALSE.,0D0,0D0,xpi,dpipj,piDpj,
+ 10, 3,4,7, 9,1)
ier1 = max(ier1,ier0)
call ffroot(dum,da1a3m,xpi(4),-piDpj(4,9),
+ del3m(1)/del2s,delps/sdel2s,ier1)
daiaj(3,1) = -ai(1)*ai(3)*da1a3m
goto 104
* #] daiaj(3,1):
elseif ( i .eq. 1 .and. j .eq. 4 ) then
* #[ daiaj(4,1):
*
* Again, the solution of a simple quadratic equation
*
call ffdl2s(delps,piDpj,4,1,8,1,3,4,7,1,10)
ier1 = ier0
ier0 = ier
call ffdl3m(del3m,.FALSE.,0D0,0D0,xpi,dpipj,piDpj,
+ 10, 3,4,7, 8,1)
ier1 = max(ier0,ier1)
call ffroot(dum,da1a4m,xpi(4),piDpj(4,8),del3m(1)/
+ del2s,delps/sdel2s,ier1)
daiaj(4,1) = ai(1)*ai(4)*da1a4m
goto 104
* #] daiaj(4,1):
elseif ( i .eq. 2 .and. j .eq. 3 ) then
* #[ daiaj(3,2):
*
* Again, the solution of a simple quadratic equation
*
call ffdl2t(delps,piDpj, 6,4, 3,4,7,1,+1, 10)
ier1 = ier0
ier0 = ier
call ffdl3m(del3m,.FALSE.,0D0,0D0,xpi,dpipj,piDpj,
+ 10, 3,4,7, 6,1)
ier1 = max(ier1,ier0)
call ffroot(dum,da2a3m,xpi(4),-piDpj(4,6),
+ del3m(1)/del2s,delps/sdel2s,ier1)
daiaj(3,2) = ai(2)*ai(3)*da2a3m
goto 104
* #] daiaj(3,2):
elseif ( i .eq. 2 .and. j .eq. 4 ) then
* #[ daiaj(4,2):
*
* Again, the solution of a simple quadratic equation
*
call ffdl2s(delps,piDpj,2,4,10,1,3,4,7,1,10)
ier1 = ier0
ier0 = ier
call ffdl3m(del3m,.FALSE.,0D0,0D0,xpi,dpipj,piDpj,
+ 10, 3,4,7, 10,1)
ier1 = max(ier0,ier1)
call ffroot(dum,da2a4m,xpi(4),piDpj(4,10),del3m(1)/
+ del2s,delps/sdel2s,ier1)
daiaj(4,2) = -ai(2)*ai(4)*da2a4m
goto 104
* #] daiaj(4,2):
elseif ( i .eq. 3 .and. j .eq. 4 ) then
* #[ daiaj(4,3):
*
* Again, the solution of a very simple quadratic equation
*
ier1 = ier
call ffroot(dum,da3a4m,xpi(4),-piDpj(4,7),
+ xpi(7),sdel2s,ier1)
daiaj(4,3) = ai(3)*ai(4)*da3a4m
goto 104
* #] daiaj(4,3):
endif
104 continue
105 continue
daiaj(i,j) = -daiaj(j,i)
ier2 = max(ier2,ier1)
110 continue
120 continue
ier = ier2
* #] get daiaj:
*###] ffai:
end
*###[ fftran:
subroutine fftran(ai,daiaj,aai,laai,xqi,dqiqj,qiDqj,
+ del2s,sdel2s,xpi,dpipj,piDpj,ier)
***#[*comment:***********************************************************
* *
* Transform the impulses according to *
* *
* ti = Ai*si *
* qij = (Ai*si - Aj*sj) *
* *
* In case del2s=0 it calculates the same coefficients but for *
* for A1,A2 leave out the delta with 2*delta = 1-xpi(4)/xpi(3) *
* infinitesimal. *
* *
* Input: ai(4) ai *
* daiaj(4,4) ai-aj *
* del2s \delta^{s(3) s4}_{s(3) s4} *
* sdel2s sqrt(del2s) *
* xpi(10) masses = s1-s2-s(3)-s4 *
* dpipj(10,10) differences *
* piDpj(10,10) dotproducts *
* *
* Output: xqi(10) transformed momenta *
* dqiqj(10,10) differences *
* qiDqj(10,10) dotproducts *
* ier (integer) 0=ok,1=inaccurate,2=error *
* *
* Calls: ffxlmb,... *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
logical laai
- DOUBLE PRECISION ai(4),daiaj(4,4),aai(4),xqi(10),dqiqj(10,10),
+ RealType ai(4),daiaj(4,4),aai(4),xqi(10),dqiqj(10,10),
+ qiDqj(10,10),del2s,sdel2s,xpi(10),dpipj(10,10),
+ piDpj(10,10)
*
* local variables
*
integer i,j,ji,k,kj,l,lk,is,isgnji,isgnlk,
+ ifirst,i1,j1,k1,j2,kk,kkj,ier0,ier1,ier2
logical lgo
- DOUBLE PRECISION xmax,dum,delps,del2d2,dl2d22,aijk,aijkl,
+ RealType xmax,dum,delps,del2d2,dl2d22,aijk,aijkl,
+ smax,s(3),som
*
* common blocks
*
#include "ff.h"
*
ifirst = 0
* #] declarations:
* #[ si.sj -> ti.tj:
*
* calculate the dotproducts of ti(i) = ai*si(i): no problems.
*
do 20 i=1,4
xqi(i) = ai(i)**2 * xpi(i)
qiDqj(i,i) = xqi(i)
do 10 j=i+1,4
qiDqj(j,i) = ai(j)*ai(i)*piDpj(j,i)
qiDqj(i,j) = qiDqj(j,i)
10 continue
20 continue
*
* and the smuggled ones for the onshell complex D0
*
if ( lsmug ) then
do 40 j=1,3
do 30 i=i+1,4
- c2sisj(i,j) = DBLE(ai(j)*ai(i))*c2sisj(i,j)
+ c2sisj(i,j) = Re(ai(j)*ai(i))*c2sisj(i,j)
c2sisj(j,i) = c2sisj(i,j)
30 continue
40 continue
endif
if ( lnasty ) then
do 60 j=3,4
*
* we also hide in this array the corresponding real value
* in (j,2) and (2,j), and the untransformed in (j,j).
* Not beuatiful, but we need these to get the correct
* Riemann sheets.
*
c2sisj(j,j) = c2sisj(j,1)
- c2sisj(j,2) = ai(j)*ai(1)*DBLE(c2sisj(j,1))
+ c2sisj(j,2) = ai(j)*ai(1)*Re(c2sisj(j,1))
c2sisj(2,j) = c2sisj(j,2)
- c2sisj(j,1) = DBLE(ai(j))*ca1*c2sisj(j,1)
+ c2sisj(j,1) = Re(ai(j))*ca1*c2sisj(j,1)
c2sisj(1,j) = c2sisj(j,1)
*
60 continue
endif
*
* #] si.sj -> ti.tj:
* #[ si.pj -> ti.qj:
*
* The dotproducts ti.qjk are still not too bad
* Notice that t3.p = t4.p, so qiDqj(3,5-10) = qiDqj(4,5-10)
*
ier2 = ier
do 90 i=1,4
do 80 j=1,3
do 70 k=j+1,4
ier1 = ier
kj = inx(k,j)
is = isgn(k,j)
if ( i.eq.4 .and.
+ (del2s.ne.0 .or. kj.eq.5 .or. kj.eq.7 )) then
qiDqj(kj,4) = qiDqj(kj,3)
goto 65
endif
s(1) = qiDqj(k,i)
s(2) = qiDqj(j,i)
qiDqj(kj,i) = is*(s(1) - s(2))
if ( abs(qiDqj(kj,i)).ge.xloss*abs(s(1)) ) goto 65
ier0 = ier
if ( del2s .eq. 0 ) then
*
* the special cases for del2s-0
*
if ( kj .eq. 5 ) then
call ffdl2t(delps,piDpj, 7,i, 1,2,5, 1,1,10)
qiDqj(5,i) = ai(1)*ai(2)*ai(i)*delps/xpi(3)
elseif ( kj .eq. 7 ) then
qiDqj(kj,i) = ai(i)*ai(4)**2*piDpj(kj,i)
else
*
* the pi has a mixed delta/no delta behaviour
*
call ffwarn(144,ier1,qiDqj(kj,i),s(1))
goto 65
endif
goto 65
endif
*
* Normal case, from the quadratic equation ...
*
ier1 = ier0
ier0 = ier
call ff2dl2(del2d2,delps,xpi,dpipj,piDpj, i,
+ j,k,kj,is, 4, 3,4,7,+1, 10, ier0)
ier1 = max(ier1,ier0)
ier0 = ier
call ff2d22(dl2d22,xpi,dpipj,piDpj, i, j,k,kj,is,
+ 3,4,7,+1)
ier1 = max(ier1,ier0)
call ffroot(dum,aijk,xpi(4),delps,dl2d22/del2s,
+ -del2d2/sdel2s,ier1)
* the minus sign is because we have aijk, not aikj.
qiDqj(kj,i) = -is*aijk*ai(i)*ai(j)*ai(k)
65 continue
qiDqj(i,kj) = qiDqj(kj,i)
ier2 = max(ier2,ier1)
70 continue
80 continue
90 continue
* #] si.pj -> ti.qj:
* #[ pi.pj -> qi.qj:
do 180 i=1,3
do 170 j=i+1,4
ji = inx(j,i)
isgnji = isgn(j,i)
do 160 k=i,3
do 150 l=k+1,4
if ( k .eq. i .and. l .lt. j ) goto 150
ier1 = ier
lk = inx(l,k)
isgnlk = isgn(l,k)
*
* Some are zero by definition, or equal to others
*
if ( del2s .ne. 0 .and. (ji.eq.7 .or. lk.eq.7)
+ .or.
+ del2s .eq. 0 .and. (ji.eq.7 .and. (lk.eq.7
+ .or. lk.eq.5) .or. ji.eq.5 .and. lk.eq.7
+ ) ) then
qiDqj(lk,ji) = 0
goto 145
endif
if ( j.eq.4 .and. (del2s.ne.0 .or. lk.eq.5) )
+ then
qiDqj(lk,ji) = isgnji*isgn(3,i)*
+ qiDqj(lk,inx(3,i))
goto 145
endif
if ( l.eq.4 .and. (del2s.ne.0 .or. ji.eq.5) )
+ then
qiDqj(lk,ji) = isgnlk*isgn(3,k)*
+ qiDqj(inx(3,k),ji)
goto 145
endif
*
* First normal try
*
if ( abs(qiDqj(k,ji)).le.abs(qiDqj(i,lk)) ) then
s(1) = qiDqj(k,ji)
s(2) = qiDqj(l,ji)
is = isgnlk
else
s(1) = qiDqj(i,lk)
s(2) = qiDqj(j,lk)
is = isgnji
endif
qiDqj(lk,ji) = is*(s(2) - s(1))
if ( abs(qiDqj(lk,ji)) .ge. xloss**2*abs(s(1)) )
+ goto 145
*
* First the special case del2s=0
*
if ( del2s .eq. 0 ) then
if ( ji .eq. 5 .and. lk .eq. 5 ) then
call ffdl3m(s(1),.FALSE.,0D0,0D0,xpi,
+ dpipj,piDpj, 10, 1,2,5, 7, 1)
qiDqj(5,5) =ai(1)**2*ai(2)**2*s(1)/xpi(3
+ )**2
else
call ffwarn(145,ier1,qiDqj(lk,ji),s(1))
endif
goto 145
endif
*
* Otherwise use determinants
*
call ffabcd(aijkl,xpi,dpipj,piDpj,del2s,
+ sdel2s, i,j,ji,isgnji, k,l,lk,isgnlk,
+ ifirst, ier1)
qiDqj(lk,ji) = (isgnji*isgnlk)*
+ aijkl*ai(i)*ai(j)*ai(k)*ai(l)
goto 145
* print *,'fftran: warning: numerical problems ',
* + 'in qiDqj(',lk,ji,')'
145 continue
if ( lk .ne. ji ) then
qiDqj(ji,lk) = qiDqj(lk,ji)
else
xqi(ji) = qiDqj(lk,ji)
endif
ier2 = max(ier2,ier1)
150 continue
160 continue
170 continue
180 continue
ier = ier2
* #] pi.pj -> qi.qj:
* #[ si^2 - sj^2:
*
* the differences may be awkward
*
ier2 = ier
do 140 i=1,4
dqiqj(i,i) = 0
do 130 j=i+1,4
ier0 = ier
dqiqj(j,i) = xqi(j) - xqi(i)
smax = abs(xqi(i))
if ( abs(dqiqj(j,i)) .ge. xloss*smax ) goto 125
if ( abs(daiaj(j,i)) .le. xloss*abs(ai(i)) )
+ then
s(1) = daiaj(j,i)*(ai(i)+ai(j))*xpi(j)
s(2) = ai(i)**2*dpipj(j,i)
som = s(1) + s(2)
xmax = abs(s(1))
if ( xmax.lt.smax ) then
dqiqj(j,i) = som
smax = xmax
endif
if ( abs(dqiqj(j,i)) .ge. xloss*smax ) goto 125
endif
*
* give up
*
125 continue
dqiqj(i,j) = -dqiqj(j,i)
ier2 = max(ier2,ier0)
130 continue
140 continue
* #] si^2 - sj^2:
* #[ si^2 - pj^2:
do 210 i=1,4
do 200 j=1,4
do 190 kk=j+1,4
ier0 = ier
k = kk
kj = inx(k,j)
kkj = kj
*
* Use that q_(i4)^2 = q_(i3)^2
*
if ( del2s.ne.0 .and. k.eq.4 ) then
if ( j .eq. 3 ) then
dqiqj(7,i) = -xqi(i)
else
dqiqj(kj,i) = dqiqj(inx(j,3),i)
endif
goto 185
elseif ( kj .eq. 7 ) then
dqiqj(7,i) = -xqi(i)
goto 185
endif
xmax = 0
181 continue
som = xqi(kj) - xqi(i)
if ( k.eq.kk .or. abs(xqi(i)).lt.xmax ) then
dqiqj(kj,i) = som
xmax = abs(xqi(i))
if ( abs(dqiqj(kj,i)) .ge. xloss*xmax ) goto 185
endif
*
* second try
* we assume that qi.qj, i,j<=3 are known
*
if ( abs(dqiqj(k,i)) .lt. abs(dqiqj(j,i)) ) then
j1 = k
j2 = j
else
j2 = k
j1 = j
endif
s(1) = dqiqj(j1,i)
s(2) = xqi(j2)
s(3) = -2*qiDqj(j1,j2)
som = s(1) + s(2) + s(3)
smax = max(abs(s(1)),abs(s(2)),abs(s(3)))
if ( smax.lt.xmax ) then
dqiqj(kj,i) = som
xmax = smax
if ( abs(dqiqj(kj,i)) .ge. xloss*xmax ) goto 185
endif
*
* third try: rearrange s(2),s(3)
* this works if ai(j1)~ai(j2)
*
if ( abs(daiaj(j2,j1)) .lt. xloss*abs(ai(j1)) ) then
s(2) = ai(j2)*daiaj(j2,j1)*xpi(j2)
s(3) = ai(j2)*ai(j1)*dpipj(kj,j1)
som = s(1) + s(2) + s(3)
smax = max(abs(s(1)),abs(s(2)),abs(s(3)))
if ( smax.lt.xmax ) then
dqiqj(kj,i) = som
xmax = smax
if ( abs(dqiqj(kj,i)) .ge. xloss*xmax )
+ goto 185
endif
endif
*
* There is a trick involving the other root for j2=4
* Of course it also works for j2=3.
*
if ( laai .and. j2 .ge. 3 ) then
s(2) = -ai(4)**2*(ai(j1)/aai(j1))*xpi(4)
som = s(1) + s(2)
smax = abs(s(1))
if ( smax.lt.xmax ) then
dqiqj(kj,i) = som
xmax = smax
if ( abs(dqiqj(kj,i)) .ge. xloss*xmax )
+ goto 185
endif
endif
*
* If k = 3 we can also try with k = 4 -- should give
* the same
*
if ( del2s.ne.0 .and. kk.eq.3 .and. k.eq.3 ) then
k = 4
kj = inx(k,j)
dqiqj(kj,i) = dqiqj(kkj,i)
goto 181
endif
if ( del2s.ne.0 .and. kk.eq.4 .and. k.eq.4 ) then
k = 3
kj = inx(k,j)
dqiqj(kj,i) = dqiqj(kkj,i)
goto 181
endif
*
* give up
*
185 continue
if ( k .ne. kk ) then
dqiqj(kkj,i) = dqiqj(kj,i)
dqiqj(i,kkj) = -dqiqj(kj,i)
else
dqiqj(i,kj) = -dqiqj(kj,i)
endif
ier2 = max(ier2,ier0)
190 continue
200 continue
210 continue
* #] si^2 - pj^2:
* #[ pi^2 - pj^2:
do 280 i=1,4
do 270 j=i+1,4
ji = inx(j,i)
dqiqj(ji,ji) = 0
do 260 k=i,4
do 250 l=k+1,4
ier0 = ier
if ( k .eq. i .and. l .le. j ) goto 250
lk = inx(l,k)
if ( del2s .eq. 0 ) then
*
* special case:
*
if ( j.eq.4 .and. i.eq.3 ) then
dqiqj(lk,7) = xqi(lk)
goto 245
endif
if ( l.eq.4 .and. k.eq.3 ) then
dqiqj(7,ji) = -xqi(ji)
goto 245
endif
else
*
* Use that t_3.p_i = t_4.p_i
*
if ( k.eq.i .and. j.eq.3 .and. l.eq.4 ) then
dqiqj(lk,ji) = 0
goto 245
endif
if ( j.eq.4 ) then
if ( i .eq. 3 ) then
dqiqj(lk,7) = xqi(lk)
else
dqiqj(lk,ji) = dqiqj(lk,inx(i,3))
endif
goto 245
endif
if ( l.eq.4 ) then
if ( k .eq. 3 ) then
dqiqj(7,ji) = -xqi(ji)
else
dqiqj(lk,ji) = dqiqj(inx(k,3),ji)
endif
goto 245
endif
endif
*
* We really have to calculate something
*
dqiqj(lk,ji) = xqi(lk) - xqi(ji)
smax = abs(xqi(lk))
if ( abs(dqiqj(lk,ji)).ge.xloss*smax ) goto 245
*
* First the special case j=k,l
*
i1 = i
j1 = j
k1 = k
lgo = .FALSE.
if ( j .eq. k ) then
k1 = l
lgo = .TRUE.
elseif ( j .eq. l ) then
lgo = .TRUE.
elseif ( i .eq. k ) then
i1 = j
j1 = i
k1 = l
lgo = .TRUE.
endif
if ( lgo ) then
s(1) = dqiqj(k1,i1)
s(2) = 2*isgn(i1,k1)*qiDqj(j1,inx(i1,k1))
xmax = abs(s(1))
if ( xmax .lt. smax ) then
smax = xmax
dqiqj(lk,ji) = s(1) + s(2)
if ( abs(dqiqj(lk,ji)).ge.xloss*smax )
+ goto 245
endif
endif
*
* Just some recombinations
*
if ( abs(dqiqj(l,ji)).lt.abs(dqiqj(k,ji)) ) then
j1 = l
j2 = k
else
j2 = l
j1 = k
endif
s(1) = dqiqj(j1,ji)
s(2) = xqi(j2)
s(3) = -2*qiDqj(j1,j2)
* only if this is an improvement
xmax = max(abs(s(1)),abs(s(2)),abs(s(3)))
if ( xmax .lt. smax ) then
smax = xmax
dqiqj(lk,ji) = s(1) + s(2) + s(3)
if ( abs(dqiqj(lk,ji)) .ge. xloss*smax )
+ goto 245
endif
if ( abs(dqiqj(j,lk)).lt.abs(dqiqj(i,lk)) ) then
j1 = j
j2 = i
else
j2 = j
j1 = i
endif
s(1) = -dqiqj(j1,lk)
s(2) = -xqi(j2)
s(3) = 2*qiDqj(j1,j2)
* only if this is an improvement
xmax = max(abs(s(1)),abs(s(2)),abs(s(3)))
if ( xmax .lt. smax ) then
dqiqj(lk,ji) = s(1) + s(2) + s(3)
smax = xmax
if ( abs(dqiqj(lk,ji)) .ge. xloss*smax )
+ goto 245
endif
*
* give up
*
245 continue
dqiqj(ji,lk) = -dqiqj(lk,ji)
ier2 = max(ier2,ier0)
250 continue
260 continue
270 continue
280 continue
ier = ier2
* #] pi^2 - pj^2:
*###] fftran:
end
diff --git a/Looptools/util/ffxli2.F b/Looptools/util/ffxli2.F
--- a/Looptools/util/ffxli2.F
+++ b/Looptools/util/ffxli2.F
@@ -1,593 +1,594 @@
#include "externals.h"
+#include "types.h"
*###[ ffxli2:
subroutine ffxli2(xdilog,xlog,x,ier)
***#[*comment:***********************************************************
* *
* Computes the dilogarithm (Li2, Sp) for (real) x to precision *
* precx. It is assumed that -1<=x<=1/2. As it is available anyway*
* log(1-x) = -Li1(x) is also passed. *
* *
* Input: x (real) *
* *
* Output: xdilog (real) Li2(x) *
* xlog (real) log(1-x) = -Li1(x) *
* ier (integer) 0=OK, 1=num prob, 2=error *
* *
* Calls: log,dfflo1 *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ier
- DOUBLE PRECISION xdilog,xlog,x
+ RealType xdilog,xlog,x
*
* local variables
*
integer ipi12
- DOUBLE PRECISION dfflo1,u,u2,a,ffbnd,
+ RealType dfflo1,u,u2,a,ffbnd,
+ xprec,bdn02,bdn05,bdn10,bdn15
- DOUBLE COMPLEX zxdilo,zlog
+ ComplexType zxdilo,zlog
external ffbnd,dfflo1
save xprec,bdn02,bdn05,bdn10,bdn15
*
* common blocks
*
#include "ff.h"
* #] declarations:
* #[ initialisations:
data xprec /-1D0/
if ( xprec .ne. precx ) then
xprec = precx
bdn02 = ffbnd(1,2,bf)
bdn05 = ffbnd(1,5,bf)
bdn10 = ffbnd(1,10,bf)
bdn15 = ffbnd(1,15,bf)
endif
* #] initialisations:
* #[ if the argument is too large...
if ( x .lt. -1.5 .or. x .gt. .75 ) then
call ffzxdl(zxdilo,ipi12,zlog,x,0,ier)
- if ( DIMAG(zxdilo) .ne. 0 ) then
+ if ( Im(zxdilo) .ne. 0 ) then
call fferr(52,ier)
endif
- xdilog = DBLE(zxdilo) + ipi12*pi12
- xlog = DBLE(zlog)
+ xdilog = Re(zxdilo) + ipi12*pi12
+ xlog = Re(zlog)
return
endif
* #] if the argument is too large...
* #[ exceptional cases:
if ( x .eq. -1 ) then
xdilog = -pi12
xlog = log(2D0)
return
elseif ( x .eq. .5D0 ) then
xdilog = - xlg2**2/2 + pi12
xlog = - xlg2
return
elseif ( abs(x) .lt. precx ) then
xdilog = x
xlog = -x
return
endif
* #] exceptional cases:
* #[ calculate dilog:
if ( abs(x) .lt. xloss ) then
xlog = dfflo1(x,ier)
else
xlog = log(1-x)
endif
u = -xlog
u2 = u*u
a = abs(u2)
if ( a .gt. bdn15 ) then
xdilog = u2*(bf(16) + u2*(bf(17) + u2*(bf(18) +
+ u2*(bf(19) + u2*bf(20) ))))
else
xdilog = 0
endif
if ( a .gt. bdn10 ) then
xdilog = u2*(bf(11) + u2*(bf(12) + u2*(bf(13) +
+ u2*(bf(14) + u2*(bf(15) + xdilog)))))
endif
if ( a .gt. bdn05 ) then
xdilog = u2*(bf(6) + u2*(bf(7) + u2*(bf(8) +
+ u2*(bf(9) + u2*(bf(10) + xdilog)))))
endif
if ( a .gt. bdn02 ) then
xdilog = u2*(bf(3) + u2*(bf(4) + u2*(bf(5) + xdilog)))
endif
* watch the powers of u.
xdilog = u + u2*(bf(1) + u*(bf(2) + xdilog))
* #] calculate dilog:
*###] ffxli2:
end
*###[ ffzxdl:
subroutine ffzxdl(zxdilo,ipi12,zlog,x,ieps,ier)
***#[*comment:***************************************************
* Computes the dilogarithm (Li2, Sp) for any (real) x *
* to precision precx. If an error message is given add *
* more bf's. For x > 1 the imaginary part is *
* -/+i*pi*log(x), corresponding to x+ieps. *
* The number of factors pi^2/12 is passed separately in *
* ipi12 for accuracy. We also calculate log(1-x) *
* which is likely to be needed. *
* *
* Input: x (real) *
* ieps (integer,+/-1) *
* *
* Output: zxdilo (complex) the dilog mod factors pi2/12 *
* ipi12 (integer) these factors *
* zlog (complex) log(1-x) *
* *
* Calls: log,dfflo1 *
* *
***#]*comment:***************************************************
* #[ declarations:
implicit none
*
* arguments
*
integer ipi12,ieps,ier
- DOUBLE PRECISION x
- DOUBLE COMPLEX zxdilo,zlog
+ RealType x
+ ComplexType zxdilo,zlog
*
* local variables
*
integer jsgn
- DOUBLE PRECISION fact,u,u2,dfflo1,ffbnd,a,xdilo,
+ RealType fact,u,u2,dfflo1,ffbnd,a,xdilo,
+ xprec,bdn02,bdn05,bdn10,bdn15
- DOUBLE COMPLEX cy,cfact
+ ComplexType cy,cfact
external ffbnd,dfflo1
save xprec,bdn02,bdn05,bdn10,bdn15
*
* common blocks
*
#include "ff.h"
* #] declarations:
* #[ initialisations:
data xprec /-1D0/
if ( xprec .ne. precx ) then
xprec = precx
bdn02 = ffbnd(1,2,bf)
bdn05 = ffbnd(1,5,bf)
bdn10 = ffbnd(1,10,bf)
bdn15 = ffbnd(1,15,bf)
endif
* #] initialisations:
* #[ exceptional cases:
if ( x .eq. 1) then
zxdilo = 0
zlog = -99999
ipi12 = 2
return
elseif (x .eq. -1) then
zxdilo = 0
zlog = xlg2
ipi12 = -1
return
elseif (x .eq. .5D0) then
zxdilo = - xlg2**2/2
zlog = -xlg2
ipi12 = 1
return
elseif ( abs(x) .lt. precx ) then
zxdilo = x
zlog = -x
ipi12 = 0
return
endif
* #] exceptional cases:
* #[ transform to (-1,.5):
if (x .lt. -1) then
fact = log(-x)
cy = - fact**2/2
ipi12 = -2
if ( -x*xloss .gt. 1 ) then
u = -dfflo1(1/x,ier)
else
u = -log(1-1/x)
endif
zlog = log(1-x)
jsgn = -1
elseif ( x .lt. .5D0) then
cy = 0
ipi12 = 0
if ( abs(x) .lt. xloss ) then
zlog = dfflo1(x,ier)
else
zlog = log(1-x)
endif
- u = -DBLE(zlog)
+ u = -Re(zlog)
jsgn = 1
elseif ( x .le. 2 ) then
u = -log(x)
if ( abs(1-x) .lt. xalogm ) then
cy = 0
elseif ( x .lt. 1 ) then
zlog = log(1-x)
- cy = DBLE(u)*zlog
+ cy = Re(u)*zlog
elseif ( ieps .gt. 0 ) then
- zlog = DCMPLX(log(x-1),-pi)
- cy = DBLE(u)*zlog
+ zlog = ToComplex(log(x-1),-pi)
+ cy = Re(u)*zlog
else
- zlog = DCMPLX(log(x-1),+pi)
- cy = DBLE(u)*zlog
+ zlog = ToComplex(log(x-1),+pi)
+ cy = Re(u)*zlog
endif
ipi12 = 2
jsgn = -1
else
if ( ieps .gt. 0 ) then
- cfact = DCMPLX(log(x),-pi)
- zlog = DCMPLX(log(x-1),-pi)
+ cfact = ToComplex(log(x),-pi)
+ zlog = ToComplex(log(x-1),-pi)
else
- cfact = DCMPLX(log(x),+pi)
- zlog = DCMPLX(log(x-1),+pi)
+ cfact = ToComplex(log(x),+pi)
+ zlog = ToComplex(log(x-1),+pi)
endif
cy = - cfact**2/2
ipi12 = -2
if ( x*xloss .gt. 1 ) then
u = -dfflo1(1/x,ier)
else
u = -log(1-1/x)
endif
jsgn = -1
endif
* #] transform to (-1,.5):
* #[ calculate dilog:
if ( abs(u) .lt. xalog2 ) then
xdilo = u
else
u2 = u**2
a = abs(u2)
if ( a .gt. bdn15 ) then
xdilo = u2*(bf(16) + u2*(bf(17) + u2*(bf(18) +
+ u2*(bf(19) + u2*bf(20) ))))
else
xdilo = 0
endif
if ( a .gt. bdn10 ) then
xdilo = u2*(bf(11) + u2*(bf(12) + u2*(bf(13) +
+ u2*(bf(14) + u2*(bf(15) + xdilo)))))
endif
if ( a .gt. bdn05 ) then
xdilo = u2*(bf(6) + u2*(bf(7) + u2*(bf(8) +
+ u2*(bf(9) + u2*(bf(10) + xdilo)))))
endif
if ( a .gt. bdn02 ) then
xdilo = u2*(bf(3) + u2*(bf(4) + u2*(bf(5) + xdilo)))
endif
* watch the powers of u.
xdilo = u + u2*(bf(1) + u*(bf(2) + xdilo))
endif
if(jsgn.eq.1)then
- zxdilo = DBLE(xdilo) + cy
+ zxdilo = Re(xdilo) + cy
else
- zxdilo = -DBLE(xdilo) + cy
+ zxdilo = -Re(xdilo) + cy
endif
* #] calculate dilog:
*###] ffzxdl:
end
*###[ zxfflg:
- DOUBLE COMPLEX function zxfflg(x,ieps,y,ier)
+ ComplexType function zxfflg(x,ieps,y,ier)
***#[*comment:***********************************************************
* *
* Calculate the complex logarithm of x. The following cases *
* are treted separately: *
* |x| too small: give warning and return 0 *
* (for Absoft, Apollo DN300) *
* |x| < 0: take sign according to ieps *
* *
***#]*comment:***********************************************************
* #[ declarations:
*
* arguments
*
implicit none
integer ieps,ier
- DOUBLE PRECISION x,y
+ RealType x,y
*
* local variables
*
- DOUBLE PRECISION xlog
+ RealType xlog
*
* common blocks
*
#include "ff.h"
* #] declarations:
* #[ calculations:
if ( abs(x) .lt. xalogm ) then
zxfflg = 0
elseif ( x .gt. 0 ) then
zxfflg = log(x)
else
xlog = log(-x)
* checked imaginary parts 19-May-1988
if ( abs(ieps) .eq. 1 ) then
if ( y*ieps .lt. 0 ) then
- zxfflg = DCMPLX(xlog,-pi)
+ zxfflg = ToComplex(xlog,-pi)
else
- zxfflg = DCMPLX(xlog,pi)
+ zxfflg = ToComplex(xlog,pi)
endif
elseif ( ieps .eq. 2 ) then
- zxfflg = DCMPLX(xlog,-pi)
+ zxfflg = ToComplex(xlog,-pi)
elseif ( ieps .eq. -2 ) then
- zxfflg = DCMPLX(xlog,+pi)
+ zxfflg = ToComplex(xlog,+pi)
else
call fferr(52,ier)
- zxfflg = DCMPLX(xlog,pi)
+ zxfflg = ToComplex(xlog,pi)
endif
endif
* #] calculations:
*###] zxfflg:
end
*###[ dfflo1:
- DOUBLE PRECISION function dfflo1(x,ier)
+ RealType function dfflo1(x,ier)
***#[*comment:***************************************************
* calculates log(1-x) for |x|<.14 in a faster way to ~15 *
* significant figures. *
***#]*comment:***************************************************
* #[ declarations:
implicit none
integer ier
- DOUBLE PRECISION x,bdn01,bdn05,bdn10,bdn15,bdn19,xprec,
+ RealType x,bdn01,bdn05,bdn10,bdn15,bdn19,xprec,
+ xa,ffbnd
- DOUBLE COMPLEX zxfflg
+ ComplexType zxfflg
external ffbnd,zxfflg
save xprec,bdn01,bdn05,bdn10,bdn15,bdn19
#include "ff.h"
* #] declarations:
* #[ initialisation:
data xprec /-1D0/
if ( xprec .ne. precx ) then
xprec = precx
* determine the boundaries for 1,5,10,15 terms
bdn01 = ffbnd(1,1,xninv)
bdn05 = ffbnd(1,5,xninv)
bdn10 = ffbnd(1,10,xninv)
bdn15 = ffbnd(1,15,xninv)
bdn19 = ffbnd(1,19,xninv)
endif
* #] initialisation:
* #[ calculations:
xa = abs(x)
if ( xa .gt. bdn19 ) then
- dfflo1 = DBLE(zxfflg(1-x,0,0D0,ier))
+ dfflo1 = Re(zxfflg(1-x,0,0D0,ier))
return
endif
if ( xa .gt. bdn15 ) then
dfflo1 = x*( xninv(16) + x*( xninv(17) + x*( xninv(18) +
+ x*( xninv(19) + x*xninv(20) ))))
else
dfflo1 = 0
endif
if ( xa .gt. bdn10 ) then
dfflo1 = x*( xninv(11) + x*( xninv(12) + x*( xninv(13) +
+ x*( xninv(14) + x*( xninv(15) + dfflo1 )))))
endif
if ( xa .gt. bdn05 ) then
dfflo1 = x*( xninv(6) + x*( xninv(7) + x*( xninv(8) +
+ x*( xninv(9) + x*( xninv(10) + dfflo1 )))))
endif
if ( xa .gt. bdn01 ) then
dfflo1 = x*( xninv(2) + x*( xninv(3) + x*( xninv(4) +
+ x*( xninv(5) + dfflo1 ))))
endif
dfflo1 = - x*( xninv(1) + dfflo1 )
* #] calculations:
*###] dfflo1:
end
*###[ dfflo2:
- DOUBLE PRECISION function dfflo2(x,ier)
+ RealType function dfflo2(x,ier)
***#[*comment:***************************************************
* calculates log(1-x)+x for |x|<.14 in a faster way to *
* ~15 significant figures. *
***#]*comment:***************************************************
* #[ declarations:
implicit none
integer ier
- DOUBLE PRECISION x,bdn01,bdn05,bdn10,bdn15,bdn18,xprec,
+ RealType x,bdn01,bdn05,bdn10,bdn15,bdn18,xprec,
+ xa,ffbnd,dfflo1
external ffbnd,dfflo1
save xprec,bdn01,bdn05,bdn10,bdn15,bdn18
#include "ff.h"
* #] declarations:
* #[ initialisation:
data xprec /-1D0/
if ( xprec .ne. precx ) then
xprec = precx
* determine the boundaries for 1,5,10,15 terms
bdn01 = ffbnd(1,1,xninv(2))
bdn05 = ffbnd(1,5,xninv(2))
bdn10 = ffbnd(1,10,xninv(2))
bdn15 = ffbnd(1,15,xninv(2))
bdn18 = ffbnd(1,18,xninv(2))
endif
* #] initialisation:
* #[ calculations:
xa = abs(x)
if ( xa .gt. bdn18 ) then
dfflo2 = dfflo1(x,ier) + x
return
endif
if ( xa .gt. bdn15 ) then
dfflo2 = x*( xninv(17) + x*( xninv(18) + x*( xninv(19) +
+ x*xninv(20) )))
else
dfflo2 = 0
endif
if ( xa .gt. bdn10 ) then
dfflo2 = x*( xninv(12) + x*( xninv(13) + x*( xninv(14) +
+ x*( xninv(15) + x*( xninv(16) + dfflo2 )))))
endif
if ( xa .gt. bdn05 ) then
dfflo2 = x*( xninv(7) + x*( xninv(8) + x*( xninv(9) +
+ x*( xninv(10) + x*( xninv(11) + dfflo2 )))))
endif
if ( xa .gt. bdn01 ) then
dfflo2 = x*( xninv(3) + x*( xninv(4) + x*( xninv(5) +
+ x*( xninv(6) + dfflo2 ))))
endif
dfflo2 = - x**2*( xninv(2) + dfflo2 )
* #] calculations:
*###] dfflo2:
end
*###[ dfflo3:
- DOUBLE PRECISION function dfflo3(x,ier)
+ RealType function dfflo3(x,ier)
***#[*comment:***************************************************
* calculates log(1-x)+x+x^2/2 for |x|<.14 in a faster *
* way to ~15 significant figures. *
***#]*comment:***************************************************
* #[ declarations:
implicit none
integer ier
- DOUBLE PRECISION x,bdn01,bdn05,bdn10,bdn15,xprec,
+ RealType x,bdn01,bdn05,bdn10,bdn15,xprec,
+ xa,ffbnd,dfflo2
external ffbnd,dfflo2
save xprec,bdn01,bdn05,bdn10,bdn15
#include "ff.h"
* #] declarations:
* #[ initialisation:
data xprec /-1D0/
if ( xprec .ne. precx ) then
xprec = precx
* determine the boundaries for 1,5,10,15 terms
bdn01 = ffbnd(1,1,xninv(3))
bdn05 = ffbnd(1,5,xninv(3))
bdn10 = ffbnd(1,10,xninv(3))
bdn15 = ffbnd(1,15,xninv(3))
endif
* #] initialisation:
* #[ calculations:
xa = abs(x)
if ( xa .gt. bdn15 ) then
dfflo3 = dfflo2(x,ier) + x**2/2
return
endif
if ( xa .gt. bdn10 ) then
dfflo3 = x*( xninv(13) + x*( xninv(14) + x*( xninv(15) +
+ x*( xninv(16) + x*xninv(17) ))))
else
dfflo3 = 0
endif
if ( xa .gt. bdn05 ) then
dfflo3 = x*( xninv(8) + x*( xninv(9) + x*( xninv(10) +
+ x*( xninv(11) + x*( xninv(12) + dfflo3 )))))
endif
if ( xa .gt. bdn01 ) then
dfflo3 = x*( xninv(4) + x*( xninv(5) + x*( xninv(6) +
+ x*( xninv(7) + dfflo3 ))))
endif
dfflo3 = - x**3*( xninv(3) + dfflo3 )
* #] calculations:
*###] dfflo3:
end
*###[ ffxl22:
subroutine ffxl22(xl22,x,ier)
***#[*comment:***************************************************
* calculates Li2(2-x) for |x|<.14 in a faster way to ~15 *
* significant figures. *
***#]*comment:***************************************************
* #[ declarations:
implicit none
integer ier,init
- DOUBLE PRECISION xl22,x,bdn01,bdn05,bdn10,bdn15,bdn20,bdn25,
+ RealType xl22,x,bdn01,bdn05,bdn10,bdn15,bdn20,bdn25,
+ xprec,xa,ffbnd,dilog2(29)
external ffbnd
save xprec,bdn01,bdn05,bdn10,bdn15,bdn20,bdn25,init,dilog2
#include "ff.h"
data xprec /-1D0/
data init /0/
if ( init .eq. 0 ) then
init = 1
* taylor(dilog(x-1),x,30);
dilog2( 1) = 0.d0
dilog2( 2) = 1/4.d0
dilog2( 3) = 1/6.d0
dilog2( 4) = 5/48.d0
dilog2( 5) = 1/15.d0
dilog2( 6) = 2/45.d0
dilog2( 7) = 13/420.d0
dilog2( 8) = 151/6720.d0
dilog2( 9) = 16/945.d0
dilog2(10) = 83/6300.d0
dilog2(11) = 73/6930.d0
dilog2(12) = 1433/166320.d0
dilog2(13) = 647/90090.d0
dilog2(14) = 15341/2522520.d0
dilog2(15) = 28211/5405400.d0
dilog2(16) = 10447/2306304.d0
dilog2(17) = 608/153153.d0
dilog2(18) = 19345/5513508.d0
dilog2(19) = 18181/5819814.d0
dilog2(20) = 130349/46558512.d0
dilog2(21) = 771079/305540235.d0
dilog2(22) = 731957/320089770.d0
dilog2(23) = 2786599/1338557220.d0
dilog2(24) = 122289917/64250746560.d0
dilog2(25) = 14614772/8365982625.d0
dilog2(26) = 140001721/87006219300.d0
dilog2(27) = 134354573/90352612350.d0
dilog2(28) = 774885169/562194032400.d0
dilog2(29) = 745984697/582272390700.d0
endif
* #] declarations:
* #[ initialisation:
if ( xprec .ne. precx ) then
xprec = precx
* determine the boundaries for 1,5,10,15,20 terms
bdn01 = ffbnd(2,1,dilog2)
bdn05 = ffbnd(2,5,dilog2)
bdn10 = ffbnd(2,10,dilog2)
bdn15 = ffbnd(2,15,dilog2)
bdn20 = ffbnd(2,20,dilog2)
bdn25 = ffbnd(2,25,dilog2)
endif
* #] initialisation:
* #[ calculations:
xa = abs(x)
if ( xa .gt. bdn25 ) then
call ffwarn(230,ier,precx,dilog2(27)*xa**25)
endif
if ( xa .gt. bdn20 ) then
xl22 = x*( dilog2(22) + x*( dilog2(23) + x*( dilog2(24) +
+ x*( dilog2(25) + x*dilog2(26) ))))
else
xl22 = 0
endif
if ( xa .gt. bdn15 ) then
xl22 = x*( dilog2(17) + x*( dilog2(18) + x*( dilog2(19) +
+ x*( dilog2(20) + x*dilog2(21) ))))
endif
if ( xa .gt. bdn10 ) then
xl22 = x*( dilog2(12) + x*( dilog2(13) + x*( dilog2(14) +
+ x*( dilog2(15) + x*dilog2(16) ))))
endif
if ( xa .gt. bdn05 ) then
xl22 = x*( dilog2(7) + x*( dilog2(8) + x*( dilog2(9) +
+ x*( dilog2(10) + x*( dilog2(11) + xl22 )))))
endif
if ( xa .gt. bdn01 ) then
xl22 = x*( dilog2(3) + x*( dilog2(4) + x*( dilog2(5) +
+ x*( dilog2(6) + xl22 ))))
endif
xl22 = - x**2*( dilog2(2) + xl22 )
* #] calculations:
*###] ffxl22:
end
diff --git a/Looptools/util/ffxxyz.F b/Looptools/util/ffxxyz.F
--- a/Looptools/util/ffxxyz.F
+++ b/Looptools/util/ffxxyz.F
@@ -1,723 +1,724 @@
#include "externals.h"
+#include "types.h"
*###[ ffxxyz:
subroutine ffxxyz(y,z,dyz,d2yzz,dy2z,ivert,sdel2p,sdel2s,etalam,
+ etami,delps,xpi,dpipj,piDpj,isoort,ldel2s,ns,ier)
***#[*comment:***********************************************************
* *
* calculate in a numerically stable way *
* *
* z(1,2) = (-p(ip1).p(is2) +/- sdel2s)/xpi(ip1) *
* y(1,2) = (-p(ip1).p(is2) +/- sdisc)/xpi(ip1) *
* disc = del2s + etaslam*xpi(ip1) *
* *
* y(3,4) = 1-y(1,2) *
* z(3,4) = 1-z(1,2) *
* dyz(i,j) = y(i) - z(j) *
* d2yzz = y(2) - z(1) - z(2) *
* dy2z(j) = y(2) - 2*z(j) *
* *
* Input: ivert (integer) defines the vertex *
* sdel2p (real) sqrt(lam(p1,p2,p3))/2 *
* sdel2s (real) sqrt(lam(p,ma,mb))/2 *
* etalam (real) det(si.sj)/det(pi.pj) *
* etami(6) (real) si.si - etalam *
* xpi(ns) (real) standard *
* piDpj(ns,ns) (real) standard *
* ns (integer) dim of xpi,piDpj *
* *
* Output: y(4),z(4),dyz(4,4) (real) see above *
* *
* Calls: fferr,ffroot *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer ivert,ns,ier,isoort(2)
logical ldel2s
- DOUBLE PRECISION y(4),z(4),dyz(2,2),d2yzz,dy2z(4),
+ RealType y(4),z(4),dyz(2,2),d2yzz,dy2z(4),
+ sdel2p,sdel2s,etalam,etami(6),delps,xpi(ns),
+ dpipj(ns,ns),piDpj(ns,ns)
*
* local variables:
*
integer i,j,n,ip1,ip2,ip3,is1,is2,is3,iwarn,ier1
- DOUBLE PRECISION disc,hulp,s,smax,som(51),xmax
- DOUBLE PRECISION t1,t2,t4,t5,t8,t3,t7,t9,t12,t14,t21,t23,t24,
+ RealType disc,hulp,s,smax,som(51),xmax
+ RealType t1,t2,t4,t5,t8,t3,t7,t9,t12,t14,t21,t23,t24,
+ t28,t6,t35,t44,t42,t36,t55,t41,t19,t59,t25,t69,t82,t75,t84,t92,
+ t31,t98,t74,t101,t89,t106,t112,t113,t13,t117,t126,t127,t129,
+ t130,t133,t128,t132,t134,t137,t139,t146,t148,t149,t153,t131,
+ t160,t171,t169,t161,t182,t168,t144,t186,t150,t208,t201,t210,
+ t219,t156,t225,t200,t228,t215,t233,t239,t240,t138,t244
*
* common blocks:
*
#include "ff.h"
* #] declarations:
* #[ set up pointers:
if ( ldel2s .and. ivert .ne. 1 ) goto 100
is1 = ivert
is2 = ivert+1
if ( is2 .eq. 4 ) is2 = 1
is3 = ivert-1
if ( is3 .eq. 0 ) is3 = 3
ip1 = is1 + 3
ip2 = is2 + 3
ip3 = is3 + 3
* #] set up pointers:
* #[ xk = 0:
if ( xpi(ip1) .eq. 0 ) then
isoort(2) = 0
if ( piDpj(is1,ip1) .eq. 0 ) then
isoort(1) = 0
return
endif
isoort(1) = 1
y(1) = etami(is2) / piDpj(is1,ip1) /2
y(2) = y(1)
y(3) = - etami(is1) / piDpj(is1,ip1) /2
y(4) = y(3)
z(1) = xpi(is2) / piDpj(is1,ip1) /2
z(2) = z(1)
z(3) = - xpi(is1) / piDpj(is1,ip1) /2
z(4) = z(3)
dyz(1,1) = - etalam / piDpj(is1,ip1) /2
dyz(1,2) = dyz(1,1)
dyz(2,1) = dyz(1,1)
dyz(2,2) = dyz(1,1)
ier1 = ier
do 10 i=1,3,2
dy2z(i) = y(i) - 2*z(i)
smax = abs(y(i))
dy2z(i+1) = dy2z(i)
10 continue
ier = ier1
return
endif
* #] xk = 0:
* #[ get y(1,2),z(1,2):
if ( sdel2s .eq. 0 ) then
isoort(1) = 2
isoort(2) = 2
z(1) = piDpj(ip1,is2)/xpi(ip1)
z(2) = z(1)
else
isoort(1) = 1
isoort(2) = 1
call ffroot(z(1),z(2),xpi(ip1),piDpj(ip1,is2),xpi(is2),
+ sdel2s,ier)
endif
disc = delps/sdel2p
call ffroot(y(1),y(2),xpi(ip1),piDpj(ip1,is2),etami(is2),disc,
+ ier)
* #] get y(1,2),z(1,2):
* #[ get y(3,4),z(3,4):
if ( isoort(1) .eq. 2 ) then
z(3) = -piDpj(ip1,is1)/xpi(ip1)
z(4) = z(3)
else
z(3) = 1-z(1)
z(4) = 1-z(2)
if ( abs(z(3)) .lt. xloss .or. abs(z(4)) .lt. xloss )
+ call ffroot(z(4),z(3),xpi(ip1),-piDpj(ip1,is1),
+ xpi(is1),sdel2s,ier)
endif
y(3) = 1-y(1)
y(4) = 1-y(2)
if ( abs(y(3)) .lt. xloss .or. abs(y(4)) .lt. xloss ) then
call ffroot(y(4),y(3),xpi(ip1),-piDpj(ip1,is1),
+ etami(is1),disc,ier)
endif
* #] get y(3,4),z(3,4):
* #[ get dyz:
* Note that dyz(i,j) only exists for i,j=1,2!
if ( isoort(1) .eq. 2 ) then
dyz(2,1) = disc/xpi(ip1)
dyz(2,2) = dyz(2,1)
elseif ( disc .gt. 0 .eqv. sdel2s .gt. 0 ) then
dyz(2,1) = ( disc + sdel2s )/xpi(ip1)
dyz(2,2) = etalam/(xpi(ip1)*dyz(2,1))
else
dyz(2,2) = ( disc - sdel2s )/xpi(ip1)
dyz(2,1) = etalam/(xpi(ip1)*dyz(2,2))
endif
dyz(1,1) = -dyz(2,2)
dyz(1,2) = -dyz(2,1)
d2yzz = 2*disc/xpi(ip1)
*
* these are very rarely needed, but ...
*
iwarn = 0
ier1 = ier
do 20 i=1,4
j = 2*((i+1)/2)
dy2z(i) = y(j) - 2*z(i)
smax = abs(y(j))
if ( abs(dy2z(i)) .lt. xloss*smax ) then
if ( i/2 .eq. 1 ) then
s = -y(j-1) - 2*sdel2s/xpi(ip1)
else
s = -y(j-1) + 2*sdel2s/xpi(ip1)
endif
if ( abs(y(j-1)) .lt. smax ) then
dy2z(i) = s
smax = abs(y(j-1))
endif
if ( abs(dy2z(i)) .lt. xloss*smax ) then
if ( iwarn .ne. 0 ) then
else
iwarn = i
xmax = smax
endif
endif
endif
20 continue
if ( iwarn .ne. 0 ) then
*
* we should import the differences, but later...
*
if ( abs(dpipj(is3,ip1)) .lt. xloss*xpi(is3)
+ .and. abs(dpipj(is1,is2)) .lt. xloss*abs(xpi(ip1))) then
*
* give it another try - multiply roots (see dy2z.frm)
*
if ( iwarn.lt.3 ) then
*prod1=
* som(1)=+160*xpi(ip1)*xpi(ip2)*xpi(is2)*piDpj(ip1,ip2)**2*
* + dpipj(is2,is1)**2
* som(2)=-40*xpi(ip1)*xpi(ip2)*piDpj(ip1,ip2)*piDpj(ip2,
* + is2)*dpipj(is2,is1)**3
* som(3)=-32*xpi(ip1)*xpi(ip2)*piDpj(ip1,ip2)**2*dpipj(is2,
* + is1)**3
* som(4)=+9*xpi(ip1)*xpi(ip2)**2*dpipj(is2,is1)**4
* som(5)=-128*xpi(ip1)*xpi(is2)*piDpj(ip1,ip2)**3*piDpj(ip2,
* + is2)*dpipj(is2,is1)
* som(6)=-128*xpi(ip1)*xpi(is2)*piDpj(ip1,ip2)**4*dpipj(is2,
* + is1)
* som(7)=+256*xpi(ip1)*xpi(is2)**2*piDpj(ip1,ip2)**4
* som(8)=-16*xpi(ip1)*piDpj(ip1,ip2)**2*piDpj(ip2,is2)**2*
* + dpipj(is2,is1)**2
* som(9)=+96*xpi(ip1)*piDpj(ip1,ip2)**3*piDpj(ip2,is2)*dpipj(is2,
* + is1)**2
* som(10)=+128*xpi(ip1)**2*xpi(ip2)*xpi(is2)*piDpj(ip1,ip2)*piDpj(
* + ip2,is2)*dpipj(is2,is1)
* som(11)=+320*xpi(ip1)**2*xpi(ip2)*xpi(is2)*piDpj(ip1,ip2)**2*
* + dpipj(is2,is1)
* som(12)=-512*xpi(ip1)**2*xpi(ip2)*xpi(is2)**2*piDpj(ip1,ip2)**2
* som(13)=-120*xpi(ip1)**2*xpi(ip2)*piDpj(ip1,ip2)*piDpj(ip2,
* + is2)*dpipj(is2,is1)**2
* som(14)=-48*xpi(ip1)**2*xpi(ip2)*piDpj(ip1,ip2)**2*dpipj(is2,
* + is1)**2
* som(15)=+40*xpi(ip1)**2*xpi(ip2)*piDpj(ip2,is2)**2*dpipj(is2,
* + is1)**2
* som(16)=-96*xpi(ip1)**2*xpi(ip2)**2*xpi(is2)*dpipj(is2,is1)**2
* som(17)=+36*xpi(ip1)**2*xpi(ip2)**2*dpipj(is2,is1)**3
* som(18)=+128*xpi(ip1)**2*xpi(is2)*piDpj(ip1,ip2)**2*piDpj(ip2,
* + is2)**2
* som(19)=-128*xpi(ip1)**2*xpi(is2)*piDpj(ip1,ip2)**3*piDpj(ip2,
* + is2)
* som(20)=-64*xpi(ip1)**2*xpi(is2)*piDpj(ip1,ip2)**4
* som(21)=-32*xpi(ip1)**2*piDpj(ip1,ip2)*piDpj(ip2,is2)**3*
* + dpipj(is2,is1)
* som(22)=-32*xpi(ip1)**2*piDpj(ip1,ip2)**2*piDpj(ip2,is2)**2*
* + dpipj(is2,is1)
* som(23)=+96*xpi(ip1)**2*piDpj(ip1,ip2)**3*piDpj(ip2,is2)*
* + dpipj(is2,is1)
* som(24)=+128*xpi(ip1)**3*xpi(ip2)*xpi(is2)*piDpj(ip1,ip2)*piDpj(
* + ip2,is2)
* som(25)=+160*xpi(ip1)**3*xpi(ip2)*xpi(is2)*piDpj(ip1,ip2)**2
* som(26)=-128*xpi(ip1)**3*xpi(ip2)*xpi(is2)*piDpj(ip2,is2)**2
* som(27)=+32*xpi(ip1)**3*xpi(ip2)*piDpj(ip1,ip2)*piDpj(ip2,
* + is1)*piDpj(ip2,is2)
* som(28)=-120*xpi(ip1)**3*xpi(ip2)*piDpj(ip1,ip2)*piDpj(ip2,
* + is2)*dpipj(is2,is1)
* som(29)=-32*xpi(ip1)**3*xpi(ip2)*piDpj(ip1,ip2)**2*dpipj(is2,
* + is1)
* som(30)=-16*xpi(ip1)**3*xpi(ip2)*piDpj(ip2,is1)*piDpj(ip2,
* + is2)**2
* som(31)=+80*xpi(ip1)**3*xpi(ip2)*piDpj(ip2,is2)**2*dpipj(is2,
* + is1)
* som(32)=-192*xpi(ip1)**3*xpi(ip2)**2*xpi(is2)*dpipj(is2,is1)
* som(33)=+256*xpi(ip1)**3*xpi(ip2)**2*xpi(is2)**2
* som(34)=+54*xpi(ip1)**3*xpi(ip2)**2*dpipj(is2,is1)**2
* som(35)=-16*xpi(ip1)**3*xpi(ip3)*piDpj(ip1,ip2)*piDpj(ip2,
* + is1)*piDpj(ip2,is2)
* som(36)=+8*xpi(ip1)**3*xpi(ip3)*piDpj(ip2,is1)*piDpj(ip2,is2)**2
* som(37)=+16*xpi(ip1)**3*xpi(is2)*piDpj(ip1,ip2)*piDpj(ip2,
* + is1)*piDpj(ip2,is2)
* som(38)=-8*xpi(ip1)**3*xpi(is2)*piDpj(ip2,is1)*piDpj(ip2,is2)**2
* som(39)=-16*xpi(ip1)**3*piDpj(ip1,ip2)*piDpj(ip2,is1)*piDpj(ip2,
* + is2)*dpipj(is3,ip1)
* som(40)=+8*xpi(ip1)**3*piDpj(ip2,is1)*piDpj(ip2,is2)**2*
* + dpipj(is3,ip1)
* som(41)=-40*xpi(ip1)**4*xpi(ip2)*piDpj(ip1,ip2)*piDpj(ip2,is2)
* som(42)=-8*xpi(ip1)**4*xpi(ip2)*piDpj(ip1,ip2)**2
* som(43)=+40*xpi(ip1)**4*xpi(ip2)*piDpj(ip2,is2)**2
* som(44)=-96*xpi(ip1)**4*xpi(ip2)**2*xpi(is2)
* som(45)=+36*xpi(ip1)**4*xpi(ip2)**2*dpipj(is2,is1)
* som(46)=+9*xpi(ip1)**5*xpi(ip2)**2
* som(47)=-8*xpi(ip2)*piDpj(ip1,ip2)**2*dpipj(is2,is1)**4
* som(48)=-64*xpi(is2)*piDpj(ip1,ip2)**4*dpipj(is2,is1)**2
* som(49)=+32*piDpj(ip1,ip2)**3*piDpj(ip2,is2)*dpipj(is2,is1)**3
* print '(7g20.12)',(som(i),i=1,49)
*
* optimized by Maple (see ffxxyz.map)
*
t1 = xpi(ip1)
t2 = xpi(ip2)
t3 = t1*t2
t4 = xpi(is2)
t5 = piDpj(ip1,ip2)
t6 = t5**2
t7 = t4*t6
t8 = dpipj(is2,is1)
t9 = t8**2
som(1) = 160*t3*t7*t9
t12 = piDpj(ip2,is2)
t13 = t5*t12
t14 = t9*t8
som(2) = -40*t3*t13*t14
som(3) = -32*t3*t6*t14
t19 = t2**2
t21 = t9**2
som(4) = 9*t1*t19*t21
t23 = t1*t4
t24 = t6*t5
t25 = t24*t12
som(5) = -128*t23*t25*t8
t28 = t6**2
som(6) = -128*t23*t28*t8
t31 = t4**2
som(7) = 256*t1*t31*t28
t35 = t12**2
t36 = t35*t9
som(8) = -16*t1*t6*t36
som(9) = 96*t1*t24*t12*t9
t41 = t1**2
t42 = t41*t2
t44 = t13*t8
som(10) = 128*t42*t4*t44
som(11) = 320*t42*t7*t8
som(12) = -512*t42*t31*t6
som(13) = -120*t42*t13*t9
som(14) = -48*t42*t6*t9
som(15) = 40*t42*t36
t55 = t41*t19
som(16) = -96*t55*t4*t9
som(17) = 36*t55*t14
t59 = t41*t4
som(18) = 128*t59*t6*t35
som(19) = -128*t59*t25
som(20) = -64*t59*t28
som(21) = -32*t41*t5*t35*t12*t8
t69 = t35*t8
som(22) = -32*t41*t6*t69
som(23) = 96*t41*t24*t12*t8
t74 = t41*t1
t75 = t74*t2
som(24) = 128*t75*t4*t5*t12
som(25) = 160*t75*t7
som(26) = -128*t75*t4*t35
t82 = piDpj(ip2,is1)
t84 = t5*t82*t12
som(27) = 32*t75*t84
som(28) = -120*t75*t44
som(29) = -32*t75*t6*t8
t89 = t82*t35
som(30) = -16*t75*t89
som(31) = 80*t75*t69
t92 = t74*t19
som(32) = -192*t92*t4*t8
som(33) = 256*t92*t31
som(34) = 54*t92*t9
t98 = t74*xpi(ip3)
som(35) = -16*t98*t84
som(36) = 8*t98*t89
t101 = t74*t4
som(37) = 16*t101*t84
som(38) = -8*t101*t89
t106 = dpipj(is3,ip1)
som(39) = -16*t74*t5*t82*t12*t106
som(40) = 8*t74*t82*t35*t106
t112 = t41**2
t113 = t112*t2
som(41) = -40*t113*t13
som(42) = -8*t113*t6
som(43) = 40*t113*t35
t117 = t112*t19
som(44) = -96*t117*t4
som(45) = 36*t117*t8
som(46) = 9*t112*t1*t19
som(47) = -8*t2*t6*t21
som(48) = -64*t4*t28*t9
som(49) = 32*t25*t14
* print '(7g20.12)',(som(i),i=1,49)
n=49
else
*prod3=
* som(1)=+160*xpi(ip1)*xpi(ip2)*xpi(is2)*piDpj(ip1,ip2)**2*
* + dpipj(is2,is1)**2
* som(2)=-40*xpi(ip1)*xpi(ip2)*piDpj(ip1,ip2)*piDpj(ip2,
* + is2)*dpipj(is2,is1)**3
* som(3)=-88*xpi(ip1)*xpi(ip2)*piDpj(ip1,ip2)**2*dpipj(is2,
* + is1)**3
* som(4)=+9*xpi(ip1)*xpi(ip2)**2*dpipj(is2,is1)**4
* som(5)=-128*xpi(ip1)*xpi(is2)*piDpj(ip1,ip2)**3*piDpj(ip2,
* + is2)*dpipj(is2,is1)
* som(6)=-256*xpi(ip1)*xpi(is2)*piDpj(ip1,ip2)**4*dpipj(is2,is1)
* som(7)=+256*xpi(ip1)*xpi(is2)**2*piDpj(ip1,ip2)**4
* som(8)=-16*xpi(ip1)*piDpj(ip1,ip2)**2*piDpj(ip2,is2)**2*dpipj(
* + is2,is1)**2
* som(9)=+64*xpi(ip1)*piDpj(ip1,ip2)**3*piDpj(ip2,is2)*dpipj(is2,
* + is1)**2
* som(10)=+80*xpi(ip1)*piDpj(ip1,ip2)**4*dpipj(is2,is1)**2
* som(11)=+128*xpi(ip1)**2*xpi(ip2)*xpi(is2)*piDpj(ip1,ip2)*piDpj(
* + ip2,is2)*dpipj(is2,is1)
* som(12)=+576*xpi(ip1)**2*xpi(ip2)*xpi(is2)*piDpj(ip1,ip2)**2*
* + dpipj(is2,is1)
* som(13)=-512*xpi(ip1)**2*xpi(ip2)*xpi(is2)**2*piDpj(ip1,ip2)**2
* som(14)=-88*xpi(ip1)**2*xpi(ip2)*piDpj(ip1,ip2)*piDpj(ip2,
* + is2)*dpipj(is2,is1)**2
* som(15)=-192*xpi(ip1)**2*xpi(ip2)*piDpj(ip1,ip2)**2*dpipj(is2,
* + is1)**2
* som(16)=+40*xpi(ip1)**2*xpi(ip2)*piDpj(ip2,is2)**2*dpipj(is2,
* + is1)**2
* som(17)=-96*xpi(ip1)**2*xpi(ip2)**2*xpi(is2)*dpipj(is2,is1)**2
* som(18)=+60*xpi(ip1)**2*xpi(ip2)**2*dpipj(is2,is1)**3
* som(19)=+128*xpi(ip1)**2*xpi(is2)*piDpj(ip1,ip2)**2*piDpj(ip2,
* + is2)**2
* som(20)=-128*xpi(ip1)**2*xpi(is2)*piDpj(ip1,ip2)**3*piDpj(ip2,
* + is2)
* som(21)=-64*xpi(ip1)**2*xpi(is2)*piDpj(ip1,ip2)**4
* som(22)=-32*xpi(ip1)**2*piDpj(ip1,ip2)*piDpj(ip2,is2)**3*
* + dpipj(is2,is1)
* som(23)=+64*xpi(ip1)**2*piDpj(ip1,ip2)**3*piDpj(ip2,is2)*
* + dpipj(is2,is1)
* som(24)=+32*xpi(ip1)**2*piDpj(ip1,ip2)**4*dpipj(is2,is1)
* som(25)=+128*xpi(ip1)**3*xpi(ip2)*xpi(is2)*piDpj(ip1,ip2)*piDpj(
* + ip2,is2)
* som(26)=+160*xpi(ip1)**3*xpi(ip2)*xpi(is2)*piDpj(ip1,ip2)**2
* som(27)=-128*xpi(ip1)**3*xpi(ip2)*xpi(is2)*piDpj(ip2,is2)**2
* som(28)=+32*xpi(ip1)**3*xpi(ip2)*piDpj(ip1,ip2)*piDpj(ip2,
* + is1)*piDpj(ip2,is2)
* som(29)=-88*xpi(ip1)**3*xpi(ip2)*piDpj(ip1,ip2)*piDpj(ip2,
* + is2)*dpipj(is2,is1)
* som(30)=-88*xpi(ip1)**3*xpi(ip2)*piDpj(ip1,ip2)**2*dpipj(is2,
* + is1)
* som(31)=-16*xpi(ip1)**3*xpi(ip2)*piDpj(ip2,is1)*piDpj(ip2,
* + is2)**2
* som(32)=+48*xpi(ip1)**3*xpi(ip2)*piDpj(ip2,is2)**2*dpipj(is2,
* + is1)
* som(33)=-320*xpi(ip1)**3*xpi(ip2)**2*xpi(is2)*dpipj(is2,is1)
* som(34)=+256*xpi(ip1)**3*xpi(ip2)**2*xpi(is2)**2
* som(35)=+118*xpi(ip1)**3*xpi(ip2)**2*dpipj(is2,is1)**2
* som(36)=-16*xpi(ip1)**3*xpi(ip3)*piDpj(ip1,ip2)*piDpj(ip2,
* + is1)*piDpj(ip2,is2)
* som(37)=+8*xpi(ip1)**3*xpi(ip3)*piDpj(ip2,is1)*piDpj(ip2,is2)**2
* som(38)=+16*xpi(ip1)**3*xpi(is2)*piDpj(ip1,ip2)*piDpj(ip2,
* + is1)*piDpj(ip2,is2)
* som(39)=-8*xpi(ip1)**3*xpi(is2)*piDpj(ip2,is1)*piDpj(ip2,is2)**2
* som(40)=-16*xpi(ip1)**3*piDpj(ip1,ip2)*piDpj(ip2,is1)*piDpj(ip2,
* + is2)*dpipj(is3,ip1)
* som(41)=+8*xpi(ip1)**3*piDpj(ip2,is1)*piDpj(ip2,is2)**2*
* + dpipj(is3,ip1)
* som(42)=-40*xpi(ip1)**4*xpi(ip2)*piDpj(ip1,ip2)*piDpj(ip2,is2)
* som(43)=-8*xpi(ip1)**4*xpi(ip2)*piDpj(ip1,ip2)**2
* som(44)=+40*xpi(ip1)**4*xpi(ip2)*piDpj(ip2,is2)**2
* som(45)=-96*xpi(ip1)**4*xpi(ip2)**2*xpi(is2)
* som(46)=+60*xpi(ip1)**4*xpi(ip2)**2*dpipj(is2,is1)
* som(47)=+9*xpi(ip1)**5*xpi(ip2)**2
* som(48)=-8*xpi(ip2)*piDpj(ip1,ip2)**2*dpipj(is2,is1)**4
* som(49)=-64*xpi(is2)*piDpj(ip1,ip2)**4*dpipj(is2,is1)**2
* som(50)=+32*piDpj(ip1,ip2)**3*piDpj(ip2,is2)*dpipj(is2,is1)**3
* som(51)=+32*piDpj(ip1,ip2)**4*dpipj(is2,is1)**3
* print '(7g20.12)',(som(i),i=1,51)
*
* optimized by Maple (see ffxxyz.map)
*
t126 = xpi(ip1)
t127 = xpi(ip2)
t128 = t126*t127
t129 = xpi(is2)
t130 = piDpj(ip1,ip2)
t131 = t130**2
t132 = t129*t131
t133 = dpipj(is2,is1)
t134 = t133**2
som(1) = 160*t128*t132*t134
t137 = piDpj(ip2,is2)
t138 = t130*t137
t139 = t134*t133
som(2) = -40*t128*t138*t139
som(3) = -88*t128*t131*t139
t144 = t127**2
t146 = t134**2
som(4) = 9*t126*t144*t146
t148 = t126*t129
t149 = t131*t130
t150 = t149*t137
som(5) = -128*t148*t150*t133
t153 = t131**2
som(6) = -256*t148*t153*t133
t156 = t129**2
som(7) = 256*t126*t156*t153
t160 = t137**2
t161 = t160*t134
som(8) = -16*t126*t131*t161
som(9) = 64*t126*t149*t137*t134
som(10) = 80*t126*t153*t134
t168 = t126**2
t169 = t168*t127
t171 = t138*t133
som(11) = 128*t169*t129*t171
som(12) = 576*t169*t132*t133
som(13) = -512*t169*t156*t131
som(14) = -88*t169*t138*t134
som(15) = -192*t169*t131*t134
som(16) = 40*t169*t161
t182 = t168*t144
som(17) = -96*t182*t129*t134
som(18) = 60*t182*t139
t186 = t168*t129
som(19) = 128*t186*t131*t160
som(20) = -128*t186*t150
som(21) = -64*t186*t153
som(22) = -32*t168*t130*t160*t137*t133
som(23) = 64*t168*t149*t137*t133
som(24) = 32*t168*t153*t133
t200 = t168*t126
t201 = t200*t127
som(25) = 128*t201*t129*t130*t137
som(26) = 160*t201*t132
som(27) = -128*t201*t129*t160
t208 = piDpj(ip2,is1)
t210 = t130*t208*t137
som(28) = 32*t201*t210
som(29) = -88*t201*t171
som(30) = -88*t201*t131*t133
t215 = t208*t160
som(31) = -16*t201*t215
som(32) = 48*t201*t160*t133
t219 = t200*t144
som(33) = -320*t219*t129*t133
som(34) = 256*t219*t156
som(35) = 118*t219*t134
t225 = t200*xpi(ip3)
som(36) = -16*t225*t210
som(37) = 8*t225*t215
t228 = t200*t129
som(38) = 16*t228*t210
som(39) = -8*t228*t215
t233 = dpipj(is3,ip1)
som(40) = -16*t200*t130*t208*t137*t233
som(41) = 8*t200*t208*t160*t233
t239 = t168**2
t240 = t239*t127
som(42) = -40*t240*t138
som(43) = -8*t240*t131
som(44) = 40*t240*t160
t244 = t239*t144
som(45) = -96*t244*t129
som(46) = 60*t244*t133
som(47) = 9*t239*t126*t144
som(48) = -8*t127*t131*t146
som(49) = -64*t129*t153*t134
som(50) = 32*t150*t139
som(51) = 32*t153*t139
* print '(7g20.12)',(som(i),i=1,51)
n=51
endif
*
s = 0
smax = 0
do 30 j=1,n
s = s + som(j)
smax = max(smax,som(j))
30 continue
if ( iwarn .lt. 3 ) then
hulp = 1/(16*xpi(ip1)**3*sdel2p**4*dy2z(3-iwarn)*
+ (y(1)-2*z(1))*(y(1)-2*z(2)))
else
hulp = 1/(16*xpi(ip1)**3*sdel2p**4*dy2z(7-iwarn)*
+ (y(3)-2*z(3))*(y(3)-2*z(4)))
endif
s = s*hulp
smax = smax*hulp
if ( smax .lt. xmax ) then
dy2z(iwarn) = s
xmax = smax
endif
else
n=0
endif
endif
ier = ier1
*
goto 200
* #] get dyz:
* #[ special case, get indices:
100 continue
if ( ivert.eq.2 ) then
is1 = 2
ip1 = 5
else
is1 = 1
ip1 = 6
endif
* #] special case, get indices:
* #[ xk = 0:
if ( xpi(ip1) .eq. 0 ) then
call fferr(88,ier)
endif
* #] xk = 0:
* #[ get ypm,zpm:
*
* special case del2s = 0, hence the roots are not the real roots
* but z_2'' = (z_2'-1)/delta, z''_3 = -z'_3/delta
*
hulp = sdel2s
disc = delps/sdel2p
if ( ivert .eq. 3 ) then
hulp = -hulp
disc = -disc
endif
if ( sdel2s .eq. 0 ) then
isoort(1) = 102
isoort(2) = 102
z(1) = piDpj(is1,3)/xpi(3)
z(2) = z(1)
else
isoort(1) = 101
isoort(2) = 101
call ffroot(z(1),z(2),xpi(3),piDpj(is1,3),xpi(is1),hulp,ier)
endif
call ffroot(y(1),y(2),xpi(3),piDpj(is1,3),etami(is1),disc,ier)
* #] get ypm,zpm:
* #[ get ypm1,zpm1:
z(3) = 1 - z(1)
z(4) = 1 - z(2)
if ( abs(z(3)).lt.xloss .or. abs(z(4)).lt.xloss ) then
if ( ivert.eq.2 ) then
call ffroot(z(4),z(3),xpi(3),piDpj(ip1,3),xpi(ip1),hulp,
+ ier)
else
call ffroot(z(4),z(3),xpi(3),-piDpj(ip1,3),xpi(ip1),hulp
+ ,ier)
endif
endif
y(3) = 1 - y(1)
y(4) = 1 - y(2)
if ( abs(y(3)) .lt. xloss .or. abs(y(4)) .lt. xloss ) then
if ( ivert .eq. 2 ) then
call ffroot(y(4),y(3),xpi(3),piDpj(ip1,3),etami(ip1),
+ disc,ier)
else
call ffroot(y(4),y(3),xpi(3),-piDpj(ip1,3),etami(ip1),
+ disc,ier)
endif
endif
* #] get ypm1,zpm1:
* #[ get dypzp, dypzm:
if ( isoort(1) .eq. 2 ) then
dyz(2,1) = disc/xpi(3)
dyz(2,2) = dyz(2,1)
elseif ( disc .gt. 0 .eqv. sdel2s .gt. 0 ) then
dyz(2,1) = ( disc + hulp )/xpi(3)
dyz(2,2) = etalam/(xpi(3)*dyz(2,1))
else
dyz(2,2) = ( disc - hulp )/xpi(3)
dyz(2,1) = etalam/(xpi(3)*dyz(2,2))
endif
dyz(1,1) = -dyz(2,2)
dyz(1,2) = -dyz(2,1)
d2yzz = 2*disc/xpi(3)
*
* these are very rarely needed, but ...
*
do 220 i=1,4
j = 2*((i+1)/2)
dy2z(i) = y(j) - 2*z(i)
smax = abs(y(j))
220 continue
* #] get dypzp, dypzm:
200 continue
*###] ffxxyz:
end
*###[ ffdwz:
subroutine ffdwz(dwz,z,i1,j1,l,alpha,alph1,xpi,dpipj,piDpj,
+ sdel2i,ns,ier)
***#[*comment:***********************************************************
* *
* Recalculate dwz(i1,j1) = w(i1) - z(j1) *
* *
***#]*comment:***********************************************************
* #[ declarations:
implicit none
*
* arguments:
*
integer i1,j1,l,ns,ier
- DOUBLE PRECISION dwz(2,2),z(4)
- DOUBLE PRECISION alpha,alph1,xpi(ns),dpipj(ns,ns),piDpj(ns,ns),
+ RealType dwz(2,2),z(4)
+ RealType alpha,alph1,xpi(ns),dpipj(ns,ns),piDpj(ns,ns),
+ sdel2i(3)
*
* local variables:
*
- DOUBLE PRECISION s(8),sum,fac,xmax
+ RealType s(8),ssum,fac,xmax
integer i
*
* common blocks:
*
#include "ff.h"
* #] declarations:
* #[ calculations:
if ( l .eq. 1 ) then
ier = ier + 100
elseif ( l .eq. 3 ) then
if ( (i1.eq.2 .and. j1.eq.1) .or. (i1.eq.1 .and. j1.eq.2) )
+ then
fac = 1D0/(sdel2i(2) + sdel2i(3))
s(1) = dpipj(6,5)*z(j1)
s(2) = -alph1*xpi(5)*z(j1+2)
if ( max(abs(dpipj(2,1)),abs(dpipj(5,6))) .lt.
+ max(abs(dpipj(2,6)),abs(dpipj(5,1))) ) then
s(3) = .5D0*dpipj(2,1)
s(4) = .5D0*dpipj(5,6)
else
s(3) = .5D0*dpipj(2,6)
s(4) = .5D0*dpipj(5,1)
endif
s(5) = piDpj(4,3)*piDpj(5,3)*fac
s(6) = -piDpj(4,3)*piDpj(6,3)*fac
s(7) = xpi(3)*dpipj(5,6)*fac
if ( i1 .eq. 1 ) then
- sum = s(1)+s(2)+s(3)+s(4) - (s(5)+s(6)+s(7))
+ ssum = s(1)+s(2)+s(3)+s(4) - (s(5)+s(6)+s(7))
else
- sum = s(1)+s(2)+s(3)+s(4) + s(5)+s(6)+s(7)
+ ssum = s(1)+s(2)+s(3)+s(4) + s(5)+s(6)+s(7)
endif
xmax = abs(s(1))
do 10 i=2,7
xmax = max(xmax,abs(s(i)))
10 continue
- if ( abs(sum) .lt. xloss*xmax ) then
+ if ( abs(ssum) .lt. xloss*xmax ) then
* this result is not used if it is not accurate (see
* ffxc0p)
ier = ier + 1
xmax = xmax/abs(alpha*xpi(5))
- dwz(i1,j1) = sum/(alpha*xpi(5))
+ dwz(i1,j1) = ssum/(alpha*xpi(5))
else
- dwz(i1,j1) = sum/(alpha*xpi(5))
+ dwz(i1,j1) = ssum/(alpha*xpi(5))
endif
else
ier = ier + 100
endif
endif
* #] calculations:
*###] ffdwz:
end
diff --git a/Looptools/util/ini.F b/Looptools/util/ini.F
--- a/Looptools/util/ini.F
+++ b/Looptools/util/ini.F
@@ -1,409 +1,664 @@
* ini.F
* routines for initializing and setting some parameters
* this file is part of LoopTools
-* last modified 9 Dec 10 th
+* last modified 3 Sep 14 th
+#include "externals.h"
+#include "types.h"
#include "defs.h"
subroutine clearcache
implicit none
#include "lt.h"
integer i
do i = 1, ncaches
cacheptr(1,1,i) = 0
cacheptr(2,1,i) = 0
+ savedptr(1,i) = 0
+ savedptr(2,i) = 0
enddo
end
************************************************************************
subroutine markcache
implicit none
#include "lt.h"
integer i
do i = 1, ncaches
savedptr(1,i) = cacheptr(1,1,i)
savedptr(2,i) = cacheptr(2,1,i)
enddo
end
************************************************************************
subroutine restorecache
implicit none
#include "lt.h"
integer i
do i = 1, ncaches
cacheptr(1,1,i) = savedptr(1,i)
cacheptr(2,1,i) = savedptr(2,i)
enddo
end
************************************************************************
* Legacy function, provided for compatibility only.
* Works only approximately as before!
subroutine setcachelast(base, offset)
implicit none
- double complex base(*)
+ ComplexType base(*)
integer offset
logical ini
data ini /.TRUE./
if( ini ) then
print *, "setcachelast is deprecated"
print *, "use clearcache or restorecache instead"
ini = .FALSE.
endif
if( offset .eq. 0 ) then
call clearcache
else
call restorecache
endif
end
************************************************************************
* Legacy function, provided for compatibility only.
* Works only approximately as before!
integer function getcachelast(base)
implicit none
- double complex base(*)
+ ComplexType base(*)
logical ini
data ini /.TRUE./
if( ini ) then
print *, "getcachelast is deprecated"
print *, "use markcache instead"
ini = .FALSE.
endif
getcachelast = 1
call markcache
end
************************************************************************
subroutine setmudim(mudim_)
implicit none
- double precision mudim_
+ RealType mudim_
#include "lt.h"
+ if( abs(mudim - mudim_) .gt. diffeps ) call clearcache
mudim = mudim_
- call clearcache
end
************************************************************************
- double precision function getmudim()
+ RealType function getmudim()
implicit none
#include "lt.h"
getmudim = mudim
end
************************************************************************
subroutine setdelta(delta_)
implicit none
- double precision delta_
+ RealType delta_
#include "lt.h"
+ if( abs(delta - delta_) .gt. diffeps ) call clearcache
delta = delta_
- call clearcache
end
************************************************************************
- double precision function getdelta()
+ RealType function getdelta()
implicit none
#include "lt.h"
getdelta = delta
end
************************************************************************
- subroutine setlambda(lambda_)
+ subroutine setuvdiv(uvdiv_)
implicit none
- double precision lambda_
+ RealType uvdiv_
#include "lt.h"
- lambda = lambda_
- call clearcache
+ if( abs(uvdiv - uvdiv_) .gt. diffeps ) call clearcache
+ uvdiv = uvdiv_
end
************************************************************************
- double precision function getlambda()
+ RealType function getuvdiv()
+ implicit none
+
+#include "lt.h"
+
+ getuvdiv = uvdiv
+ end
+
+************************************************************************
+
+ subroutine setlambda(lam_)
+ implicit none
+ RealType lam_
+
+#include "lt.h"
+
+ RealType lambda_
+
+ if( lam_ .ge. 0 .or. lam_ .eq. -1 .or. lam_ .eq. -2 ) then
+ lambda_ = dim(lam_, 0D0)
+ epsi = int(dim(0D0, lam_))
+ else
+ print *, "illegal value for lambda"
+ lambda_ = 0
+ epsi = 0
+ endif
+ if( abs(lambda - lambda_) .gt. diffeps ) call clearcache
+ lambda = lambda_
+ end
+
+************************************************************************
+
+ RealType function getlambda()
implicit none
#include "lt.h"
getlambda = lambda
end
************************************************************************
- subroutine setminmass(minmass_)
+ integer function getepsi()
implicit none
- double precision minmass_
#include "lt.h"
- minmass = minmass_
- call clearcache
+ getepsi = epsi
end
************************************************************************
- double precision function getminmass()
+ subroutine setminmass(minmass_)
+ implicit none
+ RealType minmass_
+
+#include "lt.h"
+
+ if( abs(minmass - minmass_) .gt. diffeps ) call clearcache
+ minmass = minmass_
+ end
+
+************************************************************************
+
+ RealType function getminmass()
implicit none
#include "lt.h"
getminmass = minmass
end
************************************************************************
subroutine setmaxdev(maxdev_)
implicit none
- double precision maxdev_
+ RealType maxdev_
#include "lt.h"
maxdev = maxdev_
end
************************************************************************
- double precision function getmaxdev()
+ RealType function getmaxdev()
implicit none
#include "lt.h"
getmaxdev = maxdev
end
************************************************************************
subroutine setwarndigits(warndigits_)
implicit none
integer warndigits_
#include "lt.h"
warndigits = warndigits_
end
************************************************************************
integer function getwarndigits()
implicit none
#include "lt.h"
getwarndigits = warndigits
end
************************************************************************
subroutine seterrdigits(errdigits_)
implicit none
integer errdigits_
#include "lt.h"
errdigits = errdigits_
end
************************************************************************
integer function geterrdigits()
implicit none
#include "lt.h"
geterrdigits = errdigits
end
************************************************************************
subroutine setversionkey(versionkey_)
implicit none
integer versionkey_
#include "lt.h"
versionkey = versionkey_
call clearcache
end
************************************************************************
integer function getversionkey()
implicit none
#include "lt.h"
getversionkey = versionkey
end
************************************************************************
subroutine setdebugkey(debugkey_)
implicit none
integer debugkey_
#include "lt.h"
debugkey = debugkey_
end
************************************************************************
integer function getdebugkey()
implicit none
#include "lt.h"
getdebugkey = debugkey
end
************************************************************************
subroutine setdebugrange(debugfrom_, debugto_)
implicit none
integer debugfrom_, debugto_
#include "lt.h"
debugfrom = debugfrom_
debugto = debugto_
end
************************************************************************
subroutine setcmpbits(cmpbits_)
implicit none
integer cmpbits_
#include "lt.h"
- cmpbits = cmpbits_
+ cmpbits = max(cmpbits_, 8 + KIND*4)
end
************************************************************************
integer function getcmpbits()
implicit none
#include "lt.h"
getcmpbits = cmpbits
end
************************************************************************
+ subroutine setdiffeps(diffeps_)
+ implicit none
+ RealType diffeps_
+
+#include "lt.h"
+
+ diffeps = diffeps_
+ end
+
+************************************************************************
+
+ RealType function getdiffeps()
+ implicit none
+
+#include "lt.h"
+
+ getdiffeps = diffeps
+ end
+
+************************************************************************
+
+ subroutine setzeroeps(zeroeps_)
+ implicit none
+ RealType zeroeps_
+
+#include "lt.h"
+
+ zeroeps = zeroeps_
+ end
+
+************************************************************************
+
+ RealType function getzeroeps()
+ implicit none
+
+#include "lt.h"
+
+ getzeroeps = zeroeps
+ end
+
+************************************************************************
+
* This silly subroutine is called from ffini while determining
* the working precision of the machine we're running on.
* It works around the optimizer to guarantee that we're not in
* fact determining the precision of the FPU registers.
subroutine ffset(res, x)
implicit none
- DOUBLE PRECISION res, x
+ RealType res, x
res = x
end
************************************************************************
block data LTNameData
implicit none
integer i
- character*6 paraname(Pee,2:5)
- common /ltparanames/ paraname
+#include "ltnames.h"
- character*8 coeffname(Nee,2:5)
- common /ltcoeffnames/ coeffname
+ data (paraname(i,1), i = 1, Paa) /
+ & "m" /
data (paraname(i,2), i = 1, Pbb) /
- & "p", "m1", "m2" /
+ & "m1", "m2", "p" /
data (paraname(i,3), i = 1, Pcc) /
- & "p1", "p2", "p1p2", "m1", "m2", "m3" /
+ & "m1", "m2", "m3", "p1", "p2", "p1p2" /
data (paraname(i,4), i = 1, Pdd) /
- & "p1", "p2", "p3", "p4", "p1p2", "p2p3",
- & "m1", "m2", "m3", "m4" /
+ & "m1", "m2", "m3", "m4",
+ & "p1", "p2", "p3", "p4", "p1p2", "p2p3" /
data (paraname(i,5), i = 1, Pee) /
+ & "m1", "m2", "m3", "m4", "m5",
& "p1", "p2", "p3", "p4", "p5",
- & "p1p2", "p2p3", "p3p4", "p4p5", "p5p1",
- & "m1", "m2", "m3", "m4", "m5" /
+ & "p1p2", "p2p3", "p3p4", "p4p5", "p5p1" /
+
+ data (coeffname(i,1), i = 1, Naa) /
+ & "aa0", "aa0:1", "aa0:2",
+ & "aa00", "aa00:1", "aa00:2" /
data (coeffname(i,2), i = 1, Nbb) /
- & "bb0", "bb1", "bb00", "bb11", "bb001", "bb111",
- & "dbb0", "dbb1", "dbb00", "dbb11" /
+ & "bb0", "bb0:1", "bb0:2",
+ & "bb1", "bb1:1", "bb1:2",
+ & "bb00", "bb00:1", "bb00:2",
+ & "bb11", "bb11:1", "bb11:2",
+ & "bb001", "bb001:1", "bb001:2",
+ & "bb111", "bb111:1", "bb111:2",
+ & "dbb0", "dbb0:1", "dbb0:2",
+ & "dbb1", "dbb1:1", "dbb1:2",
+ & "dbb00", "dbb00:1", "dbb00:2",
+ & "dbb11", "dbb11:1", "dbb11:2",
+ & "dbb001", "dbb001:1", "dbb001:2" /
data (coeffname(i,3), i = 1, Ncc) /
- & "cc0", "cc1", "cc2", "cc00", "cc11", "cc12", "cc22",
- & "cc001", "cc002", "cc111", "cc112", "cc122", "cc222",
- & "cc0000", "cc0011", "cc0012", "cc0022", "cc1111",
- & "cc1112", "cc1122", "cc1222", "cc2222" /
+ & "cc0", "cc0:1", "cc0:2",
+ & "cc1", "cc1:1", "cc1:2",
+ & "cc2", "cc2:1", "cc2:2",
+ & "cc00", "cc00:1", "cc00:2",
+ & "cc11", "cc11:1", "cc11:2",
+ & "cc12", "cc12:1", "cc12:2",
+ & "cc22", "cc22:1", "cc22:2",
+ & "cc001", "cc001:1", "cc001:2",
+ & "cc002", "cc002:1", "cc002:2",
+ & "cc111", "cc111:1", "cc111:2",
+ & "cc112", "cc112:1", "cc112:2",
+ & "cc122", "cc122:1", "cc122:2",
+ & "cc222", "cc222:1", "cc222:2",
+ & "cc0000", "cc0000:1", "cc0000:2",
+ & "cc0011", "cc0011:1", "cc0011:2",
+ & "cc0012", "cc0012:1", "cc0012:2",
+ & "cc0022", "cc0022:1", "cc0022:2",
+ & "cc1111", "cc1111:1", "cc1111:2",
+ & "cc1112", "cc1112:1", "cc1112:2",
+ & "cc1122", "cc1122:1", "cc1122:2",
+ & "cc1222", "cc1222:1", "cc1222:2",
+ & "cc2222", "cc2222:1", "cc2222:2" /
data (coeffname(i,4), i = 1, Ndd) /
- & "dd0", "dd1", "dd2", "dd3", "dd00", "dd11", "dd12",
- & "dd13", "dd22", "dd23", "dd33", "dd001", "dd002", "dd003",
- & "dd111", "dd112", "dd113", "dd122", "dd123", "dd133",
- & "dd222", "dd223", "dd233", "dd333", "dd0000", "dd0011",
- & "dd0012", "dd0013", "dd0022", "dd0023", "dd0033", "dd1111",
- & "dd1112", "dd1113", "dd1122", "dd1123", "dd1133", "dd1222",
- & "dd1223", "dd1233", "dd1333", "dd2222", "dd2223", "dd2233",
- & "dd2333", "dd3333", "dd00001", "dd00002", "dd00003",
- & "dd00111", "dd00112", "dd00113", "dd00122", "dd00123",
- & "dd00133", "dd00222", "dd00223", "dd00233", "dd00333",
- & "dd11111", "dd11112", "dd11113", "dd11122", "dd11123",
- & "dd11133", "dd11222", "dd11223", "dd11233", "dd11333",
- & "dd12222", "dd12223", "dd12233", "dd12333", "dd13333",
- & "dd22222", "dd22223", "dd22233", "dd22333", "dd23333",
- & "dd33333" /
+ & "dd0", "dd0:1", "dd0:2",
+ & "dd1", "dd1:1", "dd1:2",
+ & "dd2", "dd2:1", "dd2:2",
+ & "dd3", "dd3:1", "dd3:2",
+ & "dd00", "dd00:1", "dd00:2",
+ & "dd11", "dd11:1", "dd11:2",
+ & "dd12", "dd12:1", "dd12:2",
+ & "dd13", "dd13:1", "dd13:2",
+ & "dd22", "dd22:1", "dd22:2",
+ & "dd23", "dd23:1", "dd23:2",
+ & "dd33", "dd33:1", "dd33:2",
+ & "dd001", "dd001:1", "dd001:2",
+ & "dd002", "dd002:1", "dd002:2",
+ & "dd003", "dd003:1", "dd003:2",
+ & "dd111", "dd111:1", "dd111:2",
+ & "dd112", "dd112:1", "dd112:2",
+ & "dd113", "dd113:1", "dd113:2",
+ & "dd122", "dd122:1", "dd122:2",
+ & "dd123", "dd123:1", "dd123:2",
+ & "dd133", "dd133:1", "dd133:2",
+ & "dd222", "dd222:1", "dd222:2",
+ & "dd223", "dd223:1", "dd223:2",
+ & "dd233", "dd233:1", "dd233:2",
+ & "dd333", "dd333:1", "dd333:2",
+ & "dd0000", "dd0000:1", "dd0000:2",
+ & "dd0011", "dd0011:1", "dd0011:2",
+ & "dd0012", "dd0012:1", "dd0012:2",
+ & "dd0013", "dd0013:1", "dd0013:2",
+ & "dd0022", "dd0022:1", "dd0022:2",
+ & "dd0023", "dd0023:1", "dd0023:2",
+ & "dd0033", "dd0033:1", "dd0033:2",
+ & "dd1111", "dd1111:1", "dd1111:2",
+ & "dd1112", "dd1112:1", "dd1112:2",
+ & "dd1113", "dd1113:1", "dd1113:2",
+ & "dd1122", "dd1122:1", "dd1122:2",
+ & "dd1123", "dd1123:1", "dd1123:2",
+ & "dd1133", "dd1133:1", "dd1133:2",
+ & "dd1222", "dd1222:1", "dd1222:2",
+ & "dd1223", "dd1223:1", "dd1223:2",
+ & "dd1233", "dd1233:1", "dd1233:2",
+ & "dd1333", "dd1333:1", "dd1333:2",
+ & "dd2222", "dd2222:1", "dd2222:2",
+ & "dd2223", "dd2223:1", "dd2223:2",
+ & "dd2233", "dd2233:1", "dd2233:2",
+ & "dd2333", "dd2333:1", "dd2333:2",
+ & "dd3333", "dd3333:1", "dd3333:2",
+ & "dd00001", "dd00001:1", "dd00001:2",
+ & "dd00002", "dd00002:1", "dd00002:2",
+ & "dd00003", "dd00003:1", "dd00003:2",
+ & "dd00111", "dd00111:1", "dd00111:2",
+ & "dd00112", "dd00112:1", "dd00112:2",
+ & "dd00113", "dd00113:1", "dd00113:2",
+ & "dd00122", "dd00122:1", "dd00122:2",
+ & "dd00123", "dd00123:1", "dd00123:2",
+ & "dd00133", "dd00133:1", "dd00133:2",
+ & "dd00222", "dd00222:1", "dd00222:2",
+ & "dd00223", "dd00223:1", "dd00223:2",
+ & "dd00233", "dd00233:1", "dd00233:2",
+ & "dd00333", "dd00333:1", "dd00333:2",
+ & "dd11111", "dd11111:1", "dd11111:2",
+ & "dd11112", "dd11112:1", "dd11112:2",
+ & "dd11113", "dd11113:1", "dd11113:2",
+ & "dd11122", "dd11122:1", "dd11122:2",
+ & "dd11123", "dd11123:1", "dd11123:2",
+ & "dd11133", "dd11133:1", "dd11133:2",
+ & "dd11222", "dd11222:1", "dd11222:2",
+ & "dd11223", "dd11223:1", "dd11223:2",
+ & "dd11233", "dd11233:1", "dd11233:2",
+ & "dd11333", "dd11333:1", "dd11333:2",
+ & "dd12222", "dd12222:1", "dd12222:2",
+ & "dd12223", "dd12223:1", "dd12223:2",
+ & "dd12233", "dd12233:1", "dd12233:2",
+ & "dd12333", "dd12333:1", "dd12333:2",
+ & "dd13333", "dd13333:1", "dd13333:2",
+ & "dd22222", "dd22222:1", "dd22222:2",
+ & "dd22223", "dd22223:1", "dd22223:2",
+ & "dd22233", "dd22233:1", "dd22233:2",
+ & "dd22333", "dd22333:1", "dd22333:2",
+ & "dd23333", "dd23333:1", "dd23333:2",
+ & "dd33333", "dd33333:1", "dd33333:2" /
data (coeffname(i,5), i = 1, Nee) /
- & "ee0", "ee1", "ee2", "ee3", "ee4", "ee00", "ee11",
- & "ee12", "ee13", "ee14", "ee22", "ee23", "ee24", "ee33",
- & "ee34", "ee44", "ee001", "ee002", "ee003", "ee004",
- & "ee111", "ee112", "ee113", "ee114", "ee122", "ee123",
- & "ee124", "ee133", "ee134", "ee144", "ee222", "ee223",
- & "ee224", "ee233", "ee234", "ee244", "ee333", "ee334",
- & "ee344", "ee444", "ee0000", "ee0011", "ee0012", "ee0013",
- & "ee0014", "ee0022", "ee0023", "ee0024", "ee0033", "ee0034",
- & "ee0044", "ee1111", "ee1112", "ee1113", "ee1114", "ee1122",
- & "ee1123", "ee1124", "ee1133", "ee1134", "ee1144", "ee1222",
- & "ee1223", "ee1224", "ee1233", "ee1234", "ee1244", "ee1333",
- & "ee1334", "ee1344", "ee1444", "ee2222", "ee2223", "ee2224",
- & "ee2233", "ee2234", "ee2244", "ee2333", "ee2334", "ee2344",
- & "ee2444", "ee3333", "ee3334", "ee3344", "ee3444", "ee4444" /
+ & "ee0", "ee0:1", "ee0:2",
+ & "ee1", "ee1:1", "ee1:2",
+ & "ee2", "ee2:1", "ee2:2",
+ & "ee3", "ee3:1", "ee3:2",
+ & "ee4", "ee4:1", "ee4:2",
+ & "ee00", "ee00:1", "ee00:2",
+ & "ee11", "ee11:1", "ee11:2",
+ & "ee12", "ee12:1", "ee12:2",
+ & "ee13", "ee13:1", "ee13:2",
+ & "ee14", "ee14:1", "ee14:2",
+ & "ee22", "ee22:1", "ee22:2",
+ & "ee23", "ee23:1", "ee23:2",
+ & "ee24", "ee24:1", "ee24:2",
+ & "ee33", "ee33:1", "ee33:2",
+ & "ee34", "ee34:1", "ee34:2",
+ & "ee44", "ee44:1", "ee44:2",
+ & "ee001", "ee001:1", "ee001:2",
+ & "ee002", "ee002:1", "ee002:2",
+ & "ee003", "ee003:1", "ee003:2",
+ & "ee004", "ee004:1", "ee004:2",
+ & "ee111", "ee111:1", "ee111:2",
+ & "ee112", "ee112:1", "ee112:2",
+ & "ee113", "ee113:1", "ee113:2",
+ & "ee114", "ee114:1", "ee114:2",
+ & "ee122", "ee122:1", "ee122:2",
+ & "ee123", "ee123:1", "ee123:2",
+ & "ee124", "ee124:1", "ee124:2",
+ & "ee133", "ee133:1", "ee133:2",
+ & "ee134", "ee134:1", "ee134:2",
+ & "ee144", "ee144:1", "ee144:2",
+ & "ee222", "ee222:1", "ee222:2",
+ & "ee223", "ee223:1", "ee223:2",
+ & "ee224", "ee224:1", "ee224:2",
+ & "ee233", "ee233:1", "ee233:2",
+ & "ee234", "ee234:1", "ee234:2",
+ & "ee244", "ee244:1", "ee244:2",
+ & "ee333", "ee333:1", "ee333:2",
+ & "ee334", "ee334:1", "ee334:2",
+ & "ee344", "ee344:1", "ee344:2",
+ & "ee444", "ee444:1", "ee444:2",
+ & "ee0000", "ee0000:1", "ee0000:2",
+ & "ee0011", "ee0011:1", "ee0011:2",
+ & "ee0012", "ee0012:1", "ee0012:2",
+ & "ee0013", "ee0013:1", "ee0013:2",
+ & "ee0014", "ee0014:1", "ee0014:2",
+ & "ee0022", "ee0022:1", "ee0022:2",
+ & "ee0023", "ee0023:1", "ee0023:2",
+ & "ee0024", "ee0024:1", "ee0024:2",
+ & "ee0033", "ee0033:1", "ee0033:2",
+ & "ee0034", "ee0034:1", "ee0034:2",
+ & "ee0044", "ee0044:1", "ee0044:2",
+ & "ee1111", "ee1111:1", "ee1111:2",
+ & "ee1112", "ee1112:1", "ee1112:2",
+ & "ee1113", "ee1113:1", "ee1113:2",
+ & "ee1114", "ee1114:1", "ee1114:2",
+ & "ee1122", "ee1122:1", "ee1122:2",
+ & "ee1123", "ee1123:1", "ee1123:2",
+ & "ee1124", "ee1124:1", "ee1124:2",
+ & "ee1133", "ee1133:1", "ee1133:2",
+ & "ee1134", "ee1134:1", "ee1134:2",
+ & "ee1144", "ee1144:1", "ee1144:2",
+ & "ee1222", "ee1222:1", "ee1222:2",
+ & "ee1223", "ee1223:1", "ee1223:2",
+ & "ee1224", "ee1224:1", "ee1224:2",
+ & "ee1233", "ee1233:1", "ee1233:2",
+ & "ee1234", "ee1234:1", "ee1234:2",
+ & "ee1244", "ee1244:1", "ee1244:2",
+ & "ee1333", "ee1333:1", "ee1333:2",
+ & "ee1334", "ee1334:1", "ee1334:2",
+ & "ee1344", "ee1344:1", "ee1344:2",
+ & "ee1444", "ee1444:1", "ee1444:2",
+ & "ee2222", "ee2222:1", "ee2222:2",
+ & "ee2223", "ee2223:1", "ee2223:2",
+ & "ee2224", "ee2224:1", "ee2224:2",
+ & "ee2233", "ee2233:1", "ee2233:2",
+ & "ee2234", "ee2234:1", "ee2234:2",
+ & "ee2244", "ee2244:1", "ee2244:2",
+ & "ee2333", "ee2333:1", "ee2333:2",
+ & "ee2334", "ee2334:1", "ee2334:2",
+ & "ee2344", "ee2344:1", "ee2344:2",
+ & "ee2444", "ee2444:1", "ee2444:2",
+ & "ee3333", "ee3333:1", "ee3333:2",
+ & "ee3334", "ee3334:1", "ee3334:2",
+ & "ee3344", "ee3344:1", "ee3344:2",
+ & "ee3444", "ee3444:1", "ee3444:2",
+ & "ee4444", "ee4444:1", "ee4444:2" /
end
diff --git a/Looptools/util/solve-Eigen.F b/Looptools/util/solve-Eigen.F
--- a/Looptools/util/solve-Eigen.F
+++ b/Looptools/util/solve-Eigen.F
@@ -1,287 +1,289 @@
* solve-Eigen.F
* computation of the inverse and solution of a linear system
* by diagonalizing the matrix with the Jacobi algorithm
* code adapted from the "Handbook" routines for complex A
* (Wilkinson, Reinsch: Handbook for Automatic Computation, p. 202)
* this file is part of LoopTools
* last modified 9 Dec 10 th
+#include "externals.h"
+#include "types.h"
#include "defs.h"
* A matrix is considered diagonal if the sum of the squares
* of the off-diagonal elements is less than EPS.
#define EPS 2D0**(-102)
************************************************************************
** XEigen diagonalizes a complex symmetric n-by-n matrix.
** Input: n, A = n-by-n matrix
** (only the upper triangle of A needs to be filled).
** Output: d = vector of eigenvalues, U = transformation matrix
** these fulfill diag(d) = U A U^T = U A U^-1 with U U^T = 1.
subroutine XEigen(n, A,ldA, d, U,ldU)
implicit none
integer n, ldA, ldU
QVAR A(ldA,*), U(ldU,*), d(*)
integer p, q, j, sweep
QREAL red, off, thresh
QVAR delta, t, invc, s, x, y
QVAR ev(2,MAXDIM)
QREAL sq
QVAR c
sq(c) = QRE(c*QCC(c))
do p = 1, n
ev(1,p) = 0
ev(2,p) = A(p,p)
d(p) = ev(2,p)
enddo
do p = 1, n
do q = 1, n
U(q,p) = 0
enddo
U(p,p) = 1
enddo
red = .04D0/n**4
do sweep = 1, 50
off = 0
do q = 2, n
do p = 1, q - 1
off = off + sq(A(p,q))
enddo
enddo
if( .not. off .gt. EPS ) return
thresh = 0
if( sweep .lt. 4 ) thresh = off*red
do q = 2, n
do p = 1, q - 1
delta = A(p,q)
off = sq(delta)
if( sweep .gt. 4 .and. off .lt.
& EPS*max(sq(ev(2,p)), sq(ev(2,q))) ) then
A(p,q) = 0
else if( off .gt. thresh ) then
x = .5D0*(ev(2,p) - ev(2,q))
y = sqrt(x**2 + delta**2)
t = x - y
s = x + y
if( sq(t) .lt. sq(s) ) t = s
t = delta/t
delta = delta*t
ev(1,p) = ev(1,p) + delta
ev(2,p) = d(p) + ev(1,p)
ev(1,q) = ev(1,q) - delta
ev(2,q) = d(q) + ev(1,q)
invc = sqrt(t**2 + 1)
s = t/invc
t = t/(invc + 1)
do j = 1, p - 1
x = A(j,p)
y = A(j,q)
A(j,p) = x + s*(y - t*x)
A(j,q) = y - s*(x + t*y)
enddo
do j = p + 1, q - 1
x = A(p,j)
y = A(j,q)
A(p,j) = x + s*(y - t*x)
A(j,q) = y - s*(x + t*y)
enddo
do j = q + 1, n
x = A(p,j)
y = A(q,j)
A(p,j) = x + s*(y - t*x)
A(q,j) = y - s*(x + t*y)
enddo
A(p,q) = 0
do j = 1, n
x = U(p,j)
y = U(q,j)
U(p,j) = x + s*(y - t*x)
U(q,j) = y - s*(x + t*y)
enddo
endif
enddo
enddo
do p = 1, n
ev(1,p) = 0
d(p) = ev(2,p)
enddo
enddo
print *, "Bad convergence in XEigen"
end
************************************************************************
subroutine XDet(n, A,ldA, det)
implicit none
integer n, ldA
QVAR A(ldA,*), det
QVAR d(MAXDIM), U(MAXDIM,MAXDIM)
integer p
call XEigen(n, A,ldA, d, U,MAXDIM)
det = 1
do p = 1, n
det = det*d(p)
enddo
end
************************************************************************
** XInverse forms the (pseudo)inverse of a symmetric n-by-n matrix.
** Input: n, A = n-by-n matrix, symmetric
** (only the upper triangle of A needs to be filled).
** Output: Ainv = (pseudo)inverse of A
subroutine XInverse(n, A,ldA, Ainv,ldAinv)
implicit none
integer n, ldA, ldAinv
QVAR A(ldA,*), Ainv(ldAinv,*)
integer p, q, j
QVAR U(MAXDIM,MAXDIM), d(MAXDIM), t
#if 0
PRINT *, "SEigen"
PRINT *, "A11=", A(1,1)
PRINT *, "A12=", A(1,2)
PRINT *, "A21=", A(2,1)
PRINT *, "A22=", A(2,2)
if( ldA .gt. 2 ) then
PRINT *, "A13=", A(1,3), A(3,1)
PRINT *, "A23=", A(2,3), A(3,2)
PRINT *, "A33=", A(3,3)
endif
PRINT *, "-----------"
#endif
call XEigen(n, A,ldA, d, U,MAXDIM)
* form (pseudo)inverse U^T d^-1 U
do p = 1, n
do q = 1, n
t = 0
do j = 1, n
if( abs(d(j)) .gt. EPS )
& t = t + U(j,q)*U(j,p)/d(j)
enddo
Ainv(q,p) = t
enddo
enddo
#if 0
PRINT *, "d1=", d(1)
PRINT *, "d2=", d(2)
if( ldA .gt. 2 ) PRINT *, "d3=", d(3)
PRINT *, "-----------"
PRINT *, "U11=", U(1,1)
PRINT *, "U12=", U(1,2)
PRINT *, "U21=", U(2,1)
PRINT *, "U22=", U(2,2)
if( ldA .gt. 2 ) then
PRINT *, "U13=", U(1,3)
PRINT *, "U23=", U(2,3)
PRINT *, "U31=", U(3,1)
PRINT *, "U32=", U(3,2)
PRINT *, "U33=", U(3,3)
endif
PRINT *, "-----------"
PRINT *, "Ai11=", Ainv(1,1)
PRINT *, "Ai12=", Ainv(1,2)
PRINT *, "Ai21=", Ainv(2,1)
PRINT *, "Ai22=", Ainv(2,2)
if( ldA .gt. 2 ) then
PRINT *, "Ai13=", Ainv(1,3)
PRINT *, "Ai23=", Ainv(2,3)
PRINT *, "Ai31=", Ainv(3,1)
PRINT *, "Ai32=", Ainv(3,2)
PRINT *, "Ai33=", Ainv(3,3)
endif
PRINT *, "-----------"
#endif
end
************************************************************************
subroutine XSolve(n, A,ldA, Ainv,ldAinv, b)
implicit none
integer n, ldA, ldAinv
QVAR A(ldA,*), Ainv(ldAinv,*)
- double complex b(*)
+ ComplexType b(*)
integer i, j
- double complex x(MAXDIM)
+ ComplexType x(MAXDIM)
#if defined(QUAD) && !defined(COMPLEXPARA)
QVAR tr, ti
do i = 1, n
tr = 0
ti = 0
do j = 1, n
- tr = tr + Ainv(i,j)*DBLE(b(j))
- ti = ti + Ainv(i,j)*DIMAG(b(j))
+ tr = tr + Ainv(i,j)*Re(b(j))
+ ti = ti + Ainv(i,j)*Im(b(j))
enddo
- x(i) = DCMPLX(tr, ti)
+ x(i) = ToComplex(tr, ti)
enddo
#else
- double complex delta(MAXDIM), t
+ ComplexType delta(MAXDIM), t
do i = 1, n
t = 0
do j = 1, n
t = t + Ainv(i,j)*b(j)
enddo
x(i) = t
enddo
* improve on x
do i = 1, n
t = 0
do j = 1, n
t = t + A(i,j)*x(j)
enddo
delta(i) = b(i) - t
enddo
do i = 1, n
t = 0
do j = 1, n
t = t + Ainv(i,j)*delta(j)
enddo
x(i) = x(i) + t
enddo
#endif
do i = 1, n
b(i) = x(i)
enddo
end
diff --git a/Looptools/util/solve-LU.F b/Looptools/util/solve-LU.F
--- a/Looptools/util/solve-LU.F
+++ b/Looptools/util/solve-LU.F
@@ -1,238 +1,219 @@
* solve-LU.F
* Solution of the linear system A.x = B by LU decomposition
* with partial pivoting
* this file is part of LoopTools
-* last modified 14 Dec 10 th
+* last modified 26 Jan 14 th
* Author: Michael Rauch, 7 Dec 2004
* Reference: Folkmar Bornemann, lecture notes to
* Numerische Mathematik 1, Technical University, Munich, Germany
+#include "externals.h"
+#include "types.h"
#include "defs.h"
#define EPS 2D0**(-51)
************************************************************************
* XDecomp computes the LU decomposition of the n-by-n matrix A
* by Gaussian Elimination with partial pivoting;
* compact (in situ) storage scheme
* Input:
* A: n-by-n matrix to LU-decompose
* n: dimension of A
* Output:
* A: mangled LU decomposition of A in the form
* ( y11 y12 ... y1n )
* ( x21 y22 ... y2n )
* ( x31 x32 ... y3n )
* ( ............... )
* ( xn1 xn2 ... ynn )
* where
* ( 1 0 ... 0 ) ( y11 y12 ... y1n )
* ( x21 1 ... 0 ) ( 0 y22 ... y2n )
* ( x31 x32 ... 0 ) ( 0 0 ... y3n ) = Permutation(A)
* ( ............... ) ( ............... )
* ( xn1 xn2 ... 1 ) ( 0 0 ... ynn )
* perm: permutation vector
subroutine XDecomp(n, A,ldA, perm)
implicit none
integer n, ldA, perm(*)
QVAR A(ldA,*)
integer i, j, k, pj, invperm(MAXDIM)
QVAR tmp
QREAL absA, pabsA
do j = 1, n
invperm(j) = j
enddo
do j = 1, n
* do U part (minus diagonal one)
do i = 2, j - 1
tmp = 0
do k = 1, i - 1
tmp = tmp + A(i,k)*A(k,j)
enddo
A(i,j) = A(i,j) - tmp
enddo
* do L part (plus diagonal from U case)
pabsA = -1
+ pj = j
do i = j, n
tmp = 0
do k = 1, j - 1
tmp = tmp + A(i,k)*A(k,j)
enddo
A(i,j) = A(i,j) - tmp
* do partial pivoting ...
* find the pivot
absA = abs(A(i,j))
if( absA .gt. pabsA ) then
pabsA = absA
pj = i
endif
enddo
- perm(invperm(pj)) = j
+ perm(invperm(pj)) = j
* exchange rows
if( pj .ne. j ) then
invperm(pj) = invperm(j)
do k = 1, n
tmp = A(j,k)
A(j,k) = A(pj,k)
A(pj,k) = tmp
enddo
endif
* division by the pivot element
if( abs(A(j,j)) .gt. EPS ) then
tmp = 1/A(j,j)
do i = j + 1, n
A(i,j) = A(i,j)*tmp
enddo
endif
enddo
end
************************************************************************
* XSolve computes the x in A.x = b from the LU-decomposed A.
* Input:
* A: LU-decomposed n-by-n matrix A
* b: input vector b in A.x = b
* n: dimension of A
* p: permutation vector from LU decomposition
* Output:
* b: solution vector x in A.x = b
subroutine XSolve(n, A,ldA, b)
implicit none
integer n, ldA
QVAR A(ldA,*)
- double complex b(*)
+ ComplexType b(0:2,*)
integer i, j
- double complex tmp
+ ComplexType tmp(0:2)
* forward substitution L.y = b
do i = 1, n
tmp = 0
do j = 1, i - 1
- tmp = tmp + A(i,j)*b(j)
+ tmp = tmp + A(i,j)*b(:,j)
enddo
- b(i) = b(i) - tmp
+ b(:,i) = b(:,i) - tmp
enddo
* backward substitution U.x = y
do i = n, 1, -1
tmp = 0
do j = i + 1, n
- tmp = tmp + A(i,j)*b(j)
+ tmp = tmp + A(i,j)*b(:,j)
enddo
- b(i) = (b(i) - tmp)/A(i,i)
+ b(:,i) = (b(:,i) - tmp)/A(i,i)
enddo
end
************************************************************************
-
-#ifdef COMPLEXPARA
-
-#undef RSolve
-#define RSolve XSolve
-
-#else
-
-* same as XSolve but for real vector b
-
- subroutine RSolve(n, A,ldA, b)
- implicit none
- integer n, ldA
- QVAR A(ldA,*), b(*)
-
- integer i, j
- QVAR tmp
-
-* forward substitution L.y = b
- do i = 1, n
- tmp = 0
- do j = 1, i - 1
- tmp = tmp + A(i,j)*b(j)
- enddo
- b(i) = b(i) - tmp
- enddo
-
-* backward substitution U.x = y
- do i = n, 1, -1
- tmp = 0
- do j = i + 1, n
- tmp = tmp + A(i,j)*b(j)
- enddo
- b(i) = (b(i) - tmp)/A(i,i)
- enddo
- end
-
-#endif
-
-************************************************************************
* Det computes the determinant of a matrix.
* Input:
* A: n-by-n matrix A
* n: dimension of A
* Output:
* determinant of A
* Warning: A is overwritten
subroutine XDet(n, A,ldA, det)
implicit none
integer n, ldA
QVAR A(ldA,*), det
integer i, j, s, perm(MAXDIM)
call XDecomp(n, A,ldA, perm)
det = 1
s = 0
do i = 1, n
det = det*A(i,i)
j = i
do while( perm(j) .ne. i )
j = j + 1
enddo
if( j .ne. i ) then
perm(j) = perm(i)
s = s + 1
endif
enddo
if( iand(s, 1) .ne. 0 ) det = -det
end
************************************************************************
* Inverse computes the inverse of a matrix.
* Input:
* A: n-by-n matrix A
* n: dimension of A
* Output:
* A: mangled LU decomposition of A
* Ainv: inverse of A
* perm: permutation vector
subroutine XInverse(n, A,ldA, Ainv,ldAinv, perm)
implicit none
integer n, ldA, ldAinv, perm(*)
QVAR A(ldA,*), Ainv(ldAinv,*)
- integer i, j
+ integer i, j, k
+ QVAR tmp
call XDecomp(n, A,ldA, perm)
do i = 1, n
do j = 1, n
Ainv(j,i) = 0
enddo
Ainv(perm(i),i) = 1
- call RSolve(n, A,ldA, Ainv(1,i))
+
+* forward substitution L.y = b
+ do j = 1, n
+ tmp = 0
+ do k = 1, j - 1
+ tmp = tmp + A(j,k)*Ainv(k,i)
+ enddo
+ Ainv(j,i) = Ainv(j,i) - tmp
+ enddo
+
+* backward substitution U.x = y
+ do j = n, 1, -1
+ tmp = 0
+ do k = j + 1, n
+ tmp = tmp + A(j,k)*Ainv(k,i)
+ enddo
+ Ainv(j,i) = (Ainv(j,i) - tmp)/A(j,j)
+ enddo
enddo
end
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/DIS/DISBase.cc b/MatrixElement/DIS/DISBase.cc
--- a/MatrixElement/DIS/DISBase.cc
+++ b/MatrixElement/DIS/DISBase.cc
@@ -1,1178 +1,1178 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DISBase class.
//
#include "DISBase.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "Herwig/Utilities/Maths.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/PDT/StandardMatchers.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h"
#include "Herwig/PDT/StandardMatchers.h"
#include "Herwig/Models/StandardModel/StandardModel.h"
#include <numeric>
#include "Herwig/Shower/RealEmissionProcess.h"
#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h"
#include "Herwig/Shower/QTilde/Base/Branching.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
// namespace {
// using namespace Herwig;
// using namespace ThePEG::Helicity;
//
// void debuggingMatrixElement(bool BGF,const Lorentz5Momentum & pin,
// const Lorentz5Momentum & p1,
// const Lorentz5Momentum & p2,
// tcPDPtr gluon,
// const Lorentz5Momentum & pl1,
// const Lorentz5Momentum & pl2,
// const Lorentz5Momentum & pq1,
// const Lorentz5Momentum & pq2,
// tcPDPtr lepton1,tcPDPtr lepton2,
// tcPDPtr quark1 ,tcPDPtr quark2,
// Energy2 Q2,double phi, double x2, double x3,
// double xperp, double zp, double xp,
// const vector<double> & azicoeff,
// bool normalize) {
// tcHwSMPtr hwsm=ThePEG::dynamic_ptr_cast<tcHwSMPtr>
// (CurrentGenerator::current().standardModel());
// assert(hwsm);
// vector<AbstractFFVVertexPtr> weakVertex;
// vector<PDPtr> bosons;
// AbstractFFVVertexPtr strongVertex = hwsm->vertexFFG();
// if(lepton1->id()==lepton2->id()) {
// weakVertex.push_back(hwsm->vertexFFZ());
// bosons.push_back(hwsm->getParticleData(ParticleID::Z0));
// weakVertex.push_back(hwsm->vertexFFP());
// bosons.push_back(hwsm->getParticleData(ParticleID::gamma));
// }
// else {
// weakVertex.push_back(hwsm->vertexFFW());
// bosons.push_back(hwsm->getParticleData(ParticleID::Wplus));
// }
// if(!BGF) {
// SpinorWaveFunction l1,q1,qp1;
// SpinorBarWaveFunction l2,q2,qp2;
// VectorWaveFunction gl(p2,gluon,outgoing);
// if(lepton1->id()>0) {
// l1 = SpinorWaveFunction (pl1,lepton1,incoming);
// l2 = SpinorBarWaveFunction(pl2,lepton2,outgoing);
// }
// else {
// l1 = SpinorWaveFunction (pl2,lepton2,outgoing);
// l2 = SpinorBarWaveFunction(pl1,lepton1,incoming);
// }
// if(quark1->id()>0) {
// q1 = SpinorWaveFunction (pq1,quark1,incoming);
// q2 = SpinorBarWaveFunction(pq2,quark2,outgoing);
// qp1 = SpinorWaveFunction (pin,quark1,incoming);
// qp2 = SpinorBarWaveFunction(p1 ,quark2,outgoing);
// }
// else {
// q1 = SpinorWaveFunction (pq2,quark2,outgoing);
// q2 = SpinorBarWaveFunction(pq1,quark1,incoming);
// qp1 = SpinorWaveFunction (p1 ,quark2,outgoing);
// qp2 = SpinorBarWaveFunction(pin,quark1,incoming);
// }
// double lome(0.),realme(0.);
// for(unsigned int lhel1=0;lhel1<2;++lhel1) {
// l1.reset(lhel1);
// for(unsigned int lhel2=0;lhel2<2;++lhel2) {
// l2.reset(lhel2);
// for(unsigned int qhel1=0;qhel1<2;++qhel1) {
// q1.reset(qhel1);
// qp1.reset(qhel1);
// for(unsigned int qhel2=0;qhel2<2;++qhel2) {
// q2.reset(qhel2);
// qp2.reset(qhel2);
// // leading order matrix element
// Complex diagLO(0.);
// for(unsigned int ix=0;ix<weakVertex.size();++ix) {
// VectorWaveFunction inter =
// weakVertex[ix]->evaluate(Q2,3,bosons[ix],l1,l2);
// diagLO += weakVertex[ix]->evaluate(Q2,q1,q2,inter);
// }
// lome += norm(diagLO);
// // real emission matrix element
// for(unsigned int ghel=0;ghel<2;++ghel) {
// gl.reset(2*ghel);
// Complex diagReal(0.);
// for(unsigned int ix=0;ix<weakVertex.size();++ix) {
// VectorWaveFunction inter =
// weakVertex[ix]->evaluate(Q2,3,bosons[ix],l1,l2);
// SpinorWaveFunction off1 =
// strongVertex->evaluate(Q2,5,qp1.particle(),qp1,gl);
// Complex diag1 = weakVertex[ix]->evaluate(Q2,off1,qp2,inter);
// SpinorBarWaveFunction off2 =
// strongVertex->evaluate(Q2,5,qp2.particle(),qp2,gl);
// Complex diag2 = weakVertex[ix]->evaluate(Q2,qp1,off2,inter);
// diagReal += diag1+diag2;
// }
// realme += norm(diagReal);
// }
// }
// }
// }
// }
// double test1 = realme/lome/hwsm->alphaS(Q2)*Q2*UnitRemoval::InvE2;
// double cphi(cos(phi));
// double test2;
// if(normalize) {
// test2 = 8.*Constants::pi/(1.-xp)/(1.-zp)*
// (azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi))*
// (1.+sqr(xp)*(sqr(x2)+1.5*sqr(xperp)));
// }
// else {
// test2 = 8.*Constants::pi/(1.-xp)/(1.-zp)*
// (azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi));
// }
// cerr << "testing RATIO A " << test1/test2 << "\n";
// }
// else {
// SpinorWaveFunction l1,q1,qp1;
// SpinorBarWaveFunction l2,q2,qp2;
// VectorWaveFunction gl(pin,gluon,incoming);
// if(lepton1->id()>0) {
// l1 = SpinorWaveFunction (pl1,lepton1,incoming);
// l2 = SpinorBarWaveFunction(pl2,lepton2,outgoing);
// }
// else {
// l1 = SpinorWaveFunction (pl2,lepton2,outgoing);
// l2 = SpinorBarWaveFunction(pl1,lepton1,incoming);
// }
// if(quark1->id()>0) {
// q1 = SpinorWaveFunction (pq1,quark1 ,incoming);
// q2 = SpinorBarWaveFunction(pq2,quark2 ,outgoing);
// qp2 = SpinorBarWaveFunction(p1 ,quark2 ,outgoing);
// qp1 = SpinorWaveFunction (p2 ,quark1->CC(),outgoing);
// }
// else {
// q1 = SpinorWaveFunction (pq2,quark2 ,outgoing);
// q2 = SpinorBarWaveFunction(pq1,quark1 ,incoming);
// qp2 = SpinorBarWaveFunction(p2 ,quark1->CC(),outgoing);
// qp1 = SpinorWaveFunction (p1 ,quark2 ,outgoing);
// }
// double lome(0.),realme(0.);
// for(unsigned int lhel1=0;lhel1<2;++lhel1) {
// l1.reset(lhel1);
// for(unsigned int lhel2=0;lhel2<2;++lhel2) {
// l2.reset(lhel2);
// for(unsigned int qhel1=0;qhel1<2;++qhel1) {
// q1.reset(qhel1);
// qp1.reset(qhel1);
// for(unsigned int qhel2=0;qhel2<2;++qhel2) {
// q2.reset(qhel2);
// qp2.reset(qhel2);
// // leading order matrix element
// Complex diagLO(0.);
// for(unsigned int ix=0;ix<weakVertex.size();++ix) {
// VectorWaveFunction inter =
// weakVertex[ix]->evaluate(Q2,3,bosons[ix],l1,l2);
// diagLO += weakVertex[ix]->evaluate(Q2,q1,q2,inter);
// }
// lome += norm(diagLO);
// // real emission matrix element
// for(unsigned int ghel=0;ghel<2;++ghel) {
// gl.reset(2*ghel);
// Complex diagReal(0.);
// for(unsigned int ix=0;ix<weakVertex.size();++ix) {
// VectorWaveFunction inter =
// weakVertex[ix]->evaluate(Q2,3,bosons[ix],l1,l2);
// SpinorWaveFunction off1 =
// strongVertex->evaluate(Q2,5,qp1.particle(),qp1,gl);
// Complex diag1 = weakVertex[ix]->evaluate(Q2,off1,qp2,inter);
// SpinorBarWaveFunction off2 =
// strongVertex->evaluate(Q2,5,qp2.particle(),qp2,gl);
// Complex diag2 = weakVertex[ix]->evaluate(Q2,qp1,off2,inter);
// diagReal += diag1+diag2;
// }
// realme += norm(diagReal);
// }
// }
// }
// }
// }
// double test1 = realme/lome/hwsm->alphaS(Q2)*Q2*UnitRemoval::InvE2;
// double cphi(cos(phi));
// double test2;
// if(normalize) {
// test2 = 8.*Constants::pi/zp/(1.-zp)*
// (azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi))*
// sqr(xp)*(sqr(x3)+sqr(x2)+3.*sqr(xperp));
// }
// else {
// test2 = 8.*Constants::pi/zp/(1.-zp)*
// (azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi));
// }
// cerr << "testing RATIO B " << test1/test2 << "\n";
// }
// }
//
// }
DISBase::DISBase() : initial_(6.), final_(3.),
procProb_(0.35),
comptonInt_(0.), bgfInt_(0.),
comptonWeight_(50.), BGFWeight_(150.),
pTmin_(0.1*GeV),
scaleOpt_(1), muF_(100.*GeV), scaleFact_(1.),
contrib_(0), power_(0.1)
{}
DISBase::~DISBase() {}
void DISBase::persistentOutput(PersistentOStream & os) const {
os << comptonInt_ << bgfInt_ << procProb_ << initial_ << final_ << alpha_
<< ounit(pTmin_,GeV) << comptonWeight_ << BGFWeight_ << gluon_
<< ounit(muF_,GeV) << scaleFact_ << scaleOpt_ << contrib_<< power_;
}
void DISBase::persistentInput(PersistentIStream & is, int) {
is >> comptonInt_ >> bgfInt_ >> procProb_ >> initial_ >> final_ >> alpha_
>> iunit(pTmin_,GeV) >> comptonWeight_ >> BGFWeight_ >> gluon_
>> iunit(muF_,GeV) >> scaleFact_ >> scaleOpt_ >> contrib_ >> power_;
}
AbstractClassDescription<DISBase> DISBase::initDISBase;
// Definition of the static class description member.
void DISBase::Init() {
static ClassDocumentation<DISBase> documentation
("The DISBase class provides the base class for the "
"implementation of DIS type processes including the "
"hard corrections in either the old-fashioned matrix "
"element correction of POWHEG approaches");
static Parameter<DISBase,double> interfaceProcessProbability
("ProcessProbability",
"The probabilty of the QCD compton process for the process selection",
&DISBase::procProb_, 0.3, 0.0, 1.,
false, false, Interface::limited);
static Reference<DISBase,ShowerAlpha> interfaceCoupling
("Coupling",
"Pointer to the object to calculate the coupling for the correction",
&DISBase::alpha_, false, false, true, false, false);
static Parameter<DISBase,Energy> interfacepTMin
("pTMin",
"The minimum pT",
&DISBase::pTmin_, GeV, 1.*GeV, 0.0*GeV, 10.0*GeV,
false, false, Interface::limited);
static Parameter<DISBase,double> interfaceComptonWeight
("ComptonWeight",
"Weight for the overestimate ofthe compton channel",
&DISBase::comptonWeight_, 50.0, 0.0, 100.0,
false, false, Interface::limited);
static Parameter<DISBase,double> interfaceBGFWeight
("BGFWeight",
"Weight for the overestimate of the BGF channel",
&DISBase::BGFWeight_, 100.0, 0.0, 1000.0,
false, false, Interface::limited);
static Switch<DISBase,unsigned int> interfaceContribution
("Contribution",
"Which contributions to the cross section to include",
&DISBase::contrib_, 0, false, false);
static SwitchOption interfaceContributionLeadingOrder
(interfaceContribution,
"LeadingOrder",
"Just generate the leading order cross section",
0);
static SwitchOption interfaceContributionPositiveNLO
(interfaceContribution,
"PositiveNLO",
"Generate the positive contribution to the full NLO cross section",
1);
static SwitchOption interfaceContributionNegativeNLO
(interfaceContribution,
"NegativeNLO",
"Generate the negative contribution to the full NLO cross section",
2);
static Switch<DISBase,unsigned int> interfaceScaleOption
("ScaleOption",
"Option for the choice of factorization (and renormalization) scale",
&DISBase::scaleOpt_, 1, false, false);
static SwitchOption interfaceDynamic
(interfaceScaleOption,
"Dynamic",
"Dynamic factorization scale equal to the current sqrt(sHat())",
1);
static SwitchOption interfaceFixed
(interfaceScaleOption,
"Fixed",
"Use a fixed factorization scale set with FactorizationScaleValue",
2);
static Parameter<DISBase,Energy> interfaceFactorizationScale
("FactorizationScale",
"Value to use in the event of a fixed factorization scale",
&DISBase::muF_, GeV, 100.0*GeV, 1.0*GeV, 500.0*GeV,
true, false, Interface::limited);
static Parameter<DISBase,double> interfaceScaleFactor
("ScaleFactor",
"The factor used before Q2 if using a running scale",
&DISBase::scaleFact_, 1.0, 0.0, 10.0,
false, false, Interface::limited);
static Parameter<DISBase,double> interfaceSamplingPower
("SamplingPower",
"Power for the sampling of xp",
&DISBase::power_, 0.6, 0.0, 1.,
false, false, Interface::limited);
}
void DISBase::doinit() {
HwMEBase::doinit();
// integrals of me over phase space
double r5=sqrt(5.),darg((r5-1.)/(r5+1.)),ath(0.5*log((1.+1./r5)/(1.-1./r5)));
comptonInt_ = 2.*(-21./20.-6./(5.*r5)*ath+sqr(Constants::pi)/3.
-2.*Math::ReLi2(1.-darg)-2.*Math::ReLi2(1.-1./darg));
bgfInt_ = 121./9.-56./r5*ath;
// extract the gluon ParticleData objects
gluon_ = getParticleData(ParticleID::g);
}
void DISBase::initializeMECorrection(RealEmissionProcessPtr born, double & initial,
double & final) {
initial = initial_;
final = final_;
// incoming particles
for(unsigned int ix=0;ix<born->bornIncoming().size();++ix) {
if(QuarkMatcher::Check(born->bornIncoming()[ix]->data())) {
partons_[0] = born->bornIncoming()[ix]->dataPtr();
pq_[0] = born->bornIncoming()[ix]->momentum();
}
else if(LeptonMatcher::Check(born->bornIncoming()[ix]->data())) {
leptons_[0] = born->bornIncoming()[ix]->dataPtr();
pl_[0] = born->bornIncoming()[ix]->momentum();
}
}
// outgoing particles
for(unsigned int ix=0;ix<born->bornOutgoing().size();++ix) {
if(QuarkMatcher::Check(born->bornOutgoing()[ix]->data())) {
partons_[1] = born->bornOutgoing()[ix]->dataPtr();
pq_[1] = born->bornOutgoing()[ix]->momentum();
}
else if(LeptonMatcher::Check(born->bornOutgoing()[ix]->data())) {
leptons_[1] = born->bornOutgoing()[ix]->dataPtr();
pl_[1] = born->bornOutgoing()[ix]->momentum();
}
}
// extract the born variables
q_ =pl_[0]-pl_[1];
q2_ = -q_.m2();
double yB = (q_*pq_[0])/(pl_[0]*pq_[0]);
l_ = 2./yB-1.;
// calculate the A coefficient for the correlations
acoeff_ = A(leptons_[0],leptons_[1],
partons_[0],partons_[1],q2_);
}
RealEmissionProcessPtr DISBase::applyHardMatrixElementCorrection(RealEmissionProcessPtr born) {
static const double eps=1e-6;
// find the incoming and outgoing quarks and leptons
PPtr quark[2],lepton[2];
PPtr hadron;
unsigned int iqIn(0),iqOut(0);
// incoming particles
for(unsigned int ix=0;ix<born->bornIncoming().size();++ix) {
if(QuarkMatcher::Check(born->bornIncoming()[ix]->data())) {
iqIn=ix;
quark[0] = born->bornIncoming()[ix];
hadron = born->hadrons()[ix];
beam_ = dynamic_ptr_cast<tcBeamPtr>(hadron->dataPtr());
xB_ = quark[0]->momentum().rho()/hadron->momentum().rho();
}
else if(LeptonMatcher::Check(born->bornIncoming()[ix]->data())) {
lepton[0] = born->bornIncoming()[ix];
}
}
pdf_ = beam_->pdf();
assert(beam_&&pdf_&&quark[0]&&lepton[0]);
// outgoing particles
for(unsigned int ix=0;ix<born->bornOutgoing().size();++ix) {
if(QuarkMatcher::Check(born->bornOutgoing()[ix]->data())) {
iqOut=ix;
quark [1] = born->bornOutgoing()[ix];
}
else if(LeptonMatcher::Check(born->bornOutgoing()[ix]->data())) {
lepton[1] = born->bornOutgoing()[ix];
}
}
// momentum fraction
assert(quark[1]&&lepton[1]);
// calculate the matrix element
vector<double> azicoeff;
// select the type of process
bool BGF = UseRandom::rnd()>procProb_;
double xp,zp,wgt,x1,x2,x3,xperp;
// generate a QCD compton process
if(!BGF) {
wgt = generateComptonPoint(xp,zp);
if(xp<eps) return RealEmissionProcessPtr();
// common pieces
Energy2 scale = q2_*((1.-xp)*(1-zp)*zp/xp+1.);
wgt *= 2./3./Constants::pi*alpha_->value(scale)/procProb_;
// PDF piece
wgt *= pdf_->xfx(beam_,quark[0]->dataPtr(),scale,xB_/xp)/
pdf_->xfx(beam_,quark[0]->dataPtr(),q2_ ,xB_);
// other bits
xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp);
x1 = -1./xp;
x2 = 1.-(1.-zp)/xp;
x3 = 2.+x1-x2;
// matrix element pieces
azicoeff = ComptonME(xp,x2,xperp,true);
}
// generate a BGF process
else {
wgt = generateBGFPoint(xp,zp);
if(xp<eps) return RealEmissionProcessPtr();
// common pieces
Energy2 scale = q2_*((1.-xp)*(1-zp)*zp/xp+1);
wgt *= 0.25/Constants::pi*alpha_->value(scale)/(1.-procProb_);
// PDF piece
wgt *= pdf_->xfx(beam_,gluon_ ,scale,xB_/xp)/
pdf_->xfx(beam_,quark[0]->dataPtr(),q2_ ,xB_);
// other bits
xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp);
x1 = -1./xp;
x2 = 1.-(1.-zp)/xp;
x3 = 2.+x1-x2;
// matrix element pieces
azicoeff = BGFME(xp,x2,x3,xperp,true);
}
// compute the azimuthal average of the weight
wgt *= (azicoeff[0]+0.5*azicoeff[2]);
// decide whether or not to accept the weight
if(UseRandom::rnd()>wgt) return RealEmissionProcessPtr();
// if generate generate phi
unsigned int itry(0);
double phimax = std::accumulate(azicoeff.begin(),azicoeff.end(),0.);
double phiwgt,phi;
do {
phi = UseRandom::rnd()*Constants::twopi;
double cphi(cos(phi));
phiwgt = azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi);
++itry;
}
while (phimax*UseRandom::rnd() > phiwgt && itry<200);
if(itry==200) throw Exception() << "Too many tries in DISMECorrection"
<< "::applyHardMatrixElementCorrection() to"
<< " generate phi" << Exception::eventerror;
// construct lorentz transform from lab to breit frame
Lorentz5Momentum phadron = hadron->momentum();
phadron.setMass(0.*GeV);
phadron.rescaleEnergy();
Lorentz5Momentum pcmf = phadron+0.5/xB_*q_;
pcmf.rescaleMass();
LorentzRotation rot(-pcmf.boostVector());
Lorentz5Momentum pbeam = rot*phadron;
Axis axis(pbeam.vect().unit());
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
rot.rotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
Lorentz5Momentum pl = rot*pl_[0];
rot.rotateZ(-atan2(pl.y(),pl.x()));
pl_[0] *= rot;
pl_[1] *= rot;
pq_[0] *= rot;
pq_[1] *= rot;
// compute the new incoming and outgoing momenta
Energy Q(sqrt(q2_));
Lorentz5Momentum p1 = Lorentz5Momentum( 0.5*Q*xperp*cos(phi), 0.5*Q*xperp*sin(phi),
-0.5*Q*x2,0.*GeV,0.*GeV);
p1.rescaleEnergy();
Lorentz5Momentum p2 = Lorentz5Momentum(-0.5*Q*xperp*cos(phi),-0.5*Q*xperp*sin(phi),
-0.5*Q*x3,0.*GeV,0.*GeV);
p2.rescaleEnergy();
Lorentz5Momentum pin(0.*GeV,0.*GeV,-0.5*x1*Q,-0.5*x1*Q,0.*GeV);
// debuggingMatrixElement(BGF,pin,p1,p2,gluon_,pl_[0],pl_[1],pq_[0],pq_[1],
// lepton[0]->dataPtr(),lepton[1]->dataPtr(),
// quark [0]->dataPtr(),quark [1]->dataPtr(),
// q2_,phi,x2,x3,xperp,zp,xp,azicoeff,true);
// we need the Lorentz transform back to the lab
rot.invert();
// transform the momenta to lab frame
pin *= rot;
p1 *= rot;
p2 *= rot;
// test to ensure outgoing particles can be put on-shell
if(!BGF) {
if(p1.e()<quark[1]->dataPtr()->constituentMass()) return RealEmissionProcessPtr();
if(p2.e()<gluon_ ->constituentMass()) return RealEmissionProcessPtr();
}
else {
if(p1.e()<quark[1]->dataPtr() ->constituentMass()) return RealEmissionProcessPtr();
if(p2.e()<quark[0]->dataPtr()->CC()->constituentMass()) return RealEmissionProcessPtr();
}
// create the new particles and real emission process
bool isQuark = quark[0]->colourLine();
bool FSR = false;
// incoming lepton if first
if(iqIn==1)
born->incoming().push_back(born->bornIncoming()[0]->dataPtr()->
produceParticle(born->bornIncoming()[0]->momentum()));
// outgoing lepton if first
if(iqOut==1)
born->outgoing().push_back(born->bornOutgoing()[0]->dataPtr()->
produceParticle(born->bornOutgoing()[0]->momentum()));
PPtr newin,newout,emitted;
// radiating system
if(!BGF) {
newin = quark[0]->dataPtr()->produceParticle(pin);
emitted = gluon_ ->produceParticle(p2 );
newout = quark[1]->dataPtr()->produceParticle(p1 );
emitted->incomingColour(newin,!isQuark);
emitted->colourConnect(newout,!isQuark);
FSR = xp>zp;
}
else {
newin = gluon_ ->produceParticle(pin);
emitted = quark[0]->dataPtr()->CC()->produceParticle(p2 );
newout = quark[1]->dataPtr() ->produceParticle(p1 );
emitted->incomingColour(newin, isQuark);
newout ->incomingColour(newin,!isQuark);
FSR = false;
}
// set x
double x(xB_/xp);
if(born->incoming().size()==0)
born->x(make_pair(x,1.));
else
born->x(make_pair(1.,x));
if(FSR) {
born->emitter(born->outgoing().size()+2);
born->spectator(born->incoming().size());
}
else {
born->emitter(born->incoming().size());
born->spectator(born->outgoing().size()+2);
}
born->emitted(4);
// radiating particles
born->incoming().push_back(newin );
born->outgoing().push_back(newout);
// incoming lepton if second
if(iqIn==0)
born->incoming().push_back(born->bornIncoming()[1]->dataPtr()->
produceParticle(born->bornIncoming()[1]->momentum()));
// outgoing lepton if second
if(iqOut==0)
born->outgoing().push_back(born->bornOutgoing()[1]->dataPtr()->
produceParticle(born->bornOutgoing()[1]->momentum()));
// radiated particle
born->outgoing().push_back(emitted);
born->interaction(ShowerInteraction::QCD);
return born;
}
bool DISBase::softMatrixElementVeto(ShowerProgenitorPtr initial,
ShowerParticlePtr parent, Branching br) {
bool veto = !UseRandom::rndbool(parent->isFinalState() ? 1./final_ : 1./initial_);
// check if me correction should be applied
long id[2]={initial->id(),parent->id()};
if(id[0]!=id[1]||id[1]==ParticleID::g) return veto;
// get the pT
Energy pT=br.kinematics->pT();
// check if hardest so far
if(pT<initial->highestpT()) return veto;
double kappa(sqr(br.kinematics->scale())/q2_),z(br.kinematics->z());
double zk((1.-z)*kappa);
// final-state
double wgt(0.);
if(parent->isFinalState()) {
double zp=z,xp=1./(1.+z*zk);
double xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp);
double x2 = 1.-(1.-zp)/xp;
vector<double> azicoeff = ComptonME(xp,x2,xperp,false);
wgt = (azicoeff[0]+0.5*azicoeff[2])*xp/(1.+sqr(z))/final_;
if(wgt<.0||wgt>1.) {
ostringstream wstring;
wstring << "Soft ME correction weight too large or "
<< "negative for FSR in DISBase::"
<< "softMatrixElementVeto() soft weight "
<< " xp = " << xp << " zp = " << zp
<< " weight = " << wgt << "\n";
generator()->logWarning( Exception(wstring.str(),
Exception::warning) );
}
}
else {
double xp = 2.*z/(1.+zk+sqrt(sqr(1.+zk)-4.*z*zk));
double zp = 0.5* (1.-zk+sqrt(sqr(1.+zk)-4.*z*zk));
double xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp);
double x1 = -1./xp, x2 = 1.-(1.-zp)/xp, x3 = 2.+x1-x2;
// compton
if(br.ids[0]->id()!=ParticleID::g) {
vector<double> azicoeff = ComptonME(xp,x2,xperp,false);
wgt = (azicoeff[0]+0.5*azicoeff[2])*xp*(1.-z)/(1.-xp)/(1.+sqr(z))/
(1.-zp+xp-2.*xp*(1.-zp));
}
// BGF
else {
vector<double> azicoeff = BGFME(xp,x2,x3,xperp,true);
wgt = (azicoeff[0]+0.5*azicoeff[2])*xp/(1.-zp+xp-2.*xp*(1.-zp))/(sqr(z)+sqr(1.-z));
}
wgt /=initial_;
if(wgt<.0||wgt>1.) {
ostringstream wstring;
wstring << "Soft ME correction weight too large or "
<< "negative for ISR in DISBase::"
<< "softMatrixElementVeto() soft weight "
<< " xp = " << xp << " zp = " << zp
<< " weight = " << wgt << "\n";
generator()->logWarning( Exception(wstring.str(),
Exception::warning) );
}
}
// if not vetoed
if(UseRandom::rndbool(wgt)) return false;
// otherwise
parent->vetoEmission(br.type,br.kinematics->scale());
return true;
}
double DISBase::generateComptonPoint(double &xp, double & zp) {
static const double maxwgt = 1.;
double wgt;
do {
xp = UseRandom::rnd();
double zpmin = xp, zpmax = 1./(1.+xp*(1.-xp));
zp = 1.-pow((1.-zpmin)/(1.-zpmax),UseRandom::rnd())*(1.-zpmax);
wgt = log((1.-zpmin)/(1.-zpmax))*(1.-zp);
if(UseRandom::rndbool()) swap(xp,zp);
double xperp2 = 4.*(1.-xp)*(1.-zp)*zp/xp,x2=1.-(1.-zp)/xp;
wgt *= 2.*(1.+sqr(xp)*(sqr(x2)+1.5*xperp2))/(1.-xp)/(1.-zp);
if(wgt>maxwgt) {
ostringstream wstring;
wstring << "DISBase::generateComptonPoint "
<< "Weight greater than maximum "
<< "wgt = " << wgt << " maxwgt = 1\n";
generator()->logWarning( Exception(wstring.str(),
Exception::warning) );
}
}
while(wgt<UseRandom::rnd()*maxwgt);
return comptonInt_;
}
double DISBase::generateBGFPoint(double &xp, double & zp) {
static const double maxwgt = 25.;
double wgt;
do {
xp = UseRandom::rnd();
double zpmax = 1./(1.+xp*(1.-xp)), zpmin = 1.-zpmax;
zp = 1.-pow((1.-zpmin)/(1.-zpmax),UseRandom::rnd())*(1.-zpmax);
wgt = log((1.-zpmin)/(1.-zpmax))*(1.-zp);
double x1 = -1./xp;
double x2 = 1.-(1.-zp)/xp;
double x3 = 2.+x1-x2;
double xperp2 = 4.*(1.-xp)*(1.-zp)*zp/xp;
wgt *= sqr(xp)/(1.-zp)*(sqr(x3)+sqr(x2)+3.*xperp2);
if(wgt>maxwgt) {
ostringstream wstring;
wstring << "DISBase::generateBGFPoint "
<< "Weight greater than maximum "
<< "wgt = " << wgt << " maxwgt = 1\n";
generator()->logWarning( Exception(wstring.str(),
Exception::warning) );
}
}
while(wgt<UseRandom::rnd()*maxwgt);
return bgfInt_;
// static const double maxwgt = 2.,npow=0.34,ac=1.0;
// double wgt;
// do {
// double rho = UseRandom::rnd();
// xp = 1.-pow(rho,1./(1.-npow));
// wgt = (sqr(xp)+ac+sqr(1.-xp));
// if(wgt>1.+ac) cerr << "testing violates BGF maxA " << wgt << "\n";
// }
// while(wgt<UseRandom::rnd()*(1.+ac));
// double xpwgt = -((6.-5.*npow+sqr(npow))*ac-3.*npow+sqr(npow)+4)
// /(sqr(npow)*(npow-6.)+11.*npow-6.);
// xpwgt *= pow(1.-xp,npow)/wgt;
// double xp2(sqr(xp)),lxp(log(xp)),xp4(sqr(xp2)),lxp1(log(1.-xp));
// double zpwgt = (2.*xp4*(lxp+lxp1-3.)+4.*xp*xp2*(3.-lxp-lxp1)
// +xp2*(-13.+lxp+lxp1)+xp*(+7.+lxp+lxp1)-lxp-lxp1-1.)/(1.+xp-xp2);
// do {
// double zpmax = 1./(1.+xp*(1.-xp)), zpmin = 1.-zpmax;
// zp = 1.-pow((1.-zpmin)/(1.-zpmax),UseRandom::rnd())*(1.-zpmax);
// wgt = log((1.-zpmin)/(1.-zpmax))*(1.-zp);
// double x1 = -1./xp;
// double x2 = 1.-(1.-zp)/xp;
// double x3 = 2.+x1-x2;
// double xperp2 = 4.*(1.-xp)*(1.-zp)*zp/xp;
// wgt *= sqr(xp)/(1.-zp)*(sqr(x3)+sqr(x2)+3.*xperp2);
// if(wgt>maxwgt*zpwgt) cerr << "testing violates BGF maxB " << wgt/xpwgt << "\n";
// }
// while(wgt<UseRandom::rnd()*maxwgt);
// return zpwgt*xpwgt;
}
vector<double> DISBase::ComptonME(double xp, double x2, double xperp,
bool norm) {
vector<double> output(3,0.);
double cos2 = x2 /sqrt(sqr(x2)+sqr(xperp));
double sin2 = xperp/sqrt(sqr(x2)+sqr(xperp));
double root = sqrt(sqr(l_)-1.);
output[0] = sqr(cos2)+acoeff_*cos2*l_+sqr(l_);
output[1] = -acoeff_*cos2*root*sin2-2.*l_*root*sin2;
output[2] = sqr(root)*sqr(sin2);
double lo(1+acoeff_*l_+sqr(l_));
double denom = norm ? 1.+sqr(xp)*(sqr(x2)+1.5*sqr(xperp)) : 1.;
double fact = sqr(xp)*(sqr(x2)+sqr(xperp))/lo;
for(unsigned int ix=0;ix<output.size();++ix)
output[ix] = ((ix==0 ? 1. : 0.) +fact*output[ix])/denom;
return output;
}
vector<double> DISBase::BGFME(double xp, double x2, double x3,
double xperp, bool norm) {
vector<double> output(3,0.);
double cos2 = x2 /sqrt(sqr(x2)+sqr(xperp));
double sin2 = xperp/sqrt(sqr(x2)+sqr(xperp));
double fact2 = sqr(xp)*(sqr(x2)+sqr(xperp));
double cos3 = x3 /sqrt(sqr(x3)+sqr(xperp));
double sin3 = xperp/sqrt(sqr(x3)+sqr(xperp));
double fact3 = sqr(xp)*(sqr(x3)+sqr(xperp));
double root = sqrt(sqr(l_)-1.);
output[0] = fact2*(sqr(cos2)+acoeff_*cos2*l_+sqr(l_)) +
fact3*(sqr(cos3)-acoeff_*cos3*l_+sqr(l_));
output[1] = - fact2*(acoeff_*cos2*root*sin2+2.*l_*root*sin2)
- fact3*(acoeff_*cos3*root*sin3-2.*l_*root*sin3);
output[2] = fact2*(sqr(root)*sqr(sin2)) +
fact3*(sqr(root)*sqr(sin3));
double lo(1+acoeff_*l_+sqr(l_));
double denom = norm ? sqr(xp)*(sqr(x3)+sqr(x2)+3.*sqr(xperp))*lo : lo;
for(unsigned int ix=0;ix<output.size();++ix) output[ix] /= denom;
return output;
}
RealEmissionProcessPtr DISBase::generateHardest(RealEmissionProcessPtr born,
- ShowerInteraction::Type inter) {
+ ShowerInteraction inter) {
// check if generating QCD radiation
if(inter==ShowerInteraction::QED) return RealEmissionProcessPtr();
PPtr quark[2],lepton[2];
PPtr hadron;
unsigned int iqIn(0),iqOut(0);
// incoming particles
for(unsigned int ix=0;ix<born->bornIncoming().size();++ix) {
if(QuarkMatcher::Check(born->bornIncoming()[ix]->data())) {
iqIn=ix;
hadron = born->hadrons()[ix];
quark [0] = born->bornIncoming()[ix];
beam_ = dynamic_ptr_cast<tcBeamPtr>(hadron->dataPtr());
xB_ = quark[0]->momentum().rho()/hadron->momentum().rho();
}
else if(LeptonMatcher::Check(born->bornIncoming()[ix]->data())) {
lepton[0] = born->bornIncoming()[ix];
leptons_[0] = lepton[0]->dataPtr();
}
}
pdf_=beam_->pdf();
assert(beam_&&pdf_&&quark[0]&&lepton[0]);
// outgoing particles
for(unsigned int ix=0;ix<born->bornOutgoing().size();++ix) {
if(QuarkMatcher::Check(born->bornOutgoing()[ix]->data())) {
iqOut=ix;
quark [1] = born->bornOutgoing()[ix];
}
else if(LeptonMatcher::Check(born->bornOutgoing()[ix]->data())) {
lepton[1] = born->bornOutgoing()[ix];
leptons_[1] = lepton[1]->dataPtr();
}
}
assert(quark[1]&&lepton[1]);
// Particle data objects
for(unsigned int ix=0;ix<2;++ix) partons_[ix] = quark[ix]->dataPtr();
// extract the born variables
q_ =lepton[0]->momentum()-lepton[1]->momentum();
q2_ = -q_.m2();
double yB =
( q_*quark[0]->momentum())/
(lepton[0]->momentum()*quark[0]->momentum());
l_ = 2./yB-1.;
// construct lorentz transform from lab to breit frame
Lorentz5Momentum phadron = hadron->momentum();
phadron.setMass(0.*GeV);
phadron.rescaleRho();
Lorentz5Momentum pb = quark[0]->momentum();
Axis axis(q_.vect().unit());
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
LorentzRotation rot_ = LorentzRotation();
if(axis.perp2()>1e-20) {
rot_.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
rot_.rotateX(Constants::pi);
}
if(abs(1.-q_.e()/q_.vect().mag())>1e-6) rot_.boostZ( q_.e()/q_.vect().mag());
pb *= rot_;
if(pb.perp2()/GeV2>1e-20) {
Boost trans = -1./pb.e()*pb.vect();
trans.setZ(0.);
rot_.boost(trans);
}
Lorentz5Momentum pl = rot_*lepton[0]->momentum();
rot_.rotateZ(-atan2(pl.y(),pl.x()));
// momenta of the particles
pl_[0]=rot_*lepton[0]->momentum();
pl_[1]=rot_*lepton[1]->momentum();
pq_[0]=rot_* quark[0]->momentum();
pq_[1]=rot_* quark[1]->momentum();
q_ *= rot_;
// coefficient for the matrix elements
acoeff_ = A(lepton[0]->dataPtr(),lepton[1]->dataPtr(),
quark [0]->dataPtr(),quark [1]->dataPtr(),q2_);
// generate a compton point
generateCompton();
generateBGF();
// no valid emission, return
if(pTCompton_<ZERO&&pTBGF_<ZERO) {
born->pT()[ShowerInteraction::QCD] = pTmin_;
return born;
}
// type of emission, pick highest pT
bool isCompton=pTCompton_>pTBGF_;
// create the process with real emission
bool isQuark = quark[0]->colourLine();
bool FSR = false;
// incoming lepton if first
if(iqIn==1)
born->incoming().push_back(born->bornIncoming()[0]->dataPtr()->
produceParticle(born->bornIncoming()[0]->momentum()));
// outgoing lepton if first
if(iqOut==1)
born->outgoing().push_back(born->bornOutgoing()[0]->dataPtr()->
produceParticle(born->bornOutgoing()[0]->momentum()));
PPtr newout,newin,emitted;
// compton hardest
if(isCompton) {
rot_.invert();
for(unsigned int ix=0;ix<ComptonMomenta_.size();++ix) {
ComptonMomenta_[ix].transform(rot_);
}
newout = partons_[1]->produceParticle(ComptonMomenta_[1]);
emitted = gluon_ ->produceParticle(ComptonMomenta_[2]);
newin = partons_[0]->produceParticle(ComptonMomenta_[0]);
emitted->incomingColour(newin,!isQuark);
emitted->colourConnect(newout,!isQuark);
FSR = !ComptonISFS_;
born->pT()[ShowerInteraction::QCD] = pTCompton_;
}
// BGF hardest
else {
rot_.invert();
for(unsigned int ix=0;ix<BGFMomenta_.size();++ix) {
BGFMomenta_[ix].transform(rot_);
}
newin = gluon_ ->produceParticle(BGFMomenta_[0]);
emitted = quark[0]->dataPtr()->CC()->produceParticle(BGFMomenta_[2]);
newout = quark[1]->dataPtr() ->produceParticle(BGFMomenta_[1]);
emitted->incomingColour(newin, isQuark);
newout ->incomingColour(newin,!isQuark);
FSR = false;
born->pT()[ShowerInteraction::QCD] = pTBGF_;
}
double x = newin->momentum().rho()/hadron->momentum().rho();
if(born->incoming().size()==0)
born->x(make_pair(x,1.));
else
born->x(make_pair(1.,x));
if(FSR) {
born->emitter(born->outgoing().size()+2);
born->spectator(born->incoming().size());
}
else {
born->emitter(born->incoming().size());
born->spectator(born->outgoing().size()+2);
}
born->emitted(4);
// radiating particles
born->incoming().push_back(newin );
born->outgoing().push_back(newout);
// incoming lepton if second
if(iqIn==0)
born->incoming().push_back(born->bornIncoming()[1]->dataPtr()->
produceParticle(born->bornIncoming()[1]->momentum()));
// outgoing lepton if second
if(iqOut==0)
born->outgoing().push_back(born->bornOutgoing()[1]->dataPtr()->
produceParticle(born->bornOutgoing()[1]->momentum()));
// radiated particle
born->outgoing().push_back(emitted);
born->interaction(ShowerInteraction::QCD);
return born;
}
void DISBase::generateCompton() {
// maximum value of the xT
double xT = sqrt((1.-xB_)/xB_);
double xTMin = 2.*pTmin_/sqrt(q2_);
double zp;
// prefactor
double a = alpha_->overestimateValue()*comptonWeight_/Constants::twopi;
// loop to generate kinematics
double wgt(0.),xp(0.);
vector<double> azicoeff;
do {
wgt = 0.;
// intergration variables dxT/xT^3
xT *= 1./sqrt(1.-2.*log(UseRandom::rnd())/a*sqr(xT));
// zp
zp = UseRandom::rnd();
xp = 1./(1.+0.25*sqr(xT)/zp/(1.-zp));
// check allowed
if(xp<xB_||xp>1.) continue;
// phase-space piece of the weight
wgt = 8.*(1.-xp)*zp/comptonWeight_;
// PDF piece of the weight
Energy2 scale = q2_*((1.-xp)*(1-zp)*zp/xp+1.);
wgt *= pdf_->xfx(beam_,partons_[0],scale,xB_/xp)/
pdf_->xfx(beam_,partons_[0],q2_ ,xB_);
// me piece of the weight
double x2 = 1.-(1.-zp)/xp;
azicoeff = ComptonME(xp,x2,xT,false);
wgt *= 4./3.*alpha_->ratio(0.25*q2_*sqr(xT))*(azicoeff[0]+0.5*azicoeff[2]);
if(wgt>1.||wgt<0.) {
ostringstream wstring;
wstring << "DISBase::generateCompton() "
<< "Weight greater than one or less than zero"
<< "wgt = " << wgt << "\n";
generator()->logWarning( Exception(wstring.str(),
Exception::warning) );
}
}
while(xT>xTMin&&UseRandom::rnd()>wgt);
if(xT<=xTMin) {
pTCompton_=-GeV;
return;
}
// generate phi
unsigned int itry(0);
double phimax = std::accumulate(azicoeff.begin(),azicoeff.end(),0.);
double phiwgt,phi;
do {
phi = UseRandom::rnd()*Constants::twopi;
double cphi(cos(phi));
phiwgt = azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi);
++itry;
}
while (phimax*UseRandom::rnd() > phiwgt && itry<200);
if(itry==200) throw Exception() << "Too many tries in DISMECorrection"
<< "::generateCompton() to"
<< " generate phi" << Exception::eventerror;
// momenta for the configuration
Energy Q(sqrt(q2_));
double x1 = -1./xp;
double x2 = 1.-(1.-zp)/xp;
double x3 = 2.+x1-x2;
Lorentz5Momentum p1( 0.5*Q*xT*cos(phi), 0.5*Q*xT*sin(phi),
-0.5*Q*x2, 0.5*Q*sqrt(sqr(xT)+sqr(x2)));
Lorentz5Momentum p2(-0.5*Q*xT*cos(phi), -0.5*Q*xT*sin(phi),
-0.5*Q*x3, 0.5*Q*sqrt(sqr(xT)+sqr(x3)));
Lorentz5Momentum p0(ZERO,ZERO,-0.5*Q*x1,-0.5*Q*x1);
pTCompton_ = 0.5*Q*xT;
ComptonMomenta_.resize(3);
ComptonMomenta_[0] = p0;
ComptonMomenta_[1] = p1;
ComptonMomenta_[2] = p2;
ComptonISFS_ = zp>xp;
// debuggingMatrixElement(false,p0,p1,p2,gluon_,pl_[0],pl_[1],pq_[0],pq_[1],
// leptons_[0],leptons_[1],
// partons_[0],partons_[1],
// q2_,phi,x2,x3,xT,zp,xp,azicoeff,false);
}
void DISBase::generateBGF() {
// maximum value of the xT
double xT = (1.-xB_)/xB_;
double xTMin = 2.*max(pTmin_,pTCompton_)/sqrt(q2_);
double zp;
// prefactor
double a = alpha_->overestimateValue()*BGFWeight_/Constants::twopi;
// loop to generate kinematics
double wgt(0.),xp(0.);
vector<double> azicoeff;
do {
wgt = 0.;
// intergration variables dxT/xT^3
xT *= 1./sqrt(1.-2.*log(UseRandom::rnd())/a*sqr(xT));
// zp
zp = UseRandom::rnd();
xp = 1./(1.+0.25*sqr(xT)/zp/(1.-zp));
// check allowed
if(xp<xB_||xp>1.) continue;
// phase-space piece of the weight
wgt = 8.*sqr(1.-xp)*zp/BGFWeight_;
// PDF piece of the weight
Energy2 scale = q2_*((1.-xp)*(1-zp)*zp/xp+1.);
wgt *= pdf_->xfx(beam_,gluon_ ,scale,xB_/xp)/
pdf_->xfx(beam_,partons_[0],q2_ ,xB_);
// me piece of the weight
double x1 = -1./xp;
double x2 = 1.-(1.-zp)/xp;
double x3 = 2.+x1-x2;
azicoeff = BGFME(xp,x2,x3,xT,false);
wgt *= 0.5*alpha_->ratio(0.25*q2_*sqr(xT))*
(azicoeff[0]+0.5*azicoeff[2]);
if(wgt>1.||wgt<0.) {
ostringstream wstring;
wstring << "DISBase::generateBGF() "
<< "Weight greater than one or less than zero"
<< "wgt = " << wgt << "\n";
generator()->logWarning( Exception(wstring.str(),
Exception::warning) );
}
}
while(xT>xTMin&&UseRandom::rnd()>wgt);
if(xT<=xTMin) {
pTBGF_=-GeV;
return;
}
// generate phi
unsigned int itry(0);
double phimax = std::accumulate(azicoeff.begin(),azicoeff.end(),0.);
double phiwgt,phi;
do {
phi = UseRandom::rnd()*Constants::twopi;
double cphi(cos(phi));
phiwgt = azicoeff[0]+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi);
++itry;
}
while (phimax*UseRandom::rnd() > phiwgt && itry<200);
if(itry==200) throw Exception() << "Too many tries in DISMECorrection"
<< "::generateBGF() to"
<< " generate phi" << Exception::eventerror;
// momenta for the configuration
Energy Q(sqrt(q2_));
double x1 = -1./xp;
double x2 = 1.-(1.-zp)/xp;
double x3 = 2.+x1-x2;
Lorentz5Momentum p1( 0.5*Q*xT*cos(phi), 0.5*Q*xT*sin(phi),
-0.5*Q*x2, 0.5*Q*sqrt(sqr(xT)+sqr(x2)));
Lorentz5Momentum p2(-0.5*Q*xT*cos(phi), -0.5*Q*xT*sin(phi),
-0.5*Q*x3, 0.5*Q*sqrt(sqr(xT)+sqr(x3)));
Lorentz5Momentum p0(ZERO,ZERO,-0.5*Q*x1,-0.5*Q*x1);
pTBGF_=0.5*Q*xT;
BGFMomenta_.resize(3);
BGFMomenta_[0]=p0;
BGFMomenta_[1]=p1;
BGFMomenta_[2]=p2;
// debuggingMatrixElement(true,p0,p1,p2,gluon_,pl_[0],pl_[1],pq_[0],pq_[1],
// leptons_[0],leptons_[1],
// partons_[0],partons_[1],
// q2_,phi,x2,x3,xT,zp,xp,azicoeff,false);
}
int DISBase::nDim() const {
return HwMEBase::nDim() + (contrib_>0 ? 1 : 0 );
}
bool DISBase::generateKinematics(const double * r) {
// Born kinematics
if(!HwMEBase::generateKinematics(r)) return false;
if(contrib_!=0) {
// hadron and momentum fraction
if(HadronMatcher::Check(*lastParticles().first->dataPtr())) {
hadron_ = dynamic_ptr_cast<tcBeamPtr>(lastParticles().first->dataPtr());
xB_ = lastX1();
}
else {
hadron_ = dynamic_ptr_cast<tcBeamPtr>(lastParticles().second->dataPtr());
xB_ = lastX2();
}
// Q2
q2_ = -(meMomenta()[0]-meMomenta()[2]).m2();
// xp
int ndim=nDim();
double rhomin = pow(1.-xB_,1.-power_);
double rho = r[ndim-1]*rhomin;
xp_ = 1.-pow(rho,1./(1.-power_));
jac_ = rhomin/(1.-power_)*pow(1.-xp_,power_);
jacobian(jacobian()*jac_);
}
return true;
}
Energy2 DISBase::scale() const {
return scaleOpt_ == 1 ?
-sqr(scaleFact_)*tHat() : sqr(scaleFact_*muF_);
}
CrossSection DISBase::dSigHatDR() const {
return NLOWeight()*HwMEBase::dSigHatDR();
}
double DISBase::NLOWeight() const {
// If only leading order is required return 1:
if(contrib_==0) return 1.;
// scale and prefactors
Energy2 mu2(scale());
double aS = SM().alphaS(mu2);
double CFfact = 4./3.*aS/Constants::twopi;
double TRfact = 1./2.*aS/Constants::twopi;
// LO + dipole subtracted virtual + collinear quark bit with LO pdf
double virt = 1.+CFfact*(-4.5-1./3.*sqr(Constants::pi)+1.5*log(q2_/mu2/(1.-xB_))
+2.*log(1.-xB_)*log(q2_/mu2)+sqr(log(1.-xB_)));
virt /= jac_;
// PDF from leading-order
double loPDF = hadron_->pdf()->xfx(hadron_,mePartonData()[1],mu2,xB_)/xB_;
// NLO gluon PDF
tcPDPtr gluon = getParticleData(ParticleID::g);
double gPDF = hadron_->pdf()->xfx(hadron_,gluon,mu2,xB_/xp_)*xp_/xB_;
// NLO quark PDF
double qPDF = hadron_->pdf()->xfx(hadron_,mePartonData()[1],mu2,xB_/xp_)*xp_/xB_;
// collinear counterterms
// gluon
double collg =
TRfact/xp_*gPDF*(2.*xp_*(1.-xp_)+(sqr(xp_)+sqr(1.-xp_))*log((1.-xp_)*q2_/xp_/mu2));
// quark
double collq =
CFfact/xp_*qPDF*(1-xp_-2./(1.-xp_)*log(xp_)-(1.+xp_)*log((1.-xp_)/xp_*q2_/mu2))+
CFfact/xp_*(qPDF-xp_*loPDF)*(2./(1.-xp_)*log(q2_*(1.-xp_)/mu2)-1.5/(1.-xp_));
// calculate the A coefficient for the real pieces
double a(A(mePartonData()[0],mePartonData()[2],
mePartonData()[1],mePartonData()[3],q2_));
// cacluate lepton kinematic variables
Lorentz5Momentum q = meMomenta()[0]-meMomenta()[2];
double yB = (q*meMomenta()[1])/(meMomenta()[0]*meMomenta()[1]);
double l = 2./yB-1.;
// q -> qg term
double realq = CFfact/xp_/(1.+a*l+sqr(l))*qPDF/loPDF*
(2.+2.*sqr(l)-xp_+3.*xp_*sqr(l)+a*l*(2.*xp_+1.));
// g -> q qbar term
double realg =-TRfact/xp_/(1.+a*l+sqr(l))*gPDF/loPDF*
((1.+sqr(l)+2.*(1.-3.*sqr(l))*xp_*(1.-xp_))
+2.*a*l*(1.-2.*xp_*(1.-xp_)));
// return the full result
double wgt = virt+((collq+collg)/loPDF+realq+realg);
// double f2g = gPDF/xp_*TRfact*((sqr(1-xp_)+sqr(xp_))*log((1-xp_)/xp_)+
// 8*xp_*(1.-xp_)-1.);
// double f2q =
// loPDF/jac_*(1.+CFfact*(-1.5*log(1.-xB_)+sqr(log(1.-xB_))
// -sqr(Constants::pi)/3.-4.5))
// +qPDF *CFfact/xp_*(3.+2.*xp_-(1.+xp_)*log(1.-xp_)
// -(1.+sqr(xp_))/(1.-xp_)*log(xp_))
// +(qPDF-xp_*loPDF)*CFfact/xp_*(2.*log(1.-xp_)/(1.-xp_)-1.5/(1.-xp_));
// double wgt = (f2g+f2q)/loPDF;
return contrib_ == 1 ? max(0.,wgt) : max(0.,-wgt);
}
diff --git a/MatrixElement/DIS/DISBase.h b/MatrixElement/DIS/DISBase.h
--- a/MatrixElement/DIS/DISBase.h
+++ b/MatrixElement/DIS/DISBase.h
@@ -1,469 +1,469 @@
// -*- C++ -*-
#ifndef HERWIG_DISBase_H
#define HERWIG_DISBase_H
//
// This is the declaration of the DISBase class.
//
#include "Herwig/MatrixElement/HwMEBase.h"
#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h"
namespace Herwig {
using namespace ThePEG;
/**
* The DISBase class is the base class for the implementation
* of DIS type processes including corrections in both the old
* fashioned matrix element and POWHEG approaches
*
* @see \ref DISBaseInterfaces "The interfaces"
* defined for DISBase.
*/
class DISBase: public HwMEBase {
public:
/**
* The default constructor.
*/
DISBase();
/**
* The default constructor.
*/
virtual ~DISBase();
/**
* Members for the old-fashioned matrix element correction
*/
//@{
/**
* Has an old fashioned ME correction
*/
virtual bool hasMECorrection() {return true;}
/**
* Initialize the ME correction
*/
virtual void initializeMECorrection(RealEmissionProcessPtr, double &,
double & );
/**
* Apply the hard matrix element correction to a given hard process or decay
*/
virtual RealEmissionProcessPtr applyHardMatrixElementCorrection(RealEmissionProcessPtr);
/**
* Apply the soft matrix element correction
* @param initial The particle from the hard process which started the
* shower
* @param parent The initial particle in the current branching
* @param br The branching struct
* @return If true the emission should be vetoed
*/
virtual bool softMatrixElementVeto(ShowerProgenitorPtr,
ShowerParticlePtr,Branching);
//@}
/**
* Members for the POWHEG stype correction
*/
//@{
/**
* Has a POWHEG style correction
*/
virtual POWHEGType hasPOWHEGCorrection() {return Both;}
/**
* Apply the POWHEG style correction
*/
virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr,
- ShowerInteraction::Type);
+ ShowerInteraction);
//@}
public:
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* The number of internal degrees of freedom used in the matrix
* element.
*/
virtual int nDim() const;
/**
* Generate internal degrees of freedom given nDim() uniform
* random numbers in the interval \f$ ]0,1[ \f$. To help the phase space
* generator, the dSigHatDR should be a smooth function of these
* numbers, although this is not strictly necessary.
* @param r a pointer to the first of nDim() consecutive random numbers.
* @return true if the generation succeeded, otherwise false.
*/
virtual bool generateKinematics(const double * r);
/**
* Return the matrix element squared differential in the variables
* given by the last call to generateKinematics().
*/
virtual CrossSection dSigHatDR() 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 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();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is an abstract class with persistent data.
*/
static AbstractClassDescription<DISBase> initDISBase;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
DISBase & operator=(const DISBase &);
protected:
/**
* The NLO weight
*/
double NLOWeight() const;
/**
* Calculate the coefficient A for the correlations
*/
virtual double A(tcPDPtr lin, tcPDPtr lout, tcPDPtr qin, tcPDPtr qout,
Energy2 scale) const =0;
/**
* Members for the matrix element correction
*/
//@{
/**
* Generate the values of \f$x_p\f$ and \f$z_p\f$
* @param xp The value of xp, output
* @param zp The value of zp, output
*/
double generateComptonPoint(double &xp, double & zp);
/**
* Generate the values of \f$x_p\f$ and \f$z_p\f$
* @param xp The value of xp, output
* @param zp The value of zp, output
*/
double generateBGFPoint(double &xp, double & zp);
/**
* Return the coefficients for the matrix element piece for
* the QCD compton case. The output is the \f$a_i\f$ coefficients to
* give the function as
* \f$a_0+a_1\cos\phi+a_2\sin\phi+a_3\cos^2\phi+a_4\sin^2\phi\f$
* @param xp \f$x_p\f$
* @param x2 \f$x_2\f$
* @param xperp \f$x_\perp\f$
* @param norm Normalise to the large $l$ value of the ME
*/
vector<double> ComptonME(double xp, double x2, double xperp,
bool norm);
/**
* Return the coefficients for the matrix element piece for
* the QCD compton case. The output is the \f$a_i\f$ coefficients to
* give the function as
* \f$a_0+a_1\cos\phi+a_2\sin\phi+a_3\cos^2\phi+a_4\sin^2\phi\f$
* @param xp \f$x_p\f$
* @param x2 \f$x_3\f$
* @param x3 \f$x_2\f$
* @param xperp \f$x_\perp\f$
* @param norm Normalise to the large $l$ value of the ME
*/
vector<double> BGFME(double xp, double x2, double x3, double xperp,
bool norm);
//@}
/**
* Members for the POWHEG correction
*/
//@{
/**
* Generate a Compton process
*/
void generateCompton();
/**
* Generate a BGF process
*/
void generateBGF();
//@}
private:
/**
* Parameters for the matrix element correction
*/
//@{
/**
* Enchancement factor for ISR
*/
double initial_;
/**
* Enchancement factor for FSR
*/
double final_;
/**
* Relative fraction of compton and BGF processes to generate
*/
double procProb_;
/**
* Integral for compton process
*/
double comptonInt_;
/**
* Integral for BGF process
*/
double bgfInt_;
//@}
/**
* Parameters for the POWHEG correction
*/
//@{
/**
* Weight for the compton channel
*/
double comptonWeight_;
/**
* Weight for the BGF channel
*/
double BGFWeight_;
/**
* Minimum value of \f$p_T\f$
*/
Energy pTmin_;
//@}
/**
* Parameters for the point being generated
*/
//@{
/**
* \f$Q^2\f$
*/
Energy2 q2_;
/**
*
*/
double l_;
/**
* Borm momentum fraction
*/
double xB_;
/**
* Beam particle
*/
tcBeamPtr beam_;
/**
* Partons
*/
tcPDPtr partons_[2];
/**
* Leptons
*/
tcPDPtr leptons_[2];
/**
* PDF object
*/
tcPDFPtr pdf_;
/**
* Rotation to the Breit frame
*/
LorentzRotation rot_;
/**
* Lepton momenta
*/
Lorentz5Momentum pl_[2];
/**
* Quark momenta
*/
Lorentz5Momentum pq_[2];
/**
* q
*/
Lorentz5Momentum q_;
/**
* Compton parameters
*/
Energy pTCompton_;
bool ComptonISFS_;
vector<Lorentz5Momentum> ComptonMomenta_;
/**
* BGF parameters
*/
Energy pTBGF_;
vector<Lorentz5Momentum> BGFMomenta_;
//@}
/**
* The coefficient for the correlations
*/
double acoeff_;
/**
* Coupling
*/
ShowerAlphaPtr alpha_;
/**
* Gluon particle data object
*/
PDPtr gluon_;
private:
/**
* The radiative variables
*/
//@{
/**
* The \f$x_p\f$ or \f$z\f$ real integration variable
*/
double xp_;
//@}
/**
* The hadron
*/
tcBeamPtr hadron_;
/**
* Selects a dynamic or fixed factorization scale
*/
unsigned int scaleOpt_;
/**
* The factorization scale
*/
Energy muF_;
/**
* Prefactor if variable scale used
*/
double scaleFact_;
/**
* Whether to generate the positive, negative or leading order contribution
*/
unsigned int contrib_;
/**
* Power for sampling \f$x_p\f$
*/
double power_;
/**
* Jacobian for \f$x_p\f$ integral
*/
double jac_;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of DISBase. */
template <>
struct BaseClassTrait<Herwig::DISBase,1> {
/** Typedef of the first base class of DISBase. */
typedef Herwig::HwMEBase NthBase;
};
/** This template specialization informs ThePEG about the name of
* the DISBase class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::DISBase>
: public ClassTraitsBase<Herwig::DISBase> {
/** Return a platform-independent class name */
static string className() { return "Herwig::DISBase"; }
/**
* The name of a file containing the dynamic library where the class
* MENeutralCurrentDIS is implemented. It may also include several, space-separated,
* libraries if the class MENeutralCurrentDIS depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMEDIS.so"; }
};
/** @endcond */
}
#endif /* HERWIG_DISBase_H */
diff --git a/MatrixElement/DrellYanBase.cc b/MatrixElement/DrellYanBase.cc
--- a/MatrixElement/DrellYanBase.cc
+++ b/MatrixElement/DrellYanBase.cc
@@ -1,911 +1,911 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DrellYanBase class.
//
#include "DrellYanBase.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h"
#include "Herwig/Shower/QTilde/Base/ShowerParticle.h"
#include "Herwig/Shower/QTilde/Base/Branching.h"
#include "Herwig/Shower/RealEmissionProcess.h"
using namespace Herwig;
DrellYanBase::DrellYanBase()
: _channelwgtA(0.12), _channelwgtB(2.00), _nover(0), _maxwgt(0.),
_power(2.0),_preqqbar(6.5),_preqg(4.0),_pregqbar(4.0),
_min_pt(2.*GeV) {}
void DrellYanBase::persistentOutput(PersistentOStream & os) const {
os << _channelwgtA << _channelwgtB << _channelweights << _alpha
<< _power << _preqqbar << _preqg << _pregqbar << ounit( _min_pt, GeV )
<< _prefactor;
}
void DrellYanBase::persistentInput(PersistentIStream & is, int) {
is >> _channelwgtA >> _channelwgtB >> _channelweights >> _alpha
>> _power >> _preqqbar >> _preqg >> _pregqbar >> iunit( _min_pt, GeV )
>> _prefactor;
}
AbstractClassDescription<DrellYanBase> DrellYanBase::initDrellYanBase;
// Definition of the static class description member.
void DrellYanBase::Init() {
static ClassDocumentation<DrellYanBase> documentation
("The DrellYanBase class provides a base class for the"
" corrections to Drell-Yan type processes");
static Parameter<DrellYanBase,double> interfaceQQbarChannelWeight
("QQbarChannelWeight",
"The relative weights of the q qbar abd q g channels for selection."
" This is a technical parameter for the phase-space generation and "
"should not affect the results only the efficiency and fraction"
" of events with weight > 1.",
&DrellYanBase::_channelwgtA, 0.12, 0.01, 100.,
false, false, Interface::limited);
static Parameter<DrellYanBase,double> interfaceQGChannelWeight
("QGChannelWeight",
"The relative weights of the qg abd qbar g channels for selection."
" This is a technical parameter for the phase-space generation and "
"should not affect the results only the efficiency and fraction",
&DrellYanBase::_channelwgtB, 2., 0.01, 100.,
false, false, Interface::limited);
static Reference<DrellYanBase,ShowerAlpha> interfaceCoupling
("Coupling",
"Pointer to the object to calculate the coupling for the correction",
&DrellYanBase::_alpha, false, false, true, false, false);
static Parameter<DrellYanBase,double> interfacePower
("Power",
"The power for the sampling of the matrix elements",
&DrellYanBase::_power, 2.0, 1.0, 10.0,
false, false, Interface::limited);
static Parameter<DrellYanBase,double> interfacePrefactorqqbar
("Prefactorqqbar",
"The prefactor for the sampling of the q qbar channel",
&DrellYanBase::_preqqbar, 5.0, 0.0, 1000.0,
false, false, Interface::limited);
static Parameter<DrellYanBase,double> interfacePrefactorqg
("Prefactorqg",
"The prefactor for the sampling of the q g channel",
&DrellYanBase::_preqg, 3.0, 0.0, 1000.0,
false, false, Interface::limited);
static Parameter<DrellYanBase,double> interfacePrefactorgqbar
("Prefactorgqbar",
"The prefactor for the sampling of the g qbar channel",
&DrellYanBase::_pregqbar, 3.0, 0.0, 1000.0,
false, false, Interface::limited);
static Parameter<DrellYanBase, Energy> interfacePtMin
("minPt",
"The pt cut on hardest emision generation"
"2*(1-Beta)*exp(-sqr(intrinsicpT/RMS))/sqr(RMS)",
&DrellYanBase::_min_pt, GeV, 2.*GeV, ZERO, 100000.0*GeV,
false, false, Interface::limited);
}
void DrellYanBase::doinit() {
HwMEBase::doinit();
_channelweights.push_back(_channelwgtA/(1.+_channelwgtA));
_channelweights.push_back(_channelweights[0]+1./(1.+_channelwgtA)/(1+_channelwgtB));
_channelweights.push_back(1.0);
_prefactor.push_back(_preqqbar);
_prefactor.push_back(_preqg);
_prefactor.push_back(_pregqbar);
}
void DrellYanBase::dofinish() {
HwMEBase::dofinish();
if(_nover==0) return;
generator()->log() << "DrellYanBase when applying the hard correction "
<< _nover << " weights larger than one were generated of which"
<< " the largest was " << _maxwgt << "\n";
}
RealEmissionProcessPtr DrellYanBase::applyHardMatrixElementCorrection(RealEmissionProcessPtr born) {
// get the quark,antiquark
ParticleVector incoming;
vector<tcBeamPtr> beams;
for(unsigned int ix=0;ix<born->bornIncoming().size();++ix) {
incoming.push_back(born->bornIncoming()[ix]);
tPPtr beam = born->hadrons()[ix];
beams.push_back(dynamic_ptr_cast<tcBeamPtr>(beam->dataPtr()));
}
pair<double,double> xnew = born->x();
// ensure that the quark is first
if(incoming[0]->id()<incoming[1]->id()) {
swap(incoming[0],incoming[1]);
swap(beams[0],beams[1]);
swap(xnew.first,xnew.second);
}
// and the gauge boson
Lorentz5Momentum pboson;
for(unsigned int ix=0;ix<born->bornOutgoing().size();++ix) {
pboson += born->bornOutgoing()[ix]->momentum();
}
pboson.rescaleMass();
// calculate the momenta
unsigned int iemit,itype;
vector<Lorentz5Momentum> pnew;
LorentzRotation trans;
// if not accepted return
if(!applyHard(incoming,beams,pboson,iemit,itype,pnew,trans,xnew)) return RealEmissionProcessPtr();
// if applying ME correction create the new particles
// first the final-state particles
Boost boostv=pboson.findBoostToCM();
trans *=LorentzRotation(boostv);
born->transformation(trans);
for(unsigned int ix=0;ix<born->bornOutgoing().size();++ix) {
Lorentz5Momentum pnew = trans*(born->bornOutgoing()[ix]->momentum());
born->outgoing().push_back(born->bornOutgoing()[ix]->dataPtr()->produceParticle(pnew));
}
// then emitter, spectator and emitted
// emission of a final-state gluon
if(itype==0) {
// get the momenta of the new particles
Lorentz5Momentum pquark(pnew[0]),panti(pnew[1]),pgluon(pnew[2]);
if(iemit==2) swap(pquark,panti);
// ensure gluon can be put on shell
Lorentz5Momentum ptest(pgluon);
if(ptest.boost(-(pquark+panti).boostVector()).e() <
getParticleData(ParticleID::g)->constituentMass()) return RealEmissionProcessPtr();
// outgoing gluon
born->outgoing().push_back(getParticleData(ParticleID::g)->produceParticle(pgluon));
// incoming particles
if(born->bornIncoming()[0]->id()>0) {
if(iemit==1) {
born->emitter(0);
born->spectator(1);
}
else {
born->emitter(1);
born->spectator(0);
}
born->incoming().push_back(born->bornIncoming()[0]->dataPtr()->produceParticle(pquark));
born->incoming().push_back(born->bornIncoming()[1]->dataPtr()->produceParticle(panti));
born->outgoing().back()->incomingColour(born->incoming()[0]);
born->outgoing().back()->incomingAntiColour(born->incoming()[1]);
}
else {
if(iemit==1) {
born->emitter(1);
born->spectator(0);
}
else {
born->emitter(0);
born->spectator(1);
}
born->incoming().push_back(born->bornIncoming()[0]->dataPtr()->produceParticle(panti));
born->incoming().push_back(born->bornIncoming()[1]->dataPtr()->produceParticle(pquark));
born->outgoing().back()->incomingColour(born->incoming()[1]);
born->outgoing().back()->incomingAntiColour(born->incoming()[0]);
}
}
else if(itype==1) {
Lorentz5Momentum pin(pnew[0]),pout(pnew[1]),pgluon(pnew[2]);
if(iemit==2) swap(pin,pout);
// ensure outgoing quark can be put on-shell
Lorentz5Momentum ptest(pout);
if(ptest.boost(-(pin+pgluon).boostVector()).e() <
incoming[1]->dataPtr()->constituentMass()) return RealEmissionProcessPtr();
// create the new gluon
PPtr newg = getParticleData(ParticleID::g)->produceParticle(pgluon);
// create the new outgoing quark
PPtr newout= incoming[1]->dataPtr()->CC()->produceParticle(pout);
// create the new incoming quark
PPtr newin = incoming[0]->dataPtr()->produceParticle(pin);
// colours
newout->incomingColour(newg);
newin->antiColourNeighbour(newg);
if(born->bornIncoming()[0]->id()>0) {
born->emitter (1);
born->spectator(0);
born->incoming().push_back(newin);
born->incoming().push_back(newg );
}
else {
born->emitter (0);
born->spectator(1);
born->incoming().push_back(newg );
born->incoming().push_back(newin);
}
born->outgoing().push_back(newout);
}
else if(itype==2) {
Lorentz5Momentum pin(pnew[0]),pout(pnew[1]),pgluon(pnew[2]);
if(iemit==2) swap(pin,pout);
// ensure outgoing antiquark can be put on-shell
Lorentz5Momentum ptest(pout);
if(ptest.boost(-(pin+pgluon).boostVector()).e() <
incoming[0]->dataPtr()->constituentMass()) return RealEmissionProcessPtr();
// create the new gluon
PPtr newg = getParticleData(ParticleID::g)->produceParticle(pgluon);
// create the new outgoing antiquark
PPtr newout= incoming[0]->dataPtr()->CC()->produceParticle(pout);
// create the new incoming antiquark
PPtr newin = incoming[1]->dataPtr()->produceParticle(pin);
// colours
newout->incomingAntiColour(newg);
newin->colourNeighbour(newg);
if(born->bornIncoming()[0]->id()>0) {
born->emitter (0);
born->spectator(1);
born->incoming().push_back(newg );
born->incoming().push_back(newin);
}
else {
born->emitter (1);
born->spectator(0);
born->incoming().push_back(newin);
born->incoming().push_back(newg );
}
born->outgoing().push_back(newout);
}
else
assert(false);
born->emitted(born->outgoing().size()+1);
if(born->bornIncoming()[0]->id()<0) {
swap(xnew.first,xnew.second);
}
born->x(xnew);
born->interaction(ShowerInteraction::QCD);
return born;
}
bool DrellYanBase::applyHard(ParticleVector & quarks,
vector<tcBeamPtr> beams, Lorentz5Momentum boson,
unsigned int & iemit,unsigned int & itype,
vector<Lorentz5Momentum> & pnew,
LorentzRotation & trans,
pair<double,double> & xout) {
// check that quark along +z and qbar along -z
bool quarkplus=quarks[0]->momentum().z()>quarks[1]->momentum().z();
// calculate the limits on s
Energy mb = sqrt(mb2_);
Energy2 smin=mb2_;
Energy2 s=
(generator()->currentEvent()->incoming().first ->momentum()+
generator()->currentEvent()->incoming().second->momentum()).m2();
Energy2 smax(s);
// calculate the rapidity of the boson
double yB=0.5*log((boson.e()+boson.z())/
(boson.e()-boson.z()));
if(!quarkplus) yB=-yB;
// if no phase-space return
if(smax<smin) return false;
// get the evolution scales (this needs improving)
double kappa[2]={1.,1.};
// get the momentum fractions for the leading order process
// and the values of the PDF's
double x[2]={-99.99e99,-99.99e99}, fx[2]={-99.99e99,-99.99e99};
tcPDFPtr pdf[2];
x[0] = xout. first;
x[1] = xout.second;
for(unsigned int ix=0;ix<quarks.size();++ix) {
assert(beams[ix]);
pdf[ix]=beams[ix]->pdf();
assert(pdf[ix]);
fx[ix]=pdf[ix]->xfx(beams[ix],quarks[ix]->dataPtr(),mb2_,x[ix]);
}
// select the type of process and generate the kinematics
double rn(UseRandom::rnd());
Energy2 shat(ZERO),uhat(ZERO),that(ZERO);
double weight(0.),xnew[2]={1.,1.};
// generate the value of s according to 1/s^2
shat = smax*smin/(smin+UseRandom::rnd()*(smax-smin));
Energy2 jacobian = sqr(shat)*(1./smin-1./smax);
double sbar=shat/mb2_;
// calculate limits on that
Energy2 tmax=mb2_*kappa[0]*(1.-sbar)/(kappa[0]+sbar);
Energy2 tmin=shat*(1.-sbar)/(kappa[1]+sbar);
// calculate the limits on uhat
Energy2 umax(mb2_-shat-tmin),umin(mb2_-shat-tmax);
// check inside phase space
if(tmax<tmin||umax<umin) return false;
// q qbar -> g V
if(rn<_channelweights[0]) {
// generate t and u according to 1/t+1/u
// generate in 1/t
if(UseRandom::rndbool(0.5)) {
that=tmax*pow(tmin/tmax,UseRandom::rnd());
uhat=mb2_-shat-that;
jacobian *=log(tmin/tmax);
}
// generate in 1/u
else {
uhat=umax*pow(umin/umax,UseRandom::rnd());
that=mb2_-shat-uhat;
jacobian *=log(umin/umax);
}
Energy4 jacobian2 = jacobian * 2.*uhat*that/(shat-mb2_);
// new scale (this is mt^2=pt^2+mb^2)
Energy2 scale(uhat*that/shat+mb2_);
// the PDF's with the emitted gluon
double fxnew[2];
xnew[0]=exp(yB)/sqrt(s)*sqrt(shat*(mb2_-uhat)/(mb2_-that));
xnew[1]=shat/(s*xnew[0]);
for(unsigned int ix=0;ix<2;++ix)
{fxnew[ix]=pdf[ix]->xfx(beams[ix],quarks[ix]->dataPtr(),scale,xnew[ix]);}
// jacobian and me parts of the weight
weight=jacobian2*(sqr(mb2_-that)+sqr(mb2_-uhat))/(sqr(shat)*that*uhat);
// pdf part of the weight
weight *=fxnew[0]*fxnew[1]*x[0]*x[1]/(fx[0]*fx[1]*xnew[0]*xnew[1]);
// finally coupling, colour factor and different channel pieces
weight *= 2./3./Constants::pi/_channelweights[0]*_alpha->value(scale);
// select the emiting particle
iemit=1;
if(UseRandom::rnd()<sqr(mb2_-uhat)/(sqr(mb2_-uhat)+sqr(mb2_-that))) iemit=2;
itype=0;
}
// incoming gluon
else {
// generate t
if(rn>_channelweights[1]) {
swap(tmax,tmin);
tmax=mb2_-shat-tmax;
tmin=mb2_-shat-tmin;
}
that=tmax*pow(tmin/tmax,UseRandom::rnd());
uhat=mb2_-shat-that;
Energy4 jacobian2 = jacobian * that*log(tmax/tmin);
// new scale (this is mt^2=pt^2+mb^2)
Energy2 scale(uhat*that/shat+mb2_);
// g qbar -> qbar V
double fxnew[2];
if(rn<_channelweights[1]) {
itype=2;
xnew[0]=exp(yB)/sqrt(s)*sqrt(shat*(mb2_-uhat)/(mb2_-that));
xnew[1]=shat/(s*xnew[0]);
fxnew[0]=pdf[0]->xfx(beams[0],getParticleData(ParticleID::g),scale,xnew[0]);
fxnew[1]=pdf[1]->xfx(beams[1],quarks[1]->dataPtr(),scale,xnew[1]);
jacobian2/=(_channelweights[1]-_channelweights[0]);
}
// q g -> q V
else {
itype=1;
xnew[0]=exp(yB)/sqrt(s)*sqrt(shat*(mb2_-that)/(mb2_-uhat));
xnew[1]=shat/(s*xnew[0]);
fxnew[0]=pdf[0]->xfx(beams[0],quarks[0]->dataPtr(),scale,xnew[0]);
fxnew[1]=pdf[1]->xfx(beams[1],getParticleData(ParticleID::g),scale,xnew[1]);
jacobian2/=(_channelweights[2]-_channelweights[1]);
}
// jacobian and me parts of the weight
weight=-jacobian2*(sqr(mb2_-that)+sqr(mb2_-shat))/(sqr(shat)*shat*that);
// pdf part of the weight
weight *=fxnew[0]*fxnew[1]*x[0]*x[1]/(fx[0]*fx[1]*xnew[0]*xnew[1]);
// finally coupling, colour factor and different channel pieces
weight *= 0.25/Constants::pi*_alpha->value(scale);
// select the emiting particle
iemit=1;
if(UseRandom::rnd()<sqr(mb2_-that)/(sqr(mb2_-that)+sqr(mb2_-shat))) iemit=2;
}
// if me correction should be applied
if(weight>1.) {
++_nover;
_maxwgt=max(_maxwgt,weight);
weight=1.;
}
if(UseRandom::rnd()>weight) return false;
// construct the momenta in the rest frame of the boson
Lorentz5Momentum pb(ZERO,ZERO,ZERO,mb,mb),pspect,pg,pemit;
double cos3 = 0.0;
if(itype==0)
{
pg = Lorentz5Momentum(ZERO,ZERO,ZERO,0.5*(shat-mb2_)/mb,ZERO);
Energy2 tp(that),up(uhat);
double zsign(-1.);
if(iemit==2)
{
tp=uhat;
up=that;
zsign=1.;
}
pspect = Lorentz5Momentum(ZERO,ZERO,zsign*0.5*(mb2_-tp)/mb,
0.5*(mb2_-tp)/mb,ZERO);
Energy eemit=0.5*(mb2_-up)/mb;
cos3 = 0.5/pspect.z()/pg.e()*(sqr(pspect.e())+sqr(pg.e())-sqr(eemit));
}
else
{
pg=Lorentz5Momentum(ZERO,ZERO,ZERO,0.5*(mb2_-uhat)/mb,ZERO);
double zsign(1.);
if(iemit==1)
{
if(itype==1) zsign=-1.;
pspect=Lorentz5Momentum(ZERO,ZERO,0.5*zsign*(shat-mb2_)/mb,
0.5*(shat-mb2_)/mb);
Energy eemit=0.5*(mb2_-that)/mb;
cos3 = 0.5/pspect.z()/pg.e()*(sqr(pspect.e())+sqr(pg.e())-sqr(eemit));
}
else
{
if(itype==2) zsign=-1.;
pspect=Lorentz5Momentum(ZERO,ZERO,0.5*zsign*(mb2_-that)/mb,
0.5*(mb2_-that)/mb);
Energy eemit=0.5*(shat-mb2_)/mb;
cos3 = 0.5/pspect.z()/pg.e()*(-sqr(pspect.e())-sqr(pg.e())+sqr(eemit));
}
}
// rotate the gluon
double sin3(sqrt(1.-sqr(cos3)));
double phi(Constants::twopi*UseRandom::rnd());
pg.setX(pg.e()*sin3*cos(phi));
pg.setY(pg.e()*sin3*sin(phi));
pg.setZ(pg.e()*cos3);
if(itype==0) {
pemit=pb+pg-pspect;
}
else {
if(iemit==1) pemit=pb+pspect-pg;
else pemit=pspect+pg-pb;
}
pemit.rescaleMass();
// find the new CMF
Lorentz5Momentum pp[2];
if(itype==0) {
if(iemit==1) {
pp[0]=pemit;
pp[1]=pspect;
}
else {
pp[0]=pspect;
pp[1]=pemit;
}
}
else if(itype==1) {
pp[1]=pg;
if(iemit==1) pp[0]=pemit;
else pp[0]=pspect;
}
else {
pp[0]=pg;
if(iemit==1) pp[1]=pemit;
else pp[1]=pspect;
}
Lorentz5Momentum pz= quarkplus ? pp[0] : pp[1];
pp[0]/=xnew[0];
pp[1]/=xnew[1];
Lorentz5Momentum plab(pp[0]+pp[1]);
plab.rescaleMass();
// construct the boost to rest frame of plab
trans=LorentzRotation(plab.findBoostToCM());
pz.transform(trans);
// rotate so emitting particle along z axis
// rotate so in x-z plane
trans.rotateZ(-atan2(pz.y(),pz.x()));
// rotate so along
trans.rotateY(-acos(pz.z()/pz.vect().mag()));
// undo azimuthal rotation
trans.rotateZ(atan2(pz.y(),pz.x()));
// perform the transforms
pb .transform(trans);
pspect.transform(trans);
pg .transform(trans);
pemit .transform(trans);
// momenta to be returned
pnew.push_back(pemit);
pnew.push_back(pspect);
pnew.push_back(pg);
pnew.push_back(pb);
xout.first=xnew[0];
xout.second=xnew[1];
return true;
}
bool DrellYanBase::softMatrixElementVeto(ShowerProgenitorPtr initial,
ShowerParticlePtr parent,Branching br) {
if(parent->isFinalState()) return false;
// check if me correction should be applied
long id[2]={initial->id(),parent->id()};
if(id[0]!=id[1]||id[1]==ParticleID::g) return false;
// get the pT
Energy pT=br.kinematics->pT();
// check if hardest so far
if(pT<initial->highestpT()) return false;
// compute the invariants
double kappa(sqr(br.kinematics->scale())/mb2_),z(br.kinematics->z());
Energy2 shat(mb2_/z*(1.+(1.-z)*kappa)),that(-(1.-z)*kappa*mb2_),uhat(-(1.-z)*shat);
// check which type of process
// g qbar
double wgt(1.);
if(id[0]>0&&br.ids[0]->id()==ParticleID::g)
wgt=mb2_/(shat+uhat)*(sqr(mb2_-that)+sqr(mb2_-shat))/(sqr(shat+uhat)+sqr(uhat));
else if(id[0]>0&&br.ids[0]->id()==id[0])
wgt=mb2_/(shat+uhat)*(sqr(mb2_-uhat)+sqr(mb2_-that))/(sqr(shat)+sqr(shat+uhat));
else if(id[0]<0&&br.ids[0]->id()==ParticleID::g)
wgt=mb2_/(shat+uhat)*(sqr(mb2_-that)+sqr(mb2_-shat))/(sqr(shat+uhat)+sqr(uhat));
else if(id[0]<0&&br.ids[0]->id()==id[0])
wgt=mb2_/(shat+uhat)*(sqr(mb2_-uhat)+sqr(mb2_-that))/(sqr(shat)+sqr(shat+uhat));
else
return false;
if(wgt<.0||wgt>1.) generator()->log() << "Soft ME correction weight too large or "
<< "negative in DrellYanBase::"
<< "softMatrixElementVeto()soft weight "
<< " sbar = " << shat/mb2_
<< " tbar = " << that/mb2_
<< "weight = " << wgt << "\n";
// if not vetoed
if(UseRandom::rndbool(wgt)) return false;
// otherwise
parent->vetoEmission(br.type,br.kinematics->scale());
return true;
}
RealEmissionProcessPtr DrellYanBase::generateHardest(RealEmissionProcessPtr born,
- ShowerInteraction::Type inter) {
+ ShowerInteraction inter) {
if(inter==ShowerInteraction::QED) return RealEmissionProcessPtr();
useMe();
// get the particles to be showered
_beams.clear();
_partons.clear();
// find the incoming particles
ParticleVector incoming;
_quarkplus = true;
ParticleVector particlesToShower;
// progenitor particles are produced in z direction.
for(unsigned int ix=0;ix<born->bornIncoming().size();++ix) {
incoming.push_back(born->bornIncoming()[ix]);
tPPtr beam = born->hadrons()[ix];
_beams.push_back(dynamic_ptr_cast<tcBeamPtr>(beam->dataPtr()));
_partons.push_back( born->bornIncoming()[ix]->dataPtr() );
// check that quark is along +ve z direction
if(born->bornIncoming()[ix]->id() > 0 &&
born->bornIncoming()[ix]->momentum().z() < ZERO )
_quarkplus = false;
particlesToShower.push_back( born->bornIncoming()[ix] );
}
Lorentz5Momentum pboson;
for(unsigned int ix=0;ix<born->bornOutgoing().size();++ix) {
pboson += born->bornOutgoing()[ix]->momentum();
}
pboson.rescaleMass();
// calculate the rapidity of the boson
_yb = 0.5 * log((pboson.e()+pboson.z())/(pboson.e()-pboson.z()));
_yb *= _quarkplus ? 1. : -1.;
_mass = pboson.mass();
// we are assuming quark first, swap order to ensure this
// if antiquark first
bool order = _partons[0]->id()<_partons[1]->id();
if(order) {
swap(_partons[0],_partons[1]);
swap(_beams[0],_beams[1]);
}
vector<Lorentz5Momentum> pnew;
int emission_type(-1);
// generate the hard emission and return if no emission
if(!getEvent(pnew,emission_type)) {
born->pT()[ShowerInteraction::QCD] = _min_pt;
return born;
}
// construct the HardTree object needed to perform the showers
ParticleVector newparticles;
// make the particles for the HardTree
tcPDPtr gluon=getParticleData(ParticleID::g);
// create the partons
int iemit;
// q qbar -> g V
ColinePtr newline[2]={new_ptr(ColourLine()),new_ptr(ColourLine())};
if(emission_type==0) {
newparticles.push_back(_partons[0]->produceParticle(pnew[0]));
newparticles.push_back(_partons[1]->produceParticle(pnew[1]));
newparticles.push_back(gluon ->produceParticle(pnew[2]));
newline[1]->addColoured(newparticles[0]);
newline[1]->addColoured(newparticles[2]);
newline[0]->addAntiColoured(newparticles[1]);
newline[0]->addAntiColoured(newparticles[2]);
iemit = (pnew[0]-pnew[2]).m2()>(pnew[1]-pnew[2]).m2() ? 0 : 1;
}
// q g -> q V
else if(emission_type==1) {
iemit =1;
newparticles.push_back(_partons[0]->produceParticle(pnew[0]));
newparticles.push_back(gluon ->produceParticle(pnew[1]));
newparticles.push_back(_partons[1]->CC()->produceParticle(pnew[2]));
newline[1]->addColoured(newparticles[0]);
newline[1]->addAntiColoured(newparticles[1]);
newline[0]->addColoured(newparticles[1]);
newline[0]->addColoured(newparticles[2]);
}
// g qbar -> qbar V
else {
iemit =0;
newparticles.push_back(gluon ->produceParticle(pnew[0]));
newparticles.push_back(_partons[1]->produceParticle(pnew[1]));
newparticles.push_back(_partons[0]->CC()->produceParticle(pnew[2]));
newline[0]->addAntiColoured(newparticles[1]);
newline[0]->addColoured(newparticles[0]);
newline[1]->addAntiColoured(newparticles[0]);
newline[1]->addAntiColoured(newparticles[2]);
}
int ispect = iemit == 0 ? 1 : 0;
if(iemit==0) newline[0]->addColoured(newparticles.back());
else newline[1]->addAntiColoured(newparticles.back());
// compute the boost for the bosons
LorentzRotation boost(pboson.findBoostToCM());
boost.boost(pnew[3].boostVector());
born->transformation(boost);
for(unsigned int ix=0;ix<born->bornOutgoing().size();++ix) {
born->outgoing().push_back(born->bornOutgoing()[ix]->dataPtr()->
produceParticle(born->bornOutgoing()[ix]->momentum()));
born->outgoing().back()->transform(boost);
}
if(!order) {
born->incoming().push_back(newparticles[0]);
born->incoming().push_back(newparticles[1]);
}
else {
born->incoming().push_back(newparticles[1]);
born->incoming().push_back(newparticles[0]);
swap(iemit,ispect);
}
born->outgoing().push_back(newparticles[2]);
born->emitter (iemit );
born->spectator(ispect);
born->emitted(born->bornOutgoing().size()+2);
pair<double,double> xnew;
for(unsigned int ix=0;ix<2;++ix) {
double x = born->incoming()[ix]->momentum().rho()/born->hadrons()[ix]->momentum().rho();
if(ix==0) xnew.first = x;
else xnew.second = x;
}
born->x(xnew);
born->pT()[ShowerInteraction::QCD] = _pt;
born->interaction(ShowerInteraction::QCD);
return born;
}
double DrellYanBase::getResult(int emis_type, Energy pt, double yj) {
Energy2 s=sqr(generator()->maximumCMEnergy());
Energy2 m2(sqr(_mass));
Energy2 scale = m2+sqr(pt);
Energy et=sqrt(scale);
// longitudinal real correction fractions
double x = pt*exp( yj)/sqrt(s)+et*exp( _yb)/sqrt(s);
double y = pt*exp(-yj)/sqrt(s)+et*exp(-_yb)/sqrt(s);
// reject if outside region
if(x<0.||x>1.||y<0.||y>1.||x*y<m2/s) return 0.;
// longitudinal born fractions
double x1 = _mass*exp( _yb)/sqrt(s);
double y1 = _mass*exp(-_yb)/sqrt(s);
// mandelstam variables
Energy2 th = -sqrt(s)*x*pt*exp(-yj);
Energy2 uh = -sqrt(s)*y*pt*exp( yj);
Energy2 sh = m2-th-uh;
double res;
// pdf part of the cross section
double pdf[4];
pdf[0]=_beams[0]->pdf()->xfx(_beams[0],_partons[0],m2,x1);
pdf[1]=_beams[1]->pdf()->xfx(_beams[1],_partons[1],m2,y1);
//qqbar2Zg
using Constants::pi;
if(emis_type==0) {
pdf[2]=_beams[0]->pdf()->xfx(_beams[0],_partons[0],scale,x);
pdf[3]=_beams[1]->pdf()->xfx(_beams[1],_partons[1],scale,y);
res = 4./3./pi*(sqr(th-m2)+sqr(uh-m2))*pt/(sh*uh*th)*GeV;
}
//qg2Zq
else if(emis_type==1) {
pdf[2]=_beams[0]->pdf()->xfx(_beams[0],_partons[0],scale,x);
pdf[3]=_beams[1]->pdf()->xfx(_beams[1],getParticleData(ParticleID::g),scale,y);
res = -1./2./pi*(sqr(uh-m2)+sqr(sh-m2))*pt/(sh*sh*uh)*GeV;
}
//qbarg2Zqbar
else {
pdf[2]=_beams[0]->pdf()->xfx(_beams[0],getParticleData(ParticleID::g),scale,x);
pdf[3]=_beams[1]->pdf()->xfx(_beams[1],_partons[1],scale,y);
res =- 1./2./pi*(sqr(th-m2)+sqr(sh-m2))*pt/(sh*sh*th)*GeV;
}
//deals with pdf zero issue at large x
if(pdf[0]<=0.||pdf[1]<=0.||pdf[2]<=0.||pdf[3]<=0.) {
res=0.;
}
else {
res*=pdf[2]*pdf[3]/pdf[0]/pdf[1]*m2/sh;
}
res*=_alpha->ratio(sqr(pt));
return res;
}
bool DrellYanBase::getEvent(vector<Lorentz5Momentum> & pnew,
int & emis_type){
// pt cut-off
// Energy minp = 0.1*GeV;
// maximum pt (half of centre-of-mass energy)
Energy maxp = 0.5*generator()->maximumCMEnergy();
// set pt of emission to zero
_pt=ZERO;
//Working Variables
Energy pt;
double yj;
// limits on the rapidity of the jet
double minyj = -8.0,maxyj = 8.0;
bool reject;
double wgt;
emis_type=-1;
for(int j=0;j<3;j++) {
pt=maxp;
double a = _alpha->overestimateValue()*_prefactor[j]*(maxyj-minyj)/(_power-1.);
do {
// generate next pt
pt=GeV/pow(pow(GeV/pt,_power-1)-log(UseRandom::rnd())/a,1./(_power-1.));
// generate rapidity of the jet
yj=UseRandom::rnd()*(maxyj-minyj)+ minyj;
// calculate rejection weight
wgt=getResult(j,pt,yj);
wgt/= _prefactor[j]*pow(GeV/pt,_power);
reject = UseRandom::rnd()>wgt;
//no emission event if p goes past p min - basically set to outside
//of the histogram bounds (hopefully hist object just ignores it)
if(pt<_min_pt){
pt=ZERO;
reject = false;
}
if(wgt>1.0) {
ostringstream s;
s << "DrellYanBase::getEvent weight for channel " << j
<< "is " << wgt << " which is greater than 1";
generator()->logWarning( Exception(s.str(), Exception::warning) );
}
}
while(reject);
// set pt of emission etc
if(pt>_pt){
emis_type = j;
_pt=pt;
_yj=yj;
}
}
//was this an (overall) no emission event?
if(_pt<_min_pt){
_pt=ZERO;
emis_type = 3;
}
if(emis_type==3) return false;
// generate the momenta of the particles
// hadron-hadron cmf
Energy2 s=sqr(generator()->maximumCMEnergy());
// transverse energy
Energy2 m2(sqr(_mass));
Energy et=sqrt(m2+sqr(_pt));
// first calculate all the kinematic variables
// longitudinal real correction fractions
double x = _pt*exp( _yj)/sqrt(s)+et*exp( _yb)/sqrt(s);
double y = _pt*exp(-_yj)/sqrt(s)+et*exp(-_yb)/sqrt(s);
// that and uhat
Energy2 th = -sqrt(s)*x*_pt*exp(-_yj);
Energy2 uh = -sqrt(s)*y*_pt*exp( _yj);
Energy2 sh = x*y*s;
if(emis_type==1) swap(th,uh);
// decide which was the emitting particle
unsigned int iemit=1;
// from q qbar
if(emis_type==0) {
if(UseRandom::rnd()<sqr(m2-uh)/(sqr(m2-uh)+sqr(m2-th))) iemit=2;
}
else {
if(UseRandom::rnd()<sqr(m2-th)/(sqr(m2-th)+sqr(m2-sh))) iemit=2;
}
// reconstruct the momenta in the rest frame of the gauge boson
Lorentz5Momentum pb(ZERO,ZERO,ZERO,_mass,_mass),pspect,pg,pemit;
double cos3;
if(emis_type==0) {
pg=Lorentz5Momentum(ZERO,ZERO,ZERO,0.5*(sh-m2)/_mass,ZERO);
Energy2 tp(th),up(uh);
double zsign(-1.);
if(iemit==2) {
swap(tp,up);
zsign=1;
}
pspect = Lorentz5Momentum(ZERO,ZERO
,zsign*0.5*(m2-tp)/_mass,0.5*(m2-tp)/_mass,
ZERO);
Energy eemit=0.5*(m2-up)/_mass;
cos3 = 0.5/pspect.z()/pg.e()*(sqr(pspect.e())+sqr(pg.e())-sqr(eemit));
}
else {
pg=Lorentz5Momentum(ZERO,ZERO,ZERO,0.5*(m2-uh)/_mass,ZERO);
double zsign(1.);
if(iemit==1) {
if(emis_type==1) zsign=-1.;
pspect=Lorentz5Momentum(ZERO,ZERO,0.5*zsign*(sh-m2)/_mass,0.5*(sh-m2)/_mass);
Energy eemit=0.5*(m2-th)/_mass;
cos3 = 0.5/pspect.z()/pg.e()*(sqr(pspect.e())+sqr(pg.e())-sqr(eemit));
}
else {
if(emis_type==2) zsign=-1.;
pspect=Lorentz5Momentum(ZERO,ZERO,0.5*zsign*(m2-th)/_mass,0.5*(m2-th)/_mass);
Energy eemit=0.5*(sh-m2)/_mass;
cos3 = 0.5/pspect.z()/pg.e()*(-sqr(pspect.e())-sqr(pg.e())+sqr(eemit));
}
}
// rotate the gluon
double sin3(sqrt(1.-sqr(cos3))),phi(Constants::twopi*UseRandom::rnd());
pg.setX(pg.e()*sin3*cos(phi));
pg.setY(pg.e()*sin3*sin(phi));
pg.setZ(pg.e()*cos3);
if(emis_type==0) {
pemit=pb+pg-pspect;
}
else {
if(iemit==1) pemit=pb+pspect-pg;
else pemit=pspect+pg-pb;
}
pemit .setMass(ZERO);
pg .setMass(ZERO);
pspect.setMass(ZERO);
// find the new CMF
Lorentz5Momentum pp[2];
if(emis_type==0) {
pp[0]=pemit;
pp[1]=pspect;
if(iemit==2) swap(pp[0],pp[1]);
}
else if(emis_type==1) {
pp[1]=pg;
if(iemit==1) pp[0]=pemit;
else pp[0]=pspect;
}
else {
pp[0]=pg;
if(iemit==1) pp[1]=pemit;
else pp[1]=pspect;
}
Lorentz5Momentum pz= _quarkplus ? pp[0] : pp[1];
pp[0]/=x;
pp[1]/=y;
Lorentz5Momentum plab(pp[0]+pp[1]);
plab.rescaleMass();
// construct the boost to rest frame of plab
LorentzRotation trans=LorentzRotation(plab.findBoostToCM());
pz.transform(trans);
// rotate so emitting particle along z axis
// rotate so in x-z plane
trans.rotateZ(-atan2(pz.y(),pz.x()));
// rotate so along
trans.rotateY(-acos(pz.z()/pz.vect().mag()));
// undo azimuthal rotation
trans.rotateZ(atan2(pz.y(),pz.x()));
// perform the transforms
pb .transform(trans);
pspect.transform(trans);
pg .transform(trans);
pemit .transform(trans);
// copy the momenta for the new particles
pnew.resize(4);
if(emis_type==0) {
pnew[0]=pemit;
pnew[1]=pspect;
if(iemit==2) swap(pnew[0],pnew[1]);
pnew[2]=pg;
}
else if(emis_type==1) {
pnew[0]=pemit;
pnew[2]=pspect;
if(iemit==2) swap(pnew[0],pnew[2]);
pnew[1]=pg;
}
else if(emis_type==2) {
pnew[1]=pspect;
pnew[2]=pemit;
if(iemit==1) swap(pnew[1],pnew[2]);
pnew[0]=pg;
}
pnew[3]=pb;
return true;
}
diff --git a/MatrixElement/DrellYanBase.h b/MatrixElement/DrellYanBase.h
--- a/MatrixElement/DrellYanBase.h
+++ b/MatrixElement/DrellYanBase.h
@@ -1,338 +1,338 @@
// -*- C++ -*-
#ifndef HERWIG_DrellYanBase_H
#define HERWIG_DrellYanBase_H
//
// This is the declaration of the DrellYanBase class.
//
#include "HwMEBase.h"
#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h"
namespace Herwig {
using namespace ThePEG;
/**
* The DrellYanBase class class provides a base class for the implemented
* of Drell-Yan type processes and provides the matrix element and POWHEG
* style hard corrections
*
* @see \ref DrellYanBaseInterfaces "The interfaces"
* defined for DrellYanBase.
*/
class DrellYanBase: public HwMEBase {
public:
/**
* The default constructor.
*/
DrellYanBase();
/**
* Has a POWHEG style correction
*/
//virtual bool hasPOWHEGCorrection() {return _alpha;}
virtual POWHEGType hasPOWHEGCorrection() {return ISR;}
/**
* Has an old fashioned ME correction
*/
virtual bool hasMECorrection() {return _alpha;}
/**
* Initialize the ME correction
*/
virtual void initializeMECorrection(RealEmissionProcessPtr, double & initial,
double & final) {
final = 1.;
initial = 1.;
}
/**
* Apply the hard matrix element correction to a given hard process or decay
*/
virtual RealEmissionProcessPtr applyHardMatrixElementCorrection(RealEmissionProcessPtr);
/**
* Apply the soft matrix element correction
* @param initial The particle from the hard process which started the
* shower
* @param parent The initial particle in the current branching
* @param br The branching struct
* @return If true the emission should be vetoed
*/
virtual bool softMatrixElementVeto(ShowerProgenitorPtr initial,
ShowerParticlePtr parent,
Branching br);
/**
* Apply the POWHEG style correction
*/
virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr,
- ShowerInteraction::Type);
+ ShowerInteraction);
/**
* Set the typed and momenta of the incoming and outgoing partons to
* be used in subsequent calls to me() and colourGeometries()
* according to the associated XComb object.
*/
virtual void setKinematics() {
HwMEBase::setKinematics();
mb2_ = sHat();
}
protected:
/**
* Return the momenta and type of hard matrix element correction
* @param quarks The original incoming particles.
* @param beams The BeamParticleData objects
* @param boson The momentum of the original outgoing gauge boson
* @param iemit Whether the first (0) or second (1) particle emitted
* the radiation
* @param itype The type of radiated particle (0 is gluon, 1 is quark
* and 2 is antiquark)
* @param pnew The momenta of the new particles
* @param trans The LorentzRotation from the boson rest frame to the new lab
* @param xnew The new values of the momentuym fractions
* @return Whether or not the matrix element correction needs to be applied
*/
bool applyHard(ParticleVector & quarks,
vector<tcBeamPtr> beams,
Lorentz5Momentum boson,unsigned int & iemit,
unsigned int & itype,vector<Lorentz5Momentum> & pnew,
LorentzRotation & trans, pair<double,double> & xnew);
/**
* Returns the matrix element for a given type of process,
* rapidity of the jet \f$y_j\f$ and transverse momentum \f$p_T\f$
* @param emis_type the type of emission,
* (0 is \f$q\bar{q}\to Vg\f$, 1 is \f$qg\to Vq\f$ and 2 is \f$g\bar{q}\to V\bar{q}\f$)
* @param pt The transverse momentum of the jet
* @param yj The rapidity of the jet
*/
double getResult(int emis_type, Energy pt, double yj);
/**
* generates the hardest emission (yj,p)
* @param pnew The momenta of the new particles
* @param emissiontype The type of emission, as for getResult
* @return Whether not an emission was generated
*/
bool getEvent(vector<Lorentz5Momentum> & pnew,int & emissiontype);
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();
/**
* 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 static object used to initialize the description of this class.
* Indicates that this is an abstract class with persistent data.
*/
static AbstractClassDescription<DrellYanBase> initDrellYanBase;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
DrellYanBase & operator=(const DrellYanBase &);
private:
/**
* Mass squared of the vector boson
*/
Energy2 mb2_;
/**
* Parameters for the old-style ME correction
*/
//@{
/**
* Relative weight for the \f$q\bar{q}\f$ and \f$q/\bar{q}g\f$ channels
*/
double _channelwgtA;
/**
* Relative weight for the \f$qg\f$ and \f$\bar{q}g\f$ channels
*/
double _channelwgtB;
/**
* Weights for the channels as a vector
*/
vector<double> _channelweights;
/**
* Number of weights greater than 1
*/
unsigned int _nover;
/**
* Maximum weight
*/
double _maxwgt;
//@}
/**
* Constants for the sampling. The distribution is assumed to have the
* form \f$\frac{c}{{\rm GeV}}\times\left(\frac{{\rm GeV}}{p_T}\right)^n\f$
*/
//@{
/**
* The power, \f$n\f$, for the sampling
*/
double _power;
/**
* The prefactor, \f$c\f$ for the \f$q\bar{q}\f$ channel
*/
double _preqqbar;
/**
* The prefactor, \f$c\f$ for the \f$qg\f$ channel
*/
double _preqg;
/**
* The prefactor, \f$c\f$ for the \f$g\bar{q}\f$ channel
*/
double _pregqbar;
/**
* The prefactors as a vector for easy use
*/
vector<double> _prefactor;
//@}
/**
* Properties of the incoming particles
*/
//@{
/**
* Pointers to the BeamParticleData objects
*/
vector<tcBeamPtr> _beams;
/**
* Pointers to the ParticleDataObjects for the partons
*/
vector<tcPDPtr> _partons;
//@}
/**
* Properties of the boson and jets
*/
//@{
/**
* The rapidity of the gauge boson
*/
double _yb;
/**
* The mass of the gauge boson
*/
Energy _mass;
/**
* Whether the quark is in the + or - z direction
*/
bool _quarkplus;
/**
* the rapidity of the jet
*/
double _yj;
/**
* The transverse momentum of the jet
*/
Energy _pt;
//@}
/**
* The transverse momentum of the jet
*/
Energy _min_pt;
/**
* Pointer to the object calculating the strong coupling
*/
ShowerAlphaPtr _alpha;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of DrellYanBase. */
template <>
struct BaseClassTrait<Herwig::DrellYanBase,1> {
/** Typedef of the first base class of DrellYanBase. */
typedef Herwig::HwMEBase NthBase;
};
/** This template specialization informs ThePEG about the name of
* the DrellYanBase class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::DrellYanBase>
: public ClassTraitsBase<Herwig::DrellYanBase> {
/** Return a platform-independent class name */
static string className() { return "Herwig::DrellYanBase"; }
};
/** @endcond */
}
#endif /* HERWIG_DrellYanBase_H */
diff --git a/MatrixElement/Hadron/MEPP2Higgs.cc b/MatrixElement/Hadron/MEPP2Higgs.cc
--- a/MatrixElement/Hadron/MEPP2Higgs.cc
+++ b/MatrixElement/Hadron/MEPP2Higgs.cc
@@ -1,1439 +1,1439 @@
// -*- C++ -*-
//
// MEPP2Higgs.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 MEPP2Higgs class.
//
#include "MEPP2Higgs.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/Cuts/Cuts.h"
#include "Herwig/MatrixElement/HardVertex.h"
#include "Herwig/Models/StandardModel/StandardModel.h"
#include "Herwig/Utilities/Maths.h"
#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h"
#include "Herwig/Shower/RealEmissionProcess.h"
#include "Herwig/Shower/QTilde/Base/Branching.h"
using namespace Herwig;
const complex<Energy2>
MEPP2Higgs::epsi_ = complex<Energy2>(ZERO,-1.e-10*GeV2);
MEPP2Higgs::MEPP2Higgs() : scaleopt_(1), mu_F_(100.*GeV),
shapeOption_(2), processOption_(1),
minFlavour_(4), maxFlavour_(5),
mh_(ZERO), wh_(ZERO),
minLoop_(6),maxLoop_(6),massOption_(0),
mu_R_opt_(1),mu_F_opt_(1),
channelwgtA_(0.45),channelwgtB_(0.15),
ggPow_(1.6), qgPow_(1.6), enhance_(1.1),
nover_(0), ntry_(0), ngen_(0), maxwgt_(0.),
power_(2.0), pregg_(7.), preqg_(3.),
pregqbar_(3.), minpT_(2.*GeV),
spinCorrelations_(true)
{}
ClassDescription<MEPP2Higgs> MEPP2Higgs::initMEPP2Higgs;
// Definition of the static class description member.
void MEPP2Higgs::persistentOutput(PersistentOStream & os) const {
os << HGGVertex_ << HFFVertex_ << shapeOption_ << processOption_
<< minFlavour_ << maxFlavour_ << hmass_ << ounit(mh_,GeV)
<< ounit(wh_,GeV) << minLoop_ << maxLoop_ << massOption_
<< alpha_ << prefactor_ << power_ << pregg_ << preqg_
<< pregqbar_ << ounit( minpT_, GeV ) << ggPow_ << qgPow_
<< enhance_ << channelwgtA_ << channelwgtB_ << channelWeights_
<< mu_R_opt_ << mu_F_opt_ << spinCorrelations_;
}
void MEPP2Higgs::persistentInput(PersistentIStream & is, int) {
is >> HGGVertex_ >> HFFVertex_ >> shapeOption_ >> processOption_
>> minFlavour_ >> maxFlavour_ >> hmass_ >> iunit(mh_,GeV)
>> iunit(wh_,GeV) >> minLoop_ >> maxLoop_ >> massOption_
>> alpha_ >> prefactor_ >> power_ >> pregg_ >> preqg_
>> pregqbar_ >> iunit( minpT_, GeV ) >> ggPow_ >> qgPow_
>> enhance_ >> channelwgtA_ >> channelwgtB_ >> channelWeights_
>> mu_R_opt_ >> mu_F_opt_ >> spinCorrelations_;
}
void MEPP2Higgs::Init() {
static ClassDocumentation<MEPP2Higgs> documentation
("The MEPP2Higgs class implements the matrix elements for"
" Higgs production (with decay H->W-W+) in hadron-hadron collisions"
" including the generation of additional hard QCD radiation in "
"gg to h0 processes in the POWHEG scheme",
"Hard QCD radiation for $gg\\to h^0$ processes in the"
" POWHEG scheme \\cite{Hamilton:2009za}.",
"%\\cite{Hamilton:2009za}\n"
"\\bibitem{Hamilton:2009za}\n"
" K.~Hamilton, P.~Richardson and J.~Tully,\n"
" ``A Positive-Weight Next-to-Leading Order Monte Carlo Simulation for Higgs\n"
" Boson Production,''\n"
" JHEP {\\bf 0904}, 116 (2009)\n"
" [arXiv:0903.4345 [hep-ph]].\n"
" %%CITATION = JHEPA,0904,116;%%\n");
static Switch<MEPP2Higgs,unsigned int> interfaceFactorizationScaleOption
("FactorizationScaleOption",
"Option for the choice of factorization scale",
&MEPP2Higgs::scaleopt_, 1, false, false);
static SwitchOption interfaceDynamic
(interfaceFactorizationScaleOption,
"Dynamic",
"Dynamic factorization scale equal to the current sqrt(sHat())",
1);
static SwitchOption interfaceFixed
(interfaceFactorizationScaleOption,
"Fixed",
"Use a fixed factorization scale set with FactorizationScaleValue",
2);
static Parameter<MEPP2Higgs,Energy> interfaceFactorizationScaleValue
("FactorizationScaleValue",
"Value to use in the event of a fixed factorization scale",
&MEPP2Higgs::mu_F_, GeV, 100.0*GeV, 50.0*GeV, 500.0*GeV,
true, false, Interface::limited);
static Reference<MEPP2Higgs,ShowerAlpha> interfaceCoupling
("Coupling",
"Pointer to the object to calculate the coupling for the correction",
&MEPP2Higgs::alpha_, false, false, true, false, false);
static Switch<MEPP2Higgs,unsigned int> interfaceShapeOption
("ShapeScheme",
"Option for the treatment of the Higgs resonance shape",
&MEPP2Higgs::shapeOption_, 1, false, false);
static SwitchOption interfaceStandardShapeFixed
(interfaceShapeOption,
"FixedBreitWigner",
"Breit-Wigner s-channel resonanse",
1);
static SwitchOption interfaceStandardShapeRunning
(interfaceShapeOption,
"MassGenerator",
"Use the mass generator to give the shape",
2);
static Switch<MEPP2Higgs,unsigned int> interfaceProcess
("Process",
"Which subprocesses to include",
&MEPP2Higgs::processOption_, 1, false, false);
static SwitchOption interfaceProcessAll
(interfaceProcess,
"All",
"Include all subprocesses",
1);
static SwitchOption interfaceProcess1
(interfaceProcess,
"qqbar",
"Only include the incoming q qbar subprocess",
2);
static SwitchOption interfaceProcessgg
(interfaceProcess,
"gg",
"Only include the incoming gg subprocess",
3);
static Parameter<MEPP2Higgs,unsigned int> interfaceMinimumInLoop
("MinimumInLoop",
"The minimum flavour of the quarks to include in the loops",
&MEPP2Higgs::minLoop_, 6, 5, 6,
false, false, Interface::limited);
static Parameter<MEPP2Higgs,unsigned int> interfaceMaximumInLoop
("MaximumInLoop",
"The maximum flavour of the quarks to include in the loops",
&MEPP2Higgs::maxLoop_, 6, 5, 6,
false, false, Interface::limited);
static Switch<MEPP2Higgs,unsigned int> interfaceMassOption
("MassOption",
"Option for the treatment of the masses in the loop diagrams",
&MEPP2Higgs::massOption_, 0, false, false);
static SwitchOption interfaceMassOptionFull
(interfaceMassOption,
"Full",
"Include the full mass dependence",
0);
static SwitchOption interfaceMassOptionLarge
(interfaceMassOption,
"Large",
"Use the heavy mass limit",
1);
static Parameter<MEPP2Higgs,int> interfaceMinimumFlavour
("MinimumFlavour",
"The minimum flavour of the incoming quarks in the hard process",
&MEPP2Higgs::minFlavour_, 4, 3, 5,
false, false, Interface::limited);
static Parameter<MEPP2Higgs,int> interfaceMaximumFlavour
("MaximumFlavour",
"The maximum flavour of the incoming quarks in the hard process",
&MEPP2Higgs::maxFlavour_, 5, 3, 5,
false, false, Interface::limited);
static Parameter<MEPP2Higgs,double> interfaceQGChannelWeight
("QGChannelWeight",
"The relative weights of the g g and q g channels for selection."
" This is a technical parameter for the phase-space generation and "
"should not affect the results only the efficiency and fraction"
" of events with weight > 1.",
&MEPP2Higgs::channelwgtA_, 0.45, 0., 1.e10,
false, false, Interface::limited);
static Parameter<MEPP2Higgs,double> interfaceQbarGChannelWeight
("QbarGChannelWeight",
"The relative weights of the g g abd qbar g channels for selection."
" This is a technical parameter for the phase-space generation and "
"should not affect the results only the efficiency and fraction",
&MEPP2Higgs::channelwgtB_, 0.15, 0., 1.e10,
false, false, Interface::limited);
static Parameter<MEPP2Higgs,double> interfaceGGPower
("GGPower",
"Power for the phase-space sampling of the gg channel",
&MEPP2Higgs::ggPow_, 1.6, 1.0, 3.0,
false, false, Interface::limited);
static Parameter<MEPP2Higgs,double> interfaceQGPower
("QGPower",
"Power for the phase-space sampling of the qg and qbarg channels",
&MEPP2Higgs::qgPow_, 1.6, 1.0, 3.0,
false, false, Interface::limited);
static Parameter<MEPP2Higgs,double> interfaceEnhancementFactor
("InitialEnhancementFactor",
"The enhancement factor for initial-state radiation in the shower to ensure"
" the weight for the matrix element correction is less than one.",
&MEPP2Higgs::enhance_, 1.1, 1.0, 10.0,
false, false, Interface::limited);
static Parameter<MEPP2Higgs,double> interfacePower
("Power",
"The power for the sampling of the matrix elements",
&MEPP2Higgs::power_, 2.0, 1.0, 10.0,
false, false, Interface::limited);
static Parameter<MEPP2Higgs,double> interfacePrefactorgg
("Prefactorgg",
"The prefactor for the sampling of the q qbar channel",
&MEPP2Higgs::pregg_, 7.0, 0.0, 1000.0,
false, false, Interface::limited);
static Parameter<MEPP2Higgs,double> interfacePrefactorqg
("Prefactorqg",
"The prefactor for the sampling of the q g channel",
&MEPP2Higgs::preqg_, 3.0, 0.0, 1000.0,
false, false, Interface::limited);
static Parameter<MEPP2Higgs,double> interfacePrefactorgqbar
("Prefactorgqbar",
"The prefactor for the sampling of the g qbar channel",
&MEPP2Higgs::pregqbar_, 3.0, 0.0, 1000.0,
false, false, Interface::limited);
static Parameter<MEPP2Higgs, Energy> interfacePtMin
("minPt",
"The pt cut on hardest emision generation"
"2*(1-Beta)*exp(-sqr(intrinsicpT/RMS))/sqr(RMS)",
&MEPP2Higgs::minpT_, GeV, 2.*GeV, ZERO, 100000.0*GeV,
false, false, Interface::limited);
static Switch<MEPP2Higgs,unsigned int> interface_mu_R_Option
("mu_R_Option",
"Option to use pT or mT as the scale in alphaS",
&MEPP2Higgs::mu_R_opt_, 1, false, false);
static SwitchOption interface_mu_R_Option_mT
(interface_mu_R_Option,
"mT",
"Use mT as the scale in alpha_S",
0);
static SwitchOption interface_mu_R_Option_pT
(interface_mu_R_Option,
"pT",
"Use pT as the scale in alpha_S",
1);
static Switch<MEPP2Higgs,unsigned int> interface_mu_F_Option
("mu_F_Option",
"Option to use pT or mT as the factorization scale in the PDFs",
&MEPP2Higgs::mu_F_opt_, 1, false, false);
static SwitchOption interface_mu_F_Option_mT
(interface_mu_F_Option,
"mT",
"Use mT as the scale in the PDFs",
0);
static SwitchOption interface_mu_F_Option_pT
(interface_mu_F_Option,
"pT",
"Use pT as the scale in the PDFs",
1);
static Switch<MEPP2Higgs,bool> interfaceSpinCorrelations
("SpinCorrelations",
"Which on/off spin correlations in the hard process",
&MEPP2Higgs::spinCorrelations_, true, false, false);
static SwitchOption interfaceSpinCorrelationsYes
(interfaceSpinCorrelations,
"Yes",
"Switch correlations on",
true);
static SwitchOption interfaceSpinCorrelationsNo
(interfaceSpinCorrelations,
"No",
"Switch correlations off",
false);
}
void MEPP2Higgs::doinit() {
HwMEBase::doinit();
// get the vertex pointers from the SM object
tcHwSMPtr theSM = dynamic_ptr_cast<tcHwSMPtr>(standardModel());
// do the initialisation
if(!theSM) {
throw InitException() << "Wrong type of StandardModel object in MEPP2Higgs::doinit(),"
<< " the Herwig version must be used"
<< Exception::runerror;
}
HGGVertex_ = theSM->vertexHGG();
HFFVertex_ = theSM->vertexFFH();
// get the mass generator for the higgs
PDPtr h0 = getParticleData(ParticleID::h0);
mh_ = h0->mass();
wh_ = h0->generateWidth(mh_);
if(h0->massGenerator()) {
hmass_=dynamic_ptr_cast<GenericMassGeneratorPtr>(h0->massGenerator());
}
if(shapeOption_==2&&!hmass_) throw InitException()
<< "If using the mass generator for the line shape in MEPP2Higgs::doinit()"
<< "the mass generator must be an instance of the GenericMassGenerator class"
<< Exception::runerror;
// stuff for the ME correction
double total = 1.+channelwgtA_+channelwgtB_;
channelWeights_.push_back(1./total);
channelWeights_.push_back(channelWeights_.back()+channelwgtA_/total);
channelWeights_.push_back(channelWeights_.back()+channelwgtB_/total);
// insert the different prefactors in the vector for easy look up
prefactor_.push_back(pregg_);
prefactor_.push_back(preqg_);
prefactor_.push_back(preqg_);
prefactor_.push_back(pregqbar_);
prefactor_.push_back(pregqbar_);
}
void MEPP2Higgs::dofinish() {
HwMEBase::dofinish();
if(ntry_==0) return;
generator()->log() << "MEPP2Higgs when applying the hard correction "
<< "generated " << ntry_ << " trial emissions of which "
<< ngen_ << " were accepted\n";
if(nover_==0) return;
generator()->log() << "MEPP2Higgs when applying the hard correction "
<< nover_ << " weights larger than one were generated of which"
<< " the largest was " << maxwgt_ << "\n";
}
unsigned int MEPP2Higgs::orderInAlphaS() const {
return 2;
}
unsigned int MEPP2Higgs::orderInAlphaEW() const {
return 1;
}
Energy2 MEPP2Higgs::scale() const {
return scaleopt_ == 1 ? sHat() : sqr(mu_F_);
}
int MEPP2Higgs::nDim() const {
return 0;
}
bool MEPP2Higgs::generateKinematics(const double *) {
Lorentz5Momentum pout = meMomenta()[0] + meMomenta()[1];
pout.rescaleMass();
meMomenta()[2].setMass(pout.mass());
meMomenta()[2] = LorentzMomentum(pout.x(),pout.y(),pout.z(),pout.t());
jacobian(1.0);
// check whether it passes all the cuts: returns true if it does
vector<LorentzMomentum> out(1,meMomenta()[2]);
tcPDVector tout(1,mePartonData()[2]);
return lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]);
}
void MEPP2Higgs::getDiagrams() const {
tcPDPtr h0=getParticleData(ParticleID::h0);
// gg -> H process
if(processOption_==1||processOption_==3) {
tcPDPtr g=getParticleData(ParticleID::g);
add(new_ptr((Tree2toNDiagram(2), g, g, 1, h0, -1)));
}
// q qbar -> H processes
if(processOption_==1||processOption_==2) {
for ( int i = minFlavour_; i <= maxFlavour_; ++i ) {
tcPDPtr q = getParticleData(i);
tcPDPtr qb = q->CC();
add(new_ptr((Tree2toNDiagram(2), q, qb, 1, h0, -2)));
}
}
}
CrossSection MEPP2Higgs::dSigHatDR() const {
using Constants::pi;
InvEnergy2 bwfact;
if(shapeOption_==1) {
bwfact = mePartonData()[2]->generateWidth(sqrt(sHat()))*sqrt(sHat())/pi/
(sqr(sHat()-sqr(mh_))+sqr(mh_*wh_));
}
else {
bwfact = hmass_->BreitWignerWeight(sqrt(sHat()));
}
double cs = me2() * jacobian() * pi * double(UnitRemoval::E4 * bwfact/sHat());
return UnitRemoval::InvE2 * sqr(hbarc) * cs;
}
double MEPP2Higgs::me2() const {
double output(0.0);
ScalarWaveFunction hout(meMomenta()[2],mePartonData()[2],outgoing);
// Safety code to garantee the reliable behaviour of Higgs shape limits
// (important for heavy and broad Higgs resonance).
Energy hmass = meMomenta()[2].m();
tcPDPtr h0 = mePartonData()[2];
Energy mass = h0->mass();
Energy halfmass = .5*mass;
if (.0*GeV > hmass) return 0.0;
// stricly speaking the condition is applicable if
// h0->widthUpCut() == h0->widthLoCut()...
if (h0->widthLoCut() > halfmass) {
if ( mass + h0->widthUpCut() < hmass ||
mass - h0->widthLoCut() > hmass ) return 0.0;
}
else {
if (mass + halfmass < hmass || halfmass > hmass) return 0.0;
}
if (mePartonData()[0]->id() == ParticleID::g &&
mePartonData()[1]->id() == ParticleID::g) {
VectorWaveFunction gin1(meMomenta()[0],mePartonData()[0],incoming);
VectorWaveFunction gin2(meMomenta()[1],mePartonData()[1],incoming);
vector<VectorWaveFunction> g1,g2;
for(unsigned int i = 0; i < 2; ++i) {
gin1.reset(2*i);
g1.push_back(gin1);
gin2.reset(2*i);
g2.push_back(gin2);
}
output = ggME(g1,g2,hout,false);
}
else {
if (mePartonData()[0]->id() == -mePartonData()[1]->id()) {
SpinorWaveFunction qin (meMomenta()[0],mePartonData()[0],incoming);
SpinorBarWaveFunction qbin(meMomenta()[1],mePartonData()[1],incoming);
vector<SpinorWaveFunction> fin;
vector<SpinorBarWaveFunction> ain;
for (unsigned int i = 0; i < 2; ++i) {
qin.reset(i);
fin.push_back(qin);
qbin.reset(i);
ain.push_back(qbin);
}
output = qqME(fin,ain,hout,false);
}
else assert(false);
}
return output;
}
Selector<MEBase::DiagramIndex> MEPP2Higgs::diagrams(const DiagramVector & diags) const {
Selector<DiagramIndex> sel;
for (DiagramIndex i = 0; i < diags.size(); ++i)
sel.insert(1.0, i);
return sel;
}
Selector<const ColourLines *> MEPP2Higgs::colourGeometries(tcDiagPtr diag) const {
// colour lines
static const ColourLines line1("1 -2,2 -1");
static const ColourLines line2("1 -2");
// select the colour flow
Selector<const ColourLines *> sel;
if (diag->id() == -1) {
sel.insert(1.0, &line1);
} else {
sel.insert(1.0, &line2);
}
// return the answer
return sel;
}
void MEPP2Higgs::constructVertex(tSubProPtr sub) {
if(!spinCorrelations_) return;
// extract the particles in the hard process
ParticleVector hard;
hard.push_back(sub->incoming().first);
hard.push_back(sub->incoming().second);
hard.push_back(sub->outgoing()[0]);
if(hard[0]->id() < hard[1]->id()) {
swap(hard[0],hard[1]);
}
// identify the process and calculate the matrix element
if(hard[0]->id() == ParticleID::g && hard[1]->id() == ParticleID::g) {
vector<VectorWaveFunction> g1,g2;
vector<SpinorBarWaveFunction> q;
vector<SpinorWaveFunction> qbar;
VectorWaveFunction (g1,hard[0],incoming,false,true,true);
VectorWaveFunction (g2,hard[1],incoming,false,true,true);
ScalarWaveFunction hout(hard[2],outgoing,true);
g1[1] = g1[2];
g2[1] = g2[2];
ggME(g1,g2,hout,true);
}
else {
vector<SpinorWaveFunction> q1;
vector<SpinorBarWaveFunction> q2;
SpinorWaveFunction (q1,hard[0],incoming,false,true);
SpinorBarWaveFunction (q2,hard[1],incoming,false,true);
ScalarWaveFunction hout(hard[2],outgoing,true);
qqME(q1,q2,hout,true);
}
// construct the vertex
HardVertexPtr hardvertex = new_ptr(HardVertex());
// set the matrix element for the vertex
hardvertex->ME(me_);
// set the pointers and to and from the vertex
for(unsigned int i = 0; i < 3; ++i)
hard[i]->spinInfo()->productionVertex(hardvertex);
}
double MEPP2Higgs::ggME(vector<VectorWaveFunction> g1,
vector<VectorWaveFunction> g2,
ScalarWaveFunction & in,
bool calc) const {
ProductionMatrixElement newme(PDT::Spin1,PDT::Spin1,PDT::Spin0);
Energy2 s(sHat());
double me2(0.0);
for(int i = 0; i < 2; ++i) {
for(int j = 0; j < 2; ++j) {
Complex diag = HGGVertex_->evaluate(s,g1[i],g2[j],in);
me2 += norm(diag);
if(calc) newme(2*i, 2*j, 0) = diag;
}
}
if(calc) me_.reset(newme);
// initial colour and spin factors: colour -> (8/64) and spin -> (1/4)
return me2/32.;
}
double MEPP2Higgs::qqME(vector<SpinorWaveFunction> & fin,
vector<SpinorBarWaveFunction> & ain,
ScalarWaveFunction & in,
bool calc) const {
ProductionMatrixElement newme(PDT::Spin1Half,PDT::Spin1Half,PDT::Spin0);
Energy2 s(scale());
double me2(0.0);
for(int i = 0; i < 2; ++i) {
for(int j = 0; j < 2; ++j) {
Complex diag = HFFVertex_->evaluate(s,fin[i],ain[j],in);
me2+=norm(diag);
if(calc) newme(i, j, 0) = diag;
}
}
if(calc) me_.reset(newme);
// final colour/spin factors
return me2/12.;
}
RealEmissionProcessPtr MEPP2Higgs::applyHardMatrixElementCorrection(RealEmissionProcessPtr born) {
useMe();
assert(born->bornOutgoing().size()==1);
if(born->bornIncoming()[0]->id()!=ParticleID::g)
return RealEmissionProcessPtr();
// get gluons and Higgs
// get the gluons
ParticleVector incoming;
vector<tcBeamPtr> beams;
for(unsigned int ix=0;ix<born->bornIncoming().size();++ix) {
incoming.push_back(born->bornIncoming()[ix]);
beams.push_back(dynamic_ptr_cast<tcBeamPtr>(born->hadrons()[ix]->dataPtr()));
}
pair<double,double> xnew=born->x();
if(incoming[0]->momentum().z()<ZERO) {
swap(incoming[0],incoming[1]);
swap(beams[0],beams[1]);
swap(xnew.first,xnew.second);
}
// get the Higgs
PPtr higgs;
higgs=born->bornOutgoing()[0];
// calculate the momenta
unsigned int iemit,itype;
vector<Lorentz5Momentum> pnew;
// if not accepted return
tPDPtr out;
if(!applyHard(incoming,beams,higgs,iemit,itype,pnew,xnew,out)) return RealEmissionProcessPtr();
// fix the momentum of the higgs
Boost boostv=born->bornOutgoing()[0]->momentum().findBoostToCM();
LorentzRotation trans(pnew[3].boostVector());
trans *=LorentzRotation(boostv);
born->transformation(trans);
born->outgoing().push_back(born->bornOutgoing()[0]->dataPtr()->produceParticle(pnew[3]));
born->emitted(3);
// if applying ME correction create the new particles
if(itype==0) {
// ensure gluon can be put on shell
Lorentz5Momentum ptest(pnew[2]);
if(ptest.boost(-(pnew[0]+pnew[1]).boostVector()).e() <
getParticleData(ParticleID::g)->constituentMass()) return RealEmissionProcessPtr();
// create the new gluon
PPtr newg= getParticleData(ParticleID::g)->produceParticle(pnew[2]);
PPtr newg1 = incoming[0]->dataPtr()->produceParticle(pnew[0]);
PPtr newg2 = incoming[1]->dataPtr()->produceParticle(pnew[1]);
// set emitter and spectator
if(born->bornIncoming()[0]->momentum().z()>ZERO) {
born->incoming().push_back(newg1);
born->incoming().push_back(newg2);
if(iemit==0) {
born->emitter(0);
born->spectator(1);
}
else {
born->emitter(1);
born->spectator(0);
}
}
else {
born->incoming().push_back(newg2);
born->incoming().push_back(newg1);
if(iemit==0) {
born->emitter(1);
born->spectator(0);
}
else {
born->emitter(0);
born->spectator(1);
}
}
bool colour = UseRandom::rndbool();
newg ->incomingColour(newg1,!colour);
newg ->incomingColour(newg2, colour);
newg1->colourConnect(newg2,!colour);
born->outgoing().push_back(newg);
}
else if(itype==1) {
// ensure outgoing quark can be put on-shell
Lorentz5Momentum ptest(pnew[2]);
if(ptest.boost(-(pnew[0]+pnew[1]).boostVector()).e() <
out->constituentMass()) return RealEmissionProcessPtr();
// create the new particles
PPtr newqout = out->produceParticle(pnew[2]);
PPtr newqin,newg;
if(iemit==0) {
newqin = out ->produceParticle(pnew[0]);
newg = incoming[1]->dataPtr()->produceParticle(pnew[1]);
}
else {
newg = incoming[0]->dataPtr()->produceParticle(pnew[0]);
newqin = out ->produceParticle(pnew[1]);
}
newqout->incomingColour(newg);
newg->colourConnect(newqin);
if((born->bornIncoming()[0]->momentum().z()>ZERO && iemit==0) ||
(born->bornIncoming()[0]->momentum().z()<ZERO && iemit==1)) {
born->incoming().push_back(newqin);
born->incoming().push_back(newg );
born->emitter(0);
born->spectator(1);
}
else {
born->incoming().push_back(newg );
born->incoming().push_back(newqin);
born->emitter(1);
born->spectator(0);
}
born->outgoing().push_back(newqout);
}
else if(itype==2) {
// ensure outgoing antiquark can be put on-shell
Lorentz5Momentum ptest(pnew[2]);
if(ptest.boost(-(pnew[0]+pnew[1]).boostVector()).e() <
incoming[0]->dataPtr()->constituentMass()) return RealEmissionProcessPtr();
// create the new particles
PPtr newqout = out->produceParticle(pnew[2]);
PPtr newqin,newg;
if(iemit==0) {
newqin = out ->produceParticle(pnew[0]);
newg = incoming[1]->dataPtr()->produceParticle(pnew[1]);
}
else {
newg = incoming[0]->dataPtr()->produceParticle(pnew[0]);
newqin = out ->produceParticle(pnew[1]);
}
newqout->incomingAntiColour(newg);
newg->colourConnect(newqin,true);
if((born->bornIncoming()[0]->momentum().z()>ZERO && iemit==0) ||
(born->bornIncoming()[0]->momentum().z()<ZERO && iemit==1)) {
born->incoming().push_back(newqin);
born->incoming().push_back(newg );
born->emitter(0);
born->spectator(1);
}
else {
born->incoming().push_back(newg );
born->incoming().push_back(newqin);
born->emitter(1);
born->spectator(0);
}
born->outgoing().push_back(newqout);
}
if(born->bornIncoming()[0]->momentum().z()<ZERO) {
swap(xnew.first,xnew.second);
}
born->x(xnew);
born->interaction(ShowerInteraction::QCD);
return born;
}
bool MEPP2Higgs::softMatrixElementVeto(ShowerProgenitorPtr initial,
ShowerParticlePtr parent,Branching br) {
if(parent->isFinalState()) return false;
// check if me correction should be applied
long id[2]={initial->id(),parent->id()};
// must have started as a gluon
if(id[0]!=ParticleID::g) return false;
// must be a gluon going into the hard process
if(br.ids[1]->id()!=ParticleID::g) return false;
// get the pT
Energy pT=br.kinematics->pT();
// check if hardest so far
if(pT<initial->highestpT()) return false;
// compute the invariants
double kappa(sqr(br.kinematics->scale())/mh2_),z(br.kinematics->z());
Energy2 shat(mh2_/z*(1.+(1.-z)*kappa)),that(-(1.-z)*kappa*mh2_),uhat(-(1.-z)*shat);
// check which type of process
Energy2 me;
// g g
if(br.ids[0]->id()==ParticleID::g&&br.ids[2]->id()==ParticleID::g) {
double split = 6.*(z/(1.-z)+(1.-z)/z+z*(1.-z));
me = ggME(shat,that,uhat)/split;
}
// q g
else if(br.ids[0]->id() >= 1 && br.ids[0]->id() <= 5 && br.ids[2]->id()==br.ids[0]->id()) {
double split = 4./3./z*(1.+sqr(1.-z));
me = qgME(shat,uhat,that)/split;
}
// qbar g
else if(br.ids[0]->id() <= -1 && br.ids[0]->id() >= -5 && br.ids[2]->id()==br.ids[0]->id()) {
double split = 4./3./z*(1.+sqr(1.-z));
me = qbargME(shat,uhat,that)/split;
}
else {
return false;
}
InvEnergy2 pre = 0.125/Constants::pi/loME()*sqr(mh2_)*that/shat/(shat+uhat);
double wgt = -pre*me/enhance_;
if(wgt<.0||wgt>1.) generator()->log() << "Soft ME correction weight too large or "
<< "negative in MEPP2Higgs::"
<< "softMatrixElementVeto()\n soft weight "
<< " sbar = " << shat/mh2_
<< " tbar = " << that/mh2_
<< "weight = " << wgt << " for "
<< br.ids[0]->id() << " " << br.ids[1]->id() << " "
<< br.ids[2]->id() << "\n";
// if not vetoed
if(UseRandom::rndbool(wgt)) return false;
// otherwise
parent->vetoEmission(br.type,br.kinematics->scale());
return true;
}
RealEmissionProcessPtr MEPP2Higgs::generateHardest(RealEmissionProcessPtr born,
- ShowerInteraction::Type inter) {
+ ShowerInteraction inter) {
if(inter==ShowerInteraction::QED) return RealEmissionProcessPtr();
useMe();
// get the particles to be showered
beams_.clear();
partons_.clear();
// find the incoming particles
ParticleVector incoming;
ParticleVector particlesToShower;
for(unsigned int ix=0;ix<born->bornIncoming().size();++ix) {
incoming.push_back( born->bornIncoming()[ix] );
beams_.push_back( dynamic_ptr_cast<tcBeamPtr>(born->hadrons()[ix]->dataPtr()));
partons_.push_back( born->bornIncoming()[ix]->dataPtr() );
particlesToShower.push_back( born->bornIncoming()[ix] );
}
// find the higgs boson
assert(born->bornOutgoing().size()==1);
PPtr higgs = born->bornOutgoing()[0];
// calculate the rapidity of the higgs
yh_ = 0.5 * log((higgs->momentum().e()+higgs->momentum().z())/
(higgs->momentum().e()-higgs->momentum().z()));
mass_=higgs->mass();
mh2_ = sqr(mass_);
vector<Lorentz5Momentum> pnew;
int emission_type(-1);
// generate the hard emission and return if no emission
if(!getEvent(pnew,emission_type)) {
born->pT()[ShowerInteraction::QCD] = minpT_;
return born;
}
// construct the HardTree object needed to perform the showers
ParticleVector newparticles(4);
// create the partons
int iemit=-1;
// create the jet
newparticles[3] = out_->produceParticle(pnew[3]);
// g g -> h g
if(emission_type==0) {
newparticles[0] = partons_[0]->produceParticle(pnew[0]);
newparticles[1] = partons_[1]->produceParticle(pnew[1]);
iemit = pnew[0].z()/pnew[3].z()>0. ? 0 : 1;
bool colour = UseRandom::rndbool();
newparticles[3]->incomingColour(newparticles[0],!colour);
newparticles[3]->incomingColour(newparticles[1], colour);
newparticles[0]-> colourConnect(newparticles[1],!colour);
}
// g q -> H q
else if(emission_type==1) {
newparticles[0] = partons_[0]->produceParticle(pnew[0]);
newparticles[1] = out_ ->produceParticle(pnew[1]);
iemit = 1;
newparticles[3]->incomingColour(newparticles[0]);
newparticles[0]->colourConnect (newparticles[1]);
}
// q g -> H q
else if(emission_type==2) {
newparticles[0] = out_ ->produceParticle(pnew[0]);
newparticles[1] = partons_[1]->produceParticle(pnew[1]);
iemit = 0;
newparticles[3]->incomingColour(newparticles[1]);
newparticles[1]->colourConnect (newparticles[0]);
}
// g qbar -> H qbar
else if(emission_type==3) {
newparticles[0] = partons_[0]->produceParticle(pnew[0]);
newparticles[1] = out_ ->produceParticle(pnew[1]);
iemit = 1;
newparticles[3]->incomingAntiColour(newparticles[0]);
newparticles[0]->colourConnect(newparticles[1],true);
}
// qbar g -> H qbar
else if(emission_type==4) {
newparticles[0] = out_ ->produceParticle(pnew[0]);
newparticles[1] = partons_[1]->produceParticle(pnew[1]);
iemit = 0;
newparticles[3]->incomingAntiColour(newparticles[1]);
newparticles[1]->colourConnect(newparticles[0],true);
}
unsigned int ispect = iemit==0 ? 1 : 0;
// create the boson
newparticles[2] = higgs->dataPtr()->produceParticle(pnew[2]);
born->emitter (iemit);
born->spectator(ispect);
born->emitted(3);
born->pT()[ShowerInteraction::QCD] = pt_;
pair<double,double> xnew;
for(unsigned int ix=0;ix<2;++ix) {
born->incoming().push_back(newparticles[ix]);
if(ix==0) xnew.first = newparticles[ix]->momentum().rho()/born->hadrons()[ix]->momentum().rho();
else xnew.second = newparticles[ix]->momentum().rho()/born->hadrons()[ix]->momentum().rho();
}
born->x(xnew);
for(unsigned int ix=0;ix<2;++ix)
born->outgoing().push_back(newparticles[ix+2]);
// return the answer
born->interaction(ShowerInteraction::QCD);
return born;
}
bool MEPP2Higgs::applyHard(ParticleVector gluons,
vector<tcBeamPtr> beams,PPtr higgs,
unsigned int & iemit, unsigned int & itype,
vector<Lorentz5Momentum> & pnew,
pair<double,double> & xout, tPDPtr & out) {
++ntry_;
// calculate the limits on s
Energy mh(higgs->mass());
mh2_=sqr(mh);
Energy2 smin=mh2_;
Energy2 s=
(generator()->currentEvent()->incoming().first->momentum()+
generator()->currentEvent()->incoming().second->momentum()).m2();
Energy2 smax(s);
// calculate the rapidity of the higgs
double yH = 0.5*log((higgs->momentum().e()+higgs->momentum().z())/
(higgs->momentum().e()-higgs->momentum().z()));
// if no phase-space return
if(smax<smin) return false;
// get the evolution scales (this needs improving)
double kappa[2]={1.,1.};
// get the momentum fractions for the leading order process
// and the values of the PDF's
double x[2]={xout.first,xout.second},fx[2]={-99.99e99,-99.99e99};
tcPDFPtr pdf[2];
for(unsigned int ix=0;ix<gluons.size();++ix) {
assert(beams[ix]);
pdf[ix]=beams[ix]->pdf();
assert(pdf[ix]);
fx[ix]=pdf[ix]->xfx(beams[ix],gluons[ix]->dataPtr(),mh2_,x[ix]);
}
// leading order ME
Energy4 lome = loME();
// select the type of process and generate the kinematics
double rn(UseRandom::rnd());
Energy2 shat(ZERO),uhat(ZERO),that(ZERO);
double weight(0.),xnew[2]={1.,1.};
// gg -> H g
if(rn<channelWeights_[0]) {
// generate the value of s according to 1/s^n
double rhomax(pow(smin/mh2_,1.-ggPow_)),rhomin(pow(smax/mh2_,1.-ggPow_));
double rho = rhomin+UseRandom::rnd()*(rhomax-rhomin);
shat = mh2_*pow(rho,1./(1.-ggPow_));
Energy2 jacobian = mh2_/(ggPow_-1.)*(rhomax-rhomin)*pow(shat/mh2_,ggPow_);
double sbar=shat/mh2_;
// calculate limits on that
Energy2 tmax=mh2_*kappa[0]*(1.-sbar)/(kappa[0]+sbar);
Energy2 tmin=shat*(1.-sbar)/(kappa[1]+sbar);
// calculate the limits on uhat
Energy2 umax(mh2_-shat-tmin),umin(mh2_-shat-tmax);
// check inside phase space
if(tmax<tmin||umax<umin) return false;
// generate t and u according to 1/t+1/u
// generate in 1/t
if(UseRandom::rndbool(0.5)) {
that=tmax*pow(tmin/tmax,UseRandom::rnd());
uhat=mh2_-shat-that;
jacobian *=log(tmin/tmax);
}
// generate in 1/u
else {
uhat=umax*pow(umin/umax,UseRandom::rnd());
that=mh2_-shat-uhat;
jacobian *=log(umin/umax);
}
Energy4 jacobian2 = jacobian * 2.*uhat*that/(shat-mh2_);
// new scale (this is mt^2=pt^2+mh^2)
Energy2 scale(uhat*that/shat+mh2_);
// the PDF's with the emitted gluon
double fxnew[2];
xnew[0]=exp(yH)/sqrt(s)*sqrt(shat*(mh2_-uhat)/(mh2_-that));
xnew[1]=shat/(s*xnew[0]);
if(xnew[0]<=0.||xnew[0]>=1.||xnew[1]<=0.||xnew[1]>=1.) return false;
for(unsigned int ix=0;ix<2;++ix)
fxnew[ix]=pdf[ix]->xfx(beams[ix],gluons[ix]->dataPtr(),scale,xnew[ix]);
// jacobian and me parts of the weight
weight = jacobian2*ggME(shat,uhat,that)/lome*mh2_/sqr(shat);
// pdf part of the weight
weight *=fxnew[0]*fxnew[1]*x[0]*x[1]/(fx[0]*fx[1]*xnew[0]*xnew[1]);
// finally coupling and different channel pieces
weight *= 1./16./sqr(Constants::pi)*alpha_->value(scale)/channelWeights_[0];
itype=0;
iemit = that>uhat ? 0 : 1;
out = getParticleData(ParticleID::g);
}
// incoming quark or antiquark
else {
// generate the value of s according to 1/s^n
double rhomax(pow(smin/mh2_,1.-qgPow_)),rhomin(pow(smax/mh2_,1.-qgPow_));
double rho = rhomin+UseRandom::rnd()*(rhomax-rhomin);
shat = mh2_*pow(rho,1./(1.-qgPow_));
Energy2 jacobian = mh2_/(qgPow_-1.)*(rhomax-rhomin)*pow(shat/mh2_,qgPow_);
double sbar=shat/mh2_;
// calculate limits on that
Energy2 tmax=mh2_*kappa[0]*(1.-sbar)/(kappa[0]+sbar);
Energy2 tmin=shat*(1.-sbar)/(kappa[1]+sbar);
// calculate the limits on uhat
Energy2 umax(mh2_-shat-tmin),umin(mh2_-shat-tmax);
// check inside phase space
if(tmax<tmin||umax<umin) return false;
// generate t
bool order(UseRandom::rndbool());
Energy4 jacobian2;
if(order) {
uhat=umax*pow(umin/umax,UseRandom::rnd());
that=mh2_-shat-uhat;
jacobian2 = jacobian * uhat*log(umax/umin);
}
else {
that=tmax*pow(tmin/tmax,UseRandom::rnd());
uhat=mh2_-shat-that;
jacobian2 = jacobian * that*log(tmax/tmin);
}
InvEnergy4 mewgt;
// new scale (this is mt^2=pt^2+mh^2)
Energy2 scale(uhat*that/shat+mh2_);
double fxnew[2];
xnew[0]=exp(yH)/sqrt(s)*sqrt(shat*(mh2_-uhat)/(mh2_-that));
xnew[1]=shat/(s*xnew[0]);
if(xnew[0]<=0.||xnew[0]>=1.||xnew[1]<=0.||xnew[1]>=1.) return false;
if(rn<channelWeights_[1]) {
itype = 1;
// q g -> H q
if(!order) {
out = quarkFlavour(pdf[0],scale,xnew[0],beams[0],fxnew[0],false);
fxnew[1]=pdf[1]->xfx(beams[1],gluons[1]->dataPtr(),scale,xnew[1]);
iemit = 0;
mewgt = out ? qgME(shat,uhat,that)/lome*mh2_/sqr(shat) : ZERO;
}
// g q -> H q
else {
fxnew[0]=pdf[0]->xfx(beams[0],gluons[0]->dataPtr(),scale,xnew[0]);
out = quarkFlavour(pdf[1],scale,xnew[1],beams[1],fxnew[1],false);
iemit = 1;
mewgt = out ? qgME(shat,that,uhat)/lome*mh2_/sqr(shat) : ZERO;
}
jacobian2 /= (channelWeights_[1]-channelWeights_[0]);
}
else {
itype=2;
// qbar g -> H qbar
if(!order) {
out = quarkFlavour(pdf[0],scale,xnew[0],beams[0],fxnew[0],true);
fxnew[1]=pdf[1]->xfx(beams[1],gluons[1]->dataPtr(),scale,xnew[1]);
iemit = 0;
mewgt = out ? qbargME(shat,uhat,that)/lome*mh2_/sqr(shat) : ZERO;
}
// g qbar -> H qbar
else {
fxnew[0]=pdf[0]->xfx(beams[0],gluons[0]->dataPtr(),scale,xnew[0]);
out = quarkFlavour(pdf[1],scale,xnew[1],beams[1],fxnew[1],true);
iemit = 1;
mewgt = out ? qbargME(shat,that,uhat)/lome*mh2_/sqr(shat) : ZERO;
}
jacobian2/=(channelWeights_[2]-channelWeights_[1]);
}
// weight (factor of 2 as pick q(bar)g or gq(bar)
weight = 2.*jacobian2*mewgt;
// pdf part of the weight
weight *=fxnew[0]*fxnew[1]*x[0]*x[1]/(fx[0]*fx[1]*xnew[0]*xnew[1]);
// finally coupling and different channel pieces
weight *= 1./16./sqr(Constants::pi)*alpha_->value(scale);
}
// if me correction should be applied
if(weight>1.) {
++nover_;
maxwgt_ = max( maxwgt_ , weight);
weight=1.;
}
if(UseRandom::rnd()>weight) return false;
++ngen_;
// construct the momenta
Energy roots = 0.5*sqrt(s);
Energy pt = sqrt(uhat*that/shat);
Energy mt = sqrt(uhat*that/shat+mh2_);
Lorentz5Momentum pin[2]={Lorentz5Momentum(ZERO,ZERO, xnew[0]*roots,xnew[0]*roots),
Lorentz5Momentum(ZERO,ZERO,-xnew[1]*roots,xnew[1]*roots)};
double phi = Constants::twopi*UseRandom::rnd();
Lorentz5Momentum pH(pt*cos(phi),pt*sin(phi),mt*sinh(yH),mt*cosh(yH));
Lorentz5Momentum pJ(pin[0]+pin[1]-pH);
// momenta to be returned
pnew.push_back(pin[0]);
pnew.push_back(pin[1]);
pnew.push_back(pJ);
pnew.push_back(pH);
xout.first = xnew[0];
xout.second = xnew[1];
return true;
}
Energy2 MEPP2Higgs::ggME(Energy2 s, Energy2 t, Energy2 u) {
Energy2 output;
if(massOption_==0) {
complex<Energy> me[2][2][2];
me[1][1][1] = ZERO;
me[1][1][0] = ZERO;
me[0][1][0] = ZERO;
me[0][1][1] = ZERO;
for(unsigned int ix=minLoop_; ix<=maxLoop_; ++ix ) {
Energy2 mf2=sqr(getParticleData(long(ix))->mass());
bi_[1]=B(s,mf2);
bi_[2]=B(u,mf2);
bi_[3]=B(t,mf2);
bi_[4]=B(mh2_,mf2);
bi_[1]=bi_[1]-bi_[4];
bi_[2]=bi_[2]-bi_[4];
bi_[3]=bi_[3]-bi_[4];
ci_[1]=C(s,mf2);
ci_[2]=C(u,mf2);
ci_[3]=C(t,mf2);
ci_[7]=C(mh2_,mf2);
ci_[4]=(s*ci_[1]-mh2_*ci_[7])/(s-mh2_);
ci_[5]=(u*ci_[2]-mh2_*ci_[7])/(u-mh2_);
ci_[6]=(t*ci_[3]-mh2_*ci_[7])/(t-mh2_);
di_[1]=D(t,u,s,mf2);
di_[2]=D(s,t,u,mf2);
di_[3]=D(s,u,t,mf2);
me[1][1][1]+=me1(s,u,t,mf2,1,2,3,4,5,6);
me[1][1][0]+=me2(s,u,t,mf2);
me[0][1][0]+=me1(u,s,t,mf2,2,1,3,5,4,6);
me[0][1][1]+=me1(t,u,s,mf2,3,2,1,6,5,4);
}
me[0][0][0]=-me[1][1][1];
me[0][0][1]=-me[1][1][0];
me[1][0][1]=-me[0][1][0];
me[1][0][0]=-me[0][1][1];
output = real(me[0][0][0]*conj(me[0][0][0])+
me[0][0][1]*conj(me[0][0][1])+
me[0][1][0]*conj(me[0][1][0])+
me[0][1][1]*conj(me[0][1][1])+
me[1][0][0]*conj(me[1][0][0])+
me[1][0][1]*conj(me[1][0][1])+
me[1][1][0]*conj(me[1][1][0])+
me[1][1][1]*conj(me[1][1][1]));
output *= 3./8.;
}
else {
output=32./3.*
(pow<4,1>(s)+pow<4,1>(t)+pow<4,1>(u)+pow<4,1>(mh2_))/s/t/u;
}
// spin and colour factors
return output/4./64.;
}
Energy2 MEPP2Higgs::qgME(Energy2 s, Energy2 t, Energy2 u) {
Energy2 output;
if(massOption_==0) {
complex<Energy2> A(ZERO);
Energy2 si(u-mh2_);
for(unsigned int ix=minLoop_;ix<=maxLoop_;++ix) {
Energy2 mf2=sqr(getParticleData(long(ix))->mass());
A += mf2*(2.+2.*double(u/si)*(B(u,mf2)-B(mh2_,mf2))
+double((4.*mf2-s-t)/si)*Complex(u*C(u,mf2)-mh2_*C(mh2_,mf2)));
}
output =-4.*(sqr(s)+sqr(t))/sqr(si)/u*real(A*conj(A));
}
else{
output =-4.*(sqr(s)+sqr(t))/u/9.;
}
// final colour/spin factors
return output/24.;
}
Energy2 MEPP2Higgs::qbargME(Energy2 s, Energy2 t, Energy2 u) {
Energy2 output;
if(massOption_==0) {
complex<Energy2> A(ZERO);
Energy2 si(u-mh2_);
for(unsigned int ix=minLoop_;ix<=maxLoop_;++ix) {
Energy2 mf2=sqr(getParticleData(long(ix))->mass());
A+=mf2*(2.+2.*double(u/si)*(B(u,mf2)-B(mh2_,mf2))
+double((4.*mf2-s-t)/si)*Complex(u*C(u,mf2)-mh2_*C(mh2_,mf2)));
}
output =-4.*(sqr(s)+sqr(t))/sqr(si)/u*real(A*conj(A));
}
else {
output =-4.*(sqr(s)+sqr(t))/u/9.;
}
// final colour/spin factors
return output/24.;
}
Energy4 MEPP2Higgs::loME() const {
Complex I(0);
if(massOption_==0) {
for(unsigned int ix=minLoop_;ix<=maxLoop_;++ix) {
double x = sqr(getParticleData(long(ix))->mass())/mh2_;
I += 3.*x*(2.+(4.*x-1.)*F(x));
}
}
else {
I = 1.;
}
return sqr(mh2_)/576./Constants::pi*norm(I);
}
tPDPtr MEPP2Higgs::quarkFlavour(tcPDFPtr pdf, Energy2 scale,
double x, tcBeamPtr beam,
double & pdfweight, bool anti) {
vector<double> weights;
vector<tPDPtr> partons;
pdfweight = 0.;
if(!anti) {
for(unsigned int ix=1;ix<=5;++ix) {
partons.push_back(getParticleData(long(ix)));
weights.push_back(max(0.,pdf->xfx(beam,partons.back(),scale,x)));
pdfweight += weights.back();
}
}
else {
for(unsigned int ix=1;ix<=5;++ix) {
partons.push_back(getParticleData(-long(ix)));
weights.push_back(max(0.,pdf->xfx(beam,partons.back(),scale,x)));
pdfweight += weights.back();
}
}
if(pdfweight==0.) return tPDPtr();
double wgt=UseRandom::rnd()*pdfweight;
for(unsigned int ix=0;ix<weights.size();++ix) {
if(wgt<=weights[ix]) return partons[ix];
wgt -= weights[ix];
}
assert(false);
return tPDPtr();
}
Complex MEPP2Higgs::B(Energy2 s,Energy2 mf2) const {
Complex output,pii(0.,Constants::pi);
double rat=s/(4.*mf2);
if(s<ZERO)
output=2.-2.*sqrt(1.-1./rat)*log(sqrt(-rat)+sqrt(1.-rat));
else if(s>=ZERO&&rat<1.)
output=2.-2.*sqrt(1./rat-1.)*asin(sqrt(rat));
else
output=2.-sqrt(1.-1./rat)*(2.*log(sqrt(rat)+sqrt(rat-1.))-pii);
return output;
}
complex<InvEnergy2> MEPP2Higgs::C(Energy2 s,Energy2 mf2) const {
complex<InvEnergy2> output;
Complex pii(0.,Constants::pi);
double rat=s/(4.*mf2);
if(s<ZERO)
output=2.*sqr(log(sqrt(-rat)+sqrt(1.-rat)))/s;
else if(s>=ZERO&&rat<1.)
output=-2.*sqr(asin(sqrt(rat)))/s;
else {
double cosh=log(sqrt(rat)+sqrt(rat-1.));
output=2.*(sqr(cosh)-sqr(Constants::pi)/4.-pii*cosh)/s;
}
return output;
}
Complex MEPP2Higgs::dIntegral(Energy2 a, Energy2 b, double y0) const {
Complex output;
if(b==ZERO) output=0.;
else {
Complex y1=0.5*(1.+sqrt(1.-4.*(a+epsi_)/b));
Complex y2=1.-y1;
Complex z1=y0/(y0-y1);
Complex z2=(y0-1.)/(y0-y1);
Complex z3=y0/(y0-y2);
Complex z4=(y0-1.)/(y0-y2);
output=Math::Li2(z1)-Math::Li2(z2)+Math::Li2(z3)-Math::Li2(z4);
}
return output;
}
complex<InvEnergy4> MEPP2Higgs::D(Energy2 s,Energy2 t, Energy2,
Energy2 mf2) const {
Complex output,pii(0.,Constants::pi);
Energy4 st=s*t;
Energy4 root=sqrt(sqr(st)-4.*st*mf2*(s+t-mh2_));
double xp=0.5*(st+root)/st,xm=1-xp;
output = 2.*(-dIntegral(mf2,s,xp)-dIntegral(mf2,t,xp)
+dIntegral(mf2,mh2_,xp)+log(-xm/xp)
*(log((mf2+epsi_)/GeV2)-log((mf2+epsi_-s*xp*xm)/GeV2)
+log((mf2+epsi_-mh2_*xp*xm)/GeV2)-log((mf2+epsi_-t*xp*xm)/GeV2)));
return output/root;
}
complex<Energy> MEPP2Higgs::me1(Energy2 s,Energy2 t,Energy2 u, Energy2 mf2,
unsigned int i ,unsigned int j ,unsigned int k ,
unsigned int i1,unsigned int j1,unsigned int k1) const {
Energy2 s1(s-mh2_),t1(t-mh2_),u1(u-mh2_);
return mf2*4.*sqrt(2.*s*t*u)*
(-4.*(1./(u*t)+1./(u*u1)+1./(t*t1))
-4.*((2.*s+t)*bi_[k]/sqr(u1)+(2.*s+u)*bi_[j]/sqr(t1))/s
-(s-4.*mf2)*(s1*ci_[i1]+(u-s)*ci_[j1]+(t-s)*ci_[k1])/(s*t*u)
-8.*mf2*(ci_[j1]/(t*t1)+ci_[k1]/(u*u1))
+0.5*(s-4.*mf2)*(s*t*di_[k]+u*s*di_[j]-u*t*di_[i])/(s*t*u)
+4.*mf2*di_[i]/s
-2.*(u*ci_[k]+t*ci_[j]+u1*ci_[k1]+t1*ci_[j1]-u*t*di_[i])/sqr(s));
}
complex<Energy> MEPP2Higgs::me2(Energy2 s,Energy2 t,Energy2 u,
Energy2 mf2) const {
Energy2 s1(s-mh2_),t1(t-mh2_),u1(u-mh2_);
return mf2*4.*sqrt(2.*s*t*u)*(4.*mh2_+(mh2_-4.*mf2)*(s1*ci_[4]+t1*ci_[5]+u1*ci_[6])
-0.5*(mh2_-4.*mf2)*(s*t*di_[3]+u*s*di_[2]+u*t*di_[1]) )/
(s*t*u);
}
Complex MEPP2Higgs::F(double x) const {
if(x<.25) {
double root = sqrt(1.-4.*x);
Complex pii(0.,Constants::pi);
return 0.5*sqr(log((1.+root)/(1.-root))-pii);
}
else {
return -2.*sqr(asin(0.5/sqrt(x)));
}
}
bool MEPP2Higgs::getEvent(vector<Lorentz5Momentum> & pnew,
int & emis_type){
// maximum pt (half of centre-of-mass energy)
Energy maxp = 0.5*generator()->maximumCMEnergy();
// set pt of emission to zero
pt_=ZERO;
//Working Variables
Energy pt;
double yj;
// limits on the rapidity of the jet
double minyj = -8.0,maxyj = 8.0;
bool reject;
double wgt;
emis_type=-1;
tcPDPtr outParton;
for(int j=0;j<5;++j) {
pt = maxp;
do {
double a = alpha_->overestimateValue()*prefactor_[j]*(maxyj-minyj)/(power_-1.);
// generate next pt
pt=GeV/pow(pow(GeV/pt,power_-1)-log(UseRandom::rnd())/a,1./(power_-1.));
// generate rapidity of the jet
yj=UseRandom::rnd()*(maxyj-minyj)+ minyj;
// calculate rejection weight
wgt=getResult(j,pt,yj,outParton);
wgt/= prefactor_[j]*pow(GeV/pt,power_);
reject = UseRandom::rnd()>wgt;
//no emission event if p goes past p min - basically set to outside
//of the histogram bounds (hopefully hist object just ignores it)
if(pt<minpT_){
pt=ZERO;
reject = false;
}
if(wgt>1.0) {
ostringstream s;
s << "MEPP2Higgs::getEvent weight for channel " << j
<< "is " << wgt << " which is greater than 1";
generator()->logWarning( Exception(s.str(), Exception::warning) );
}
}
while(reject);
// set pt of emission etc
if(pt>pt_){
emis_type = j;
pt_=pt;
yj_=yj;
out_ = outParton;
}
}
//was this an (overall) no emission event?
if(pt_<minpT_){
pt_=ZERO;
emis_type = 5;
}
if(emis_type==5) return false;
// generate the momenta of the particles
// hadron-hadron cmf
Energy2 s=sqr(generator()->maximumCMEnergy());
// transverse energy
Energy et=sqrt(mh2_+sqr(pt_));
// first calculate all the kinematic variables
// longitudinal real correction fractions
double x = pt_*exp( yj_)/sqrt(s)+et*exp( yh_)/sqrt(s);
double y = pt_*exp(-yj_)/sqrt(s)+et*exp(-yh_)/sqrt(s);
// that and uhat
// Energy2 th = -sqrt(s)*x*pt_*exp(-yj_);
// Energy2 uh = -sqrt(s)*y*pt_*exp( yj_);
// Energy2 sh = x*y*s;
// reconstruct the momenta
// incoming momenta
pnew.push_back(Lorentz5Momentum(ZERO,ZERO,
x*0.5*sqrt(s), x*0.5*sqrt(s),ZERO));
pnew.push_back(Lorentz5Momentum(ZERO,ZERO,
-y*0.5*sqrt(s), y*0.5*sqrt(s),ZERO));
// outgoing momenta
double phi(Constants::twopi*UseRandom::rnd());
double sphi(sin(phi)),cphi(cos(phi));
pnew.push_back(Lorentz5Momentum( cphi*pt_, sphi*pt_, et*sinh(yh_),
et*cosh(yh_), mass_));
pnew.push_back(Lorentz5Momentum(-cphi*pt_,-sphi*pt_,pt_*sinh(yj_),
pt_*cosh(yj_),ZERO));
return true;
}
double MEPP2Higgs::getResult(int emis_type, Energy pt, double yj,
tcPDPtr & outParton) {
Energy2 s=sqr(generator()->maximumCMEnergy());
Energy2 scale = mh2_+sqr(pt);
Energy et=sqrt(scale);
scale = mu_F_opt_==0 ? mh2_+sqr(pt) : sqr(pt) ;
// longitudinal real correction fractions
double x = pt*exp( yj)/sqrt(s)+et*exp( yh_)/sqrt(s);
double y = pt*exp(-yj)/sqrt(s)+et*exp(-yh_)/sqrt(s);
// reject if outside region
if(x<0.||x>1.||y<0.||y>1.||x*y<mh2_/s) return 0.;
// longitudinal born fractions
double x1 = mass_*exp( yh_)/sqrt(s);
double y1 = mass_*exp(-yh_)/sqrt(s);
// mandelstam variables
Energy2 th = -sqrt(s)*x*pt*exp(-yj);
Energy2 uh = -sqrt(s)*y*pt*exp( yj);
Energy2 sh = mh2_-th-uh;
InvEnergy2 res = InvEnergy2();
// pdf part of the cross section
double pdf[4] = {99.99e99,99.99e99,99.99e99,99.99e99};
if(mu_F_opt_==0) { // As in original version ...
pdf[0]=beams_[0]->pdf()->xfx(beams_[0],partons_[0],mh2_,x1);
pdf[1]=beams_[1]->pdf()->xfx(beams_[1],partons_[1],mh2_,y1);
} else { // As in Nason and Ridolfi paper ...
pdf[0]=beams_[0]->pdf()->xfx(beams_[0],partons_[0],scale,x1);
pdf[1]=beams_[1]->pdf()->xfx(beams_[1],partons_[1],scale,y1);
}
// g g -> H g
if(emis_type==0) {
outParton = partons_[1];
pdf[2]=beams_[0]->pdf()->xfx(beams_[0],partons_[0],scale,x);
pdf[3]=beams_[1]->pdf()->xfx(beams_[1],partons_[1],scale,y);
res = ggME(sh,uh,th)/loME();
}
// q g -> H q
else if(emis_type==1) {
outParton = quarkFlavour(beams_[0]->pdf(),scale,x,beams_[0],pdf[2],false);
pdf[3]=beams_[1]->pdf()->xfx(beams_[1],partons_[1],scale,y);
res = outParton ? qgME(sh,uh,th)/loME() : ZERO;
}
// g q -> H q
else if(emis_type==2) {
pdf[2]=beams_[0]->pdf()->xfx(beams_[0],partons_[0],scale,x);
outParton = quarkFlavour(beams_[1]->pdf(),scale,y,beams_[1],pdf[3],false);
res = outParton ? qgME(sh,th,uh)/loME() : ZERO;
}
// qbar g -> H qbar
else if(emis_type==3) {
outParton = quarkFlavour(beams_[0]->pdf(),scale,x,beams_[0],pdf[2],true);
pdf[3]=beams_[1]->pdf()->xfx(beams_[1],partons_[1],scale,y);
res = outParton ? qbargME(sh,uh,th)/loME() : ZERO;
}
// g qbar -> H qbar
else if(emis_type==4) {
pdf[2]=beams_[0]->pdf()->xfx(beams_[0],partons_[0],scale,x);
outParton = quarkFlavour(beams_[1]->pdf(),scale,y,beams_[1],pdf[3],true);
res = outParton ? qbargME(sh,th,uh)/loME() : ZERO;
}
//deals with pdf zero issue at large x
if(pdf[0]<=0.||pdf[1]<=0.||pdf[2]<=0.||pdf[3]<=0.) {
res = ZERO;
}
else {
res *= pdf[2]*pdf[3]/pdf[0]/pdf[1]*mh2_/sh;
}
scale = mu_R_opt_==0 ? mh2_+sqr(pt) : sqr(pt) ;
return alpha_->ratio(scale)/8./sqr(Constants::pi)*mh2_/sh*GeV*pt*res;
}
void MEPP2Higgs::initializeMECorrection(RealEmissionProcessPtr born, double & initial,
double & final) {
final = 1.;
initial = born->bornIncoming()[0]->id()==ParticleID::g ?
enhance_ : 1.;
}
diff --git a/MatrixElement/Hadron/MEPP2Higgs.h b/MatrixElement/Hadron/MEPP2Higgs.h
--- a/MatrixElement/Hadron/MEPP2Higgs.h
+++ b/MatrixElement/Hadron/MEPP2Higgs.h
@@ -1,742 +1,742 @@
// -*- C++ -*-
//
// MEPP2Higgs.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_MEPP2Higgs_H
#define HERWIG_MEPP2Higgs_H
//
// This is the declaration of the MEPP2Higgs class.
//
#include "Herwig/MatrixElement/HwMEBase.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "ThePEG/Helicity/Vertex/AbstractFFSVertex.h"
#include "ThePEG/Helicity/Vertex/AbstractVVSVertex.h"
#include "Herwig/PDT/GenericMassGenerator.h"
#include "Herwig/MatrixElement/ProductionMatrixElement.h"
#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h"
namespace Herwig {
using namespace ThePEG;
using namespace ThePEG::Helicity;
/**
* The MEPP2Higgs class implements the matrix element for the process
* pp->Higgs with different Higgs shape prescriptions (see details in hep-ph/9505211)
* and the NLL corrected Higgs width (see details in the FORTRAN HERWIG manual).
*
* @see \ref MEPP2HiggsInterfaces "The interfaces"
* defined for MEPP2Higgs.
*/
class MEPP2Higgs: public HwMEBase {
public:
/**
* The default constructor.
*/
MEPP2Higgs();
/**
* Return the matrix element for the kinematical configuation
* previously provided by the last call to setKinematics(). Uses
* me().
*/
virtual CrossSection dSigHatDR() const;
/**
* Set the typed and momenta of the incoming and outgoing partons to
* be used in subsequent calls to me() and colourGeometries()
* according to the associated XComb object.
*/
virtual void setKinematics() {
HwMEBase::setKinematics();
mh2_ = sHat();
}
public:
/** @name Member functions for the generation of hard QCD radiation */
//@{
/**
* Has a POWHEG style correction
*/
virtual POWHEGType hasPOWHEGCorrection() {return ISR;}
/**
* Has an old fashioned ME correction
*/
virtual bool hasMECorrection() {return true;}
/**
* Initialize the ME correction
*/
virtual void initializeMECorrection(RealEmissionProcessPtr, double &,
double & );
/**
* Apply the hard matrix element correction to a given hard process or decay
*/
virtual RealEmissionProcessPtr applyHardMatrixElementCorrection(RealEmissionProcessPtr);
/**
* Apply the soft matrix element correction
* @param initial The particle from the hard process which started the
* shower
* @param parent The initial particle in the current branching
* @param br The branching struct
* @return If true the emission should be vetoed
*/
virtual bool softMatrixElementVeto(ShowerProgenitorPtr initial,
ShowerParticlePtr parent,
Branching br);
/**
* Apply the POWHEG style correction
*/
virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr,
- ShowerInteraction::Type);
+ ShowerInteraction);
//@}
public:
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Generate internal degrees of freedom given nDim() uniform
* random numbers in the interval \f$ ]0,1[ \f$. To help the phase space
* generator, the dSigHatDR should be a smooth function of these
* numbers, although this is not strictly necessary.
* @param r a pointer to the first of nDim() consecutive random numbers.
* @return true if the generation succeeded, otherwise false.
*/
virtual bool generateKinematics(const double * r);
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* The number of internal degrees of freedom used in the matrix
* element.
*/
virtual int nDim() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *> colourGeometries(tcDiagPtr diag) const;
/**
* Construct the vertex of spin correlations.
*/
virtual void constructVertex(tSubProPtr);
//@}
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 { return new_ptr(*this); }
/** 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 { return new_ptr(*this); }
//@}
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();
/**
* Finalize this object. Called in the run phase just after a
* run has ended. Used eg. to write out statistics.
*/
virtual void dofinish();
//@}
protected:
/**
* Members to calculate the real emission matrix elements
*/
//@{
/**
* The leading-order matrix element for \f$gg\to H\f$
*/
Energy4 loME() const;
/**
* The matrix element for \f$gg\to H g\f$
*/
Energy2 ggME(Energy2 s, Energy2 t, Energy2 u);
/**
* The matrix element for \f$qg\to H q\f$
*/
Energy2 qgME(Energy2 s, Energy2 t, Energy2 u);
/**
* The matrix element for \f$qbarg\to H qbar\f$
*/
Energy2 qbargME(Energy2 s, Energy2 t, Energy2 u);
//@}
/**
* Members to calculate the functions for the loop diagrams
*/
//@{
/**
* The \f$B(s)\f$ function of NBP339 (1990) 38-66
* @param s The scale
* @param mf2 The fermion mass squared.
*/
Complex B(Energy2 s,Energy2 mf2) const;
/**
* The \f$C(s)\f$ function of NBP339 (1990) 38-66
* @param s The scale
* @param mf2 The fermion mass squared.
*/
complex<InvEnergy2> C(Energy2 s,Energy2 mf2) const;
/**
* The \f$C(s)\f$ function of NBP339 (1990) 38-66
* @param s The \f$s\f$ invariant
* @param t The \f$t\f$ invariant
* @param u The \f$u\f$ invariant
* @param mf2 The fermion mass squared
*/
complex<InvEnergy4> D(Energy2 s,Energy2 t, Energy2 u,Energy2 mf2) const;
/**
* The integral \f$\int\frac{dy}{y-y_0}\log(a-i\epsilon-b y(1-y))\f$
* from NBP339 (1990) 38-66.
* @param a The parameter \f$a\f$.
* @param b The parameter \f$b\f$.
* @param y0 The parameter \f$y_0\f$.
*/
Complex dIntegral(Energy2 a, Energy2 b, double y0) const;
/**
* The \f$M_{+++}\f$ matrix element of NBP339 (1990) 38-66.
* @param s The \f$s\f$ invariant
* @param t The \f$t\f$ invariant
* @param u The \f$u\f$ invariant
* @param mf2 The fermion mass squared.
* @param i Which of the stored values to use for \f$D(u,t)\f$.
* @param j Which of the stored values to use for \f$D(u,s)\f$.
* @param k Which of the stored values to use for \f$D(s,t)\f$.
* @param i1 Which of the stored values to use for \f$C_1(s)\f$.
* @param j1 Which of the stored values to use for \f$C_1(t)\f$.
* @param k1 Which of the stored values to use for \f$C_1(u)\f$.
*/
complex<Energy> me1(Energy2 s,Energy2 t,Energy2 u, Energy2 mf2,
unsigned int i,unsigned int j, unsigned int k,
unsigned int i1,unsigned int j1, unsigned int k1) const;
/**
* The \f$M_{++-}\f$ matrix element of NBP339 (1990) 38-66.
* @param s The \f$s\f$ invariant
* @param t The \f$t\f$ invariant
* @param u The \f$u\f$ invariant
* @param mf2 The fermion mass squared.
*/
complex<Energy> me2(Energy2 s,Energy2 t,Energy2 u, Energy2 mf2) const;
/**
* The \f$F(x)\f$ function for the leading-order result
*/
Complex F(double x) const;
//@}
/**
* Method to extract the PDF weight for quark/antiquark
* initiated processes and select the quark flavour
*/
tPDPtr quarkFlavour(tcPDFPtr pdf, Energy2 scale, double x, tcBeamPtr beam,
double & pdfweight, bool anti);
/**
* Return the momenta and type of hard matrix element correction
* @param gluons The original incoming particles.
* @param beams The BeamParticleData objects
* @param higgs The original outgoing higgs
* @param iemit Whether the first (0) or second (1) particle emitted
* the radiation
* @param itype The type of radiated particle (0 is gluon, 1 is quark
* and 2 is antiquark)
* @param pnew The momenta of the new particles
* @param xnew The new values of the momentuym fractions
* @param out The ParticleData object for the outgoing parton
* @return Whether or not the matrix element correction needs to be applied
*/
bool applyHard(ParticleVector gluons,
vector<tcBeamPtr> beams,
PPtr higgs,unsigned int & iemit,
unsigned int & itype,vector<Lorentz5Momentum> & pnew,
pair<double,double> & xnew,
tPDPtr & out);
/**
* generates the hardest emission (yj,p)
* @param pnew The momenta of the new particles
* @param emissiontype The type of emission, as for getResult
* @return Whether not an emission was generated
*/
bool getEvent(vector<Lorentz5Momentum> & pnew,int & emissiontype);
/**
* Returns the matrix element for a given type of process,
* rapidity of the jet \f$y_j\f$ and transverse momentum \f$p_T\f$
* @param emis_type the type of emission,
* (0 is \f$gg\to h^0g\f$, 1 is \f$qg\to h^0q\f$ and 2 is \f$g\bar{q}\to h^0\bar{q}\f$)
* @param pt The transverse momentum of the jet
* @param yj The rapidity of the jet
* @param outParton the outgoing parton
*/
double getResult(int emis_type, Energy pt, double yj,tcPDPtr & outParton);
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEPP2Higgs> initMEPP2Higgs;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEPP2Higgs & operator=(const MEPP2Higgs &);
//@}
/**
* Members to return the matrix elements for the different subprocesses
*/
//@{
/**
* Calculates the matrix element for the process g,g->h (via quark loops)
* @param g1 a vector of wave functions of the first incoming gluon
* @param g2 a vector of wave functions of the second incoming gluon
* @param calc Whether or not to calculate the matrix element for spin correlations
* @return the amlitude value.
*/
double ggME(vector<VectorWaveFunction> g1,
vector<VectorWaveFunction> g2,
ScalarWaveFunction &,
bool calc) const;
/**
* Calculates the matrix element for the process q,qbar->h
* @param fin a vector of quark spinors
* @param ain a vector of anti-quark spinors
* @param calc Whether or not to calculate the matrix element for spin correlations
* @return the amlitude value.
*/
double qqME(vector<SpinorWaveFunction> & fin,
vector<SpinorBarWaveFunction> & ain,
ScalarWaveFunction &,
bool calc) const;
//@}
private:
/**
* Selects a dynamic (sHat) or fixed factorization scale
*/
unsigned int scaleopt_;
/**
* The value associated to the fixed factorization scale option
*/
Energy mu_F_;
/**
* Defines the Higgs resonance shape
*/
unsigned int shapeOption_;
/**
* The processes to be included (GG->H and/or qq->H)
*/
unsigned int processOption_;
/**
* Minimum flavour of incoming quarks
*/
int minFlavour_;
/**
* Maximum flavour of incoming quarks
*/
int maxFlavour_;
/**
* Matrix element for spin correlations
*/
ProductionMatrixElement me_;
/**
* Pointer to the H-> 2 gluon vertex (used in gg->H)
*/
AbstractVVSVertexPtr HGGVertex_;
/**
* Pointer to the fermion-fermion Higgs vertex (used in qq->H)
*/
AbstractFFSVertexPtr HFFVertex_;
/**
* The mass generator for the Higgs
*/
GenericMassGeneratorPtr hmass_;
/**
* On-shell mass for the higgs
*/
Energy mh_;
/**
* On-shell width for the higgs
*/
Energy wh_;
/**
* Stuff for the ME correction
*/
//@{
/**
* Parameters for the evaluation of the loops for the
* matrix elements
*/
//@{
/**
* Minimum flavour of quarks to include in the loops
*/
unsigned int minLoop_;
/**
* Maximum flavour of quarks to include in the loops
*/
unsigned int maxLoop_;
/**
* Option for treatment of the fermion loops
*/
unsigned int massOption_;
/**
* Option for dynamic scale choice in alpha_S (0=mT,>0=pT)
*/
unsigned int mu_R_opt_;
/**
* Option for dynamic scale choice in PDFs (0=mT,>0=pT)
*/
unsigned int mu_F_opt_;
//@}
//@}
/**
* Small complex number to regularize some integrals
*/
static const complex<Energy2> epsi_;
/**
* Storage of the loop functions
*/
//@{
/**
* B functions
*/
mutable Complex bi_[5];
/**
* C functions
*/
mutable complex<InvEnergy2> ci_[8];
/**
* D functions
*/
mutable complex<InvEnergy4> di_[4];
//@}
/**
* Pointer to the object calculating the strong coupling
*/
ShowerAlphaPtr alpha_;
/**
* Mass squared of Higgs
*/
Energy2 mh2_;
/**
* Relative weight of the \f$qg\f$ to the \f$gg\f$ channel
*/
double channelwgtA_;
/**
* Relative weight for the \f$\bar{q}g\f$ to the \f$gg\f$ channel
*/
double channelwgtB_;
/**
* Weights for the channels as a vector
*/
vector<double> channelWeights_;
/**
* Power for the \f$\frac{{\rm d}\hat{s}}{\hat{s}^n}\f$ importance sampling
* of the \f$gg\f$ component
*/
double ggPow_;
/**
* Power for the \f$\frac{{\rm d}\hat{s}}{\hat{s}^n}\f$ importance sampling
* of the \f$qg\f$ and \f$\bar{q}g\f$ components
*/
double qgPow_;
/**
* The enhancement factor for initial-state radiation
*/
double enhance_;
/**
* Number of weights greater than 1
*/
unsigned int nover_;
/**
* Number of attempts
*/
unsigned int ntry_;
/**
* Number which suceed
*/
unsigned int ngen_;
/**
* Maximum weight
*/
double maxwgt_;
//@}
/**
* Constants for the sampling. The distribution is assumed to have the
* form \f$\frac{c}{{\rm GeV}}\times\left(\frac{{\rm GeV}}{p_T}\right)^n\f$
*/
//@{
/**
* The power, \f$n\f$, for the sampling
*/
double power_;
/**
* The prefactor, \f$c\f$ for the \f$gg\f$ channel
*/
double pregg_;
/**
* The prefactor, \f$c\f$ for the \f$qg\f$ channel
*/
double preqg_;
/**
* The prefactor, \f$c\f$ for the \f$g\bar{q}\f$ channel
*/
double pregqbar_;
/**
* The prefactors as a vector for easy use
*/
vector<double> prefactor_;
//@}
/**
* The transverse momentum of the jet
*/
Energy minpT_;
/**
* Properties of the incoming particles
*/
//@{
/**
* Pointers to the BeamParticleData objects
*/
vector<tcBeamPtr> beams_;
/**
* Pointers to the ParticleDataObjects for the partons
*/
vector<tcPDPtr> partons_;
//@}
/**
* Properties of the boson and jets
*/
//@{
/**
* The rapidity of the Higgs boson
*/
double yh_;
/**
* The mass of the Higgs boson
*/
Energy mass_;
/**
* the rapidity of the jet
*/
double yj_;
/**
* The transverse momentum of the jet
*/
Energy pt_;
/**
* The outgoing parton
*/
tcPDPtr out_;
//@}
/**
* Whether of not to construct the vertex for spin correlations
*/
bool spinCorrelations_;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the base classes of MEPP2Higgs. */
template <>
struct BaseClassTrait<Herwig::MEPP2Higgs,1> {
/** Typedef of the first base class of MEPP2Higgs. */
typedef Herwig::HwMEBase NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEPP2Higgs class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEPP2Higgs>
: public ClassTraitsBase<Herwig::MEPP2Higgs> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEPP2Higgs"; }
/**
* The name of a file containing the dynamic library where the class
* MEPP2Higgs is implemented. It may also include several, space-separated,
* libraries if the class MEPP2Higgs depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMEHadron.so"; }
};
/** @endcond */
}
#endif /* HERWIG_MEPP2Higgs_H */
diff --git a/MatrixElement/Hadron/MEPP2HiggsVBF.cc b/MatrixElement/Hadron/MEPP2HiggsVBF.cc
--- a/MatrixElement/Hadron/MEPP2HiggsVBF.cc
+++ b/MatrixElement/Hadron/MEPP2HiggsVBF.cc
@@ -1,1453 +1,1453 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the MEPP2HiggsVBF class.
//
#include "MEPP2HiggsVBF.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "ThePEG/PDT/StandardMatchers.h"
#include <numeric>
#include "Herwig/Utilities/Maths.h"
#include "Herwig/Models/StandardModel/StandardModel.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h"
#include "Herwig/Shower/QTilde/Base/Branching.h"
#include "Herwig/Shower/RealEmissionProcess.h"
using namespace Herwig;
// namespace {
// using namespace Herwig;
// using namespace ThePEG;
// using namespace ThePEG::Helicity;
// void debuggingMatrixElement(bool BGF,
// tcPDPtr partons1, tcPDPtr partons2,
// tcPDPtr partons3, tcPDPtr partons4,
// const Lorentz5Momentum & psystem0,
// const Lorentz5Momentum & psystem1,
// const Lorentz5Momentum & pother0,
// const Lorentz5Momentum & pother1,
// const Lorentz5Momentum & p0,
// const Lorentz5Momentum & p1,
// const Lorentz5Momentum & p2,
// const Lorentz5Momentum & phiggs,
// Energy2 Q12, Energy2 scale,
// double old) {
// // get the vertex and the boson
// tcHwSMPtr hwsm=ThePEG::dynamic_ptr_cast<tcHwSMPtr>
// (CurrentGenerator::current().standardModel());
// assert(hwsm);
// tcPDPtr boson;
// AbstractFFVVertexPtr weakVertex;
// AbstractFFVVertexPtr strongVertex = hwsm->vertexFFG();
// AbstractVVSVertexPtr higgsVertex = hwsm->vertexWWH();
// if(partons1->id()==partons2->id()) {
// weakVertex = hwsm->vertexFFZ();
// boson = hwsm->getParticleData(ParticleID::Z0);
// }
// else {
// weakVertex = hwsm->vertexFFW();
// boson = hwsm->getParticleData(ParticleID::Wplus);
// }
// tcPDPtr hdata = hwsm->getParticleData(ParticleID::h0);
// tcPDPtr gluon = hwsm->getParticleData(ParticleID::g);
// SpinorWaveFunction q1,q2;
// SpinorBarWaveFunction qbar1,qbar2;
// if(partons1->id()>0) {
// q1 = SpinorWaveFunction (psystem0,partons1,incoming);
// qbar1 = SpinorBarWaveFunction(psystem1,partons2,outgoing);
// }
// else {
// q1 = SpinorWaveFunction (psystem1,partons2,outgoing);
// qbar1 = SpinorBarWaveFunction(psystem0,partons1,incoming);
// }
// if(partons3->id()>0) {
// q2 = SpinorWaveFunction (pother0,partons3,incoming);
// qbar2 = SpinorBarWaveFunction(pother1,partons4,outgoing);
// }
// else {
// q2 = SpinorWaveFunction (pother1,partons4,outgoing);
// qbar2 = SpinorBarWaveFunction(pother0,partons3,incoming);
// }
// ScalarWaveFunction higgs(phiggs,hdata,outgoing);
// if(!BGF) {
// SpinorWaveFunction q1p;
// SpinorBarWaveFunction qbar1p;
// if(partons1->id()>0) {
// q1p = SpinorWaveFunction (p0 ,partons1,incoming);
// qbar1p = SpinorBarWaveFunction(p1 ,partons2,outgoing);
// }
// else {
// q1p = SpinorWaveFunction (p1 ,partons2,outgoing);
// qbar1p = SpinorBarWaveFunction(p0 ,partons1,incoming);
// }
// VectorWaveFunction gl(p2,gluon,outgoing);
// double lome(0.),realme(0.);
// for(unsigned int lhel1=0;lhel1<2;++lhel1) {
// q2.reset(lhel1);
// for(unsigned int lhel2=0;lhel2<2;++lhel2) {
// qbar2.reset(lhel2);
// VectorWaveFunction off1
// = weakVertex->evaluate(scale,3,boson,q2,qbar2);
// VectorWaveFunction off2
// = higgsVertex->evaluate(scale,3,boson,off1,higgs);
// for(unsigned int qhel1=0;qhel1<2;++qhel1) {
// q1.reset(qhel1);
// q1p.reset(qhel1);
// for(unsigned int qhel2=0;qhel2<2;++qhel2) {
// qbar1.reset(qhel2);
// qbar1p.reset(qhel2);
// Complex diag = weakVertex->evaluate(scale,q1,qbar1,off2);
// lome += norm(diag);
// for(unsigned int ghel=0;ghel<2;++ghel) {
// gl.reset(2*ghel);
// SpinorWaveFunction inter1 =
// strongVertex->evaluate(Q12,5,q1p.particle(),q1p,gl);
// Complex diag1 = weakVertex->evaluate(scale,inter1,qbar1p,off2);
// SpinorBarWaveFunction inter2 =
// strongVertex->evaluate(Q12,5,qbar1p.particle(),qbar1p,gl);
// Complex diag2 = weakVertex->evaluate(scale,q1p,inter2,off2);
// realme += norm(diag1+diag2);
// }
// }
// }
// }
// }
// double test1 = realme/lome/hwsm->alphaS(Q12)*Q12*UnitRemoval::InvE2;
// cerr << "testing ratio A " << old/test1 << "\n";
// }
// else {
// SpinorWaveFunction q1p;
// SpinorBarWaveFunction qbar1p;
// if(partons1->id()>0) {
// q1p = SpinorWaveFunction (p2,partons1->CC(),outgoing);
// qbar1p = SpinorBarWaveFunction(p1,partons2 ,outgoing);
// }
// else {
// q1p = SpinorWaveFunction (p1,partons2 ,outgoing);
// qbar1p = SpinorBarWaveFunction(p2,partons1->CC(),outgoing);
// }
// VectorWaveFunction gl(p0,gluon,incoming);
// double lome(0.),realme(0.);
// for(unsigned int lhel1=0;lhel1<2;++lhel1) {
// q2.reset(lhel1);
// for(unsigned int lhel2=0;lhel2<2;++lhel2) {
// qbar2.reset(lhel2);
// VectorWaveFunction off1
// = weakVertex->evaluate(scale,3,boson,q2,qbar2);
// VectorWaveFunction off2
// = higgsVertex->evaluate(scale,3,boson,off1,higgs);
// for(unsigned int qhel1=0;qhel1<2;++qhel1) {
// q1.reset(qhel1);
// q1p.reset(qhel1);
// for(unsigned int qhel2=0;qhel2<2;++qhel2) {
// qbar1.reset(qhel2);
// qbar1p.reset(qhel2);
// Complex diag = weakVertex->evaluate(scale,q1,qbar1,off2);
// lome += norm(diag);
// for(unsigned int ghel=0;ghel<2;++ghel) {
// gl.reset(2*ghel);
// SpinorWaveFunction inter1 =
// strongVertex->evaluate(Q12,5,q1p.particle(),q1p,gl);
// Complex diag1 = weakVertex->evaluate(scale,inter1,qbar1p,off2);
// SpinorBarWaveFunction inter2 =
// strongVertex->evaluate(Q12,5,qbar1p.particle(),qbar1p,gl);
// Complex diag2 = weakVertex->evaluate(scale,q1p,inter2,off2);
// realme += norm(diag1+diag2);
// }
// }
// }
// }
// }
// double test1 = realme/lome/hwsm->alphaS(Q12)*Q12*UnitRemoval::InvE2;
// cerr << "testing ratio B " << old/test1 << "\n";
// }
// }
// }
MEPP2HiggsVBF::MEPP2HiggsVBF() : comptonWeight_(8.), BGFWeight_(30.),
pTmin_(1.*GeV),initial_(10.),final_(8.),
procProb_(0.5), comptonInt_(0.), bgfInt_(0.),
nover_(0),maxwgt_(make_pair(0.,0.))
{}
void MEPP2HiggsVBF::doinit() {
gluon_ = getParticleData(ParticleID::g);
// integrals of me over phase space
double r5=sqrt(5.),darg((r5-1.)/(r5+1.)),ath(0.5*log((1.+1./r5)/(1.-1./r5)));
comptonInt_ = 2.*(-21./20.-6./(5.*r5)*ath+sqr(Constants::pi)/3.
-2.*Math::ReLi2(1.-darg)-2.*Math::ReLi2(1.-1./darg));
bgfInt_ = 121./9.-56./r5*ath;
// get the vertex pointers from the SM object
tcHwSMPtr hwsm= dynamic_ptr_cast<tcHwSMPtr>(standardModel());
if(!hwsm)
throw InitException() << "Wrong type of StandardModel object in "
<< "MEPP2HiggsVBF::doinit() the Herwig"
<< " version must be used"
<< Exception::runerror;
// set the vertex
setWWHVertex(hwsm->vertexWWH());
higgs(getParticleData(ParticleID::h0));
MEfftoffH::doinit();
}
void MEPP2HiggsVBF::dofinish() {
MEfftoffH::dofinish();
if(nover_==0) return;
generator()->log() << "VBFMECorrection when applying the hard correction "
<< nover_ << " weights larger than one were generated of which"
<< " the largest was " << maxwgt_.first << " for the QCD compton"
<< " processes and " << maxwgt_.second << " for the BGF process\n";
}
void MEPP2HiggsVBF::getDiagrams() const {
// get the quark particle data objects as we'll be using them
tcPDPtr q[6],qbar[6];
for ( int ix=0; ix<5; ++ix ) {
q [ix] = getParticleData(ix+1);
qbar[ix] = q[ix]->CC();
}
// WW processes
if(process()==0||process()==1) {
std::vector<pair<tcPDPtr,tcPDPtr> > parentpair;
parentpair.reserve(6);
// don't even think of putting 'break' in here!
switch(maxFlavour()) {
case 5:
if (minFlavour()<=4)
parentpair.push_back(make_pair(getParticleData(ParticleID::b),
getParticleData(ParticleID::c)));
if (minFlavour()<=2)
parentpair.push_back(make_pair(getParticleData(ParticleID::b),
getParticleData(ParticleID::u)));
case 4:
if (minFlavour()<=3)
parentpair.push_back(make_pair(getParticleData(ParticleID::s),
getParticleData(ParticleID::c)));
if (minFlavour()<=1)
parentpair.push_back(make_pair(getParticleData(ParticleID::d),
getParticleData(ParticleID::c)));
case 3:
if (minFlavour()<=2)
parentpair.push_back(make_pair(getParticleData(ParticleID::s),
getParticleData(ParticleID::u)));
case 2:
if (minFlavour()<=1)
parentpair.push_back(make_pair(getParticleData(ParticleID::d),
getParticleData(ParticleID::u)));
default:
;
}
for(unsigned int ix=0;ix<parentpair.size();++ix) {
for(unsigned int iy=0;iy<parentpair.size();++iy) {
// q1 q2 -> q1' q2' h
if(parentpair[ix].first->id()<parentpair[iy].second->id()) {
add(new_ptr((Tree2toNDiagram(4), parentpair[ix].first, WMinus(), WPlus(),
parentpair[iy].second, 1, parentpair[ix].second, 3,
parentpair[iy].first, 2, higgs(),-1)));
}
else {
add(new_ptr((Tree2toNDiagram(4), parentpair[iy].second, WPlus(), WMinus(),
parentpair[ix].first, 1, parentpair[iy].first, 3,
parentpair[ix].second, 2, higgs(),-1)));
}
// q1 qbar2 -> q1' qbar2' h
add(new_ptr((Tree2toNDiagram(4), parentpair[ix].first, WMinus(), WPlus(),
parentpair[iy].first->CC(), 1,
parentpair[ix].second, 3, parentpair[iy].second->CC(),
2, higgs(),-1)));
add(new_ptr((Tree2toNDiagram(4),parentpair[iy].second, WPlus(), WMinus(),
parentpair[ix].second->CC(), 1, parentpair[iy].first,
3, parentpair[ix].first->CC(),
2, higgs(),-1)));
// qbar1 qbar2 -> qbar1' qbar2' h
if(parentpair[ix].first->id()<parentpair[ix].second->id()) {
add(new_ptr((Tree2toNDiagram(4), parentpair[ix].first->CC(), WPlus(), WMinus(),
parentpair[iy].second->CC(), 1,
parentpair[ix].second->CC(), 3, parentpair[iy].first->CC(),
2, higgs(),-1)));
}
else {
add(new_ptr((Tree2toNDiagram(4), parentpair[iy].second->CC(), WMinus(), WPlus(),
parentpair[ix].first->CC(), 1,
parentpair[iy].first->CC(), 3, parentpair[ix].second->CC(),
2, higgs(),-1)));
}
}
}
}
// ZZ processes
if(process()==0||process()==2) {
for(unsigned int ix=minFlavour()-1;ix<maxFlavour();++ix) {
for(unsigned int iy=ix;iy<maxFlavour();++iy) {
// q q -> q q H
add(new_ptr((Tree2toNDiagram(4), q[ix], Z0(), Z0(), q[iy],
1, q[ix], 3, q[iy], 2, higgs(),-2)));
// qbar qbar -> qbar qbar H
add(new_ptr((Tree2toNDiagram(4), qbar[ix], Z0(), Z0(), qbar[iy],
1, qbar[ix], 3, qbar[iy], 2, higgs(),-2)));
}
// q qbar -> q qbar H
for(unsigned int iy=minFlavour()-1;iy<maxFlavour();++iy) {
add(new_ptr((Tree2toNDiagram(4), q[ix], Z0(), Z0(), qbar[iy],
1, q[ix], 3, qbar[iy], 2, higgs(),-2)));
}
}
}
}
void MEPP2HiggsVBF::persistentOutput(PersistentOStream & os) const {
os << initial_ << final_
<< alpha_ << ounit(pTmin_,GeV) << comptonWeight_ << BGFWeight_ << gluon_
<< comptonInt_ << bgfInt_ << procProb_;
}
void MEPP2HiggsVBF::persistentInput(PersistentIStream & is, int) {
is >> initial_ >> final_
>> alpha_ >> iunit(pTmin_,GeV) >> comptonWeight_ >> BGFWeight_ >> gluon_
>> comptonInt_ >> bgfInt_ >> procProb_;
}
ClassDescription<MEPP2HiggsVBF> MEPP2HiggsVBF::initMEPP2HiggsVBF;
// Definition of the static class description member.
void MEPP2HiggsVBF::Init() {
static ClassDocumentation<MEPP2HiggsVBF> documentation
("The MEPP2HiggsVBF class implements Higgs production via vector-boson fusion");
static Reference<MEPP2HiggsVBF,ShowerAlpha> interfaceShowerAlphaQCD
("ShowerAlphaQCD",
"The object calculating the strong coupling constant",
&MEPP2HiggsVBF::alpha_, false, false, true, false, false);
static Parameter<MEPP2HiggsVBF,Energy> interfacepTMin
("pTMin",
"The minimum pT",
&MEPP2HiggsVBF::pTmin_, GeV, 1.*GeV, 0.0*GeV, 10.0*GeV,
false, false, Interface::limited);
static Parameter<MEPP2HiggsVBF,double> interfaceComptonWeight
("ComptonWeight",
"Weight for the overestimate ofthe compton channel",
&MEPP2HiggsVBF::comptonWeight_, 50.0, 0.0, 100.0,
false, false, Interface::limited);
static Parameter<MEPP2HiggsVBF,double> interfaceBGFWeight
("BGFWeight",
"Weight for the overestimate of the BGF channel",
&MEPP2HiggsVBF::BGFWeight_, 100.0, 0.0, 1000.0,
false, false, Interface::limited);
static Parameter<MEPP2HiggsVBF,double> interfaceProcessProbability
("ProcessProbability",
"The probabilty of the QCD compton process for the process selection",
&MEPP2HiggsVBF::procProb_, 0.3, 0.0, 1.,
false, false, Interface::limited);
}
RealEmissionProcessPtr MEPP2HiggsVBF::generateHardest(RealEmissionProcessPtr born,
- ShowerInteraction::Type inter) {
+ ShowerInteraction inter) {
if(inter==ShowerInteraction::QED) return RealEmissionProcessPtr();
pair<tPPtr,tPPtr> first,second;
pair<tcBeamPtr,tcBeamPtr> beams;
pair<tPPtr,tPPtr> hadrons;
// get the incoming particles
for(unsigned int ix=0;ix<born->bornIncoming().size();++ix) {
if(!first.first) {
first.first = born->bornIncoming()[ix];
hadrons.first = born->hadrons()[ix];
beams.first = dynamic_ptr_cast<tcBeamPtr>(born->hadrons()[ix]->dataPtr());
}
else {
second.first = born->bornIncoming()[ix];
hadrons.second = born->hadrons()[ix];
beams.second = dynamic_ptr_cast<tcBeamPtr>(born->hadrons()[ix]->dataPtr());
}
}
// and the outgoing
for(unsigned int ix=0;ix<born->bornOutgoing().size();++ix) {
if(born->bornOutgoing()[ix]->id()==ParticleID::h0) {
higgs_ = born->bornOutgoing()[ix];
}
else {
if(abs(born->bornOutgoing()[ix]->id())>5) continue;
if(born->bornOutgoing()[ix]->colourLine()&&
born->bornOutgoing()[ix]->colourLine()==first.first->colourLine()) {
first.second = born->bornOutgoing()[ix];
continue;
}
if(born->bornOutgoing()[ix]->antiColourLine()&&
born->bornOutgoing()[ix]->antiColourLine()==first.first->antiColourLine()) {
first.second = born->bornOutgoing()[ix];
continue;
}
if(born->bornOutgoing()[ix]->colourLine()&&
born->bornOutgoing()[ix]->colourLine()==second.first->colourLine()) {
second.second = born->bornOutgoing()[ix];
continue;
}
if(born->bornOutgoing()[ix]->antiColourLine()&&
born->bornOutgoing()[ix]->antiColourLine()==second.first->antiColourLine()) {
second.second = born->bornOutgoing()[ix];
continue;
}
}
}
// loop over the two possible emitting systems
q_ [0] = first .second->momentum()-first .first->momentum();
q2_[0] = -q_[0].m2();
q_ [1] = second.second->momentum()-second.first->momentum();
q2_[1] = -q_[1].m2();
for(unsigned int ix=0;ix<2;++ix) {
if(ix==1) {
swap(first,second);
swap(beams.first,beams.second);
swap(hadrons.first,hadrons.second);
}
// check beam, all particles
assert(beams.first && higgs_ &&
first .first && first.second &&
second.first && second.second);
// beam and pdf
beam_[ix] = beams.first;
pdf_ [ix] = beam_[ix]->pdf();
assert(beam_[ix] && pdf_[ix] );
// Particle data objects
partons_[ix][0] = first. first->dataPtr();
partons_[ix][1] = first.second->dataPtr();
partons_[ix][2] = second. first->dataPtr();
partons_[ix][3] = second.second->dataPtr();
// extract the born variables
xB_[ix] = first.first->momentum().rho()/hadrons.first->momentum().rho();
Lorentz5Momentum pb = first.first->momentum();
Axis axis(q_[ix].vect().unit());
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
rot_[ix] = LorentzRotation();
if(axis.perp2()>1e-20) {
rot_[ix].setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
rot_[ix].rotateX(Constants::pi);
}
if(abs(1.-q_[ix].e()/q_[ix].vect().mag())>1e-6)
rot_[ix].boostZ( q_[ix].e()/q_[ix].vect().mag());
pb *= rot_[ix];
if(pb.perp2()/GeV2>1e-20) {
Boost trans = -1./pb.e()*pb.vect();
trans.setZ(0.);
rot_[ix].boost(trans);
}
// momenta of the particles
phiggs_ [ix] = rot_[ix]*higgs_->momentum();
pother_ [ix][0] = rot_[ix]*second. first->momentum();
pother_ [ix][1] = rot_[ix]*second.second->momentum();
psystem_[ix][0] = rot_[ix]* first. first->momentum();
psystem_[ix][1] = rot_[ix]* first.second->momentum();
q_[ix] *= rot_[ix];
pTCompton_[ix] = pTBGF_[ix] = ZERO;
// generate a compton point
generateCompton(ix);
// generate a BGF point
generateBGF(ix);
}
// no valid emissions, return
if(pTCompton_[0]<ZERO && pTCompton_[1]<ZERO&&
pTBGF_ [0]<ZERO && pTBGF_ [1]<ZERO) {
born->pT()[ShowerInteraction::QCD] = pTmin_;
return born;
}
// find the maximum pT emission
unsigned int system = 0;
bool isCompton = false;
Energy pTmax = -GeV;
for(unsigned int ix=0;ix<2;++ix) {
if(pTCompton_[ix]>pTmax) {
pTmax = pTCompton_[ix];
isCompton = true;
system = ix;
}
if(pTBGF_[ix]>pTmax) {
pTmax = pTBGF_[ix];
isCompton = false;
system = ix;
}
}
if(system==0) {
swap(first,second);
swap(beams.first,beams.second);
swap(hadrons.first,hadrons.second);
}
// the non emitting particles
PPtr spectin =second.first ->dataPtr()->produceParticle(second.first ->momentum());
PPtr spectout=second.second->dataPtr()->produceParticle(second.second->momentum());
spectout->incomingColour(spectin,spectout->id()<0);
PPtr higgs = higgs_->dataPtr()->produceParticle(higgs_->momentum());
rot_[system].invert();
PPtr newout,newin,emitted;
bool FSR = false;
bool isQuark = first.first->colourLine();
// compton hardest
if(isCompton) {
for(unsigned int ix=0;ix<ComptonMomenta_[system].size();++ix) {
ComptonMomenta_[system][ix].transform(rot_[system]);
}
newout = partons_[system][1]->produceParticle(ComptonMomenta_[system][1]);
emitted = gluon_ ->produceParticle(ComptonMomenta_[system][2]);
newin = partons_[system][0]->produceParticle(ComptonMomenta_[system][0]);
FSR = !ComptonISFS_[system];
emitted->incomingColour(newin,!isQuark);
emitted->colourConnect(newout,!isQuark);
}
// BGF hardest
else {
for(unsigned int ix=0;ix<BGFMomenta_[system].size();++ix) {
BGFMomenta_[system][ix].transform(rot_[system]);
}
FSR = false;
newin = gluon_ ->produceParticle(BGFMomenta_[system][0]);
emitted = partons_[system][0]->CC()->produceParticle(BGFMomenta_[system][2]);
newout = partons_[system][1] ->produceParticle(BGFMomenta_[system][1]);
emitted->incomingColour(newin, isQuark);
newout ->incomingColour(newin,!isQuark);
}
pair<double,double> x;
pair<unsigned int,unsigned int> radiators;
if(born->bornIncoming()[0]!=first.first) {
born->incoming().push_back(spectin);
born->incoming().push_back(newin);
x.first = born->bornIncoming()[0]->momentum().rho()/born->hadrons()[0]->momentum().rho();
x.second = newin ->momentum().rho()/born->hadrons()[1]->momentum().rho();
radiators.first = 1;
}
else {
born->incoming().push_back(newin);
born->incoming().push_back(spectin);
x.first = newin ->momentum().rho()/born->hadrons()[0]->momentum().rho();
x.second = born->bornIncoming()[1]->momentum().rho()/born->hadrons()[1]->momentum().rho();
radiators.first = 0;
}
born->x(x);
for(unsigned int ix=0;ix<born->bornOutgoing().size();++ix) {
if(born->bornOutgoing()[ix]==second.second) {
born->outgoing().push_back(spectout);
}
else if(born->bornOutgoing()[ix]==first.second) {
radiators.second = born->outgoing().size()+2;
born->outgoing().push_back(newout);
}
else
born->outgoing().push_back(higgs);
}
if(FSR) swap(radiators.first,radiators.second);
born->emitter (radiators.first );
born->spectator(radiators.second);
born->emitted(born->outgoing().size()+2);
// radiated particle
born->outgoing().push_back(emitted);
born->pT()[ShowerInteraction::QCD] = isCompton ? pTCompton_[system] : pTBGF_[system];
born->interaction(ShowerInteraction::QCD);
return born;
}
void MEPP2HiggsVBF::generateCompton(unsigned int system) {
// calculate the A coefficient for the correlations
acoeff_ = A(partons_[system][0],partons_[system][1],
partons_[system][2],partons_[system][3]);
// maximum value of the xT
double xT = sqrt((1.-xB_[system])/xB_[system]);
double xTMin = 2.*pTmin_/sqrt(q2_[system]);
double zp;
// prefactor
double a = alpha_->overestimateValue()*comptonWeight_/Constants::twopi;
// loop to generate kinematics
double wgt(0.),xp(0.);
l_ = 2.*pother_[system][0]/sqrt(q2_[system]);
m_ = 2.*pother_[system][1]/sqrt(q2_[system]);
vector<double> azicoeff;
do {
wgt = 0.;
// intergration variables dxT/xT^3
xT *= 1./sqrt(1.-2.*log(UseRandom::rnd())/a*sqr(xT));
// dz
zp = UseRandom::rnd();
xp = 1./(1.+0.25*sqr(xT)/zp/(1.-zp));
// check allowed
if(xp<xB_[system]||xp>1.) continue;
// phase-space piece of the weight
wgt = 8.*(1.-xp)*zp/comptonWeight_;
// PDF piece of the weight
Energy2 mu2 = q2_[system]*((1.-xp)*(1-zp)*zp/xp+1.);
double pdf = pdf_[system]->xfx(beam_[system],partons_[system][0],
mu2 ,xB_[system]/xp)/
pdf_[system]->xfx(beam_[system],partons_[system][0],
scale(),xB_[system] );
wgt *= max(pdf,0.);
// me piece of the weight
// double me = comptonME(system,xT,xp,zp,phi);
double x2 = 1.-(1.-zp)/xp;
azicoeff = ComptonME(xp,x2,xT,l_,m_);
double me = 4./3.*alpha_->ratio(0.25*q2_[system]*sqr(xT))*
(azicoeff[0]+0.5*azicoeff[2]+0.5*azicoeff[4]);
wgt *= me;
if(wgt>1.||wgt<-1e-8) {
ostringstream wstring;
wstring << "MEPP2HiggsVBF::generateCompton() "
<< "Weight greater than one or less than zero"
<< "wgt = " << wgt << "\n";
generator()->logWarning( Exception(wstring.str(),
Exception::warning) );
}
}
while(xT>xTMin&&UseRandom::rnd()>wgt);
if(xT<=xTMin) {
pTCompton_[system]=-GeV;
return;
}
// generate phi
unsigned int itry(0);
double phimax = std::accumulate(azicoeff.begin(),azicoeff.end(),0.);
double phiwgt,phi;
do {
phi = UseRandom::rnd()*Constants::twopi;
double cphi(cos(phi)),sphi(sin(phi));
phiwgt = azicoeff[0]+azicoeff[5]*sphi*cphi
+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi)
+azicoeff[3]*sphi+azicoeff[4]*sqr(sphi);
++itry;
}
while (phimax*UseRandom::rnd() > phiwgt && itry<200);
if(itry==200) throw Exception() << "Too many tries in MEPP2HiggsVBF"
<< "::generateCompton() to"
<< " generate phi" << Exception::eventerror;
// momenta for the configuration
Energy Q(sqrt(q2_[system]));
double x1 = -1./xp;
double x2 = 1.-(1.-zp)/xp;
double x3 = 2.+x1-x2;
Lorentz5Momentum p1( 0.5*Q*xT*cos(phi), 0.5*Q*xT*sin(phi),
-0.5*Q*x2, 0.5*Q*sqrt(sqr(xT)+sqr(x2)));
Lorentz5Momentum p2(-0.5*Q*xT*cos(phi), -0.5*Q*xT*sin(phi),
-0.5*Q*x3, 0.5*Q*sqrt(sqr(xT)+sqr(x3)));
Lorentz5Momentum p0(ZERO,ZERO,-0.5*Q*x1,-0.5*Q*x1);
pTCompton_[system] = 0.5*Q*xT;
ComptonMomenta_[system].resize(3);
ComptonMomenta_[system][0] = p0;
ComptonMomenta_[system][1] = p1;
ComptonMomenta_[system][2] = p2;
ComptonISFS_[system] = zp>xp;
}
double MEPP2HiggsVBF::comptonME(unsigned int system, double xT,
double xp, double zp, double phi) {
// scale and prefactors
double CFfact = 4./3.*alpha_->ratio(0.25*q2_[system]*sqr(xT));
Energy Q(sqrt(q2_[system]));
double x1 = -1./xp;
double x2 = 1.-(1.-zp)/xp;
double x3 = 2.+x1-x2;
//set NLO momenta
Lorentz5Momentum p1( 0.5*Q*xT*cos(phi), 0.5*Q*xT*sin(phi),
-0.5*Q*x2, 0.5*Q*sqrt(sqr(xT)+sqr(x2)));
Lorentz5Momentum p2(-0.5*Q*xT*cos(phi), -0.5*Q*xT*sin(phi),
-0.5*Q*x3, 0.5*Q*sqrt(sqr(xT)+sqr(x3)));
Lorentz5Momentum p0(ZERO,ZERO,-0.5*Q*x1,-0.5*Q*x1);
Lorentz5Momentum qnlo = p2+p1-p0;
// Breit frame variables
Lorentz5Momentum r1 = -p0/x1;
Lorentz5Momentum r2 = p1/x2;
// electroweak parameters
double c0L,c1L,c0R,c1R;
// W
if(partons_[system][0]->id()!=partons_[system][1]->id()) {
c0L = sqrt(0.5);
c0R = 0;
c1L = sqrt(0.5);
c1R = 0;
}
// Z
else {
if(abs(partons_[system][0]->id())%2==0) {
c0L =
generator()->standardModel()->vu()+
generator()->standardModel()->au();
c0R =
generator()->standardModel()->vu()-
generator()->standardModel()->au();
}
else {
c0L =
generator()->standardModel()->vd()+
generator()->standardModel()->ad();
c0R =
generator()->standardModel()->vd()-
generator()->standardModel()->ad();
}
if(abs(partons_[system][2]->id())%2==0) {
c1L =
generator()->standardModel()->vu()+
generator()->standardModel()->au();
c1R =
generator()->standardModel()->vu()-
generator()->standardModel()->au();
}
else {
c1L =
generator()->standardModel()->vd()+
generator()->standardModel()->ad();
c1R =
generator()->standardModel()->vd()-
generator()->standardModel()->ad();
}
c0L *= 0.25;
c0R *= 0.25;
c1L *= 0.25;
c1R *= 0.25;
}
// Matrix element variables
double G1 = sqr(c0L*c1L)+sqr(c0R*c1R);
double G2 = sqr(c0L*c1R)+sqr(c0R*c1L);
Energy4 term1,term2,loME;
if(partons_[system][0]->id()>0) {
if(partons_[system][2]->id()>0) {
term1 = loMatrixElement(r1 ,pother_[system][0],
qnlo+r1 ,pother_[system][1],G1,G2);
term2 = loMatrixElement(r2-qnlo ,pother_[system][0],
r2 ,pother_[system][1],G1,G2);
loME = loMatrixElement(psystem_[system][0],pother_[system][0],
psystem_[system][1],pother_[system][1],G1,G2);
}
else {
term1 = loMatrixElement(r1 ,pother_[system][1],
qnlo+r1 ,pother_[system][0],G1,G2);
term2 = loMatrixElement(r2-qnlo ,pother_[system][1],
r2 ,pother_[system][0],G1,G2);
loME = loMatrixElement(psystem_[system][0],pother_[system][1],
psystem_[system][1],pother_[system][0],G1,G2);
}
}
else {
if(partons_[system][2]->id()>0) {
term1 = loMatrixElement(qnlo+r1 ,pother_[system][0],
r1 ,pother_[system][1],G1,G2);
term2 = loMatrixElement(r2 ,pother_[system][0],
r2-qnlo ,pother_[system][1],G1,G2);
loME = loMatrixElement(psystem_[system][1],pother_[system][0],
psystem_[system][0],pother_[system][1],G1,G2);
}
else {
term1 = loMatrixElement(qnlo+r1,pother_[system][1],r1 ,
pother_[system][0],G1,G2);
term2 = loMatrixElement(r2 ,pother_[system][1],r2-qnlo,
pother_[system][0],G1,G2);
loME = loMatrixElement(psystem_[system][1],pother_[system][1],
psystem_[system][0],pother_[system][0],G1,G2);
}
}
double R1 = term1/loME;
double R2 = sqr(x2)/(sqr(x2)+sqr(xT))*(term2/loME);
// debuggingMatrixElement(false,
// partons_[system][0],partons_[system][1],
// partons_[system][2],partons_[system][3],
// psystem_[system][0],psystem_[system][1],
// pother_ [system][0],pother_ [system][1],
// p0,p1,p2,phiggs_[system],q2_[system],scale(),
// 8.*Constants::pi/(1.-xp)/(1.-zp)*(R1+sqr(xp)*(sqr(x2)+sqr(xT))*R2));
// cerr << "testing pieces A " << R1 << " " << sqr(xp)*(sqr(x2)+sqr(xT)) << " " << R2 << "\n";
return CFfact*(R1+sqr(xp)*(sqr(x2)+sqr(xT))*R2);
}
void MEPP2HiggsVBF::generateBGF(unsigned int system) {
// maximum value of the xT
double xT = (1.-xB_[system])/xB_[system];
double xTMin = 2.*pTmin_/sqrt(q2_[system]);
double zp;
// prefactor
double a = alpha_->overestimateValue()*BGFWeight_/Constants::twopi;
// loop to generate kinematics
double wgt(0.),xp(0.);
l_ = 2.*pother_[system][0]/sqrt(q2_[system]);
m_ = 2.*pother_[system][1]/sqrt(q2_[system]);
vector<double> azicoeff;
do {
wgt = 0.;
// intergration variables dxT/xT^3
xT *= 1./sqrt(1.-2.*log(UseRandom::rnd())/a*sqr(xT));
// dzp
zp = UseRandom::rnd();
xp = 1./(1.+0.25*sqr(xT)/zp/(1.-zp));
// check allowed
if(xp<xB_[system]||xp>1.) continue;
// phase-space piece of the weight
wgt = 8.*sqr(1.-xp)*zp/BGFWeight_;
// PDF piece of the weight
Energy2 mu2 = q2_[system]*((1.-xp)*(1-zp)*zp/xp+1.);
wgt *= pdf_[system]->xfx(beam_[system],gluon_ ,
mu2 ,xB_[system]/xp)/
pdf_[system]->xfx(beam_[system],partons_[system][0],
scale(),xB_[system]);
// me piece of the weight
//double me = BGFME(system,xT,xp,zp,phi);
double x1 = -1./xp;
double x2 = 1.-(1.-zp)/xp;
double x3 = 2.+x1-x2;
azicoeff = BGFME(xp,x2,x3,xT,l_,m_);
double me = 0.5*alpha_->ratio(0.25*q2_[system]*sqr(xT))*
(azicoeff[0]+0.5*azicoeff[2]+0.5*azicoeff[4]);
wgt *= me;
if(wgt>1.||wgt<-1e-8) {
ostringstream wstring;
wstring << "MEPP2HiggsVBF::generateBGF() "
<< "Weight greater than one or less than zero"
<< "wgt = " << wgt << "\n";
generator()->logWarning( Exception(wstring.str(),
Exception::warning) );
}
}
while(xT>xTMin&&UseRandom::rnd()>wgt);
if(xT<=xTMin) {
pTBGF_[system] = -GeV;
return;
}
// generate phi
unsigned int itry(0);
double phimax = std::accumulate(azicoeff.begin(),azicoeff.end(),0.);
double phiwgt,phi;
do {
phi = UseRandom::rnd()*Constants::twopi;
double cphi(cos(phi)),sphi(sin(phi));
phiwgt = azicoeff[0]+azicoeff[5]*sphi*cphi
+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi)
+azicoeff[3]*sphi+azicoeff[4]*sqr(sphi);
++itry;
}
while (phimax*UseRandom::rnd() > phiwgt && itry<200);
if(itry==200) throw Exception() << "Too many tries in MEPP2HiggsVBF"
<< "::generateBGF() to"
<< " generate phi" << Exception::eventerror;
// momenta for the configuration
Energy Q(sqrt(q2_[system]));
double x1 = -1./xp;
double x2 = 1.-(1.-zp)/xp;
double x3 = 2.+x1-x2;
Lorentz5Momentum p1( 0.5*Q*xT*cos(phi), 0.5*Q*xT*sin(phi),
-0.5*Q*x2, 0.5*Q*sqrt(sqr(xT)+sqr(x2)));
Lorentz5Momentum p2(-0.5*Q*xT*cos(phi), -0.5*Q*xT*sin(phi),
-0.5*Q*x3, 0.5*Q*sqrt(sqr(xT)+sqr(x3)));
Lorentz5Momentum p0(ZERO,ZERO,-0.5*Q*x1,-0.5*Q*x1);
pTBGF_[system] = 0.5*Q*xT;
BGFMomenta_[system].resize(3);
BGFMomenta_[system][0] = p0;
BGFMomenta_[system][1] = p1;
BGFMomenta_[system][2] = p2;
}
double MEPP2HiggsVBF::BGFME(unsigned int system, double xT,
double xp, double zp, double phi) {
// scale and prefactors
double TRfact = 0.5*alpha_->ratio(0.25*q2_[system]*sqr(xT));
Energy Q(sqrt(q2_[system]));
double x1 = -1./xp;
double x2 = 1.-(1.-zp)/xp;
double x3 = 2.+x1-x2;
// Set NLO momenta
Lorentz5Momentum p1( 0.5*Q*xT*cos(phi), 0.5*Q*xT*sin(phi),
-0.5*Q*x2, 0.5*Q*sqrt(sqr(xT)+sqr(x2)));
Lorentz5Momentum p2(-0.5*Q*xT*cos(phi), -0.5*Q*xT*sin(phi),
-0.5*Q*x3, 0.5*Q*sqrt(sqr(xT)+sqr(x3)));
Lorentz5Momentum p0(ZERO,ZERO,-0.5*Q*x1,-0.5*Q*x1);
Lorentz5Momentum qnlo = p2+p1-p0;
// Breit frame variables
Lorentz5Momentum r2 = p1/x2;
Lorentz5Momentum r3 = -p2/x3;
// electroweak parameters
double c0L,c1L,c0R,c1R;
// W
if(partons_[system][0]->id()!=partons_[system][1]->id()) {
c0L = sqrt(0.5);
c0R = 0;
c1L = sqrt(0.5);
c1R = 0;
}
// Z
else {
if(abs(partons_[system][0]->id())%2==0) {
c0L =
generator()->standardModel()->vu()+
generator()->standardModel()->au();
c0R =
generator()->standardModel()->vu()-
generator()->standardModel()->au();
}
else {
c0L =
generator()->standardModel()->vd()+
generator()->standardModel()->ad();
c0R =
generator()->standardModel()->vd()-
generator()->standardModel()->ad();
}
if(abs(partons_[system][2]->id())%2==0) {
c1L =
generator()->standardModel()->vu()+
generator()->standardModel()->au();
c1R =
generator()->standardModel()->vu()-
generator()->standardModel()->au();
}
else {
c1L =
generator()->standardModel()->vd()+
generator()->standardModel()->ad();
c1R =
generator()->standardModel()->vd()-
generator()->standardModel()->ad();
}
c0L *= 0.25;
c0R *= 0.25;
c1L *= 0.25;
c1R *= 0.25;
}
// Matrix element variables
double G1 = sqr(c0L*c1L)+sqr(c0R*c1R);
double G2 = sqr(c0L*c1R)+sqr(c0R*c1L);
Energy4 term2,term3,loME;
if(partons_[system][0]->id()>0) {
if(partons_[system][2]->id()>0) {
term2 = loMatrixElement(r2-qnlo,pother_[system][0],
r2 ,pother_[system][1],G1,G2);
term3 = loMatrixElement(r3 ,pother_[system][0],
qnlo+r3,pother_[system][1],G1,G2);
loME = loMatrixElement(psystem_[system][0],pother_[system][0],
psystem_[system][1],pother_[system][1],G1,G2);
}
else {
term2 = loMatrixElement(r2-qnlo,pother_[system][1],
r2 ,pother_[system][0],G1,G2);
term3 = loMatrixElement(r3 ,pother_[system][1],
qnlo+r3,pother_[system][0],G1,G2);
loME = loMatrixElement(psystem_[system][0],pother_[system][1],
psystem_[system][1],pother_[system][0],G1,G2);
}
}
else {
if(partons_[system][2]->id()>0) {
term2 = loMatrixElement(r2 ,pother_[system][0],
r2-qnlo,pother_[system][1],G1,G2);
term3 = loMatrixElement(qnlo+r3,pother_[system][0],
r3 ,pother_[system][1],G1,G2);
loME = loMatrixElement(psystem_[system][1],pother_[system][0],
psystem_[system][0],pother_[system][1],G1,G2);
}
else {
term2 = loMatrixElement(r2 ,pother_[system][1],
r2-qnlo,pother_[system][0],G1,G2);
term3 = loMatrixElement(qnlo+r3,pother_[system][1],
r3 ,pother_[system][0],G1,G2);
loME = loMatrixElement(psystem_[system][1],pother_[system][1],
psystem_[system][0],pother_[system][0],G1,G2);
}
}
double R3 = sqr(x3)/(sqr(x3)+sqr(xT))*(term3/loME);
double R2 = sqr(x2)/(sqr(x2)+sqr(xT))*(term2/loME);
// debuggingMatrixElement(true,
// partons_[system][0],partons_[system][1],
// partons_[system][2],partons_[system][3],
// psystem_[system][0],psystem_[system][1],
// pother_ [system][0],pother_ [system][1],
// p0,p1,p2,phiggs_[system],q2_[system],
// 8.*Constants::pi/zp/(1.-zp)*(sqr(xp)*(sqr(x3)+sqr(xT))*R3+
// sqr(xp)*(sqr(x2)+sqr(xT))*R2));
return TRfact*
(sqr(xp)*(sqr(x3)+sqr(xT))*R3+
sqr(xp)*(sqr(x2)+sqr(xT))*R2);
}
Energy4 MEPP2HiggsVBF::loMatrixElement(const Lorentz5Momentum &p1,
const Lorentz5Momentum &p2,
const Lorentz5Momentum &q1,
const Lorentz5Momentum &q2,
double G1, double G2) const {
return G1*(p1*p2)*(q1*q2) + G2*(p1*q2)*(q1*p2);
}
void MEPP2HiggsVBF::initializeMECorrection(RealEmissionProcessPtr born,
double & initial,
double & final) {
systems_.clear();
for(unsigned int ix=0;ix<born->bornIncoming().size();++ix) {
if(QuarkMatcher::Check(born->bornIncoming()[ix]->data())) {
systems_.push_back(tChannelPair());
systems_.back().hadron = born->hadrons()[ix];
systems_.back().beam = dynamic_ptr_cast<tcBeamPtr>(systems_.back().hadron->dataPtr());
systems_.back().incoming = born->bornIncoming()[ix];
systems_.back().pdf = systems_.back().beam->pdf();
}
}
vector<PPtr> outgoing;
for(unsigned int ix=0;ix<born->bornOutgoing().size();++ix) {
if(born->bornOutgoing()[ix]->id()==ParticleID::h0)
higgs_ = born->bornOutgoing()[ix];
else if(QuarkMatcher::Check(born->bornOutgoing()[ix]->data()))
outgoing.push_back(born->bornOutgoing()[ix]);
}
assert(outgoing.size()==2&&higgs_);
// match up the quarks
for(unsigned int ix=0;ix<systems_.size();++ix) {
if(systems_[ix].incoming->colourLine()) {
for(unsigned int iy=0;iy<outgoing.size();++iy) {
if(outgoing[iy]->colourLine()==systems_[ix].incoming->colourLine()) {
systems_[ix].outgoing=outgoing[iy];
break;
}
}
}
else {
for(unsigned int iy=0;iy<outgoing.size();++iy) {
if(outgoing[iy]->antiColourLine()==systems_[ix].incoming->antiColourLine()) {
systems_[ix].outgoing=outgoing[iy];
break;
}
}
}
}
assert(systems_[0].outgoing&&systems_[1].outgoing);
assert(systems_.size()==2);
initial = initial_;
final = final_;
}
RealEmissionProcessPtr MEPP2HiggsVBF::applyHardMatrixElementCorrection(RealEmissionProcessPtr born) {
static const double eps = 1e-6;
// select emitting line
if(UseRandom::rndbool()) swap(systems_[0],systems_[1]);
// extract the born variables
q_[0] = systems_[0].outgoing->momentum()-systems_[0].incoming->momentum();
q2_[0] = -q_[0].m2();
Energy Q = sqrt(q2_[0]);
xB_[0] = systems_[0].incoming->momentum().rho()/systems_[0].hadron->momentum().rho();
// construct lorentz transform from lab to breit frame
Lorentz5Momentum phadron = systems_[0].hadron->momentum();
phadron.setMass(0.*GeV);
phadron.rescaleEnergy();
Lorentz5Momentum pcmf = phadron+0.5/xB_[0]*q_[0];
pcmf.rescaleMass();
LorentzRotation rot(-pcmf.boostVector());
Lorentz5Momentum pbeam = rot*phadron;
Axis axis(pbeam.vect().unit());
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
rot.rotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
Lorentz5Momentum pout = rot*(systems_[1].outgoing->momentum()+higgs_->momentum());
rot.rotateZ(-atan2(pout.y(),pout.x()));
// calculate the A coefficient for the correlations
acoeff_ = A(systems_[0].incoming->dataPtr(),systems_[0].outgoing->dataPtr(),
systems_[1].incoming->dataPtr(),systems_[1].outgoing->dataPtr());
vector<double> azicoeff;
// select the type of process
bool BGF = UseRandom::rnd()>procProb_;
double wgt,xp,zp,x1,x2,x3,xperp;
l_ = 2.*(rot*systems_[1].incoming->momentum())/Q;
m_ = 2.*(rot*systems_[1].outgoing->momentum())/Q;
// compton process
if(!BGF) {
wgt = generateComptonPoint(xp,zp);
if(xp<eps) return RealEmissionProcessPtr();
// common pieces
Energy2 mu2 = q2_[0]*((1.-xp)*(1-zp)*zp/xp+1);
wgt *= 2./3./Constants::pi*alpha_->value(mu2)/procProb_;
// PDF piece
wgt *= systems_[0].pdf->xfx(systems_[0].beam,
systems_[0].incoming->dataPtr(),mu2 ,xB_[0]/xp)/
systems_[0].pdf->xfx(systems_[0].beam,
systems_[0].incoming->dataPtr(),scale(),xB_[0] );
// numerator factors
wgt /= (1.-xp)*(1.-zp);
// other bits
xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp);
x1 = -1./xp;
x2 = 1.-(1.-zp)/xp;
x3 = 2.+x1-x2;
// matrix element pieces
azicoeff = ComptonME(xp,x2,xperp,l_,m_);
}
else {
wgt = generateBGFPoint(xp,zp);
if(xp<1e-6) return RealEmissionProcessPtr();
// common pieces
Energy2 mu2 = q2_[0]*((1.-xp)*(1-zp)*zp/xp+1);
wgt *= 0.25/Constants::pi*alpha_->value(mu2)/(1.-procProb_);
// PDF piece
wgt *= systems_[0].pdf->xfx(systems_[0].beam,
gluon_ ,mu2 ,xB_[0]/xp)/
systems_[0].pdf->xfx(systems_[0].beam,
systems_[0].incoming->dataPtr(),scale(),xB_[0] );
// numerator factors
wgt /= (1.-zp);
// other bits
xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp);
x1 = -1./xp;
x2 = 1.-(1.-zp)/xp;
x3 = 2.+x1-x2;
// matrix element pieces
azicoeff = BGFME(xp,x2,x3,xperp,l_,m_);
}
// compute the azimuthal average of the weight
wgt *= azicoeff[0]+0.5*(azicoeff[2]+azicoeff[4]);
// finally factor as picked one line
wgt *= 2.;
// decide whether or not to accept the weight
if(UseRandom::rnd()>wgt) return RealEmissionProcessPtr();
// if accepted generate generate phi
unsigned int itry(0);
double phimax = std::accumulate(azicoeff.begin(),azicoeff.end(),0.);
double phiwgt,phi;
do {
phi = UseRandom::rnd()*Constants::twopi;
double cphi(cos(phi)),sphi(sin(phi));
phiwgt = azicoeff[0]+azicoeff[5]*sphi*cphi
+azicoeff[1]*cphi+azicoeff[2]*sqr(cphi)
+azicoeff[3]*sphi+azicoeff[4]*sqr(sphi);
++itry;
}
while (phimax*UseRandom::rnd() > phiwgt && itry<200);
if(itry==200) throw Exception() << "Too many tries in VBFMECorrection"
<< "::applyHardMatrixElementCorrection() to"
<< " generate phi" << Exception::eventerror;
// compute the new incoming and outgoing momenta
Lorentz5Momentum p1 = Lorentz5Momentum( 0.5*Q*xperp*cos(phi), 0.5*Q*xperp*sin(phi),
-0.5*Q*x2,0.*GeV,0.*GeV);
p1.rescaleEnergy();
Lorentz5Momentum p2 = Lorentz5Momentum(-0.5*Q*xperp*cos(phi),-0.5*Q*xperp*sin(phi),
-0.5*Q*x3,0.*GeV,0.*GeV);
p2.rescaleEnergy();
Lorentz5Momentum pin(0.*GeV,0.*GeV,-0.5*x1*Q,-0.5*x1*Q,0.*GeV);
// debugging code to test vs helicity amplitude expression for matrix elements
// double cphi(cos(phi)),sphi(sin(phi));
// double old = (azicoeff[0]+azicoeff[5]*sphi*cphi
// +azicoeff[1]*cphi+azicoeff[2]*sqr(cphi)
// +azicoeff[3]*sphi+azicoeff[4]*sqr(sphi));
// if(!BGF) {
// old *= 8.*Constants::pi/(1.-xp)/(1.-zp);
// }
// else {
// old *= 8.*Constants::pi/zp/(1.-zp);
// }
// debuggingMatrixElement(BGF,
// systems_[0].incoming->dataPtr(),
// systems_[0].outgoing->dataPtr(),
// systems_[1].incoming->dataPtr(),
// systems_[1].outgoing->dataPtr(),
// rot*systems_[0].incoming->momentum(),
// rot*systems_[0].outgoing->momentum(),
// rot*systems_[1].incoming->momentum(),
// rot*systems_[1].outgoing->momentum(),
// pin,p1,p2,rot*higgs_->momentum(),
// q2_[0],scale(),old);
// we need inverse of the rotation, i.e back to lab from breit
rot.invert();
// transform the momenta to lab frame
pin *= rot;
p1 *= rot;
p2 *= rot;
// test to ensure outgoing particles can be put on-shell
if(!BGF) {
if(p1.e()<systems_[0].outgoing->dataPtr()->constituentMass()) return RealEmissionProcessPtr();
if(p2.e()<gluon_ ->constituentMass()) return RealEmissionProcessPtr();
}
else {
if(p1.e()<systems_[0].outgoing->dataPtr() ->constituentMass()) return RealEmissionProcessPtr();
if(p2.e()<systems_[0].incoming->dataPtr()->CC()->constituentMass()) return RealEmissionProcessPtr();
}
// stats for weights > 1
if(wgt>1.) {
++nover_;
if(!BGF) maxwgt_.first = max(maxwgt_.first ,wgt);
else maxwgt_.second = max(maxwgt_.second,wgt);
}
// create the new particles and add to ShowerTree
bool isQuark = systems_[0].incoming->colourLine();
bool FSR= false;
PPtr newin,newout,emitted;
if(!BGF) {
newin = systems_[0].incoming->dataPtr()->produceParticle(pin);
emitted = gluon_ ->produceParticle(p2 );
newout = systems_[0].outgoing->dataPtr()->produceParticle(p1 );
emitted->incomingColour(newin,!isQuark);
emitted->colourConnect(newout,!isQuark);
FSR = xp>zp;
}
else {
newin = gluon_ ->produceParticle(pin);
emitted = systems_[0].incoming->dataPtr()->CC()->produceParticle(p2 );
newout = systems_[0].outgoing->dataPtr() ->produceParticle(p1 );
emitted->incomingColour(newin, isQuark);
newout ->incomingColour(newin,!isQuark);
FSR = false;
}
pair<double,double> x;
pair<unsigned int,unsigned int> radiators;
if(born->bornIncoming()[0]!=systems_[0].incoming) {
born->incoming().push_back(born->bornIncoming()[0]);
born->incoming().push_back(newin);
x.first = born->bornIncoming()[0]->momentum().rho()/born->hadrons()[0]->momentum().rho();
x.second = x.first = xB_[0]/xp;
radiators.first = 1;
}
else {
born->incoming().push_back(newin);
born->incoming().push_back(born->bornIncoming()[1]);
x.first = xB_[0]/xp;
x.second = born->bornIncoming()[1]->momentum().rho()/born->hadrons()[1]->momentum().rho();
radiators.first = 0;
}
born->x(x);
for(unsigned int ix=0;ix<born->bornOutgoing().size();++ix) {
if(born->bornOutgoing()[ix]!=systems_[0].outgoing) {
born->outgoing().push_back(born->bornOutgoing()[ix]);
}
else {
radiators.second = born->outgoing().size()+2;
born->outgoing().push_back(newout);
}
}
if(FSR) swap(radiators.first,radiators.second);
born->emitter (radiators.first );
born->spectator(radiators.second);
born->emitted(born->outgoing().size()+2);
// radiated particle
born->outgoing().push_back(emitted);
born->interaction(ShowerInteraction::QCD);
return born;
}
double MEPP2HiggsVBF::A(tcPDPtr qin1, tcPDPtr qout1,
tcPDPtr qin2, tcPDPtr ) {
double output;
// charged current
if(qin1->id()!=qout1->id()) {
output = 2;
}
// neutral current
else {
double cvl,cal,cvq,caq;
if(abs(qin2->id())%2==0) {
cvl = generator()->standardModel()->vu();
cal = generator()->standardModel()->au();
}
else {
cvl = generator()->standardModel()->vd();
cal = generator()->standardModel()->ad();
}
if(abs(qin1->id())%2==0) {
cvq = generator()->standardModel()->vu();
caq = generator()->standardModel()->au();
}
else {
cvq = generator()->standardModel()->vd();
caq = generator()->standardModel()->ad();
}
output = 8.*cvl*cal*cvq*caq/(sqr(cvl)+sqr(cal))/(sqr(cvq)+sqr(caq));
}
if(qin1->id()<0) output *= -1.;
if(qin2->id()<0) output *= -1;
return output;
}
double MEPP2HiggsVBF::generateComptonPoint(double &xp, double & zp) {
static const double maxwgt = 50.;
double wgt,xperp2,x2;
do {
xp = UseRandom::rnd();
double zpmin = xp, zpmax = 1./(1.+xp*(1.-xp));
zp = 1.-pow((1.-zpmin)/(1.-zpmax),UseRandom::rnd())*(1.-zpmax);
wgt = log((1.-zpmin)/(1.-zpmax))*(1.-zp);
if(UseRandom::rndbool()) swap(xp,zp);
xperp2 = 4.*(1.-xp)*(1.-zp)*zp/xp;
x2 = 1.-(1.-zp)/xp;
wgt *= 2.*(1.+sqr(xp)*(sqr(x2)+1.5*xperp2))/(1.-xp)/(1.-zp);
if(wgt>maxwgt)
if(wgt>maxwgt) {
ostringstream wstring;
wstring << "MEPP2HiggsVBF::generateComptonPoint() "
<< "Weight greater than maximum"
<< "wgt = " << wgt << " maxwgt = " << maxwgt << "\n";
generator()->logWarning( Exception(wstring.str(),
Exception::warning) );
}
}
while(wgt<UseRandom::rnd()*maxwgt);
return comptonInt_/((1.+sqr(xp)*(sqr(x2)+1.5*xperp2))/(1.-xp)/(1.-zp));
}
double MEPP2HiggsVBF::generateBGFPoint(double &xp, double & zp) {
static const double maxwgt = 25.;
double wgt;
double x2,x3,xperp2;
do {
xp = UseRandom::rnd();
double zpmax = 1./(1.+xp*(1.-xp)), zpmin = 1.-zpmax;
zp = 1.-pow((1.-zpmin)/(1.-zpmax),UseRandom::rnd())*(1.-zpmax);
wgt = log((1.-zpmin)/(1.-zpmax))*(1.-zp);
double x1 = -1./xp;
x2 = 1.-(1.-zp)/xp;
x3 = 2.+x1-x2;
xperp2 = 4.*(1.-xp)*(1.-zp)*zp/xp;
wgt *= sqr(xp)/(1.-zp)*(sqr(x3)+sqr(x2)+3.*xperp2);
if(wgt>maxwgt) {
ostringstream wstring;
wstring << "DISBase::generateBGFPoint "
<< "Weight greater than maximum "
<< "wgt = " << wgt << " maxwgt = 1\n";
generator()->logWarning( Exception(wstring.str(),
Exception::warning) );
}
}
while(wgt<UseRandom::rnd()*maxwgt);
return bgfInt_/sqr(xp)*(1.-zp)/(sqr(x3)+sqr(x2)+3.*xperp2);
}
bool MEPP2HiggsVBF::softMatrixElementVeto(ShowerProgenitorPtr initial,
ShowerParticlePtr parent,Branching br) {
bool veto = !UseRandom::rndbool(parent->isFinalState() ? 1./final_ : 1./initial_);
// check if me correction should be applied
long id[2]={initial->id(),parent->id()};
if(id[0]!=id[1]||id[1]==ParticleID::g) return veto;
// if not from the right side
if(initial->progenitor()!=systems_[0].incoming &&
initial->progenitor()!=systems_[0].outgoing) return veto;
// get the pT
Energy pT=br.kinematics->pT();
// check if hardest so far
if(pT<initial->highestpT()) return veto;
double kappa(sqr(br.kinematics->scale())/q2_[0]),z(br.kinematics->z());
double zk((1.-z)*kappa);
// final-state
double wgt(0.);
if(parent->isFinalState()) {
double zp=z,xp=1./(1.+z*zk);
double xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp);
double x2 = 1.-(1.-zp)/xp;
vector<double> azicoeff = ComptonME(xp,x2,xperp,l_,m_);
wgt = (azicoeff[0]+0.5*azicoeff[2]+0.5*azicoeff[4])*
xp/(1.+sqr(z))/final_;
if(wgt<.0||wgt>1.) {
ostringstream wstring;
wstring << "Soft ME correction weight too large or "
<< "negative for FSR in MEPP2HiggsVBF::"
<< "softMatrixElementVeto() soft weight "
<< " xp = " << xp << " zp = " << zp
<< " weight = " << wgt << "\n";
generator()->logWarning( Exception(wstring.str(),
Exception::warning) );
}
}
else {
double xp = 2.*z/(1.+zk+sqrt(sqr(1.+zk)-4.*z*zk));
double zp = 0.5* (1.-zk+sqrt(sqr(1.+zk)-4.*z*zk));
double xperp = sqrt(4.*(1.-xp)*(1.-zp)*zp/xp);
double x1 = -1./xp, x2 = 1.-(1.-zp)/xp, x3 = 2.+x1-x2;
// compton
if(br.ids[0]->id()!=ParticleID::g) {
vector<double> azicoeff = ComptonME(xp,x2,xperp,l_,m_);
wgt = (azicoeff[0]+0.5*azicoeff[2]+0.5*azicoeff[4])*
xp*(1.-z)/(1.-xp)/(1.+sqr(z))/(1.-zp+xp-2.*xp*(1.-zp));
}
// BGF
else {
vector<double> azicoeff = BGFME(xp,x2,x3,xperp,l_,m_);
wgt = (azicoeff[0]+0.5*azicoeff[2]+0.5*azicoeff[4])*
xp/(1.-zp+xp-2.*xp*(1.-zp))/(sqr(z)+sqr(1.-z));
}
wgt /=initial_;
if(wgt<.0||wgt>1.) {
ostringstream wstring;
wstring << "Soft ME correction weight too large or "
<< "negative for ISR in MEPP2HiggsVBF::"
<< "softMatrixElementVeto() soft weight "
<< " xp = " << xp << " zp = " << zp
<< " weight = " << wgt << "\n";
generator()->logWarning( Exception(wstring.str(),
Exception::warning) );
}
}
// if not vetoed
if(UseRandom::rndbool(wgt)) return false;
// otherwise
parent->vetoEmission(br.type,br.kinematics->scale());
return true;
}
vector<double> MEPP2HiggsVBF::ComptonME(double xp, double x2, double xperp,
LorentzVector<double> l,
LorentzVector<double> m) {
vector<double> output(6,0.);
double cos2 = x2 /sqrt(sqr(x2)+sqr(xperp));
double sin2 = xperp/sqrt(sqr(x2)+sqr(xperp));
// no phi dependence
output[0] = l.t()*m.t()-l.z()*m.z()*sqr(cos2)+0.5*acoeff_*cos2*(l.t()*m.z()-l.z()*m.t());
// cos(phi)
output[1] = sin2*(-l.x()*m.t()-l.t()*m.x()
+ 0.5*acoeff_*cos2*(l.z()*m.x()-m.z()*l.x()));
// cos(phi)^2
output[2] = +sqr(sin2)*l.x()*m.x();
// sin(phi)
output[3] = sin2*(-l.t()*m.y()-l.y()*m.t()
+ 0.5*acoeff_*cos2*(l.z()*m.y()-m.z()*l.y()));
// sin(phi)^2
output[4] = +sqr(sin2)*l.y()*m.y();
// sin(phi)cos(phi)
output[5] = +sqr(sin2)*(m.y()*l.x()+m.x()*l.y());
// additional factors
double denom = -l.z()*m.z()+l.t()*m.t()+0.5*acoeff_*(l.t()*m.z()-l.z()*m.t());
double fact = sqr(xp)*(sqr(x2)+sqr(xperp))/denom;
for(unsigned int ix=0;ix<output.size();++ix) output[ix] *=fact;
output[0] += 1.;
return output;
}
vector<double> MEPP2HiggsVBF::BGFME(double xp, double x2, double x3,
double xperp,
LorentzVector<double> l,
LorentzVector<double> m) {
vector<double> output(6,0.);
double denom = -l.z()*m.z()+l.t()*m.t()+0.5*acoeff_*(l.t()*m.z()-l.z()*m.t());
double cos2 = x2 /sqrt(sqr(x2)+sqr(xperp));
double sin2 = xperp/sqrt(sqr(x2)+sqr(xperp));
double fact2 = sqr(xp)*(sqr(x2)+sqr(xperp))/denom;
double cos3 = x3 /sqrt(sqr(x3)+sqr(xperp));
double sin3 = xperp/sqrt(sqr(x3)+sqr(xperp));
double fact3 = sqr(xp)*(sqr(x3)+sqr(xperp))/denom;
// no phi dependence
output[0] =
fact2*(l.t()*m.t()-l.z()*m.z()*sqr(cos2)
+ 0.5*acoeff_*cos2*(l.t()*m.z()-l.z()*m.t())) +
fact3*(l.t()*m.t()-l.z()*m.z()*sqr(cos3)
- 0.5*acoeff_*cos3*(l.t()*m.z()-l.z()*m.t()));
// cos(phi)
output[1] =
fact2*sin2*( - l.x()*m.t()-l.t()*m.x()
+ 0.5*acoeff_*cos2*(l.z()*m.x()-m.z()*l.x())) -
fact3*sin3*( - l.x()*m.t()-l.t()*m.x()
- 0.5*acoeff_*cos3*(l.z()*m.x()-m.z()*l.x())) ;
// cos(phi)^2
output[2] = (fact2*sqr(sin2)+fact3*sqr(sin3))*l.x()*m.x();
// sin(phi)
output[3] =
fact2*sin2*( - l.t()*m.y()-l.y()*m.t()
+ 0.5*acoeff_*cos2*(l.z()*m.y()-m.z()*l.y())) -
fact3*sin3*( - l.t()*m.y()-l.y()*m.t()
- 0.5*acoeff_*cos3*(l.z()*m.y()-m.z()*l.y()));
// sin(phi)^2
output[4] = (fact2*sqr(sin2)+fact3*sqr(sin3))*l.y()*m.y();
// sin(phi)cos(phi)
output[5] = (fact2*sqr(sin2)+fact3*sqr(sin3))*(m.y()*l.x()+m.x()*l.y());
// return the answer
return output;
}
diff --git a/MatrixElement/Hadron/MEPP2HiggsVBF.h b/MatrixElement/Hadron/MEPP2HiggsVBF.h
--- a/MatrixElement/Hadron/MEPP2HiggsVBF.h
+++ b/MatrixElement/Hadron/MEPP2HiggsVBF.h
@@ -1,502 +1,502 @@
// -*- C++ -*-
#ifndef HERWIG_MEPP2HiggsVBF_H
#define HERWIG_MEPP2HiggsVBF_H
//
// This is the declaration of the MEPP2HiggsVBF class.
//
#include "Herwig/MatrixElement/MEfftoffH.h"
#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h"
namespace Herwig {
using namespace ThePEG;
/**
* The MEPP2HiggsVBF class provides the matrix elements for the
* production of the Higgs boson via the vector boson fusion mechanism
* in hadron collisions
*
* @see \ref MEPP2HiggsVBFInterfaces "The interfaces"
* defined for MEPP2HiggsVBF.
*/
class MEPP2HiggsVBF: public MEfftoffH {
/**
* Struct to contain the hadronic system
*/
struct tChannelPair{
/**
* The hadron
*/
PPtr hadron;
/**
* The beam particle data object
*/
tcBeamPtr beam;
/**
* The incoming particle
*/
PPtr incoming;
/**
* The outgoing particle
*/
PPtr outgoing;
/**
* The PDF
*/
tcPDFPtr pdf;
};
public:
/**
* The default constructor.
*/
MEPP2HiggsVBF();
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
//@}
/**
* Virtual members to be overridden by inheriting classes
* which implement hard corrections
*/
//@{
/**
* Has a POWHEG style correction
*/
virtual POWHEGType hasPOWHEGCorrection() {return Both;}
/**
* Has an old fashioned ME correction
*/
virtual bool hasMECorrection() {return true;}
/**
* Initialize the ME correction
*/
virtual void initializeMECorrection(RealEmissionProcessPtr, double &,
double & );
/**
* Apply the hard matrix element correction to a given hard process or decay
*/
virtual RealEmissionProcessPtr applyHardMatrixElementCorrection(RealEmissionProcessPtr);
/**
* Apply the soft matrix element correction
* @param initial The particle from the hard process which started the
* shower
* @param parent The initial particle in the current branching
* @param br The branching struct
* @return If true the emission should be vetoed
*/
virtual bool softMatrixElementVeto(ShowerProgenitorPtr,
ShowerParticlePtr,Branching);
/**
* Apply the POWHEG style correction
*/
virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr,
- ShowerInteraction::Type);
+ ShowerInteraction);
//@}
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:
/**
* Generate the hardest emission in the POWHEG approach
*/
//@{
/**
* Generate a Compton process
*/
void generateCompton(unsigned int system);
/**
* Generate a BGF process
*/
void generateBGF(unsigned int system);
/**
* Matrix element piece for the Compton process
*/
double comptonME(unsigned int system,
double xT,double xp, double zp, double phi);
/**
* Matrix element piece for the Compton process
*/
double BGFME(unsigned int system,
double xT,double xp, double zp, double phi);
/**
* Leading order matrix element
*/
Energy4 loMatrixElement(const Lorentz5Momentum &p1,
const Lorentz5Momentum &p2,
const Lorentz5Momentum &q1,
const Lorentz5Momentum &q2,
double G1, double G2) const;
//@}
/**
* Generate the hard emission in the old-fashioned matrix element correction approach
*/
//@{
/**
* Generate the values of \f$x_p\f$ and \f$z_p\f$
* @param xp The value of xp, output
* @param zp The value of zp, output
*/
double generateComptonPoint(double &xp, double & zp);
/**
* Generate the values of \f$x_p\f$ and \f$z_p\f$
* @param xp The value of xp, output
* @param zp The value of zp, output
*/
double generateBGFPoint(double &xp, double & zp);
/**
* Return the coefficients for the matrix element piece for
* the QCD compton case. The output is the \f$a_i\f$ coefficients to
* give the function as
* \f$a_0+a_1\cos\phi+a_2\sin\phi+a_3\cos^2\phi+a_4\sin^2\phi\f$
* @param xp \f$x_p\f$
* @param x2 \f$x_2\f$
* @param xperp \f$x_\perp\f$
* @param l Scaled momentum of incoming spectator
* @param m Scaled momentum of outgoing spectator
*
*/
vector<double> ComptonME(double xp, double x2, double xperp,
LorentzVector<double> l,
LorentzVector<double> m);
/**
* Return the coefficients for the matrix element piece for
* the QCD compton case. The output is the \f$a_i\f$ coefficients to
* give the function as
* \f$a_0+a_1\cos\phi+a_2\sin\phi+a_3\cos^2\phi+a_4\sin^2\phi\f$
* @param xp \f$x_p\f$
* @param x2 \f$x_3\f$
* @param x3 \f$x_2\f$
* @param xperp \f$x_\perp\f$
* @param l Scaled momentum of incoming spectator
* @param m Scaled momentum of outgoing spectator
*
*/
vector<double> BGFME(double xp, double x2, double x3, double xperp,
LorentzVector<double> l,
LorentzVector<double> m);
/**
* Calculate the coefficient A for the correlations
*/
double A(tcPDPtr qin1, tcPDPtr qout1, tcPDPtr qin2, tcPDPtr qout2);
//@}
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();
/**
* Finalize this object. Called in the run phase just after a
* run has ended. Used eg. to write out statistics.
*/
virtual void dofinish();
//@}
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const { return new_ptr(*this); }
/** 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 { return new_ptr(*this); }
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEPP2HiggsVBF> initMEPP2HiggsVBF;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEPP2HiggsVBF & operator=(const MEPP2HiggsVBF &);
private:
/**
* Parameters for the hard POWHEG emission
*/
//@{
/**
* Pointer to the object calculating the strong coupling
*/
ShowerAlphaPtr alpha_;
/**
* Weight for the compton channel
*/
double comptonWeight_;
/**
* Weight for the BGF channel
*/
double BGFWeight_;
/**
* Minimum value of \f$p_T\f$
*/
Energy pTmin_;
/**
* Gluon particle data object
*/
PDPtr gluon_;
//@}
/**
* Properties of the emission
*/
//@{
/**
* Beam particle
*/
tcBeamPtr beam_[2];
/**
* PDF object
*/
tcPDFPtr pdf_[2];
/**
* Partons
*/
tcPDPtr partons_[2][4];
/**
* q
*/
Lorentz5Momentum q_[2];
/**
* \f$Q^2\f$
*/
Energy2 q2_[2];
/**
* Coupling factor
*/
double acoeff_;
/**
* Lorentz vectors for the matrix element
*/
LorentzVector<double> l_;
/**
* Lorentz vectors for the matrix element
*/
LorentzVector<double> m_;
/**
* Born momentum fraction
*/
double xB_[2];
/**
* Rotation to the Breit frame
*/
LorentzRotation rot_[2];
/**
* Quark momenta for spectator system
*/
Lorentz5Momentum pother_[2][2];
/**
* Quark momenta for emitting system
*/
Lorentz5Momentum psystem_[2][2];
/**
* Higgs momenta
*/
Lorentz5Momentum phiggs_[2];
/**
* Transverse momenta for the compton emissions
*/
Energy pTCompton_[2];
/**
* Transverse momenta for the BGF emissions
*/
Energy pTBGF_[2];
/**
* Whether the Compton radiation is ISR or FSR
*/
bool ComptonISFS_[2];
/**
* Momenta of the particles for a compton emission
*/
vector<Lorentz5Momentum> ComptonMomenta_[2];
/**
* Momenta of the particles for a BGF emission
*/
vector<Lorentz5Momentum> BGFMomenta_[2];
/**
* the systems
*/
vector<tChannelPair> systems_;
/**
* Higgs boson
*/
PPtr higgs_;
//@}
/**
* Parameters for the matrix element correction
*/
//@{
/**
* Enchancement factor for ISR
*/
double initial_;
/**
* Enchancement factor for FSR
*/
double final_;
/**
* Relative fraction of compton and BGF processes to generate
*/
double procProb_;
/**
* Integral for compton process
*/
double comptonInt_;
/**
* Integral for BGF process
*/
double bgfInt_;
/**
* Number of weights greater than 1
*/
unsigned int nover_;
/**
* Maximum weight
*/
pair<double,double> maxwgt_;
//@}
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEPP2HiggsVBF. */
template <>
struct BaseClassTrait<Herwig::MEPP2HiggsVBF,1> {
/** Typedef of the first base class of MEPP2HiggsVBF. */
typedef Herwig::MEfftoffH NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEPP2HiggsVBF class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEPP2HiggsVBF>
: public ClassTraitsBase<Herwig::MEPP2HiggsVBF> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEPP2HiggsVBF"; }
/**
* The name of a file containing the dynamic library where the class
* MEPP2HiggsVBF is implemented. It may also include several, space-separated,
* libraries if the class MEPP2HiggsVBF depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMEHadron.so"; }
};
/** @endcond */
}
#endif /* HERWIG_MEPP2HiggsVBF_H */
diff --git a/MatrixElement/HwMEBase.cc b/MatrixElement/HwMEBase.cc
--- a/MatrixElement/HwMEBase.cc
+++ b/MatrixElement/HwMEBase.cc
@@ -1,301 +1,301 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the HwMEBase class.
//
#include "HwMEBase.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "Herwig/PDT/GenericMassGenerator.h"
#include "ThePEG/Cuts/Cuts.h"
#include "Herwig/Shower/QTilde/Base/Branching.h"
#include "Herwig/Shower/RealEmissionProcess.h"
using namespace Herwig;
void HwMEBase::persistentOutput(PersistentOStream & os) const {
os << massOption_ << rescaleOption_;
}
void HwMEBase::persistentInput(PersistentIStream & is, int) {
is >> massOption_ >> rescaleOption_;
}
AbstractClassDescription<HwMEBase> HwMEBase::initHwMEBase;
// Definition of the static class description member.
void HwMEBase::Init() {
static ClassDocumentation<HwMEBase> documentation
("The HwMEBase class is the base class for matrix elements in Herwig"
" and provides the virtual members for hard radiation corrections in the"
" shower.");
}
int HwMEBase::nDim() const {
unsigned ndim = 1;
for(unsigned int ix=0;ix<massOption_.size();++ix)
if(massOption_[ix]==2) ++ndim;
return ndim;
}
CrossSection HwMEBase::dSigHatDR() const {
return me2()*jacobian()/(16.0*sqr(Constants::pi)*sHat())*sqr(hbarc);
}
void HwMEBase::setKinematics() {
MEBase::setKinematics();
lastTHat_ = (meMomenta()[0] - meMomenta()[2]).m2();
lastUHat_ = (meMomenta()[1] - meMomenta()[2]).m2();
lastPhi_ = meMomenta()[2].phi();
}
bool HwMEBase::generateMasses(vector<Energy> & masses, double & mjac,
const double *r) {
assert(massOption_.size()+2==mePartonData().size());
mjac = 1.;
masses.clear();
masses.resize(massOption_.size(),ZERO);
Energy ecm = sqrt(sHat());
Energy emin(ZERO);
int noff(0);
for(unsigned int ix=0;ix<massOption_.size();++ix) {
if(massOption_[ix]==1) {
masses[ix] = mePartonData()[ix+2]->hardProcessMass();
emin += masses[ix];
}
else if (massOption_[ix]==2) {
emin += mePartonData()[ix+2]->massMin();
++noff;
}
}
// check allowed
if(emin>ecm) return false;
// if nothing off-shell return
if(noff==0) return true;
int iloc = nDim()-noff;
emin = ecm - emin;
// generate the masses
for(unsigned int ix=0;ix<massOption_.size();++ix) {
if(massOption_[ix]!=2) continue;
Energy mmin = mePartonData()[ix+2]->massMin();
emin += mmin;
Energy mmax = min(mePartonData()[ix+2]->massMax(),emin);
if(mmin>mmax) return false;
tGenericMassGeneratorPtr gen = mePartonData()[ix+2]->massGenerator() ?
dynamic_ptr_cast<tGenericMassGeneratorPtr>(mePartonData()[ix+2]->massGenerator()) :
tGenericMassGeneratorPtr();
if(gen) {
double jtemp(0.);
masses[ix] = gen->mass(jtemp,*mePartonData()[ix+2],mmin,mmax,r[iloc]);
mjac *= jtemp;
}
else {
Energy mon(mePartonData()[ix+2]->hardProcessMass());
Energy width(mePartonData()[ix+2]->width());
double rhomin = atan2((sqr(mmin)-sqr(mon)), mon*width);
double rhomax = atan2((sqr(mmax)-sqr(mon)), mon*width);
masses[ix] = sqrt(mon*width*tan(rhomin+r[iloc]*(rhomax-rhomin))+sqr(mon));
mjac *= (rhomax-rhomin)/Constants::pi;
}
emin -= masses[ix];
if(emin<ZERO) return false;
++iloc;
}
return true;
}
bool HwMEBase::generateKinematics(const double * r) {
jacobian(1.);
vector<Energy> masses;
double mjac(0.);
if(!generateMasses(masses,mjac,r)) return false;
// set up the momenta
for ( int i = 2, N = meMomenta().size(); i < N; ++i ) {
meMomenta()[i] = Lorentz5Momentum(masses[i-2]);
}
double ctmin = -1.0, ctmax = 1.0;
Energy q = ZERO;
try {
q = SimplePhaseSpace::
getMagnitude(sHat(), meMomenta()[2].mass(), meMomenta()[3].mass());
}
catch ( ImpossibleKinematics ) {
return false;
}
Energy e = sqrt(sHat())/2.0;
Energy2 m22 = meMomenta()[2].mass2();
Energy2 m32 = meMomenta()[3].mass2();
Energy2 e0e2 = 2.0*e*sqrt(sqr(q) + m22);
Energy2 e1e2 = 2.0*e*sqrt(sqr(q) + m22);
Energy2 e0e3 = 2.0*e*sqrt(sqr(q) + m32);
Energy2 e1e3 = 2.0*e*sqrt(sqr(q) + m32);
Energy2 pq = 2.0*e*q;
Energy2 thmin = lastCuts().minTij(mePartonData()[0], mePartonData()[2]);
if ( thmin > ZERO ) ctmax = min(ctmax, (e0e2 - m22 - thmin)/pq);
thmin = lastCuts().minTij(mePartonData()[1], mePartonData()[2]);
if ( thmin > ZERO ) ctmin = max(ctmin, (thmin + m22 - e1e2)/pq);
thmin = lastCuts().minTij(mePartonData()[1], mePartonData()[3]);
if ( thmin > ZERO ) ctmax = min(ctmax, (e1e3 - m32 - thmin)/pq);
thmin = lastCuts().minTij(mePartonData()[0], mePartonData()[3]);
if ( thmin > ZERO ) ctmin = max(ctmin, (thmin + m32 - e0e3)/pq);
Energy ptmin = max(lastCuts().minKT(mePartonData()[2]),
lastCuts().minKT(mePartonData()[3]));
if ( ptmin > ZERO ) {
double ctm = 1.0 - sqr(ptmin/q);
if ( ctm <= 0.0 ) return false;
ctmin = max(ctmin, -sqrt(ctm));
ctmax = min(ctmax, sqrt(ctm));
}
double ymin2 = lastCuts().minYStar(mePartonData()[2]);
double ymax2 = lastCuts().maxYStar(mePartonData()[2]);
double ymin3 = lastCuts().minYStar(mePartonData()[3]);
double ymax3 = lastCuts().maxYStar(mePartonData()[3]);
double ytot = lastCuts().Y() + lastCuts().currentYHat();
if ( ymin2 + ytot > -0.9*Constants::MaxRapidity )
ctmin = max(ctmin, sqrt(sqr(q) + m22)*tanh(ymin2)/q);
if ( ymax2 + ytot < 0.9*Constants::MaxRapidity )
ctmax = min(ctmax, sqrt(sqr(q) + m22)*tanh(ymax2)/q);
if ( ymin3 + ytot > -0.9*Constants::MaxRapidity )
ctmax = min(ctmax, sqrt(sqr(q) + m32)*tanh(-ymin3)/q);
if ( ymax3 + ytot < 0.9*Constants::MaxRapidity )
ctmin = max(ctmin, sqrt(sqr(q) + m32)*tanh(-ymax3)/q);
if ( ctmin >= ctmax ) return false;
double cth = getCosTheta(ctmin, ctmax, r[0]);
Energy pt = q*sqrt(1.0-sqr(cth));
phi(rnd(2.0*Constants::pi));
meMomenta()[2].setVect(Momentum3( pt*sin(phi()), pt*cos(phi()), q*cth));
meMomenta()[3].setVect(Momentum3(-pt*sin(phi()), -pt*cos(phi()), -q*cth));
meMomenta()[2].rescaleEnergy();
meMomenta()[3].rescaleEnergy();
vector<LorentzMomentum> out(2);
out[0] = meMomenta()[2];
out[1] = meMomenta()[3];
tcPDVector tout(2);
tout[0] = mePartonData()[2];
tout[1] = mePartonData()[3];
if ( !lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]) )
return false;
tHat(pq*cth + m22 - e0e2);
uHat(m22 + m32 - sHat() - tHat());
jacobian((pq/sHat())*Constants::pi*jacobian()*mjac);
// compute the rescaled momenta
return rescaleMomenta(meMomenta(),mePartonData());
}
bool HwMEBase::rescaleMomenta(const vector<Lorentz5Momentum> & momenta,
const cPDVector & data) {
assert(momenta.size()==4&&data.size()==4);
// default just use the ones we generated
rescaledMomenta_=momenta;
if(rescaleOption_==1) return true;
Energy mnew[2] = {0*MeV, ZERO};
if(rescaleOption_==0) {
mnew[0] = ZERO;
mnew[1] = ZERO;
}
else if(rescaleOption_==2) {
mnew[0] = data[2]->hardProcessMass();
mnew[1] = data[3]->hardProcessMass();
}
else if(rescaleOption_==3) {
if(abs(data[2]->id())!=abs(data[3]->id())) return true;
mnew[0] = 0.5*(momenta[2].mass()+momenta[3].mass());
mnew[1] = mnew[0];
}
else {
assert(false);
}
Lorentz5Momentum pcm(momenta[2]+momenta[3]);
Energy m0=pcm.m();
if(m0<mnew[0]+mnew[1]) return false;
Boost bv = pcm.boostVector();
rescaledMomenta_[2].boost(bv);
rescaledMomenta_[2].setMass(mnew[0]);
rescaledMomenta_[2].setE(0.5*(sqr(m0)+sqr(mnew[0])-sqr(mnew[1]))/m0);
if(rescaledMomenta_[2].t()-rescaledMomenta_[2].mass()>1e-10*(rescaledMomenta_[2].t()+rescaledMomenta_[2].mass()))
rescaledMomenta_[2].rescaleRho();
else {
rescaledMomenta_[2].setX(ZERO);
rescaledMomenta_[2].setY(ZERO);
rescaledMomenta_[2].setZ(ZERO);
}
rescaledMomenta_[2].boost(-bv);
rescaledMomenta_[3].boost(bv);
rescaledMomenta_[3].setMass(mnew[1]);
rescaledMomenta_[3].setE(0.5*(sqr(m0)-sqr(mnew[0])+sqr(mnew[1]))/m0);
if(rescaledMomenta_[3].t()-rescaledMomenta_[3].mass()>1e-10*(rescaledMomenta_[3].t()+rescaledMomenta_[3].mass()))
rescaledMomenta_[3].rescaleRho();
else {
rescaledMomenta_[3].setX(ZERO);
rescaledMomenta_[3].setY(ZERO);
rescaledMomenta_[3].setZ(ZERO);
}
rescaledMomenta_[3].boost(-bv);
return true;
}
double HwMEBase::getCosTheta(double ctmin, double ctmax, const double r) {
double cth = 0.0;
static const double eps = 1.0e-6;
if ( 1.0 + ctmin <= eps && 1.0 - ctmax <= eps ) {
jacobian(jacobian()*(ctmax - ctmin));
cth = ctmin + r*(ctmax - ctmin);
} else if ( 1.0 + ctmin <= eps ) {
cth = 1.0 - (1.0 - ctmax)*pow((1.0 - ctmin)/(1.0 - ctmax), r);
jacobian(jacobian()*log((1.0 - ctmin)/(1.0 - ctmax))*(1.0 - cth));
} else if ( 1.0 - ctmax <= eps ) {
cth = -1.0 + (1.0 + ctmin)*pow((1.0 + ctmax)/(1.0 + ctmin), r);
jacobian(jacobian()*log((1.0 + ctmax)/(1.0 + ctmin))*(1.0 + cth));
} else {
double zmin = 0.5*(1.0 - ctmax);
double zmax = 0.5*(1.0 - ctmin);
double A1 = -ctmin/(zmax*(1.0-zmax));
double A0 = -ctmax/(zmin*(1.0-zmin));
double A = r*(A1 - A0) + A0;
double z = A < 2.0? 2.0/(sqrt(sqr(A) + 4.0) + 2 - A):
0.5*(A - 2.0 + sqrt(sqr(A) + 4.0))/A;
cth = 1.0 - 2.0*z;
jacobian(jacobian()*2.0*(A1 - A0)*sqr(z)*sqr(1.0 - z)/(sqr(z) + sqr(1.0 - z)));
}
return cth;
}
bool HwMEBase::softMatrixElementVeto(ShowerProgenitorPtr,
ShowerParticlePtr,Branching) {
assert(false);
return false;
}
-RealEmissionProcessPtr HwMEBase::generateHardest(RealEmissionProcessPtr,ShowerInteraction::Type) {
+RealEmissionProcessPtr HwMEBase::generateHardest(RealEmissionProcessPtr,ShowerInteraction) {
assert(false);
return RealEmissionProcessPtr();
}
RealEmissionProcessPtr HwMEBase::applyHardMatrixElementCorrection(RealEmissionProcessPtr) {
assert(false);
return RealEmissionProcessPtr();
}
void HwMEBase::initializeMECorrection(RealEmissionProcessPtr , double & ,
double & ) {
assert(false);
}
diff --git a/MatrixElement/HwMEBase.h b/MatrixElement/HwMEBase.h
--- a/MatrixElement/HwMEBase.h
+++ b/MatrixElement/HwMEBase.h
@@ -1,319 +1,319 @@
// -*- C++ -*-
#ifndef HERWIG_HwMEBase_H
#define HERWIG_HwMEBase_H
//
// This is the declaration of the HwMEBase class.
//
#include "ThePEG/MatrixElement/MEBase.h"
#include "Herwig/Shower/QTilde/Base/ShowerParticle.fh"
#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.fh"
#include "Herwig/Shower/RealEmissionProcess.fh"
#include "Herwig/Shower/QTilde/ShowerInteraction.h"
#include "ThePEG/PDF/BeamParticleData.h"
#include "HwMEBase.fh"
namespace Herwig {
struct Branching;
using namespace ThePEG;
typedef Ptr<BeamParticleData>::transient_const_pointer tcBeamPtr;
/**
* The HwMEBase class serves a number of purposes
* - it implements the phase space for \f$2\to2\f$ scattering processes
* - it provides virtual members for the implementation of hard radiation
* - it gives us greater control over the masses of the outgoing
* particles so that they can be
* - set massless where required by gauge invariance
* - have their off-shell masses generated using the sophisticated approaches
* available in Herwig.
*
* @see \ref HwMEBaseInterfaces "The interfaces"
* defined for HwMEBase.
*/
class HwMEBase: public MEBase {
public:
/**
* Default constructor.
*/
HwMEBase() : lastTHat_(ZERO), lastUHat_(ZERO),
lastPhi_(0.0), rescaleOption_(1)
{}
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* The number of internal degreed of freedom used in the matrix
* element.
*/
virtual int nDim() const;
/**
* Generate internal degrees of freedom given 'nDim()' uniform
* random numbers in the interval ]0,1[. To help the phase space
* generator, the 'dSigHatDR()' should be a smooth function of these
* numbers, although this is not strictly necessary. Return
* false if the chosen points failed the kinematical cuts.
*/
virtual bool generateKinematics(const double * r);
/**
* Return the matrix element for the kinematical configuation
* previously provided by the last call to setKinematics(). Uses
* me().
*/
virtual CrossSection dSigHatDR() const;
/**
* Set the typed and momenta of the incoming and outgoing partons to
* be used in subsequent calls to me() and colourGeometries()
* according to the associated XComb object.
*/
virtual void setKinematics();
//@}
/**
* Virtual members to be overridden by inheriting classes
* which implement hard corrections
*/
//@{
/**
* Type of POWHEG correction
*/
enum POWHEGType {No, ISR, FSR, Both};
/**
* Has a POWHEG style correction
*/
virtual POWHEGType hasPOWHEGCorrection() {return No;}
/**
* Has an old fashioned ME correction
*/
virtual bool hasMECorrection() {return false;}
/**
* Initialize the ME correction
*/
virtual void initializeMECorrection(RealEmissionProcessPtr , double & ,
double & );
/**
* Apply the hard matrix element correction to a given hard process or decay
*/
virtual RealEmissionProcessPtr applyHardMatrixElementCorrection(RealEmissionProcessPtr);
/**
* Apply the soft matrix element correction
* @param initial The particle from the hard process which started the
* shower
* @param parent The initial particle in the current branching
* @param br The branching struct
* @return If true the emission should be vetoed
*/
virtual bool softMatrixElementVeto(ShowerProgenitorPtr initial,
ShowerParticlePtr parent,
Branching br);
/**
* Apply the POWHEG style correction
*/
virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr,
- ShowerInteraction::Type);
+ ShowerInteraction);
//@}
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 Access cached values in of the last set phase space point. */
//@{
/**
* Return the \f$\hat{t}\f$ of the last set phase space point.
*/
Energy2 tHat() const { return lastTHat_; }
/**
* Return the \f$\hat{u}\f$ of the last set phase space point.
*/
Energy2 uHat() const { return lastUHat_; }
/**
* Return the azimuth angle of the last set phase space point.
*/
double phi() const { return lastPhi_; }
//@}
/** @name Set the cached values in of the last set phase space point. */
//@{
/**
* Set the \f$\hat{t}\f$ of the last set phase space point.
*/
void tHat(Energy2 e2) { lastTHat_ = e2; }
/**
* Set the \f$\hat{u}\f$ of the last set phase space point.
*/
void uHat(Energy2 e2) { lastUHat_ = e2; }
/**
* Set the azimuth angle of the last set phase space point.
*/
void phi(double phi) { lastPhi_ = phi; }
//@}
/**
* Set the treatment of the outgoing masses
* @param iopt The option for the treatment of the mass
*/
void massOption(vector<unsigned int> iopt) {
massOption_ = iopt;
}
/**
* Rescaled momenta for the helicity ME
*/
//@{
/**
* Set the treatment of the rescaling of the momenta for
* the matrix element calculation
* @param iopt The rescaling option
*/
void rescalingOption(unsigned int iopt) {
rescaleOption_=iopt;
}
/**
* rescale the momenta for the computation of the helicity matrix element
*/
bool rescaleMomenta(const vector<Lorentz5Momentum> &,
const cPDVector &);
/**
* Access to the rescaled momenta
*/
const vector<Lorentz5Momentum> & rescaledMomenta() const {
return rescaledMomenta_;
}
//@}
/**
* Generate the masses of the particles
*/
bool generateMasses(vector<Energy> & masses, double & mjac,
const double *r);
/**
* Used internally by generateKinematics, after calculating the
* limits on cos(theta).
*/
virtual double getCosTheta(double cthmin, double cthmax, const double r);
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is an abstract class without persistent data.
*/
static AbstractClassDescription<HwMEBase> initHwMEBase;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
HwMEBase & operator=(const HwMEBase &);
private:
/**
* Option for the treatment of the particle masses
*/
vector<unsigned int> massOption_;
/**
* The \f$\hat{t}\f$ of the last set phase space point.
*/
Energy2 lastTHat_;
/**
* The \f$\hat{u}\f$ of the last set phase space point.
*/
Energy2 lastUHat_;
/**
* The azimuth angle of the last set phase space point.
*/
double lastPhi_;
/**
* Produced to produce rescaled momenta
*/
unsigned int rescaleOption_;
/**
* Rescaled momenta for use in ME calculations
*/
vector<Lorentz5Momentum> rescaledMomenta_;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of HwMEBase. */
template <>
struct BaseClassTrait<Herwig::HwMEBase,1> {
/** Typedef of the first base class of HwMEBase. */
typedef MEBase NthBase;
};
/** This template specialization informs ThePEG about the name of
* the HwMEBase class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::HwMEBase>
: public ClassTraitsBase<Herwig::HwMEBase> {
/** Return a platform-independent class name */
static string className() { return "Herwig::HwMEBase"; }
};
/** @endcond */
}
#endif /* HERWIG_HwMEBase_H */
diff --git a/Contrib/LeptonME/MEee2Higgs2SM.cc b/MatrixElement/Lepton/MEee2Higgs2SM.cc
rename from Contrib/LeptonME/MEee2Higgs2SM.cc
rename to MatrixElement/Lepton/MEee2Higgs2SM.cc
diff --git a/Contrib/LeptonME/MEee2Higgs2SM.h b/MatrixElement/Lepton/MEee2Higgs2SM.h
rename from Contrib/LeptonME/MEee2Higgs2SM.h
rename to MatrixElement/Lepton/MEee2Higgs2SM.h
--- a/Contrib/LeptonME/MEee2Higgs2SM.h
+++ b/MatrixElement/Lepton/MEee2Higgs2SM.h
@@ -1,277 +1,277 @@
// -*- C++ -*-
//
// MEee2Higgs2SM.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_MEee2Higgs2SM_H
#define HERWIG_MEee2Higgs2SM_H
//
// This is the declaration of the MEee2Higgs2SM class.
//
#include "ThePEG/MatrixElement/ME2to2Base.h"
#include "Herwig/Models/StandardModel/StandardModel.h"
#include "Herwig/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
namespace Herwig {
using namespace ThePEG;
/**
* The MEee2Higgs2SM class implements the production of an \f$s\f$-channel
* Higgs in \f$e^+e^-\f$ collisions in order to allow easy tests of Higgs
* decays. It should not be used for physics studies.
*
* @see \ref MEee2Higgs2SMInterfaces "The interfaces"
* defined for MEee2Higgs2SM.
*/
class MEee2Higgs2SM: public ME2to2Base {
public:
/**
* The default constructor.
*/
inline MEee2Higgs2SM() : allowed_(0) {}
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* set up the spin correlations
*/
virtual void constructVertex(tSubProPtr sub);
//@}
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.
*/
inline virtual IBPtr clone() const {return new_ptr(*this);}
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const {return new_ptr(*this);}
//@}
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();
/**
* Rebind pointer to other Interfaced objects. Called in the setup phase
* after all objects used in an EventGenerator has been cloned so that
* the pointers will refer to the cloned objects afterwards.
* @param trans a TranslationMap relating the original objects to
* their respective clones.
* @throws RebindException if no cloned object was found for a given
* pointer.
*/
virtual void rebind(const TranslationMap & trans)
;
/**
* Return a vector of all pointers to Interfaced objects used in this
* object.
* @return a vector of pointers.
*/
virtual IVector getReferences();
//@}
private:
/**
* The matrix element
* @param fin The incoming spinor wavefunction
* @param ain The incoming spinorbar wavefunction
* @param fout The outgoing spinor bar wavefunction
* @param aout The outgoing spinor wavefunction
* @param me The spin averaged matrix element
*/
ProductionMatrixElement HelicityME(vector<SpinorWaveFunction> fin,
vector<SpinorBarWaveFunction> ain,
vector<SpinorBarWaveFunction> fout,
vector<SpinorWaveFunction> aout,double& me) const;
/**
* \f$H\to gg\f$ matrix element
* @param fin The incoming spinor wavefunction
* @param ain The incoming spinorbar wavefunction
* @param g1 Outgoing gluon wavefunction
* @param g2 Outgoing gluon wavefunction
* @param me The spin averaged matrix element
*/
ProductionMatrixElement ggME(vector<SpinorWaveFunction> fin,
vector<SpinorBarWaveFunction> ain,
vector<VectorWaveFunction> g1,
vector<VectorWaveFunction> g2,
double & me) const;
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEee2Higgs2SM> initMEee2Higgs2SM;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEee2Higgs2SM & operator=(const MEee2Higgs2SM &);
private:
/**
* Pointer to the Higgs fermion-antifermion vertex
*/
AbstractFFSVertexPtr FFHVertex_;
/**
* Pointer to Higgs-gluon-gluon vertex
*/
AbstractVVSVertexPtr HGGVertex_;
/**
* Allowed outgoing particles
*/
int allowed_;
/**
* Pointer to the Higgs ParticleData object
*/
PDPtr h0_;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEee2Higgs2SM. */
template <>
struct BaseClassTrait<Herwig::MEee2Higgs2SM,1> {
/** Typedef of the first base class of MEee2Higgs2SM. */
typedef ME2to2Base NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEee2Higgs2SM class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEee2Higgs2SM>
: public ClassTraitsBase<Herwig::MEee2Higgs2SM> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEee2Higgs2SM"; }
/**
* The name of a file containing the dynamic library where the class
* MEee2Higgs2SM is implemented. It may also include several, space-separated,
* libraries if the class MEee2Higgs2SM depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
- static string library() { return "LeptonME.so"; }
+ static string library() { return "HwMELepton.so"; }
};
/** @endcond */
}
#endif /* HERWIG_MEee2Higgs2SM_H */
diff --git a/MatrixElement/Lepton/MEee2gZ2ll.cc b/MatrixElement/Lepton/MEee2gZ2ll.cc
--- a/MatrixElement/Lepton/MEee2gZ2ll.cc
+++ b/MatrixElement/Lepton/MEee2gZ2ll.cc
@@ -1,716 +1,716 @@
// -*- C++ -*-
//
// MEee2gZ2ll.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 MEee2gZ2ll class.
//
#include "MEee2gZ2ll.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "Herwig/MatrixElement/HardVertex.h"
#include "ThePEG/PDF/PolarizedBeamParticleData.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include <numeric>
#include "Herwig/Shower/RealEmissionProcess.h"
using namespace Herwig;
void MEee2gZ2ll::getDiagrams() const {
// specific the diagrams
tcPDPtr ep = getParticleData(ParticleID::eplus);
tcPDPtr em = getParticleData(ParticleID::eminus);
// setup the processes
for( int i =11;i<=16;++i) {
if(allowed_==0 || (allowed_==1 && i%2==1) || (allowed_==2&&i==11)
|| (allowed_==3&&i==13) || (allowed_==4&&i==15)) {
tcPDPtr lm = getParticleData(i);
tcPDPtr lp = lm->CC();
add(new_ptr((Tree2toNDiagram(2), em, ep, 1, gamma_, 3, lm, 3, lp, -1)));
add(new_ptr((Tree2toNDiagram(2), em, ep, 1, Z0_, 3, lm, 3, lp, -2)));
}
}
}
Energy2 MEee2gZ2ll::scale() const {
return sHat();
}
unsigned int MEee2gZ2ll::orderInAlphaS() const {
return 0;
}
unsigned int MEee2gZ2ll::orderInAlphaEW() const {
return 2;
}
Selector<MEBase::DiagramIndex>
MEee2gZ2ll::diagrams(const DiagramVector & diags) const {
double lastCont(0.5),lastBW(0.5);
if ( lastXCombPtr() ) {
lastCont = meInfo()[0];
lastBW = meInfo()[1];
}
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i ) {
if ( diags[i]->id() == -1 ) sel.insert(lastCont, i);
else if ( diags[i]->id() == -2 ) sel.insert(lastBW, i);
}
return sel;
}
Selector<const ColourLines *>
MEee2gZ2ll::colourGeometries(tcDiagPtr) const {
static ColourLines ctST(" ");
Selector<const ColourLines *> sel;
sel.insert(1.0, &ctST);
return sel;
}
void MEee2gZ2ll::persistentOutput(PersistentOStream & os) const {
os << allowed_ << FFZVertex_ << FFPVertex_ << gamma_ << Z0_
<< alphaQED_ << ounit(pTmin_,GeV) << preFactor_;
}
void MEee2gZ2ll::persistentInput(PersistentIStream & is, int) {
is >> allowed_ >> FFZVertex_ >> FFPVertex_ >> gamma_ >> Z0_
>> alphaQED_ >> iunit(pTmin_,GeV) >> preFactor_;
}
// *** 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<MEee2gZ2ll,HwMEBase>
describeMEee2gZ2ll("Herwig::MEee2gZ2ll", "HwMELepton.so");
void MEee2gZ2ll::Init() {
static ClassDocumentation<MEee2gZ2ll> documentation
("The MEee2gZ2ll class implements the matrix element for"
"e+e- to leptons via Z and photon exchange using helicity amplitude"
"techniques");
static Switch<MEee2gZ2ll,int> interfaceallowed
("Allowed",
"Allowed outgoing leptons",
&MEee2gZ2ll::allowed_, 0, false, false);
static SwitchOption interfaceallowedAll
(interfaceallowed,
"All",
"Allow all leptons as outgoing particles",
0);
static SwitchOption interfaceallowedCharged
(interfaceallowed,
"Charged",
"Only charged leptons as outgoing particles",
1);
static SwitchOption interfaceallowedElectron
(interfaceallowed,
"Electron",
"Only the electron and positron as outgoing leptons",
2);
static SwitchOption interfaceallowedMuon
(interfaceallowed,
"Muon",
"Only muons as outgoing particles",
3);
static SwitchOption interfaceallowedTau
(interfaceallowed,
"Tau",
"Only taus as outgoing particles",
4);
static Parameter<MEee2gZ2ll,Energy> interfacepTMin
("pTMin",
"Minimum pT for hard radiation",
&MEee2gZ2ll::pTmin_, GeV, 1.0*GeV, 0.001*GeV, 10.0*GeV,
false, false, Interface::limited);
static Parameter<MEee2gZ2ll,double> interfacePrefactor
("Prefactor",
"Prefactor for the overestimate of the emission probability",
&MEee2gZ2ll::preFactor_, 6.0, 1.0, 100.0,
false, false, Interface::limited);
static Reference<MEee2gZ2ll,ShowerAlpha> interfaceEMCoupling
("AlphaQED",
"Pointer to the object to calculate the EM coupling for the correction",
&MEee2gZ2ll::alphaQED_, false, false, true, false, false);
}
double MEee2gZ2ll::me2() const {
return loME(mePartonData(),rescaledMomenta(),true);
}
double MEee2gZ2ll::loME(const vector<cPDPtr> & partons,
const vector<Lorentz5Momentum> & momenta,
bool first) const {
vector<SpinorWaveFunction> fin,aout;
vector<SpinorBarWaveFunction> ain,fout;
SpinorWaveFunction ein (momenta[0],partons[0],incoming);
SpinorBarWaveFunction pin (momenta[1],partons[1],incoming);
SpinorBarWaveFunction ilmout(momenta[2],partons[2],outgoing);
SpinorWaveFunction ilpout(momenta[3],partons[3],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
ein.reset(ix) ;fin.push_back( ein );
pin.reset(ix) ;ain.push_back( pin );
ilmout.reset(ix);fout.push_back(ilmout);
ilpout.reset(ix);aout.push_back(ilpout);
}
// compute the matrix element
double me,lastCont,lastBW;
HelicityME(fin,ain,fout,aout,me,lastCont,lastBW);
// save the components
if(first) {
DVector save;
save.push_back(lastCont);
save.push_back(lastBW);
meInfo(save);
}
// return the answer
return me;
}
ProductionMatrixElement MEee2gZ2ll::HelicityME(vector<SpinorWaveFunction> & fin,
vector<SpinorBarWaveFunction> & ain,
vector<SpinorBarWaveFunction> & fout,
vector<SpinorWaveFunction> & aout,
double & me,double & cont,
double & BW ) const {
// the particles should be in the order
// for the incoming
// 0 incoming fermion (u spinor)
// 1 incoming antifermion (vbar spinor)
// for the outgoing
// 0 outgoing fermion (ubar spinor)
// 1 outgoing antifermion (v spinor)
// me to be returned
ProductionMatrixElement output(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half);
ProductionMatrixElement gamma (PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half);
ProductionMatrixElement Zboson(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half);
// // wavefunctions for the intermediate particles
VectorWaveFunction interZ,interG;
// temporary storage of the different diagrams
Complex diag1,diag2;
// sum over helicities to get the matrix element
unsigned int inhel1,inhel2,outhel1,outhel2;
double total[3]={0.,0.,0.};
for(inhel1=0;inhel1<2;++inhel1) {
for(inhel2=0;inhel2<2;++inhel2) {
// intermediate Z
interZ = FFZVertex_->evaluate(sHat(),1,Z0_,fin[inhel1],ain[inhel2]);
// intermediate photon
interG = FFPVertex_->evaluate(sHat(),1,gamma_,fin[inhel1],ain[inhel2]);
for(outhel1=0;outhel1<2;++outhel1) {
for(outhel2=0;outhel2<2;++outhel2) {
// first the Z exchange diagram
diag1 = FFZVertex_->evaluate(sHat(),aout[outhel2],fout[outhel1],
interZ);
// then the photon exchange diagram
diag2 = FFPVertex_->evaluate(sHat(),aout[outhel2],fout[outhel1],
interG);
// add up squares of individual terms
total[1] += norm(diag1);
Zboson(inhel1,inhel2,outhel1,outhel2) = diag1;
total[2] += norm(diag2);
gamma (inhel1,inhel2,outhel1,outhel2) = diag2;
// the full thing including interference
diag1 += diag2;
total[0] += norm(diag1);
output(inhel1,inhel2,outhel1,outhel2) = diag1;
}
}
}
}
// results
for(int ix=0;ix<3;++ix) total[ix] *= 0.25;
tcPolarizedBeamPDPtr beam[2] =
{dynamic_ptr_cast<tcPolarizedBeamPDPtr>(mePartonData()[0]),
dynamic_ptr_cast<tcPolarizedBeamPDPtr>(mePartonData()[1])};
if( beam[0] || beam[1] ) {
RhoDMatrix rho[2] = {beam[0] ? beam[0]->rhoMatrix() : RhoDMatrix(mePartonData()[0]->iSpin()),
beam[1] ? beam[1]->rhoMatrix() : RhoDMatrix(mePartonData()[1]->iSpin())};
total[0] = output.average(rho[0],rho[1]);
total[1] = Zboson.average(rho[0],rho[1]);
total[2] = gamma .average(rho[0],rho[1]);
}
cont = total[2];
BW = total[1];
me = total[0];
return output;
}
void MEee2gZ2ll::constructVertex(tSubProPtr sub) {
// extract the particles in the hard process
ParticleVector hard;
hard.push_back(sub->incoming().first);hard.push_back(sub->incoming().second);
hard.push_back(sub->outgoing()[0]);hard.push_back(sub->outgoing()[1]);
if(hard[0]->id()<hard[1]->id()) swap(hard[0],hard[1]);
if(hard[2]->id()<hard[3]->id()) swap(hard[2],hard[3]);
vector<SpinorWaveFunction> fin,aout;
vector<SpinorBarWaveFunction> ain,fout;
SpinorWaveFunction( fin ,hard[0],incoming,false,true);
SpinorBarWaveFunction(ain ,hard[1],incoming,false,true);
SpinorBarWaveFunction(fout,hard[2],outgoing,true ,true);
SpinorWaveFunction( aout,hard[3],outgoing,true ,true);
// calculate the matrix element
double me,cont,BW;
ProductionMatrixElement prodme=HelicityME(fin,ain,fout,aout,me,cont,BW);
// construct the vertex
HardVertexPtr hardvertex=new_ptr(HardVertex());
// set the matrix element for the vertex
hardvertex->ME(prodme);
// set the pointers and to and from the vertex
for(unsigned int ix=0;ix<4;++ix) {
tSpinPtr spin = hard[ix]->spinInfo();
if(ix<2) {
tcPolarizedBeamPDPtr beam =
dynamic_ptr_cast<tcPolarizedBeamPDPtr>(hard[ix]->dataPtr());
if(beam) spin->rhoMatrix() = beam->rhoMatrix();
}
spin->productionVertex(hardvertex);
}
}
void MEee2gZ2ll::doinit() {
HwMEBase::doinit();
// set the particle data objects
Z0_=getParticleData(ThePEG::ParticleID::Z0);
gamma_=getParticleData(ThePEG::ParticleID::gamma);
// cast the SM pointer to the Herwig SM pointer
tcHwSMPtr hwsm= dynamic_ptr_cast<tcHwSMPtr>(standardModel());
// do the initialisation
if(!hwsm) throw InitException() << "Wrong type of StandardModel object in "
<< "MEee2gZ2ll::doinit() the Herwig"
<< " version must be used"
<< Exception::runerror;
FFZVertex_ = hwsm->vertexFFZ();
FFPVertex_ = hwsm->vertexFFP();
}
void MEee2gZ2ll::rebind(const TranslationMap & trans) {
FFZVertex_ = trans.translate(FFZVertex_);
FFPVertex_ = trans.translate(FFPVertex_);
Z0_ = trans.translate(Z0_);
gamma_ = trans.translate(gamma_);
HwMEBase::rebind(trans);
}
IVector MEee2gZ2ll::getReferences() {
IVector ret = HwMEBase::getReferences();
ret.push_back(FFZVertex_);
ret.push_back(FFPVertex_);
ret.push_back(Z0_ );
ret.push_back(gamma_ );
return ret;
}
RealEmissionProcessPtr MEee2gZ2ll::generateHardest(RealEmissionProcessPtr born,
- ShowerInteraction::Type inter) {
+ ShowerInteraction inter) {
// check if QED switched on
if(inter==ShowerInteraction::QCD) return RealEmissionProcessPtr();
// generate the momenta for the hard emission
vector<Lorentz5Momentum> emission;
unsigned int iemit,ispect;
Energy pTveto = generateHard(born,emission,iemit,ispect,false);
// check if charged
if(!partons_[2]->charged()) return RealEmissionProcessPtr();
// maximum pT of emission
if(pTveto<=ZERO) {
born->pT()[ShowerInteraction::QED] = pTmin_;
return born;
}
else {
born->pT()[ShowerInteraction::QED] = pTveto;
}
born->interaction(ShowerInteraction::QED);
// get the quark and antiquark
ParticleVector qq;
for(unsigned int ix=0;ix<2;++ix) qq.push_back(born->bornOutgoing()[ix]);
bool order = qq[0]->id()>0;
if(!order) swap(qq[0],qq[1]);
// create the new quark, antiquark and gluon
PPtr newq = qq[0]->dataPtr()->produceParticle(emission[2]);
PPtr newa = qq[1]->dataPtr()->produceParticle(emission[3]);
PPtr newg = gamma_->produceParticle(emission[4]);
// create the output real emission process
for(unsigned int ix=0;ix<born->bornIncoming().size();++ix) {
born->incoming().push_back(born->bornIncoming()[ix]->dataPtr()->
produceParticle(born->bornIncoming()[ix]->momentum()));
}
if(order) {
born->outgoing().push_back(newq);
born->outgoing().push_back(newa);
}
else {
born->outgoing().push_back(newa);
born->outgoing().push_back(newq);
swap(iemit,ispect);
}
born->outgoing().push_back(newg);
// set emitter and spectator
born->emitter (iemit);
born->spectator(ispect);
born->emitted(4);
return born;
}
double MEee2gZ2ll::meRatio(vector<cPDPtr> partons,
vector<Lorentz5Momentum> momenta,
unsigned int iemitter, bool subtract) const {
Lorentz5Momentum q = momenta[2]+momenta[3]+momenta[4];
Energy2 Q2=q.m2();
Energy2 lambda = sqrt((Q2-sqr(momenta[2].mass()+momenta[3].mass()))*
(Q2-sqr(momenta[2].mass()-momenta[3].mass())));
InvEnergy2 D[2];
double lome[2];
for(unsigned int iemit=0;iemit<2;++iemit) {
unsigned int ispect = iemit==0 ? 1 : 0;
Energy2 pipj = momenta[4 ] * momenta[2+iemit ];
Energy2 pipk = momenta[4 ] * momenta[2+ispect];
Energy2 pjpk = momenta[2+iemit] * momenta[2+ispect];
double y = pipj/(pipj+pipk+pjpk);
double z = pipk/( pipk+pjpk);
Energy mij = sqrt(2.*pipj+sqr(momenta[2+iemit].mass()));
Energy2 lamB = sqrt((Q2-sqr(mij+momenta[2+ispect].mass()))*
(Q2-sqr(mij-momenta[2+ispect].mass())));
Energy2 Qpk = q*momenta[2+ispect];
Lorentz5Momentum pkt =
lambda/lamB*(momenta[2+ispect]-Qpk/Q2*q)
+0.5/Q2*(Q2+sqr(momenta[2+ispect].mass())-sqr(momenta[2+ispect].mass()))*q;
Lorentz5Momentum pijt =
q-pkt;
double muj = momenta[2+iemit ].mass()/sqrt(Q2);
double muk = momenta[2+ispect].mass()/sqrt(Q2);
double vt = sqrt((1.-sqr(muj+muk))*(1.-sqr(muj-muk)))/(1.-sqr(muj)-sqr(muk));
double v = sqrt(sqr(2.*sqr(muk)+(1.-sqr(muj)-sqr(muk))*(1.-y))-4.*sqr(muk))
/(1.-y)/(1.-sqr(muj)-sqr(muk));
// dipole term
D[iemit] = 0.5/pipj*(2./(1.-(1.-z)*(1.-y))
-vt/v*(2.-z+sqr(momenta[2+iemit].mass())/pipj));
// matrix element
vector<Lorentz5Momentum> lomom(4);
lomom[0] = momenta[0];
lomom[1] = momenta[1];
if(iemit==0) {
lomom[2] = pijt;
lomom[3] = pkt ;
}
else {
lomom[3] = pijt;
lomom[2] = pkt ;
}
lome[iemit] = loME(partons,lomom,false);
}
InvEnergy2 ratio = realME(partons,momenta)
*abs(D[iemitter])/(abs(D[0]*lome[0])+abs(D[1]*lome[1]));
double output = Q2*ratio;
if(subtract) output -= 2.*Q2*D[iemitter];
return output;
}
InvEnergy2 MEee2gZ2ll::realME(const vector<cPDPtr> & partons,
const vector<Lorentz5Momentum> & momenta) const {
// compute the spinors
vector<SpinorWaveFunction> fin,aout;
vector<SpinorBarWaveFunction> ain,fout;
vector<VectorWaveFunction> gout;
SpinorWaveFunction ein (momenta[0],partons[0],incoming);
SpinorBarWaveFunction pin (momenta[1],partons[1],incoming);
SpinorBarWaveFunction qkout(momenta[2],partons[2],outgoing);
SpinorWaveFunction qbout(momenta[3],partons[3],outgoing);
VectorWaveFunction photon(momenta[4],partons[4],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
ein.reset(ix) ;
fin.push_back( ein );
pin.reset(ix) ;
ain.push_back( pin );
qkout.reset(ix);
fout.push_back(qkout);
qbout.reset(ix);
aout.push_back(qbout);
photon.reset(2*ix);
gout.push_back(photon);
}
vector<Complex> diag(4,0.);
ProductionMatrixElement output(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1);
double total(0.);
for(unsigned int inhel1=0;inhel1<2;++inhel1) {
for(unsigned int inhel2=0;inhel2<2;++inhel2) {
// intermediate Z
VectorWaveFunction interZ =
FFZVertex_->evaluate(scale(),1,Z0_,fin[inhel1],ain[inhel2]);
// intermediate photon
VectorWaveFunction interG =
FFPVertex_->evaluate(scale(),1,gamma_,fin[inhel1],ain[inhel2]);
for(unsigned int outhel1=0;outhel1<2;++outhel1) {
for(unsigned int outhel2=0;outhel2<2;++outhel2) {
for(unsigned int outhel3=0;outhel3<2;++outhel3) {
SpinorBarWaveFunction off1 =
FFPVertex_->evaluate(scale(),3,partons[2],fout[outhel1],gout[outhel3]);
diag[0] = FFZVertex_->evaluate(scale(),aout[outhel2],off1,interZ);
diag[1] = FFPVertex_->evaluate(scale(),aout[outhel2],off1,interG);
SpinorWaveFunction off2 =
FFPVertex_->evaluate(scale(),3,partons[3],aout[outhel2],gout[outhel3]);
diag[2] = FFZVertex_->evaluate(scale(),off2,fout[outhel1],interZ);
diag[3] = FFPVertex_->evaluate(scale(),off2,fout[outhel1],interG);
// sum of diagrams
Complex sum = std::accumulate(diag.begin(),diag.end(),Complex(0.));
// matrix element
output(inhel1,inhel2,outhel1,outhel2,outhel3)=sum;
// me2
total += norm(sum);
}
}
}
}
}
// spin average
total *= 0.25;
tcPolarizedBeamPDPtr beam[2] =
{dynamic_ptr_cast<tcPolarizedBeamPDPtr>(partons[0]),
dynamic_ptr_cast<tcPolarizedBeamPDPtr>(partons[1])};
if( beam[0] || beam[1] ) {
RhoDMatrix rho[2] =
{beam[0] ? beam[0]->rhoMatrix() : RhoDMatrix(mePartonData()[0]->iSpin()),
beam[1] ? beam[1]->rhoMatrix() : RhoDMatrix(mePartonData()[1]->iSpin())};
total = output.average(rho[0],rho[1]);
}
// divide out the coupling and charge
total /= norm(FFPVertex_->norm())*
sqr(double(mePartonData()[2]->iCharge())/3.);
// return the total
return total*UnitRemoval::InvE2;
}
Energy MEee2gZ2ll::generateHard(RealEmissionProcessPtr born,
vector<Lorentz5Momentum> & emmision,
unsigned int & iemit, unsigned int & ispect,
bool applyVeto) {
// get the momenta of the incoming and outgoing particles
// incoming
tPPtr em = born->bornIncoming()[0];
tPPtr ep = born->bornIncoming()[1];
if(em->id()<0) swap(em,ep);
// outgoing
tPPtr qk = born->bornOutgoing()[0];
tPPtr qb = born->bornOutgoing()[1];
if(qk->id()<0) swap(qk,qb);
// extract the momenta
loMomenta_.clear();
loMomenta_.push_back(em->momentum());
loMomenta_.push_back(ep->momentum());
loMomenta_.push_back(qk->momentum());
loMomenta_.push_back(qb->momentum());
// and ParticleData objects
partons_.resize(5);
partons_[0]=em->dataPtr();
partons_[1]=ep->dataPtr();
partons_[2]=qk->dataPtr();
partons_[3]=qb->dataPtr();
partons_[4]=gamma_;
// boost from lab to CMS frame with outgoing particles
// along the z axis
LorentzRotation eventFrame( ( loMomenta_[2] + loMomenta_[3] ).findBoostToCM() );
Lorentz5Momentum spectator = eventFrame*loMomenta_[2];
eventFrame.rotateZ( -spectator.phi() );
eventFrame.rotateY( -spectator.theta() );
eventFrame.invert();
// mass of the final-state system
Energy2 M2 = (loMomenta_[2]+loMomenta_[3]).m2();
Energy M = sqrt(M2);
double mu1 = loMomenta_[2].mass()/M;
double mu2 = loMomenta_[3].mass()/M;
double mu12 = sqr(mu1), mu22 = sqr(mu2);
double lambda = sqrt(1.+sqr(mu12)+sqr(mu22)-2.*mu12-2.*mu22-2.*mu12*mu22);
// max pT
Energy pTmax = 0.5*sqrt(M2)*
(1.-sqr(loMomenta_[2].mass()+loMomenta_[3].mass())/M2);
// max y
double ymax = acosh(pTmax/pTmin_);
double a = alphaQED_->overestimateValue()/Constants::twopi*
2.*ymax*preFactor_*sqr(double(mePartonData()[2]->iCharge())/3.);
// variables for the emission
Energy pT[2];
double y[2],phi[2],x3[2],x1[2][2],x2[2][2];
double contrib[2][2];
// storage of the real emission momenta
vector<Lorentz5Momentum> realMomenta[2][2]=
{{vector<Lorentz5Momentum>(5),vector<Lorentz5Momentum>(5)},
{vector<Lorentz5Momentum>(5),vector<Lorentz5Momentum>(5)}};
for(unsigned int ix=0;ix<2;++ix)
for(unsigned int iy=0;iy<2;++iy)
for(unsigned int iz=0;iz<2;++iz)
realMomenta[ix][iy][iz] = loMomenta_[iz];
// generate the emission
for(unsigned int ix=0;ix<2;++ix) {
if(ix==1) {
swap(mu1 ,mu2 );
swap(mu12,mu22);
}
pT[ix] = pTmax;
y [ix] = 0.;
bool reject = true;
do {
// generate pT
pT[ix] *= pow(UseRandom::rnd(),1./a);
if(pT[ix]<pTmin_) {
pT[ix] = -GeV;
break;
}
// generate y
y[ix] = -ymax+2.*UseRandom::rnd()*ymax;
// generate phi
phi[ix] = UseRandom::rnd()*Constants::twopi;
// calculate x3 and check in allowed region
x3[ix] = 2.*pT[ix]*cosh(y[ix])/M;
if(x3[ix] < 0. || x3[ix] > 1. -sqr( mu1 + mu2 ) ) continue;
// find the possible solutions for x1
double xT2 = sqr(2./M*pT[ix]);
double root = (-sqr(x3[ix])+xT2)*
(xT2*mu22+2.*x3[ix]-sqr(mu12)+2.*mu22+2.*mu12-sqr(x3[ix])-1.
+2.*mu12*mu22-sqr(mu22)-2.*mu22*x3[ix]-2.*mu12*x3[ix]);
double c1=2.*sqr(x3[ix])-4.*mu22-6.*x3[ix]+4.*mu12-xT2*x3[ix]
+2.*xT2-2.*mu12*x3[ix]+2.*mu22*x3[ix]+4.;
if(root<0.) continue;
x1[ix][0] = 1./(4.-4.*x3[ix]+xT2)*(c1-2.*sqrt(root));
x1[ix][1] = 1./(4.-4.*x3[ix]+xT2)*(c1+2.*sqrt(root));
// change sign of y if 2nd particle emits
if(ix==1) y[ix] *=-1.;
// loop over the solutions
for(unsigned int iy=0;iy<2;++iy) {
contrib[ix][iy]=0.;
// check x1 value allowed
if(x1[ix][iy]<2.*mu1||x1[ix][iy]>1.+mu12-mu22) continue;
// calculate x2 value and check allowed
x2[ix][iy] = 2.-x3[ix]-x1[ix][iy];
double root = max(0.,sqr(x1[ix][iy])-4.*mu12);
root = sqrt(root);
double x2min = 1.+mu22-mu12
-0.5*(1.-x1[ix][iy]+mu12-mu22)/(1.-x1[ix][iy]+mu12)*(x1[ix][iy]-2.*mu12+root);
double x2max = 1.+mu22-mu12
-0.5*(1.-x1[ix][iy]+mu12-mu22)/(1.-x1[ix][iy]+mu12)*(x1[ix][iy]-2.*mu12-root);
if(x2[ix][iy]<x2min||x2[ix][iy]>x2max) continue;
// check the z components
double z1 = sqrt(sqr(x1[ix][iy])-4.*mu12-xT2);
double z2 = -sqrt(sqr(x2[ix][iy])-4.*mu22);
double z3 = pT[ix]*sinh(y[ix])*2./M;
if(ix==1) z3 *=-1.;
if(abs(-z1+z2+z3)<1e-9) z1 *= -1.;
if(abs(z1+z2+z3)>1e-5) continue;
// if using as an ME correction the veto
if(applyVeto) {
// double xb = x1[ix][iy], xc = x2[ix][iy];
// double b = mu12, c = mu22;
// double r = 0.5*(1.+b/(1.+c-xc));
// double z1 = r + (xb-(2.-xc)*r)/sqrt(sqr(xc)-4.*c);
// double kt1 = (1.-b+c-xc)/z1/(1.-z1);
// r = 0.5*(1.+c/(1.+b-xb));
// double z2 = r + (xc-(2.-xb)*r)/sqrt(sqr(xb)-4.*b);
// double kt2 = (1.-c+b-xb)/z2/(1.-z2);
// if(ix==1) {
// swap(z1 ,z2);
// swap(kt1,kt2);
// }
// // veto the shower region
// if( kt1 < d_kt1_ || kt2 < d_kt2_ ) continue;
}
// construct the momenta
realMomenta[ix][iy][4] =
Lorentz5Momentum(pT[ix]*cos(phi[ix]),pT[ix]*sin(phi[ix]),
pT[ix]*sinh(y[ix]) ,pT[ix]*cosh(y[ix]),ZERO);
if(ix==0) {
realMomenta[ix][iy][2] =
Lorentz5Momentum(-pT[ix]*cos(phi[ix]),-pT[ix]*sin(phi[ix]),
z1*0.5*M,x1[ix][iy]*0.5*M,M*mu1);
realMomenta[ix][iy][3] =
Lorentz5Momentum(ZERO,ZERO, z2*0.5*M,x2[ix][iy]*0.5*M,M*mu2);
}
else {
realMomenta[ix][iy][2] =
Lorentz5Momentum(ZERO,ZERO,-z2*0.5*M,x2[ix][iy]*0.5*M,M*mu2);
realMomenta[ix][iy][3] =
Lorentz5Momentum(-pT[ix]*cos(phi[ix]),-pT[ix]*sin(phi[ix]),
-z1*0.5*M,x1[ix][iy]*0.5*M,M*mu1);
}
// boost the momenta back to the lab
for(unsigned int iz=2;iz<5;++iz)
realMomenta[ix][iy][iz] *= eventFrame;
// jacobian and prefactors for the weight
Energy J = M/sqrt(xT2)*abs(-x1[ix][iy]*x2[ix][iy]+2.*mu22*x1[ix][iy]
+x2[ix][iy]+x2[ix][iy]*mu12+mu22*x2[ix][iy]
-sqr(x2[ix][iy]))
/pow(sqr(x2[ix][iy])-4.*mu22,1.5);
// prefactors etc
contrib[ix][iy] = 0.5*pT[ix]/J/preFactor_/lambda;
// matrix element piece
contrib[ix][iy] *= meRatio(partons_,realMomenta[ix][iy],ix,false);
// coupling piece
contrib[ix][iy] *= alphaQED_->ratio(sqr(pT[ix]));
}
if(contrib[ix][0]+contrib[ix][1]>1.) {
ostringstream s;
s << "MEee2gZ2qq::generateHardest weight for channel " << ix
<< "is " << contrib[ix][0]+contrib[ix][1]
<< " which is greater than 1";
generator()->logWarning( Exception(s.str(), Exception::warning) );
}
reject = UseRandom::rnd() > contrib[ix][0] + contrib[ix][1];
}
while (reject);
if(pT[ix]<pTmin_)
pT[ix] = -GeV;
}
// now pick the emmision with highest pT
Energy pTemit(ZERO);
// no emission
if(pT[0]<ZERO&&pT[1]<ZERO) return -GeV;
// which one emitted
if(pT[0]>pT[1]) {
iemit = 2;
ispect = 3;
pTemit = pT[0];
if(UseRandom::rnd()<contrib[0][0]/(contrib[0][0]+contrib[0][1]))
emmision = realMomenta[0][0];
else
emmision = realMomenta[0][1];
}
else {
iemit = 3;
ispect = 2;
pTemit = pT[1];
if(UseRandom::rnd()<contrib[1][0]/(contrib[1][0]+contrib[1][1]))
emmision = realMomenta[1][0];
else
emmision = realMomenta[1][1];
}
// return pT of emmision
return pTemit;
}
diff --git a/MatrixElement/Lepton/MEee2gZ2ll.h b/MatrixElement/Lepton/MEee2gZ2ll.h
--- a/MatrixElement/Lepton/MEee2gZ2ll.h
+++ b/MatrixElement/Lepton/MEee2gZ2ll.h
@@ -1,401 +1,401 @@
// -*- C++ -*-
//
// MEee2gZ2ll.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_MEee2gZ2ll_H
#define HERWIG_MEee2gZ2ll_H
//
// This is the declaration of the MEee2gZ2ll class.
//
#include "Herwig/MatrixElement/HwMEBase.h"
#include "Herwig/Models/StandardModel/StandardModel.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "Herwig/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h"
namespace Herwig {
using namespace ThePEG;
/**
* The MEee2gZ2ll class provides the matrix element for
* \f$e^+e^-\to\ell^+\ell^-\f$. N.B. for the production of \f$e^+e^-\f$
* only the \f$s\f$-channel Z and photon diagrams are included.
*
* @see \ref MEee2gZ2llInterfaces "The interfaces"
* defined for MEee2gZ2ll.
*/
class MEee2gZ2ll: public HwMEBase {
public:
/**
* The default constructor.
*/
MEee2gZ2ll() : allowed_(0), pTmin_(GeV),
preFactor_(6.) {
massOption(vector<unsigned int>(2,1));
}
/**
* Members for hard corrections to the emission of QCD radiation
*/
//@{
/**
* Has a POWHEG style correction
*/
virtual POWHEGType hasPOWHEGCorrection() {return FSR;}
/**
* Has an old fashioned ME correction
*/
virtual bool hasMECorrection() {return false;}
/**
* Apply the POWHEG style correction
*/
virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr,
- ShowerInteraction::Type);
+ ShowerInteraction);
//@}
public:
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* Construct the vertex of spin correlations.
*/
virtual void constructVertex(tSubProPtr);
//@}
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 {return new_ptr(*this);}
/** 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 {return new_ptr(*this);}
//@}
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();
/**
* Rebind pointer to other Interfaced objects. Called in the setup phase
* after all objects used in an EventGenerator has been cloned so that
* the pointers will refer to the cloned objects afterwards.
* @param trans a TranslationMap relating the original objects to
* their respective clones.
* @throws RebindException if no cloned object was found for a given
* pointer.
*/
virtual void rebind(const TranslationMap & trans)
;
/**
* Return a vector of all pointers to Interfaced objects used in this
* object.
* @return a vector of pointers.
*/
virtual IVector getReferences();
//@}
protected:
/**
* Calculate the matrix element for \f$e^+e^-\to \ell^+ \ell^-\f$.
* @param partons The incoming and outgoing particles
* @param momenta The momenta of the incoming and outgoing particles
*/
double loME(const vector<cPDPtr> & partons,
const vector<Lorentz5Momentum> & momenta,
bool first) const;
/**
* Member to calculate the matrix element
* @param fin Spinors for incoming fermion
* @param ain Spinors for incoming antifermion
* @param fout Spinors for outgoing fermion
* @param aout Spinors for outgong antifermion
* @param me Spin summed Matrix element
* @param cont The continuum piece of the matrix element
* @param BW The Z piece of the matrix element
*/
ProductionMatrixElement HelicityME(vector<SpinorWaveFunction> & fin,
vector<SpinorBarWaveFunction> & ain,
vector<SpinorBarWaveFunction> & fout,
vector<SpinorWaveFunction> & aout,
double & me,
double & cont,
double & BW ) const;
/**
* The ratio of the matrix element for one additional jet over the
* leading order result. In practice
* \[\frac{\hat{s}|\overline{\mathcal{M}}|^2_2|D_{\rm emit}|}{4\pi C_F\alpha_S|\overline{\mathcal{M}}|^2_3\left(|D_{\rm emit}|+|D_{\rm spect}\right)}}\]
* is returned where \f$\|\overline{\mathcal{M}}|^2\f$ is
* the spin and colour summed/averaged matrix element.
* @param partons The incoming and outgoing particles
* @param momenta The momenta of the incoming and outgoing particles
* @param iemitter Whether the quark or antiquark is regardede as the emitter
* @param inter The type of interaction
*/
double meRatio(vector<cPDPtr> partons,
vector<Lorentz5Momentum> momenta,
unsigned int iemittor,
bool subtract=false) const;
/**
* Calculate the matrix element for \f$e^-e^-\to q \bar q g$.
* @param partons The incoming and outgoing particles
* @param momenta The momenta of the incoming and outgoing particles
* @param inter The type of interaction
*/
InvEnergy2 realME(const vector<cPDPtr> & partons,
const vector<Lorentz5Momentum> & momenta) const;
/**
* Generate the momenta for a hard configuration
*/
Energy generateHard(RealEmissionProcessPtr tree,
vector<Lorentz5Momentum> & emission,
unsigned int & iemit, unsigned int & ispect,
bool applyVeto);
protected:
/**
* Pointer to the fermion-antifermion Z vertex
*/
AbstractFFVVertexPtr FFZVertex() const {return FFZVertex_;}
/**
* Pointer to the fermion-antifermion photon vertex
*/
AbstractFFVVertexPtr FFPVertex() const {return FFPVertex_;}
/**
* Pointer to the particle data object for the Z
*/
PDPtr Z0() const {return Z0_;}
/**
* Pointer to the particle data object for the photon
*/
PDPtr gamma() const {return gamma_;}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEee2gZ2ll & operator=(const MEee2gZ2ll &);
private:
/**
* Pointers to the vertices
*/
//@{
/**
* Pointer to the fermion-antifermion Z vertex
*/
AbstractFFVVertexPtr FFZVertex_;
/**
* Pointer to the fermion-antifermion photon vertex
*/
AbstractFFVVertexPtr FFPVertex_;
//@}
/**
* Pointer to the particle data object for the Z
*/
PDPtr Z0_;
/**
* Pointer to the particle data object for the photon
*/
PDPtr gamma_;
/**
* The allowed outgoing
*/
int allowed_;
/**
* The initial kappa-tilde values for radiation from the quark
*/
double d_kt1_;
/**
* Pointer to the EM coupling
*/
ShowerAlphaPtr alphaQED_;
/**
* Variables for the POWHEG style corrections
*/
//@{
/**
* The cut off on pt, assuming massless quarks.
*/
Energy pTmin_;
/**
* Overestimate for the prefactor
*/
double preFactor_;
/**
* ParticleData objects for the partons
*/
vector<cPDPtr> partons_;
/**
* Momenta of the leading-order partons
*/
vector<Lorentz5Momentum> loMomenta_;
//@}
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEee2gZ2ll. */
template <>
struct BaseClassTrait<Herwig::MEee2gZ2ll,1> {
/** Typedef of the first base class of MEee2gZ2ll. */
typedef Herwig::HwMEBase NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEee2gZ2ll class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEee2gZ2ll>
: public ClassTraitsBase<Herwig::MEee2gZ2ll> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEee2gZ2ll"; }
/**
* The name of a file containing the dynamic library where the class
* MEee2gZ2ll is implemented. It may also include several, space-separated,
* libraries if the class MEee2gZ2ll depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMELepton.so"; }
};
/** @endcond */
}
#endif /* HERWIG_MEee2gZ2ll_H */
diff --git a/MatrixElement/Lepton/MEee2gZ2qq.cc b/MatrixElement/Lepton/MEee2gZ2qq.cc
--- a/MatrixElement/Lepton/MEee2gZ2qq.cc
+++ b/MatrixElement/Lepton/MEee2gZ2qq.cc
@@ -1,987 +1,987 @@
// -*- C++ -*-
//
// MEee2gZ2qq.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 MEee2gZ2qq class.
//
#include "MEee2gZ2qq.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "Herwig/MatrixElement/HardVertex.h"
#include "Herwig/Shower/QTilde/Base/Branching.h"
#include "ThePEG/PDF/PolarizedBeamParticleData.h"
#include <numeric>
#include "ThePEG/Utilities/DescribeClass.h"
#include "Herwig/Shower/RealEmissionProcess.h"
#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h"
#include "Herwig/Shower/QTilde/Base/Branching.h"
using namespace Herwig;
const double MEee2gZ2qq::EPS_=0.00000001;
void MEee2gZ2qq::doinit() {
HwMEBase::doinit();
massOption(vector<unsigned int>(2,massopt_));
rescalingOption(3);
if(minflav_>maxflav_)
throw InitException() << "The minimum flavour " << minflav_
<< "must be lower the than maximum flavour " << maxflav_
<< " in MEee2gZ2qq::doinit() "
<< Exception::runerror;
// set the particle data objects
Z0_ = getParticleData(ParticleID::Z0);
gamma_ = getParticleData(ParticleID::gamma);
gluon_ = getParticleData(ParticleID::g);
// cast the SM pointer to the Herwig SM pointer
tcHwSMPtr hwsm= dynamic_ptr_cast<tcHwSMPtr>(standardModel());
// do the initialisation
if(!hwsm) throw InitException()
<< "Wrong type of StandardModel object in "
<< "MEee2gZ2qq::doinit() the Herwig version must be used"
<< Exception::runerror;
FFZVertex_ = hwsm->vertexFFZ();
FFPVertex_ = hwsm->vertexFFP();
FFGVertex_ = hwsm->vertexFFG();
}
void MEee2gZ2qq::getDiagrams() const {
// specific the diagrams
tcPDPtr ep = getParticleData(ParticleID::eplus);
tcPDPtr em = getParticleData(ParticleID::eminus);
tcPDPtr gamma = getParticleData(ParticleID::gamma);
tcPDPtr Z0 = getParticleData(ParticleID::Z0);
// setup the processes
for ( int i =minflav_; i<=maxflav_; ++i ) {
tcPDPtr qk = getParticleData(i);
tcPDPtr qb = qk->CC();
add(new_ptr((Tree2toNDiagram(2), em, ep, 1, gamma, 3, qk, 3, qb, -1)));
add(new_ptr((Tree2toNDiagram(2), em, ep, 1, Z0 , 3, qk, 3, qb, -2)));
}
}
Energy2 MEee2gZ2qq::scale() const {
return sqr(getParticleData(ParticleID::Z0)->mass());
// return sHat();
}
unsigned int MEee2gZ2qq::orderInAlphaS() const {
return 0;
}
unsigned int MEee2gZ2qq::orderInAlphaEW() const {
return 2;
}
Selector<MEBase::DiagramIndex>
MEee2gZ2qq::diagrams(const DiagramVector & diags) const {
double lastCont(0.5),lastBW(0.5);
if ( lastXCombPtr() ) {
lastCont = meInfo()[0];
lastBW = meInfo()[1];
}
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i ) {
if ( diags[i]->id() == -1 ) sel.insert(lastCont, i);
else if ( diags[i]->id() == -2 ) sel.insert(lastBW, i);
}
return sel;
}
Selector<const ColourLines *>
MEee2gZ2qq::colourGeometries(tcDiagPtr ) const {
static const ColourLines c("-5 4");
Selector<const ColourLines *> sel;
sel.insert(1.0, &c);
return sel;
}
void MEee2gZ2qq::persistentOutput(PersistentOStream & os) const {
os << FFZVertex_ << FFPVertex_ << FFGVertex_
<< Z0_ << gamma_ << gluon_ << minflav_
<< maxflav_ << massopt_ << alphaQCD_ << alphaQED_
<< ounit(pTminQED_,GeV) << ounit(pTminQCD_,GeV) << preFactor_
<< spinCorrelations_;
}
void MEee2gZ2qq::persistentInput(PersistentIStream & is, int) {
is >> FFZVertex_ >> FFPVertex_ >> FFGVertex_
>> Z0_ >> gamma_ >> gluon_ >> minflav_
>> maxflav_ >> massopt_ >> alphaQCD_ >> alphaQED_
>> iunit(pTminQED_,GeV) >> iunit(pTminQCD_,GeV) >> preFactor_
>> spinCorrelations_;
}
// The following static variable is needed for the type
// description system in ThePEG.
DescribeClass<MEee2gZ2qq,HwMEBase>
describeMEee2gZ2qq("Herwig::MEee2gZ2qq", "HwMELepton.so");
void MEee2gZ2qq::Init() {
static ClassDocumentation<MEee2gZ2qq> documentation
("The MEee2gZ2qq class implements the matrix element for e+e- -> q qbar");
static Parameter<MEee2gZ2qq,int> interfaceMinimumFlavour
("MinimumFlavour",
"The PDG code of the quark with the lowest PDG code to produce.",
&MEee2gZ2qq::minflav_, 1, 1, 6,
false, false, Interface::limited);
static Parameter<MEee2gZ2qq,int> interfaceMaximumFlavour
("MaximumFlavour",
"The PDG code of the quark with the highest PDG code to produce",
&MEee2gZ2qq::maxflav_, 5, 1, 6,
false, false, Interface::limited);
static Switch<MEee2gZ2qq,unsigned int> interfaceTopMassOption
("TopMassOption",
"Option for the treatment of the top quark mass",
&MEee2gZ2qq::massopt_, 1, false, false);
static SwitchOption interfaceTopMassOptionOnMassShell
(interfaceTopMassOption,
"OnMassShell",
"The top is produced on its mass shell",
1);
static SwitchOption interfaceTopMassOption2
(interfaceTopMassOption,
"OffShell",
"The top is generated off-shell using the mass and width generator.",
2);
static Parameter<MEee2gZ2qq,Energy> interfacepTMinQED
("pTMinQED",
"Minimum pT for hard QED radiation",
&MEee2gZ2qq::pTminQED_, GeV, 1.0*GeV, 0.001*GeV, 10.0*GeV,
false, false, Interface::limited);
static Parameter<MEee2gZ2qq,Energy> interfacepTMinQCD
("pTMinQCD",
"Minimum pT for hard QCD radiation",
&MEee2gZ2qq::pTminQCD_, GeV, 1.0*GeV, 0.001*GeV, 10.0*GeV,
false, false, Interface::limited);
static Parameter<MEee2gZ2qq,double> interfacePrefactor
("Prefactor",
"Prefactor for the overestimate of the emission probability",
&MEee2gZ2qq::preFactor_, 6.0, 1.0, 100.0,
false, false, Interface::limited);
static Reference<MEee2gZ2qq,ShowerAlpha> interfaceQCDCoupling
("AlphaQCD",
"Pointer to the object to calculate the strong coupling for the correction",
&MEee2gZ2qq::alphaQCD_, false, false, true, false, false);
static Reference<MEee2gZ2qq,ShowerAlpha> interfaceEMCoupling
("AlphaQED",
"Pointer to the object to calculate the EM coupling for the correction",
&MEee2gZ2qq::alphaQED_, false, false, true, false, false);
static Switch<MEee2gZ2qq,bool> interfaceSpinCorrelations
("SpinCorrelations",
"Switch the construction of the veretx for spin correlations on/off",
&MEee2gZ2qq::spinCorrelations_, true, false, false);
static SwitchOption interfaceSpinCorrelationsYes
(interfaceSpinCorrelations,
"Yes",
"Swtich On",
true);
static SwitchOption interfaceSpinCorrelationsNo
(interfaceSpinCorrelations,
"No",
"Switch off",
false);
}
double MEee2gZ2qq::me2() const {
return loME(mePartonData(),rescaledMomenta(),true);
}
ProductionMatrixElement MEee2gZ2qq::HelicityME(vector<SpinorWaveFunction> & fin,
vector<SpinorBarWaveFunction> & ain,
vector<SpinorBarWaveFunction> & fout,
vector<SpinorWaveFunction> & aout,
double & me,
double & cont,
double & BW ) const {
// the particles should be in the order
// for the incoming
// 0 incoming fermion (u spinor)
// 1 incoming antifermion (vbar spinor)
// for the outgoing
// 0 outgoing fermion (ubar spinor)
// 1 outgoing antifermion (v spinor)
// me to be returned
ProductionMatrixElement output(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half);
ProductionMatrixElement gamma (PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half);
ProductionMatrixElement Zboson(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half);
// wavefunctions for the intermediate particles
VectorWaveFunction interZ,interG;
// temporary storage of the different diagrams
Complex diag1,diag2;
// sum over helicities to get the matrix element
unsigned int inhel1,inhel2,outhel1,outhel2;
double total[3]={0.,0.,0.};
for(inhel1=0;inhel1<2;++inhel1) {
for(inhel2=0;inhel2<2;++inhel2) {
// intermediate Z
interZ = FFZVertex_->evaluate(scale(),1,Z0_,fin[inhel1],ain[inhel2]);
// intermediate photon
interG = FFPVertex_->evaluate(scale(),1,gamma_,fin[inhel1],ain[inhel2]);
for(outhel1=0;outhel1<2;++outhel1) {
for(outhel2=0;outhel2<2;++outhel2) {
// first the Z exchange diagram
diag1 = FFZVertex_->evaluate(scale(),aout[outhel2],fout[outhel1],
interZ);
// then the photon exchange diagram
diag2 = FFPVertex_->evaluate(scale(),aout[outhel2],fout[outhel1],
interG);
// add up squares of individual terms
total[1] += norm(diag1);
Zboson(inhel1,inhel2,outhel1,outhel2) = diag1;
total[2] += norm(diag2);
gamma (inhel1,inhel2,outhel1,outhel2) = diag2;
// the full thing including interference
diag1 += diag2;
total[0] += norm(diag1);
output(inhel1,inhel2,outhel1,outhel2)=diag1;
}
}
}
}
for(int ix=0;ix<3;++ix) total[ix] *= 0.25;
tcPolarizedBeamPDPtr beam[2] =
{dynamic_ptr_cast<tcPolarizedBeamPDPtr>(mePartonData()[0]),
dynamic_ptr_cast<tcPolarizedBeamPDPtr>(mePartonData()[1])};
if( beam[0] || beam[1] ) {
RhoDMatrix rho[2] =
{beam[0] ? beam[0]->rhoMatrix() : RhoDMatrix(mePartonData()[0]->iSpin()),
beam[1] ? beam[1]->rhoMatrix() : RhoDMatrix(mePartonData()[1]->iSpin())};
total[0] = output.average(rho[0],rho[1]);
total[1] = Zboson.average(rho[0],rho[1]);
total[2] = gamma .average(rho[0],rho[1]);
}
// results
for(int ix=0;ix<3;++ix) total[ix]*= 3.;
cont = total[2];
BW = total[1];
me = total[0];
return output;
}
void MEee2gZ2qq::constructVertex(tSubProPtr sub) {
if(!spinCorrelations_) return;
// extract the particles in the hard process
ParticleVector hard;
hard.push_back(sub->incoming().first);
hard.push_back(sub->incoming().second);
hard.push_back(sub->outgoing()[0]);
hard.push_back(sub->outgoing()[1]);
if(hard[0]->id()<hard[1]->id()) swap(hard[0],hard[1]);
if(hard[2]->id()<hard[3]->id()) swap(hard[2],hard[3]);
vector<SpinorWaveFunction> fin,aout;
vector<SpinorBarWaveFunction> ain,fout;
// get wave functions for off-shell momenta for later on
SpinorWaveFunction( fin ,hard[0],incoming,false,true);
SpinorBarWaveFunction(ain ,hard[1],incoming,false,true);
SpinorBarWaveFunction(fout,hard[2],outgoing,true ,true);
SpinorWaveFunction( aout,hard[3],outgoing,true ,true);
// now rescale the momenta and compute the matrix element with the
// rescaled momenta for correlations
vector<Lorentz5Momentum> momenta;
cPDVector data;
for(unsigned int ix=0;ix<4;++ix) {
momenta.push_back(hard[ix]->momentum());
data .push_back(hard[ix]->dataPtr());
}
rescaleMomenta(momenta,data);
SpinorWaveFunction ein (rescaledMomenta()[0],data[0],incoming);
SpinorBarWaveFunction pin (rescaledMomenta()[1],data[1],incoming);
SpinorBarWaveFunction qkout(rescaledMomenta()[2],data[2],outgoing);
SpinorWaveFunction qbout(rescaledMomenta()[3],data[3],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
ein.reset(ix) ; fin [ix] = ein ;
pin.reset(ix) ; ain [ix] = pin ;
qkout.reset(ix); fout[ix] = qkout;
qbout.reset(ix); aout[ix] = qbout;
}
// calculate the matrix element
double me,cont,BW;
ProductionMatrixElement prodme=HelicityME(fin,ain,fout,aout,me,cont,BW);
// construct the vertex
HardVertexPtr hardvertex=new_ptr(HardVertex());
// set the matrix element for the vertex
hardvertex->ME(prodme);
// set the pointers and to and from the vertex
for(unsigned int ix=0;ix<4;++ix) {
tSpinPtr spin = hard[ix]->spinInfo();
if(ix<2) {
tcPolarizedBeamPDPtr beam =
dynamic_ptr_cast<tcPolarizedBeamPDPtr>(hard[ix]->dataPtr());
if(beam) spin->rhoMatrix() = beam->rhoMatrix();
}
spin->productionVertex(hardvertex);
}
}
void MEee2gZ2qq::rebind(const TranslationMap & trans) {
FFZVertex_ = trans.translate(FFZVertex_);
FFPVertex_ = trans.translate(FFPVertex_);
FFGVertex_ = trans.translate(FFGVertex_);
Z0_ = trans.translate(Z0_);
gamma_ = trans.translate(gamma_);
gluon_ = trans.translate(gluon_);
HwMEBase::rebind(trans);
}
IVector MEee2gZ2qq::getReferences() {
IVector ret = HwMEBase::getReferences();
ret.push_back(FFZVertex_);
ret.push_back(FFPVertex_);
ret.push_back(FFGVertex_);
ret.push_back(Z0_ );
ret.push_back(gamma_ );
ret.push_back(gluon_ );
return ret;
}
void MEee2gZ2qq::initializeMECorrection(RealEmissionProcessPtr,
double & initial,
double & final) {
d_Q_ = sqrt(sHat());
d_m_ = 0.5*(meMomenta()[2].mass()+meMomenta()[3].mass());
// set the other parameters
d_rho_ = sqr(d_m_/d_Q_);
d_v_ = sqrt(1.-4.*d_rho_);
// maximum evolution scale
d_kt1_ = (1. + sqrt(1. - 4.*d_rho_))/2.;
double num = d_rho_ * d_kt1_ + 0.25 * d_v_ *(1.+d_v_)*(1.+d_v_);
double den = d_kt1_ - d_rho_;
d_kt2_ = num/den;
// maximums for reweighting
initial = 1.;
final = 1.;
}
RealEmissionProcessPtr MEee2gZ2qq::applyHardMatrixElementCorrection(RealEmissionProcessPtr born) {
return calculateRealEmission(born,true,ShowerInteraction::QCD);
}
RealEmissionProcessPtr MEee2gZ2qq::calculateRealEmission(RealEmissionProcessPtr born, bool veto,
- ShowerInteraction::Type inter) {
+ ShowerInteraction inter) {
vector<Lorentz5Momentum> emission;
unsigned int iemit,ispect;
- pair<Energy,ShowerInteraction::Type> output =
+ pair<Energy,ShowerInteraction> output =
generateHard(born,emission,iemit,ispect,veto,inter);
if(emission.empty()) {
if(inter!=ShowerInteraction::QCD) born->pT()[ShowerInteraction::QED] = pTminQED_;
if(inter!=ShowerInteraction::QED) born->pT()[ShowerInteraction::QCD] = pTminQCD_;
return born;
}
else {
Energy pTveto = output.first;
if(inter!=ShowerInteraction::QCD) born->pT()[ShowerInteraction::QED] = pTveto;
if(inter!=ShowerInteraction::QED) born->pT()[ShowerInteraction::QCD] = pTveto;
}
// generate the momenta for the hard emission
- ShowerInteraction::Type force = output.second;
+ ShowerInteraction force = output.second;
born->interaction(force);
// get the quark and antiquark
ParticleVector qq;
for(unsigned int ix=0;ix<2;++ix) qq.push_back(born->bornOutgoing()[ix]);
bool order = qq[0]->id()>0;
if(!order) swap(qq[0],qq[1]);
// perform final check to ensure energy greater than constituent mass
for (int i=0; i<2; i++) {
if (emission[i+2].e() < qq[i]->data().constituentMass())
return RealEmissionProcessPtr();
}
if(force!=ShowerInteraction::QED &&
emission[4].e() < gluon_->constituentMass())
return RealEmissionProcessPtr();
// set masses
for (int i=0; i<2; i++) emission[i+2].setMass(qq[i]->mass());
emission[4].setMass(ZERO);
// create the new quark, antiquark and gluon
PPtr newq = qq[0]->dataPtr()->produceParticle(emission[2]);
PPtr newa = qq[1]->dataPtr()->produceParticle(emission[3]);
PPtr newg;
if(force==ShowerInteraction::QCD)
newg = gluon_->produceParticle(emission[4]);
else
newg = gamma_->produceParticle(emission[4]);
// create the output real emission process
for(unsigned int ix=0;ix<born->bornIncoming().size();++ix) {
born->incoming().push_back(born->bornIncoming()[ix]->dataPtr()->
produceParticle(born->bornIncoming()[ix]->momentum()));
}
if(order) {
born->outgoing().push_back(newq);
born->outgoing().push_back(newa);
}
else {
born->outgoing().push_back(newa);
born->outgoing().push_back(newq);
swap(iemit,ispect);
}
born->outgoing().push_back(newg);
// set emitter and spectator
born->emitter (iemit);
born->spectator(ispect);
born->emitted(4);
// make colour connections
if(force==ShowerInteraction::QCD) {
newg->colourNeighbour(newq);
newa->colourNeighbour(newg);
}
else {
newa->colourNeighbour(newq);
}
return born;
}
bool MEee2gZ2qq::softMatrixElementVeto(ShowerProgenitorPtr initial,
ShowerParticlePtr parent,Branching br) {
// check we should be applying the veto
if(parent->id()!=initial->progenitor()->id()||
br.ids[0]->id()!=br.ids[1]->id()||
br.ids[2]->id()!=ParticleID::g) return false;
// calculate pt
double d_z = br.kinematics->z();
Energy d_qt = br.kinematics->scale();
Energy2 d_m2 = parent->momentum().m2();
Energy pPerp = (1.-d_z)*sqrt( sqr(d_z*d_qt) - d_m2);
// if not hardest so far don't apply veto
if(pPerp<initial->highestpT()) return false;
// calculate x and xb
double kti = sqr(d_qt/d_Q_);
double w = sqr(d_v_) + kti*(-1. + d_z)*d_z*(2. + kti*(-1. + d_z)*d_z);
if (w < 0) return false;
double x = (1. + sqr(d_v_)*(-1. + d_z) + sqr(kti*(-1. + d_z))*d_z*d_z*d_z
+ d_z*sqrt(w)
- kti*(-1. + d_z)*d_z*(2. + d_z*(-2 + sqrt(w))))/
(1. - kti*(-1. + d_z)*d_z + sqrt(w));
double xb = 1. + kti*(-1. + d_z)*d_z;
// calculate the weight
if(parent->id()<0) swap(x,xb);
// if exceptionally out of phase space, leave this emission, as there
// is no good interpretation for the soft ME correction.
if( x<0 || xb<0) return false;
double xg = 2. - xb - x;
// always return one in the soft gluon region
if(xg < EPS_) return false;
// check it is in the phase space
if((1.-x)*(1.-xb)*(1.-xg) < d_rho_*xg*xg) {
parent->vetoEmission(parent->id()>0 ? ShowerPartnerType::QCDColourLine :
ShowerPartnerType::QCDColourLine,br.kinematics->scale());
return true;
}
double k1 = getKfromX(x, xb);
double k2 = getKfromX(xb, x);
double weight = 1.;
// quark emission
if(parent->id() > 0 && k1 < d_kt1_) {
weight = MEV(x, xb)/PS(x, xb);
// is it also in the anti-quark emission zone?
if(k2 < d_kt2_) weight *= 0.5;
}
// antiquark emission
if(parent->id() < 0 && k2 < d_kt2_) {
weight = MEV(x, xb)/PS(xb, x);
// is it also in the quark emission zone?
if(k1 < d_kt1_) weight *= 0.5;
}
// compute veto from weight
bool veto = !UseRandom::rndbool(weight);
// if not vetoed reset max
// if vetoing reset the scale
if(veto) {
parent->vetoEmission(parent->id()>0 ? ShowerPartnerType::QCDColourLine :
ShowerPartnerType::QCDColourLine,br.kinematics->scale());
}
// return the veto
return veto;
}
double MEee2gZ2qq::getKfromX(double x1, double x2) {
double uval = 0.5*(1. + d_rho_/(1.-x2+d_rho_));
double num = x1 - (2. - x2)*uval;
double den = sqrt(x2*x2 - 4.*d_rho_);
double zval = uval + num/den;
return (1.-x2)/(zval*(1.-zval));
}
double MEee2gZ2qq::MEV(double x1, double x2) {
// Vector part
double num = (x1+2.*d_rho_)*(x1+2.*d_rho_) + (x2+2.*d_rho_)*(x2+2.*d_rho_)
- 8.*d_rho_*(1.+2.*d_rho_);
double den = (1.+2.*d_rho_)*(1.-x1)*(1.-x2);
return (num/den - 2.*d_rho_/((1.-x1)*(1.-x1))
- 2*d_rho_/((1.-x2)*(1.-x2)))/d_v_;
}
double MEee2gZ2qq::PS(double x, double xbar) {
double u = 0.5*(1. + d_rho_ / (1.-xbar+d_rho_));
double z = u + (x - (2.-xbar)*u)/sqrt(xbar*xbar - 4.*d_rho_);
double brack = (1.+z*z)/(1.-z)- 2.*d_rho_/(1-xbar);
// interesting: the splitting function without the subtraction
// term. Actually gives a much worse approximation in the collinear
// limit. double brack = (1.+z*z)/(1.-z);
double den = (1.-xbar)*sqrt(xbar*xbar - 4.*d_rho_);
return brack/den;
}
-pair<Energy,ShowerInteraction::Type>
+pair<Energy,ShowerInteraction>
MEee2gZ2qq::generateHard(RealEmissionProcessPtr born,
vector<Lorentz5Momentum> & emmision,
unsigned int & iemit, unsigned int & ispect,
- bool applyVeto,ShowerInteraction::Type inter) {
- vector<ShowerInteraction::Type> interactions;
+ bool applyVeto,ShowerInteraction inter) {
+ vector<ShowerInteraction> interactions;
if(inter==ShowerInteraction::Both) {
interactions.push_back(ShowerInteraction::QED);
interactions.push_back(ShowerInteraction::QCD);
}
else
interactions.push_back(inter);
// incoming particles
tPPtr em = born->bornIncoming()[0];
tPPtr ep = born->bornIncoming()[1];
if(em->id()<0) swap(em,ep);
// outgoing particles
tPPtr qk = born->bornOutgoing()[0];
tPPtr qb = born->bornOutgoing()[1];
if(qk->id()<0) swap(qk,qb);
// extract the momenta
loMomenta_.clear();
loMomenta_.push_back(em->momentum());
loMomenta_.push_back(ep->momentum());
loMomenta_.push_back(qk->momentum());
loMomenta_.push_back(qb->momentum());
// and ParticleData objects
partons_.resize(5);
partons_[0]=em->dataPtr();
partons_[1]=ep->dataPtr();
partons_[2]=qk->dataPtr();
partons_[3]=qb->dataPtr();
partons_[4]=cPDPtr();
// boost from lab to CMS frame with outgoing particles
// along the z axis
LorentzRotation eventFrame( ( loMomenta_[2] + loMomenta_[3] ).findBoostToCM() );
Lorentz5Momentum spectator = eventFrame*loMomenta_[2];
eventFrame.rotateZ( -spectator.phi() );
eventFrame.rotateY( -spectator.theta() );
eventFrame.invert();
// mass of the final-state system
Energy2 M2 = (loMomenta_[2]+loMomenta_[3]).m2();
Energy M = sqrt(M2);
double mu1 = loMomenta_[2].mass()/M;
double mu2 = loMomenta_[3].mass()/M;
double mu12 = sqr(mu1), mu22 = sqr(mu2);
double lambda = sqrt(1.+sqr(mu12)+sqr(mu22)-2.*mu12-2.*mu22-2.*mu12*mu22);
// max pT
Energy pTmax = 0.5*sqrt(M2)*
(1.-sqr(loMomenta_[2].mass()+loMomenta_[3].mass())/M2);
// max y
if ( pTmax < pTminQED_ && pTmax < pTminQCD_ ) return make_pair(ZERO,ShowerInteraction::QCD);
vector<Energy> pTemit;
vector<vector<Lorentz5Momentum> > emittedMomenta;;
vector<unsigned int> iemitter,ispectator;
for(unsigned int iinter=0;iinter<interactions.size();++iinter) {
Energy pTmin(ZERO);
double a,ymax;
if(interactions[iinter]==ShowerInteraction::QCD) {
pTmin = pTminQCD_;
ymax = acosh(pTmax/pTmin);
partons_[4] = gluon_;
// prefactor for the overestimate of the Sudakov
a = 4./3.*alphaQCD_->overestimateValue()/Constants::twopi*
2.*ymax*preFactor_;
}
else {
pTmin = pTminQED_;
ymax = acosh(pTmax/pTmin);
partons_[4] = gamma_;
a = alphaQED_->overestimateValue()/Constants::twopi*
2.*ymax*preFactor_*sqr(double(mePartonData()[2]->iCharge())/3.);
}
// variables for the emission
Energy pT[2];
double y[2],phi[2],x3[2],x1[2][2],x2[2][2];
double contrib[2][2];
// storage of the real emission momenta
vector<Lorentz5Momentum> realMomenta[2][2]=
{{vector<Lorentz5Momentum>(5),vector<Lorentz5Momentum>(5)},
{vector<Lorentz5Momentum>(5),vector<Lorentz5Momentum>(5)}};
for(unsigned int ix=0;ix<2;++ix)
for(unsigned int iy=0;iy<2;++iy)
for(unsigned int iz=0;iz<2;++iz)
realMomenta[ix][iy][iz] = loMomenta_[iz];
// generate the emission
for(unsigned int ix=0;ix<2;++ix) {
if(ix==1) {
swap(mu1 ,mu2 );
swap(mu12,mu22);
}
pT[ix] = pTmax;
y [ix] = 0.;
bool reject = true;
do {
// generate pT
pT[ix] *= pow(UseRandom::rnd(),1./a);
if(pT[ix]<pTmin) {
pT[ix] = -GeV;
break;
}
// generate y
y[ix] = -ymax+2.*UseRandom::rnd()*ymax;
// generate phi
phi[ix] = UseRandom::rnd()*Constants::twopi;
// calculate x3 and check in allowed region
x3[ix] = 2.*pT[ix]*cosh(y[ix])/M;
if(x3[ix] < 0. || x3[ix] > 1. -sqr( mu1 + mu2 ) ) continue;
// find the possible solutions for x1
double xT2 = sqr(2./M*pT[ix]);
double root = (-sqr(x3[ix])+xT2)*
(xT2*mu22+2.*x3[ix]-sqr(mu12)+2.*mu22+2.*mu12-sqr(x3[ix])-1.
+2.*mu12*mu22-sqr(mu22)-2.*mu22*x3[ix]-2.*mu12*x3[ix]);
double c1=2.*sqr(x3[ix])-4.*mu22-6.*x3[ix]+4.*mu12-xT2*x3[ix]
+2.*xT2-2.*mu12*x3[ix]+2.*mu22*x3[ix]+4.;
if(root<0.) continue;
x1[ix][0] = 1./(4.-4.*x3[ix]+xT2)*(c1-2.*sqrt(root));
x1[ix][1] = 1./(4.-4.*x3[ix]+xT2)*(c1+2.*sqrt(root));
// change sign of y if 2nd particle emits
if(ix==1) y[ix] *=-1.;
// loop over the solutions
for(unsigned int iy=0;iy<2;++iy) {
contrib[ix][iy]=0.;
// check x1 value allowed
if(x1[ix][iy]<2.*mu1||x1[ix][iy]>1.+mu12-mu22) continue;
// calculate x2 value and check allowed
x2[ix][iy] = 2.-x3[ix]-x1[ix][iy];
double root = max(0.,sqr(x1[ix][iy])-4.*mu12);
root = sqrt(root);
double x2min = 1.+mu22-mu12
-0.5*(1.-x1[ix][iy]+mu12-mu22)/(1.-x1[ix][iy]+mu12)*(x1[ix][iy]-2.*mu12+root);
double x2max = 1.+mu22-mu12
-0.5*(1.-x1[ix][iy]+mu12-mu22)/(1.-x1[ix][iy]+mu12)*(x1[ix][iy]-2.*mu12-root);
if(x2[ix][iy]<x2min||x2[ix][iy]>x2max) continue;
// check the z components
double z1 = sqrt(sqr(x1[ix][iy])-4.*mu12-xT2);
double z2 = -sqrt(sqr(x2[ix][iy])-4.*mu22);
double z3 = pT[ix]*sinh(y[ix])*2./M;
if(ix==1) z3 *=-1.;
if(abs(-z1+z2+z3)<1e-9) z1 *= -1.;
if(abs(z1+z2+z3)>1e-5) continue;
// if using as an ME correction the veto
if(applyVeto) {
double xb = x1[ix][iy], xc = x2[ix][iy];
double b = mu12, c = mu22;
double r = 0.5*(1.+b/(1.+c-xc));
double z1 = r + (xb-(2.-xc)*r)/sqrt(sqr(xc)-4.*c);
double kt1 = (1.-b+c-xc)/z1/(1.-z1);
r = 0.5*(1.+c/(1.+b-xb));
double z2 = r + (xc-(2.-xb)*r)/sqrt(sqr(xb)-4.*b);
double kt2 = (1.-c+b-xb)/z2/(1.-z2);
if(ix==1) {
swap(z1 ,z2);
swap(kt1,kt2);
}
// veto the shower region
if( kt1 < d_kt1_ || kt2 < d_kt2_ ) continue;
}
// construct the momenta
realMomenta[ix][iy][4] =
Lorentz5Momentum(pT[ix]*cos(phi[ix]),pT[ix]*sin(phi[ix]),
pT[ix]*sinh(y[ix]) ,pT[ix]*cosh(y[ix]),ZERO);
if(ix==0) {
realMomenta[ix][iy][2] =
Lorentz5Momentum(-pT[ix]*cos(phi[ix]),-pT[ix]*sin(phi[ix]),
z1*0.5*M,x1[ix][iy]*0.5*M,M*mu1);
realMomenta[ix][iy][3] =
Lorentz5Momentum(ZERO,ZERO, z2*0.5*M,x2[ix][iy]*0.5*M,M*mu2);
}
else {
realMomenta[ix][iy][2] =
Lorentz5Momentum(ZERO,ZERO,-z2*0.5*M,x2[ix][iy]*0.5*M,M*mu2);
realMomenta[ix][iy][3] =
Lorentz5Momentum(-pT[ix]*cos(phi[ix]),-pT[ix]*sin(phi[ix]),
-z1*0.5*M,x1[ix][iy]*0.5*M,M*mu1);
}
// boost the momenta back to the lab
for(unsigned int iz=2;iz<5;++iz)
realMomenta[ix][iy][iz] *= eventFrame;
// jacobian and prefactors for the weight
Energy J = M/sqrt(xT2)*abs(-x1[ix][iy]*x2[ix][iy]+2.*mu22*x1[ix][iy]
+x2[ix][iy]+x2[ix][iy]*mu12+mu22*x2[ix][iy]
-sqr(x2[ix][iy]))
/pow(sqr(x2[ix][iy])-4.*mu22,1.5);
// prefactors etc
contrib[ix][iy] = 0.5*pT[ix]/J/preFactor_/lambda;
// matrix element piece
contrib[ix][iy] *= meRatio(partons_,realMomenta[ix][iy],
ix,interactions[iinter],false);
// coupling piece
if(interactions[iinter]==ShowerInteraction::QCD)
contrib[ix][iy] *= alphaQCD_->ratio(sqr(pT[ix]));
else
contrib[ix][iy] *= alphaQED_->ratio(sqr(pT[ix]));
}
if(contrib[ix][0]+contrib[ix][1]>1.) {
ostringstream s;
s << "MEee2gZ2qq::generateHardest weight for channel " << ix
<< "is " << contrib[ix][0]+contrib[ix][1]
<< " which is greater than 1";
generator()->logWarning( Exception(s.str(), Exception::warning) );
}
reject = UseRandom::rnd() > contrib[ix][0] + contrib[ix][1];
}
while (reject);
if(pT[ix]<pTmin)
pT[ix] = -GeV;
}
// pt of emission
if(pT[0]<ZERO && pT[1]<ZERO) {
pTemit.push_back(-GeV);
emittedMomenta.push_back(vector<Lorentz5Momentum>());
iemitter .push_back(0);
ispectator.push_back(0);
continue;
}
// now pick the emission with highest pT
vector<Lorentz5Momentum> emission;
if(pT[0]>pT[1]) {
iemitter .push_back(2);
ispectator.push_back(3);
pTemit.push_back(pT[0]);
if(UseRandom::rnd()<contrib[0][0]/(contrib[0][0]+contrib[0][1]))
emission = realMomenta[0][0];
else
emission = realMomenta[0][1];
}
else {
iemitter .push_back(3);
ispectator.push_back(2);
pTemit.push_back(pT[1]);
if(UseRandom::rnd()<contrib[1][0]/(contrib[1][0]+contrib[1][1]))
emission = realMomenta[1][0];
else
emission = realMomenta[1][1];
}
emittedMomenta.push_back(emission);
}
// select the type of emission
int iselect=-1;
pTmax = ZERO;
for(unsigned int ix=0;ix<interactions.size();++ix) {
if(pTemit[ix]>pTmax) {
iselect = ix;
pTmax = pTemit[ix];
}
}
// no emission return
if(iselect<0) {
return make_pair(ZERO,ShowerInteraction::QCD);
}
partons_[4] = interactions[iselect]==ShowerInteraction::QCD ? gluon_ : gamma_;
iemit = iemitter[iselect];
ispect = ispectator[iselect];
emmision = emittedMomenta[iselect];
// return pT of emission
return make_pair(pTmax,interactions[iselect]);
}
RealEmissionProcessPtr MEee2gZ2qq::generateHardest(RealEmissionProcessPtr born,
- ShowerInteraction::Type inter) {
+ ShowerInteraction inter) {
return calculateRealEmission(born,false,inter);
}
double MEee2gZ2qq::meRatio(vector<cPDPtr> partons,
vector<Lorentz5Momentum> momenta,
unsigned int iemitter,
- ShowerInteraction::Type inter,
+ ShowerInteraction inter,
bool subtract) const {
Lorentz5Momentum q = momenta[2]+momenta[3]+momenta[4];
Energy2 Q2=q.m2();
Energy2 lambda = sqrt((Q2-sqr(momenta[2].mass()+momenta[3].mass()))*
(Q2-sqr(momenta[2].mass()-momenta[3].mass())));
InvEnergy2 D[2];
double lome[2];
for(unsigned int iemit=0;iemit<2;++iemit) {
unsigned int ispect = iemit==0 ? 1 : 0;
Energy2 pipj = momenta[4 ] * momenta[2+iemit ];
Energy2 pipk = momenta[4 ] * momenta[2+ispect];
Energy2 pjpk = momenta[2+iemit] * momenta[2+ispect];
double y = pipj/(pipj+pipk+pjpk);
double z = pipk/( pipk+pjpk);
Energy mij = sqrt(2.*pipj+sqr(momenta[2+iemit].mass()));
Energy2 lamB = sqrt((Q2-sqr(mij+momenta[2+ispect].mass()))*
(Q2-sqr(mij-momenta[2+ispect].mass())));
Energy2 Qpk = q*momenta[2+ispect];
Lorentz5Momentum pkt =
lambda/lamB*(momenta[2+ispect]-Qpk/Q2*q)
+0.5/Q2*(Q2+sqr(momenta[2+ispect].mass())-sqr(momenta[2+ispect].mass()))*q;
Lorentz5Momentum pijt =
q-pkt;
double muj = momenta[2+iemit ].mass()/sqrt(Q2);
double muk = momenta[2+ispect].mass()/sqrt(Q2);
double vt = sqrt((1.-sqr(muj+muk))*(1.-sqr(muj-muk)))/(1.-sqr(muj)-sqr(muk));
double v = sqr(2.*sqr(muk)+(1.-sqr(muj)-sqr(muk))*(1.-y))-4.*sqr(muk);
if(v<=0.) return 0.;
v = sqrt(v)/(1.-y)/(1.-sqr(muj)-sqr(muk));
// dipole term
D[iemit] = 0.5/pipj*(2./(1.-(1.-z)*(1.-y))
-vt/v*(2.-z+sqr(momenta[2+iemit].mass())/pipj));
// matrix element
vector<Lorentz5Momentum> lomom(4);
lomom[0] = momenta[0];
lomom[1] = momenta[1];
if(iemit==0) {
lomom[2] = pijt;
lomom[3] = pkt ;
}
else {
lomom[3] = pijt;
lomom[2] = pkt ;
}
lome[iemit] = loME(partons,lomom,false)/3.;
}
InvEnergy2 ratio = realME(partons,momenta,inter)
*abs(D[iemitter])/(abs(D[0]*lome[0])+abs(D[1]*lome[1]));
double output = Q2*ratio;
if(subtract) output -= 2.*Q2*D[iemitter];
return output;
}
double MEee2gZ2qq::loME(const vector<cPDPtr> & partons,
const vector<Lorentz5Momentum> & momenta,
bool first) const {
// compute the spinors
vector<SpinorWaveFunction> fin,aout;
vector<SpinorBarWaveFunction> ain,fout;
SpinorWaveFunction ein (momenta[0],partons[0],incoming);
SpinorBarWaveFunction pin (momenta[1],partons[1],incoming);
SpinorBarWaveFunction qkout(momenta[2],partons[2],outgoing);
SpinorWaveFunction qbout(momenta[3],partons[3],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
ein.reset(ix) ;
fin.push_back( ein );
pin.reset(ix) ;
ain.push_back( pin );
qkout.reset(ix);
fout.push_back(qkout);
qbout.reset(ix);
aout.push_back(qbout);
}
// compute the matrix element
double me,lastCont,lastBW;
HelicityME(fin,ain,fout,aout,me,lastCont,lastBW);
// save the components
if(first) {
DVector save;
save.push_back(lastCont);
save.push_back(lastBW);
meInfo(save);
}
// return the answer
return me;
}
InvEnergy2 MEee2gZ2qq::realME(const vector<cPDPtr> & partons,
const vector<Lorentz5Momentum> & momenta,
- ShowerInteraction::Type inter) const {
+ ShowerInteraction inter) const {
// compute the spinors
vector<SpinorWaveFunction> fin,aout;
vector<SpinorBarWaveFunction> ain,fout;
vector<VectorWaveFunction> gout;
SpinorWaveFunction ein (momenta[0],partons[0],incoming);
SpinorBarWaveFunction pin (momenta[1],partons[1],incoming);
SpinorBarWaveFunction qkout(momenta[2],partons[2],outgoing);
SpinorWaveFunction qbout(momenta[3],partons[3],outgoing);
VectorWaveFunction gluon(momenta[4],partons[4],outgoing);
for(unsigned int ix=0;ix<2;++ix) {
ein.reset(ix) ;
fin.push_back( ein );
pin.reset(ix) ;
ain.push_back( pin );
qkout.reset(ix);
fout.push_back(qkout);
qbout.reset(ix);
aout.push_back(qbout);
gluon.reset(2*ix);
gout.push_back(gluon);
}
AbstractFFVVertexPtr vertex = inter == ShowerInteraction::QCD ?
FFGVertex_ : FFPVertex_;
vector<Complex> diag(4,0.);
ProductionMatrixElement output(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1);
double total(0.);
for(unsigned int inhel1=0;inhel1<2;++inhel1) {
for(unsigned int inhel2=0;inhel2<2;++inhel2) {
// intermediate Z
VectorWaveFunction interZ =
FFZVertex_->evaluate(scale(),1,Z0_,fin[inhel1],ain[inhel2]);
// intermediate photon
VectorWaveFunction interG =
FFPVertex_->evaluate(scale(),1,gamma_,fin[inhel1],ain[inhel2]);
for(unsigned int outhel1=0;outhel1<2;++outhel1) {
for(unsigned int outhel2=0;outhel2<2;++outhel2) {
for(unsigned int outhel3=0;outhel3<2;++outhel3) {
SpinorBarWaveFunction off1 =
vertex->evaluate(scale(),3,partons[2],fout[outhel1],gout[outhel3]);
diag[0] = FFZVertex_->evaluate(scale(),aout[outhel2],off1,interZ);
diag[1] = FFPVertex_->evaluate(scale(),aout[outhel2],off1,interG);
SpinorWaveFunction off2 =
vertex->evaluate(scale(),3,partons[3],aout[outhel2],gout[outhel3]);
diag[2] = FFZVertex_->evaluate(scale(),off2,fout[outhel1],interZ);
diag[3] = FFPVertex_->evaluate(scale(),off2,fout[outhel1],interG);
// sum of diagrams
Complex sum = std::accumulate(diag.begin(),diag.end(),Complex(0.));
// matrix element
output(inhel1,inhel2,outhel1,outhel2,outhel3)=sum;
// me2
total += norm(sum);
}
}
}
}
}
// spin average
total *= 0.25;
tcPolarizedBeamPDPtr beam[2] =
{dynamic_ptr_cast<tcPolarizedBeamPDPtr>(partons[0]),
dynamic_ptr_cast<tcPolarizedBeamPDPtr>(partons[1])};
if( beam[0] || beam[1] ) {
RhoDMatrix rho[2] =
{beam[0] ? beam[0]->rhoMatrix() : RhoDMatrix(mePartonData()[0]->iSpin()),
beam[1] ? beam[1]->rhoMatrix() : RhoDMatrix(mePartonData()[1]->iSpin())};
total = output.average(rho[0],rho[1]);
}
// divide out the coupling
total /= norm(vertex->norm());
// and charge (if needed)
if(inter==ShowerInteraction::QED)
total /= sqr(double(mePartonData()[2]->iCharge())/3.);
// return the total
return total*UnitRemoval::InvE2;
}
diff --git a/MatrixElement/Lepton/MEee2gZ2qq.h b/MatrixElement/Lepton/MEee2gZ2qq.h
--- a/MatrixElement/Lepton/MEee2gZ2qq.h
+++ b/MatrixElement/Lepton/MEee2gZ2qq.h
@@ -1,507 +1,507 @@
// -*- C++ -*-
//
// MEee2gZ2qq.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_MEee2gZ2qq_H
#define HERWIG_MEee2gZ2qq_H
//
// This is the declaration of the MEee2gZ2qq class.
//
#include "Herwig/MatrixElement/HwMEBase.h"
#include "Herwig/Models/StandardModel/StandardModel.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/Rebinder.h"
#include "Herwig/MatrixElement/ProductionMatrixElement.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h"
namespace Herwig {
using namespace ThePEG;
/**
* The MEee2gZ2qq class implements the matrix element
* for \f$e^+e^-\to Z/\gamma \to q\bar{q}\f$ including spin correlations.
* The class includes greater control over the type of quark produced than is available
* in the corresponding matrix element from ThePEG, in addition to spin correlations.
*
* @see \ref MEee2gZ2qqInterfaces "The interfaces"
* defined for MEee2gZ2qq.
*/
class MEee2gZ2qq: public HwMEBase {
public:
/**
* The default constructor.
*/
MEee2gZ2qq() : minflav_(1), maxflav_(5), massopt_(1),
spinCorrelations_(true),
pTminQED_(GeV), pTminQCD_(GeV),
preFactor_(6.)
{}
/**
* Members for hard corrections to the emission of QCD radiation
*/
//@{
/**
* Has a POWHEG style correction
*/
virtual POWHEGType hasPOWHEGCorrection() {return FSR;}
/**
* Has an old fashioned ME correction
*/
virtual bool hasMECorrection() {return true;}
/**
* Initialize the ME correction
*/
virtual void initializeMECorrection(RealEmissionProcessPtr, double &,
double & );
/**
* Apply the hard matrix element correction to a given hard process or decay
*/
virtual RealEmissionProcessPtr applyHardMatrixElementCorrection(RealEmissionProcessPtr);
/**
* Apply the soft matrix element correction
* @param initial The particle from the hard process which started the
* shower
* @param parent The initial particle in the current branching
* @param br The branching struct
* @return If true the emission should be vetoed
*/
virtual bool softMatrixElementVeto(ShowerProgenitorPtr initial,
ShowerParticlePtr parent,
Branching br);
/**
* Apply the POWHEG style correction
*/
- virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr,ShowerInteraction::Type);
+ virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr,ShowerInteraction);
//@}
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* Construct the vertex of spin correlations.
*/
virtual void constructVertex(tSubProPtr);
//@}
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 {return new_ptr(*this);}
/** 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 {return new_ptr(*this);}
//@}
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();
/**
* Rebind pointer to other Interfaced objects. Called in the setup phase
* after all objects used in an EventGenerator has been cloned so that
* the pointers will refer to the cloned objects afterwards.
* @param trans a TranslationMap relating the original objects to
* their respective clones.
* @throws RebindException if no cloned object was found for a given
* pointer.
*/
virtual void rebind(const TranslationMap & trans)
;
/**
* Return a vector of all pointers to Interfaced objects used in this
* object.
* @return a vector of pointers.
*/
virtual IVector getReferences();
//@}
protected:
/**
* Calculate the matrix element for \f$e^+e^-\to q \bar{q}\f$.
* @param partons The incoming and outgoing particles
* @param momenta The momenta of the incoming and outgoing particles
* @param first Whether or not to calculate the spin correlations
*/
double loME(const vector<cPDPtr> & partons,
const vector<Lorentz5Momentum> & momenta,
bool first) const;
/**
* Member to calculate the matrix element
* @param fin Spinors for incoming fermion
* @param ain Spinors for incoming antifermion
* @param fout Spinors for outgoing fermion
* @param aout Spinors for outgong antifermion
* @param me Spin summed Matrix element
* @param cont The continuum piece of the matrix element
* @param BW The Z piece of the matrix element
*/
ProductionMatrixElement HelicityME(vector<SpinorWaveFunction> & fin,
vector<SpinorBarWaveFunction> & ain,
vector<SpinorBarWaveFunction> & fout,
vector<SpinorWaveFunction> & aout,
double & me,
double & cont,
double & BW ) const;
/**
* The ratio of the matrix element for one additional jet over the
* leading order result. In practice
* \f[\frac{\hat{s}|\overline{\mathcal{M}}|^2_2|D_{\rm emit}|}{4\pi C_F\alpha_S|\overline{\mathcal{M}}|^2_3\left(|D_{\rm emit}|+|D_{\rm spect}|\right)}\f]
* is returned where \f$\|\overline{\mathcal{M}}|^2\f$ is
* the spin and colour summed/averaged matrix element.
* @param partons The incoming and outgoing particles
* @param momenta The momenta of the incoming and outgoing particles
* @param iemitter Whether the quark or antiquark is regardede as the emitter
* @param inter The type of interaction
* @param subtract Whether or not to subtract the relevant dipole term
*/
double meRatio(vector<cPDPtr> partons,
vector<Lorentz5Momentum> momenta,
unsigned int iemitter,
- ShowerInteraction::Type inter,
+ ShowerInteraction inter,
bool subtract =false) const;
/**
* Calculate the matrix element for \f$e^-e^-\to q \bar q g\f$.
* @param partons The incoming and outgoing particles
* @param momenta The momenta of the incoming and outgoing particles
* @param inter The type of interaction
*/
InvEnergy2 realME(const vector<cPDPtr> & partons,
const vector<Lorentz5Momentum> & momenta,
- ShowerInteraction::Type inter) const;
+ ShowerInteraction inter) const;
private:
/**
* Generate the momenta for a hard configuration
*/
- pair<Energy,ShowerInteraction::Type>
+ pair<Energy,ShowerInteraction>
generateHard(RealEmissionProcessPtr,
vector<Lorentz5Momentum> & emission,
unsigned int & iemit, unsigned int & ispect,
- bool applyVeto,ShowerInteraction::Type);
+ bool applyVeto,ShowerInteraction);
/**
* Calculate the reall emission
*/
RealEmissionProcessPtr calculateRealEmission(RealEmissionProcessPtr born, bool veto,
- ShowerInteraction::Type inter);
+ ShowerInteraction inter);
/**
* Calculate \f$\tilde{\kappa}\f$.
*/
double getKfromX(double, double);
/**
* Vector and axial vector parts of the matrix element
*/
//@{
/**
* Vector part of the matrix element
*/
double MEV(double, double);
/**
* The matrix element, given \f$x_1\f$, \f$x_2\f$.
* @param x1 \f$x_1\f$
* @param x2 \f$x_2\f$
*/
double PS(double x1, double x2);
//@}
protected:
/**
* Pointer to the fermion-antifermion Z vertex
*/
AbstractFFVVertexPtr FFZVertex() const {return FFZVertex_;}
/**
* Pointer to the fermion-antifermion photon vertex
*/
AbstractFFVVertexPtr FFPVertex() const {return FFPVertex_;}
/**
* Pointer to the particle data object for the Z
*/
PDPtr Z0() const {return Z0_;}
/**
* Pointer to the particle data object for the photon
*/
PDPtr gamma() const {return gamma_;}
/**
* Pointer to the particle data object for the gluon
*/
PDPtr gluon() const {return gluon_;}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEee2gZ2qq & operator=(const MEee2gZ2qq &);
private:
/**
* Parameters controlling the leading-order process
*/
//@{
/**
* The minimum PDG of the quarks to be produced
*/
int minflav_;
/**
* The maximum PDG of the quarks to be produced
*/
int maxflav_;
/**
* Option for the treatment of the top quark mass
*/
unsigned int massopt_;
//@}
/**
* Pointers to the vertices
*/
//@{
/**
* Pointer to the fermion-antifermion Z vertex
*/
AbstractFFVVertexPtr FFZVertex_;
/**
* Pointer to the fermion-antifermion photon vertex
*/
AbstractFFVVertexPtr FFPVertex_;
/**
* Pointer to the fermion-antifermion photon vertex
*/
AbstractFFVVertexPtr FFGVertex_;
//@}
/**
* Switch on/off the helivity vertex construction
*/
bool spinCorrelations_;
/**
* Pointer to the ParticleData objects
*/
//@{
/**
* Pointer to the particle data object for the Z
*/
PDPtr Z0_;
/**
* Pointer to the particle data object for the photon
*/
PDPtr gamma_;
/**
* Pointer to the particle data object for the gluon
*/
PDPtr gluon_;
//@}
/**
* CM energy
*/
Energy d_Q_;
/**
* Quark mass
*/
Energy d_m_;
/**
* The rho parameter
*/
double d_rho_;
/**
* The v parameter
*/
double d_v_;
/**
* The initial kappa-tilde values for radiation from the quark
*/
double d_kt1_;
/**
* The initial kappa-tilde values for radiation from the antiquark
*/
double d_kt2_;
/**
* Cut-off parameter
*/
static const double EPS_;
/**
* Pointer to the strong coupling
*/
ShowerAlphaPtr alphaQCD_;
/**
* Pointer to the EM coupling
*/
ShowerAlphaPtr alphaQED_;
private:
/**
* Variables for the POWHEG style corrections
*/
//@{
/**
* The cut off on pt for QED, assuming massless quarks.
*/
Energy pTminQED_;
/**
* The cut off on pt for QCD, assuming massless quarks.
*/
Energy pTminQCD_;
/**
* Overestimate for the prefactor
*/
double preFactor_;
/**
* ParticleData objects for the partons
*/
vector<cPDPtr> partons_;
/**
* Momenta of the leading-order partons
*/
vector<Lorentz5Momentum> loMomenta_;
//@}
};
}
#endif /* HERWIG_MEee2gZ2qq_H */
diff --git a/MatrixElement/Lepton/Makefile.am b/MatrixElement/Lepton/Makefile.am
--- a/MatrixElement/Lepton/Makefile.am
+++ b/MatrixElement/Lepton/Makefile.am
@@ -1,9 +1,10 @@
pkglib_LTLIBRARIES = HwMELepton.la
HwMELepton_la_SOURCES = \
MEee2gZ2qq.h MEee2gZ2qq.cc\
MEee2gZ2ll.h MEee2gZ2ll.cc\
MEee2ZH.h MEee2ZH.cc\
MEee2HiggsVBF.h MEee2HiggsVBF.cc \
MEee2VV.h MEee2VV.cc \
-MEee2VectorMeson.h MEee2VectorMeson.cc
+MEee2VectorMeson.h MEee2VectorMeson.cc \
+MEee2Higgs2SM.h MEee2Higgs2SM.cc
HwMELepton_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 6:0:0
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,1722 +1,1720 @@
// -*- 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/Utilities/RunDirectories.h"
+#include "Herwig/API/RunDirectories.h"
#include "Herwig/MatrixElement/ProductionMatrixElement.h"
#include "Herwig/MatrixElement/HardVertex.h"
-#include <boost/foreach.hpp>
#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),
theDiagramWeightVerboseDown(10000000000000.),
theDiagramWeightVerboseUp(0.) {}
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<int> MatchboxMEBase::getNLightJetVec() const { return factory()->nLightJetVec(); }
vector<int> MatchboxMEBase::getNHeavyJetVec() const { return factory()->nHeavyJetVec(); }
vector<int> 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 ( vector<Ptr<Tree2toNDiagram>::ptr>::iterator d = diags.begin();
d != diags.end(); ++d ) {
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 ( list<list<list<pair<int,bool> > > >::const_iterator fit =
cflows.begin(); fit != cflows.end(); ++fit ) {
flows.push_back(new ColourLines(ColourBasis::cfstring(*fit)));
}
}
Selector<const ColourLines *> res;
for ( vector<ColourLines*>::const_iterator f = flows.begin();
f != flows.end(); ++f )
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 ( size_t k = 0; k < sub->outgoing().size(); ++k ) {
out.push_back(sub->outgoing()[k]->data().iSpin());
hard.push_back(sub->outgoing()[k]);
}
// 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 ( ParticleVector::const_iterator p = sub->outgoing().begin();
p != sub->outgoing().end(); ++p ) {
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);
}
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();
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 ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator v =
virtuals().begin(); v != virtuals().end(); ++v ) {
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() const {
if ( haveX1X2() ) {
lastXCombPtr()->lastSHat((meMomenta()[0]+meMomenta()[1]).m2());
}
Energy2 fcscale = factorizationScale();
Energy2 fscale = fcscale*sqr(factorizationScaleFactor());
Energy2 rscale = renormalizationScale()*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 ( map<long,int>::const_iterator c = counts.begin();
c != counts.end(); ++c ) {
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::dSigHatDR() const {
getPDFWeight();
if ( !lastXCombPtr()->willPassCuts() ) {
lastMECrossSection(ZERO);
return lastMECrossSection();
}
double xme2 = me2();
if (factory()->verboseDia()){
double diagweightsum = 0.0;
for ( vector<Ptr<DiagramBase>::ptr>::const_iterator d = diagrams().begin();
d != diagrams().end(); ++d ) {
diagweightsum += phasespace()->diagramWeight(dynamic_cast<const Tree2toNDiagram&>(**d));
}
double piWeight = pow(2.*Constants::pi,(int)(3*(meMomenta().size()-2)-4));
double units = pow(lastSHat() / GeV2, mePartonData().size() - 4.);
bookMEoverDiaWeight(log(xme2/(diagweightsum*piWeight*units)));//
}
if ( xme2 == 0. && !oneLoopNoBorn() ) {
lastMECrossSection(ZERO);
return lastMECrossSection();
}
double vme2 = 0.;
if ( oneLoop() && !oneLoopNoLoops() )
vme2 = oneLoopInterference();
CrossSection res = ZERO;
if ( !oneLoopNoBorn() )
res +=
(sqr(hbarc)/(2.*lastSHat())) *
jacobian()* lastMEPDFWeight() * xme2;
if ( oneLoop() && !oneLoopNoLoops() )
res +=
(sqr(hbarc)/(2.*lastSHat())) *
jacobian()* lastMEPDFWeight() * vme2;
if ( !onlyOneLoop() ) {
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator v =
virtuals().begin(); v != virtuals().end(); ++v ) {
(**v).setXComb(lastXCombPtr());
res += (**v).dSigHatDR();
}
if ( checkPoles() && oneLoop() )
logPoles();
}
double weight = 0.0;
bool applied = false;
for ( vector<Ptr<MatchboxReweightBase>::ptr>::const_iterator rw =
theReweights.begin(); rw != theReweights.end(); ++rw ) {
(**rw).setXComb(lastXCombPtr());
if ( !(**rw).apply() )
continue;
weight += (**rw).evaluate();
applied = true;
}
if ( applied )
res *= weight;
lastMECrossSection(res);
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 ( isnan(a) || isnan(b) ||
- isinf(a) || isinf(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 ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator v =
virtuals().begin(); v != virtuals().end(); ++v ) {
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<Ptr<SubtractionDipole>::ptr>
MatchboxMEBase::getDipoles(const vector<Ptr<SubtractionDipole>::ptr>& dipoles,
const vector<Ptr<MatchboxMEBase>::ptr>& borns) const {
vector<Ptr<SubtractionDipole>::ptr> 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<Ptr<SubtractionDipole>::ptr> matchDipoles;
for ( vector<Ptr<SubtractionDipole>::ptr>::const_iterator d =
dipoles.begin(); d != dipoles.end(); ++d ) {
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<Ptr<SubtractionDipole>::ptr> matchDipoles2;
for ( list<Ptr<SubtractionDipole>::ptr>::const_iterator d =
matchDipoles.begin(); d != matchDipoles.end(); ++d ) {
if ( !(**d).canHandleSplitting(rep,emitter,emission) )
continue;
matchDipoles2.push_back(*d);
}
if ( matchDipoles2.empty() )
continue;
map<Ptr<DiagramBase>::ptr,SubtractionDipole::MergeInfo> mergeInfo;
for ( DiagramVector::const_iterator d = diagrams().begin(); d != diagrams().end(); ++d ) {
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<Ptr<SubtractionDipole>::ptr> matchDipoles3;
for ( list<Ptr<SubtractionDipole>::ptr>::const_iterator d =
matchDipoles2.begin(); d != matchDipoles2.end(); ++d ) {
if ( !(**d).canHandleSpectator(rep,spectator) )
continue;
matchDipoles3.push_back(*d);
}
if ( matchDipoles3.empty() )
continue;
if ( noDipole(emitter,emission,spectator) )
continue;
for ( list<Ptr<SubtractionDipole>::ptr>::const_iterator d =
matchDipoles3.begin(); d != matchDipoles3.end(); ++d ) {
if ( !(**d).canHandle(rep,emitter,emission,spectator) )
continue;
for ( vector<Ptr<MatchboxMEBase>::ptr>::const_iterator b =
borns.begin(); b != borns.end(); ++b ) {
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);
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;
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 ( vector<ReweightPtr>::const_iterator rw = factory()->reweighters().begin();
rw != factory()->reweighters().end(); ++rw )
nDipole->addReweighter(*rw);
}
if ( !factory()->preweighters().empty() ) {
for ( vector<ReweightPtr>::const_iterator rw = factory()->preweighters().begin();
rw != factory()->preweighters().end(); ++rw )
nDipole->addPreweighter(*rw);
}
nDipole->cloneDependencies(dname.str());
}
}
}
}
}
}
vector<Ptr<SubtractionDipole>::tptr> partners;
copy(res.begin(),res.end(),back_inserter(partners));
for ( vector<Ptr<SubtractionDipole>::ptr>::iterator d = res.begin();
d != res.end(); ++d )
(**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 ( vector<Ptr<MatchboxReweightBase>::ptr>::iterator r =
reweights().begin(); r != reweights().end(); ++r ) {
(**r).flushCaches();
}
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator v =
virtuals().begin(); v != virtuals().end(); ++v ) {
(**v).flushCaches();
}
}
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) {
if ( phasespace() ) {
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());
matchboxAmplitude(myAmplitude);
amplitude(myAmplitude);
matchboxAmplitude()->orderInGs(orderInAlphaS());
matchboxAmplitude()->orderInGem(orderInAlphaEW());
}
if ( scaleChoice() ) {
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 ( vector<Ptr<MatchboxReweightBase>::ptr>::iterator rw =
theReweights.begin(); rw != theReweights.end(); ++rw ) {
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 ( vector<Ptr<MatchboxInsertionOperator>::ptr>::iterator v =
virtuals().begin(); v != virtuals().end(); ++v ) {
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 ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator v =
virtuals().begin(); v != virtuals().end(); ++v ) {
insertionAdd = max(insertionAdd,(**v).nDimAdditional());
}
xc.nDimInsertions(insertionAdd);
xc.nLight(getNLight());
for (size_t inlv=0; inlv<getNLightJetVec().size(); ++inlv)
xc.nLightJetVec(getNLightJetVec()[inlv]);
for (size_t inhv=0; inhv<getNHeavyJetVec().size(); ++inhv)
xc.nHeavyJetVec(getNHeavyJetVec()[inhv]);
for (size_t inlpv=0; inlpv<getNLightProtonVec().size(); ++inlpv)
xc.nLightProtonVec(getNLightProtonVec()[inlpv]);
xc.olpId(olpProcess());
if ( initVerbose() ) {
ostringstream fname_strm;
// only allow alphanumeric, / and _ in filename
- BOOST_FOREACH (const char c, name()) {
+ 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
<< theOLPProcess << theNoCorrelations
<< theHavePDFs << checkedPDFs<<theDiagramWeightVerboseDown<<theDiagramWeightVerboseUp;
}
void MatchboxMEBase::persistentInput(PersistentIStream & is, int) {
is >> theLastXComb >> theFactory >> thePhasespace
>> theAmplitude >> theScaleChoice >> theVirtuals
>> theReweights >> theSubprocess >> theOneLoop
>> theOneLoopNoBorn >> theOneLoopNoLoops
>> epsilonSquarePoleHistograms >> epsilonPoleHistograms
>> theOLPProcess >> theNoCorrelations
>> theHavePDFs >> checkedPDFs>>theDiagramWeightVerboseDown>>theDiagramWeightVerboseUp;
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 ( vector<Ptr<MatchboxReweightBase>::ptr>::iterator rw =
theReweights.begin(); rw != theReweights.end(); ++rw ) {
(**rw).init();
}
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::iterator v =
virtuals().begin(); v != virtuals().end(); ++v ) {
(**v).init();
}
}
void MatchboxMEBase::bookMEoverDiaWeight(double x) const {
if (MEoverDiaWeight.size()==0){
theDiagramWeightVerboseDown=min(theDiagramWeightVerboseDown,x*0.9);
theDiagramWeightVerboseUp=max(theDiagramWeightVerboseUp,x*1.1);
}
map<double,double>::iterator bx =MEoverDiaWeight.upper_bound(x);
if ( bx == MEoverDiaWeight.end() ) {
return;
}
bx->second += 1.;
Nevents++;
if (int(Nevents)%1000==0){
ofstream out((RunDirectories::runStorage()+"/"+name()+"-MeoDiaW.dat").c_str());
int i=0;
double m=0.;
for ( map<double,double>::const_iterator bx = MEoverDiaWeight.begin();bx != MEoverDiaWeight.end(); ++bx,i++ ) {
out << " " << bx->first<<" "<<( bx->second/double(Nevents))<<"\n ";
m=max(m,bx->second/double(Nevents));
}
out.close();
ofstream gpout((RunDirectories::runStorage()+"/"+name()+"-MeoDiaW.gp").c_str());
gpout << "set terminal epslatex color solid\n"
<< "set output '" << name()<<"-MeoDiaW"<< "-plot.tex'\n"
<< "#set logscale x\n"
<< "set xrange [" << theDiagramWeightVerboseDown << ":" << theDiagramWeightVerboseUp << "]\n"
<< "set yrange [0.:"<<(m*0.95)<<"]\n"
<< "set xlabel '$log(ME/\\sum DiaW)$'\n"
<< "set size 0.7,0.7\n"
<< "plot 1 w lines lc rgbcolor \"#DDDDDD\" notitle, '" << name()<<"-MeoDiaW"
<< ".dat' with histeps lc rgbcolor \"#00AACC\" t '$"<<name()<<"$'";
gpout.close();
}
}
void MatchboxMEBase::doinitrun() {
MEBase::doinitrun();
if ( matchboxAmplitude() )
matchboxAmplitude()->initrun();
if ( phasespace() ) {
phasespace()->initrun();
}
if ( scaleChoice() ) {
scaleChoice()->initrun();
}
for ( vector<Ptr<MatchboxReweightBase>::ptr>::iterator rw =
theReweights.begin(); rw != theReweights.end(); ++rw ) {
(**rw).initrun();
}
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::iterator v =
virtuals().begin(); v != virtuals().end(); ++v ) {
(**v).initrun();
}
if ( factory()->verboseDia() ) {
for ( int k = 0; k < factory()->diagramWeightVerboseNBins() ; ++k ) {
MEoverDiaWeight[theDiagramWeightVerboseDown+
double(k)*(theDiagramWeightVerboseUp-
theDiagramWeightVerboseDown)
/double(factory()->diagramWeightVerboseNBins()) ] = 0.;
}
Nevents=0.;
ofstream out("DiagramWeights.sh");
out<<"P=$(pwd)"
<<"\ncd "<<RunDirectories::runStorage()
<<"\nrm -f DiagramWeights.tex"
<<"\n echo \"\\documentclass{article}\" >> DiagramWeights.tex"
<<"\n echo \"\\usepackage{amsmath,amsfonts,amssymb,graphicx,color}\" >> DiagramWeights.tex"
<<"\n echo \"\\usepackage[left=2cm,right=2cm,top=2cm,bottom=2cm]{geometry}\" >> DiagramWeights.tex"
<<"\n echo \"\\begin{document}\" >> DiagramWeights.tex"
<<"\n echo \"\\setlength{\\parindent}{0cm}\" >> DiagramWeights.tex"
<<"\n\n for i in $(ls *.gp | sed s/'\\.gp'//g) ; "
<<"\n do"
<<"\n echo \"\\input{\"\"$i\"-plot\"}\" >> DiagramWeights.tex"
<<"\n done"
<<"\n echo \"\\end{document}\" >> DiagramWeights.tex "
<<"\n for i in *.gp ; do "
<<"\n gnuplot $i "
<<"\n done "
<<"\n pdflatex DiagramWeights.tex \ncp DiagramWeights.pdf $P";
out.close();
}
}
void MatchboxMEBase::dofinish() {
MEBase::dofinish();
for ( map<cPDVector,AccuracyHistogram>::const_iterator
b = epsilonSquarePoleHistograms.begin();
b != epsilonSquarePoleHistograms.end(); ++b ) {
b->second.dump(factory()->poleData(),"epsilonSquarePoles-",b->first);
}
for ( map<cPDVector,AccuracyHistogram>::const_iterator
b = epsilonPoleHistograms.begin();
b != epsilonPoleHistograms.end(); ++b ) {
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/Builtin/Amplitudes/Makefile.am b/MatrixElement/Matchbox/Builtin/Amplitudes/Makefile.am
--- a/MatrixElement/Matchbox/Builtin/Amplitudes/Makefile.am
+++ b/MatrixElement/Matchbox/Builtin/Amplitudes/Makefile.am
@@ -1,53 +1,67 @@
pkglib_LTLIBRARIES = HwMatchboxBuiltin.la
HwMatchboxBuiltin_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 3:0:0
-HwMatchboxBuiltin_la_SOURCES = \
-MatchboxCurrents.h MatchboxCurrents.cc \
-MatchboxZGammaAmplitude.h MatchboxZGammaAmplitude.cc \
+HwMatchboxBuiltin_la_SOURCES = $(ALL_H_FILES) Amplitudes__all.cc
+
+BUILT_SOURCES = Amplitudes__all.cc
+DISTCLEANFILES = Amplitudes__all.cc
+
+Amplitudes__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+MatchboxCurrents.h \
+MatchboxZGammaAmplitude.h \
+MatchboxAmplitudellbarqqbargg.h \
+MatchboxAmplitudellbarqqbarg.h \
+MatchboxAmplitudellbarqqbar.h \
+MatchboxAmplitudellbarqqbarqqbar.h \
+MatchboxAmplitudelnuqqbargg.h \
+MatchboxAmplitudelnuqqbarg.h \
+MatchboxAmplitudelnuqqbar.h \
+MatchboxAmplitudelnuqqbarqqbar.h \
+MatchboxAmplitudehbbbarg.h \
+MatchboxAmplitudehbbbar.h \
+MatchboxAmplitudehggg.h \
+MatchboxAmplitudehgg.h \
+MatchboxAmplitudehqqbarg.h \
+MatchboxAmplitudeqqbarttbar.h \
+MatchboxAmplitudeqqbarttbarg.h \
+MatchboxAmplitudeggttbar.h \
+MatchboxAmplitudeggttbarg.h \
+HelAmps_sm.h \
+Parameters_sm.h \
+MG_qqx2ttx.h \
+MG_qqx2ttxg.h \
+MG_gg2ttx.h \
+MG_gg2ttxg.h
+
+ALL_CC_FILES = \
+MatchboxCurrents.cc \
+MatchboxZGammaAmplitude.cc \
MatchboxAmplitudellbarqqbar.cc \
MatchboxAmplitudellbarqqbarg.cc \
MatchboxAmplitudellbarqqbargg.cc \
-MatchboxAmplitudellbarqqbargg.h \
-MatchboxAmplitudellbarqqbarg.h \
-MatchboxAmplitudellbarqqbar.h \
MatchboxAmplitudellbarqqbarqqbar.cc \
-MatchboxAmplitudellbarqqbarqqbar.h \
MatchboxAmplitudelnuqqbar.cc \
MatchboxAmplitudelnuqqbarg.cc \
MatchboxAmplitudelnuqqbargg.cc \
-MatchboxAmplitudelnuqqbargg.h \
-MatchboxAmplitudelnuqqbarg.h \
-MatchboxAmplitudelnuqqbar.h \
MatchboxAmplitudelnuqqbarqqbar.cc \
-MatchboxAmplitudelnuqqbarqqbar.h \
MatchboxAmplitudehbbbar.cc \
MatchboxAmplitudehbbbarg.cc \
-MatchboxAmplitudehbbbarg.h \
-MatchboxAmplitudehbbbar.h \
MatchboxAmplitudehgg.cc \
MatchboxAmplitudehggg.cc \
-MatchboxAmplitudehggg.h \
-MatchboxAmplitudehgg.h \
MatchboxAmplitudehqqbarg.cc \
-MatchboxAmplitudehqqbarg.h \
MatchboxAmplitudeqqbarttbar.cc \
-MatchboxAmplitudeqqbarttbar.h \
MatchboxAmplitudeqqbarttbarg.cc \
-MatchboxAmplitudeqqbarttbarg.h \
MatchboxAmplitudeggttbar.cc \
-MatchboxAmplitudeggttbar.h \
MatchboxAmplitudeggttbarg.cc \
-MatchboxAmplitudeggttbarg.h \
HelAmps_sm.cc \
-HelAmps_sm.h \
Parameters_sm.cc \
-Parameters_sm.h \
MG_qqx2ttx.cc \
-MG_qqx2ttx.h \
MG_qqx2ttxg.cc \
-MG_qqx2ttxg.h \
MG_gg2ttx.cc \
-MG_gg2ttx.h \
-MG_gg2ttxg.cc \
-MG_gg2ttxg.h
+MG_gg2ttxg.cc
diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbar.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbar.cc
old mode 100755
new mode 100644
diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbar.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbar.h
old mode 100755
new mode 100644
diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarg.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarg.cc
old mode 100755
new mode 100644
diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarg.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxAmplitudellbarqqbarg.h
old mode 100755
new mode 100644
diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.cc b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.cc
old mode 100755
new mode 100644
--- a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.cc
+++ b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.cc
@@ -1,2861 +1,2861 @@
// - * - C++ - * -
//
// MatchboxCurrents.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 "MatchboxCurrents.h"
#include "Herwig/Utilities/Maths.h"
using namespace Herwig;
using namespace Herwig::Math;
using Constants::pi;
namespace {
const static LorentzVector<Complex> czero(0.,0.,0.,0.);
inline Complex csqr(const Complex & a) {
return a * a;
}
inline double theta(const double x) {
if ( x >= 0. )
return 1.;
return 0.;
}
inline double sign(const double x) {
if ( x >= 0. )
return 1.;
return -1.;
}
// quick'n'dirty fix to template troubles
Complex operator * (const Complex& a, const double b) {
return Complex(a.real() * b,a.imag() * b);
}
Complex operator * (const double b, const Complex& a) {
return Complex(a.real() * b,a.imag() * b);
}
Complex operator+(const Complex& a, const double b) {
return Complex(a.real()+b,a.imag());
}
Complex operator+(const double b, const Complex& a) {
return Complex(a.real()+b,a.imag());
}
Complex operator-(const Complex& a, const double b) {
return Complex(a.real()-b,a.imag());
}
Complex operator-(const double b, const Complex& a) {
return Complex(b-a.real(),-a.imag());
}
// end fix, needs to be looked at in ThePEG/Config/
}
void MatchboxCurrents::setupLeptons(const int l, const Lorentz5Momentum& pl,
const int lbar, const Lorentz5Momentum& plbar) {
const Energy4 Delta = (sqr(pl*plbar) - (pl*pl)*(plbar*plbar));
const Energy2 prod = pl*plbar;
// Variable to contain the sign of pl*plbar
double sgn;
if (prod < ZERO ) {sgn = -1;}
else if (prod > ZERO) {sgn = 1;}
else {sgn = 0;}
InvEnergy2 fact = 0.5/(sgn*sqrt(Delta));
Lorentz5Momentum lmassless = ( double(fact*(sgn*sqrt(Delta) + prod))*pl - double(fact*( pl*pl))*plbar );
Lorentz5Momentum lbarmassless = ( double(fact*(sgn*sqrt(Delta) + prod))*plbar - double(fact*(plbar*plbar))*pl );
lmassless.setMass(ZERO); lmassless.rescaleEnergy();
lbarmassless.setMass(ZERO); lbarmassless.rescaleEnergy();
if ( pl.t() < ZERO )
lmassless.setT(-lmassless.t());
if ( plbar.t() < ZERO )
lbarmassless.setT(-lbarmassless.t());
momentum(l,lmassless,true,pl.mass());
momentum(lbar,lbarmassless,true,plbar.mass());
}
void MatchboxCurrents::setupQuarks(const int q, const Lorentz5Momentum& pq,
const int qbar, const Lorentz5Momentum& pqbar) {
const Energy4 Delta = (sqr(pq*pqbar) - (pq*pq)*(pqbar*pqbar));
const Energy2 prod = pq*pqbar;
// Variable to contain the sign of pq*pqbar
double sgn;
if (prod < ZERO) {sgn = -1;}
else if (prod > ZERO) {sgn = 1;}
else {sgn = 0;}
InvEnergy2 fact = 0.5/(sgn*sqrt(Delta));
Lorentz5Momentum qmassless = ( double(fact*(sgn*sqrt(Delta) + prod))*pq - double(fact*(pq*pq))*pqbar );
Lorentz5Momentum qbarmassless = ( double(fact*(sgn*sqrt(Delta) + prod))*pqbar - double(fact*(pqbar*pqbar))*pq );
qmassless.setMass(ZERO); qmassless.rescaleEnergy();
qbarmassless.setMass(ZERO); qbarmassless.rescaleEnergy();
if ( pq.t() < ZERO )
qmassless.setT(-qmassless.t());
if ( pqbar.t() < ZERO )
qbarmassless.setT(-qbarmassless.t());
momentum(q,qmassless,true,pq.mass());
momentum(qbar,qbarmassless,true,pqbar.mass());
}
const LorentzVector<Complex>& MatchboxCurrents::llbarLeftCurrent(const int l, const int lHel,
const int lbar, const int lbarHel) {
if ( getCurrent(hash<0>(1,1,l,lHel,lbar,lbarHel)) ) {
if ( lHel == 1 && lbarHel == 1 )
cacheCurrent(Complex(0.,1.) * minusCurrent(l,lbar));
if ( lHel == 1 && lbarHel == -1 )
cacheCurrent((Complex(0.,2.) * mass(lbar)/plusProduct(l,lbar)) * momentum(l));
if ( lHel == -1 && lbarHel == 1 )
cacheCurrent((Complex(0.,-2.) * mass(l)/minusProduct(l,lbar)) * momentum(lbar));
if ( lHel == -1 && lbarHel == -1 )
cacheCurrent((Complex(0.,1.) * mass(l) * mass(lbar)/invariant(l,lbar)) * minusCurrent(lbar,l));
}
return cachedCurrent();
}
const LorentzVector<Complex>& MatchboxCurrents::llbarRightCurrent(const int l, const int lHel,
const int lbar, const int lbarHel) {
if ( getCurrent(hash<0>(2,1,l,lHel,lbar,lbarHel)) ) {
if ( lHel == 1 && lbarHel == 1 )
cacheCurrent((Complex(0.,1.) * mass(l) * mass(lbar)/invariant(l,lbar)) * minusCurrent(l,lbar));
if ( lHel == 1 && lbarHel == -1 )
cacheCurrent((Complex(0.,-2.) * mass(l)/plusProduct(l,lbar)) * momentum(lbar));
if ( lHel == -1 && lbarHel == 1 )
cacheCurrent((Complex(0.,2.) * mass(lbar)/minusProduct(l,lbar)) * momentum(l));
if ( lHel == -1 && lbarHel == -1 )
cacheCurrent(Complex(0.,1.) * minusCurrent(lbar,l));
}
return cachedCurrent();
}
const LorentzVector<Complex>& MatchboxCurrents::qqbarLeftCurrent(const int q, const int qHel,
const int qbar, const int qbarHel) {
if ( getCurrent(hash<1>(1,1,q,qHel,qbar,qbarHel)) ) {
if ( qHel == 1 && qbarHel == 1 )
cacheCurrent(Complex(0.,1.) * minusCurrent(q,qbar));
if ( qHel == 1 && qbarHel == -1 )
cacheCurrent((Complex(0.,2.) * mass(qbar)/plusProduct(q,qbar)) * momentum(q));
if ( qHel == -1 && qbarHel == 1 )
cacheCurrent((Complex(0.,-2.) * mass(q)/minusProduct(q,qbar)) * momentum(qbar));
if ( qHel == -1 && qbarHel == -1 )
cacheCurrent((Complex(0.,1.) * mass(q) * mass(qbar)/invariant(q,qbar)) * minusCurrent(qbar,q));
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbarLeftCurrent",cachedCurrent(),momentum(q)+momentum(qbar));
#endif
return cachedCurrent();
}
const LorentzVector<Complex>& MatchboxCurrents::qqbarRightCurrent(const int q, const int qHel,
const int qbar, const int qbarHel) {
if ( getCurrent(hash<1>(2,1,q,qHel,qbar,qbarHel)) ) {
if ( qHel == 1 && qbarHel == 1 )
cacheCurrent((Complex(0.,1.) * mass(q) * mass(qbar)/invariant(q,qbar)) * minusCurrent(q,qbar));
if ( qHel == 1 && qbarHel == -1 )
cacheCurrent((Complex(0.,-2.) * mass(q)/plusProduct(q,qbar)) * momentum(qbar));
if ( qHel == -1 && qbarHel == 1 )
cacheCurrent((Complex(0.,2.) * mass(qbar)/minusProduct(q,qbar)) * momentum(q));
if ( qHel == -1 && qbarHel == -1 )
cacheCurrent(Complex(0.,1.) * minusCurrent(qbar,q));
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbarRightCurrent",cachedCurrent(),momentum(q)+momentum(qbar));
#endif
return cachedCurrent();
}
const LorentzVector<Complex>& MatchboxCurrents::qqbargLeftCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g, const int gHel) {
if ( gHel == 1 ) {
if ( getCurrent(hash<2>(1,1,q,qHel,qbar,qbarHel,g,gHel)) ) {
// Invariant products from propagator denominators
const Complex den_i = invariant(q,g) + (sqr(mass(q))/invariant(q,qbar))*invariant(qbar,g);
const Complex den_j = invariant(qbar,g) + (sqr(mass(qbar))/invariant(q,qbar))*invariant(q,g);
// 2*factor from the spinor definition of the negative helicity gluon
// Note that the gluon is outgoing so the polarisation vector of the hel=+1 gluon is conjugated to give the hel=-1 vector
const Complex cminus = sqrt(2.0) / minusProduct(g,q);
if ( qHel == 1 && qbarHel == 1 )
cacheCurrent( Complex(0.,1.)*cminus*( ((sqr(mass(q))*plusProduct(qbar,g)/(plusProduct(qbar,q)*den_i)) - (minusProduct(qbar,q)*plusProduct(g,qbar)/den_j))*minusCurrent(q, qbar) - (minusProduct(g,q)*plusProduct(g,qbar)/den_j)*minusCurrent(q,g) ) );
if ( qHel == 1 && qbarHel == -1 )
cacheCurrent( Complex(0.,1.)*cminus*(-mass(qbar)/plusProduct(qbar,q)) * ( ((sqr(mass(q))*plusProduct(qbar,g)/(plusProduct(qbar,q)*den_i)) - (plusProduct(qbar,g)*minusProduct(q,qbar)/den_j))*2*momentum(q) + (invariant(q,g)/den_j)*minusCurrent(q,g) ) );
if ( qHel == -1 && qbarHel == 1 )
cacheCurrent( Complex(0.,1.)*cminus*(mass(q)/minusProduct(qbar,q)) * ( ((sqr(mass(q))*plusProduct(g,qbar)/(plusProduct(q,qbar)*den_i)) - (plusProduct(g,qbar)*minusProduct(qbar,q)/den_j))*2*momentum(qbar) - (minusProduct(g,q)*plusProduct(g,qbar)/den_j)*minusCurrent(qbar,g) ) );
if ( qHel == -1 && qbarHel == -1 )
cacheCurrent( Complex(0.,1.)*cminus*(mass(qbar)*mass(q)/(invariant(q,qbar))) * ( ((sqr(mass(q))*plusProduct(g,qbar)/(plusProduct(q,qbar)*den_i)) - (minusProduct(q,qbar)*plusProduct(qbar,g)/den_j))*minusCurrent(qbar,q) + (invariant(q,g)/den_j)*minusCurrent(qbar,g) ) );
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbargLeftCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(g));
#endif
return cachedCurrent();
}
if ( gHel == -1 ) {
if ( getCurrent(hash<2>(1,1,q,qHel,qbar,qbarHel,g,gHel)) ) {
// Invariant products from propagator denominators
const Complex den_i = invariant(q,g) + (sqr(mass(q))/invariant(q,qbar))*invariant(qbar,g);
const Complex den_j = invariant(qbar,g) + (sqr(mass(qbar))/invariant(q,qbar))*invariant(q,g);
// 2*factor from the spinor definition of the positive helicity gluon
const Complex cplus = sqrt(2.0) / plusProduct(q,g);
if ( qHel == 1 && qbarHel == 1 )
cacheCurrent( Complex(0.,1.)*cplus*( ((sqr(mass(q))*minusProduct(g,qbar)/(minusProduct(q,qbar)*den_i)) - (minusProduct(qbar,g)*plusProduct(q,qbar)/den_j))*minusCurrent(q, qbar) - (invariant(q,g)/den_i)*minusCurrent(g,qbar) ) );
if ( qHel == 1 && qbarHel == -1 )
cacheCurrent( Complex(0.,1.)*cplus*(-mass(qbar)/plusProduct(qbar,q)) * ( ((sqr(mass(q))*minusProduct(g,qbar)/(minusProduct(q,qbar)*den_i)) - (plusProduct(qbar,q)*minusProduct(g,qbar)/den_j))*2*momentum(q) - (invariant(q,g)/den_i)*minusCurrent(g,q) ) );
if ( qHel == -1 && qbarHel == 1 )
cacheCurrent( Complex(0.,1.)*cplus*(mass(q)/minusProduct(qbar,q)) * ( ((sqr(mass(q))*minusProduct(qbar,g)/(minusProduct(qbar,q)*den_i)) - (minusProduct(qbar,g)*plusProduct(q,qbar)/den_j))*2*momentum(qbar) + (minusProduct(qbar,g)*plusProduct(q,g)/den_i)*minusCurrent(g,qbar) ) );
if ( qHel == -1 && qbarHel == -1 )
cacheCurrent( Complex(0.,1.)*cplus*(mass(qbar)*mass(q)/(invariant(q,qbar))) * ( ((sqr(mass(q))*minusProduct(qbar,g)/(minusProduct(qbar,q)*den_i)) - (plusProduct(qbar,q)*minusProduct(g,qbar)/den_j))*minusCurrent(qbar, q) + (minusProduct(qbar,g)*plusProduct(q,g)/den_i)*minusCurrent(g,q) ) );
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbargLeftCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(g));
#endif
return cachedCurrent();
}
return czero;
}
const LorentzVector<Complex>& MatchboxCurrents::qqbargRightCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g, const int gHel) {
if ( gHel == 1 ) {
if ( getCurrent(hash<2>(2,1,q,qHel,qbar,qbarHel,g,gHel)) ) {
// Invariant products from propagator denominators
const Complex den_i = invariant(q,g) + (sqr(mass(q))/invariant(q,qbar))*invariant(qbar,g);
const Complex den_j = invariant(qbar,g) + (sqr(mass(qbar))/invariant(q,qbar))*invariant(q,g);
// 2*factor from the spinor definition of the positive helicity gluon
const Complex cminus = sqrt(2.0) / minusProduct(g,q);
if ( qHel == 1 && qbarHel == 1 )
cacheCurrent( Complex(0.,1.)*cminus*(mass(qbar)*mass(q)/(invariant(q,qbar))) * ( ((sqr(mass(q))*plusProduct(qbar,g)/(plusProduct(qbar,q)*den_i)) - (minusProduct(qbar,q)*plusProduct(g,qbar)/den_j))*plusCurrent(qbar, q) + (plusProduct(qbar,g)*minusProduct(q,g)/den_i)*plusCurrent(g,q) ) );
if ( qHel == 1 && qbarHel == -1 )
cacheCurrent( Complex(0.,1.)*cminus*(mass(q)/plusProduct(qbar,q)) * ( ((sqr(mass(q))*plusProduct(qbar,g)/(plusProduct(qbar,q)*den_i)) - (plusProduct(qbar,g)*minusProduct(q,qbar)/den_j))*2*momentum(qbar) + (plusProduct(qbar,g)*minusProduct(q,g)/den_i)*plusCurrent(g,qbar) ) );
if ( qHel == -1 && qbarHel == 1 )
cacheCurrent( Complex(0.,1.)*cminus*(-mass(qbar)/minusProduct(qbar,q)) * ( ((sqr(mass(q))*plusProduct(g,qbar)/(plusProduct(q,qbar)*den_i)) - (minusProduct(qbar,q)*plusProduct(g,qbar)/den_j))*2*momentum(q) - (invariant(q,g)/den_i)*plusCurrent(g,q) ) );
if ( qHel == -1 && qbarHel == -1 )
cacheCurrent( Complex(0.,1.)*cminus*( ((sqr(mass(q))*plusProduct(g,qbar)/(plusProduct(q,qbar)*den_i)) - (plusProduct(qbar,g)*minusProduct(q,qbar)/den_j))*plusCurrent(q, qbar) - (invariant(q,g)/den_i)*plusCurrent(g,qbar) ) );
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbargRightCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(g));
#endif
return cachedCurrent();
}
if ( gHel == -1 ) {
if ( getCurrent(hash<2>(2,1,q,qHel,qbar,qbarHel,g,gHel)) ) {
// Invariant products from propagator denominators
const Complex den_i = invariant(q,g) + (sqr(mass(q))/invariant(q,qbar))*invariant(qbar,g);
const Complex den_j = invariant(qbar,g) + (sqr(mass(qbar))/invariant(q,qbar))*invariant(q,g);
// 2*factor from the spinor definition of the positive helicity gluon
const Complex cplus = sqrt(2.0) / plusProduct(q,g);
if ( qHel == 1 && qbarHel == 1 )
cacheCurrent( Complex(0.,1.)*cplus*(mass(qbar)*mass(q)/(invariant(q,qbar))) * ( ((sqr(mass(q))*minusProduct(g,qbar)/(minusProduct(q,qbar)*den_i)) - (plusProduct(q,qbar)*minusProduct(qbar,g)/den_j))*plusCurrent(qbar, q) + (invariant(q,g)/den_j)*plusCurrent(qbar,g) ) );
if ( qHel == 1 && qbarHel == -1 )
cacheCurrent( Complex(0.,1.)*cplus*(mass(q)/plusProduct(qbar,q)) * ( ((sqr(mass(q))*minusProduct(g,qbar)/(minusProduct(q,qbar)*den_i)) - (minusProduct(g,qbar)*plusProduct(qbar,q)/den_j))*2*momentum(qbar) - (plusProduct(g,q)*minusProduct(g,qbar)/den_j)*plusCurrent(qbar,g) ) );
if ( qHel == -1 && qbarHel == 1 )
cacheCurrent( Complex(0.,1.)*cplus*(-mass(qbar)/minusProduct(qbar,q)) * ( ((sqr(mass(q))*minusProduct(qbar,g)/(minusProduct(qbar,q)*den_i)) - (minusProduct(qbar,g)*plusProduct(q,qbar)/den_j))*2*momentum(q) + (invariant(q,g)/den_j)*plusCurrent(q,g) ) );
if ( qHel == -1 && qbarHel == -1 )
cacheCurrent( Complex(0.,1.)*cplus*( ((sqr(mass(q))*minusProduct(qbar,g)/(minusProduct(qbar,q)*den_i)) - (plusProduct(qbar,q)*minusProduct(g,qbar)/den_j))*plusCurrent(q, qbar) - (plusProduct(g,q)*minusProduct(g,qbar)/den_j)*plusCurrent(q,g) ) );
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbargRightCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(g));
#endif
return cachedCurrent();
}
return czero;
}
LorentzVector<Complex> MatchboxCurrents::qqbarggGeneralLeftCurrent(const int i, const int,
const int j, const int,
const int k, const int g1Hel,
const int l, const int g2Hel,
const int n) {
const double ik = invariant(i,k);
const double il = invariant(i,l);
const double jk = invariant(j,k);
const double jl = invariant(j,l);
const double kl = invariant(k,l);
const Complex plusP_ik = plusProduct(i,k);
const Complex plusP_il = plusProduct(i,l);
const Complex plusP_in = plusProduct(i,n);
const Complex plusP_jk = plusProduct(j,k);
const Complex plusP_jl = plusProduct(j,l);
const Complex plusP_jn = plusProduct(j,n);
const Complex plusP_kl = plusProduct(k,l);
const Complex plusP_kn = plusProduct(k,n);
const Complex plusP_ln = plusProduct(l,n);
const Complex minusP_ik = minusProduct(i,k);
const Complex minusP_il = minusProduct(i,l);
const Complex minusP_in = minusProduct(i,n);
const Complex minusP_jk = minusProduct(j,k);
const Complex minusP_jl = minusProduct(j,l);
const Complex minusP_jn = minusProduct(j,n);
const Complex minusP_kl = minusProduct(k,l);
const Complex minusP_kn = minusProduct(k,n);
const Complex minusP_ln = minusProduct(l,n);
const LorentzVector<Complex> & minusC_ij = minusCurrent(i,j);
const LorentzVector<Complex> & minusC_ik = minusCurrent(i,k);
const LorentzVector<Complex> & minusC_il = minusCurrent(i,l);
const LorentzVector<Complex> & minusC_kj = minusCurrent(k,j);
const LorentzVector<Complex> & minusC_kl = minusCurrent(k,l);
const LorentzVector<Complex> & minusC_lj = minusCurrent(l,j);
if ( g1Hel == 1 && g2Hel == 1 ) {
return
(Complex(0,-2) * plusP_jl * plusP_kl * minusC_ik)/
(jl * (jk + jl + kl)) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_ik)/
(kl * (jk + jl + kl)) -
(Complex(0,2) * plusP_jk * plusP_kl * minusC_il)/
(kl * (jk + jl + kl)) +
(Complex(0,2) * plusP_il * plusP_kl * minusC_ij * minusP_in)/
(kl * (ik + il + kl) * minusP_kn) -
(Complex(0,2) * plusP_ik * plusP_jl * minusC_il * minusP_in)/
(ik * jl * minusP_kn) +
(Complex(0,2) * sqr(plusP_kl) * minusC_kj * minusP_in)/
(kl * (ik + il + kl) * minusP_kn) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_ij * minusP_jn)/
(jl * (jk + jl + kl) * minusP_kn) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_ij * minusP_jn)/
(kl * (jk + jl + kl) * minusP_kn) +
(Complex(0,2) * plusP_jk * plusP_jl * minusC_il * minusP_jn)/
(jl * (jk + jl + kl) * minusP_kn) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_ij * minusP_in)/
(kl * (ik + il + kl) * minusP_ln) -
(Complex(0,2) * sqr(plusP_kl) * minusC_lj * minusP_in)/
(kl * (ik + il + kl) * minusP_ln) -
(Complex(0,2) * plusP_jk * plusP_kl * minusC_ij * minusP_jn)/
(kl * (jk + jl + kl) * minusP_ln) +
(Complex(0,2) * plusP_jk * plusP_jl * minusC_ik * minusP_jn)/
(jl * (jk + jl + kl) * minusP_ln) +
(Complex(0,2) * plusP_ik * plusP_il * minusC_ij * sqr(minusP_in))/
(ik * (ik + il + kl) * minusP_kn * minusP_ln) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_kj * sqr(minusP_in))/
(ik * (ik + il + kl) * minusP_kn * minusP_ln) -
(Complex(0,2) * plusP_ik * plusP_jl * minusC_ij * minusP_in * minusP_jn)/
(ik * jl * minusP_kn * minusP_ln) +
(Complex(0,2) * plusP_jk * plusP_jl * minusC_ij * sqr(minusP_jn))/
(jl * (jk + jl + kl) * minusP_kn * minusP_ln) -
(Complex(0,2) * plusP_jk * plusP_kl * minusC_ik * minusP_kn)/
(kl * (jk + jl + kl) * minusP_ln) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_il * minusP_ln)/
(jl * (jk + jl + kl) * minusP_kn) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_il * minusP_ln)/
(kl * (jk + jl + kl) * minusP_kn);
}
if ( g1Hel == 1 && g2Hel == -1 ) {
return
(Complex(0,-2) * plusP_jk * plusP_jn * minusC_ik * minusP_jl)/
(jl * (jk + jl + kl) * plusP_ln) +
(Complex(0,2) * plusP_jk * plusP_kn * minusC_ik * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ln) -
(Complex(0,2) * plusP_ik * plusP_in * minusC_ij * minusP_il * minusP_in)/
(ik * (ik + il + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_ik * plusP_kn * minusC_kj * minusP_il * minusP_in)/
(ik * (ik + il + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_ik * minusC_lj * minusP_il * minusP_in)/
(ik * (ik + il + kl) * minusP_kn) +
(Complex(0,2) * plusP_ik * plusP_jn * minusC_ij * minusP_in * minusP_jl)/
(ik * jl * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_jk * plusP_jn * minusC_ij * minusP_jl * minusP_jn)/
(jl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_ik * plusP_kn * minusC_ij * minusP_in * minusP_kl)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) +
(Complex(0,2) * plusP_kl * plusP_kn * minusC_lj * minusP_in * minusP_kl)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) +
(Complex(0,2) * plusP_jk * plusP_kn * minusC_ij * minusP_jn * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,1) * plusP_ik * plusP_kn * minusC_ij * minusP_ik * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) +
(Complex(0,1) * plusP_kl * plusP_kn * minusC_lj * minusP_ik * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_in * plusP_kl * minusC_ij * minusP_il * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) +
(Complex(0,1) * plusP_il * plusP_kn * minusC_ij * minusP_il * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) -
(Complex(0,1) * plusP_kl * plusP_kn * minusC_kj * minusP_il * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_kl * minusC_lj * minusP_il * minusP_ln)/
(kl * (ik + il + kl) * minusP_kn) +
(Complex(0,1) * plusP_jk * plusP_kn * minusC_ij * minusP_jk * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) +
(Complex(0,2) * plusP_jn * plusP_kl * minusC_ij * minusP_jl * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,1) * plusP_jl * plusP_kn * minusC_ij * minusP_jl * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_jk * plusP_jn * minusC_il * minusP_jl * minusP_ln)/
(jl * (jk + jl + kl) * plusP_ln * minusP_kn) +
(Complex(0,2) * plusP_jn * plusP_kl * minusC_ik * minusP_kl * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,1) * plusP_jl * plusP_kn * minusC_ik * minusP_kl * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) +
(Complex(0,1) * plusP_jk * plusP_kn * minusC_il * minusP_kl * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn);
}
if ( g1Hel == -1 && g2Hel == 1 ) {
return
(Complex(0,2) * plusP_in * plusP_jl * minusC_il * minusP_ik)/
(ik * jl * plusP_kn) +
(Complex(0,2) * plusP_jl * minusC_kl * minusP_ik)/(ik * jl) -
(Complex(0,2) * plusP_jl * plusP_ln * minusC_ij * minusP_jk)/
(jl * (jk + jl + kl) * plusP_kn) +
(Complex(0,2) * plusP_jl * plusP_ln * minusC_il * minusP_kl)/
(jl * (jk + jl + kl) * plusP_kn) +
(Complex(0,2) * plusP_jl * plusP_ln * minusC_il * minusP_kl)/
(kl * (jk + jl + kl) * plusP_kn) -
(Complex(0,2) * plusP_il * plusP_in * minusC_ij * minusP_ik * minusP_in)/
(ik * (ik + il + kl) * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_in * plusP_kl * minusC_kj * minusP_ik * minusP_in)/
(ik * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_in * plusP_jl * minusC_ij * minusP_ik * minusP_jn)/
(ik * jl * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_jl * minusC_kj * minusP_ik * minusP_jn)/
(ik * jl * minusP_ln) -
(Complex(0,2) * plusP_jl * plusP_jn * minusC_ij * minusP_jk * minusP_jn)/
(jl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_il * plusP_ln * minusC_ij * minusP_in * minusP_kl)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_kl * plusP_ln * minusC_kj * minusP_in * minusP_kl)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_jl * plusP_ln * minusC_ij * minusP_jn * minusP_kl)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_jl * plusP_jn * minusC_il * minusP_jn * minusP_kl)/
(jl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_il * minusC_ij * minusP_ik * minusP_kn)/
(ik * (ik + il + kl) * minusP_ln) -
(Complex(0,2) * plusP_in * plusP_kl * minusC_ij * minusP_ik * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) -
(Complex(0,1) * plusP_ik * plusP_ln * minusC_ij * minusP_ik * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_kl * minusC_kj * minusP_ik * minusP_kn)/
(ik * (ik + il + kl) * minusP_ln) -
(Complex(0,2) * plusP_kl * minusC_kj * minusP_ik * minusP_kn)/
(kl * (ik + il + kl) * minusP_ln) -
(Complex(0,1) * plusP_kl * plusP_ln * minusC_lj * minusP_ik * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,1) * plusP_il * plusP_ln * minusC_ij * minusP_il * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,1) * plusP_kl * plusP_ln * minusC_kj * minusP_il * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_jn * plusP_kl * minusC_ij * minusP_jk * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) +
(Complex(0,1) * plusP_jk * plusP_ln * minusC_ij * minusP_jk * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,1) * plusP_jl * plusP_ln * minusC_ij * minusP_jl * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) +
(Complex(0,1) * plusP_jl * plusP_ln * minusC_ik * minusP_kl * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_jn * plusP_kl * minusC_il * minusP_kl * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,1) * plusP_jk * plusP_ln * minusC_il * minusP_kl * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln);
}
if ( g1Hel == -1 && g2Hel == -1 ) {
return
(Complex(0,2) * sqr(plusP_in) * minusC_ij * minusP_ik * minusP_il)/
(ik * (ik + il + kl) * plusP_kn * plusP_ln) +
(Complex(0,2) * plusP_in * minusC_kj * minusP_ik * minusP_il)/
(ik * (ik + il + kl) * plusP_ln) +
(Complex(0,2) * plusP_in * minusC_lj * minusP_ik * minusP_il)/
(ik * (ik + il + kl) * plusP_kn) -
(Complex(0,2) * plusP_in * plusP_jn * minusC_ij * minusP_ik * minusP_jl)/
(ik * jl * plusP_kn * plusP_ln) -
(Complex(0,2) * plusP_jn * minusC_kj * minusP_ik * minusP_jl)/
(ik * jl * plusP_ln) +
(Complex(0,2) * sqr(plusP_jn) * minusC_ij * minusP_jk * minusP_jl)/
(jl * (jk + jl + kl) * plusP_kn * plusP_ln) +
(Complex(0,2) * plusP_in * minusC_ij * minusP_ik * minusP_kl)/
(ik * (ik + il + kl) * plusP_ln) +
(Complex(0,2) * plusP_in * minusC_ij * minusP_ik * minusP_kl)/
(kl * (ik + il + kl) * plusP_ln) +
(Complex(0,2) * plusP_kn * minusC_kj * minusP_ik * minusP_kl)/
(ik * (ik + il + kl) * plusP_ln) +
(Complex(0,2) * plusP_kn * minusC_kj * minusP_ik * minusP_kl)/
(kl * (ik + il + kl) * plusP_ln) +
(Complex(0,2) * minusC_lj * minusP_ik * minusP_kl)/
(ik * (ik + il + kl)) +
(Complex(0,2) * minusC_lj * minusP_ik * minusP_kl)/
(kl * (ik + il + kl)) +
(Complex(0,2) * plusP_in * minusC_ij * minusP_il * minusP_kl)/
(kl * (ik + il + kl) * plusP_kn) +
(Complex(0,2) * minusC_kj * minusP_il * minusP_kl)/
(kl * (ik + il + kl)) +
(Complex(0,2) * plusP_ln * minusC_lj * minusP_il * minusP_kl)/
(kl * (ik + il + kl) * plusP_kn) -
(Complex(0,2) * plusP_jn * minusC_ij * minusP_jk * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ln) -
(Complex(0,2) * plusP_jn * minusC_ij * minusP_jl * minusP_kl)/
(kl * (jk + jl + kl) * plusP_kn) -
(Complex(0,2) * sqr(plusP_jn) * minusC_il * minusP_jl * minusP_kl)/
(jl * (jk + jl + kl) * plusP_kn * plusP_ln) -
(Complex(0,2) * plusP_jn * minusC_ik * sqr(minusP_kl))/
(kl * (jk + jl + kl) * plusP_kn) +
(Complex(0,2) * plusP_jn * minusC_il * sqr(minusP_kl))/
(kl * (jk + jl + kl) * plusP_ln);
}
return czero;
}
LorentzVector<Complex> MatchboxCurrents::qqbarggFixedLeftCurrent(const int i, const int,
const int j, const int,
const int k, const int g1Hel,
const int l, const int g2Hel) {
const double ik = invariant(i,k);
const double il = invariant(i,l);
const double jk = invariant(j,k);
const double jl = invariant(j,l);
const double kl = invariant(k,l);
const Complex plusP_ij = plusProduct(i,j);
const Complex plusP_ik = plusProduct(i,k);
const Complex plusP_il = plusProduct(i,l);
const Complex plusP_jk = plusProduct(j,k);
const Complex plusP_jl = plusProduct(j,l);
const Complex plusP_kl = plusProduct(k,l);
const Complex minusP_ij = minusProduct(i,j);
const Complex minusP_ik = minusProduct(i,k);
const Complex minusP_il = minusProduct(i,l);
const Complex minusP_jk = minusProduct(j,k);
const Complex minusP_jl = minusProduct(j,l);
const Complex minusP_kl = minusProduct(k,l);
const LorentzVector<Complex> & minusC_ij = minusCurrent(i,j);
const LorentzVector<Complex> & minusC_ik = minusCurrent(i,k);
const LorentzVector<Complex> & minusC_il = minusCurrent(i,l);
const LorentzVector<Complex> & minusC_kj = minusCurrent(k,j);
const LorentzVector<Complex> & minusC_kl = minusCurrent(k,l);
const LorentzVector<Complex> & minusC_lj = minusCurrent(l,j);
if ( g1Hel == 1 && g2Hel == 1 ) {
return
(Complex(0,-2) * plusP_jl * plusP_kl * minusC_ik)/
(jl * (jk + jl + kl)) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_ik)/
(kl * (jk + jl + kl)) -
(Complex(0,2) * plusP_jk * plusP_kl * minusC_il)/
(kl * (jk + jl + kl)) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_ij * minusP_ij)/
(jl * (jk + jl + kl) * minusP_ik) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_ij * minusP_ij)/
(kl * (jk + jl + kl) * minusP_ik) +
(Complex(0,2) * plusP_jk * plusP_jl * minusC_il * minusP_ij)/
(jl * (jk + jl + kl) * minusP_ik) -
(Complex(0,2) * plusP_jk * plusP_kl * minusC_ij * minusP_ij)/
(kl * (jk + jl + kl) * minusP_il) +
(Complex(0,2) * plusP_jk * plusP_jl * minusC_ik * minusP_ij)/
(jl * (jk + jl + kl) * minusP_il) +
(Complex(0,2) * plusP_jk * plusP_jl * minusC_ij * sqr(minusP_ij))/
(jl * (jk + jl + kl) * minusP_ik * minusP_il) -
(Complex(0,2) * plusP_jk * plusP_kl * minusC_ik * minusP_ik)/
(kl * (jk + jl + kl) * minusP_il) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_il * minusP_il)/
(jl * (jk + jl + kl) * minusP_ik) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_il * minusP_il)/
(kl * (jk + jl + kl) * minusP_ik);
}
if ( g1Hel == 1 && g2Hel == -1 ) {
return
(Complex(0,-1) * sqr(plusP_ik) * minusC_ij * minusP_il)/
(kl * (ik + il + kl) * plusP_il) +
(Complex(0,1) * plusP_ik * plusP_kl * minusC_lj * minusP_il)/
(kl * (ik + il + kl) * plusP_il) +
(Complex(0,1) * plusP_ik * minusC_ij * sqr(minusP_il))/
(kl * (ik + il + kl) * minusP_ik) -
(Complex(0,1) * plusP_ik * plusP_kl * minusC_kj * sqr(minusP_il))/
(kl * (ik + il + kl) * plusP_il * minusP_ik) -
(Complex(0,2) * plusP_kl * minusC_lj * sqr(minusP_il))/
(kl * (ik + il + kl) * minusP_ik) +
(Complex(0,1) * plusP_ik * plusP_jk * minusC_ij * minusP_il * minusP_jk)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) -
(Complex(0,2) * plusP_ij * plusP_jk * minusC_ik * minusP_jl)/
(jl * (jk + jl + kl) * plusP_il) -
(Complex(0,2) * plusP_ij * plusP_jk * minusC_ij * minusP_ij * minusP_jl)/
(jl * (jk + jl + kl) * plusP_il * minusP_ik) -
(Complex(0,1) * plusP_ik * plusP_jl * minusC_ij * minusP_il * minusP_jl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) +
(Complex(0,2) * plusP_ij * plusP_kl * minusC_ij * minusP_il * minusP_jl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) -
(Complex(0,2) * plusP_ij * plusP_jk * minusC_il * minusP_il * minusP_jl)/
(jl * (jk + jl + kl) * plusP_il * minusP_ik) +
(Complex(0,2) * plusP_ik * plusP_jk * minusC_ik * minusP_kl)/
(kl * (jk + jl + kl) * plusP_il) +
(Complex(0,2) * plusP_ik * plusP_jk * minusC_ij * minusP_ij * minusP_kl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) -
(Complex(0,1) * plusP_ik * plusP_jl * minusC_ik * minusP_il * minusP_kl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) +
(Complex(0,2) * plusP_ij * plusP_kl * minusC_ik * minusP_il * minusP_kl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) +
(Complex(0,1) * plusP_ik * plusP_jk * minusC_il * minusP_il * minusP_kl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik);
}
if ( g1Hel == -1 && g2Hel == 1 ) {
return
(Complex(0,1) * sqr(plusP_il) * minusC_ij * minusP_ik)/
(kl * (ik + il + kl) * plusP_ik) +
(Complex(0,1) * plusP_il * plusP_kl * minusC_kj * minusP_ik)/
(kl * (ik + il + kl) * plusP_ik) +
(Complex(0,2) * plusP_jl * minusC_kl * minusP_ik)/(ik * jl) +
(Complex(0,2) * plusP_jl * minusC_kj * minusP_ij * minusP_ik)/
(ik * jl * minusP_il) -
(Complex(0,2) * plusP_il * minusC_ij * sqr(minusP_ik))/
(ik * (ik + il + kl) * minusP_il) -
(Complex(0,1) * plusP_il * minusC_ij * sqr(minusP_ik))/
(kl * (ik + il + kl) * minusP_il) -
(Complex(0,2) * plusP_kl * minusC_kj * sqr(minusP_ik))/
(ik * (ik + il + kl) * minusP_il) -
(Complex(0,2) * plusP_kl * minusC_kj * sqr(minusP_ik))/
(kl * (ik + il + kl) * minusP_il) -
(Complex(0,1) * plusP_il * plusP_kl * minusC_lj * sqr(minusP_ik))/
(kl * (ik + il + kl) * plusP_ik * minusP_il) -
(Complex(0,2) * plusP_il * plusP_jl * minusC_ij * minusP_jk)/
(jl * (jk + jl + kl) * plusP_ik) -
(Complex(0,2) * plusP_ij * plusP_jl * minusC_ij * minusP_ij * minusP_jk)/
(jl * (jk + jl + kl) * plusP_ik * minusP_il) +
(Complex(0,1) * plusP_il * plusP_jk * minusC_ij * minusP_ik * minusP_jk)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) +
(Complex(0,2) * plusP_ij * plusP_kl * minusC_ij * minusP_ik * minusP_jk)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) -
(Complex(0,1) * plusP_il * plusP_jl * minusC_ij * minusP_ik * minusP_jl)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) +
(Complex(0,2) * plusP_il * plusP_jl * minusC_il * minusP_kl)/
(jl * (jk + jl + kl) * plusP_ik) +
(Complex(0,2) * plusP_il * plusP_jl * minusC_il * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ik) +
(Complex(0,2) * plusP_il * plusP_jl * minusC_ij * minusP_ij * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) +
(Complex(0,2) * plusP_ij * plusP_jl * minusC_il * minusP_ij * minusP_kl)/
(jl * (jk + jl + kl) * plusP_ik * minusP_il) +
(Complex(0,1) * plusP_il * plusP_jl * minusC_ik * minusP_ik * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) -
(Complex(0,1) * plusP_il * plusP_jk * minusC_il * minusP_ik * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) -
(Complex(0,2) * plusP_ij * plusP_kl * minusC_il * minusP_ik * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il);
}
if ( g1Hel == -1 && g2Hel == -1 ) {
return
(Complex(0,-2) * plusP_ij * minusC_kj * minusP_ik * minusP_jl)/
(ik * jl * plusP_il) +
(Complex(0,2) * sqr(plusP_ij) * minusC_ij * minusP_jk * minusP_jl)/
(jl * (jk + jl + kl) * plusP_ik * plusP_il) +
(Complex(0,2) * plusP_ik * minusC_kj * minusP_ik * minusP_kl)/
(ik * (ik + il + kl) * plusP_il) +
(Complex(0,2) * plusP_ik * minusC_kj * minusP_ik * minusP_kl)/
(kl * (ik + il + kl) * plusP_il) +
(Complex(0,2) * minusC_lj * minusP_ik * minusP_kl)/
(ik * (ik + il + kl)) +
(Complex(0,2) * minusC_lj * minusP_ik * minusP_kl)/
(kl * (ik + il + kl)) +
(Complex(0,2) * minusC_kj * minusP_il * minusP_kl)/
(kl * (ik + il + kl)) +
(Complex(0,2) * plusP_il * minusC_lj * minusP_il * minusP_kl)/
(kl * (ik + il + kl) * plusP_ik) -
(Complex(0,2) * plusP_ij * minusC_ij * minusP_jk * minusP_kl)/
(kl * (jk + jl + kl) * plusP_il) -
(Complex(0,2) * plusP_ij * minusC_ij * minusP_jl * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ik) -
(Complex(0,2) * sqr(plusP_ij) * minusC_il * minusP_jl * minusP_kl)/
(jl * (jk + jl + kl) * plusP_ik * plusP_il) -
(Complex(0,2) * plusP_ij * minusC_ik * sqr(minusP_kl))/
(kl * (jk + jl + kl) * plusP_ik) +
(Complex(0,2) * plusP_ij * minusC_il * sqr(minusP_kl))/
(kl * (jk + jl + kl) * plusP_il);
}
return czero;
}
LorentzVector<Complex> MatchboxCurrents::qqbarggGeneralRightCurrent(const int i, const int,
const int j, const int,
const int k, const int g1Hel,
const int l, const int g2Hel,
const int n) {
const double ik = invariant(i,k);
const double il = invariant(i,l);
const double jk = invariant(j,k);
const double jl = invariant(j,l);
const double kl = invariant(k,l);
const Complex plusP_ik = plusProduct(i,k);
const Complex plusP_il = plusProduct(i,l);
const Complex plusP_in = plusProduct(i,n);
const Complex plusP_jk = plusProduct(j,k);
const Complex plusP_jl = plusProduct(j,l);
const Complex plusP_jn = plusProduct(j,n);
const Complex plusP_kl = plusProduct(k,l);
const Complex plusP_kn = plusProduct(k,n);
const Complex plusP_ln = plusProduct(l,n);
const Complex minusP_ik = minusProduct(i,k);
const Complex minusP_il = minusProduct(i,l);
const Complex minusP_in = minusProduct(i,n);
const Complex minusP_jk = minusProduct(j,k);
const Complex minusP_jl = minusProduct(j,l);
const Complex minusP_jn = minusProduct(j,n);
const Complex minusP_kl = minusProduct(k,l);
const Complex minusP_kn = minusProduct(k,n);
const Complex minusP_ln = minusProduct(l,n);
const LorentzVector<Complex> & minusC_ji = minusCurrent(j,i);
const LorentzVector<Complex> & minusC_jk = minusCurrent(j,k);
const LorentzVector<Complex> & minusC_jl = minusCurrent(j,l);
const LorentzVector<Complex> & minusC_ki = minusCurrent(k,i);
const LorentzVector<Complex> & minusC_li = minusCurrent(l,i);
const LorentzVector<Complex> & minusC_lk = minusCurrent(l,k);
if ( g1Hel == 1 && g2Hel == 1 ) {
return
(Complex(0,2) * plusP_il * plusP_kl * minusC_jk)/
(kl * (ik + il + kl)) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_jl)/
(ik * (ik + il + kl)) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_jl)/
(kl * (ik + il + kl)) +
(Complex(0,2) * plusP_il * plusP_kl * minusC_ji * minusP_in)/
(kl * (ik + il + kl) * minusP_kn) +
(Complex(0,2) * plusP_ik * plusP_il * minusC_jl * minusP_in)/
(ik * (ik + il + kl) * minusP_kn) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_ji * minusP_jn)/
(kl * (jk + jl + kl) * minusP_kn) -
(Complex(0,2) * sqr(plusP_kl) * minusC_ki * minusP_jn)/
(kl * (jk + jl + kl) * minusP_kn) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_ji * minusP_in)/
(ik * (ik + il + kl) * minusP_ln) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_ji * minusP_in)/
(kl * (ik + il + kl) * minusP_ln) +
(Complex(0,2) * plusP_ik * plusP_il * minusC_jk * minusP_in)/
(ik * (ik + il + kl) * minusP_ln) -
(Complex(0,2) * plusP_jk * plusP_kl * minusC_ji * minusP_jn)/
(kl * (jk + jl + kl) * minusP_ln) -
(Complex(0,2) * plusP_ik * plusP_jl * minusC_jk * minusP_jn)/
(ik * jl * minusP_ln) +
(Complex(0,2) * sqr(plusP_kl) * minusC_li * minusP_jn)/
(kl * (jk + jl + kl) * minusP_ln) +
(Complex(0,2) * plusP_ik * plusP_il * minusC_ji * sqr(minusP_in))/
(ik * (ik + il + kl) * minusP_kn * minusP_ln) -
(Complex(0,2) * plusP_ik * plusP_jl * minusC_ji * minusP_in * minusP_jn)/
(ik * jl * minusP_kn * minusP_ln) +
(Complex(0,2) * plusP_jk * plusP_jl * minusC_ji * sqr(minusP_jn))/
(jl * (jk + jl + kl) * minusP_kn * minusP_ln) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_li * sqr(minusP_jn))/
(jl * (jk + jl + kl) * minusP_kn * minusP_ln) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_jk * minusP_kn)/
(ik * (ik + il + kl) * minusP_ln) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_jk * minusP_kn)/
(kl * (ik + il + kl) * minusP_ln) +
(Complex(0,2) * plusP_il * plusP_kl * minusC_jl * minusP_ln)/
(kl * (ik + il + kl) * minusP_kn);
}
if ( g1Hel == 1 && g2Hel == -1 ) {
return
(Complex(0,-2) * plusP_ik * plusP_kn * minusC_ji * minusP_il)/
(ik * (ik + il + kl) * plusP_ln) +
(Complex(0,2) * plusP_ik * plusP_jn * minusC_jk * minusP_jl)/
(ik * jl * plusP_ln) +
(Complex(0,2) * plusP_ik * minusC_lk * minusP_jl)/(ik * jl) -
(Complex(0,2) * plusP_ik * plusP_kn * minusC_jk * minusP_kl)/
(ik * (ik + il + kl) * plusP_ln) -
(Complex(0,2) * plusP_ik * plusP_kn * minusC_jk * minusP_kl)/
(kl * (ik + il + kl) * plusP_ln) -
(Complex(0,2) * plusP_ik * plusP_in * minusC_ji * minusP_il * minusP_in)/
(ik * (ik + il + kl) * plusP_ln * minusP_kn) +
(Complex(0,2) * plusP_ik * plusP_jn * minusC_ji * minusP_in * minusP_jl)/
(ik * jl * plusP_ln * minusP_kn) +
(Complex(0,2) * plusP_ik * minusC_li * minusP_in * minusP_jl)/
(ik * jl * minusP_kn) -
(Complex(0,2) * plusP_jk * plusP_jn * minusC_ji * minusP_jl * minusP_jn)/
(jl * (jk + jl + kl) * plusP_ln * minusP_kn) +
(Complex(0,2) * plusP_jn * plusP_kl * minusC_li * minusP_jl * minusP_jn)/
(jl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_ik * plusP_kn * minusC_ji * minusP_in * minusP_kl)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_ik * plusP_in * minusC_jk * minusP_in * minusP_kl)/
(ik * (ik + il + kl) * plusP_ln * minusP_kn) +
(Complex(0,2) * plusP_jk * plusP_kn * minusC_ji * minusP_jn * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_kl * plusP_kn * minusC_li * minusP_jn * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,1) * plusP_ik * plusP_kn * minusC_ji * minusP_ik * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_in * plusP_kl * minusC_ji * minusP_il * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) +
(Complex(0,1) * plusP_il * plusP_kn * minusC_ji * minusP_il * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) +
(Complex(0,1) * plusP_jk * plusP_kn * minusC_ji * minusP_jk * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,1) * plusP_kl * plusP_kn * minusC_li * minusP_jk * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,2) * plusP_jk * minusC_ji * minusP_jl * minusP_ln)/
(jl * (jk + jl + kl) * minusP_kn) +
(Complex(0,2) * plusP_jn * plusP_kl * minusC_ji * minusP_jl * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) -
(Complex(0,1) * plusP_jl * plusP_kn * minusC_ji * minusP_jl * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) +
(Complex(0,1) * plusP_kl * plusP_kn * minusC_ki * minusP_jl * minusP_ln)/
(kl * (jk + jl + kl) * plusP_ln * minusP_kn) +
(Complex(0,2) * plusP_kl * minusC_li * minusP_jl * minusP_ln)/
(jl * (jk + jl + kl) * minusP_kn) +
(Complex(0,2) * plusP_kl * minusC_li * minusP_jl * minusP_ln)/
(kl * (jk + jl + kl) * minusP_kn) -
(Complex(0,2) * plusP_in * plusP_kl * minusC_jk * minusP_kl * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) +
(Complex(0,1) * plusP_il * plusP_kn * minusC_jk * minusP_kl * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn) -
(Complex(0,1) * plusP_ik * plusP_kn * minusC_jl * minusP_kl * minusP_ln)/
(kl * (ik + il + kl) * plusP_ln * minusP_kn);
}
if ( g1Hel == -1 && g2Hel == 1 ) {
return
(Complex(0,-2) * plusP_il * plusP_in * minusC_jl * minusP_ik)/
(ik * (ik + il + kl) * plusP_kn) -
(Complex(0,2) * plusP_il * plusP_ln * minusC_jl * minusP_kl)/
(kl * (ik + il + kl) * plusP_kn) -
(Complex(0,2) * plusP_il * plusP_in * minusC_ji * minusP_ik * minusP_in)/
(ik * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_in * plusP_jl * minusC_ji * minusP_ik * minusP_jn)/
(ik * jl * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_jl * plusP_jn * minusC_ji * minusP_jk * minusP_jn)/
(jl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_jl * minusC_ki * minusP_jk * minusP_jn)/
(jl * (jk + jl + kl) * minusP_ln) -
(Complex(0,2) * plusP_jl * plusP_ln * minusC_li * minusP_jk * minusP_jn)/
(jl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_il * plusP_ln * minusC_ji * minusP_in * minusP_kl)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_jl * plusP_ln * minusC_ji * minusP_jn * minusP_kl)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_kl * plusP_ln * minusC_ki * minusP_jn * minusP_kl)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_in * plusP_kl * minusC_ji * minusP_ik * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) -
(Complex(0,1) * plusP_ik * plusP_ln * minusC_ji * minusP_ik * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) -
(Complex(0,2) * plusP_il * plusP_in * minusC_jk * minusP_ik * minusP_kn)/
(ik * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,1) * plusP_il * plusP_ln * minusC_ji * minusP_il * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_jn * plusP_kl * minusC_ji * minusP_jk * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) +
(Complex(0,1) * plusP_jk * plusP_ln * minusC_ji * minusP_jk * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_kl * minusC_ki * minusP_jk * minusP_kn)/
(kl * (jk + jl + kl) * minusP_ln) +
(Complex(0,1) * plusP_kl * plusP_ln * minusC_li * minusP_jk * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,1) * plusP_jl * plusP_ln * minusC_ji * minusP_jl * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,1) * plusP_kl * plusP_ln * minusC_ki * minusP_jl * minusP_kn)/
(kl * (jk + jl + kl) * plusP_kn * minusP_ln) -
(Complex(0,1) * plusP_il * plusP_ln * minusC_jk * minusP_kl * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,2) * plusP_in * plusP_kl * minusC_jl * minusP_kl * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln) +
(Complex(0,1) * plusP_ik * plusP_ln * minusC_jl * minusP_kl * minusP_kn)/
(kl * (ik + il + kl) * plusP_kn * minusP_ln);
}
if ( g1Hel == -1 && g2Hel == -1 ) {
return
(Complex(0,2) * sqr(plusP_in) * minusC_ji * minusP_ik * minusP_il)/
(ik * (ik + il + kl) * plusP_kn * plusP_ln) -
(Complex(0,2) * plusP_in * plusP_jn * minusC_ji * minusP_ik * minusP_jl)/
(ik * jl * plusP_kn * plusP_ln) -
(Complex(0,2) * plusP_in * minusC_li * minusP_ik * minusP_jl)/
(ik * jl * plusP_kn) +
(Complex(0,2) * sqr(plusP_jn) * minusC_ji * minusP_jk * minusP_jl)/
(jl * (jk + jl + kl) * plusP_kn * plusP_ln) +
(Complex(0,2) * plusP_jn * minusC_ki * minusP_jk * minusP_jl)/
(jl * (jk + jl + kl) * plusP_ln) +
(Complex(0,2) * plusP_jn * minusC_li * minusP_jk * minusP_jl)/
(jl * (jk + jl + kl) * plusP_kn) +
(Complex(0,2) * plusP_in * minusC_ji * minusP_ik * minusP_kl)/
(kl * (ik + il + kl) * plusP_ln) +
(Complex(0,2) * sqr(plusP_in) * minusC_jk * minusP_ik * minusP_kl)/
(ik * (ik + il + kl) * plusP_kn * plusP_ln) +
(Complex(0,2) * plusP_in * minusC_ji * minusP_il * minusP_kl)/
(kl * (ik + il + kl) * plusP_kn) -
(Complex(0,2) * plusP_jn * minusC_ji * minusP_jk * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ln) -
(Complex(0,2) * plusP_kn * minusC_ki * minusP_jk * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ln) -
(Complex(0,2) * minusC_li * minusP_jk * minusP_kl)/
(kl * (jk + jl + kl)) -
(Complex(0,2) * plusP_jn * minusC_ji * minusP_jl * minusP_kl)/
(jl * (jk + jl + kl) * plusP_kn) -
(Complex(0,2) * plusP_jn * minusC_ji * minusP_jl * minusP_kl)/
(kl * (jk + jl + kl) * plusP_kn) -
(Complex(0,2) * minusC_ki * minusP_jl * minusP_kl)/
(jl * (jk + jl + kl)) -
(Complex(0,2) * minusC_ki * minusP_jl * minusP_kl)/
(kl * (jk + jl + kl)) -
(Complex(0,2) * plusP_ln * minusC_li * minusP_jl * minusP_kl)/
(jl * (jk + jl + kl) * plusP_kn) -
(Complex(0,2) * plusP_ln * minusC_li * minusP_jl * minusP_kl)/
(kl * (jk + jl + kl) * plusP_kn) +
(Complex(0,2) * plusP_in * minusC_jk * sqr(minusP_kl))/
(kl * (ik + il + kl) * plusP_kn) -
(Complex(0,2) * plusP_in * minusC_jl * sqr(minusP_kl))/
(kl * (ik + il + kl) * plusP_ln);
}
return czero;
}
LorentzVector<Complex> MatchboxCurrents::qqbarggFixedRightCurrent(const int i, const int,
const int j, const int,
const int k, const int g1Hel,
const int l, const int g2Hel) {
const double ik = invariant(i,k);
const double il = invariant(i,l);
const double jk = invariant(j,k);
const double jl = invariant(j,l);
const double kl = invariant(k,l);
const Complex plusP_ij = plusProduct(i,j);
const Complex plusP_ik = plusProduct(i,k);
const Complex plusP_il = plusProduct(i,l);
const Complex plusP_jk = plusProduct(j,k);
const Complex plusP_jl = plusProduct(j,l);
const Complex plusP_kl = plusProduct(k,l);
const Complex minusP_ij = minusProduct(i,j);
const Complex minusP_ik = minusProduct(i,k);
const Complex minusP_il = minusProduct(i,l);
const Complex minusP_jk = minusProduct(j,k);
const Complex minusP_jl = minusProduct(j,l);
const Complex minusP_kl = minusProduct(k,l);
const LorentzVector<Complex> & minusC_ji = minusCurrent(j,i);
const LorentzVector<Complex> & minusC_jk = minusCurrent(j,k);
const LorentzVector<Complex> & minusC_jl = minusCurrent(j,l);
const LorentzVector<Complex> & minusC_ki = minusCurrent(k,i);
const LorentzVector<Complex> & minusC_li = minusCurrent(l,i);
const LorentzVector<Complex> & minusC_lk = minusCurrent(l,k);
if ( g1Hel == 1 && g2Hel == 1 ) {
return
(Complex(0,2) * plusP_il * plusP_kl * minusC_jk)/
(kl * (ik + il + kl)) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_jl)/
(ik * (ik + il + kl)) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_jl)/
(kl * (ik + il + kl)) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_ji * minusP_ij)/
(kl * (jk + jl + kl) * minusP_ik) -
(Complex(0,2) * sqr(plusP_kl) * minusC_ki * minusP_ij)/
(kl * (jk + jl + kl) * minusP_ik) -
(Complex(0,2) * plusP_jk * plusP_kl * minusC_ji * minusP_ij)/
(kl * (jk + jl + kl) * minusP_il) -
(Complex(0,2) * plusP_ik * plusP_jl * minusC_jk * minusP_ij)/
(ik * jl * minusP_il) +
(Complex(0,2) * sqr(plusP_kl) * minusC_li * minusP_ij)/
(kl * (jk + jl + kl) * minusP_il) +
(Complex(0,2) * plusP_jk * plusP_jl * minusC_ji * sqr(minusP_ij))/
(jl * (jk + jl + kl) * minusP_ik * minusP_il) -
(Complex(0,2) * plusP_jl * plusP_kl * minusC_li * sqr(minusP_ij))/
(jl * (jk + jl + kl) * minusP_ik * minusP_il) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_jk * minusP_ik)/
(ik * (ik + il + kl) * minusP_il) +
(Complex(0,2) * plusP_ik * plusP_kl * minusC_jk * minusP_ik)/
(kl * (ik + il + kl) * minusP_il) +
(Complex(0,2) * plusP_il * plusP_kl * minusC_jl * minusP_il)/
(kl * (ik + il + kl) * minusP_ik);
}
if ( g1Hel == 1 && g2Hel == -1 ) {
return
(Complex(0,-2) * sqr(plusP_ik) * minusC_ji * minusP_il)/
(ik * (ik + il + kl) * plusP_il) -
(Complex(0,1) * sqr(plusP_ik) * minusC_ji * minusP_il)/
(kl * (ik + il + kl) * plusP_il) +
(Complex(0,1) * plusP_ik * minusC_ji * sqr(minusP_il))/
(kl * (ik + il + kl) * minusP_ik) +
(Complex(0,1) * plusP_ik * plusP_jk * minusC_ji * minusP_il * minusP_jk)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) -
(Complex(0,1) * plusP_ik * plusP_kl * minusC_li * minusP_il * minusP_jk)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) +
(Complex(0,2) * plusP_ij * plusP_ik * minusC_jk * minusP_jl)/
(ik * jl * plusP_il) +
(Complex(0,2) * plusP_ik * minusC_lk * minusP_jl)/(ik * jl) -
(Complex(0,2) * plusP_ij * plusP_jk * minusC_ji * minusP_ij * minusP_jl)/
(jl * (jk + jl + kl) * plusP_il * minusP_ik) +
(Complex(0,2) * plusP_ij * plusP_kl * minusC_li * minusP_ij * minusP_jl)/
(jl * (jk + jl + kl) * plusP_il * minusP_ik) -
(Complex(0,2) * plusP_jk * minusC_ji * minusP_il * minusP_jl)/
(jl * (jk + jl + kl) * minusP_ik) -
(Complex(0,1) * plusP_ik * plusP_jl * minusC_ji * minusP_il * minusP_jl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) +
(Complex(0,2) * plusP_ij * plusP_kl * minusC_ji * minusP_il * minusP_jl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) +
(Complex(0,1) * plusP_ik * plusP_kl * minusC_ki * minusP_il * minusP_jl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) +
(Complex(0,2) * plusP_kl * minusC_li * minusP_il * minusP_jl)/
(jl * (jk + jl + kl) * minusP_ik) +
(Complex(0,2) * plusP_kl * minusC_li * minusP_il * minusP_jl)/
(kl * (jk + jl + kl) * minusP_ik) -
(Complex(0,2) * sqr(plusP_ik) * minusC_jk * minusP_kl)/
(ik * (ik + il + kl) * plusP_il) -
(Complex(0,2) * sqr(plusP_ik) * minusC_jk * minusP_kl)/
(kl * (ik + il + kl) * plusP_il) +
(Complex(0,2) * plusP_ik * plusP_jk * minusC_ji * minusP_ij * minusP_kl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) -
(Complex(0,2) * plusP_ik * plusP_kl * minusC_li * minusP_ij * minusP_kl)/
(kl * (jk + jl + kl) * plusP_il * minusP_ik) +
(Complex(0,1) * plusP_ik * minusC_jk * minusP_il * minusP_kl)/
(kl * (ik + il + kl) * minusP_ik) -
(Complex(0,1) * sqr(plusP_ik) * minusC_jl * minusP_il * minusP_kl)/
(kl * (ik + il + kl) * plusP_il * minusP_ik);
}
if ( g1Hel == -1 && g2Hel == 1 ) {
return
(Complex(0,1) * sqr(plusP_il) * minusC_ji * minusP_ik)/
(kl * (ik + il + kl) * plusP_ik) -
(Complex(0,1) * plusP_il * minusC_ji * sqr(minusP_ik))/
(kl * (ik + il + kl) * minusP_il) -
(Complex(0,2) * plusP_ij * plusP_jl * minusC_ji * minusP_ij * minusP_jk)/
(jl * (jk + jl + kl) * plusP_ik * minusP_il) -
(Complex(0,2) * plusP_jl * minusC_ki * minusP_ij * minusP_jk)/
(jl * (jk + jl + kl) * minusP_il) -
(Complex(0,2) * plusP_il * plusP_jl * minusC_li * minusP_ij * minusP_jk)/
(jl * (jk + jl + kl) * plusP_ik * minusP_il) +
(Complex(0,1) * plusP_il * plusP_jk * minusC_ji * minusP_ik * minusP_jk)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) +
(Complex(0,2) * plusP_ij * plusP_kl * minusC_ji * minusP_ik * minusP_jk)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) +
(Complex(0,2) * plusP_kl * minusC_ki * minusP_ik * minusP_jk)/
(kl * (jk + jl + kl) * minusP_il) +
(Complex(0,1) * plusP_il * plusP_kl * minusC_li * minusP_ik * minusP_jk)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) -
(Complex(0,1) * plusP_il * plusP_jl * minusC_ji * minusP_ik * minusP_jl)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) -
(Complex(0,1) * plusP_il * plusP_kl * minusC_ki * minusP_ik * minusP_jl)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) -
(Complex(0,2) * sqr(plusP_il) * minusC_jl * minusP_kl)/
(kl * (ik + il + kl) * plusP_ik) +
(Complex(0,2) * plusP_il * plusP_jl * minusC_ji * minusP_ij * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) +
(Complex(0,2) * plusP_il * plusP_kl * minusC_ki * minusP_ij * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ik * minusP_il) -
(Complex(0,1) * sqr(plusP_il) * minusC_jk * minusP_ik * minusP_kl)/
(kl * (ik + il + kl) * plusP_ik * minusP_il) +
(Complex(0,1) * plusP_il * minusC_jl * minusP_ik * minusP_kl)/
(kl * (ik + il + kl) * minusP_il);
}
if ( g1Hel == -1 && g2Hel == -1 ) {
return
(Complex(0,2) * sqr(plusP_ij) * minusC_ji * minusP_jk * minusP_jl)/
(jl * (jk + jl + kl) * plusP_ik * plusP_il) +
(Complex(0,2) * plusP_ij * minusC_ki * minusP_jk * minusP_jl)/
(jl * (jk + jl + kl) * plusP_il) +
(Complex(0,2) * plusP_ij * minusC_li * minusP_jk * minusP_jl)/
(jl * (jk + jl + kl) * plusP_ik) -
(Complex(0,2) * plusP_ij * minusC_ji * minusP_jk * minusP_kl)/
(kl * (jk + jl + kl) * plusP_il) -
(Complex(0,2) * plusP_ik * minusC_ki * minusP_jk * minusP_kl)/
(kl * (jk + jl + kl) * plusP_il) -
(Complex(0,2) * minusC_li * minusP_jk * minusP_kl)/
(kl * (jk + jl + kl)) -
(Complex(0,2) * plusP_ij * minusC_ji * minusP_jl * minusP_kl)/
(jl * (jk + jl + kl) * plusP_ik) -
(Complex(0,2) * plusP_ij * minusC_ji * minusP_jl * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ik) -
(Complex(0,2) * minusC_ki * minusP_jl * minusP_kl)/
(jl * (jk + jl + kl)) -
(Complex(0,2) * minusC_ki * minusP_jl * minusP_kl)/
(kl * (jk + jl + kl)) -
(Complex(0,2) * plusP_il * minusC_li * minusP_jl * minusP_kl)/
(jl * (jk + jl + kl) * plusP_ik) -
(Complex(0,2) * plusP_il * minusC_li * minusP_jl * minusP_kl)/
(kl * (jk + jl + kl) * plusP_ik);
}
return czero;
}
const LorentzVector<Complex>& MatchboxCurrents::qqbarggLeftCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g1, const int g1Hel,
const int g2, const int g2Hel) {
if ( qHel != 1 || qbarHel != 1 )
return czero;
if ( getCurrent(hash<3>(1,1,q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel)) ) {
#ifdef CHECK_MatchboxCurrents
LorentzVector<Complex> ni = qqbarggGeneralLeftCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel,q);
LorentzVector<Complex> nj = qqbarggGeneralLeftCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel,qbar);
LorentzVector<Complex> nl = qqbarggGeneralLeftCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel,0);
LorentzVector<Complex> nlbar = qqbarggGeneralLeftCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel,1);
LorentzVector<Complex> fixed = qqbarggFixedLeftCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel);
LorentzVector<Complex> x1 = fixed - ni;
LorentzVector<Complex> x2 = fixed - nj;
LorentzVector<Complex> x3 = fixed - nl;
LorentzVector<Complex> x4 = fixed - nlbar;
double c1 =
real(x1.t() * conj(x1.t())) + real(x1.x() * conj(x1.x())) + real(x1.y() * conj(x1.y())) + real(x1.z() * conj(x1.z()));
double c2 =
real(x2.t() * conj(x2.t())) + real(x2.x() * conj(x2.x())) + real(x2.y() * conj(x2.y())) + real(x2.z() * conj(x2.z()));
double c3 =
real(x3.t() * conj(x3.t())) + real(x3.x() * conj(x3.x())) + real(x3.y() * conj(x3.y())) + real(x3.z() * conj(x3.z()));
double c4 =
real(x4.t() * conj(x4.t())) + real(x4.x() * conj(x4.x())) + real(x4.y() * conj(x4.y())) + real(x4.z() * conj(x4.z()));
ostream& ncheck = checkStream("qqbarggLeftCurrentNChoice");
ncheck << (c1 != 0. ? log10(abs(c1)) : 0.) << " "
<< (c2 != 0. ? log10(abs(c2)) : 0.) << " "
<< (c3 != 0. ? log10(abs(c3)) : 0.) << " "
<< (c4 != 0. ? log10(abs(c4)) : 0.) << " "
<< "\n" << flush;
#endif
cacheCurrent(qqbarggFixedLeftCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel));
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbarggLeftCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(g1)+momentum(g2));
#endif
return cachedCurrent();
}
const LorentzVector<Complex>& MatchboxCurrents::qqbarggRightCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g1, const int g1Hel,
const int g2, const int g2Hel) {
if ( qHel != -1 || qbarHel != -1 )
return czero;
if ( getCurrent(hash<3>(2,1,q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel)) ) {
#ifdef CHECK_MatchboxCurrents
LorentzVector<Complex> ni = qqbarggGeneralRightCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel,q);
LorentzVector<Complex> nj = qqbarggGeneralRightCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel,qbar);
LorentzVector<Complex> nl = qqbarggGeneralRightCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel,0);
LorentzVector<Complex> nlbar = qqbarggGeneralRightCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel,1);
LorentzVector<Complex> fixed = qqbarggFixedRightCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel);
LorentzVector<Complex> x1 = fixed - ni;
LorentzVector<Complex> x2 = fixed - nj;
LorentzVector<Complex> x3 = fixed - nl;
LorentzVector<Complex> x4 = fixed - nlbar;
double c1 =
real(x1.t() * conj(x1.t())) + real(x1.x() * conj(x1.x())) + real(x1.y() * conj(x1.y())) + real(x1.z() * conj(x1.z()));
double c2 =
real(x2.t() * conj(x2.t())) + real(x2.x() * conj(x2.x())) + real(x2.y() * conj(x2.y())) + real(x2.z() * conj(x2.z()));
double c3 =
real(x3.t() * conj(x3.t())) + real(x3.x() * conj(x3.x())) + real(x3.y() * conj(x3.y())) + real(x3.z() * conj(x3.z()));
double c4 =
real(x4.t() * conj(x4.t())) + real(x4.x() * conj(x4.x())) + real(x4.y() * conj(x4.y())) + real(x4.z() * conj(x4.z()));
ostream& ncheck = checkStream("qqbarggRightCurrentNChoice");
ncheck << (c1 != 0. ? log10(abs(c1)) : 0.) << " "
<< (c2 != 0. ? log10(abs(c2)) : 0.) << " "
<< (c3 != 0. ? log10(abs(c3)) : 0.) << " "
<< (c4 != 0. ? log10(abs(c4)) : 0.) << " "
<< "\n" << flush;
#endif
cacheCurrent(qqbarggFixedRightCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,g2,g2Hel));
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbarggRightCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(g1)+momentum(g2));
#endif
return cachedCurrent();
}
const LorentzVector<Complex>& MatchboxCurrents::qqbarqqbarLeftCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int k, const int kHel,
const int kbar, const int kbarHel) {
if ( qHel != 1 || qbarHel != 1 ||
abs(kHel+kbarHel) != 2 )
return czero;
const int i = q; const int j = qbar; const int l = kbar;
const double ik = invariant(i,k);
const double il = invariant(i,l);
const double jk = invariant(j,k);
const double jl = invariant(j,l);
const double kl = invariant(k,l);
const Complex plusP_ik = plusProduct(i,k);
const Complex plusP_il = plusProduct(i,l);
const Complex plusP_kj = plusProduct(k,j);
const Complex plusP_kl = plusProduct(k,l);
const Complex plusP_lj = plusProduct(l,j);
const Complex plusP_lk = plusProduct(l,k);
const Complex minusP_ik = minusProduct(i,k);
const Complex minusP_il = minusProduct(i,l);
const Complex minusP_jk = minusProduct(j,k);
const Complex minusP_jl = minusProduct(j,l);
const Complex minusP_ki = minusProduct(k,i);
const Complex minusP_kl = minusProduct(k,l);
const Complex minusP_li = minusProduct(l,i);
const Complex minusP_lk = minusProduct(l,k);
const LorentzVector<Complex> & minusC_ij = minusCurrent(i,j);
const LorentzVector<Complex> & minusC_ik = minusCurrent(i,k);
const LorentzVector<Complex> & minusC_il = minusCurrent(i,l);
const LorentzVector<Complex> & minusC_kj = minusCurrent(k,j);
const LorentzVector<Complex> & minusC_lj = minusCurrent(l,j);
if ( kHel == 1 && kbarHel == 1 ) {
if ( getCurrent(hash<4>(1,1,q,qHel,qbar,qbarHel,k,kHel,kbar,kbarHel)) ) {
cacheCurrent((Complex(0.,-2.)/kl)*
((minusP_ki * plusP_il * minusC_ij+
minusP_ik * plusP_lk * minusC_kj)/
(kl+il+ik)-
(minusP_jk * plusP_lj * minusC_ij+
minusP_lk * plusP_lj * minusC_il)/
(kl+jl+jk)));
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbarqqbarLeftCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(k)+momentum(kbar));
#endif
return cachedCurrent();
}
if ( kHel == -1 && kbarHel == -1 ) {
if ( getCurrent(hash<4>(1,1,q,qHel,qbar,qbarHel,k,kHel,kbar,kbarHel)) ) {
cacheCurrent((Complex(0.,-2.)/kl)*
((minusP_li * plusP_ik * minusC_ij+
minusP_il * plusP_kl * minusC_lj)/
(kl+il+ik)-
(minusP_jl * plusP_kj * minusC_ij+
minusP_kl * plusP_kj * minusC_ik)/
(kl+jl+jk)));
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbarqqbarLeftCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(k)+momentum(kbar));
#endif
return cachedCurrent();
}
return czero;
}
const LorentzVector<Complex>& MatchboxCurrents::qqbarqqbarRightCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int k, const int kHel,
const int kbar, const int kbarHel) {
if ( qHel != -1 || qbarHel != -1 ||
abs(kHel+kbarHel) != 2 )
return czero;
const int i = q; const int j = qbar; const int l = kbar;
const double ik = invariant(i,k);
const double il = invariant(i,l);
const double jk = invariant(j,k);
const double jl = invariant(j,l);
const double kl = invariant(k,l);
const Complex plusP_ik = plusProduct(i,k);
const Complex plusP_il = plusProduct(i,l);
const Complex plusP_ki = plusProduct(k,i);
const Complex plusP_kj = plusProduct(k,j);
const Complex plusP_kl = plusProduct(k,l);
const Complex plusP_li = plusProduct(l,i);
const Complex plusP_lj = plusProduct(l,j);
const Complex plusP_lk = plusProduct(l,k);
const Complex minusP_jk = minusProduct(j,k);
const Complex minusP_jl = minusProduct(j,l);
const Complex minusP_ki = minusProduct(k,i);
const Complex minusP_kl = minusProduct(k,l);
const Complex minusP_li = minusProduct(l,i);
const Complex minusP_lk = minusProduct(l,k);
const LorentzVector<Complex> & minusC_ji = minusCurrent(j,i);
const LorentzVector<Complex> & minusC_jk = minusCurrent(j,k);
const LorentzVector<Complex> & minusC_jl = minusCurrent(j,l);
const LorentzVector<Complex> & minusC_ki = minusCurrent(k,i);
const LorentzVector<Complex> & minusC_li = minusCurrent(l,i);
if ( kHel == 1 && kbarHel == 1 ) {
if ( getCurrent(hash<4>(2,1,q,qHel,qbar,qbarHel,k,kHel,kbar,kbarHel)) ) {
cacheCurrent((Complex(0.,-2.)/kl)*
((minusP_ki * plusP_il * minusC_ji+
minusP_lk * plusP_li * minusC_jl)/
(kl+il+ik)-
(minusP_jk * plusP_lj * minusC_ji+
minusP_jk * plusP_lk * minusC_ki)/
(kl+jl+jk)));
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbarqqbarRightCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(k)+momentum(kbar));
#endif
return cachedCurrent();
}
if ( kHel == -1 && kbarHel == -1 ) {
if ( getCurrent(hash<4>(2,1,q,qHel,qbar,qbarHel,k,kHel,kbar,kbarHel)) ) {
cacheCurrent((Complex(0.,-2.)/kl)*
((minusP_li * plusP_ik * minusC_ji+
minusP_kl * plusP_ki * minusC_jk)/
(kl+il+ik)-
(minusP_jl * plusP_kj * minusC_ji+
minusP_jl * plusP_kl * minusC_li)/
(kl+jl+jk)));
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbarqqbarRightCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(k)+momentum(kbar));
#endif
return cachedCurrent();
}
return czero;
}
// Definition of sqrt to enable calculation of the sqrt of a negative double
inline Complex sqrt1 (double a) {
if (a > 0.) { return Complex(sqrt(a), 0.) ;}
else if (a < 0.) { return Complex(0., sqrt(abs(a))) ;}
else { return Complex(0., 0.); }
}
// Definition of sqrt to enable calculation of the sqrt of Complex arguments
inline Complex sqrt1 (Complex a) {
const double real_part = sqrt(abs(a))*cos(0.5*arg(a));
const double imag_part = sqrt(abs(a))*sin(0.5*arg(a));
return Complex(real_part, imag_part) ;
}
// Definition of log to enable continuation of the log of a negative double
inline Complex log1 (double a) {
if (a < 0.) { return Complex(log(abs(a)), Constants::pi) ;}
else { return Complex(log(a), 0.) ;}
}
// Definition of log to enable continuation of the log of a Complex argument with a negative real part
inline Complex log1 (Complex a) {
return Complex(log(abs(a)), arg(a)) ;
}
const LorentzVector<Complex>& MatchboxCurrents::qqbarLeftOneLoopCurrent(const int q, const int qHel,
const int qbar, const int qbarHel) {
// Note this cannot currently handle the case of one massive quark and one massless quark
assert( (mass(q) == 0 && mass(qbar) == 0) || (mass(q) != 0 && mass(qbar) != 0) );
// Massless quarks
if ( mass(q) == 0 && mass(qbar) == 0 ) {
if ( qHel != 1 || qbarHel != 1 )
return czero;
const LorentzVector<Complex>& tree = qqbarLeftCurrent(q,qHel,qbar,qbarHel);
if ( getCurrent(hash<1>(1,2,q,qHel,qbar,qbarHel)) ) {
cacheCurrent( 0.5*CF*( -8. - 3.*log1(-1./invariant(q,qbar)) - sqr(log1(-1./invariant(q,qbar))) ) * tree );
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbarLeftOneLoopCurrent",cachedCurrent(),momentum(q)+momentum(qbar));
#endif
return cachedCurrent();
}
// Massive quarks
else {
const LorentzVector<Complex>& momQ = momentum(q) + (sqr(mass(q))/invariant(q,qbar))*momentum(qbar);
const LorentzVector<Complex>& momQbar = momentum(qbar) + (sqr(mass(qbar))/invariant(q,qbar))*momentum(q);
const Complex s = (momQ+momQbar).dot(momQ+momQbar);
const Complex inv12 = s - sqr(mass(q)) - sqr(mass(qbar));
// Coefficient of the left-handed born-level current
const Complex coeffLeftTree = -1.0*log1(1./sqr(mass(q)))-1.0*log1(1./sqr(mass(qbar)))-4.0 + 0.5*((2.*log1(sqr(mass(q))/sqr(mass(qbar)))*(0.5*inv12+sqr(mass(q))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))-(2.*inv12*Li2(0.5-(0.25*inv12)/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))-(0.5*sqr(mass(qbar)))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(2.*inv12*Li2((0.5*(0.5*inv12+sqr(mass(q))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))-(1.*inv12*log1(-((0.5*inv12+sqr(mass(q))-1.*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))))*log1(-((1.*inv12+sqr(mass(q))+sqr(mass(qbar)))/(0.5*inv12+sqr(mass(q))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(2.*inv12*log1((2*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar))))*log1((-0.5*inv12-1.*sqr(mass(qbar))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(0.5*inv12+sqr(mass(q))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(1.*inv12*log1((1.*inv12+sqr(mass(q))+sqr(mass(qbar)))/(0.5*inv12+sqr(mass(qbar))-1.*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*log1((0.5*inv12+sqr(mass(qbar))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(0.5*inv12*sqr(log1(-((0.5*inv12+sqr(mass(q))-1.*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(0.5*inv12*sqr(log1((1.*inv12+sqr(mass(q))+sqr(mass(qbar)))/(0.5*inv12+sqr(mass(qbar))-1.*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))-(0.5*inv12*sqr(log1(-((1.*inv12+sqr(mass(q))+sqr(mass(qbar)))/(0.5*inv12+sqr(mass(q))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))-(0.5*inv12*sqr(log1((0.5*inv12+sqr(mass(qbar))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(4*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*(-0.25*(3+2*log1(1./(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))))*sqr(inv12)+sqr(mass(q))*sqr(mass(qbar))-0.5*inv12*(1.+log1(1./(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))))*(sqr(mass(q))+sqr(mass(qbar)))))/((1.*inv12+sqr(mass(q))+sqr(mass(qbar)))*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))));
// Coefficient of the right-handed born-level current
const Complex coeffRightTree = (2*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*mass(q)*mass(qbar))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)));
const LorentzVector<Complex>& leftTree = qqbarLeftCurrent(q,qHel,qbar,qbarHel);
const LorentzVector<Complex>& rightTree = qqbarRightCurrent(q,qHel,qbar,qbarHel);
if ( getCurrent(hash<1>(1,2,q,qHel,qbar,qbarHel)) ) {
if ( qHel == 1 && qbarHel == 1 ) {
cacheCurrent( 0.5*CF*( coeffLeftTree*leftTree + coeffRightTree*rightTree) );
}
if ( qHel == 1 && qbarHel == -1 ) {
// Coefficients of the left and right handed products of massive spinors
const LorentzVector<Complex>& coeffLeftProd = ( (mass(qbar)*(-2.*(momQ+momQbar)*(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))+log1(sqr(mass(q))/sqr(mass(qbar)))*(1.*inv12*(2.*momQ+momQbar)+(3.*momQ+2.*momQbar)*sqr(mass(q))+momQ*sqr(mass(qbar)))-(2.*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*(0.5*(2.*momQ+momQbar)*sqr(inv12)-momQbar*sqr(mass(q))*sqr(mass(qbar))+0.5*inv12*((5.*momQ+2.*momQbar)*sqr(mass(q))+momQ*sqr(mass(qbar)))+(2.*momQ+momQbar)*sqr(sqr(mass(q)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqr(1.*inv12+sqr(mass(q))+sqr(mass(qbar))) );
const LorentzVector<Complex>& coeffRightProd = ( (mass(q)*(2.*(momQ+momQbar)*(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))+log1(sqr(mass(q))/sqr(mass(qbar)))*(1.*inv12*(momQ+2.*momQbar)+momQbar*sqr(mass(q))+(2.*momQ+3.*momQbar)*sqr(mass(qbar)))+(2.*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*(0.5*(momQ+2.*momQbar)*sqr(inv12)-momQ*sqr(mass(q))*sqr(mass(qbar))+0.5*inv12*(momQbar*sqr(mass(q))+(2.*momQ+5.*momQbar)*sqr(mass(qbar)))+(momQ+2.*momQbar)*sqr(sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqr(1.*inv12+sqr(mass(q))+sqr(mass(qbar))) );
const Complex leftProd = Complex(0.,1.) * minusProduct(q,qbar);
const Complex rightProd = Complex(0.,1.) * mass(q)*mass(qbar)/plusProduct(q,qbar);
cacheCurrent( 0.5*CF*( coeffLeftTree*leftTree + coeffRightTree*rightTree + coeffLeftProd*leftProd + coeffRightProd*rightProd ) );
}
if ( qHel == -1 && qbarHel == 1 ){
// Coefficients of the left and right handed products of massive spinors
const LorentzVector<Complex>& coeffLeftProd = ( (mass(qbar)*(-2.*(momQ+momQbar)*(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))+log1(sqr(mass(q))/sqr(mass(qbar)))*(1.*inv12*(2.*momQ+momQbar)+(3.*momQ+2.*momQbar)*sqr(mass(q))+momQ*sqr(mass(qbar)))-(2.*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*(0.5*(2.*momQ+momQbar)*sqr(inv12)-momQbar*sqr(mass(q))*sqr(mass(qbar))+0.5*inv12*((5.*momQ+2.*momQbar)*sqr(mass(q))+momQ*sqr(mass(qbar)))+(2.*momQ+momQbar)*sqr(sqr(mass(q)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqr(1.*inv12+sqr(mass(q))+sqr(mass(qbar))) );
const LorentzVector<Complex>& coeffRightProd = ( (mass(q)*(2.*(momQ+momQbar)*(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))+log1(sqr(mass(q))/sqr(mass(qbar)))*(1.*inv12*(momQ+2.*momQbar)+momQbar*sqr(mass(q))+(2.*momQ+3.*momQbar)*sqr(mass(qbar)))+(2.*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*(0.5*(momQ+2.*momQbar)*sqr(inv12)-momQ*sqr(mass(q))*sqr(mass(qbar))+0.5*inv12*(momQbar*sqr(mass(q))+(2.*momQ+5.*momQbar)*sqr(mass(qbar)))+(momQ+2.*momQbar)*sqr(sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqr(1.*inv12+sqr(mass(q))+sqr(mass(qbar))) );
const Complex leftProd = Complex(0.,1.) * mass(q)*mass(qbar)/minusProduct(q,qbar);
const Complex rightProd = Complex(0.,1.) * plusProduct(q,qbar);
cacheCurrent( 0.5*CF*( coeffLeftTree*leftTree + coeffRightTree*rightTree + coeffLeftProd*leftProd + coeffRightProd*rightProd ) );
}
if ( qHel == -1 && qbarHel == -1 ){
cacheCurrent( 0.5*CF*( coeffLeftTree*leftTree + coeffRightTree*rightTree ) );
}
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbarLeftOneLoopCurrent",cachedCurrent(),momentum(q)+momentum(qbar));
#endif
return cachedCurrent();
}
}
const LorentzVector<Complex>& MatchboxCurrents::qqbarRightOneLoopCurrent(const int q, const int qHel,
const int qbar, const int qbarHel) {
// Note this cannot currently handle the case of one massive quark and one massless quark
assert( (mass(q) == 0 && mass(qbar) == 0) || (mass(q) != 0 && mass(qbar) != 0) );
// Massless quarks
if ( mass(q) == 0 && mass(qbar) ==0 ) {
if ( qHel != -1 || qbarHel != -1 )
return czero;
const LorentzVector<Complex>& tree = qqbarRightCurrent(q,qHel,qbar,qbarHel);
if ( getCurrent(hash<1>(2,2,q,qHel,qbar,qbarHel)) ) {
cacheCurrent( 0.5*CF*( -8. - 3.*log1(-1./invariant(q,qbar)) - sqr(log1(-1./invariant(q,qbar))) ) * tree );
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbarRightOneLoopCurrent",cachedCurrent(),momentum(q)+momentum(qbar));
#endif
return cachedCurrent();
}
// Massive quarks
else {
const LorentzVector<Complex>& momQ = momentum(q) + (sqr(mass(q))/invariant(q,qbar))*momentum(qbar);
const LorentzVector<Complex>& momQbar = momentum(qbar) + (sqr(mass(qbar))/invariant(q,qbar))*momentum(q);
const Complex s = (momQ+momQbar).dot(momQ+momQbar);
const Complex inv12 = s - sqr(mass(q)) - sqr(mass(qbar));
// Coefficient of the right-handed born-level current
const Complex coeffRightTree = -1.0*log1(1./sqr(mass(q)))-1.0*log1(1./sqr(mass(qbar)))-4.0 + 0.5*((2.*log1(sqr(mass(q))/sqr(mass(qbar)))*(0.5*inv12+sqr(mass(q))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))-(2.*inv12*Li2(0.5-(0.25*inv12)/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))-(0.5*sqr(mass(qbar)))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(2.*inv12*Li2((0.5*(0.5*inv12+sqr(mass(q))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))-(1.*inv12*log1(-((0.5*inv12+sqr(mass(q))-1.*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))))*log1(-((1.*inv12+sqr(mass(q))+sqr(mass(qbar)))/(0.5*inv12+sqr(mass(q))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(2.*inv12*log1((2*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar))))*log1((-0.5*inv12-1.*sqr(mass(qbar))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(0.5*inv12+sqr(mass(q))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(1.*inv12*log1((1.*inv12+sqr(mass(q))+sqr(mass(qbar)))/(0.5*inv12+sqr(mass(qbar))-1.*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*log1((0.5*inv12+sqr(mass(qbar))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(0.5*inv12*sqr(log1(-((0.5*inv12+sqr(mass(q))-1.*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(0.5*inv12*sqr(log1((1.*inv12+sqr(mass(q))+sqr(mass(qbar)))/(0.5*inv12+sqr(mass(qbar))-1.*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))-(0.5*inv12*sqr(log1(-((1.*inv12+sqr(mass(q))+sqr(mass(qbar)))/(0.5*inv12+sqr(mass(q))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))-(0.5*inv12*sqr(log1((0.5*inv12+sqr(mass(qbar))+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar))))/(1.*inv12+sqr(mass(q))+sqr(mass(qbar))))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))+(4*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*(-0.25*(3+2*log1(1./(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))))*sqr(inv12)+sqr(mass(q))*sqr(mass(qbar))-0.5*inv12*(1.+log1(1./(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))))*(sqr(mass(q))+sqr(mass(qbar)))))/((1.*inv12+sqr(mass(q))+sqr(mass(qbar)))*sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))));
// Coefficient of the left-handed born-level current
const Complex coeffLeftTree = (2*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*mass(q)*mass(qbar))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)));
const LorentzVector<Complex>& leftTree = qqbarLeftCurrent(q,qHel,qbar,qbarHel);
const LorentzVector<Complex>& rightTree = qqbarRightCurrent(q,qHel,qbar,qbarHel);
if ( getCurrent(hash<1>(2,2,q,qHel,qbar,qbarHel)) ) {
if ( qHel == 1 && qbarHel == 1 ) {
cacheCurrent( 0.5*CF*( coeffLeftTree*leftTree + coeffRightTree*rightTree ) );
}
if ( qHel == 1 && qbarHel == -1 ) {
// Coefficients of the right and left handed products of massive spinors
const LorentzVector<Complex>& coeffRightProd = ( (mass(qbar)*(-2.*(momQ+momQbar)*(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))+log1(sqr(mass(q))/sqr(mass(qbar)))*(1.*inv12*(2.*momQ+momQbar)+(3.*momQ+2.*momQbar)*sqr(mass(q))+momQ*sqr(mass(qbar)))-(2.*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*(0.5*(2.*momQ+momQbar)*sqr(inv12)-momQbar*sqr(mass(q))*sqr(mass(qbar))+0.5*inv12*((5.*momQ+2.*momQbar)*sqr(mass(q))+momQ*sqr(mass(qbar)))+(2.*momQ+momQbar)*sqr(sqr(mass(q)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqr(1.*inv12+sqr(mass(q))+sqr(mass(qbar))) );
const LorentzVector<Complex>& coeffLeftProd = ( (mass(q)*(2.*(momQ+momQbar)*(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))+log1(sqr(mass(q))/sqr(mass(qbar)))*(1.*inv12*(momQ+2.*momQbar)+momQbar*sqr(mass(q))+(2.*momQ+3.*momQbar)*sqr(mass(qbar)))+(2.*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*(0.5*(momQ+2.*momQbar)*sqr(inv12)-momQ*sqr(mass(q))*sqr(mass(qbar))+0.5*inv12*(momQbar*sqr(mass(q))+(2.*momQ+5.*momQbar)*sqr(mass(qbar)))+(momQ+2.*momQbar)*sqr(sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqr(1.*inv12+sqr(mass(q))+sqr(mass(qbar))) );
const Complex leftProd = Complex(0.,1.) * minusProduct(q,qbar);
const Complex rightProd = Complex(0.,1.) * mass(q)*mass(qbar)/plusProduct(q,qbar);
cacheCurrent( 0.5*CF*( coeffLeftTree*leftTree + coeffRightTree*rightTree + coeffLeftProd*leftProd + coeffRightProd*rightProd ) );
}
if ( qHel == -1 && qbarHel == 1 ){
// Coefficients of the right and left handed products of massive spinors
const LorentzVector<Complex>& coeffRightProd = ( (mass(qbar)*(-2.*(momQ+momQbar)*(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))+log1(sqr(mass(q))/sqr(mass(qbar)))*(1.*inv12*(2.*momQ+momQbar)+(3.*momQ+2.*momQbar)*sqr(mass(q))+momQ*sqr(mass(qbar)))-(2.*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*(0.5*(2.*momQ+momQbar)*sqr(inv12)-momQbar*sqr(mass(q))*sqr(mass(qbar))+0.5*inv12*((5.*momQ+2.*momQbar)*sqr(mass(q))+momQ*sqr(mass(qbar)))+(2.*momQ+momQbar)*sqr(sqr(mass(q)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqr(1.*inv12+sqr(mass(q))+sqr(mass(qbar))) );
const LorentzVector<Complex>& coeffLeftProd = ( (mass(q)*(2.*(momQ+momQbar)*(1.*inv12+sqr(mass(q))+sqr(mass(qbar)))+log1(sqr(mass(q))/sqr(mass(qbar)))*(1.*inv12*(momQ+2.*momQbar)+momQbar*sqr(mass(q))+(2.*momQ+3.*momQbar)*sqr(mass(qbar)))+(2.*log1((-1.*mass(q)*mass(qbar))/(0.5*inv12+sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))*(0.5*(momQ+2.*momQbar)*sqr(inv12)-momQ*sqr(mass(q))*sqr(mass(qbar))+0.5*inv12*(momQbar*sqr(mass(q))+(2.*momQ+5.*momQbar)*sqr(mass(qbar)))+(momQ+2.*momQbar)*sqr(sqr(mass(qbar)))))/sqrt1(0.25*sqr(inv12)-sqr(mass(q))*sqr(mass(qbar)))))/sqr(1.*inv12+sqr(mass(q))+sqr(mass(qbar))) );
const Complex leftProd = Complex(0.,1.) * mass(q)*mass(qbar)/minusProduct(q,qbar);
const Complex rightProd = Complex(0.,1.) * plusProduct(q,qbar);
cacheCurrent( 0.5*CF*( coeffLeftTree*leftTree + coeffRightTree*rightTree + coeffLeftProd*leftProd + coeffRightProd*rightProd ) );
}
if ( qHel == -1 && qbarHel == -1 ){
cacheCurrent( 0.5*CF*( coeffLeftTree*leftTree + coeffRightTree*rightTree ) );
}
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbarRightOneLoopCurrent",cachedCurrent(),momentum(q)+momentum(qbar));
#endif
return cachedCurrent();
}
}
// ln(s(a+i0))
inline Complex log(double s, double a) {
return
s < 0. ?
Complex(log(abs(a)),-pi * theta(a)) :
Complex(log(abs(a)),pi * theta(-a));
}
// ln(s(a+i0)/(b+i0))
inline Complex log(double s, double a, double b) {
return
s < 0. ?
Complex(log(abs(a/b)),-pi * theta(a/b) * sign(b-a)) :
Complex(log(abs(a/b)),pi * theta(-a/b) * sign(b-a));
}
// Li2(-(a+i0)/(b+i0))
inline Complex Li2(double a, double b) {
if ( -a/b < 1. )
return Complex(Herwig::Math::ReLi2(-a/b),0.0);
return Complex(Herwig::Math::ReLi2(-a/b),-pi * log(-a/b) * sign(b-a));
}
Complex MatchboxCurrents::box6(const int i, const int j, const int k) {
const double sij = invariant(i,j);
const double sik = invariant(i,k);
const double sjk = invariant(j,k);
return
-( Li2(sik+sjk,sij) + Li2(sik+sij,sjk) + 0.5 * csqr(log(1.,sij,sjk)) + sqr(pi)/6. )/8.;
}
void MatchboxCurrents::qqbargLoopCoefficients(const int i, const int j, const int k) {
// use a dummy cache entry to check if we need to get some work done
static Complex dummy;
if ( getAmplitude(hash<5>(1,2,i,0,j,0,k,0)) ) {
dummy = 0.;
cacheAmplitude(dummy);
cachedAmplitude();
} else {
cachedAmplitude();
return;
}
qqbargLoops.resize(13);
// get the transcendentals
const double ij = invariant(i,j);
const double ij2 = sqr(ij);
const double ij3 = ij2 * ij;
const double ik = invariant(i,k);
const double ik2 = sqr(ik);
//const double ik3 = ik2 * ik;
const double jk = invariant(j,k);
const double jk2 = sqr(jk);
const double jk3 = jk2 * jk;
const double ij_ik = ij + ik;
const double ij_ik_2 = sqr(ij_ik);
const double ij_jk = ij + jk;
const double ij_jk_2 = sqr(ij_jk);
const double ik_jk = ik + jk;
const double ik_jk_2 = sqr(ik_jk);
const double Q2 = ij + ik + jk;
// checked for LEP that virtuals + I operator are mu2 independent
//double xmu2 = 10 * GeV2/sqr(amplitudeScale());
const double xmu2 = 1.;
const Complex Lijk = log(1.,-xmu2/Q2);
const Complex Lij = log(1.,Q2,ij);
const Complex Lik = log(1.,Q2,ik);
const Complex Ljk = log(1.,Q2,jk);
const Complex Box6ijk = box6(i,j,k);
const Complex Box6ikj = box6(i,k,j);
const Complex Box6jik = box6(j,i,k);
// get the coefficients
qqbargLoops[0] = (
(2 * CF * ij2) -
(32 * CA * Box6ijk * ij2) +
(64 * CF * Box6ijk * ij2) -
(8 * CA * Box6jik * ij2) +
(16 * CF * Box6jik * ij2) +
(2 * CA * Lij * ij2) -
(4 * CF * Lij * ij2) -
(CA * Lik * ij2) -
(2 * CF * Lik * ij2) -
(4 * CF * Ljk * ij2) -
(16 * CA * Box6ijk * ij3) / ik +
(32 * CF * Box6ijk * ij3) / ik +
(CA * Lij * ij3) / ik -
(2 * CF * Lij * ij3) / ik +
(2 * CF * ij * ik) -
(16 * CA * Box6ijk * ij * ik) +
(32 * CF * Box6ijk * ij * ik) -
(16 * CA * Box6jik * ij * ik) +
(32 * CF * Box6jik * ij * ik) +
(CA * Lij * ij * ik) -
(2 * CF * Lij * ij * ik) -
(2 * CA * Lik * ij * ik) -
(4 * CF * Lik * ij * ik) -
(4 * CF * Ljk * ij * ik) -
(8 * CA * Box6jik * ik2) +
(16 * CF * Box6jik * ik2) -
(CA * Lik * ik2) -
(2 * CF * Lik * ik2) -
(8 * CA * Box6jik * ij3) / jk +
(16 * CF * Box6jik * ij3) / jk -
(16 * CA * Box6jik * ij2 * ik) / jk +
(32 * CF * Box6jik * ij2 * ik) / jk -
(8 * CA * Box6jik * ij * ik2) / jk +
(16 * CF * Box6jik * ij * ik2) / jk +
(2 * CF * ij * jk) -
(40 * CA * Box6ijk * ij * jk) +
(80 * CF * Box6ijk * ij * jk) +
(24 * CA * Box6ikj * ij * jk) +
(2 * CA * Lij * ij * jk) -
(4 * CF * Lij * ij * jk) -
(CA * Lik * ij * jk) -
(4 * CF * Lik * ij * jk) -
(12 * CF * Ljk * ij * jk) -
(8 * CA * Box6ijk * ij3 * jk) / ik2 +
(16 * CF * Box6ijk * ij3 * jk) / ik2 -
(32 * CA * Box6ijk * ij2 * jk) / ik +
(64 * CF * Box6ijk * ij2 * jk) / ik +
(CA * Lij * ij2 * jk) / ik -
(2 * CF * Lij * ij2 * jk) / ik +
(CA * Ljk * ij2 * jk) / ik -
(2 * CF * Ljk * ij2 * jk) / ik +
(2 * CF * ik * jk) -
(16 * CA * Box6ijk * ik * jk) +
(32 * CF * Box6ijk * ik * jk) +
(48 * CA * Box6ikj * ik * jk) +
(CA * Lij * ik * jk) -
(2 * CF * Lij * ik * jk) -
(2 * CA * Lik * ik * jk) -
(8 * CF * Lik * ik * jk) -
(CA * Ljk * ik * jk) -
(8 * CF * Ljk * ik * jk) +
(24 * CA * Box6ikj * ik2 * jk) / ij -
(CA * Lik * ik2 * jk) / ij -
(4 * CF * Lik * ik2 * jk) / ij -
(8 * CA * Box6ijk * jk2) +
(16 * CF * Box6ijk * jk2) +
(24 * CA * Box6ikj * jk2) -
(8 * CF * Ljk * jk2) -
(8 * CA * Box6ijk * ij2 * jk2) / ik2 +
(16 * CF * Box6ijk * ij2 * jk2) / ik2 -
(16 * CA * Box6ijk * ij * jk2) / ik +
(32 * CF * Box6ijk * ij * jk2) / ik +
(CA * Ljk * ij * jk2) / ik -
(2 * CF * Ljk * ij * jk2) / ik +
(48 * CA * Box6ikj * ik * jk2) / ij -
(CA * Ljk * ik * jk2) / ij -
(4 * CF * Ljk * ik * jk2) / ij +
(24 * CA * Box6ikj * ik2 * jk2) / ij2
) / (ij_ik_2 * ij_jk);
qqbargLoops[1] = (
(-2 * CF * ij2) +
(8 * CA * Box6ijk * ij2) -
(16 * CF * Box6ijk * ij2) +
(32 * CA * Box6jik * ij2) -
(64 * CF * Box6jik * ij2) -
(2 * CA * Lij * ij2) +
(4 * CF * Lij * ij2) +
(4 * CF * Lik * ij2) +
(CA * Ljk * ij2) +
(2 * CF * Ljk * ij2) +
(8 * CA * Box6ijk * ij3) / ik -
(16 * CF * Box6ijk * ij3) / ik -
(2 * CF * ij * ik) -
(24 * CA * Box6ikj * ij * ik) +
(40 * CA * Box6jik * ij * ik) -
(80 * CF * Box6jik * ij * ik) -
(2 * CA * Lij * ij * ik) +
(4 * CF * Lij * ij * ik) +
(12 * CF * Lik * ij * ik) +
(CA * Ljk * ij * ik) +
(4 * CF * Ljk * ij * ik) -
(24 * CA * Box6ikj * ik2) +
(8 * CA * Box6jik * ik2) -
(16 * CF * Box6jik * ik2) +
(8 * CF * Lik * ik2) +
(8 * CA * Box6jik * ij3 * ik) / jk2 -
(16 * CF * Box6jik * ij3 * ik) / jk2 +
(8 * CA * Box6jik * ij2 * ik2) / jk2 -
(16 * CF * Box6jik * ij2 * ik2) / jk2 +
(16 * CA * Box6jik * ij3) / jk -
(32 * CF * Box6jik * ij3) / jk -
(CA * Lij * ij3) / jk +
(2 * CF * Lij * ij3) / jk +
(32 * CA * Box6jik * ij2 * ik) / jk -
(64 * CF * Box6jik * ij2 * ik) / jk -
(CA * Lij * ij2 * ik) / jk +
(2 * CF * Lij * ij2 * ik) / jk -
(CA * Lik * ij2 * ik) / jk +
(2 * CF * Lik * ij2 * ik) / jk +
(16 * CA * Box6jik * ij * ik2) / jk -
(32 * CF * Box6jik * ij * ik2) / jk -
(CA * Lik * ij * ik2) / jk +
(2 * CF * Lik * ij * ik2) / jk -
(2 * CF * ij * jk) +
(16 * CA * Box6ijk * ij * jk) -
(32 * CF * Box6ijk * ij * jk) +
(16 * CA * Box6jik * ij * jk) -
(32 * CF * Box6jik * ij * jk) -
(CA * Lij * ij * jk) +
(2 * CF * Lij * ij * jk) +
(4 * CF * Lik * ij * jk) +
(2 * CA * Ljk * ij * jk) +
(4 * CF * Ljk * ij * jk) +
(16 * CA * Box6ijk * ij2 * jk) / ik -
(32 * CF * Box6ijk * ij2 * jk) / ik -
(2 * CF * ik * jk) -
(48 * CA * Box6ikj * ik * jk) +
(16 * CA * Box6jik * ik * jk) -
(32 * CF * Box6jik * ik * jk) -
(CA * Lij * ik * jk) +
(2 * CF * Lij * ik * jk) +
(CA * Lik * ik * jk) +
(8 * CF * Lik * ik * jk) +
(2 * CA * Ljk * ik * jk) +
(8 * CF * Ljk * ik * jk) -
(48 * CA * Box6ikj * ik2 * jk) / ij +
(CA * Lik * ik2 * jk) / ij +
(4 * CF * Lik * ik2 * jk) / ij +
(8 * CA * Box6ijk * jk2) -
(16 * CF * Box6ijk * jk2) +
(CA * Ljk * jk2) +
(2 * CF * Ljk * jk2) +
(8 * CA * Box6ijk * ij * jk2) / ik -
(16 * CF * Box6ijk * ij * jk2) / ik -
(24 * CA * Box6ikj * ik * jk2) / ij +
(CA * Ljk * ik * jk2) / ij +
(4 * CF * Ljk * ik * jk2) / ij -
(24 * CA * Box6ikj * ik2 * jk2) / ij2
) / (ij_ik * ij_jk_2);
qqbargLoops[2] = -3 * CF * Lijk + (
(-4 * CA * Box6jik * ij3) +
(8 * CF * Box6jik * ij3) +
(CA * Lij * ij3) / 2. -
(CF * Lij * ij3) +
(CA * ij2 * ik) -
(9 * CF * ij2 * ik) +
(8 * CA * Box6ijk * ij2 * ik) -
(16 * CF * Box6ijk * ij2 * ik) -
(8 * CA * Box6ikj * ij2 * ik) -
(8 * CA * Box6jik * ij2 * ik) +
(16 * CF * Box6jik * ij2 * ik) +
(CA * Lij * ij2 * ik) / 2. -
(CF * Lij * ij2 * ik) +
(CA * Lik * ij2 * ik) / 2. -
(CF * Lik * ij2 * ik) +
(CA * ij * ik2) -
(9 * CF * ij * ik2) +
(8 * CA * Box6ijk * ij * ik2) -
(16 * CF * Box6ijk * ij * ik2) -
(8 * CA * Box6ikj * ij * ik2) -
(4 * CA * Box6jik * ij * ik2) +
(8 * CF * Box6jik * ij * ik2) +
(CA * Lik * ij * ik2) / 2. -
(CF * Lik * ij * ik2) -
(4 * CA * Box6jik * ij3 * ik) / jk +
(8 * CF * Box6jik * ij3 * ik) / jk -
(4 * CA * Box6jik * ij2 * ik2) / jk +
(8 * CF * Box6jik * ij2 * ik2) / jk +
(CA * ij2 * jk) -
(9 * CF * ij2 * jk) +
(12 * CA * Box6ijk * ij2 * jk) -
(24 * CF * Box6ijk * ij2 * jk) -
(8 * CA * Box6ikj * ij2 * jk) -
(4 * CA * Box6jik * ij2 * jk) +
(8 * CF * Box6jik * ij2 * jk) +
(CA * Lik * ij2 * jk) / 2. -
(CF * Lik * ij2 * jk) -
(CA * Ljk * ij2 * jk) / 2. +
(CF * Ljk * ij2 * jk) +
(4 * CA * Box6ijk * ij3 * jk) / ik -
(8 * CF * Box6ijk * ij3 * jk) / ik -
(CA * Lij * ij3 * jk) / (2. * ik) +
(CF * Lij * ij3 * jk) / ik +
(2 * CA * ij * ik * jk) -
(18 * CF * ij * ik * jk) +
(16 * CA * Box6ijk * ij * ik * jk) -
(32 * CF * Box6ijk * ij * ik * jk) -
(28 * CA * Box6ikj * ij * ik * jk) -
(4 * CA * Box6jik * ij * ik * jk) +
(8 * CF * Box6jik * ij * ik * jk) +
(CA * Lij * ij * ik * jk) / 2. -
(CF * Lij * ij * ik * jk) +
(CA * Lik * ij * ik * jk) -
(CF * Lik * ij * ik * jk) -
(CA * Ljk * ij * ik * jk) / 2. +
(3 * CF * Ljk * ij * ik * jk) +
(CA * ik2 * jk) -
(9 * CF * ik2 * jk) +
(8 * CA * Box6ijk * ik2 * jk) -
(16 * CF * Box6ijk * ik2 * jk) -
(20 * CA * Box6ikj * ik2 * jk) +
(CA * Lik * ik2 * jk) / 2. +
(CA * ij * jk2) -
(9 * CF * ij * jk2) +
(12 * CA * Box6ijk * ij * jk2) -
(24 * CF * Box6ijk * ij * jk2) -
(20 * CA * Box6ikj * ij * jk2) -
(CA * Lij * ij * jk2) / 2. +
(CF * Lij * ij * jk2) +
(CA * Lik * ij * jk2) / 2. -
(CA * Ljk * ij * jk2) +
(4 * CF * Ljk * ij * jk2) +
(4 * CA * Box6ijk * ij3 * jk2) / ik2 -
(8 * CF * Box6ijk * ij3 * jk2) / ik2 +
(8 * CA * Box6ijk * ij2 * jk2) / ik -
(16 * CF * Box6ijk * ij2 * jk2) / ik -
(CA * Lij * ij2 * jk2) / (2. * ik) +
(CF * Lij * ij2 * jk2) / ik -
(CA * Ljk * ij2 * jk2) / (2. * ik) +
(CF * Ljk * ij2 * jk2) / ik +
(CA * ik * jk2) -
(9 * CF * ik * jk2) +
(8 * CA * Box6ijk * ik * jk2) -
(16 * CF * Box6ijk * ik * jk2) -
(32 * CA * Box6ikj * ik * jk2) +
(CA * Lik * ik * jk2) / 2. -
(CA * Ljk * ik * jk2) / 2. +
(3 * CF * Ljk * ik * jk2) -
(12 * CA * Box6ikj * ik2 * jk2) / ij -
(12 * CA * Box6ikj * jk3) -
(CA * Ljk * jk3) / 2. +
(3 * CF * Ljk * jk3) +
(4 * CA * Box6ijk * ij2 * jk3) / ik2 -
(8 * CF * Box6ijk * ij2 * jk3) / ik2 +
(4 * CA * Box6ijk * ij * jk3) / ik -
(8 * CF * Box6ijk * ij * jk3) / ik -
(CA * Ljk * ij * jk3) / (2. * ik) +
(CF * Ljk * ij * jk3) / ik -
(12 * CA * Box6ikj * ik * jk3) / ij
) / (ij_ik * ij_jk * ik_jk);
qqbargLoops[3] = 3 * CF * Lijk + (
(8 * CF * ij2) -
(8 * CA * Box6ijk * ij2) +
(16 * CF * Box6ijk * ij2) +
(8 * CA * Box6ikj * ij2) -
(8 * CA * Box6jik * ij2) +
(16 * CF * Box6jik * ij2) +
(CA * Lij * ij2) / 2. -
(CF * Lij * ij2) +
(8 * CF * ij * ik) -
(8 * CA * Box6ijk * ij * ik) +
(16 * CF * Box6ijk * ij * ik) +
(8 * CA * Box6ikj * ij * ik) -
(12 * CA * Box6jik * ij * ik) +
(24 * CF * Box6jik * ij * ik) +
(CA * Lij * ij * ik) / 2. -
(CF * Lij * ij * ik) +
(CA * Lik * ij * ik) / 2. -
(CF * Lik * ij * ik) -
(4 * CA * Box6jik * ik2) +
(8 * CF * Box6jik * ik2) +
(CA * Lik * ik2) / 2. -
(CF * Lik * ik2) -
(4 * CA * Box6jik * ij2 * ik) / jk +
(8 * CF * Box6jik * ij2 * ik) / jk -
(4 * CA * Box6jik * ij * ik2) / jk +
(8 * CF * Box6jik * ij * ik2) / jk +
(8 * CF * ij * jk) -
(12 * CA * Box6ijk * ij * jk) +
(24 * CF * Box6ijk * ij * jk) +
(8 * CA * Box6ikj * ij * jk) -
(8 * CA * Box6jik * ij * jk) +
(16 * CF * Box6jik * ij * jk) +
(CA * Lij * ij * jk) / 2. -
(CF * Lij * ij * jk) +
(CA * Ljk * ij * jk) / 2. -
(CF * Ljk * ij * jk) -
(4 * CA * Box6ijk * ij2 * jk) / ik +
(8 * CF * Box6ijk * ij2 * jk) / ik +
(8 * CF * ik * jk) -
(8 * CA * Box6ijk * ik * jk) +
(16 * CF * Box6ijk * ik * jk) -
(4 * CA * Box6ikj * ik * jk) -
(8 * CA * Box6jik * ik * jk) +
(16 * CF * Box6jik * ik * jk) +
(CA * Lij * ik * jk) / 2. -
(CF * Lij * ik * jk) +
(CA * Lik * ik * jk) / 2. +
(2 * CF * Lik * ik * jk) +
(CA * Ljk * ik * jk) / 2. +
(2 * CF * Ljk * ik * jk) -
(12 * CA * Box6ikj * ik2 * jk) / ij +
(CA * Lik * ik2 * jk) / (2. * ij) +
(2 * CF * Lik * ik2 * jk) / ij -
(4 * CA * Box6ijk * jk2) +
(8 * CF * Box6ijk * jk2) +
(CA * Ljk * jk2) / 2. -
(CF * Ljk * jk2) -
(4 * CA * Box6ijk * ij * jk2) / ik +
(8 * CF * Box6ijk * ij * jk2) / ik -
(12 * CA * Box6ikj * ik * jk2) / ij +
(CA * Ljk * ik * jk2) / (2. * ij) +
(2 * CF * Ljk * ik * jk2) / ij -
(12 * CA * Box6ikj * ik2 * jk2) / ij2
) / (ij_ik * ij_jk);
qqbargLoops[4] = -3 * CF * Lijk + (
(-8 * CF * ij2) +
(8 * CA * Box6ijk * ij2) -
(16 * CF * Box6ijk * ij2) -
(8 * CA * Box6ikj * ij2) +
(8 * CA * Box6jik * ij2) -
(16 * CF * Box6jik * ij2) -
(CA * Lij * ij2) / 2. +
(CF * Lij * ij2) -
(8 * CF * ij * ik) +
(8 * CA * Box6ijk * ij * ik) -
(16 * CF * Box6ijk * ij * ik) -
(8 * CA * Box6ikj * ij * ik) +
(12 * CA * Box6jik * ij * ik) -
(24 * CF * Box6jik * ij * ik) -
(CA * Lij * ij * ik) / 2. +
(CF * Lij * ij * ik) -
(CA * Lik * ij * ik) / 2. +
(CF * Lik * ij * ik) +
(4 * CA * Box6jik * ik2) -
(8 * CF * Box6jik * ik2) -
(CA * Lik * ik2) / 2. +
(CF * Lik * ik2) +
(4 * CA * Box6jik * ij2 * ik) / jk -
(8 * CF * Box6jik * ij2 * ik) / jk +
(4 * CA * Box6jik * ij * ik2) / jk -
(8 * CF * Box6jik * ij * ik2) / jk -
(8 * CF * ij * jk) +
(12 * CA * Box6ijk * ij * jk) -
(24 * CF * Box6ijk * ij * jk) -
(8 * CA * Box6ikj * ij * jk) +
(8 * CA * Box6jik * ij * jk) -
(16 * CF * Box6jik * ij * jk) -
(CA * Lij * ij * jk) / 2. +
(CF * Lij * ij * jk) -
(CA * Ljk * ij * jk) / 2. +
(CF * Ljk * ij * jk) +
(4 * CA * Box6ijk * ij2 * jk) / ik -
(8 * CF * Box6ijk * ij2 * jk) / ik -
(8 * CF * ik * jk) +
(8 * CA * Box6ijk * ik * jk) -
(16 * CF * Box6ijk * ik * jk) +
(4 * CA * Box6ikj * ik * jk) +
(8 * CA * Box6jik * ik * jk) -
(16 * CF * Box6jik * ik * jk) -
(CA * Lij * ik * jk) / 2. +
(CF * Lij * ik * jk) -
(CA * Lik * ik * jk) / 2. -
(2 * CF * Lik * ik * jk) -
(CA * Ljk * ik * jk) / 2. -
(2 * CF * Ljk * ik * jk) +
(12 * CA * Box6ikj * ik2 * jk) / ij -
(CA * Lik * ik2 * jk) / (2. * ij) -
(2 * CF * Lik * ik2 * jk) / ij +
(4 * CA * Box6ijk * jk2) -
(8 * CF * Box6ijk * jk2) -
(CA * Ljk * jk2) / 2. +
(CF * Ljk * jk2) +
(4 * CA * Box6ijk * ij * jk2) / ik -
(8 * CF * Box6ijk * ij * jk2) / ik +
(12 * CA * Box6ikj * ik * jk2) / ij -
(CA * Ljk * ik * jk2) / (2. * ij) -
(2 * CF * Ljk * ik * jk2) / ij +
(12 * CA * Box6ikj * ik2 * jk2) / ij2
) / (ij_ik * ij_jk);
qqbargLoops[5] = 3 * CF * Lijk + (
(-4 * CA * Box6jik * ij2) +
(8 * CF * Box6jik * ij2) +
(CA * Lij * ij2) / 2. -
(CF * Lij * ij2) -
(CA * ij * ik) +
(9 * CF * ij * ik) -
(8 * CA * Box6ijk * ij * ik) +
(16 * CF * Box6ijk * ij * ik) +
(8 * CA * Box6ikj * ij * ik) -
(4 * CA * Box6jik * ij * ik) +
(8 * CF * Box6jik * ij * ik) +
(CA * Lij * ij * ik) / 2. -
(CF * Lij * ij * ik) +
(CA * Lik * ij * ik) / 2. -
(CF * Lik * ij * ik) -
(CA * ik2) +
(9 * CF * ik2) -
(8 * CA * Box6ijk * ik2) +
(16 * CF * Box6ijk * ik2) +
(8 * CA * Box6ikj * ik2) +
(CA * Lik * ik2) / 2. -
(CF * Lik * ik2) -
(4 * CA * Box6jik * ij2 * ik) / jk +
(8 * CF * Box6jik * ij2 * ik) / jk -
(4 * CA * Box6jik * ij * ik2) / jk +
(8 * CF * Box6jik * ij * ik2) / jk -
(CA * ij * jk) +
(9 * CF * ij * jk) -
(4 * CA * Box6ijk * ij * jk) +
(8 * CF * Box6ijk * ij * jk) +
(8 * CA * Box6ikj * ij * jk) -
(CA * Lij * ij * jk) / 2. +
(CF * Lij * ij * jk) +
(CA * Lik * ij * jk) / 2. -
(CF * Lik * ij * jk) -
(CA * Ljk * ij * jk) / 2. +
(CF * Ljk * ij * jk) +
(4 * CA * Box6ijk * ij2 * jk) / ik -
(8 * CF * Box6ijk * ij2 * jk) / ik -
(CA * Lij * ij2 * jk) / (2. * ik) +
(CF * Lij * ij2 * jk) / ik -
(CA * ik * jk) +
(9 * CF * ik * jk) -
(8 * CA * Box6ijk * ik * jk) +
(16 * CF * Box6ijk * ik * jk) +
(20 * CA * Box6ikj * ik * jk) +
(CA * Lik * ik * jk) / 2. -
(CF * Lik * ik * jk) -
(CA * Ljk * ik * jk) / 2. -
(2 * CF * Ljk * ik * jk) +
(12 * CA * Box6ikj * ik2 * jk) / ij +
(12 * CA * Box6ikj * jk2) -
(CA * Ljk * jk2) / 2. -
(2 * CF * Ljk * jk2) +
(4 * CA * Box6ijk * ij2 * jk2) / ik2 -
(8 * CF * Box6ijk * ij2 * jk2) / ik2 +
(4 * CA * Box6ijk * ij * jk2) / ik -
(8 * CF * Box6ijk * ij * jk2) / ik -
(CA * Ljk * ij * jk2) / (2. * ik) +
(CF * Ljk * ij * jk2) / ik +
(12 * CA * Box6ikj * ik * jk2) / ij
) / (ij_ik * ik_jk);
qqbargLoops[6] = (
(-2 * CF * ij) +
(32 * CA * Box6ijk * ij) -
(64 * CF * Box6ijk * ij) -
(4 * CA * Lij * ij) +
(8 * CF * Lij * ij) +
(4 * CF * Ljk * ij) +
(16 * CA * Box6ijk * ij2) / ik -
(32 * CF * Box6ijk * ij2) / ik -
(2 * CA * Lij * ij2) / ik +
(4 * CF * Lij * ij2) / ik -
(2 * CF * ik) +
(16 * CA * Box6ijk * ik) -
(32 * CF * Box6ijk * ik) -
(2 * CA * Lij * ik) +
(4 * CF * Lij * ik) +
(4 * CF * Ljk * ik) +
(16 * CA * Box6ijk * jk) -
(32 * CF * Box6ijk * jk) -
(2 * CA * Ljk * jk) +
(6 * CF * Ljk * jk) +
(16 * CA * Box6ijk * ij2 * jk) / ik2 -
(32 * CF * Box6ijk * ij2 * jk) / ik2 +
(32 * CA * Box6ijk * ij * jk) / ik -
(64 * CF * Box6ijk * ij * jk) / ik -
(2 * CA * Ljk * ij * jk) / ik +
(4 * CF * Ljk * ij * jk) / ik
) / ij_ik_2;
qqbargLoops[7] = (
(8 * CA * Box6jik * ij) -
(16 * CF * Box6jik * ij) +
(CA * Lij * ij) -
(2 * CF * Lij * ij) +
(CA * Lik * ij) +
(2 * CF * Lik * ij) +
(CA * Lij * ij2) / ik -
(2 * CF * Lij * ij2) / ik +
(8 * CA * Box6jik * ik) -
(16 * CF * Box6jik * ik) +
(CA * Lik * ik) +
(2 * CF * Lik * ik) +
(8 * CA * Box6jik * ij2) / jk -
(16 * CF * Box6jik * ij2) / jk +
(8 * CA * Box6jik * ij * ik) / jk -
(16 * CF * Box6jik * ij * ik) / jk -
(24 * CA * Box6ikj * jk) +
(CA * Lij * jk) -
(2 * CF * Lij * jk) +
(CA * Lik * jk) +
(4 * CF * Lik * jk) +
(CA * Ljk * jk) +
(4 * CF * Ljk * jk) -
(8 * CA * Box6ijk * ij2 * jk) / ik2 +
(16 * CF * Box6ijk * ij2 * jk) / ik2 -
(8 * CA * Box6ijk * ij * jk) / ik +
(16 * CF * Box6ijk * ij * jk) / ik +
(CA * Lij * ij * jk) / ik -
(2 * CF * Lij * ij * jk) / ik +
(CA * Ljk * ij * jk) / ik -
(2 * CF * Ljk * ij * jk) / ik -
(24 * CA * Box6ikj * ik * jk) / ij +
(CA * Lik * ik * jk) / ij +
(4 * CF * Lik * ik * jk) / ij -
(24 * CA * Box6ikj * jk2) / ij +
(CA * Ljk * jk2) / ij +
(4 * CF * Ljk * jk2) / ij -
(8 * CA * Box6ijk * ij * jk2) / ik2 +
(16 * CF * Box6ijk * ij * jk2) / ik2 -
(8 * CA * Box6ijk * jk2) / ik +
(16 * CF * Box6ijk * jk2) / ik +
(CA * Ljk * jk2) / ik -
(2 * CF * Ljk * jk2) / ik -
(24 * CA * Box6ikj * ik * jk2) / ij2
) / (ij_ik * ij_jk);
qqbargLoops[8] = (
(-8 * CA * Box6ijk * ij) +
(16 * CF * Box6ijk * ij) -
(CA * Lij * ij) +
(2 * CF * Lij * ij) -
(CA * Ljk * ij) -
(2 * CF * Ljk * ij) -
(8 * CA * Box6ijk * ij2) / ik +
(16 * CF * Box6ijk * ij2) / ik +
(24 * CA * Box6ikj * ik) -
(CA * Lij * ik) +
(2 * CF * Lij * ik) -
(CA * Lik * ik) -
(4 * CF * Lik * ik) -
(CA * Ljk * ik) -
(4 * CF * Ljk * ik) +
(24 * CA * Box6ikj * ik2) / ij -
(CA * Lik * ik2) / ij -
(4 * CF * Lik * ik2) / ij +
(8 * CA * Box6jik * ij2 * ik) / jk2 -
(16 * CF * Box6jik * ij2 * ik) / jk2 +
(8 * CA * Box6jik * ij * ik2) / jk2 -
(16 * CF * Box6jik * ij * ik2) / jk2 -
(CA * Lij * ij2) / jk +
(2 * CF * Lij * ij2) / jk +
(8 * CA * Box6jik * ij * ik) / jk -
(16 * CF * Box6jik * ij * ik) / jk -
(CA * Lij * ij * ik) / jk +
(2 * CF * Lij * ij * ik) / jk -
(CA * Lik * ij * ik) / jk +
(2 * CF * Lik * ij * ik) / jk +
(8 * CA * Box6jik * ik2) / jk -
(16 * CF * Box6jik * ik2) / jk -
(CA * Lik * ik2) / jk +
(2 * CF * Lik * ik2) / jk -
(8 * CA * Box6ijk * jk) +
(16 * CF * Box6ijk * jk) -
(CA * Ljk * jk) -
(2 * CF * Ljk * jk) -
(8 * CA * Box6ijk * ij * jk) / ik +
(16 * CF * Box6ijk * ij * jk) / ik +
(24 * CA * Box6ikj * ik * jk) / ij -
(CA * Ljk * ik * jk) / ij -
(4 * CF * Ljk * ik * jk) / ij +
(24 * CA * Box6ikj * ik2 * jk) / ij2
) / (ij_ik * ij_jk);
qqbargLoops[9] = (
(2 * CF * ij) -
(32 * CA * Box6jik * ij) +
(64 * CF * Box6jik * ij) +
(4 * CA * Lij * ij) -
(8 * CF * Lij * ij) -
(4 * CF * Lik * ij) -
(16 * CA * Box6jik * ik) +
(32 * CF * Box6jik * ik) +
(2 * CA * Lik * ik) -
(6 * CF * Lik * ik) -
(16 * CA * Box6jik * ij2 * ik) / jk2 +
(32 * CF * Box6jik * ij2 * ik) / jk2 -
(16 * CA * Box6jik * ij2) / jk +
(32 * CF * Box6jik * ij2) / jk +
(2 * CA * Lij * ij2) / jk -
(4 * CF * Lij * ij2) / jk -
(32 * CA * Box6jik * ij * ik) / jk +
(64 * CF * Box6jik * ij * ik) / jk +
(2 * CA * Lik * ij * ik) / jk -
(4 * CF * Lik * ij * ik) / jk +
(2 * CF * jk) -
(16 * CA * Box6jik * jk) +
(32 * CF * Box6jik * jk) +
(2 * CA * Lij * jk) -
(4 * CF * Lij * jk) -
(4 * CF * Lik * jk)
) / ij_jk_2;
qqbargLoops[10] = (
(-8 * CA * Box6ijk * ij2 * jk) +
(16 * CF * Box6ijk * ij2 * jk) +
(2 * CA * Lij * ij2 * jk) -
(4 * CF * Lij * ij2 * jk) -
(CA * ij * ik * jk) +
(2 * CF * ij * ik * jk) -
(8 * CA * Box6ijk * ij * ik * jk) +
(16 * CF * Box6ijk * ij * ik * jk) +
(3 * CA * Lij * ij * ik * jk) -
(6 * CF * Lij * ij * ik * jk) +
(CA * Ljk * ij * ik * jk) -
(2 * CF * Ljk * ij * ik * jk) -
(CA * ik2 * jk) +
(2 * CF * ik2 * jk) +
(CA * Lij * ik2 * jk) -
(2 * CF * Lij * ik2 * jk) +
(CA * Ljk * ik2 * jk) -
(CF * Ljk * ik2 * jk) -
(CA * ij * jk2) +
(2 * CF * ij * jk2) -
(16 * CA * Box6ijk * ij * jk2) +
(32 * CF * Box6ijk * ij * jk2) +
(2 * CA * Lij * ij * jk2) -
(4 * CF * Lij * ij * jk2) +
(2 * CA * Ljk * ij * jk2) -
(4 * CF * Ljk * ij * jk2) -
(16 * CA * Box6ijk * ij2 * jk2) / ik +
(32 * CF * Box6ijk * ij2 * jk2) / ik +
(CA * Lij * ij2 * jk2) / ik -
(2 * CF * Lij * ij2 * jk2) / ik -
(CA * ik * jk2) +
(2 * CF * ik * jk2) +
(CA * Lij * ik * jk2) -
(2 * CF * Lij * ik * jk2) +
(2 * CA * Ljk * ik * jk2) -
(2 * CF * Ljk * ik * jk2) +
(CA * Ljk * jk3) -
(CF * Ljk * jk3) -
(8 * CA * Box6ijk * ij2 * jk3) / ik2 +
(16 * CF * Box6ijk * ij2 * jk3) / ik2 -
(8 * CA * Box6ijk * ij * jk3) / ik +
(16 * CF * Box6ijk * ij * jk3) / ik +
(CA * Ljk * ij * jk3) / ik -
(2 * CF * Ljk * ij * jk3) / ik
) / (ij_ik * ik_jk_2);
qqbargLoops[11] = (
(16 * CA * Box6jik * ij2 * ik) -
(32 * CF * Box6jik * ij2 * ik) -
(CA * Lij * ij2 * ik) +
(2 * CF * Lij * ij2 * ik) +
(8 * CA * Box6jik * ij * ik2) -
(16 * CF * Box6jik * ij * ik2) -
(CA * Lik * ij * ik2) +
(2 * CF * Lik * ij * ik2) +
(8 * CA * Box6jik * ij2 * ik2) / jk -
(16 * CF * Box6jik * ij2 * ik2) / jk +
(8 * CA * Box6jik * ij2 * jk) -
(16 * CF * Box6jik * ij2 * jk) -
(2 * CA * Lij * ij2 * jk) +
(4 * CF * Lij * ij2 * jk) +
(CA * ij * ik * jk) -
(2 * CF * ij * ik * jk) +
(16 * CA * Box6jik * ij * ik * jk) -
(32 * CF * Box6jik * ij * ik * jk) -
(2 * CA * Lij * ij * ik * jk) +
(4 * CF * Lij * ij * ik * jk) -
(2 * CA * Lik * ij * ik * jk) +
(4 * CF * Lik * ij * ik * jk) -
(CA * Lik * ik2 * jk) +
(CF * Lik * ik2 * jk) +
(CA * ij * jk2) -
(2 * CF * ij * jk2) +
(8 * CA * Box6jik * ij * jk2) -
(16 * CF * Box6jik * ij * jk2) -
(3 * CA * Lij * ij * jk2) +
(6 * CF * Lij * ij * jk2) -
(CA * Lik * ij * jk2) +
(2 * CF * Lik * ij * jk2) +
(CA * ik * jk2) -
(2 * CF * ik * jk2) -
(CA * Lij * ik * jk2) +
(2 * CF * Lij * ik * jk2) -
(2 * CA * Lik * ik * jk2) +
(2 * CF * Lik * ik * jk2) +
(CA * jk3) -
(2 * CF * jk3) -
(CA * Lij * jk3) +
(2 * CF * Lij * jk3) -
(CA * Lik * jk3) +
(CF * Lik * jk3)
) / (ij_jk * ik_jk_2);
qqbargLoops[12] = -3 * CF * Lijk + (
(CA * ij2 * ik) -
(9 * CF * ij2 * ik) +
(8 * CA * Box6ijk * ij2 * ik) -
(16 * CF * Box6ijk * ij2 * ik) -
(8 * CA * Box6ikj * ij2 * ik) +
(CA * ij * ik2) -
(9 * CF * ij * ik2) +
(8 * CA * Box6ijk * ij * ik2) -
(16 * CF * Box6ijk * ij * ik2) -
(8 * CA * Box6ikj * ij * ik2) +
(CA * ij2 * jk) -
(9 * CF * ij2 * jk) -
(8 * CA * Box6ikj * ij2 * jk) +
(8 * CA * Box6jik * ij2 * jk) -
(16 * CF * Box6jik * ij2 * jk) +
(2 * CA * ij * ik * jk) -
(18 * CF * ij * ik * jk) +
(8 * CA * Box6ijk * ij * ik * jk) -
(16 * CF * Box6ijk * ij * ik * jk) -
(40 * CA * Box6ikj * ij * ik * jk) +
(8 * CA * Box6jik * ij * ik * jk) -
(16 * CF * Box6jik * ij * ik * jk) +
(3 * CF * Lik * ij * ik * jk) +
(3 * CF * Ljk * ij * ik * jk) +
(CA * ik2 * jk) -
(9 * CF * ik2 * jk) +
(8 * CA * Box6ijk * ik2 * jk) -
(16 * CF * Box6ijk * ik2 * jk) -
(32 * CA * Box6ikj * ik2 * jk) +
(3 * CF * Lik * ik2 * jk) +
(CA * ij * jk2) -
(9 * CF * ij * jk2) -
(8 * CA * Box6ikj * ij * jk2) +
(8 * CA * Box6jik * ij * jk2) -
(16 * CF * Box6jik * ij * jk2) +
(CA * ik * jk2) -
(9 * CF * ik * jk2) -
(32 * CA * Box6ikj * ik * jk2) +
(8 * CA * Box6jik * ik * jk2) -
(16 * CF * Box6jik * ik * jk2) +
(3 * CF * Ljk * ik * jk2) -
(24 * CA * Box6ikj * ik2 * jk2) / ij
) / (ij_ik * ij_jk * ik_jk);
/* // idendities implied by gauge invariance and current conservation; checked analytically and numerically
Complex c1 = qqbargLoops[0] + qqbargLoops[6] + qqbargLoops[7];
Complex c2 = qqbargLoops[1] + qqbargLoops[8] + qqbargLoops[9];
Complex c3 = qqbargLoops[3] + qqbargLoops[4];
Complex c4 = qqbargLoops[2] + qqbargLoops[5] + qqbargLoops[10] + qqbargLoops[11];
Complex c5 =
2. * qqbargLoops[3]/ik +
2. * qqbargLoops[5]/jk +
qqbargLoops[6] * (1.+ij/ik) +
qqbargLoops[8] * (jk+ij)/ik +
2. * qqbargLoops[10] * (1./ik+1./jk) +
2. * qqbargLoops[12] * (1./ik+1./jk);
Complex c6 =
2. * qqbargLoops[4]/jk +
2. * qqbargLoops[5]/jk +
qqbargLoops[7] * (ik+ij)/jk +
qqbargLoops[9] * (1.+ij/jk) +
2. * qqbargLoops[11] * (ik/jk2+1./jk);
Complex c7 =
0.5 * qqbargLoops[0] * (ij+ik) +
0.5 * qqbargLoops[1] * (ij+jk) +
qqbargLoops[2] * (1.+ik/jk) -
qqbargLoops[12] * (1.+ik/jk);
double x1 = c1 != 0. ? log(abs(real(c1 * conj(c1)))) : 0.;
double x2 = c2 != 0. ? log(abs(real(c2 * conj(c2)))) : 0.;
double x3 = c3 != 0. ? log(abs(real(c3 * conj(c3)))) : 0.;
double x4 = c4 != 0. ? log(abs(real(c4 * conj(c4)))) : 0.;
double x5 = c5 != 0. ? log(abs(real(c5 * conj(c5)))) : 0.;
double x6 = c6 != 0. ? log(abs(real(c6 * conj(c6)))) : 0.;
double x7 = c7 != 0. ? log(abs(real(c7 * conj(c7)))) : 0.;
cerr << x1 << " " << x2 << " " << x3 << " " << x4 << " "
<< x5 << " " << x6 << " " << x7 << "\n";
*/
}
LorentzVector<Complex> MatchboxCurrents::qqbargGeneralLeftLoopCurrent(const int i, const int,
const int j, const int,
const int k, const int gHel,
const int n) {
qqbargLoopCoefficients(i,j,k);
const double ik = invariant(i,k);
const double jk = invariant(j,k);
const Complex plusP_ik = plusProduct(i,k);
const Complex plusP_in = plusProduct(i,n);
const Complex plusP_jk = plusProduct(j,k);
const Complex plusP_jn = plusProduct(j,n);
const Complex plusP_kn = plusProduct(k,n);
const Complex minusP_ik = minusProduct(i,k);
const Complex minusP_in = minusProduct(i,n);
const Complex minusP_jk = minusProduct(j,k);
const Complex minusP_jn = minusProduct(j,n);
const Complex minusP_kn = minusProduct(k,n);
const LorentzVector<Complex> & minusC_ij = minusCurrent(i,j);
const LorentzVector<Complex> & minusC_nk = minusCurrent(n,k);
const LorentzVector<Complex> & minusC_kj = minusCurrent(k,j);
const LorentzVector<Complex> & minusC_kn = minusCurrent(k,n);
Complex c1 = qqbargLoops[0]; Complex c2 = qqbargLoops[1]; Complex c3 = qqbargLoops[2];
Complex c4 = qqbargLoops[3]; Complex c5 = qqbargLoops[4]; Complex c6 = qqbargLoops[5];
Complex c7 = qqbargLoops[6]; Complex c8 = qqbargLoops[7]; Complex c9 = qqbargLoops[8];
Complex c10 = qqbargLoops[9]; Complex c11 = qqbargLoops[10]; Complex c12 = qqbargLoops[11];
Complex c13 = qqbargLoops[12];
if ( gHel == 1 ) {
return
(sqrt(2) * c6 * plusP_jk * minusC_nk * minusP_ik)/(jk * minusP_kn) +
(sqrt(2) * c1 * plusP_jk * momentum(i) * minusP_in)/minusP_kn +
(sqrt(2) * c2 * plusP_jk * momentum(j) * minusP_in)/minusP_kn +
(2 * sqrt(2) * c3 * plusP_jk * momentum(k) * minusP_in)/(jk * minusP_kn) +
(sqrt(2) * c4 * plusP_ik * minusC_ij * minusP_in)/(ik * minusP_kn) -
(sqrt(2) * c7 * plusP_ik * plusP_jk * momentum(i) * minusP_ik * minusP_in)/(ik * minusP_kn) -
(sqrt(2) * c9 * plusP_ik * plusP_jk * momentum(j) * minusP_ik * minusP_in)/(ik * minusP_kn) -
(2 * sqrt(2) * c11 * plusP_ik * plusP_jk * momentum(k) * minusP_ik * minusP_in)/(ik * jk * minusP_kn) +
(sqrt(2) * c5 * plusP_jk * minusC_ij * minusP_jn)/(jk * minusP_kn) -
(sqrt(2) * c8 * sqr(plusP_jk) * momentum(i) * minusP_ik * minusP_jn)/(jk * minusP_kn) -
(sqrt(2) * c10 * sqr(plusP_jk) * momentum(j) * minusP_ik * minusP_jn)/(jk * minusP_kn) -
(2 * sqrt(2) * c12 * sqr(plusP_jk) * momentum(k) * minusP_ik * minusP_jn)/(sqr(jk) * minusP_kn);
}
if ( gHel == -1 ) {
return
-((sqrt(2) * c1 * plusP_jn * momentum(i) * minusP_ik)/plusP_kn) -
(sqrt(2) * c2 * plusP_jn * momentum(j) * minusP_ik)/plusP_kn -
(2 * sqrt(2) * c3 * plusP_jn * momentum(k) * minusP_ik)/(jk * plusP_kn) -
(sqrt(2) * c4 * plusP_in * minusC_ij * minusP_ik)/(ik * plusP_kn) +
(sqrt(2) * c13 * minusC_kj * minusP_ik)/ik + (sqrt(2) * c13 * minusC_kj * minusP_ik)/jk -
(sqrt(2) * c6 * plusP_jk * minusC_kn * minusP_ik)/(jk * plusP_kn) +
(sqrt(2) * c7 * plusP_in * plusP_jk * momentum(i) * sqr(minusP_ik))/(ik * plusP_kn) +
(sqrt(2) * c9 * plusP_in * plusP_jk * momentum(j) * sqr(minusP_ik))/(ik * plusP_kn) +
(2 * sqrt(2) * c11 * plusP_in * plusP_jk * momentum(k) * sqr(minusP_ik))/(ik * jk * plusP_kn) -
(sqrt(2) * c5 * plusP_jn * minusC_ij * minusP_jk)/(jk * plusP_kn) +
(sqrt(2) * c8 * plusP_jk * plusP_jn * momentum(i) * minusP_ik * minusP_jk)/(jk * plusP_kn) +
(sqrt(2) * c10 * plusP_jk * plusP_jn * momentum(j) * minusP_ik * minusP_jk)/(jk * plusP_kn) +
(2 * sqrt(2) * c12 * plusP_jk * plusP_jn * momentum(k) * minusP_ik * minusP_jk)/(sqr(jk) * plusP_kn);
}
return czero;
}
LorentzVector<Complex> MatchboxCurrents::qqbargFixedLeftLoopCurrent(const int i, const int,
const int j, const int,
const int k, const int gHel) {
qqbargLoopCoefficients(i,j,k);
const double ik = invariant(i,k);
const double jk = invariant(j,k);
const Complex plusP_ij = plusProduct(i,j);
const Complex plusP_jk = plusProduct(j,k);
const Complex minusP_ij = minusProduct(i,j);
const Complex minusP_ik = minusProduct(i,k);
const LorentzVector<Complex> & minusC_ij = minusCurrent(i,j);
const LorentzVector<Complex> & minusC_ik = minusCurrent(i,k);
const LorentzVector<Complex> & minusC_kj = minusCurrent(k,j);
//Complex c1 = qqbargLoops[0]; Complex c2 = qqbargLoops[1]; Complex c3 = qqbargLoops[2];
Complex c4 = qqbargLoops[3]; Complex c5 = qqbargLoops[4]; Complex c6 = qqbargLoops[5];
Complex c7 = qqbargLoops[6]; Complex c8 = qqbargLoops[7]; Complex c9 = qqbargLoops[8];
Complex c10 = qqbargLoops[9]; Complex c11 = qqbargLoops[10]; Complex c12 = qqbargLoops[11];
Complex c13 = qqbargLoops[12];
if ( gHel == 1 ) {
return
-((sqrt(2) * c6 * plusP_jk * minusC_ik)/jk)
- (sqrt(2) * c8 * sqr(plusP_jk) * momentum(i) * minusP_ij)/jk -
(sqrt(2) * c10 * sqr(plusP_jk) * momentum(j) * minusP_ij)/jk -
(2 * sqrt(2) * c12 * sqr(plusP_jk) * momentum(k) * minusP_ij)/sqr(jk) +
(sqrt(2) * c5 * plusP_jk * minusC_ij * minusP_ij)/(jk * minusP_ik);
}
if ( gHel == -1 ) {
return
(sqrt(2) * c4 * plusP_ij * minusC_ij * minusP_ik)/(ik * plusP_jk) +
(sqrt(2) * c13 * minusC_kj * minusP_ik)/ik + (sqrt(2) * c13 * minusC_kj * minusP_ik)/jk +
(sqrt(2) * c6 * minusC_kj * minusP_ik)/jk - (sqrt(2) * c7 * plusP_ij * momentum(i)*
sqr(minusP_ik))/ik -
(sqrt(2) * c9 * plusP_ij * momentum(j) * sqr(minusP_ik))/ik -
(2 * sqrt(2) * c11 * plusP_ij * momentum(k) * sqr(minusP_ik))/(ik * jk);
}
return czero;
}
LorentzVector<Complex> MatchboxCurrents::qqbargGeneralRightLoopCurrent(const int i, const int,
const int j, const int,
const int k, const int gHel,
const int n) {
qqbargLoopCoefficients(i,j,k);
const double ik = invariant(i,k);
const double jk = invariant(j,k);
const Complex plusP_ik = plusProduct(i,k);
const Complex plusP_in = plusProduct(i,n);
const Complex plusP_jk = plusProduct(j,k);
const Complex plusP_jn = plusProduct(j,n);
const Complex plusP_kn = plusProduct(k,n);
const Complex minusP_ik = minusProduct(i,k);
const Complex minusP_in = minusProduct(i,n);
const Complex minusP_jk = minusProduct(j,k);
const Complex minusP_jn = minusProduct(j,n);
const Complex minusP_kn = minusProduct(k,n);
const LorentzVector<Complex> & minusC_ji = minusCurrent(j,i);
const LorentzVector<Complex> & minusC_jk = minusCurrent(j,k);
const LorentzVector<Complex> & minusC_nk = minusCurrent(n,k);
const LorentzVector<Complex> & minusC_kn = minusCurrent(k,n);
Complex c1 = qqbargLoops[0]; Complex c2 = qqbargLoops[1]; Complex c3 = qqbargLoops[2];
Complex c4 = qqbargLoops[3]; Complex c5 = qqbargLoops[4]; Complex c6 = qqbargLoops[5];
Complex c7 = qqbargLoops[6]; Complex c8 = qqbargLoops[7]; Complex c9 = qqbargLoops[8];
Complex c10 = qqbargLoops[9]; Complex c11 = qqbargLoops[10]; Complex c12 = qqbargLoops[11];
Complex c13 = qqbargLoops[12];
if ( gHel == 1 ) {
return
-((sqrt(2) * c13 * plusP_ik * minusC_jk)/ik) - (sqrt(2) * c13 * plusP_ik * minusC_jk)/jk +
(sqrt(2) * c4 * plusP_ik * minusC_ji * minusP_in)/(ik * minusP_kn) +
(sqrt(2) * c6 * plusP_ik * minusC_nk * minusP_jk)/(jk * minusP_kn) -
(sqrt(2) * c7 * sqr(plusP_ik) * momentum(i) * minusP_in * minusP_jk)/(ik * minusP_kn) -
(sqrt(2) * c9 * sqr(plusP_ik) * momentum(j) * minusP_in * minusP_jk)/(ik * minusP_kn) -
(2 * sqrt(2) * c11 * sqr(plusP_ik) * momentum(k) * minusP_in * minusP_jk)/(ik * jk * minusP_kn) +
(sqrt(2) * c1 * plusP_ik * momentum(i) * minusP_jn)/minusP_kn +
(sqrt(2) * c2 * plusP_ik * momentum(j) * minusP_jn)/minusP_kn +
(2 * sqrt(2) * c3 * plusP_ik * momentum(k) * minusP_jn)/(jk * minusP_kn) +
(sqrt(2) * c5 * plusP_jk * minusC_ji * minusP_jn)/(jk * minusP_kn) -
(sqrt(2) * c8 * plusP_ik * plusP_jk * momentum(i) * minusP_jk * minusP_jn)/(jk * minusP_kn) -
(sqrt(2) * c10 * plusP_ik * plusP_jk * momentum(j) * minusP_jk * minusP_jn)/(jk * minusP_kn) -
(2 * sqrt(2) * c12 * plusP_ik * plusP_jk * momentum(k) * minusP_jk * minusP_jn)/(sqr(jk) * minusP_kn);
}
if ( gHel == -1 ) {
return
-((sqrt(2) * c4 * plusP_in * minusC_ji * minusP_ik)/(ik * plusP_kn)) -
(sqrt(2) * c1 * plusP_in * momentum(i) * minusP_jk)/plusP_kn -
(sqrt(2) * c2 * plusP_in * momentum(j) * minusP_jk)/plusP_kn -
(2 * sqrt(2) * c3 * plusP_in * momentum(k) * minusP_jk)/(jk * plusP_kn) -
(sqrt(2) * c5 * plusP_jn * minusC_ji * minusP_jk)/(jk * plusP_kn) -
(sqrt(2) * c6 * plusP_ik * minusC_kn * minusP_jk)/(jk * plusP_kn) +
(sqrt(2) * c7 * plusP_ik * plusP_in * momentum(i) * minusP_ik * minusP_jk)/(ik * plusP_kn) +
(sqrt(2) * c9 * plusP_ik * plusP_in * momentum(j) * minusP_ik * minusP_jk)/(ik * plusP_kn) +
(2 * sqrt(2) * c11 * plusP_ik * plusP_in * momentum(k) * minusP_ik * minusP_jk)/
(ik * jk * plusP_kn) +
(sqrt(2) * c8 * plusP_ik * plusP_jn * momentum(i) * sqr(minusP_jk))/(jk * plusP_kn) +
(sqrt(2) * c10 * plusP_ik * plusP_jn * momentum(j) * sqr(minusP_jk))/(jk * plusP_kn) +
(2 * sqrt(2) * c12 * plusP_ik * plusP_jn * momentum(k) * sqr(minusP_jk))/(sqr(jk) * plusP_kn);
}
return czero;
}
LorentzVector<Complex> MatchboxCurrents::qqbargFixedRightLoopCurrent(const int i, const int,
const int j, const int,
const int k, const int gHel) {
qqbargLoopCoefficients(i,j,k);
const double ik = invariant(i,k);
const double jk = invariant(j,k);
const Complex plusP_ij = plusProduct(i,j);
const Complex plusP_ik = plusProduct(i,k);
const Complex minusP_ij = minusProduct(i,j);
const Complex minusP_jk = minusProduct(j,k);
const LorentzVector<Complex> & minusC_ji = minusCurrent(j,i);
const LorentzVector<Complex> & minusC_jk = minusCurrent(j,k);
const LorentzVector<Complex> & minusC_ki = minusCurrent(k,i);
//Complex c1 = qqbargLoops[0]; Complex c2 = qqbargLoops[1]; Complex c3 = qqbargLoops[2];
Complex c4 = qqbargLoops[3]; Complex c5 = qqbargLoops[4]; Complex c6 = qqbargLoops[5];
Complex c7 = qqbargLoops[6]; Complex c8 = qqbargLoops[7]; Complex c9 = qqbargLoops[8];
Complex c10 = qqbargLoops[9]; Complex c11 = qqbargLoops[10]; Complex c12 = qqbargLoops[11];
Complex c13 = qqbargLoops[12];
if ( gHel == 1 ) {
return
-((sqrt(2) * c13 * plusP_ik * minusC_jk)/ik) -
(sqrt(2) * c13 * plusP_ik * minusC_jk)/jk -
(sqrt(2) * c6 * plusP_ik * minusC_jk)/jk +
(sqrt(2) * c7 * sqr(plusP_ik) * momentum(i) * minusP_ij)/ik +
(sqrt(2) * c9 * sqr(plusP_ik) * momentum(j) * minusP_ij)/ik +
(2 * sqrt(2) * c11 * sqr(plusP_ik) * momentum(k) * minusP_ij)/(ik * jk) -
(sqrt(2) * c4 * plusP_ik * minusC_ji * minusP_ij)/(ik * minusP_jk);
}
if ( gHel == -1 ) {
return
-((sqrt(2) * c5 * plusP_ij * minusC_ji * minusP_jk)/(jk * plusP_ik)) +
(sqrt(2) * c6 * minusC_ki * minusP_jk)/jk +
(sqrt(2) * c8 * plusP_ij * momentum(i) * sqr(minusP_jk))/jk +
(sqrt(2) * c10 * plusP_ij * momentum(j) * sqr(minusP_jk))/jk +
(2 * sqrt(2) * c12 * plusP_ij * momentum(k) * sqr(minusP_jk))/sqr(jk);
}
return czero;
}
const LorentzVector<Complex>& MatchboxCurrents::qqbargLeftOneLoopCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g1, const int g1Hel) {
if ( qHel != 1 || qbarHel != 1 )
return czero;
if ( getCurrent(hash<2>(1,2,q,qHel,qbar,qbarHel,g1,g1Hel)) ) {
#ifdef CHECK_MatchboxCurrents
LorentzVector<Complex> ni = Complex(0.,0.5) * qqbargGeneralLeftLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,q);
LorentzVector<Complex> nj = Complex(0.,0.5) * qqbargGeneralLeftLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,qbar);
LorentzVector<Complex> nl = Complex(0.,0.5) * qqbargGeneralLeftLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,0);
LorentzVector<Complex> nlbar = Complex(0.,0.5) * qqbargGeneralLeftLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,1);
LorentzVector<Complex> fixed = Complex(0.,0.5) * qqbargFixedLeftLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel);
LorentzVector<Complex> x1 = fixed - ni;
LorentzVector<Complex> x2 = fixed - nj;
LorentzVector<Complex> x3 = fixed - nl;
LorentzVector<Complex> x4 = fixed - nlbar;
double c1 =
real(x1.t() * conj(x1.t())) + real(x1.x() * conj(x1.x())) + real(x1.y() * conj(x1.y())) + real(x1.z() * conj(x1.z()));
double c2 =
real(x2.t() * conj(x2.t())) + real(x2.x() * conj(x2.x())) + real(x2.y() * conj(x2.y())) + real(x2.z() * conj(x2.z()));
double c3 =
real(x3.t() * conj(x3.t())) + real(x3.x() * conj(x3.x())) + real(x3.y() * conj(x3.y())) + real(x3.z() * conj(x3.z()));
double c4 =
real(x4.t() * conj(x4.t())) + real(x4.x() * conj(x4.x())) + real(x4.y() * conj(x4.y())) + real(x4.z() * conj(x4.z()));
ostream& ncheck = checkStream("qqbargLeftLoopCurrentNChoice");
ncheck << (c1 != 0. ? log10(abs(c1)) : 0.) << " "
<< (c2 != 0. ? log10(abs(c2)) : 0.) << " "
<< (c3 != 0. ? log10(abs(c3)) : 0.) << " "
<< (c4 != 0. ? log10(abs(c4)) : 0.) << " "
<< "\n" << flush;
#endif
cacheCurrent(Complex(0.,0.5) * qqbargFixedLeftLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel));
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbargLeftLoopCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(g1));
#endif
return cachedCurrent();
}
const LorentzVector<Complex>& MatchboxCurrents::qqbargRightOneLoopCurrent(const int q, const int qHel,
const int qbar, const int qbarHel,
const int g1, const int g1Hel) {
if ( qHel != -1 || qbarHel != -1 )
return czero;
if ( getCurrent(hash<2>(2,2,q,qHel,qbar,qbarHel,g1,g1Hel)) ) {
#ifdef CHECK_MatchboxCurrents
LorentzVector<Complex> ni = Complex(0.,0.5) * qqbargGeneralRightLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,q);
LorentzVector<Complex> nj = Complex(0.,0.5) * qqbargGeneralRightLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,qbar);
LorentzVector<Complex> nl = Complex(0.,0.5) * qqbargGeneralRightLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,0);
LorentzVector<Complex> nlbar = Complex(0.,0.5) * qqbargGeneralRightLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel,1);
LorentzVector<Complex> fixed = Complex(0.,0.5) * qqbargFixedRightLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel);
LorentzVector<Complex> x1 = fixed - ni;
LorentzVector<Complex> x2 = fixed - nj;
LorentzVector<Complex> x3 = fixed - nl;
LorentzVector<Complex> x4 = fixed - nlbar;
double c1 =
real(x1.t() * conj(x1.t())) + real(x1.x() * conj(x1.x())) + real(x1.y() * conj(x1.y())) + real(x1.z() * conj(x1.z()));
double c2 =
real(x2.t() * conj(x2.t())) + real(x2.x() * conj(x2.x())) + real(x2.y() * conj(x2.y())) + real(x2.z() * conj(x2.z()));
double c3 =
real(x3.t() * conj(x3.t())) + real(x3.x() * conj(x3.x())) + real(x3.y() * conj(x3.y())) + real(x3.z() * conj(x3.z()));
double c4 =
real(x4.t() * conj(x4.t())) + real(x4.x() * conj(x4.x())) + real(x4.y() * conj(x4.y())) + real(x4.z() * conj(x4.z()));
ostream& ncheck = checkStream("qqbargRightLoopCurrentNChoice");
ncheck << (c1 != 0. ? log10(abs(c1)) : 0.) << " "
<< (c2 != 0. ? log10(abs(c2)) : 0.) << " "
<< (c3 != 0. ? log10(abs(c3)) : 0.) << " "
<< (c4 != 0. ? log10(abs(c4)) : 0.) << " "
<< "\n" << flush;
#endif
cacheCurrent(Complex(0.,0.5) * qqbargFixedRightLoopCurrent(q,qHel,qbar,qbarHel,g1,g1Hel));
}
#ifdef CHECK_MatchboxCurrents
checkCurrent("qqbargRightLoopCurrent",cachedCurrent(),momentum(q)+momentum(qbar)+momentum(g1));
#endif
return cachedCurrent();
}
#ifdef CHECK_MatchboxCurrents
map<string,ofstream * >& MatchboxCurrents::checkStreams() {
static map<string,ofstream * > theMap;
return theMap;
}
ostream& MatchboxCurrents::checkStream(const string& id) {
map<string,ofstream * >::iterator ret = checkStreams().find(id);
if ( ret == checkStreams().end() ) {
checkStreams()[id] = new ofstream(id.c_str());
ret = checkStreams().find(id);
}
return *(ret->second);
}
void MatchboxCurrents::checkCurrent(const string& id,
const LorentzVector<Complex>& current,
const LorentzVector<double>& q) {
Complex c = current.dot(q);
double ac = abs(real(conj(c) * c));
- if ( isnan(ac) || isinf(ac) ) {
+ if ( ! isfinite(ac) ) {
cerr << "ooops ... nan encountered in current conservation\n" << flush;
return;
}
checkStream(id) << (ac > 0. ? log10(ac) : 0.) << "\n";
}
#endif // CHECK_MatchboxCurrents
diff --git a/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h b/MatrixElement/Matchbox/Builtin/Amplitudes/MatchboxCurrents.h
old mode 100755
new mode 100644
diff --git a/MatrixElement/Matchbox/ColorFull/Col_basis.cc b/MatrixElement/Matchbox/ColorFull/Col_basis.cc
--- a/MatrixElement/Matchbox/ColorFull/Col_basis.cc
+++ b/MatrixElement/Matchbox/ColorFull/Col_basis.cc
@@ -1,1036 +1,1036 @@
// -*- C++ -*-
/*
* Col_basis.cc
* Contains definition of the base class Col_basis and associated types and operators.
* Created on: Aug 9, 2012
* Author: Malin Sjodahl
*/
#include "Col_basis.h"
#include "parameters.h"
#include <cassert>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <iomanip>
namespace ColorFull {
void Col_basis::scalar_product_matrix_no_mem(){
if(ng+nq>6){
std::cout << "Col_basis::scalar_product_matrix: nq+ng=" << nq+ng << " is large, consider using numerical and/or memory version. " << std::endl;
std::cout.flush();
}
return scalar_product_matrix( true, true, false );
}
void Col_basis::scalar_product_matrix(){
return scalar_product_matrix( true, true, true );
}
void Col_basis::scalar_product_matrix_num_no_mem(){
return scalar_product_matrix( false, true, false );
}
void Col_basis::scalar_product_matrix_num(){
return scalar_product_matrix( false, true, true );
}
void Col_basis::leading_scalar_product_matrix(){
if( cb.size()==0 ) {
std::cerr << "Col_basis::leading_scalar_product_matrix: There are no basis vectors in this basis, consider using create_basis or read_in_Col_basis." << std::endl;
std::cerr.flush();
return ;
}
if( P_spm.empty() ) {
scalar_product_matrix( true, true, true );
}
leading_P_spm = Col_fun.leading( P_spm );
leading_d_spm = Col_fun.double_num( leading_P_spm );
}
std::string Col_basis::basis_file_name() const{
// First construct filename
std::ostringstream ss;
std::string filename;
ss << "ColorResults";
ss << '/';
// ColorFull
ss << "CF_";
// Basis Type
if( trace_basis ) ss << "TB_";
else if ( tree_level_gluon_basis ) ss << "TGB_";
else if ( orthogonal_basis ) ss << "OB_";
else ss << "CB_";
ss << "q_";
ss << nq;
ss << "_g_";
ss << ng;
// If Nc is not 3, append Nc info
if( Col_fun.get_Nc() != 3 ){
ss << "_Nc_";
ss << Col_fun.get_Nc();
}
// If TR is not 1/2, append TR info
if( Col_fun.get_TR() != 0.5 ){
ss << "_TR_";
ss << Col_fun.get_TR();
}
filename=ss.str();
return filename.c_str();
}
std::string Col_basis::spm_file_name(const bool leading, const bool poly ) const{
// First construct filename
std::ostringstream ss;
std::string filename;
ss << "ColorResults";
ss << '/';
// CF as in ColorFull
ss << "CF_";
// Prefix according to basis type
if( trace_basis ) ss << "TB_";
else if ( tree_level_gluon_basis ) ss << "TGB_";
else if ( orthogonal_basis ) ss << "OB_";
else ss << "CB_";
// Polynomial or numerical matrix?
if( poly )ss << "P_";
else ss << "d_";
ss << "spm_q";
ss << nq;
ss << "_g";
ss << ng;
if ( leading ) ss << "_l";
if ( Col_fun.get_full_CF() ) ss << "_cff";
else ss << "_cfl";
if(Col_fun.get_Nc() != 3 ){
ss << "_Nc_";
ss << Col_fun.get_Nc();
}
if(Col_fun.get_TR() != 0.5 ){
ss << "_TR_";
ss << Col_fun.get_TR();
}
filename=ss.str();
return filename;
}
void Col_basis::write_out_Col_basis() const{
write_out_Col_basis( basis_file_name() );
}
void Col_basis::write_out_Col_basis( std::string filename ) const {
if ((cb.size() == 0)) {
std::cerr
<< "Col_basis::write_out_Col_basis(filename): There are no basis vectors in this basis, consider using create_basis or read_in_Col_basis."
<< std::endl;
return;
}
std::ofstream outfile(filename.c_str());
if ( !outfile )
std::cerr << "Col_basis::write_out_Col_basis: Cannot write out basis as the file \""
<< filename.c_str() << "\" could not be opened. (Does the directory exist? Consider creating the directory.)" << std::endl;
outfile << std::setprecision(16);
for ( uint m = 0; m < cb.size(); m++ ) {
outfile << m << " " << cb.at(m) << std::endl;
}
outfile.flush();
}
void Col_basis::write_out_Col_basis_to_cout() const{
if( (cb.size()==0 ) ) {
std::cerr << "Col_basis::write_out_Col_basis(): There are no basis vectors in this basis, consider using create_basis or read_in_Col_basis." << std::endl;
std::cerr.flush();
return ;
}
for (uint m = 0; m < cb.size(); m++) {
std::cout << m << " "<< cb.at(m) << std::endl;
}
}
void Col_basis::write_out_d_spm( std::string filename ) const{
Col_fun.write_out_dmatr( d_spm, filename );
}
void Col_basis::write_out_d_spm( ) const{
std::string filename = spm_file_name( false, false );
write_out_d_spm( filename );
}
void Col_basis::write_out_P_spm( std::string filename ) const{
P_spm.write_out_Poly_matr( filename );
}
void Col_basis::write_out_P_spm( ) const{
std::string filename = spm_file_name( false, true );
write_out_P_spm( filename );
}
void Col_basis::write_out_leading_d_spm( std::string filename ) const{
Col_fun.write_out_dmatr( leading_d_spm, filename );
}
void Col_basis::write_out_leading_d_spm( ) const{
std::string filename = spm_file_name( true, false );
write_out_leading_d_spm( filename );
}
void Col_basis::write_out_leading_P_spm( std::string filename ) const{
leading_P_spm.write_out_Poly_matr( filename );
}
void Col_basis::write_out_leading_P_spm( ) const{
std::string filename = spm_file_name( true, true );
write_out_leading_P_spm( filename );
}
void Col_basis::read_in_Col_basis( std::string filename ) {
// Read in file
std::ifstream fin(filename.c_str());
// Check that file exists
if( !fin ){
std::cerr << "Col_basis::read_in_Col_basis: The file "
<< filename << " could not be opened." << std::endl;
assert( 0 );
}
// Erase current information
cb.clear();
// Copy info from file to string
std::string str((std::istreambuf_iterator<char>(fin)), std::istreambuf_iterator<char>());
Col_basis_of_str( str );
}
void Col_basis::read_in_d_spm( std::string filename){
d_spm= Col_fun.read_in_dmatr( filename );
}
void Col_basis::read_in_d_spm( ){
d_spm=Col_fun.read_in_dmatr( spm_file_name( false, false ).c_str() );
}
void Col_basis::read_in_leading_d_spm( std::string filename){
leading_d_spm=Col_fun.read_in_dmatr( filename );
}
void Col_basis::read_in_leading_d_spm( ){
leading_d_spm=Col_fun.read_in_dmatr( spm_file_name( true, false ).c_str() );
}
void Col_basis::read_in_P_spm( std::string filename ){
P_spm.read_in_Poly_matr( filename );
}
void Col_basis::read_in_P_spm( ){
P_spm.read_in_Poly_matr( spm_file_name( false, true) );
}
void Col_basis::read_in_leading_P_spm( std::string filename){
leading_P_spm.read_in_Poly_matr( filename );
}
void Col_basis::read_in_leading_P_spm( ){
leading_P_spm.read_in_Poly_matr( spm_file_name( true, true) );
}
int Col_basis::n_quark_check() const {
if (empty()) return 0;
int nq=cb.at(0).n_quark_check();
for( uint n=0; n< cb.size(); n++ )
if( cb.at(n).n_quark_check() != nq) {
std::cerr << "Col_basis::n_quark_check: The Col_amps in " << cb << " have differently many quarks." << std::endl;
}
return nq;
}
int Col_basis::n_gluon_check() const {
if ( empty()) return 0;
int nq=cb.at(0).n_gluon_check();
for( uint n=0; n< cb.size(); n++ )
if( cb.at(n).n_gluon_check() != nq) {
std::cerr << "Col_basis::n_gluon_check: The Col_amps in " << cb << " have differently many gluons." << std::endl;
}
return nq;
}
void Col_basis::simplify(){
for( uint i=0; i< cb.size(); i++ ){
cb.at(i).simplify();
}
}
Poly_vec Col_basis::decompose( const Col_amp & ){
std::cerr << "Col_basis::decompose: This function is not implemented for the Col_basis class. Try using a derived class (such as Trace_basis). " << std::endl;
Poly_vec Pv;
assert( 0 );
return Pv;
}
Col_amp Col_basis::exchange_gluon( uint vec, int p1, int p2 ) {
if( (cb.size()==0 ) ) {
std::cerr << "Col_basis::exchange_gluon: There are no basis vectors in this basis, consider using create_basis or read_in_Col_basis." << std::endl;
std::cerr.flush();
assert( 0 );
}
// Check that the basis vector exists
if ( vec >= cb.size() ) {
std::cerr << "Col_basis::exchange_gluon: Basis vector number "<< vec
<< " does not exist, as the basis only have " << cb.size()
<< " basis vectors." << std::endl;
assert( 0 );
}
return Col_fun.exchange_gluon( cb.at(vec), p1, p2);
}
Poly_matr Col_basis::Col_gamma( int p1, int p2 ) {
if( (cb.size()==0 ) ) {
std::cerr << "Col_basis::Col_gamma: There are no basis vectors in this basis, consider using create_basis or read_in_Col_basis." << std::endl;
std::cerr.flush();
assert( 0 );
}
// Function not available for Tree_level_gluon basis
if( tree_level_gluon_basis ) {
std::cerr << "Col_basis::Col_gamma: This function is not available for Tree_level_gluon_basis "
<< "as the vector resulting after gluon exchange contains vectors which are not in the basis. "
<< "Consider using Trace_basis."<< std::endl;
std::cerr.flush();
assert( 0 );
}
// Function should only be used for Orthogonal_basis and Trace_basis
if( ( !trace_basis ) and (! orthogonal_basis) ) {
std::cerr << "Col_basis::Col_gamma: This function is only implemented for Trace_basis and Orthogonal_basis. "
<< "If your basis is not orthogonal, the result will not be correct. "
<< "If your basis is orthogonal, consider using Orthogonal_basis."
<< std::endl;
std::cerr.flush();
}
// To contain the resulting matrix
Poly_matr gamma_res;
// Fill gamma_res with 0s
Polynomial Zero;
Zero=Zero*0;
for( uint i=0; i < cb.size(); i++ ){
Poly_vec rowi;
for( uint j=0; j < cb.size(); j++ ){
rowi.push_back(Zero);
}
gamma_res.push_back(rowi);
}
// To contain the Col_amp after gluon exchange
Col_amp Ca_ae;
// First exchange a gluon between partons p1 and p2 in the vector v1
for ( uint vi=0; vi < cb.size(); vi++ ){
Ca_ae=exchange_gluon( vi, p1, p2 );
// Then decompose the result into the basis,
Poly_vec col_vi = decompose( Ca_ae );
// This gives the vi:th column in Col_gamma
// Loop over rows in that column
for ( uint vj=0; vj < cb.size(); vj++ ){
gamma_res.at(vj).pv.at(vi) = col_vi.at(vj);
}
}
return gamma_res;
}
void Col_basis::Col_basis_of_str( std::string str ){
if (str.size() == 0) {
std::cerr << "Col_basis::Col_basis_of_str: The basis string is empty. This should not happen." << std::endl;
assert( 0 );
}
// Skip lines starting with #
while(str.at(0)== '#'){
while (str.at(0) != '\n'){
str.erase( str.begin() );
}
// erase endl sign(s)
while(str.at(0)== '\n'){
str.erase(str.begin());
}
}
// First char in string should be '0'
if (str.at(0) != '0') {
std::cerr
<< "Col_basis::Col_basis_of_str: First char in basis data file after comments should be '0', as in basis vector 0 as in vector number 0, but it was: "
<< str.at(0) << std::endl;
assert( 0 );
}
// Read the string, starting from 0th element
uint i = 0;
while (i < str.size() - 2) {
//i += 1; testing to move down 130917
// We may have some white spaces
while (i< str.size()-2 &&(str.at(i) == ' ')) i++;
// After white spaces there should be a number, the vector number
while (i< str.size()-2 &&(str.at(i) == '0' or str.at(i) == '1' or str.at(i) == '2' or str.at(i) == '3' or str.at(i) == '4' or str.at(i) == '5' or str.at(i) == '6' or str.at(i) == '7' or str.at(i) == '8' or str.at(i) == '9') ) i++;
// We may have some more white spaces
while (i< str.size()-2 &&(str.at(i) == ' ')) i++;
// String to make a Col_amp of
std::string Ca_str;
Ca_str.clear();
// Keep reading the Ca_str while not '\n which marks new vector
//while ( i< str.size()-1 && (str.at(i) != '\n') )
while ( i< str.size() && (str.at(i) != '\n') ){
Ca_str.push_back(str.at(i));
i++;
}
// Make the Col_amp (basis vector)
Col_amp Ca( Ca_str );
// Simplify, for example move Polynomials to multiply Col_strs, rather than Quark-lines
Ca.simplify();
push_back(Ca);
i++;
}
// Check that the basis is not empty
if( empty()){
std::cerr << "Col_basis::Col_basis_of_str: The basis is empty. " << std::endl;
assert( 0 );
}
// Check that first vector is not empty
if(cb.at(0).ca.empty()){
std::cerr << "Col_basis::Col_basis_of_str: The first Col_amp (vector) in the basis is empty. " << std::endl;
assert( 0 );
}
// Check that first col_str in first vector is not empty
if(cb.at(0).ca.at(0).cs.empty()){
std::cerr << "Col_basis::Col_basis_of_str: The first Col_str in the first basis vector is empty. " << std::endl;
assert( 0 );
}
// Check that first quark_line in the first col_str in first vector is not empty
if(cb.at(0).ca.at(0).cs.at(0).ql.empty()){
std::cerr << "Col_basis::Col_basis_of_str: The first Quark_line in the first Col_str in the first basis vector is empty. " << std::endl;
assert( 0 );
}
// Find the number of quarks and gluons
nq=n_quark_check();
ng=n_gluon_check();
// Test if it's a trace basis
if( trace_basis ){
bool is_trace_basis=true;
for ( uint j=0; j< cb.size(); j++ ){
if( cb.at(j).size() !=1 ) is_trace_basis=false;
if(! is_trace_basis ){
std::cerr << "Col_basis::Col_basis_of_str: You are trying to read in a non-trace basis to a trace basis object. "
<<"The length of the Col_amp " << cb.at(j) << " is not 1."
<< std::endl;
assert( 0 );
}
}
}
}
void Col_basis::read_in_Col_basis( ) {
read_in_Col_basis( basis_file_name() );
}
void Col_basis::scalar_product_matrix( bool save_P_spm, bool save_d_spm, bool use_mem ) {
if( (cb.size()==0 ) ) {
std::cerr << "Col_basis::scalar_product_matrix: There are no basis vectors in this basis, consider using create_basis or read_in_Col_basis." << std::endl;
std::cerr.flush();
return ;
}
// Simplify the basis vectors
simplify();
// If the P_spm and d_spm have already been calculated, erase them
if( !P_spm.empty() ) P_spm.clear();
if( !d_spm.empty() ) d_spm.clear();
// Check that all Polynomials are real
// (check doesn't cover the case of complex Poly in a Quark_line)
// but if an entry is not real this will be discovered as the d_spm is calculated
for ( uint cbi=0; cbi < cb.size(); cbi++){
for ( uint j=0; j< cb.at(cbi).size(); j++){
if( imag (Col_fun.cnum_num( cb.at(cbi).at(j).Poly )) > accuracy ){
std::cerr << "Col_basis::scalar_product_matrix: ColorFull expects real Polynomial multiplying the color structure, but the Polynomial\n"
<< cb.at(cbi).at(j).Poly << std::endl
<< " appearing in front of the Col_str " << cb.at(cbi).at(j).cs
<< " in basis vector number " << cbi << " is not real."<< std::endl << std::endl;
std::cerr.flush();
assert( 0 );
}
}
}
// For remembering already calculated topologies
- std::map<std::string, boost::shared_ptr<Polynomial> > mem_map;
+ std::map<std::string, std::shared_ptr<Polynomial> > mem_map;
// Loop over basis vectors in Basis
for( uint i=0; i < cb.size(); i++){
// To contain a row of the resulting scalar product matrix
Poly_vec rowi;
// Loop over basis vectors in Basis, normally over all vectors,
// but for orthogonal_basis only for i==j
uint minj=0, maxj=cb.size();
for( uint j=minj; j< maxj; j++){
Polynomial ijRes;
ijRes=ijRes*0;
if(use_mem){
// Loop over Col_strs in first Ca
for( uint Ca1i=0; Ca1i< cb.at(i).size(); Ca1i++){
// Loop over Col_strs in second Ca
for( uint Ca2i=0; Ca2i< cb.at(j).size(); Ca2i++){
// To contain the contribution to the ij-th entry if memoization is used
- boost::shared_ptr<Polynomial> ijEntry_contr;
+ std::shared_ptr<Polynomial> ijEntry_contr;
// Rename indices, and make string of new col_strs, to use in map
// strip off Polynomial information to make the map minimal
Col_str Cs1, Cs2;
Cs1.append(cb.at(i).at(Ca1i).cs);
Cs2.append(cb.at(j).at(Ca2i).cs);
rename_indices( Cs1, Cs2 );
std::ostringstream Cs_string;
Cs_string << Cs1 << Cs2;
// Calculate element contribution to the ij:th element in scalar product matrix
// If this has scalar product has occurred before, reuse old value
if (mem_map.count( Cs_string.str() ) > 0) {
ijEntry_contr = mem_map[Cs_string.str()];
}
// Otherwise, calculate value and save topology
else {
if( !tree_level_gluon_basis ){
Polynomial p = Col_fun.scalar_product(Cs1, Cs2);
ijEntry_contr = shared_ptr<Polynomial> (new Polynomial(p));
mem_map[Cs_string.str()] = ijEntry_contr;
}
else if( tree_level_gluon_basis ){
int sign = (ng % 2 ? -1 : 1);
Col_str Cs2_conj=Cs2;
Cs2_conj.conjugate();
Polynomial P = 2* Col_fun. scalar_product( Cs1, Cs2 )
+ sign*2*Col_fun. scalar_product( Cs1, Cs2_conj );
ijEntry_contr = shared_ptr<Polynomial> (new Polynomial(P));
mem_map[Cs_string.str()] = ijEntry_contr;
}
}
// Sum up all the contributions to one Polynomial, recall to multiply with Polynomials
Polynomial ijEntry_contr_poly=(*ijEntry_contr)* cb.at(i).at(Ca1i).Poly*cb.at(j).at(Ca2i).Poly;
// If Polynomial version is not needed convert all algebraic information
// to numerical in the vectors
if( !save_P_spm ) {
double ijEntry_contr_d= Col_fun.double_num( ijEntry_contr_poly );
Monomial Mon( ijEntry_contr_d );
ijRes+= Mon;
}
else ijRes += ijEntry_contr_poly;
} // end looping over Cs in first Ca
} // end looping over Cs in 2nd Ca
// If Polynomial result is wanted, simplify
if ( save_P_spm ) ijRes.simplify();
// Otherwise convert to numerical
else {
double num_ijRes= Col_fun.double_num(ijRes);
ijRes.clear();
Monomial Mon( num_ijRes );
ijRes.push_back(Mon);
}
rowi.push_back( ijRes );
} // end if ( use_mem )
else{
// Calculate element ij in scalar product matrix
ijRes=ij_entry( i, j );
rowi.push_back( ijRes );
// Convert to numerical if not saving Polynomial version
if ( ! save_P_spm ) {
double num_ijRes= Col_fun.double_num(ijRes);
ijRes.clear();
Monomial Mon( num_ijRes );
ijRes.push_back(Mon);
}
} //end if (not mem)
}
P_spm.push_back(rowi);
}
// For saving and checking symmetry of numerical version
// d_spm has to be calculated even if it's not saved to facilitate
// symmetry check
d_spm= Col_fun.double_num( P_spm );
// Making consistency checks (needs double version)
check_spm();
// Erasing the double spm
if( ! save_d_spm ) {
d_spm.clear();
}
// Erasing the Polynomial spm
if( !save_P_spm ) {
P_spm.clear();
}
return;
}
Polynomial Col_basis::ij_entry( const int i, const int j ) const{
Polynomial ijEntry;
ijEntry=Col_fun.scalar_product(cb.at(i), cb.at(j));
ijEntry.simplify();
return ijEntry;
}
bool Col_basis::check_symmetry( const dmatr & matr ) const {
if( matr.size()==0 ){
std::cout << "Col_basis::check_symmetry( dmatr ): The numerical matrix is empty..." << std::endl;
}
else{
//std::cout << "Col_basis::check_symmetry( dmatr ): Numerically verifying symmetry of matrix...";
}
// Verifying that the matrix is symmetric to accuracy "accuracy",
// if not sym is put to false
bool sym=true;
// Loop over basis vectors in Basis
for (uint i = 0; i < d_spm.size(); i++) {
Poly_vec rowi;
// Loop over basis vectors in Basis
for (uint j = 0; j <=i; j++) {
if ((fabs(d_spm.at(i).at(j) / d_spm.at(j).at(i) - 1.0) > accuracy) && (d_spm.at(i).at(j) > accuracy) && (d_spm.at(j).at(i) > accuracy)) {
sym=false;
std::cerr
<< "Col_basis::check_symmetry( dmatr ): Error, the resulting scalar product matrix is not symmetric. \n "
<< "Element " << i << "," << j << ": "
<< d_spm.at(i).at(j) << ", Element " << j << "," << i
<< ": " << d_spm.at(j).at(i) << std::endl
<< "This indicates an error in calculation of scalar products. " << std::endl;
}
}
}
//if( matr.size() !=0 and sym ) std::cout << " done." << std::endl;
return sym;
}
bool Col_basis::check_diagonal( const dmatr & matr ) const{
if( matr.size()==0 ){
std::cerr << "Col_basis::check_diagonal( dmatr ): The numerical matrix is empty...";
std::cout.flush();
}
else{
//std::cout << "Col_basis::check_diagonal( dmatr ): Numerically checking if the matrix is diagonal...";
//std::cout.flush();
}
// Verifying that the matrix is diagonal
// if not sym is put to false
bool diag=true;
// Loop over basis vectors in Basis
for (uint i = 0; i < matr.size(); i++) {
Poly_vec rowi;
// Loop over basis vectors in Basis
for (uint j = 0; j <=i; j++) {
// If non-diagonal elements are sufficiently large write warning
if ( std::abs( matr.at(i).at(j) ) > accuracy and i!=j ) {
diag=false;
if( !(trace_basis or tree_level_gluon_basis) ){
std::cout
<< "Col_basis::check_diagonal( matr ): Warning, the matrix is not diagonal. \n "
<< "Element " << i << "," << j << ": "
<< matr.at(i).at(j) << std::endl;
}
}
}
}
if (! diag ){
std::cout << "Col_basis::check_diagonal: the matrix is not diagonal." << std::endl;
}
//else if (diag) std::cout << " done." << std::endl;
return diag;
}
void Col_basis::check_spm() const{
// Verifying that the matrix is symmetric to accuracy
bool sym=check_symmetry(d_spm);
if( !sym ) {
std::cerr <<"Col_basis::check_spm(): scalar product matrix not symmetric. Please report bug." << std::endl;
std::cerr.flush();
assert( 0 );
}
// Verifying that the leading terms only sit on the diagonal
bool diagonal=true;
if( !leading_d_spm.empty() ){
diagonal=check_diagonal(leading_d_spm);
}
if(!diagonal and ( trace_basis or tree_level_gluon_basis ) ) {
std::cout <<"Col_basis::check_spm(): Leading terms appear of the diagonal. This should not happen in a trace type basis."
<< " For numerical bases it can appear to happen as powers of Nc may hide in numerical constants." << std::endl;
std::cout.flush();
}
}
void Col_basis::rename_indices(Col_str & Cs1, Col_str & Cs2) const{
/*
This is a two-step process:
1) Compute new indices
2) Replace indices
The new indices are stored in a vector named new_indices, such that
old_index should be replaced by new_indices[old_index]
*/
std::vector<int> new_indices;
uint n_indices_total = 2*Cs1.n_quark() + Cs1.n_gluon();
new_indices.resize(n_indices_total+1);
assert(2*Cs1.n_quark() + Cs1.n_gluon() == 2*Cs1.n_quark() + Cs1.n_gluon());
int new_ind=0; // The new index
uint Nql= Cs1.cs.size();
// Loop over Quark_lines in Cs1
for(uint i=0; i< Nql; i++ ){
Quark_line & Ql_i = Cs1.cs.at(i);
uint Nind = Ql_i.ql.size();
// Loop over indices in the Quark_line
for(uint j=0; j< Nind; j++ ){
new_ind++;
// The old index in Cs1, to be replaced also in Cs2
uint old_ind=Ql_i.ql.at(j);
// Replace index in Cs1
Ql_i.ql.at(j) = new_ind;
// Insert into replacement map
// If the assert fails, we have not allocated enough space, and will fail.
assert(old_ind <= n_indices_total);
new_indices[old_ind] = new_ind;
}
}
// Loop over Quark_lines in Cs2
Nql= Cs2.cs.size();
for(uint i=0; i< Nql; i++ ){
Quark_line & Ql_i = Cs2.cs.at(i);
uint Nind = Ql_i.ql.size();
// Loop over indices in the Quark_line
for(uint j=0; j< Nind; j++ ){
// Replace index in Cs2
Ql_i.ql.at(j) = new_indices[Ql_i.ql.at(j)];
}
}
}
Polynomial Col_basis::scalar_product( const Col_amp & Ca1, const Col_amp & Ca2 ) {
// Check that we have a basis
if(cb.size()==0){
std::cerr << "Col_basis::scalar_product: The basis vector cb is empty, consider using create_basis or read in basis." << std::endl;
assert( 0 );
}
// Check that the Polynomial scalar product matrix is calculated, if not calculate it
if( P_spm.size() != cb.size() ) {
std::cerr << "Col_basis::scalar_product: This function uses the scalar product matrix which has not yet been calculated." << std::endl;
assert( 0 );
}
// To contain the resulting Polynomial
Polynomial Poly_res;
Poly_res=Poly_res*0;
// Decompose the Col_amps
Poly_vec Polyv1=decompose(Ca1);
Polyv1.conjugate();
Poly_vec Polyv2=decompose( Ca2 );
// Then add contributions
for ( uint m1=0; m1< cb.size(); m1++ ){
// Diagonal terms
Poly_res=Poly_res+Polyv1.at(m1) *Polyv2.at(m1) *P_spm.at(m1).at(m1);
for (uint m2=0; m2< m1; m2++){
// Other terms, use symmetry of scalar product matrix
Poly_res=Poly_res+ ( Polyv1.at(m1) *Polyv2.at(m2)+Polyv1.at(m2) *Polyv2.at(m1) ) *P_spm.at(m1).at(m2);
}
}
return Poly_res;
}
cnum Col_basis::scalar_product_num( const Col_amp & Ca1, const Col_amp & Ca2 ) {
// Check that we have a basis
if(cb.size()==0){
std::cerr << "Col_basis::scalar_product_num: The basis vector cb is empty consider using create_basis or read in basis." << std::endl;
assert( 0 );
}
// Check that the Polynomial scalar product matrix is calculated, if not calculate it
if( d_spm.size() != cb.size() ) {
std::cerr << "Col_basis::scalar_product_num: This function uses the numerical scalar product matrix which has not yet been calculated." << std::endl;
assert( 0 );
}
// To contain the resulting Polynomial
cnum res=0;
uint basis_size=cb.size();
// Decompose the Col_amps
Poly_vec Polyv1, Polyv2;
Polyv1=decompose(Ca1);
if( &Ca1==&Ca2 ) Polyv2=Polyv1;
else Polyv2=decompose(Ca2);
// Conjugate first arg
Polyv1.conjugate();
// Make ordinary vectors to speed up multiplication
cvec v1, v2;
v1.reserve( basis_size );
for (uint i=0; i< basis_size; i++){
v1.push_back( Col_fun.cnum_num( Polyv1.at(i) ) );
}
if (false) v2=v1;
else{
v2.reserve(basis_size);
for (uint i=0; i< basis_size; i++) v2.push_back( Col_fun.cnum_num( Polyv2.at(i) ) );
}
// Then add contributions
cnum v1m1, v2m1;
dvec row;
for (uint m1=0; m1< basis_size; m1++){
v1m1=v1.at(m1);
v2m1=v2.at(m1);
row=d_spm.at( m1 );
// Diagonal terms
res=res+ v1m1 *v2.at(m1) *row.at(m1);
for (uint m2=0; m2< m1; m2++){
res += (v1m1*v2.at(m2) +v1.at(m2)*v2m1 ) *row.at(m2);
}
}
return res;
}
cnum Col_basis::scalar_product_num( const cvec & v1, const cvec & v2) {
if( v1.size()!= v2.size() ){
std::cerr << "Col_basis::scalar_product_num: Size of first vector "
<< v1.size() << " does not agree with size of second vector "
<< v2.size() << std::endl;
assert( 0 );
}
if( v1.size()!= d_spm.size() ){
std::cerr << "Col_basis::scalar_product_num: Size of vectors "
<< v1.size() << " does not agree with size of d_spm matrix "
<< d_spm.size() << std::endl;
assert( 0 );
}
uint basis_size=v1.size();
// To contain the result
cnum res=0;
cnum tmp=0, tmp2=0;
// Add contributions
cnum v1m1, v2m1;
for (uint m1=0; m1< basis_size; m1++){
v1m1= conj( v1.at(m1) );
v2m1=v2.at(m1);
const dvec &row = d_spm.at(m1);
// Diagonal parts
res += v1m1 *v2.at(m1) *row.at(m1);
tmp = 0;
tmp2=0;
for (uint m2=0; m2< m1; m2++){
tmp += (v1m1*v2[m2]+v2m1*conj(v1[m2])) *row[m2];
}
res+=tmp;
}
return res;
}
cnum Col_basis::scalar_product_num_diagonal( const cvec & v1, const cvec & v2 ) {
if(v1.size()!= v2.size()){
std::cerr << "Col_basis::scalar_product_num_diagonal: Size of first vector "
<< v1.size() << " does not agree with size of second vector "
<< v2.size() << std::endl;
assert( 0 );
}
if(v1.size()!= d_spm.size()){
std::cerr << "Col_basis::scalar_product_num_diagonal: Size of vectors "
<< v1.size() << " do not agree with size of d_spm matrix "
<< d_spm.size() << std::endl;
assert( 0 );
}
// To contain the result
cnum res=0;
// Check dimension
uint basis_size=v1.size();
// Then add contributions
for (uint m1=0; m1< basis_size; m1++){
res=res+ conj( v1.at(m1) ) *v2.at(m1) *d_spm.at(m1).at(m1);
}
return res;
}
std::ostream& operator<<( std::ostream& out, const col_basis & cb ) {
int max = cb.size();
for (int i = 0; i < max; i++) {
out <<", " << cb.at(i);
}
return out;
}
}
diff --git a/MatrixElement/Matchbox/ColorFull/Col_functions.cc b/MatrixElement/Matchbox/ColorFull/Col_functions.cc
--- a/MatrixElement/Matchbox/ColorFull/Col_functions.cc
+++ b/MatrixElement/Matchbox/ColorFull/Col_functions.cc
@@ -1,1841 +1,1839 @@
/*
* Col_functions.cc
* Contains definitions of functions and operators used for treating the color structure
* Created on: Jul 8, 2010
* Author: malin
*/
#include "Col_functions.h"
#include "parameters.h"
#include <cassert>
#include <fstream>
#include <iostream>
#include <limits>
namespace ColorFull {
-using boost::shared_ptr;
-
int Col_functions::leading_Nc_pow( const Polynomial & Poly ) const{
if( Poly.poly.empty()) {
if( double_num(Poly)!=0 ) return 0;
else return std::numeric_limits<int>::min();
}
int leading_pow=Poly.at(0).pow_Nc + Poly.at(0).pow_CF;
// Loop over non-zero Monomials
for (uint i=0; i<Poly.poly.size(); i++){
if( Poly.at(i).pow_Nc + Poly.at(i).pow_CF > leading_pow && Poly.at(i).int_part!=0 )
leading_pow=Poly.at(i).pow_Nc + Poly.at(i).pow_CF;
}
return leading_pow;
}
int Col_functions::leading_Nc_pow( const Poly_vec & Pv ) const{
int leading_pow=leading_Nc_pow( Pv.at(0) );
// Loop over Polynomials
for (uint p=0; p<Pv.size(); p++){
if ( leading_Nc_pow( Pv.at(p) ) > leading_pow )
leading_pow=leading_Nc_pow( Pv.at(p) );
}
return leading_pow;
}
-int Col_functions::leading_Nc_pow( std::vector< boost::shared_ptr<Polynomial> > Pvp) const{
+int Col_functions::leading_Nc_pow( std::vector< shared_ptr<Polynomial> > Pvp) const{
int leading_pow=leading_Nc_pow( *(Pvp.at(0)) );
// Loop over Polynomials
for (uint p=1; p<Pvp.size(); p++){
if ( leading_Nc_pow( *(Pvp.at(p)) ) > leading_pow )
leading_pow=leading_Nc_pow( *(Pvp.at(p)) );
}
return leading_pow;
}
Polynomial Col_functions::leading( const Polynomial & Poly ) const{
// If the Polynomial is empty=1, or it it has only one term,
// just return the Poly itself
if( Poly.empty() ) return Poly;
// Candidate for highest power of Nc+CF
int cand_pow = Poly.at(0).pow_Nc + Poly.at(0).pow_CF;
// For containing the leading Nc Polynomial
Polynomial Leading_pol;
Leading_pol.push_back(Poly.at(0));
// If only one term, keep that term
if( Poly.size()==1 ) Leading_pol=Poly;
// If more than one term, look for higher powers
// Looks for Monomials with highest Nc power
if( Poly.size()>1 ){// found bug for Polynomials with one term 13 07 12
for (int k = 1; k < Poly.size(); k++) {
// If power higher
if ((Poly.at(k).pow_Nc + Poly.at(k).pow_CF) > cand_pow) {
cand_pow = Poly.at(k).pow_Nc + Poly.at(k).pow_CF;
Leading_pol.clear();
Leading_pol = Leading_pol * 0;
Leading_pol = Leading_pol + Poly.at(k);
}
// If power equal
else if (Poly.at(k).pow_Nc + Poly.at(k).pow_CF == cand_pow) {
Leading_pol = Leading_pol + Poly.at(k);
}
}
}
// now Leading_pol contains terms with maximal power of CF plus Nc
// If the variable full_CF is false (default), CF should be replaced with TR*Nc.
// If numerical evaluation is done after this, CF will thus be evaluated to TR Nc.
// If full_cf is true, CF will be replaced by CF(Nc).
if ( ! full_CF ) {
// Loop over terms and replace CF with the Nc -> infinity limit of CF =TR*Nc
for (int i = 0; i < Leading_pol.size(); i++) {
int pow_CF = Leading_pol.at(i).pow_CF;
Leading_pol.at(i).pow_Nc += pow_CF;
Leading_pol.at(i).pow_TR += pow_CF;
Leading_pol.at(i).pow_CF = 0;
}
}
Leading_pol.simplify();
return Leading_pol;
}
Poly_vec Col_functions::leading( const Poly_vec & Pv ) const{
// To contain the result
Poly_vec Pv_res;
// Take the leading part of each Polynomial
// after this all Monomials in the SAME Polynomial have the same Nc power
for (uint i = 0; i < Pv.size(); i++) {
// Take the leading terms in each component
Pv_res.push_back( leading( Pv.at(i) ) );
}
// Find the leading power
int leading_pow = leading_Nc_pow(Pv_res);
// Loop over entries and keep only those with maximal power
for (uint p = 0; p < Pv_res.size(); p++) {
if (leading_Nc_pow(Pv_res.at(p)) != leading_pow) {
Pv_res.at(p) = 0 * Pv_res.at(p);
Pv_res.at(p).simplify();
}
}
return Pv_res;
}
Poly_matr Col_functions::leading( const Poly_matr & Pm ) const{
// To contain the result
Poly_matr Pm_res;
Pm_res.pm.reserve(Pm.pm.size());
// Loop over Poly_vecs, and take the leading part of each Poly_vec
for (uint i = 0; i < Pm.size(); i++) {
// Take the leading terms in each Poly_vec
Poly_vec Pvl= leading( Pm.at(i) );
Pm_res.push_back( Pvl );
}
int cand_pow = leading_Nc_pow( Pm.at(0).pv );
// Loop over Poly_vecs to locate highest power
for (uint k = 0; k < Pm_res.size(); k++) {
int pow_at_k = leading_Nc_pow(Pm_res.at(k).pv);
if (pow_at_k > cand_pow)
cand_pow = pow_at_k;
}
// In all Polynomials, in all Poly_vec's,
// put all elements which doesn't have highest power to 0
for (uint k = 0; k < Pm_res.size(); k++) {
// In each Poly_vec, loop over all Polynomials
for (uint p = 0; p < Pm_res.at(k).size(); p++) {
if (leading_Nc_pow(Pm_res.at(k).at(p)) != cand_pow) {
//Pm_res.at(k).pv.at(p) = Pm_res.at(k).pv.at(p) * 0;
Pm_res.at( k,p )=Pm_res.at(k).at(p) * 0;
Pm_res.at(k,p).simplify();
}
}
}
return Pm_res;
}
-Poly_vec Col_functions::leading( std::vector<boost::shared_ptr<Polynomial> > Pvp ) const{
+Poly_vec Col_functions::leading( std::vector<shared_ptr<Polynomial> > Pvp ) const{
Poly_vec Pv_res;
// Loop over entries in vector (Poly_vecs), and take the leading part of each Polynomial
// after this each Monomial has the same Nc+CF-power
for (uint i = 0; i < Pvp.size(); i++) {
// Take the leading terms in each component
- boost::shared_ptr<Polynomial> the_pointer=Pvp.at(i);
+ shared_ptr<Polynomial> the_pointer=Pvp.at(i);
Pv_res.push_back( leading( (*the_pointer) ) );
}
// Find the leading power
int leading_pow = leading_Nc_pow(Pv_res);
// Loop over entries and keep only those with maximal power
for (uint p = 0; p < Pv_res.size(); p++) {
if (leading_Nc_pow(Pv_res.at(p)) != leading_pow) {
Pv_res.at(p) = 0 * Pv_res.at(p);
Pv_res.at(p).simplify();
}
}
return Pv_res;
}
-dmatr Col_functions::leading( std::vector< std::vector< boost::shared_ptr<Polynomial> > > Ppm ) const {
+dmatr Col_functions::leading( std::vector< std::vector< shared_ptr<Polynomial> > > Ppm ) const {
// To contain the result as a matrix of double
dmatr res;
res.reserve( Ppm.size() );
int cand_pow = leading_Nc_pow( Ppm.at(0) );
// Loop over Poly_vecs to locate highest power
for (uint k = 0; k < Ppm.size(); k++) {
int the_pow=leading_Nc_pow(Ppm.at(k));
if ( the_pow > cand_pow )
cand_pow = the_pow;
}
// In all Polynomials, in all Poly_vec's,
// put all elements which doesn't have highest power to 0
for (uint k = 0; k < Ppm.size(); k++) {
dvec dummy;
res.push_back(dummy); // Not to run out of range
// In each Poly_vec, loop over all Polynomials
for (uint p = 0; p < Ppm.at(k).size(); p++) {
Polynomial the_poly=*Ppm.at(k).at(p);
leading_Nc_pow( the_poly );
if ( leading_Nc_pow( the_poly ) != cand_pow ) {res.at(k).push_back(0);}
else res.at(k).push_back( double_num(leading(the_poly)) );
}
}
return res;
}
std::map< std::string, Polynomial > Col_functions::leading( std::map< std::string, Polynomial > mem_map ) const{
// To contain (string, leading(Polynomial))
std::map< std::string, Polynomial > res;
// Iterator for looping
std::map< std::string, Polynomial >::iterator iter=mem_map.begin();
// Find the highest power of Nc+CF
int pow_cand=leading_Nc_pow( (iter->second) );
for( iter = mem_map.begin(); iter != mem_map.end(); ++iter ) {
Polynomial Poly= (iter->second);
if( leading_Nc_pow(Poly) > pow_cand ) pow_cand=leading_Nc_pow(Poly);
}
for( iter = mem_map.begin(); iter != mem_map.end(); ++iter ) {
// Insert pair of string and the leading versions of the Polynomial
Polynomial lead_Poly= leading( (iter->second) );
if ( leading_Nc_pow(lead_Poly) != pow_cand ) lead_Poly=lead_Poly*0;
res.insert( make_pair( iter->first, lead_Poly ) );
} // After this only the leading part of each Polynomial contributes
return res;
}
cnum Col_functions::cnum_num( const Monomial & Mon ) const {
cnum res=Mon.cnum_part*static_cast<double>(Mon.int_part);
for ( int ix=0; ix<Mon.pow_Nc; ix++ )
res *= Nc;
for ( int ix=0; ix<Mon.pow_CF; ix++ )
res *= CF;
for ( int ix=0; ix<Mon.pow_TR; ix++ )
res *= TR;
for ( int ix=0; ix>Mon.pow_Nc; ix-- )
res /= static_cast<double>(Nc);
for ( int ix=0; ix>Mon.pow_CF; ix-- )
res /= static_cast<double>(CF);
for ( int ix=0; ix>Mon.pow_TR; ix-- )
res /= static_cast<double>(TR);
//cnum res=pow(Nc, Mon.pow_Nc)*pow(CF, Mon.pow_CF)*pow(TR, Mon.pow_TR)*Mon.int_part* Mon.cnum_part;
return res;
}
double Col_functions::double_num( const Monomial & Mon ) const{
double im=imag( cnum_num(Mon) );
double re=real( cnum_num(Mon) );
// Warn if the complex number has significant imaginary parts
if( im!=0.0 and re!=0.0 ) {
double ratio =im/re;
if( ratio > accuracy )
std::cerr << "Col_functions::double_num(Mon): Warning keeping only real part of complex number, the ratio im/re was " << ratio << std::endl;
}
else if ( im!=0.0 and re==0.0 ){
std::cerr << "Col_functions::double_num(Mon): Warning keeping only real part of complex number, imaginary part was " << im << std::endl;
}
return re;
}
cnum Col_functions::cnum_num( const Polynomial & Poly ) const {
// An empty Polynomial has numerical value 1
if( Poly.empty() ) return 1.0;
cnum res = 0;
// Add contributions from Monomials
for ( int k = 0; k < Poly.size(); k++ ) {
cnum part_k;
part_k=cnum_num( Poly.at(k) );
res = res + part_k;
}
return res;
}
double Col_functions::double_num( const Polynomial & Poly ) const{
double im=imag( cnum_num(Poly) );
double re=real( cnum_num(Poly) );
// Warn if the complex number has significant imaginary parts
if( im!=0.0 and re!=0.0 ) {
double ratio =im/re;
if( ratio > accuracy )
std::cerr << "Col_functions::double_num: Warning keeping only real part of complex number, the ratio im/re was " << ratio << std::endl;
}
else if ( im!=0.0 and re==0.0 ){
std::cerr << "Col_functions::double_num: Warning keeping only real part of complex number, imaginary part was " << im << std::endl;
}
return re;
}
Col_amp Col_functions::emit_gluon( const Col_str & in_Col_str, int emitter, int g_new ) const{
// Locate the emitter in the Col_str
std::pair<int, int> place=in_Col_str.find_parton(emitter);
// Find what kind, q qbar or g, the emitter is
std::string kind=in_Col_str.find_kind(emitter);
// Defining Col_str to return (two needed in case of g)
Col_str out_Col_str1=in_Col_str;
Col_str out_Col_str2=in_Col_str;
// Defining Col_amp to return
Col_amp out_Col_amp;
// If the emitter is a quark
if( kind =="q" ){
// Add new parton index at second first place in relevant quark_line
out_Col_str1.insert( place.first, place.second+1, g_new );
out_Col_amp.ca.push_back( out_Col_str1 );
}
// If the emitter is an anti-quark
else if( kind =="qbar" ){
// Add new gluon before the qbar
out_Col_str1.insert( place.first, place.second, g_new );
// Change sign
out_Col_str1.Poly=out_Col_str1.Poly*(-1);
// Making a Col_amp to return
out_Col_amp.ca.push_back( out_Col_str1 );
}
// If the emitter is a g
else if( kind =="g" ){
// If the emitter is a gluon a new gluon line should be inserted in two
// different places, before and after the emitter
// -sign when inserting the gluon before
// Change sign Poly for first term
Monomial Mon_tmp;
Mon_tmp.int_part=-1;
out_Col_str1.Poly=out_Col_str1.Poly*Mon_tmp;
// Inserting the gluon before
out_Col_str1.insert( place.first, place.second, g_new );
// Inserting the gluon after
out_Col_str2.insert( place.first, place.second+1, g_new );
// Appending result to out_Col_amp
out_Col_amp.ca.push_back( out_Col_str1 );
out_Col_amp.ca.push_back( out_Col_str2 );
// Normal order
out_Col_amp.normal_order();
}
out_Col_amp.simplify();
return out_Col_amp;
}
Col_amp Col_functions::emit_gluon( const Col_amp & Ca_in, int emitter, int g_new ) const{
Col_amp Ca_out;
// Emit from each Col_str, and append to new Col_amp
for( uint m=0; m< Ca_in.ca.size(); m++ ){
Col_amp part_m=emit_gluon(Ca_in.ca.at(m), emitter, g_new);
Ca_out.append(part_m.ca);
}
return Ca_out;
}
// See my general color structure paper
Col_amp Col_functions::exchange_gluon( const Col_str & Cs, int p1, int p2 ) const{
Col_str Cs_copy=Cs;
// Find out kind and location of partons
std::string kind1 = Cs_copy.find_kind(p1);
std::string kind2 = Cs_copy.find_kind(p2);
std::pair<int, int> place1 = Cs_copy.find_parton(p1);
std::pair<int, int> place2 = Cs_copy.find_parton(p2);
// To contain result
Col_amp Ca;
// Make sure the col_f in multiplying participating Ql's are 0
Polynomial Poly1; // For comparing Poly is 1, all powers are 0
if (!(Poly1 == Cs_copy.cs.at(place1.first).Poly)) {
// Move factor of Quark_line to Col_str
Cs_copy.Poly = Cs_copy.Poly * Cs_copy.cs.at(place1.first).Poly;
Cs_copy.cs.at(place1.first).Poly = Poly1;
}
if (!(Cs_copy.cs.at(place2.first).Poly == Poly1)) {
// Move factor of Quark_line to Col_str
Cs_copy.Poly = Cs_copy.Poly * Cs_copy.cs.at(place2.first).Poly;
Cs_copy.cs.at(place2.first).Poly = Poly1;
}
// sign
if ( place1.first == place2.first && place1.second == place2.second ) {
Monomial mon;
// For qq or qbar qbar
// If the qs are the same, the result is just CF*old for q and qbar
// there are 0 minus signs for quarks and 2 for anti-quarks
if (kind1 == "q" or kind1 == "qbar")
mon.pow_CF = 1;
// for gluons
else{
mon.pow_Nc = 1;
// There is a factor TR from the contracted gluon,
// The sign can be checked by writing out four terms
// corresponding to inserting the new gluon
// first/first, first/last, last/first, last/last
mon.pow_TR+=1;
mon.int_part*=2;
}
Cs_copy.Poly = Cs_copy.Poly * mon;
Ca.ca.push_back( Cs_copy );
return Ca;
}
// Exchange between qq or qbar qbar
if ((kind1 == "q" && kind2 == "q") or (kind1 == "qbar" && kind2 == "qbar")) {
Col_str Cs2 = Cs_copy;
// The q's normally sit on different quark_lines
// The leading Nc-tems has the q's exchanged
Cs_copy.cs.at(place1.first).ql.at(place1.second) = p2;
Cs_copy.cs.at(place2.first).ql.at(place2.second) = p1;
// Multiply with TR
Monomial Mon;
Mon.pow_TR = 1;
Cs_copy.Poly = Cs_copy.Poly * Mon;
// The suppressed term is a copy of the old term,
// but multiplied with -TR /Nc
Mon.pow_TR = 1;
Mon.int_part = -1;
Mon.pow_Nc = -1;
Cs2.Poly = Cs2.Poly * Mon;
Ca.ca.push_back(Cs_copy);
Ca.ca.push_back(Cs2);
}
// Exchange between q qbar
if ((kind1 == "q" && kind2 == "qbar") or (kind1 == "qbar" && kind2 == "q")) {
std::pair<int, int> q_place;
std::pair<int, int> qbar_place;
int the_q=-1;
int the_qbar=-1;
if ((kind1 == "q" && kind2 == "qbar")) {
q_place = place1;
qbar_place = place2;
the_q = p1;
the_qbar = p2;
} else if ((kind1 == "qbar" && kind2 == "q")) {
q_place = place2;
qbar_place = place1;
the_q = p2;
the_qbar = p1;
}
Col_str Cs2 = Cs_copy;
// If q and qbar are not part of same ql
if (q_place.first != qbar_place.first) {
// The non-suppressed term, obtained by erasing q qbar and joining rest
Cs_copy.erase(q_place);
Cs_copy.erase(qbar_place);
// In the ql of the qbar, append the ql of the q, then erase the ql of the q
Cs_copy.cs.at(qbar_place.first).append(Cs_copy.cs.at(q_place.first).ql);
// and erase the ql of the q
Cs_copy.erase(q_place.first);
}
// If q and qbar sit on same ql
else {
// The non-suppressed term, obtained by erasing q qbar and joining rest to a ring
Cs_copy.erase(qbar_place);
Cs_copy.erase(q_place);
Cs_copy.cs.at(q_place.first).open = false;
// If only one quark remains the term should be 0
}
// q and qbar must be found
assert( the_q!=-1);
assert( the_qbar!=-1);
// Construct Quark_line={q,qbar}, and append it
Quark_line Ql;
Ql.open = true;
Ql.push_back( the_q );
Ql.push_back( the_qbar );
Cs_copy.push_back(Ql);
// Multiply with TR
Monomial Mon;
Mon.pow_TR = 1;
Cs_copy.Poly = Cs_copy.Poly * Mon;
// The suppressed term is a copy of the old term,
// but multiplied with -TR / Nc
Mon.pow_TR=1;
Mon.int_part = -1;
Mon.pow_Nc = -1;
Cs2.Poly = Cs2.Poly * Mon;
// Construct the resulting color_amplitude and return
// Make sure there is not only one or 0 gluons in a closed ql
// Append Cs to ca if >=2 gluons
// if open, append
if (Cs_copy.cs.at(q_place.first).open)
Ca.ca.push_back(Cs_copy);
// if closed but >= 2 gluons, append
else if (Cs_copy.cs.at(q_place.first).ql.size() >= 2 && !Cs_copy.cs.at(
q_place.first).open)
Ca.ca.push_back(Cs_copy);
// If 1 gluon, the term is 0 and is not appended
// If 0 gluons the empty colsed ql is equivalent to multiplying with Nc, obtained after simplification
else if (Cs_copy.cs.at(q_place.first).empty()
&& !Cs_copy.cs.at(q_place.first).open) {
// return 2nd term * (1-Nc^2)
Ca.ca.push_back(Cs_copy);
Ca.ca.push_back(Cs2);
Ca.simplify();
return Ca;
}
Ca.ca.push_back(Cs2);
}
// Exchange between q g
if ((kind1 == "q" && kind2 == "g") or (kind1 == "g" && kind2 == "q")) {
std::pair<int, int> q_place;
std::pair<int, int> g_place;
int the_q=0;
int the_g=0;
if (kind1 == "q" && kind2 == "g") {
q_place = place1;
g_place = place2;
the_q = p1;
the_g = p2;
} else if (kind1 == "g" && kind2 == "q") {
q_place = place2;
g_place = place1;
the_q = p2;
the_g = p1;
}
// For containing Quark_lines
Quark_line Ql11;
Quark_line Ql12;
Quark_line Ql21;
Quark_line Ql22;
Col_str Cs1 = Cs_copy;
Col_str Cs2 = Cs_copy;
// If the q and the g are not part of same ql
if (g_place.first != q_place.first) {
// Take split the Ql with the gluon after the gluon
Quark_line Qlg_start = Cs_copy.cs.at(g_place.first).before( g_place.second );
Quark_line Qlg_end = Cs_copy.cs.at(g_place.first).after( g_place.second );
Quark_line Qlq_end = Cs_copy.cs.at(q_place.first).after( q_place.second );
// First part, + sign
// First part, first Ql
Ql11 = Qlg_end;
Ql11.prepend(the_g);
Ql11.prepend(the_q);
// First part, second Ql
Ql12 = Qlg_start;
Ql12.append(Qlq_end.ql);
// If the ql of the gluon was closed account for this by gluing qls together
if (!Qlg_start.open) {
Ql11.append(Ql12.ql);
Ql11.open = true;
};
// Second part, first Ql
Ql21 = Qlg_end;
Ql21.prepend(the_q);
// Second part, second Ql
Ql22 = Qlg_start;
Ql22.append(the_g);
Ql22.append(Qlq_end.ql);
// If the ql of the gluon was closed account for this by gluing qls together
if (!Qlg_start.open) {
Ql21.append(Ql22.ql);
Ql21.open = true;
};
// Replace Ql's in the Col_str
Cs1.cs.at(q_place.first) = Ql11;
Cs2.cs.at(q_place.first) = Ql21;
// There is only one ql if the ql of the gluon was closed
if (Qlg_start.open) {
Cs1.cs.at(g_place.first) = Ql12;
Cs2.cs.at(g_place.first) = Ql22;
} else { // Erase 2nd ql
Cs1.erase(g_place.first);
Cs2.erase(g_place.first);
}
}
// If q and g are part of same ql
else {
Quark_line Ql1 = Cs_copy.cs.at(g_place.first).before( g_place.second );
Ql1.ql.erase(Ql1.ql.begin());
Quark_line Ql2 = Cs_copy.cs.at(g_place.first).after( g_place.second);
// First term, First ql
Ql11 = Ql1;
Ql11.open = false;
// First term, 2nd ql
Ql12 = Ql2;
Ql12.prepend(the_g);
Ql12.prepend(the_q);
// 2nd term, 1st ql
Ql21 = Ql1;
Ql21.append(the_g);
Ql21.open = false;
// 2nd term 2nd ql
Ql22 = Ql2;
Ql22.prepend(the_q);
// Replace Ql's in the Col_str
Cs1.cs.at(q_place.first) = Ql11;
Cs1.cs.insert(Cs1.cs.begin() + q_place.first + 1, Ql12);
// Replace Ql's in the Col_str
Cs2.cs.at(q_place.first) = Ql21;
Cs2.cs.insert(Cs2.cs.begin() + q_place.first + 1, Ql22);
}
// Multiply first part with TR
Monomial Mon_tmp;
Mon_tmp.pow_TR = 1;
Cs1.Poly = Cs1.Poly * Mon_tmp;
// Multiply second part with -TR
Monomial Mon_tmp2;
Mon_tmp2.pow_TR = 1;
Mon_tmp2.int_part = -1;
Cs2.Poly = Cs2.Poly * Mon_tmp2;
// Add to result
Ca.ca.push_back(Cs1);
Ca.ca.push_back(Cs2);
}// end exchange between q g
// Exchange between qbar g (q and g in my paper)
if ((kind1 == "qbar" && kind2 == "g") or (kind1 == "g" && kind2 == "qbar")) {
std::pair<int, int> qbar_place;
std::pair<int, int> g_place;
int the_qbar=0;
int the_g=0;
if (kind1 == "qbar" && kind2 == "g") {
qbar_place = place1;
g_place = place2;
the_qbar = p1;
the_g = p2;
} else if (kind1 == "g" && kind2 == "qbar") {
qbar_place = place2;
g_place = place1;
the_qbar = p2;
the_g = p1;
}
// For containing Quark_lines
Quark_line Ql11, Ql12, Ql21, Ql22;
// For containing resulting Col_str's
Col_str Cs1 = Cs_copy;
Col_str Cs2 = Cs_copy;
// If ql and g on different quark_lines
if (g_place.first != qbar_place.first) {
// Split ql's into parts
Quark_line Qlg_start = Cs_copy.cs.at(g_place.first).before( g_place.second) ;
Quark_line Qlg_end = Cs_copy.cs.at(g_place.first).after( g_place.second );
Quark_line Qlqbar_start = Cs_copy.cs.at( qbar_place.first ).before(qbar_place.second);
// First part, + sign, first Ql
Ql11 = Qlqbar_start;
Ql11.append(the_g);
Ql11.append(Qlg_end.ql);
// First part, + sign, second Ql
Ql12 = Qlg_start;
Ql12.append(the_qbar);
// If the ql of the gluon was closed account for this by gluing qls together
if (!Qlg_start.open) {
Ql11.append(Ql12.ql);
Ql11.open = true;
};
// Second part, - sign, first Ql
Ql21 = Qlqbar_start;
Ql21.append(Qlg_end.ql);
// Second part, - sign, second Ql
Ql22 = Qlg_start;
Ql22.append(the_g);
Ql22.append(the_qbar);
// If the ql of the gluon was closed account for this by gluing qls together
if (!Qlg_start.open) {
Ql21.append(Ql22.ql);
Ql21.open = true;
};
// Replace Ql's in the Col_str
Cs1 = Cs_copy;
Cs2 = Cs_copy;
if (Qlg_start.open) {
Cs1.cs.at(qbar_place.first) = Ql11;
Cs1.cs.at(g_place.first) = Ql12;
Cs2.cs.at(qbar_place.first) = Ql21;
Cs2.cs.at(g_place.first) = Ql22;
} else { // If the ql of the g was closed, there is only one ql, erase 2nd ql
Cs1.cs.at(qbar_place.first) = Ql11;
Cs1.erase(g_place.first);
Cs2.cs.at(qbar_place.first) = Ql21;
Cs2.erase(g_place.first);
}
}
// If qbar and g are part of same quark_line
else {
Quark_line Ql1 = Cs_copy.cs.at(g_place.first).before(g_place.second );
Quark_line Ql2 = Cs_copy.cs.at(g_place.first).after( g_place.second );
Ql2.ql.erase(Ql2.ql.end() - 1);
// First term, First ql
Ql11 = Ql1;
Ql11.append(the_qbar);
// First term, 2nd ql
Ql12 = Ql2;
Ql12.prepend(the_g);
Ql12.open = false;
// 2nd term, 1st ql
Ql21 = Ql1;
Ql21.append(the_g);
Ql21.append(the_qbar);
// 2nd term 2nd ql
Ql22 = Ql2;
Ql22.open = false;
// Replace Ql's in the Col_str
Cs1 = Cs_copy;
Cs1.cs.at(qbar_place.first) = Ql11;
Cs1.cs.insert(Cs1.cs.begin() + qbar_place.first + 1, Ql12);
// Replace Ql's in the Col_str
Cs2 = Cs_copy;
Cs2.cs.at(qbar_place.first) = Ql21;
Cs2.cs.insert(Cs2.cs.begin() + qbar_place.first + 1, Ql22);
}
// Multiply with TR
Monomial Mon_tmp;
Mon_tmp.pow_TR = 1;
Cs1.Poly = Cs1.Poly * Mon_tmp;
// Multiply with -TR
Monomial Mon_tmp2;
Mon_tmp2.pow_TR = 1;
Mon_tmp2.int_part = -1;
Cs2.Poly = Cs2.Poly * Mon_tmp2;
Ca.ca.push_back(Cs1);
Ca.ca.push_back(Cs2);
}
// Exchange between g g
if (kind1 == "g" && kind2 == "g") {
// For containing resulting Col_str's
Col_str Cs1 = Cs_copy;
Col_str Cs2 = Cs_copy;
Col_str Cs3 = Cs_copy;
Col_str Cs4 = Cs_copy;
// For containing Quark_lines
Quark_line Ql11, Ql12, Ql21, Ql22, Ql31, Ql32, Ql41, Ql42;
// If g's on different Ql's
if (place1.first != place2.first) {
// Split both ql's into parts
Quark_line Ql1_start = Cs_copy.cs.at(place1.first).before( place1.second );
Quark_line Ql1_end = Cs_copy.cs.at(place1.first).after( place1.second );
Quark_line Ql2_start = Cs_copy.cs.at(place2.first).before( place2.second );
Quark_line Ql2_end = Cs_copy.cs.at(place2.first).after( place2.second );
// First term, both quarks on 2nd ql, First ql
Ql11 = Ql1_start;
Ql11.append(Ql2_end.ql);
// First term, 2nd ql
Ql12 = Ql2_start;
Ql12.append(p2);
Ql12.append(p1);
Ql12.append(Ql1_end.ql);
// 2nd term, g1 on ql1, g2 on ql2, 1st ql
Ql21 = Ql1_start;
Ql21.append(p1);
Ql21.append(Ql2_end.ql);
// 2nd term, 2nd ql
Ql22 = Ql2_start;
Ql22.append(p2);
Ql22.append(Ql1_end.ql);
// 3rd term, g2 on ql1, g1 on ql2,1st ql
Ql31 = Ql1_start;
Ql31.append(p2);
Ql31.append(Ql2_end.ql);
// 3rd term, 2nd ql
Ql32 = Ql2_start;
Ql32.append(p1);
Ql32.append(Ql1_end.ql);
// last term, both quarks on 1st ql,1st ql
Ql41 = Ql1_start;
Ql41.append(p1);
Ql41.append(p2);
Ql41.append(Ql2_end.ql);
// last term, 2nd ql
Ql42 = Ql2_start;
Ql42.append(Ql1_end.ql);
// Replace Ql's in the Col_str
// If both Ql's are open
if (Cs_copy.cs.at(place1.first).open && Cs_copy.cs.at(place2.first).open) {
Cs1.cs.at(place1.first) = Ql11;
Cs1.cs.at(place2.first) = Ql12;
Cs2.cs.at(place1.first) = Ql21;
Cs2.cs.at(place2.first) = Ql22;
Cs3.cs.at(place1.first) = Ql31;
Cs3.cs.at(place2.first) = Ql32;
Cs4.cs.at(place1.first) = Ql41;
Cs4.cs.at(place2.first) = Ql42;
}
// If string where closed glue together ends
// If first ql closed
else if (!Cs_copy.cs.at(place1.first).open) {
Ql12.append(Ql11.ql);
Ql22.append(Ql21.ql);
Ql32.append(Ql31.ql);
Ql42.append(Ql41.ql);
//The result should be open/closed if the ql2 was open/closed
Ql12.open = Cs_copy.cs.at(place2.first).open;
Ql22.open = Cs_copy.cs.at(place2.first).open;
Ql32.open = Cs_copy.cs.at(place2.first).open;
Ql42.open = Cs_copy.cs.at(place2.first).open;
//The reslut contaied int Qlx2 sould be used for the Color structure
// Replace Ql's in the Col_str
Cs1.cs.at(place2.first) = Ql12;
Cs2.cs.at(place2.first) = Ql22;
Cs3.cs.at(place2.first) = Ql32;
Cs4.cs.at(place2.first) = Ql42;
Cs1.erase(place1.first);
Cs2.erase(place1.first);
Cs3.erase(place1.first);
Cs4.erase(place1.first);
}
// if only 2nd ql closed
if (!Cs_copy.cs.at(place2.first).open && Cs_copy.cs.at(place1.first).open) {
Ql11.append(Ql12.ql);
Ql21.append(Ql22.ql);
Ql31.append(Ql32.ql);
Ql41.append(Ql42.ql);
// The result should be open
Ql11.open = true;
Ql21.open = true;
Ql21.open = true;
Ql21.open = true;
//The result contained int Qlx1 should be used for the Color structure
// Replace Ql's in the Col_str
Cs1.cs.at(place2.first) = Ql11;
Cs2.cs.at(place2.first) = Ql21;
Cs3.cs.at(place2.first) = Ql31;
Cs4.cs.at(place2.first) = Ql41;
Cs1.erase(place1.first);
Cs2.erase(place1.first);
Cs3.erase(place1.first);
Cs4.erase(place1.first);
}
}
// If g's on same ql's
if (place1.first == place2.first) {
Quark_line Ql_start = Cs_copy.cs.at(place1.first).before( std::min(place2.second, place1.second));
// the part between the g's
Quark_line Ql_between = Cs_copy.cs.at(place1.first).before(std::max(
place2.second, place1.second));
Ql_between = Ql_between.after( std::min(place2.second, place1.second) );
// the end after 2nd g
Quark_line Ql_end = Cs_copy.cs.at(place1.first).after( std::max(place2.second,
place1.second));
// we have to know what g is first to put them back in right order
int first_g, last_g;
if( place1.second < place2.second ) {
first_g=p1;
last_g=p2;
}
else {
first_g=p2;
last_g=p1;
}
// First term, both gluons inbetween
Ql11 = Ql_start;
Ql11.append(Ql_end.ql);
// First term, part between quarks
Ql12 = Ql_between;
Ql12.append( last_g );
Ql12.append( first_g );
Ql12.open = false;
// 2nd term, g1 after first part, g2 after 2nd
Ql21 = Ql_start;
Ql21.append( first_g );
Ql21.append(Ql_end.ql);
// First term, part between quarks
Ql22 = Ql_between;
Ql22.append( last_g );
Ql22.open = false;
// 3rd term, g2 after first part, g1 after 2nd
Ql31 = Ql_start;
Ql31.append( last_g);
Ql31.append(Ql_end.ql);
// First term, part between quarks
Ql32 = Ql_between;
Ql32.append( first_g );
Ql32.open = false;
// 4th term, g2 after first part, g1 after 2nd
Ql41 = Ql_start;
Ql41.append( first_g );
Ql41.append( last_g );
Ql41.append(Ql_end.ql);
// First term, part between quarks
Ql42 = Ql_between;
Ql42.open = false;
Cs1.cs.at(place1.first) = Ql11;
Cs1.cs.insert(Cs1.cs.begin() + place1.first + 1, Ql12);
Cs2.cs.at(place1.first) = Ql21;
Cs2.cs.insert(Cs2.cs.begin() + place1.first + 1, Ql22);
Cs3.cs.at(place1.first) = Ql31;
Cs3.cs.insert(Cs3.cs.begin() + place1.first + 1, Ql32);
Cs4.cs.at(place1.first) = Ql41;
Cs4.cs.insert(Cs4.cs.begin() + place1.first + 1, Ql42);
}
// Multiplying with TR where appropriate
Monomial Mon_tmp;
Mon_tmp.pow_TR = 1;
Cs2.Poly = Cs2.Poly * Mon_tmp;
Cs3.Poly = Cs3.Poly * Mon_tmp;
// Multiplying with -TR where appropriate
Mon_tmp.pow_TR = 1;
Mon_tmp.int_part = -1;
Cs1.Poly = Cs1.Poly * Mon_tmp;
Cs4.Poly = Cs4.Poly * Mon_tmp;
Ca.ca.push_back(Cs1);
Ca.ca.push_back(Cs2);
Ca.ca.push_back(Cs3);
Ca.ca.push_back(Cs4);
}
// Simplify Col_amp
Ca.simplify();
return Ca;
}
Col_amp Col_functions::exchange_gluon( const Col_amp & Ca, int p1, int p2 ) const{
// Final col_amp to return
Col_amp Ca_out;
// Exchange in each Col_str, and append to new Col_amp
for(uint m=0; m< Ca.ca.size(); m++ ){
// Exchange in Col_str m
Col_amp part_m=exchange_gluon( Ca.ca.at(m), p1, p2 );
// Append result
Ca_out.append(part_m.ca);
}
return Ca_out;
}
/*
Col_str Col_functions::contract_quarks( Col_str Cs1, Col_str Cs2 ) const{
std::vector<int> q_place;
std::vector<int> q_place2;
// The conjugate of Cs1
Col_str conj_Cs1 = Cs1;
conj_Cs1.conjugate();
// The total color structure
Col_str Cs = conj_Cs1*Cs2;
// Count how many quarks should be contracted
int n_q = Cs.n_quark();
// As long as there are quark_lines left to contract
while (n_q > 0) {
// Find first quark in Cs1 by looping over Quark_lines
for (int i = 0; (n_q>0 && i < static_cast<int>(Cs.cs.size()) ); i++) {
// Check if the quark-line is open, in which case it has a q
if (Cs.cs.at(i).open) {
// The first quark is located and has position
q_place.clear();
q_place.push_back(i);
q_place.push_back(0);
// and number
int q = Cs.at(q_place.at(0), q_place.at(1));
// Locate same quark a second time
// Loop over Quark_lines
q_place2.clear();
int i2 = i + 1; // Quark_line of second occurrence
while (q_place2.empty()) { // As long as quark not found a second time
if (Cs.cs.at(i2).at(Cs.cs.at(i2).ql.size() - 1) == q) {// If quark found, store place
q_place2.push_back(i2);
q_place2.push_back(Cs.cs.at(i2).ql.size() - 1);
}
i2++;
}
if (q_place2.empty()) {
std::cerr << "Col_functions::contract_quarks(Cs1, Cs2): Found q " << q
<< " only once in " << Cs << std::endl;
}
// Prepare new Quark_line
// to be inserted at the place of found open Quark_line
Quark_line new_Quark_line;
Quark_line part2_new_Quark_line;
// The first part of the new Quark_line should be the Quark_line
// containing q in the conjugate
new_Quark_line = Cs.cs.at(q_place2.at(0));
// Erasing q in the end
new_Quark_line.ql.erase(--new_Quark_line.ql.end());
part2_new_Quark_line = Cs.cs.at(q_place.at(0));
// Erasing the q in the beginning of second part
part2_new_Quark_line.ql.erase(part2_new_Quark_line.ql.begin());
new_Quark_line.append(part2_new_Quark_line.ql);
// So far we have not included the Polynomial of part2_new_Quark_line
new_Quark_line.Poly=new_Quark_line.Poly*part2_new_Quark_line.Poly;
// If the first q index and the last qbar index in the new
// Quark_line is the same (and the Quark_line is "open"), the indices
// should be removed and the Quark_line should be closed
if (new_Quark_line.ql.at(0) == new_Quark_line.ql.at(
new_Quark_line.ql.size() - 1) && new_Quark_line.open) {
// The string is closed
new_Quark_line.open = false;
// Remove last and first index
new_Quark_line.ql.erase(--new_Quark_line.ql.end(),
new_Quark_line.ql.end());
new_Quark_line.ql.erase(new_Quark_line.ql.begin());
}
// Inserting new Quark_line in the place of the old
Cs.cs.at(i) = new_Quark_line;
// Remove quark_line with q in Cs
Cs.cs.erase((Cs.cs.begin() + q_place2.at(0)));
i=-1; // reset to keep looking from the beginning in the new Cs (i will be increased to 0)
}// end of if (open)
n_q = Cs.n_quark();
} // end of for, loop over quark_lines
}
return Cs;
}
Col_amp Col_functions::contract_quarks( Col_amp Ca1, Col_amp Ca2 ) const{
if(Ca1.empty()){
std::cerr << "Col_functions::contract_quarks: Expects non-empty Col_amps, got first argument "
<< Ca1 << std::endl;
assert(0);
}
if(Ca2.empty()){
std::cerr << "Col_functions::contract_quarks: Expects non-empty Col_amps, got second argument "
<< Ca2 << std::endl;
assert(0);
}
Col_amp Ca_res;
// Make sure the Col_strs are not empty "[]"=1, as all indices contracted
Ca1.remove_empty_Col_strs();
Ca2.remove_empty_Col_strs();
// Loop over Col_strs, and contract quarks between all possible combinations
// Loop over Col_strs in Ca1
for(uint m1=0; m1 < Ca1.ca.size(); m1++ ){
// Loop over Col_strs in Ca2
for(uint m2=0; m2 < Ca2.ca.size(); m2++ ){
Col_str Cs_tmp;
Cs_tmp.contract_quarks( Ca1.ca.at(m1), Ca2.ca.at(m2));
Ca_res.ca.push_back( Cs_tmp );
}
}
return Ca_res;
}
*/
std::map< std::string, double > Col_functions::double_num( std::map< std::string, Polynomial > mem_map ) const{
std::map< std::string, double > res;
// Loop over entries
std::map< std::string, Polynomial >::iterator iter=mem_map.begin();
for( iter = mem_map.begin(); iter != mem_map.end(); ++iter) {
// Insert pair of string and the leading versions of the Polynomial
double_num( (iter->second) );
res.insert(std::make_pair( iter->first, double_num((iter->second)) ));
}
return res;
}
Polynomial Col_functions::Polynomial_cnum_num( const Polynomial & Poly ) const{
// Store content in numerical part of the Monomial
Monomial Mon;
Mon.cnum_part = cnum_num(Poly);
Polynomial res;
res = res * Mon;
return res;
}
cvec Col_functions::cnum_num( const Poly_vec & Pv ) const{
// To contain the numerical result
cvec res;
// Loop over Polynomials in the vector, and add the numerical value
// to the vector to return
for (uint p = 0; p < Pv.size(); p++) {
res.push_back(cnum_num(Pv.at(p)));
}
return res;
}
dvec Col_functions::double_num( const Poly_vec & Pv ) const{
// To contain the numerical result
dvec res;
// Loop over Polynomials in the vector, and add the numerical value
// to the vector to return
for (uint p = 0; p < Pv.size(); p++) {
res.push_back(double_num( Pv.at(p)) );
}
return res;
}
dmatr Col_functions::double_num( const Poly_matr & Pm ) const{
// To contain the numerical result
dmatr res;
// Loop over Poly_vecs in the vector, and add the numerical value
// to the vector to return
for (uint pv = 0; pv < Pm.size(); pv++) {
res.push_back(double_num( Pm.at(pv).pv ) );
}
return res;
}
-dvec Col_functions::double_num( const std::vector<boost::shared_ptr<Polynomial> > & Pv ) const{
+dvec Col_functions::double_num( const std::vector<shared_ptr<Polynomial> > & Pv ) const{
// To contain the numerical result
dvec res;
// Loop over Polynomials in the vector, and add the numerical value
// to the vector to return
for (uint p = 0; p < Pv.size(); p++) {
- boost::shared_ptr<Polynomial> the_pointer=Pv.at(p);
+ shared_ptr<Polynomial> the_pointer=Pv.at(p);
// Want double of the polynomial which the pointer points at
res.push_back( double_num(*the_pointer) );
}
return res;
}
Poly_vec Col_functions::Poly_vec_cnum_num( const Poly_vec & Pv) const{
// To contain the result
Poly_vec res;
// Loop over Polynomials in the vector, put each Polynomial to its numerical value
for (uint p = 0; p < Pv.size(); p++) {
res.push_back( Polynomial_cnum_num( Pv.at( p ) ) );
}
return res;
}
Poly_matr Col_functions::Poly_matr_cnum_num( const Poly_matr & Pm ) const {
// To contain the result
Poly_matr res_matr;
// Loop over Polynomials in the matrix
// and change each Polynomial to its numerical version
for (uint v = 0; v < Pm.size(); v++) {
res_matr.push_back( Poly_vec_cnum_num( Pm.at( v ).pv ));
}
return res_matr;
}
cmatr Col_functions::cnum_num( const Poly_matr & Pm ) const{
// To contain the numerical result
cmatr res;
// Loop over Polynomials in the vector, and add the numerical value
// to the vector to return
for (uint v = 0; v < Pm.size(); v++) {
res.push_back(cnum_num( Pm.at(v).pv ));
}
return res;
}
-dmatr Col_functions::double_num( const std::vector<std::vector<boost::shared_ptr<Polynomial> > > & Pm ) const{
+dmatr Col_functions::double_num( const std::vector<std::vector<shared_ptr<Polynomial> > > & Pm ) const{
// To contain the numerical result
dmatr res;
// Loop over Polynomials in the vector, and add the numerical value
// to the vector to return
for (uint v = 0; v < Pm.size(); v++) {
res.push_back(double_num(Pm.at(v)));
}
return res;
}
Polynomial Col_functions::scalar_product( const Col_amp & Ca1 , const Col_amp & Ca2 ) const{
//std::cout << "Col_functions::scalar_product, incoming Ca1 " << Ca1 <<" and Ca2 " << Ca2 << std::endl;
if( !Ca1.Scalar.empty() and ( cnum_num(Ca1.Scalar).real()!=0 or cnum_num(Ca1.Scalar).imag()!=0 ) ){
std::cerr << "Col_functions::scalar_product(Ca1,Ca2): "
<< "Expects Col_amps with empty Scalar parts, but the Scalar of the first Col_amp was " <<
Ca1.Scalar << std::endl;
assert(0);
}
if( !Ca2.Scalar.empty() and ( cnum_num(Ca2.Scalar).real()!=0 or cnum_num(Ca2.Scalar).imag()!=0 ) ){
std::cerr << "Col_functions::scalar_product(Ca1,Ca2): "
<< "Expects Col_amps with empty Scalar parts, but the Scalar of the second Col_amp was " <<
Ca2.Scalar << std::endl;
assert(0);
}
// To contain the result
Col_amp Ca_res;
// Contract the quarks
//Ca_res = contract_quarks(Ca1, Ca2);
Ca_res.contract_quarks( Ca1, Ca2 );
//std::cout << "Col_functions::scalar_product, contracted quarks " << Ca_res << std::endl;
// Look for simple simplifications
Ca_res.simplify();
//Ca_res.simplify(); // why twice
//std::cout << "Col_functions::scalar_product, simplified " << Ca_res << std::endl;
// Contract the gluons
Ca_res.contract_all_gluons();
if (!Ca_res.empty()) {
std::cerr << "Col_functions::scalar_product: terminating due to non-contracted indices."
<< std::endl;
std::cerr << "The Col_amp is " << Ca_res << std::endl;
std::cerr.flush();
assert( 0 );
return Ca_res.Scalar;
}
else
return Ca_res.Scalar;
}
Polynomial Col_functions::scalar_product( const Col_str & Cs1, const Col_str & Cs2 ) const{
Col_str Cs_tmp;
// Contract the quarks
Cs_tmp.contract_quarks( Cs1, Cs2 );
Col_amp Ca_tmp(Cs_tmp);
// Contract the gluons
Ca_tmp.contract_all_gluons();
if ( !Ca_tmp.empty() ){
std::cerr << "Col_functions::scalar_product: terminating due to non-contracted quark indices." <<std::endl;
std::cerr << "The col_amp is " << Ca_tmp << std::endl;
assert( 0 );
}
return Ca_tmp.Scalar;
}
Polynomial Col_functions::color_correlator( const Col_amp Ca, int p1, int p2, int g_new ) const{
// The amplitudes after emission
Col_amp Cai = emit_gluon(Ca, p1, g_new);
Col_amp Caj = emit_gluon(Ca, p2, g_new);
Polynomial res=0;
res = scalar_product( Cai, Caj );
return res;
}
int Col_functions::factorial( int i ) const{
if(i<0) {
std::cerr << "Col_functions::factorial: intended for int >=0, argument was " << i << std::endl;
std::cerr.flush();
assert( 0 );
}
if (i==0) return 1;
return factorial(i-1)*i; // Recursive call
}
void Col_functions::write_out_dvec( const dvec & dv, std::string filename ) const {
std::ofstream outfile(filename.c_str() );
outfile << dv;
}
dmatr Col_functions::read_in_dmatr( std::string filename ) const {
// Read in file
std::ifstream fin(filename.c_str());
// Check that file exists
if( !fin ){
std::cerr << "Col_functions::read_in_dmatr: The file "
<< filename << " could not be opened." << std::endl;
assert( 0 );
}
// Copy info from file to string
std::string str((std::istreambuf_iterator<char>(fin)), std::istreambuf_iterator<char>());
// Skip lines starting with #
while(str.at(0)== '#'){
while (str.at(0) != '\n'){
str.erase(str.begin());
}
// erase endl sign(s)
while(str.at(0)== '\n'){
str.erase(str.begin());
}
}
// First char in file should be '{'
if (str.at(0) != '{') {
std::cerr
<< "Col_functions::read_in_dmatr: First char in matrix data file after comments should be '{', it was: "
<< str.at(0) << std::endl;
assert( 0 );
}
// Check that only allowed characters
uint j = 0;
while (j < str.size()) {
if (!(str.at(j) == '+' or str.at(j) == '-' or str.at(j) == '.'
or str.at(j) == '{' or str.at(j) == '}' or str.at(j) == '\n'
or str.at(j) == ',' or str.at(j) == ' ' or str.at(j) == '0'
or str.at(j) == '1' or str.at(j) == '2' or str.at(j) == '3'
or str.at(j) == '4' or str.at(j) == '5' or str.at(j) == '6'
or str.at(j) == '7' or str.at(j) == '8' or str.at(j) == '9')) {
std::cerr
<< "Col_functions::read_in_dmatr: A disallowed characters encountered in string for dmatr: "
<< str.at(j) << ", in file " << filename << std::endl;
std::cerr << "Col_functions::read_in_dmatr expects a numerical matrix." << std::endl;
assert( 0 );
}
j++;
}
// Row to contain numbers
dvec row;
// To contain matrix of scalar products
dmatr matr;
// Read the string, starting from 0th element
uint i = 0;
while (i < str.size() - 2) {
i += 1;
// We may have to skip some chars
while (i< str.size()-2 &&(str.at(i) == ',' or str.at(i) == '}' or str.at(i) == ' ' or str.at(i) == '\n' or str.at(i) == ' ' or str.at(i) == '{') ) i++;
// String to make a number of, and double to contain number
std::string num_str;
num_str.clear();
double num;
// Keep reading the number while not ',' or '}'
while ( i< str.size()-2 && (str.at(i) != ',' && str.at(i) != '}') )
{
num_str.push_back(str.at(i));
i++;
}
// num_str contains the string to make a number of
std::istringstream parton_str_st( num_str );
parton_str_st >> num;
// Add number to vector
row.push_back(num);
// If we have a new row
if( i< str.size()-2 && str.at(i)=='}'){
// Save row in matrix, and empty row
matr.push_back(row);
row.clear();
// We may have to skip some chars
while (i< str.size()-2 &&(str.at(i) == ',' or str.at(i) == '}' or str.at(i) == ' ' or str.at(i) == '\n' ) ) {
i++;
}
}
// Otherwise just keep on reading the next number in row
}
return matr;
}
dvec Col_functions::read_in_dvec( std::string filename ) const {
// Read in file
std::ifstream fin(filename.c_str());
// Check that file exists
if( !fin ){
std::cerr << "Col_functions::read_in_dvec: The file "
<< filename << " could not be opened." << std::endl;
assert( 0 );
}
// Copy info from file to string
std::string str((std::istreambuf_iterator<char>(fin)), std::istreambuf_iterator<char>());
// Skip lines starting with #
while(str.at(0)== '#'){
while (str.at(0) != '\n'){
str.erase(str.begin());
}
// erase endl sign(s)
while(str.at(0)== '\n'){
str.erase(str.begin());
}
}
// First char in file should be '{'
if (str.at(0) != '{') {
std::cerr
<< "Col_functions::read_in_dvec: First char in matrix data file after comments should be '{', it was: "
<< str.at(0) << std::endl;
assert( 0 );
}
// Check that only allowed characters
uint j = 0;
while (j < str.size()) {
if (!(str.at(j) == '+' or str.at(j) == '-' or str.at(j) == '.'
or str.at(j) == '{' or str.at(j) == '}' or str.at(j) == '\n'
or str.at(j) == ',' or str.at(j) == ' ' or str.at(j) == '0'
or str.at(j) == '1' or str.at(j) == '2' or str.at(j) == '3'
or str.at(j) == '4' or str.at(j) == '5' or str.at(j) == '6'
or str.at(j) == '7' or str.at(j) == '8' or str.at(j) == '9')) {
std::cerr
<< "Col_functions::read_in_dvec: A disallowed character encountered in string for dmatr: "
<< str.at(j) << ", in file " << filename << std::endl;
std::cerr << "Col_functions::read_in_dvec expects a numerical matrix." << std::endl;
assert( 0 );
}
j++;
}
// Row to contain numbers
dvec row;
// To contain matrix of scalar products
dmatr matr;
// Read the string, starting from 0th element
unsigned int i = 0;
while (i < str.size() - 1) {
i += 1;
// We may have to skip some chars
while (i< str.size()-2 &&(str.at(i) == ',' or str.at(i) == '}' or str.at(i) == ' ' or str.at(i) == '\n' or str.at(i) == ' ' or str.at(i) == '{') ) i++;
// String to make a number of, and double to contain number
std::string num_str;
num_str.clear();
double num;
// Keep reading the number while not ',' or '}'
while ( i< str.size()-1 && (str.at(i) != ',' && str.at(i) != '}') )
{
num_str.push_back(str.at(i));
i++;
}
// now, at(i), there is either , or }
// num_str contains the string to make a number of
std::istringstream num_str_st( num_str );
num_str_st >> num;
// Add number to vector
row.push_back(num);
// Skip signs in end and make sure not to enter loop one extra time
while( i<str.size() and ( str.at(i)==' ' or str.at(i)=='\n' or str.at(i)=='}' ) ) i++;
}
return row;
}
void Col_functions::write_out_dmatr( const dmatr & matr, std::string filename ) const {
std::ofstream outfile(filename.c_str());
outfile << matr;
}
std::list<int>::iterator operator+( std::list<int>::iterator x, int n ) {
while(n>0){
x++;
n--;
}
while(n<0){
x--;
n++;
}
return x;
}
std::list<int>::iterator operator-( std::list<int>::iterator x, int n ) {
while(n>0){
x--;
n--;
}
while(n<0){
x++;
n++;
}
return x;
}
std::list< Quark_line >::iterator operator+( std::list < Quark_line >::iterator x, int n ){
while(n>0){
x++;
n--;
}
while(n<0){
x--;
n++;
}
return x;
}
col_str::iterator operator-( col_str::iterator x, int n ){
while(n>0){
x--;
n--;
}
while(n<0){
x++;
n++;
}
return x;
}
std::ostream& operator<<( std::ostream& out, std::vector<int> vec ){
int max=vec.size();
if(max==0) out <<"{}";
else{
out <<"{";
for (int i=0; i<max-1; i++){
out << vec.at(i) << ",";
}
out << vec.at(max-1) <<"}";
}
return out;
}
std::ostream& operator<<( std::ostream& out, const cvec & cv ) {
out << "{";
// Loop over entries
for (uint i = 0; i < cv.size(); i++) {
// Print element
std::cout.width(6);
std::ostringstream outstr;
outstr << cv.at(i);
out << outstr.str();
// If not last element print ","
if (i < (cv.size() -1 )) out << ", ";
}
out << "}";
return out;
}
std::ostream& operator<<(std::ostream& out, const dvec & dv) {
out << "{";
// Loop over entries
for (uint i = 0; i < dv.size(); i++) {
// Print element
std::cout.width(6);
std::ostringstream outstr;
outstr << dv.at(i);
out << outstr.str();
// If not last element print ","
if (i < (dv.size() -1 )) out << ", ";
}
out << "}";
return out;
}
std::ostream& operator<<( std::ostream& out, const cmatr & cm ){
out <<"{" << std::endl;
// Loop over rows
for(uint i=0; i< cm.size(); i++ ){
out <<"{";
// Loop over columns
for(uint j=0; j< cm.at(i).size(); j++ ){
// Print element
std::cout.width( 6 );
std::ostringstream outstr;
outstr << cm.at(i).at(j);
// If not last element print ","
if (j<cm.at(i).size()-1 ) outstr << ",";
out << outstr.str();
//out << Poly_m.at(i).at(j) << "";
}
out <<"}";
// If not last row, print ","
if (i<cm.at(i).size()-1 ) out << ",";
out << std::endl;
}
out <<"}" << std::endl;
return out;
}
std::ostream& operator<<( std::ostream& out, const dmatr & matr ){
out <<"{" << std::endl;
// Loop over rows
for(uint i=0; i< matr.size(); i++ ){
out <<"{";
// Loop over columns
for(uint j=0; j< matr.at(i).size(); j++ ){
// Print element
std::ostringstream outstr;
outstr.width( 20 );
outstr.precision(16);
// If the result is larger than accuracy print it out
if( std::abs( matr.at(i).at(j) )> accuracy ){
outstr << std::fixed << matr.at(i).at(j);
}
// otherwise is should probably be 0
else
outstr << std::fixed << 0;
// If not last element print ","
if (j<matr.at(i).size()-1 ) outstr << ",";
out << outstr.str();
}
out <<"}";
// If not last row, print ","
if (i<matr.at(i).size()-1 ) out << ",";
out << std::endl;
}
out <<"}" <<std::endl;
return out;
}
std::ostream& operator<<( std::ostream& out, std::pair<int, int> pair ) {
out << "(";
out << pair.first;
out << ", ";
out << pair.second;
out << ")";
return out;
}
} //end namespace ColorFull
diff --git a/MatrixElement/Matchbox/ColorFull/Col_functions.h b/MatrixElement/Matchbox/ColorFull/Col_functions.h
--- a/MatrixElement/Matchbox/ColorFull/Col_functions.h
+++ b/MatrixElement/Matchbox/ColorFull/Col_functions.h
@@ -1,318 +1,317 @@
// -*- C++ -*-
/*
* Col_functions.h
* Contains declarations of the class Col_str and associated types and operators
* Author: Malin Sjodahl
*/
#ifndef COLORFULL_Col_functions_h
#define COLORFULL_Col_functions_h
#include "Col_amp.h"
#include "Poly_matr.h"
#include <list>
#include <map>
-#include <boost/shared_ptr.hpp>
+#include <memory>
namespace ColorFull {
-using boost::shared_ptr;
-
+using std::shared_ptr;
/// Library class containing functions for index contraction and
/// numerical evaluation.
/// This is where the parameters Nc, TR and CF are contained.
class Col_functions {
private:
/// The number of colors, used in numerical results. Change here for different value.
double Nc;
/// The trace convention Tr( t^a t^a )=TR (no sum).
/// The normalization of the SU(Nc) generators, to be used in numerical evaluation.
/// The value 1/2 corresponds to the Gell-Mann normalization.
double TR;
/// The value of CF=TR (Nc^2-1)/(Nc).
/// Note that CF can be changed independently of Nc.
double CF;
/// While evaluating leading terms one may want to keep the full value of CF for
/// Nc=3, (TR(Nc^2-1)/Nc), or only keep the leading Nc term =TR*Nc (default).
/// full_CF is used by the Polynomial version of leading
/// (and hence also Poly_vec and Poly_matr versions etc).
/// The leading functions replaces CF by TR*Nc if full_CF is false (default)
/// while evaluating the leading terms.
/// If full_CF is true, CF is replaced by TR(Nc^2-1)/Nc.
/// Clearly this affects the result of subsequent numerical evaluation.
/// In the Col_basis class (and derived) the matrix version of leading
/// is used to evaluate scalar product matrices.
bool full_CF;
public:
/// Default constructor.
Col_functions()
: Nc(3.0), TR(0.5), CF(4.0/3.0), full_CF( false ) {}
/// Set the number of colors.
/// The value of CF is adjusted accordingly.
void set_Nc( double n) {
Nc = n;
CF = TR*(Nc*Nc-1.)/Nc;
}
/// Set the normalization of the generators.
/// The value of CF is adjusted accordingly.
void set_TR( double tr) {
CF *= tr/TR;
TR = tr;
}
/// Set the value of CF.
/// The value of Nc is NOT adjusted accordingly.
void set_CF( double cf) {
CF = cf;
}
/// Switch on/off full_CF.
void set_full_CF( bool is_full ) { full_CF = is_full; }
/// Get the number of colors.
double get_Nc() const { return Nc; }
// Returns the normalization of the generators,
/// tr(t^a t^b)=TR*delta^{a,b}.
double get_TR() const { return TR; }
/// Get the number of colors.
double get_CF() const { return CF; }
/// Return true, if full CF is used
bool get_full_CF() const { return full_CF; }
/****************** Functions for leading terms *************************/
// The functions called leading(...) depend on the variable full_CF.
// As it would be messy to let each Polynomial carry around
// its own full_CF, these functions are kept here.
/// Function for finding the leading power of Nc in a Poly_vec,
/// i.e., the power of Nc plus the power of CF.
int leading_Nc_pow( const Polynomial & Poly ) const;
/// Function for finding the leading power of Nc in a Poly_vec.
int leading_Nc_pow( const Poly_vec & Pv ) const;
/// Function for finding the leading power of Nc in a
/// vector of pointer to Polynomials.
-int leading_Nc_pow( std::vector< boost::shared_ptr<Polynomial> > Pvp) const;
+int leading_Nc_pow( std::vector< shared_ptr<Polynomial> > Pvp) const;
/// Takes the leading Nc terms of a Polynonmial, i.e. Monomials with highest
/// power of Nc+CF. If full_CF is false (default), CF is replaced by TR Nc.
/// If full_CF is true CF is replaced by TR(Nc^2-1)/Nc.
Polynomial leading( const Polynomial & Poly ) const;
/// Take the leading part of a Poly_vec.
/// Keeps only Monomials with maximal power of CF + Nc.
/// Uses leading( const Polynomial & Poly).
/// If full_CF is false (default), CF is replaced by TR Nc.
/// If full_CF is true CF is replaced by TR(Nc^2-1)/Nc.
/// Note that taking the leading terms of a Poly_vec is not
/// the same as taking the leading terms in each Polynomial.
// Used only by Poly_matr version of leading
Poly_vec leading( const Poly_vec & Pv ) const;
/// Takes the leading part of a matrix of Polynomials,
/// keeping only those with maximal power of CF + Nc.
/// If full_CF is false (default), CF is replaced by TR Nc.
/// If full_CF is true CF is replaced by TR(Nc^2-1)/Nc.
/// Note that taking the leading terms of a Poly_matr is not
/// the same as taking the leading terms in each Poly_vec.
// Used only once in Col_basis
Poly_matr leading( const Poly_matr & Pm ) const;
/// Take the leading part of a Poly_vec, given a vector of pointers to the Polynomials.
/// Keeps only Monomials with maximal power of CF + Nc.
// Currently never used
-Poly_vec leading( std::vector<boost::shared_ptr<Polynomial> > Pvp) const;
+Poly_vec leading( std::vector<shared_ptr<Polynomial> > Pvp) const;
/// Take the leading part of a Poly_matr, given a vector of vector of pointers to the Polynomials.
/// Loops over Monomials in all Polynomials
/// and keeps only those with maximal power of CF + Nc.
// used only by scalar_product_matrix_mem in Col_functions
-dmatr leading( std::vector< std::vector< boost::shared_ptr<Polynomial> > > Pm ) const;
+dmatr leading( std::vector< std::vector< shared_ptr<Polynomial> > > Pm ) const;
/// To keep only leading terms in a map.
// used only on Col_functions by scalar product_matrix_mem_2 and radiation_amplitude_matrix
std::map< std::string, Polynomial > leading( std::map< std::string, Polynomial > mem_map ) const;
/********************* Functions for numerical evaluation *************************/
// These functions has to be kept in Col_functions class as they need numerical
// values for evaluation. Letting each Polynomial carry around its own Nc etc.
// would be messy.
/// To take the numerical value of a map.
-std::map< std::string, double > double_num( std::map< std::string, boost::shared_ptr<Polynomial> > mem_map ) const;
+std::map< std::string, double > double_num( std::map< std::string, shared_ptr<Polynomial> > mem_map ) const;
/// Numerically evaluates a Monomial using the Nc and CF variables;
cnum cnum_num( const Monomial & Mon ) const;
// Numerically evaluates a Monomial to a double.
double double_num( const Monomial & Mon ) const;
/// Numerically evaluates a Polynomial, using the CF and Nc variables.
cnum cnum_num( const Polynomial & Poly ) const;
/// Numerically evaluates a Polynomial using the data members Nc, CF and TR.
double double_num( const Polynomial & Poly ) const;
/// To take the numerical value of a map.
std::map< std::string, double > double_num(std::map< std::string, Polynomial > mem_map) const;
/// Numerically evaluates a Poly_vec (vector of Polynomial) for Nc=3.
dvec double_num( const Poly_vec & Pv ) const;
/// Returns a double value. The argument is a vector of pointers to Polynomials.
-dvec double_num( const std::vector<boost::shared_ptr<Polynomial> > & Pv ) const;
+dvec double_num( const std::vector<shared_ptr<Polynomial> > & Pv ) const;
/// Returns a double value. The argument is a vector of vector of pointers to Polynomials.
-dmatr double_num( const std::vector<std::vector<boost::shared_ptr<Polynomial> > > & Pm ) const;
+dmatr double_num( const std::vector<std::vector<shared_ptr<Polynomial> > > & Pm ) const;
/// Numerically evaluates a Polynomial for Nc=3,
/// and stores in the format of a Polynomial with only one term with only a numerical part.
Polynomial Polynomial_cnum_num( const Polynomial & Poly ) const;
/// Numerically evaluates a Poly_vec (vector of Polynomial),
/// using cnum_num (Polynomial).
cvec cnum_num( const Poly_vec & Pv ) const;
/// Numerically evaluates a Poly_vec (vector of Polynomial)
/// and stores in the form of a Poly_vec, uses polynomial_cnum_num( Pv.at( p ) ).
/// for each Polynomial.
Poly_vec Poly_vec_cnum_num( const Poly_vec & Pv ) const;
/// Numerically evaluates a Poly_matr (vector of Poly_vec)
/// and stores in the form of a Poly_matr.
Poly_matr Poly_matr_cnum_num( const Poly_matr & Pm ) const;
/// Numerically evaluates a Poly_matr (vector of Poly_vec),
/// using cnum_num( Poly_vec ) for each Poly_vec.
cmatr cnum_num( const Poly_matr & Pm ) const;
/// Numerically evaluates a Poly_matr (vector of Poly_vec).
dmatr double_num( const Poly_matr & Pm ) const;
/****************** Functions for scalar products *************************/
/// Function for calculating scalar products between Col_amps.
/// Does not add implicit state in the gluons only case.
Polynomial scalar_product( const Col_amp & Ca1, const Col_amp & Ca2 ) const;
/// Function for calculating scalar product between two Col_strs.
/// Does not add implicit state in the gluons only case.
Polynomial scalar_product( const Col_str & Cs1, const Col_str & Cs2 ) const;
/****************** Functions for gluon emission and exchange *************/
/// Function for emitting a gluon from a Col_str.
/// When the gluon is inserted before the emitter in a Quark_line,
/// the amplitude comes with a minus sign.
Col_amp emit_gluon( const Col_str & in_Col_str, int emitter, int g_new ) const;
/// Function for emitting a gluon from a Col_amp.
/// When the gluon is inserted before the emitter in a Quark_line,
/// the amplitude comes with a minus sign.
Col_amp emit_gluon( const Col_amp & Ca_in, int emitter, int g_new ) const;
/// Function for exchanging a gluon between the partons p1 and p2 in the Col_str Cs.
/// When the gluon is inserted before the emitter in a Quark_line,
/// the amplitude comes with a minus sign.
Col_amp exchange_gluon( const Col_str & Cs, int p1, int p2 ) const;
/// Function for exchanging a gluon between two partons p1 and p2 in the Col_amp Ca.
/// When the gluon is inserted before the emitter in a Quark_line,
/// the amplitude comes with a minus sign.
/// (The incoming amplitude is what it is, there is no special
/// treatment of glons only cases.)
Col_amp exchange_gluon( const Col_amp & Ca, int p1, int p2 ) const;
/// Calculates < M | T^(i) T^(j) | M >, the "color correlator"
/// relevant for coherent gluon emission of gluon g_new from
/// parton i and parton j, or gluon exchange between i and j.
/// The Ca should thus be | M >, g_new should be a unique dummy index,
/// and i and j are the partons involved in the emission (exchange).
/// (The incoming amplitude is what it is, there is no special
/// treatment of gluons only cases.)
Polynomial color_correlator( const Col_amp Ca, int i, int j, int g_new ) const;
/********************* Other functions *************************/
// As dvec and dmatr are not classes some read and write functions
// are contained here.
/// Read in a numerical matrix from filename and save it as a double matrix, dmatr.
/// The file should be in the format
/// {d11,...,d1n}.
dvec read_in_dvec( std::string filename ) const;
/// Read in a numerical matrix from filename and save it as a double matrix, dmatr.
/// The file should be in the format
/// {{d11,...,d1n},
/// ...,
/// {dn1,...,dnn}},
/// and may contain comment lines starting with # at the top.
dmatr read_in_dmatr( std::string filename ) const;
/// Function for writing out a numerical vector,
/// to the file filename.
void write_out_dvec( const dvec & dv, std::string filename ) const;
/// Writes out the double version of a (scalar product) matrix
/// to the file filename.
void write_out_dmatr( const dmatr & matr, std::string filename ) const;
/// The factorial of an int, 0! is defined as 1.
int factorial( int i ) const;
}; // end class Col_functions
/////////////////////// DECLEARING OPERATORS /////////////////////
/// Defining + operator to be able to erase elements at place
std::list<int>::iterator operator+( std::list<int>::iterator x, int n );
std::list<int>::iterator operator-( std::list<int>::iterator x, int n );
/// Defining + operator to be able to erase elements at place
std::list< Quark_line >::iterator operator+( std::list < Quark_line >::iterator x, int n );
col_str::iterator operator-( col_str::iterator x, int n );
/// Define the operator << for vector of int.
std::ostream& operator<<( std::ostream& out, std::vector<int> vec );
/// Define the operator << for cvec.
std::ostream& operator<<( std::ostream& out, const cvec & cv );
/// Define the operator << for dvec.
std::ostream& operator<<( std::ostream& out, const dvec & dv );
/// Define the operator << for cmatr.
std::ostream& operator<<( std::ostream& out, const cmatr & cm );
/// Define the operator << for dmatr.
std::ostream& operator<<( std::ostream& out, const dmatr & matr );
/// Define the operator << for std::pair<int, int>.
std::ostream& operator<<( std::ostream& out, std::pair<int, int> pair );
} // end namespace ColorFull
#endif /* COLORFULL_Col_functions_h */
diff --git a/MatrixElement/Matchbox/ColorFull/Orthogonal_basis.cc b/MatrixElement/Matchbox/ColorFull/Orthogonal_basis.cc
--- a/MatrixElement/Matchbox/ColorFull/Orthogonal_basis.cc
+++ b/MatrixElement/Matchbox/ColorFull/Orthogonal_basis.cc
@@ -1,500 +1,500 @@
/*
* Orthogonal_basis.cc
* Contains the definitions of the class Orthogonal_basis, related types and operators.
* Created on: May 25, 2013
* Author: Malin Sjodahl
*/
#include "Orthogonal_basis.h"
#include "parameters.h"
#include <cassert>
#include <fstream>
#include <iostream>
namespace ColorFull {
void Orthogonal_basis::scalar_product_matrix(){
if( ng+nq>5 ){
std::cout << "Orthogonal_basis::scalar_product_matrix: nq+n_g0=" << nq+ng << " is large, consider using numerical and/or memory version. " << std::endl;
std::cout.flush();
}
return scalar_product_matrix( true, true, false );
}
void Orthogonal_basis::diagonal_scalar_product_matrix( bool save_P_diagonal_spm, bool save_d_diagonal_spm, bool use_mem ){
// If the diagonal_P_spm and diagonal_d_spm have already been calculated, erase them
diagonal_P_spm.clear();
diagonal_d_spm.clear();
if( (cb.size()==0 ) ) {
std::cout << "Orthogonal_basis::diagonal_scalar_product_matrix: There are no basis vectors in this basis, consider using read_in_basis." << std::endl;
std::cout.flush();
return ;
}
// Check that all Polynomials are real
// (check doesn't cover the case of complex Polynomial in a Quark_line)
// but if an entry is not real this will be discovered as the d_spm is calculated
for ( uint cbi=0; cbi < cb.size(); cbi++){
for ( uint j=0; j< cb.at(cbi).size(); j++){
if( imag (Col_fun.cnum_num( cb.at(cbi).at(j).Poly )) > accuracy ){
std::cerr << "Orthogonal_basis::diagonal_scalar_product_matrix: ColorFull expects real Polynomial multiplying the color structure, but the Polynomial\n"
<< cb.at(cbi).at(j).Poly << std::endl
<< " appearing in front of the Col_str " << cb.at(cbi).at(j).cs
<< " in basis vector number " << cbi << " is not real."<< std::endl << std::endl;
std::cerr.flush();
assert( 0 );
}
}
}
// For remembering already calculated topologies
- std::map<std::string, boost::shared_ptr<Polynomial> > mem_map;
+ std::map<std::string, std::shared_ptr<Polynomial> > mem_map;
// Loop over basis vectors in Basis
for( uint i=0; i < cb.size(); i++){
// To contain the result of vector i square
Polynomial iiRes;
iiRes=iiRes*0;
if(use_mem){
// Loop over Col_strs in first Ca
for( uint Ca1i=0; Ca1i< cb.at(i).size(); Ca1i++){
// Loop over Col_strs in second Ca
for( uint Ca2i=0; Ca2i< cb.at(i).size(); Ca2i++){
// To contain the contribution to the ii-th entry if memoization is used
- boost::shared_ptr<Polynomial> iiEntry_contr;
+ std::shared_ptr<Polynomial> iiEntry_contr;
// Rename indices, and make string of new col_strs, to use in map
// strip off Polynomial information to make the map minimal
Col_str Cs1, Cs2;
Cs1.append(cb.at(i).at(Ca1i).cs);
Cs2.append(cb.at(i).at(Ca2i).cs);
rename_indices( Cs1, Cs2 );
std::ostringstream Cs_string;
Cs_string << Cs1 << Cs2;
// Calculate element contribution to the ijth element in scalar product matrix
// If this has scalar product has occurred before, reuse old value
if (mem_map.count( Cs_string.str() ) > 0) {
iiEntry_contr = mem_map[Cs_string.str()];
}
// Otherwise, calculate value and save topology
else {
Polynomial p = Col_fun.scalar_product(Cs1, Cs2);
iiEntry_contr = shared_ptr<Polynomial> (new Polynomial(p));
mem_map[Cs_string.str()] = iiEntry_contr;
}
// Sum up all the contributions to one Polynomial, recall to multiply with Polynomials
Polynomial iiEntry_contr_poly=(*iiEntry_contr)* cb.at(i).at(Ca1i).Poly*cb.at(i).at(Ca2i).Poly;
if( !save_P_diagonal_spm ) {
double iiEntry_contr_d= Col_fun. double_num( iiEntry_contr_poly );
Monomial Mon( iiEntry_contr_d );
iiRes+= Mon;
}
else iiRes += iiEntry_contr_poly;
} // end looping over Cs in first Ca
} // end looping over Cs in 2nd Ca
// If Polynomial result is wanted, simplify
if ( save_P_diagonal_spm ) iiRes.simplify();
// Otherwise convert to numerical
else {
double num_iiRes= Col_fun. double_num( iiRes );
iiRes.clear();
Monomial Mon( num_iiRes );
iiRes.push_back(Mon);
}
diagonal_P_spm.push_back( iiRes );
} // end if ( use_mem )
else{
// Calculate element ij in scalar product matrix
Polynomial iiRes=Col_fun.scalar_product(cb.at(i), cb.at(i));
iiRes.simplify();
diagonal_P_spm.push_back( iiRes );
} //end if (not mem)
}// end looping over i
if ( save_d_diagonal_spm ){
diagonal_d_spm=Col_fun.double_num(diagonal_P_spm);
}
if (! save_P_diagonal_spm){
diagonal_P_spm.clear();
}
return;
}
void Orthogonal_basis::scalar_product_matrix( bool save_P_spm, bool save_d_spm, bool use_mem ) {
// If the P_spm and d_spm have already been calculated, erase them
P_spm.clear();
d_spm.clear();
// First calculate diagonal version
diagonal_scalar_product_matrix( save_P_spm, save_d_spm, use_mem );
// Then copy content to matrix
if( save_P_spm ){
// First empty P_spm
P_spm.clear();
Polynomial Zero;
Zero=0*Zero;
for (uint i=0; i< diagonal_P_spm.size(); i++ ){
Poly_vec rowi;
for (uint j=0; j< diagonal_P_spm.size(); j++ ){
if(i==j){// diagonal entries
rowi.push_back( diagonal_P_spm.at(i));
}
else{// non-diagonal parts
rowi.push_back(Zero);
}
}
P_spm.push_back(rowi);
}
}
if( save_d_spm ){
// First empty P_spm
d_spm.clear();
for (uint i=0; i< diagonal_d_spm.size(); i++ ){
dvec rowi;
for (uint j=0; j< diagonal_d_spm.size(); j++ ){
if(i==j){// diagonal entries
rowi.push_back( diagonal_d_spm.at(i));
}
else{// non-diagonal parts
rowi.push_back( 0 );
}
}
d_spm.push_back(rowi);
}
}
}
Poly_vec Orthogonal_basis::decompose( const Col_amp & Ca ) {
// Check that we have a basis
if(cb.size()==0){
std::cerr << "Orthogonal_basis::decompose: The basis vector cb is empty consider reading in basis." << std::endl;
assert( 0 );
}
// Check that quark and gluon content agree with that in Col_amp
else if(Ca.size()>0 ){
if(Ca.at(0).n_quark() != nq)
{
std::cerr << "Orthogonal_basis::decompose: The number of quarks in the argument Col_amp, " << Ca.at(0).n_quark()
<< ", does not fit the number of quarks in the basis "
<< nq << std::endl;}
if(Ca.at(0).n_gluon() != ng )
{
std::cerr << "Orthogonal_basis::decompose: The number of gluons in the argument Col_amp " << Ca.at(0).n_gluon()
<< " does not fit the number of gluons in the basis "
<< nq << std::endl;
}
}
// This version of decompose (as opposed to trace type versions)
// need scalar product matrix
// If P_spm is not empty, but has wrong size
if( P_spm.size() != cb.size() and !P_spm.empty() ){
std::cerr << "Orthogonal_basis::decompose: The size of the scalar product matrix and the basis do not agree." << std::endl;
assert( 0 );
}
// If diagonal_P_spm is not empty, but has wrong size
if( diagonal_P_spm.size() != cb.size() and !diagonal_P_spm.empty() ){
std::cerr << "Orthogonal_basis::decompose: The size of the diagonal scalar product matrix and the basis do not agree." << std::endl;
assert( 0 );
}
// If both are empty, calculate diagonal version
if( P_spm.empty() and diagonal_P_spm.empty() ){
diagonal_scalar_product_matrix(true, true, true);
}
// Use matrix information if diagonal spm is empty
if( diagonal_P_spm.empty() ){
for ( uint i=0; i< P_spm.size(); i++ ){
diagonal_P_spm.push_back( P_spm.at(i).at(i) );
}
diagonal_d_spm=Col_fun.double_num(diagonal_P_spm);
}
// To contain the decomposed vector
Poly_vec Decv;
// Loop over all vectors in cb and calculate projection
for (uint i = 0; i < cb.size(); i++) {
double inv_norm=1.0/diagonal_d_spm.at(i);
//Decv.at(i)= Col_fun.scalar_product( cb.at(i) , Ca )*inv_norm;
Decv.push_back( Col_fun.scalar_product( cb.at(i) , Ca )*inv_norm );
}
return Decv;
}
std::string Orthogonal_basis::diagonal_spm_file_name(const bool leading, const bool poly ) const{
// First construct filename
std::ostringstream ss;
std::string filename;
ss << "ColorResults";
ss << '/';
// CF as in ColorFull
ss << "CF_";
// Prefix according to basis type
ss << "OB_";
// diagonal version
ss << "diagonal_";
// Polynomial or numerical matrix?
if( poly )ss << "P_";
else ss << "d_";
ss << "spm_q";
ss << nq;
ss << "_g";
ss << ng;
// is the result leading, and if so, how?
if ( leading ) ss << "_l";
if ( Col_fun.get_full_CF() ) ss << "_cff";
else ss << "_cfl";
if( Col_fun.get_Nc() != 3 ){
ss << "_Nc_";
ss << Col_fun.get_Nc();
}
if(Col_fun.get_TR() != 0.5 ){
ss << "_TR_";
ss << Col_fun.get_TR();
}
filename=ss.str();
return filename;
}
void Orthogonal_basis::write_out_diagonal_d_spm( std::string filename ) const{
Col_fun.write_out_dvec( diagonal_d_spm, filename );
}
void Orthogonal_basis::write_out_diagonal_d_spm( ) const{
std::string filename = diagonal_spm_file_name( false, false );
write_out_diagonal_d_spm( filename );
}
void Orthogonal_basis::write_out_diagonal_P_spm( std::string filename ) const{
diagonal_P_spm.write_out_Poly_vec( filename );
}
void Orthogonal_basis::write_out_diagonal_P_spm( ) const{
std::string filename = diagonal_spm_file_name( false, true );
write_out_diagonal_P_spm( filename );
}
Polynomial Orthogonal_basis::scalar_product( const Col_amp & Ca1, const Col_amp & Ca2 ) {
// Check that we have a basis
if(cb.size()==0){
std::cerr << "Orthogonal_basis::scalar_product: The basis vector cb is empty consider using create_basis or read_in_basis." << std::endl;
assert( 0 );
}
// Check that size of P_spm is consistent (if calculated)
if( (P_spm.size() != cb.size()) and P_spm.size() !=0 ) {
std::cerr << "Orthogonal_basis::scalar_product: Size of scalar product matrix P_spm and color basis cb do not agree." << std::endl;
assert( 0 );
}
// Check that size of diagonal_P_spm is consistent (if calculated)
if( (diagonal_P_spm.size() != cb.size()) and diagonal_P_spm.size() !=0 ) {
std::cerr << "Orthogonal_basis::scalar_product: Size of diagonal_P_spm and color basis cb do not agree." << std::endl;
assert( 0 );
}
// Check if at least one of P_spm and diagonal_P_spm exist,
// If non exist, calculate diagonal
if( P_spm.empty() and diagonal_P_spm.empty() ){
diagonal_scalar_product_matrix(true, true, true);
}
// If matrix form, but not diagonal exist, copy diagonal entries
else if(diagonal_P_spm.empty() ){
for( uint i=0; i< P_spm.size(); i++ ){
diagonal_P_spm.push_back(P_spm.at(i).at(i));
}
}
// To contain the resulting Polynomial
Polynomial Poly_res;
Poly_res=Poly_res*0;
// Decompose the Col_amps
Poly_vec Polyv1=decompose(Ca1);
Polyv1.conjugate();
Poly_vec Polyv2=decompose( Ca2 );
// Then add contributions
for (uint m1=0; m1< cb.size(); m1++){
// Diagonal terms
Poly_res=Poly_res+Polyv1.at(m1) *Polyv2.at(m1) *diagonal_P_spm.at(m1);
}
return Poly_res;
}
cnum Orthogonal_basis::scalar_product_num( const Col_amp & Ca1, const Col_amp & Ca2 ) {
// Check that we have a basis
if(cb.size()==0){
std::cerr << "Orthogonal_basis::scalar_product_num: The basis vector cb is empty consider using create_basis or read_in_basis." << std::endl;
assert( 0 );
}
// Check that size of d_spm is consistent (if calculated)
if( (d_spm.size() != cb.size()) and d_spm.size() !=0 ) {
std::cerr << "Orthogonal_basis::scalar_product_num: Size of scalar product matrix d_spm and color basis cb do not agree." << std::endl;
assert( 0 );
}
// Check that size of diagonal_d_spm is consistent (if calculated)
if( (diagonal_d_spm.size() != cb.size()) and diagonal_d_spm.size() !=0 ) {
std::cerr << "Orthogonal_basis::scalar_product_num: Size of diagonal_d_spm and color basis cb do not agree." << std::endl;
assert( 0 );
}
// Check if at least one of d_spm and diagonal_d_spm exist,
// If non exist, calculate diagonal version
if( d_spm.empty() and diagonal_d_spm.empty() ){
diagonal_scalar_product_matrix(false, true, true);
}
// If matrix form, but not diagonal exist, copy diagonal entries
else if(diagonal_d_spm.empty() ){
for( uint i=0; i< d_spm.size(); i++ ){
diagonal_d_spm.push_back(d_spm.at(i).at(i));
}
}
// To contain the result
double res=0;
// Decompose the Col_amps
Poly_vec Polyv1=decompose(Ca1);
Polyv1.conjugate();
Poly_vec Polyv2=decompose( Ca2 );
dvec v1=Col_fun.double_num( Polyv1 );
dvec v2=Col_fun.double_num( Polyv2 );
// Then add contributions
for (uint m1=0; m1< cb.size(); m1++){
// Diagonal terms
res=res+v1.at(m1) *v2.at(m1) *diagonal_d_spm.at(m1);
}
return res;
}
cnum Orthogonal_basis::scalar_product_num( const cvec & v1, const cvec & v2) {
if(v1.size()!= v2.size()){
std::cerr << "Orthogonal_basis::scalar_product_num: Size of first vector "
<< v1.size() << " does not agree with size of second vector "
<< v2.size() << std::endl;
assert( 0 );
}
// Check that size of d_spm is consistent (if calculated)
if( ( d_spm.size() != cb.size()) and d_spm.size() !=0 ) {
std::cerr << "Orthogonal_basis::scalar_product_num: Size of scalar product matrix d_spm and color basis cb do not agree." << std::endl;
assert( 0 );
}
// Check that size of diagonal_d_spm is consistent (if calculated)
if( ( diagonal_d_spm.size() != cb.size()) and diagonal_d_spm.size() !=0 ) {
std::cerr << "Orthogonal_basis::scalar_product_num: Size of diagonal_d_spm and color basis cb do not agree." << std::endl;
assert( 0 );
}
// Check if at least one of d_spm and diagonal_d_spm exist,
// If non exist, calculate diagonal version
if( d_spm.empty() and diagonal_d_spm.empty() ){
diagonal_scalar_product_matrix(false, true, true);
}
// If matrix form, but not diagonal exist, copy diagonal entries
else if(diagonal_d_spm.empty() ){
for( uint i=0; i< d_spm.size(); i++ ){
diagonal_d_spm.push_back(d_spm.at(i).at(i));
}
}
uint basis_size=v1.size();
// To contain the result
cnum res=0;
// Add contributions, diagonal parts only
for (uint m1=0; m1< basis_size; m1++){
res += conj( v1.at(m1) ) *v2.at(m1) *diagonal_d_spm.at(m1);
}
return res;
}
void Orthogonal_basis::write_out_diagonal_spm( const dvec & dv, const bool leading ) const{
std::string filename = diagonal_spm_file_name( leading, false );
std::ofstream outfile(filename.c_str());
if ( !outfile )
std::cerr << "Orthogonal_basis::write_out_diagonal_spm: Cannot write out diagonal scalar products as the file \""
<< filename.c_str() << "\" could not be opened. (Does the directory exist? Consider creating the directory.)" << std::endl;
outfile << dv;
}
void Orthogonal_basis::write_out_diagonal_spm( const Poly_vec & Pv, const bool leading ) const{
std::string filename = diagonal_spm_file_name( leading, true );
std::ofstream outfile(filename.c_str());
outfile << Pv;
}
} //end namespace ColorFull
diff --git a/MatrixElement/Matchbox/Cuts/Makefile.am b/MatrixElement/Matchbox/Cuts/Makefile.am
--- a/MatrixElement/Matchbox/Cuts/Makefile.am
+++ b/MatrixElement/Matchbox/Cuts/Makefile.am
@@ -1,19 +1,31 @@
pkglib_LTLIBRARIES = HwMatchboxCuts.la
HwMatchboxCuts_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 2:0:0
-HwMatchboxCuts_la_SOURCES = \
+HwMatchboxCuts_la_SOURCES = $(ALL_H_FILES) Cuts__all.cc
+
+BUILT_SOURCES = Cuts__all.cc
+DISTCLEANFILES = Cuts__all.cc
+
+Cuts__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+IdentifiedParticleCut.h \
+MatchboxDeltaRCut.h \
+MissingPtCut.h \
+FrixionePhotonSeparationCut.h \
+InvariantMassCut.h \
+PairPtCut.h \
+PairRapidityCut.h
+
+ALL_CC_FILES = \
IdentifiedParticleCut.cc \
-IdentifiedParticleCut.h \
MatchboxDeltaRCut.cc \
-MatchboxDeltaRCut.h \
MissingPtCut.cc \
-MissingPtCut.h \
FrixionePhotonSeparationCut.cc \
-FrixionePhotonSeparationCut.h \
InvariantMassCut.cc \
-InvariantMassCut.h \
PairPtCut.cc \
-PairPtCut.h \
-PairRapidityCut.cc \
-PairRapidityCut.h
+PairRapidityCut.cc
diff --git a/MatrixElement/Matchbox/Dipoles/Makefile.am b/MatrixElement/Matchbox/Dipoles/Makefile.am
--- a/MatrixElement/Matchbox/Dipoles/Makefile.am
+++ b/MatrixElement/Matchbox/Dipoles/Makefile.am
@@ -1,56 +1,69 @@
noinst_LTLIBRARIES = libHwMatchboxDipoles.la
-libHwMatchboxDipoles_la_SOURCES = \
-FFggxDipole.cc \
+libHwMatchboxDipoles_la_SOURCES = $(ALL_H_FILES) Dipole__all.cc
+
+BUILT_SOURCES = Dipole__all.cc
+DISTCLEANFILES = Dipole__all.cc
+
+Dipole__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_CC_FILES)
+
+ALL_H_FILES = \
FFggxDipole.h \
-FFqgxDipole.cc \
FFqgxDipole.h \
-FFqqxDipole.cc \
FFqqxDipole.h \
-FIggxDipole.cc \
FIggxDipole.h \
-FIqgxDipole.cc \
FIqgxDipole.h \
-FIqqxDipole.cc \
FIqqxDipole.h \
-IFggxDipole.cc \
IFggxDipole.h \
-IFgqxDipole.cc \
IFgqxDipole.h \
-IFqgxDipole.cc \
IFqgxDipole.h \
-IFqqxDipole.cc \
IFqqxDipole.h \
-IIggxDipole.cc \
IIggxDipole.h \
-IIgqxDipole.cc \
IIgqxDipole.h \
-IIqgxDipole.cc \
IIqgxDipole.h \
-IIqqxDipole.cc \
IIqqxDipole.h \
-FFMggxDipole.cc \
FFMggxDipole.h \
-FFMqgxDipole.cc \
FFMqgxDipole.h \
-FFMsqgxDipole.cc \
FFMsqgxDipole.h \
-FFMqqxDipole.cc \
FFMqqxDipole.h \
-FIMqgxDipole.cc \
FIMqgxDipole.h \
-FIMsqgxDipole.cc \
FIMsqgxDipole.h \
-FIMqqxDipole.cc \
FIMqqxDipole.h \
-IFMggxDipole.cc \
IFMggxDipole.h \
-IFMgqxDipole.cc \
IFMgqxDipole.h \
-IFMqgxDipole.cc \
IFMqgxDipole.h \
-IFMqqxDipole.cc \
IFMqqxDipole.h \
-SubtractionDipole.cc \
SubtractionDipole.fh \
SubtractionDipole.h
+
+
+ALL_CC_FILES = \
+FFggxDipole.cc \
+FFqgxDipole.cc \
+FFqqxDipole.cc \
+FIggxDipole.cc \
+FIqgxDipole.cc \
+FIqqxDipole.cc \
+IFggxDipole.cc \
+IFgqxDipole.cc \
+IFqgxDipole.cc \
+IFqqxDipole.cc \
+IIggxDipole.cc \
+IIgqxDipole.cc \
+IIqgxDipole.cc \
+IIqqxDipole.cc \
+FFMggxDipole.cc \
+FFMqgxDipole.cc \
+FFMsqgxDipole.cc \
+FFMqqxDipole.cc \
+FIMqgxDipole.cc \
+FIMsqgxDipole.cc \
+FIMqqxDipole.cc \
+IFMggxDipole.cc \
+IFMgqxDipole.cc \
+IFMqgxDipole.cc \
+IFMqqxDipole.cc \
+SubtractionDipole.cc
diff --git a/MatrixElement/Matchbox/External/GoSam/Makefile.am b/MatrixElement/Matchbox/External/GoSam/Makefile.am
--- a/MatrixElement/Matchbox/External/GoSam/Makefile.am
+++ b/MatrixElement/Matchbox/External/GoSam/Makefile.am
@@ -1,18 +1,10 @@
-pkglib_LTLIBRARIES = HwMatchboxGoSam.la
-HwMatchboxGoSam_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 13:0:0
-
-HwMatchboxGoSam_la_SOURCES = \
-GoSamAmplitude.h GoSamAmplitude.cc
-
-HwMatchboxGoSam_la_CPPFLAGS = $(AM_CPPFLAGS) \
--DHERWIG_BINDIR="\"$(bindir)\"" \
--DHERWIG_PKGDATADIR="\"$(pkgdatadir)\"" \
--DGOSAM_PREFIX="\"$(GOSAMPREFIX)\""
-
-EXTRA_DIST = gosam2herwig.py
+EXTRA_DIST = \
+GoSamAmplitude.h \
+GoSamAmplitude.cc \
+gosam2herwig.py
install-exec-local:
$(install_sh_SCRIPT) $(srcdir)/gosam2herwig.py $(DESTDIR)$(bindir)/gosam2herwig
uninstall-local:
rm -f $(DESTDIR)$(bindir)/gosam2herwig
diff --git a/MatrixElement/Matchbox/External/MadGraph/MadGraphAmplitude.cc b/MatrixElement/Matchbox/External/MadGraph/MadGraphAmplitude.cc
--- a/MatrixElement/Matchbox/External/MadGraph/MadGraphAmplitude.cc
+++ b/MatrixElement/Matchbox/External/MadGraph/MadGraphAmplitude.cc
@@ -1,849 +1,848 @@
// -*- C++ -*-
//
// MadGraphAmplitude.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 MadGraphAmplitude class.
//
#include "MadGraphAmplitude.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 "Herwig/MatrixElement/Matchbox/MatchboxFactory.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
-#include <boost/lexical_cast.hpp>
#include <boost/filesystem.hpp>
#include <cstdlib>
#include <dlfcn.h>
#include <errno.h>
#include <sstream>
using namespace Herwig;
#ifndef HERWIG_BINDIR
#error Makefile.am needs to define HERWIG_BINDIR
#endif
#ifndef HERWIG_PKGDATADIR
#error Makefile.am needs to define HERWIG_PKGDATADIR
#endif
#ifndef MADGRAPH_PREFIX
#error Makefile.am needs to define MADGRAPH_PREFIX
#endif
extern "C" void mginitproc_(char *i,int);
extern "C" void MG_Calculate_wavefunctions_virt(int* proc,double*,double*);
extern "C" void MG_Calculate_wavefunctions_born(int* proc,double*, int*);
extern "C" void MG_Jamp (int* proc,int*, double*);
extern "C" void MG_LNJamp (int* proc,int*, double*);
extern "C" void MG_Virt (int* proc,double*);
extern "C" void MG_NCol (int* proc,int*);
extern "C" void MG_vxxxxx (double* p,double* n,int* inc,double* );
extern "C" void MG_Colour (int* proc,int* i,int* j ,int* color);
MadGraphAmplitude::MadGraphAmplitude()
: theMGmodel("loop_sm"),keepinputtopmass(false),
bindir_(HERWIG_BINDIR), includedir_(HERWIG_INCLUDEDIR), pkgdatadir_(HERWIG_PKGDATADIR), madgraphPrefix_(MADGRAPH_PREFIX)
{}
MadGraphAmplitude::~MadGraphAmplitude() {
}
IBPtr MadGraphAmplitude::clone() const {
return new_ptr(*this);
}
IBPtr MadGraphAmplitude::fullclone() const {
return new_ptr(*this);
}
bool MadGraphAmplitude::initializedMad=false;
vector<string> MadGraphAmplitude::BornAmplitudes=vector<string>();
vector<string> MadGraphAmplitude::VirtAmplitudes=vector<string>();
void MadGraphAmplitude::initProcess(const cPDVector& ) {
if ( lastMatchboxXComb()->initialized() )
return;
if ( !DynamicLoader::load(mgProcLibPath()+"InterfaceMadGraph.so") )
throw Exception() << "MadGraphAmplitude: Failed to load MadGraph amplitudes\n"
<< DynamicLoader::lastErrorMessage
<< Exception::runerror;
if (!initializedMad){
string mstr=(factory()->runStorage()+"MadGraphAmplitudes"+"/param_card"+((theMGmodel=="loop_sm")?"":("_"+theMGmodel))+".dat");
if( theMGmodel[0]=='/')mstr="param_card.dat";
size_t len = mstr.size();
mginitproc_(const_cast<char*>(mstr.c_str()),len);
initializedMad=true;
}
lastMatchboxXComb()->isInitialized();
}
bool MadGraphAmplitude::writeAmplitudesDat(){
bool res=false;
string born= mgProcLibPath()+"BornAmplitudes.dat";
if ( !boost::filesystem::exists(born) ) {
ofstream borns(born.c_str());
for (vector<string>::iterator amps=BornAmplitudes.begin();amps!=BornAmplitudes.end();amps++)
borns<<*amps<<endl;
borns.close();
res=true;
}
string virt= mgProcLibPath()+"VirtAmplitudes.dat";
if ( !boost::filesystem::exists(virt) ) {
ofstream virts(virt.c_str());
for (vector<string>::iterator amps=VirtAmplitudes.begin();amps!=VirtAmplitudes.end();amps++)
virts<<*amps<<endl;
virts.flush();
virts.close();
res=true;
}
return res;
}
bool MadGraphAmplitude::checkAmplitudes(){
string born= mgProcLibPath()+"BornAmplitudes.dat";
string virt= mgProcLibPath()+"VirtAmplitudes.dat";
assert ( boost::filesystem::exists(born)|| boost::filesystem::exists(virt));
bool foundallborns=true;
for (vector<string>::iterator amps=BornAmplitudes.begin();amps!=BornAmplitudes.end();amps++){
ifstream borns(born.c_str());
string line;
bool foundthisborn=false;
while (std::getline(borns, line)) {
if(line==*amps)foundthisborn=true;
}
foundallborns&=foundthisborn;
}
bool foundallvirts=true;
for (vector<string>::iterator amps=VirtAmplitudes.begin();amps!=VirtAmplitudes.end();amps++){
ifstream virts(virt.c_str());
string line;
bool foundthisvirt=false;
while (std::getline(virts, line)) {
if(line==*amps)foundthisvirt=true;
}
foundallvirts&=foundthisvirt;
}
if (!foundallborns||!foundallvirts)
throw Exception() << "MadGraphAmplitude: The MadGraph amplitudes did not match the process.\n"
<< " Please remove:"<<mgProcLibPath()<< "\n"
<< " or set a process path via the interface:\n"
<< " set /Herwig/MatrixElements/Matchbox/Amplitudes/MadGraph:ProcessPath ..."
<< Exception::runerror;
return foundallborns && foundallvirts;
}
string MadGraphAmplitude::mgProcLibPath(){
string res=theProcessPath == "" ? factory()->buildStorage()+"MadGraphAmplitudes" : theProcessPath;
if (res.at(res.length()-1) != '/') res.append("/");
return res;
}
bool MadGraphAmplitude::initializeExternal() {
if ( boost::filesystem::exists(mgProcLibPath()) ) {
if ( !boost::filesystem::is_directory(mgProcLibPath()) )
throw Exception() << "MadGraphAmplitude: MadGraph amplitude storage '"
<< mgProcLibPath() << "' existing but not a directory."
<< Exception::runerror;
} else {
boost::filesystem::create_directories(mgProcLibPath());
}
string runAmplitudes = factory()->runStorage() + "/MadGraphAmplitudes";
if ( boost::filesystem::exists(runAmplitudes) ) {
if ( !boost::filesystem::is_directory(runAmplitudes) )
throw Exception() << "MadGraphAmplitude: MadGraph amplitude storage '"
<< runAmplitudes << "' existing but not a directory."
<< Exception::runerror;
} else {
boost::filesystem::create_directories(runAmplitudes);
}
//EW-consistency check:
Energy MW=getParticleData(ParticleID::Wplus)->hardProcessMass();
Energy MZ=getParticleData(ParticleID::Z0)->hardProcessMass();
if( MW!= sqrt(MZ*MZ/2.0+sqrt(MZ*MZ*MZ*MZ/4.0-Constants::pi*SM().alphaEMMZ()*MZ*MZ/ sqrt(2.0)/SM().fermiConstant()))){
generator()->log()<<"\n\n-----!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!-----";
generator()->log() << "\nYou are using a EW scheme which is inconsistent with the MadGraph parametisation:\n\n"
<<MW/GeV<< " GeV==MW!= sqrt(MZ^2/2+sqrt(MZ^4/4.0-pi*alphaEMMZ*MZ^2/ sqrt(2)/G_f))=="<<
sqrt(MZ*MZ/2.0+sqrt(MZ*MZ*MZ*MZ/4.0-Constants::pi*SM().alphaEMMZ()*MZ*MZ/ sqrt(2.0)/SM().fermiConstant()))/GeV
<<" GeV\n\n-----!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!-----\n";
}
string para= factory()->runStorage()+"/MadGraphAmplitudes"+"/MG-Parameter.dat";
ofstream params(para.c_str());
params<<"$WZ$ " <<std::setiosflags(ios::scientific) <<getParticleData(ParticleID::Z0)->hardProcessWidth() /GeV;
params<<"\n$WW$ " <<std::setiosflags(ios::scientific) <<getParticleData(ParticleID::Wplus)->hardProcessWidth()/GeV;
params<<"\n$alphas$ " <<std::setiosflags(ios::scientific) <<SM().alphaS();
params<<"\n$GF$ " <<std::setiosflags(ios::scientific) <<SM().fermiConstant()*GeV2 ;
params<<"\n$alphaMZ$ " <<std::setiosflags(ios::scientific) <<1/SM().alphaEMMZ();
params<<"\n$MZ$ " <<std::setiosflags(ios::scientific) <<getParticleData(ParticleID::Z0)->hardProcessMass() /GeV<<flush;
params<<"\n$MW$ " <<std::setiosflags(ios::scientific) <<getParticleData(ParticleID::Wplus)->hardProcessMass() /GeV<<flush;
params<<"\n$sw2$ " <<std::setiosflags(ios::scientific) << SM().sin2ThetaW() <<flush;
if(theMGmodel=="heft"&&!keepinputtopmass){
if ( factory()->initVerbose() ) {
generator()->log()<<"\n---------------------------------------------------------------";
generator()->log()<<"\n---------------------------------------------------------------";
generator()->log()<<"\nNote: You are using the Higgs Effective model (heft) in ";
generator()->log()<<"\n Madgraph. We assume you try to calculate NLO with ";
generator()->log()<<"\n the GoSam virtual amplitudes. To match the models we ";
generator()->log()<<"\n therefore set the topmass to 10000000 GeV.";
generator()->log()<<"\n\n For more information see the \\tau parameter in:";
generator()->log()<<"\n https://cp3.irmp.ucl.ac.be/projects/madgraph/wiki/Models/HiggsEffective";
generator()->log()<<"\n\n The Effective Higgs model in Gosam is using mT=infinity";
generator()->log()<<"\n\n\n If you want to use the LO matrixelements of MadGraph with finite' topmass you need to add: ";
generator()->log()<<"\n\n set Madgraph:KeepInputTopMass True";
generator()->log()<<"\n\n to your input file.";
generator()->log()<<"\n---------------------------------------------------------------";
generator()->log()<<"\n---------------------------------------------------------------\n";
}
params<<"\n$MT$ 10000000." <<flush;
}else{
params<<"\n$MT$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::t)->hardProcessMass() /GeV <<flush;
}
params<<"\n$WT$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::t)->hardProcessWidth() /GeV <<flush;
params<<"\n$MB$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::b)->hardProcessMass() /GeV <<flush;
params<<"\n$MH$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::h0)->hardProcessMass() /GeV <<flush;
params<<"\n$WH$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::h0)->hardProcessWidth() /GeV <<flush;
params<<"\n$MTA$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::tauplus)->hardProcessMass() /GeV <<flush;
string cmd = "python " + bindir_ + "/mg2herwig ";
cmd +=" --buildpath "+mgProcLibPath();
cmd += !theProcessPath.empty() ? " --absolute-links" : "";
cmd +=" --model "+theMGmodel;
cmd +=" --runpath "+factory()->runStorage()+"/MadGraphAmplitudes ";
cmd +=" --datadir "+pkgdatadir_;
cmd +=" --includedir "+includedir_;
std::stringstream as,aem;
as << factory()->orderInAlphaS();
cmd +=" --orderas "+as.str() ;
aem <<factory()->orderInAlphaEW();
cmd +=" --orderew "+aem.str();
// TODO move to boost::system
writeAmplitudesDat();
if (boost::filesystem::exists(mgProcLibPath()+"InterfaceMadGraph.so") ){
//set the parameters
checkAmplitudes();
std::system(cmd.c_str());
ranMadGraphInitializeExternal = true;
return true;
}
char cwd[1024];
if ( !getcwd(cwd,sizeof(cwd)) )
throw Exception() << "MadGraphAmplitude: failed to determine current working directory\n"
<< Exception::runerror;
cmd +=" --madgraph " + madgraphPrefix_ + "/bin " ;
cmd +="--build > ";
cmd += mgProcLibPath()+"MG.log 2>&1";
generator()->log() << "\n>>> Compiling MadGraph amplitudes. This may take some time -- please be patient.\n"
<< ">>> In case of problems see " << mgProcLibPath() << "MG.log for details.\n\n"
<< flush;
std::system(cmd.c_str());
cmd = "python " + bindir_ + "/mg2herwig ";
cmd +=" --buildpath "+mgProcLibPath();
cmd +=" --model "+theMGmodel;
cmd +=" --runpath "+factory()->runStorage()+"/MadGraphAmplitudes ";
cmd +=" --datadir "+pkgdatadir_;
as.clear();
aem.clear();
as << factory()->orderInAlphaS();
cmd +=" --orderas "+as.str() ;
aem <<factory()->orderInAlphaEW();
cmd +=" --orderew "+aem.str();
std::system(cmd.c_str());
ranMadGraphInitializeExternal = true;
return boost::filesystem::exists(mgProcLibPath()+"InterfaceMadGraph.so");
}
int MadGraphAmplitude::externalId(const cPDVector& proc) {
for (int i=0;i<100;i++){
colourindex.push_back(-2);
}
assert(!BornAmplitudes.empty()||!VirtAmplitudes.empty());
writeAmplitudesDat();
int res=0;
string amp="";
int k=0;
for (cPDVector::const_iterator it=proc.begin();it!=proc.end();it++,k++){
- amp+=boost::lexical_cast<string>( (*it)->id())+" ";if (k==1)amp+=" > ";
+ amp+=std::to_string( (*it)->id())+" ";if (k==1)amp+=" > ";
}
string born= mgProcLibPath()+"BornAmplitudes.dat";
string virt= mgProcLibPath()+"VirtAmplitudes.dat";
assert ( boost::filesystem::exists(born)|| boost::filesystem::exists(virt));
ifstream borns(born.c_str());
string line;
while (std::getline(borns, line)) {
res+=1;
if(line==amp)return res;
}
ifstream virts(virt.c_str());
while (std::getline(virts, line)) {
res+=1;
if(line==amp)return res;
}
throw Exception() << "MadGraphAmplitude: One amplitude has no externalId. Please remove the MadGraphAmplitude-folder and rebuild.\n" << Exception::runerror;
return res;
}
bool MadGraphAmplitude::ranMadGraphInitializeExternal = false;
void MadGraphAmplitude::doinit() {
if ( !ranMadGraphInitializeExternal ) {
initializeExternal();
}
MatchboxAmplitude::doinit();
}
void MadGraphAmplitude::doinitrun() {
if ( !ranMadGraphInitializeExternal ) {
initializeExternal();
}
MatchboxAmplitude::doinitrun();
}
bool MadGraphAmplitude::canHandle(const PDVector& p,
Ptr<MatchboxFactory>::tptr factory,
bool virt) const {
if ( factory->processData()->diagramMap().find(p) !=
factory->processData()->diagramMap().end() )
return true;
vector<Ptr<Tree2toNDiagram>::ptr> diags =
factory->diagramGenerator()->generate(p,orderInGs(),orderInGem());
if ( diags.empty() )
return false;
factory->processData()->diagramMap()[p] = diags;
string amp="";
int k=0;
for (PDVector::const_iterator it=p.begin();it!=p.end();it++,k++){
- amp+=boost::lexical_cast<string>( (*it)->id())+" ";if (k==1)amp+=" > ";
+ amp+=std::to_string( (*it)->id())+" ";if (k==1)amp+=" > ";
}
if (virt && factory->highestVirt()>=p.size()){
VirtAmplitudes.push_back(amp);
}else{
BornAmplitudes.push_back(amp);
}
return true;
}
void MadGraphAmplitude::prepareAmplitudes(Ptr<MatchboxMEBase>::tcptr me) {
useMe();
if ( !calculateTreeAmplitudes() ) {
MatchboxAmplitude::prepareAmplitudes(me);
return;
}
if (colourindex.empty()) {
for (int i=0;i<100;i++){
colourindex.push_back(-2);
}
}
lastMatchboxXComb()->clearheljamp();
lastMatchboxXComb()->clearhelLNjamp();
initProcess(mePartonData());
MatchboxAmplitude::prepareAmplitudes(me);
}
Complex MadGraphAmplitude::evaluate(size_t i, const vector<int>& hel, Complex& largeN) {
//find the colourline:
int ii = -1;
int xx=lastMatchboxXComb()->externalId();
if (colourindex.size()<=i) {
colourindex.clear();
for (size_t l=0;l<=i+10;l++){
colourindex.push_back(-2);
}
}
if(colourindex[i]!=-2){
ii = colourindex[i];
if (ii==-1) {
largeN = Complex(0.0);
return Complex(0.0);
}
} else {
set<vector<size_t> > a = colourOrdering(i);
int ncol=-1;
MG_NCol(&xx,&ncol);
assert(ncol!=-1);
for( int it = 0; it < ncol; it++ ){
int n = 0;
for ( cPDVector::const_iterator nx = mePartonData().begin();
nx != mePartonData().end(); nx++ )
if ( (*nx)->coloured() ) n++;
set<vector<size_t> > tmpset;
vector<size_t> tmpvek;
for ( int it2 = 0; it2 < n; it2++ ) {
int ret=-2;
MG_Colour(&xx,&it,&it2,&ret);
assert(ret !=-2);
if (ret== -1)
break;
if ( ret == 0 ) {
n++;
tmpset.insert(tmpvek);
tmpvek.clear();
} else {
tmpvek.push_back(ret-1);
}
if( it2 == n-1 ) tmpset.insert(tmpvek);
}
bool found_all = true;
for ( set<vector<size_t> >::iterator it3 = a.begin(); it3 != a.end(); it3++ ) {
bool found_it3=false;
for ( set<vector<size_t> >::iterator it4 = tmpset.begin(); it4 != tmpset.end(); it4++ ) {
vector<size_t> it3tmp = gluonsFirst(*it3);
vector<size_t> it4tmp = (*it4);
if ( it3tmp.size() != it4tmp.size() ) continue;
if ( it3tmp == it4tmp ) found_it3 = true;
}
found_all = found_all && found_it3;
}
if ( found_all ) {
colourindex[i]=it;
ii=it;
}
}
}
if ( ii == -1 ){
colourindex[i]=ii;
largeN = Complex(0.0);
return Complex(0.0);
}
const map<vector<int>,vector < complex<double> > >& tmp = lastMatchboxXComb()->heljamp();
const map<vector<int>,vector < complex<double> > >& tmpLN = lastMatchboxXComb()->helLNjamp();
if( tmp.find(hel) != tmp.end()) {
largeN = tmpLN.find(hel)->second[ii];
return tmp.find(hel)->second[ii];;
}
double units = pow(sqrt(lastSHat())/GeV,int(hel.size())-4);
int heltmp[10];
for(size_t j=0;j<hel.size();j++){
int cross=crossingMap()[j];
if( (cross>1&&j<=1)||(cross<=1&&j>1)){
heltmp[cross]=-1*hel[j];}
else{heltmp[cross]=hel[j];}
}
vector<Lorentz5Momentum> reshuffled = meMomenta();
if ( !reshuffleMasses().empty() && reshuffled.size() > 3 ) {
const cPDVector& pdata = mePartonData();
const map<long,Energy>& masses = reshuffleMasses();
lastMatchboxXComb()->reshuffle(reshuffled,pdata,masses);
}
double momenta[50];
size_t j=0;
for (size_t i=0;i<mePartonData().size();i++){
momenta[j]=abs(reshuffled[i].e()/GeV)<1.e-13?0.:double(reshuffled[i].e()/GeV);
momenta[j+1]=abs(reshuffled[i].x()/GeV)<1.e-13?0.:double(reshuffled[i].x()/GeV);
momenta[j+2]=abs(reshuffled[i].y()/GeV)<1.e-13?0.:double(reshuffled[i].y()/GeV);
momenta[j+3]=abs(reshuffled[i].z()/GeV)<1.e-13?0.:double(reshuffled[i].z()/GeV);
if(momenta[j ] == 0. && momenta[j+1] == 0. &&
momenta[j+2] == 0. && momenta[j+3] == 0. )
return 0.;
j+=4;
}
MG_Calculate_wavefunctions_born(&xx, &momenta[0], &heltmp[0]);
int ncol=-1;
MG_NCol(&xx,&ncol);
Complex res;
Complex resLN;
for( int it = 0; it < ncol; it++ ){
double dd[2];
MG_Jamp(&xx,&it,&dd[0]);
Complex d(dd[0],dd[1]);
if(it==ii)res=d*units;
lastMatchboxXComb()->pushheljamp(hel,d*units);
double ddLN[2];
MG_LNJamp(&xx,&it,&ddLN[0]);
Complex dLN(ddLN[0],ddLN[1]);
if(it==ii)resLN=dLN*units;
lastMatchboxXComb()->pushhelLNjamp(hel,dLN*units);
}
largeN = resLN;
return res;
}
vector<unsigned int> MadGraphAmplitude::physicalHelicities(const vector<int>& hel) const {
vector<unsigned int> res(hel.size(),0);
for ( size_t j = 0; j < hel.size(); ++j ) {
int cross = crossingMap()[j];
int xhel = 0;
if ( (cross > 1 && j <= 1) || (cross <= 1 && j > 1) )
xhel = -1*hel[j];
else
xhel = hel[j];
if ( mePartonData()[cross]->iSpin() == PDT::Spin1Half )
res[cross] = (xhel == -1 ? 0 : 1);
else if ( mePartonData()[cross]->iSpin() == PDT::Spin1 )
res[cross] = (unsigned int)(xhel + 1);
else if ( mePartonData()[cross]->iSpin() == PDT::Spin0 )
res[cross] = 0;
else assert(false);
}
return res;
}
LorentzVector<Complex> MadGraphAmplitude::plusPolarization(const Lorentz5Momentum& p,
const Lorentz5Momentum& n,
int i) const {
int tmp=i;
double pg[4],ng[4],poltmp[8];
pg[0]=p.e()/GeV;pg[1]=p.x()/GeV;pg[2]=p.y()/GeV;pg[3]=p.z()/GeV;
ng[0]=n.e()/GeV;ng[1]=n.x()/GeV;ng[2]=n.y()/GeV;ng[3]=n.z()/GeV;
MG_vxxxxx(&pg[0],&ng[0],&tmp,&poltmp[0]);
complex<double> pol[6];
pol[0]=Complex(poltmp[0],poltmp[1]);
pol[1]=Complex(poltmp[2],poltmp[3]);
pol[2]=Complex(poltmp[4],poltmp[5]);
pol[3]=Complex(poltmp[6],poltmp[7]);
LorentzVector<Complex> polarization(pol[1],pol[2],pol[3],pol[0]);
return polarization;
}
bool equalsModulo(unsigned int i, const vector<int>& a, const vector<int>& b) {
assert(a.size()==b.size());
if ( a[i] == b[i] )
return false;
for ( unsigned int k = 0; k < a.size(); ++k ) {
if ( k == i )
continue;
if ( a[k] != b[k] )
return false;
}
return true;
}
vector<size_t> MadGraphAmplitude::gluonsFirst(vector<size_t> vec) {
vector<size_t> vecout;
for(vector<size_t>::iterator it= vec.begin();it!= vec.end();++it)
if ( mePartonData()[crossingMap()[*it]]->id()==21)
vecout.push_back(crossingMap()[*it]);
for(vector<size_t>::iterator it= vec.begin();it!= vec.end();++it)
if ( mePartonData()[crossingMap()[*it]]->id()!=21)
vecout.push_back(crossingMap()[*it]);
return vecout;
}
double MadGraphAmplitude::spinColourCorrelatedME2(pair<int,int> ij,
const SpinCorrelationTensor& c) const {
vector<Lorentz5Momentum> reshuffled = meMomenta();
if ( !reshuffleMasses().empty() && reshuffled.size() > 3 ) {
const cPDVector& pdata = mePartonData();
const map<long,Energy>& masses = reshuffleMasses();
lastMatchboxXComb()->reshuffle(reshuffled,pdata,masses);
}
Lorentz5Momentum p = reshuffled[ij.first];
Lorentz5Momentum n = reshuffled[ij.second];
LorentzVector<Complex> polarization = plusPolarization(p,n,ij.first<2?-1:1);
int iCrossed = -1;
for ( unsigned int k = 0; k < crossingMap().size(); ++k )
if ( crossingMap()[k] == ij.first ) {
iCrossed = k;
break;
}
assert(iCrossed!=-1);
if(ij.first>1) polarization =polarization.conjugate();
if(iCrossed<2) polarization =polarization.conjugate();
Complex pFactor = (polarization*c.momentum())/sqrt(abs(c.scale()));
double avg =
colourCorrelatedME2(ij)*(-c.diagonal()+ (c.scale() > ZERO ? 1. : -1.)*norm(pFactor));
Complex csCorr = 0.0;
if ( calculateColourSpinCorrelator(ij) ) {
set<const CVector*> done;
for ( AmplitudeConstIterator a = lastAmplitudes().begin();
a != lastAmplitudes().end(); ++a ) {
if ( done.find(&(a->second)) != done.end() )
continue;
AmplitudeConstIterator b = lastAmplitudes().begin();
while ( !equalsModulo(iCrossed,a->first,b->first) )
if ( ++b == lastAmplitudes().end() )
break;
if ( b == lastAmplitudes().end() || done.find(&(b->second)) != done.end() )
continue;
done.insert(&(a->second)); done.insert(&(b->second));
if ( a->first[iCrossed] == 1 )
swap(a,b);
csCorr -= colourBasis()->colourCorrelatedInterference(ij,mePartonData(),a->second,b->second);
}
lastColourSpinCorrelator(ij,csCorr);
} else {
csCorr = lastColourSpinCorrelator(ij);
}
double corr =
2.*real(csCorr*sqr(pFactor));
double Nc = generator()->standardModel()->Nc();
double cfac = 1.;
if ( mePartonData()[ij.first]->iColour() == PDT::Colour8 ) {
cfac = Nc;
} else if ( mePartonData()[ij.first]->iColour() == PDT::Colour3 ||
mePartonData()[ij.first]->iColour() == PDT::Colour3bar ) {
cfac = (sqr(Nc)-1.)/(2.*Nc);
} else assert(false);
return
( avg +(c.scale() > ZERO ? 1. : -1.)*corr/cfac);
}
void MadGraphAmplitude::prepareOneLoopAmplitudes(Ptr<MatchboxMEBase>::tcptr ){
assert(false);
}
double MadGraphAmplitude::oneLoopInterference() const {
if ( !calculateOneLoopInterference() )
return lastOneLoopInterference();
evaloneLoopInterference();
return lastOneLoopInterference();
}
void MadGraphAmplitude::evaloneLoopInterference() const {
double units = pow(lastSHat()/GeV2,int(mePartonData().size())-4);
vector<Lorentz5Momentum> reshuffled = meMomenta();
if ( !reshuffleMasses().empty() && reshuffled.size() > 3 ) {
const cPDVector& pdata = mePartonData();
const map<long,Energy>& masses = reshuffleMasses();
lastMatchboxXComb()->reshuffle(reshuffled,pdata,masses);
}
double virt[20];
double momenta[50];
size_t j=0;
for (size_t i=0;i<mePartonData().size();i++){
momenta[j]=abs(reshuffled[i].e()/GeV)<1.e-13?0.:double(reshuffled[i].e()/GeV);
momenta[j+1]=abs(reshuffled[i].x()/GeV)<1.e-13?0.:double(reshuffled[i].x()/GeV);
momenta[j+2]=abs(reshuffled[i].y()/GeV)<1.e-13?0.:double(reshuffled[i].y()/GeV);
momenta[j+3]=abs(reshuffled[i].z()/GeV)<1.e-13?0.:double(reshuffled[i].z()/GeV);
j+=4;
}
int xx=lastMatchboxXComb()->externalId();
MG_Calculate_wavefunctions_virt(&xx,&momenta[0],&virt[0]);
double ifact = 1.;
ifact = 1./4.;
if (lastMatchboxXComb()->matchboxME()->mePartonData()[0]->iColour() == PDT::Colour3 ||
lastMatchboxXComb()->matchboxME()->mePartonData()[0]->iColour() == PDT::Colour3bar )
ifact /= SM().Nc();
else if ( lastMatchboxXComb()->matchboxME()->mePartonData()[0]->iColour() == PDT::Colour8 )
ifact /= (SM().Nc()*SM().Nc()-1.);
if ( lastMatchboxXComb()->matchboxME()->mePartonData()[1]->iColour() == PDT::Colour3 ||
lastMatchboxXComb()->matchboxME()->mePartonData()[1]->iColour() == PDT::Colour3bar )
ifact /= SM().Nc();
else if ( mePartonData()[1]->iColour() == PDT::Colour8 )
ifact /= (SM().Nc()*SM().Nc()-1.);
ifact *= lastMatchboxXComb()->matchboxME()->finalStateSymmetry();
lastOneLoopInterference(virt[1]/ifact*units);
lastOneLoopPoles(pair<double, double>(virt[2]/ifact*units,virt[3]/ifact*units));
}
void MadGraphAmplitude::persistentOutput(PersistentOStream & os) const {
os << theOrderInGs << theOrderInGem << BornAmplitudes << VirtAmplitudes
<< colourindex<<crossing << theProcessPath << theMGmodel << bindir_
<< pkgdatadir_ << madgraphPrefix_;
}
void MadGraphAmplitude::persistentInput(PersistentIStream & is, int) {
is >> theOrderInGs >> theOrderInGem >> BornAmplitudes >> VirtAmplitudes
>> colourindex>>crossing >> theProcessPath >> theMGmodel >> bindir_
>> pkgdatadir_ >> madgraphPrefix_;
}
// *** 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<MadGraphAmplitude,MatchboxAmplitude>
describeHerwigMadGraphAmplitude("Herwig::MadGraphAmplitude", "HwMatchboxMadGraph.so");
void MadGraphAmplitude::Init() {
static ClassDocumentation<MadGraphAmplitude>
documentation("MadGraphAmplitude",
"Matrix elements have been calculated using MadGraph5 \\cite{Alwall:2011uj}",
"%\\cite{Alwall:2011uj}\n"
"\\bibitem{Alwall:2011uj}\n"
"J. Alwall et al.,\n"
"``MadGraph 5 : Going Beyond,''\n"
"arXiv:1106.0522 [hep-ph].\n"
"%%CITATION = ARXIV:1106.0522;%%");
static Parameter<MadGraphAmplitude,string> interfaceProcessPath
("ProcessPath",
"The Process Path.",
&MadGraphAmplitude::theProcessPath, "",false, false);
static Parameter<MadGraphAmplitude,string> interfaceModel
("Model",
"The MadGraph-Model.",
&MadGraphAmplitude::theMGmodel, "loop_sm",false, false);
static Switch<MadGraphAmplitude,bool> interfacekeepinputtopmass
("KeepInputTopMass",
"Switch On/Off formopt",
&MadGraphAmplitude::keepinputtopmass, false, false, false);
static SwitchOption interfacekeepinputtopmassTrue
(interfacekeepinputtopmass,
"On",
"On",
true);
static SwitchOption interfacekeepinputtopmassFalse
(interfacekeepinputtopmass,
"Off",
"Off",
false);
static Parameter<MadGraphAmplitude,string> interfaceBinDir
("BinDir",
"The location for the installed executable",
&MadGraphAmplitude::bindir_, string(HERWIG_BINDIR),
false, false);
static Parameter<MadGraphAmplitude,string> interfacePKGDATADIR
("DataDir",
"The location for the installed Herwig data files",
&MadGraphAmplitude::pkgdatadir_, string(HERWIG_PKGDATADIR),
false, false);
static Parameter<MadGraphAmplitude,string> interfaceMadgraphPrefix
("MadgraphPrefix",
"The prefix for the location of MadGraph",
&MadGraphAmplitude::madgraphPrefix_, string(MADGRAPH_PREFIX),
false, false);
}
diff --git a/MatrixElement/Matchbox/External/MadGraph/Makefile.am b/MatrixElement/Matchbox/External/MadGraph/Makefile.am
--- a/MatrixElement/Matchbox/External/MadGraph/Makefile.am
+++ b/MatrixElement/Matchbox/External/MadGraph/Makefile.am
@@ -1,28 +1,22 @@
-pkglib_LTLIBRARIES = HwMatchboxMadGraph.la
-HwMatchboxMadGraph_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 3:0:0
+EXTRA_DIST = \
+MadGraphAmplitude.h \
+MadGraphAmplitude.cc \
+mg2herwig.py
-HwMatchboxMadGraph_la_SOURCES = \
-MadGraphAmplitude.h MadGraphAmplitude.cc
madgraphdir = ${pkgdatadir}/MadGraphInterface
INPUTFILES = \
InterfaceMadGraph.f.in \
param_card.dat.in \
param_card_heft.dat.in
dist_madgraph_DATA = $(INPUTFILES)
-HwMatchboxMadGraph_la_CPPFLAGS = $(AM_CPPFLAGS) \
--DHERWIG_BINDIR="\"$(bindir)\"" \
--DHERWIG_INCLUDEDIR="\"$(includedir)\"" \
--DHERWIG_PKGDATADIR="\"$(pkgdatadir)\"" \
--DMADGRAPH_PREFIX="\"$(MADGRAPHPREFIX)\""
-EXTRA_DIST = mg2herwig.py
install-exec-local:
$(install_sh_SCRIPT) $(builddir)/mg2herwig.py $(DESTDIR)$(bindir)/mg2herwig
uninstall-local:
rm -f $(DESTDIR)$(bindir)/mg2herwig
diff --git a/MatrixElement/Matchbox/External/MadGraph/mg2herwig.py.in b/MatrixElement/Matchbox/External/MadGraph/mg2herwig.py.in
--- a/MatrixElement/Matchbox/External/MadGraph/mg2herwig.py.in
+++ b/MatrixElement/Matchbox/External/MadGraph/mg2herwig.py.in
@@ -1,392 +1,395 @@
#! /usr/bin/env python
import os,sys,glob,errno,shutil,time,fnmatch #argparse
from optparse import OptionParser
# helper to replace all sourceText in fileName with replaceText
def replacetext(fileName, sourceText, replaceText):
file = open(fileName, "r")
text = file.read()
file.close()
file = open(fileName, "w")
file.write(text.replace(sourceText, replaceText))
file.close()
# helper to build recursivly path
def mkdir_p(path):
try:
os.makedirs(path)
except OSError as exc: # Python >2.5
if exc.errno == errno.EEXIST and os.path.isdir(path):
pass
else: raise
# helper to find all files of with name in path
def find(name, path):
for root, dirs, files in os.walk(path):
if name in files:
return os.path.join(root, name)
# helper to find all file paths which contain file names matching filepattern
def finddirs(filepattern, path):
founddirs = []
for root, dirs, files in os.walk(path):
if fnmatch.filter(files, filepattern):
founddirs.append(root)
return founddirs
# fill the proc.dat file from BornAmplitudes.dat and VirtAmplitudes.dat.
def fillprocs(model,oras,orew):
bornlist=[]
virtlist=[]
fileproc=open("proc.dat","w")
fileproc.write("set fortran_compiler @FC@ --no_save\n")
fileproc.write("import model "+model+"\n")
borns="BornAmplitudes.dat"
virts="VirtAmplitudes.dat"
first=True
procnr=0
virtlines=""
bornlines=""
minlegs=100
legs=0
for i in [borns, virts]:
file = open(i, "r")
for line in file:
if (len(line.split(" "))<minlegs):
minlegs=len(line.split(" "))
for it in line.split(" "):
if it.replace("-","").isdigit():
legs+=1
file.close()
#conversion for heft model to go from (2QCD+1QED)->1HIG for each FS HIGGS.
HIG=0
if (model=="heft"):
HIG=(int(oras)+int(orew)-legs+2)/2
if (int(oras)+int(orew)-legs+2)%2!=0:
print "Warning: No possible coupling power:(int(oras)+int(orew)-legs+2)%2!=0 "
exit()
return
file = open(borns, "r")
for line in file:
#this assumes extra QCD emmissions
addalphas=len(line.split(" "))-minlegs
linetmp=line.rstrip()
procnr+=1
bornlist+=[str(procnr)]
if first:
if HIG ==0 :
bornlines+="generate "+linetmp+" QCD="+str(int(oras)+addalphas)+" QED="+str(orew)+" @"+str(procnr)+"\n"
else:
bornlines+="generate "+linetmp+" HIG="+str(HIG)+" QCD="+str(int(oras)+addalphas-2*HIG)+" QED="+str(int(orew)-HIG)+" @"+str(procnr)+"\n"
first=False
else:
if HIG ==0 :
bornlines+="add process "+linetmp+" QCD="+str(int(oras)+addalphas)+" QED="+str(orew)+" @"+str(procnr)+"\n"
else:
bornlines+="add process "+linetmp+" HIG="+str(HIG)+" QCD="+str(int(oras)+addalphas-2*HIG)+" QED="+str(int(orew)-HIG)+" @"+str(procnr)+"\n"
file.close()
first=True
file = open(virts, "r")
for line in file:
addalphas=len(line.split(" "))-minlegs
linetmp=line.rstrip()+" QCD="+str(int(oras)+addalphas)+" QED="+str(int(orew))+" [ virt=QCD ]"
procnr+=1
virtlist+=[str(procnr)]
if first:
virtlines+="generate "+linetmp+" @"+str(procnr)+"\n"
first=False
else:
virtlines+="add process "+linetmp+" @"+str(procnr)+"\n"
file.close()
fileproc.write(bornlines)
if virtlines!="" and bornlines!="":
fileproc.write("output matchbox MG5 --postpone_model\n")
fileproc.write(virtlines)
fileproc.write("output matchbox MG5 -f\n")
fileproc.close()
return bornlist,virtlist
def build_matchbox_tmp(pwd,buildpath,absolute_links):
cwd=os.getcwd()
os.chdir(pwd)
mkdir_p(pwd+"/Herwig-scratch/MG_tmp/")
if not buildpath.startswith("/"):
buildpath=pwd+"/"+buildpath.lstrip("./")
if not buildpath.endswith("/"):
buildpath=buildpath + "/"
resources=glob.glob(buildpath +"MG5/SubProcesses/MadLoop5_resources/*")
resources+=glob.glob(buildpath +"MG5/Cards/*")
resources+=glob.glob(buildpath +"MG5/Cards/SubProcesses/*")
for i in resources:
if not os.path.isfile( pwd+"/Herwig-scratch/MG_tmp/"+os.path.basename(i)) \
and not os.path.islink( pwd+"/Herwig-scratch/MG_tmp/"+os.path.basename(i)):
if not absolute_links:
source=os.path.dirname(i)
dest=pwd+"/Herwig-scratch/MG_tmp/"
os.chdir(dest)
os.symlink(os.path.relpath(source,dest)+"/"+os.path.basename(i),"./" + os.path.basename(i))
else:
os.symlink(i, pwd+"/Herwig-scratch/MG_tmp/"+os.path.basename(i))
os.chdir(cwd)
parser = OptionParser()
parser.add_option("-a", "--buildpath", dest="buildpath",help="Do not use this script. Only for Herwig internal use. ")
parser.add_option("-b", "--build", action="store_true", dest="build", default=True,help="Do not use this script. Only for Herwig internal use.")
parser.add_option("-c", "--madgraph", dest="madgraph",help="Do not use this script. Only for Herwig internal use.")
parser.add_option("-d", "--runpath", dest="runpath",help="Do not use this script. Only for Herwig internal use.")
parser.add_option("-e", "--model", dest="model",help="Do not use this script. Only for Herwig internal use.")
parser.add_option("-f", "--orderas", dest="orderas",help="Do not use this script. Only for Herwig internal use.")
parser.add_option("-g", "--orderew", dest="orderew",help="Do not use this script. Only for Herwig internal use.")
parser.add_option("-i", "--datadir",dest="datadir",help="Do not use this script. Only for Herwig internal use.")
parser.add_option("-I", "--includedir",dest="includedir",help="Do not use this script. Only for Herwig internal use.")
parser.add_option("-l", "--absolute-links",action="store_true", dest="absolute_links", default=False,\
help="Do not use this script. Only for Herwig internal use.")
(options, args) = parser.parse_args()
#parser = argparse.ArgumentParser()
#parser.add_argument('--buildpath', help='installpath')
#parser.add_argument('--build', help='build', action="store_true")
#parser.add_argument('--madgraph', help='madgraph_installpath')
#parser.add_argument('--runpath', help='runpath')
#parser.add_argument('--model', help='model')
#parser.add_argument('--orderas', help='orderas')
#parser.add_argument('--orderew', help='orderew')
#parser.add_argument('--datadir', help='datadir')
#args = parser.parse_args()
pwd=os.getcwd()
param_card=""
mkdir_p(pwd+"/Herwig-scratch/MG_tmp/")
if options.model=="loop_sm" or options.model=="heft":
if options.model=="loop_sm":
param_card="param_card.dat"
else:
param_card="param_card_"+options.model+".dat"
file = open("%s/MadGraphInterface/%s.in" % (options.datadir,param_card) , "r")
paramcard = file.read()
file.close()
file = open(options.runpath+"/"+param_card, "w")
params=open(options.runpath+"/MG-Parameter.dat", "r")
for line in params:
a=line.split()
paramcard=paramcard.replace(a[0],a[1])
params.close()
file.write(paramcard)
file.close()
elif options.model.startswith("/"):
os.system("python %s/write_param_card.py " % options.model)
else:
print "---------------------------------------------------------------"
print "---------------------------------------------------------------"
print "Warning: The model set for the MadGraph Interface "
print " needs a parameter setting by hand."
print " Please fill the param_card_"+options.model+".dat"
print " with your favourite assumptions."
print " And make sure Herwig uses the same parameters."
print "---------------------------------------------------------------"
print "---------------------------------------------------------------"
if os.path.isfile(options.buildpath +"/MG5/Cards/param_card.dat") and not os.path.isfile(options.runpath+"/"+"param_card_"+options.model+".dat"):
shutil.copyfile(options.buildpath +"/MG5/Cards/param_card.dat", options.runpath+"/"+"param_card_"+options.model+".dat")
time.sleep(1)
if not os.path.isdir(options.buildpath):
print "The MadGraph Install path was not existend. It has been created for you."
print "Just start Herwig read again.."
mkdir_p(options.buildpath)
exit()
os.chdir(options.buildpath)
if os.path.isfile("InterfaceMadGraph.so"):
build_matchbox_tmp(pwd,options.buildpath,options.absolute_links)
exit()
Bornlist,Virtlist=fillprocs(options.model,options.orderas,options.orderew)
if not options.madgraph and not os.path.isfile("InterfaceMadGraph.so"):
print "*** warning *** MadGraph build failed, check logfile for details"
print "Known issue: If this is your first NLO calculation with pure Madgraph Amplitudes"
print " the CutTools compilation can result in a non usable configuration."
print " Please open $HERWIG_ENV/opt/madgraph/vendor/CutTools/makefile"
print " and add a \\ after FC=gfortran... in the ARGS variable."
print " Then run make clean && make in the CutTools folder. "
exit()
os.system("python "+options.madgraph+"/mg5_aMC proc.dat")
routines=[["","BORN(momenta,hel)"],
["","SLOOPMATRIX(momenta,virt)"],
["","GET_JAMP(color,Jamp)"],
["","GET_LNJAMP(color,Jamp)"],
["","GET_NCOL(color)"],
["","GET_NCOLOR(i,j,color)"]]
for routine in routines:
for i in Bornlist + list(set(Virtlist) - set(Bornlist)):
if routine[1]=="Virt(amp)" or routine[1]=="SLOOPMATRIX(momenta,virt)" and i not in Virtlist:
continue
if routine[0]=="":
routine[0]+=" SELECT CASE (proc) \n"
routine[0]+=" CASE("+i+") \n CALL "
routine[0]+= "MG5_"+i+"_"+routine[1]+"\n"
else:
routine[0]+=" CASE("+i+") \n"\
" CALL "
routine[0]+= "MG5_"+i+"_"+routine[1]+"\n"
if routine[0]!="":
routine[0]+=" CASE DEFAULT\n"
routine[0]+=" WRITE(*,*) '##W02A WARNING No id found '\n"
routine[0]+=" END SELECT \n"
shutil.copyfile("%s/MadGraphInterface/InterfaceMadGraph.f.in" % options.datadir, "InterfaceMadGraph.f")
replacetext("InterfaceMadGraph.f","MG_CalculateBORNtxt",routines[0][0])
replacetext("InterfaceMadGraph.f","MG_CalculateVIRTtxt",routines[1][0])
replacetext("InterfaceMadGraph.f","MG_Jamptxt", routines[2][0])
replacetext("InterfaceMadGraph.f","MG_LNJamptxt", routines[3][0])
replacetext("InterfaceMadGraph.f","MG_NColtxt", routines[4][0])
replacetext("InterfaceMadGraph.f","MG_ColourMattxt",routines[5][0])
MG_vxxxxxtxt=""
if routines[1][0]!="":
MG_vxxxxxtxt=""" subroutine MG_vxxxxx(p, n,inc,VC)
$ bind(c, name='MG_vxxxxx')
IMPLICIT NONE
double precision p(0:3)
double precision n(0:3)
INTEGER inc
double precision VC(0:7)
double complex VCtmp(8)
call vxxxxx(p, 0d0,1,inc ,VCtmp)
VC(0)= real(VCtmp(5))
VC(1)=aimag(VCtmp(5))
VC(2)= real(VCtmp(6))
VC(3)=aimag(VCtmp(6))
VC(4)= real(VCtmp(7))
VC(5)=aimag(VCtmp(7))
VC(6)= real(VCtmp(8))
VC(7)=aimag(VCtmp(8))
END"""
else:
MG_vxxxxxtxt=""" subroutine MG_vxxxxx(p, n,inc,VC)
$ bind(c, name='MG_vxxxxx')
IMPLICIT NONE
double precision p(0:3)
double precision n(0:3)
INTEGER inc
double precision VC(0:7)
double complex VCtmp(6)
call vxxxxx(p, 0d0,1,inc ,VCtmp)
VC(0)= real(VCtmp(3))
VC(1)=aimag(VCtmp(3))
VC(2)= real(VCtmp(4))
VC(3)=aimag(VCtmp(4))
VC(4)= real(VCtmp(5))
VC(5)=aimag(VCtmp(5))
VC(6)= real(VCtmp(6))
VC(7)=aimag(VCtmp(6))
END"""
replacetext("InterfaceMadGraph.f","MG_vxxxxxtxt",MG_vxxxxxtxt)
make=" "
fortanfiles=glob.glob('*/*/*.f')+glob.glob('*/*/*/*.f')
for i in fortanfiles:
- if "check_sa" not in i:
+ if "check_sa" not in i and "f2py_wrapper" not in i:
if not os.path.islink(i):
make += " "+i+"\\\n "
incfiles=glob.glob('*/*/*.inc')+glob.glob('*/*/*/*.inc')
coefdir=""
for i in incfiles:
if "nexternal.inc" in i:
coefdir+=" -I"+i.replace("nexternal.inc"," ")
file=open("makefile","w")
file.write("include MG5/Source/make_opts ")
if Virtlist!=[]:
file.write("\nLIBDIR = MG5/lib\nLINKLIBS = -L$(LIBDIR) -lcts -liregi -L$(LIBDIR)/golem95_lib -lgolem")
file.write("\nLIBS = $(LIBDIR)libcts.$(libext) $(LIBDIR)libgolem.$(libext) $(LIBDIR)libiregi.$(libext)")
file.write("\nPROCESS= InterfaceMadGraph.f "+make+"\n\nall: \n\t @FC@ @FFLAGS@ -w -fbounds-check -ffixed-line-length-132 -fPIC -fno-f2c -shared -s -o InterfaceMadGraph.so -IMG5/SubProcesses/" )
if Virtlist!=[]:
file.write(" -IMG5/lib/golem95_include ")
# Find all .mod files also in /usr/include if golem was build there.
# There can be an error message in the MadGraph output to add the golem include path to the makefiles.
# Usually MadGraph finds the path if its Golem was build in an separate dictionary.
# Our bootstrap script installs golem with gosam beside boost. Here MadGraph creates a link (->errormessage).
# If we can find the modfiles easily the user doesn't need to change the makefiles.
moddirs=finddirs('*.mod',options.includedir)
for moddir in moddirs:
file.write(" -I%s " % moddir)
if os.path.isdir("/usr/include"):
moddirs=finddirs('*.mod',"/usr/include")
for moddir in moddirs:
file.write(" -I%s " % moddir)
if coefdir != "":
file.write(coefdir)
file.write(" $(PROCESS) $(LINKLIBS) ")
file.close()
os.chdir(pwd)
os.chdir(options.buildpath)
replacetext("MG5/Source/MODEL/lha_read.f", "ident_card.dat","Herwig-scratch/MG_tmp/ident_card.dat")
replacetext("MG5/Source/MODEL/lha_read.f", "param.log","Herwig-scratch/MG_tmp/param.log")
if Virtlist!=[]:
replacetext("MG5/SubProcesses/MadLoopCommons.f", "PREFIX='./'","PREFIX='./Herwig-scratch/MG_tmp/'")
os.system("make")
-
+if not os.path.isfile("InterfaceMadGraph.so"):
+ print "Second trial to make MadGraph Interface. "
+ print "Needed if new .mod files are produced by make."
+ os.system("make")
build_matchbox_tmp(pwd,options.buildpath,options.absolute_links)
diff --git a/MatrixElement/Matchbox/External/Makefile.am b/MatrixElement/Matchbox/External/Makefile.am
--- a/MatrixElement/Matchbox/External/Makefile.am
+++ b/MatrixElement/Matchbox/External/Makefile.am
@@ -1,22 +1,95 @@
-SUBDIRS = \
-BLHAGeneric
+SUBDIRS = BLHAGeneric VBFNLO NJet GoSam OpenLoops MadGraph
+
+
+pkglib_LTLIBRARIES =
+
+##############
+
+if HAVE_GOSAM
+pkglib_LTLIBRARIES += HwMatchboxGoSam.la
+endif
+
+HwMatchboxGoSam_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 13:0:0
+
+HwMatchboxGoSam_la_CPPFLAGS = $(AM_CPPFLAGS) \
+-DHERWIG_BINDIR="\"$(bindir)\"" \
+-DHERWIG_PKGDATADIR="\"$(pkgdatadir)\"" \
+-DGOSAM_PREFIX="\"$(GOSAMPREFIX)\""
+
+HwMatchboxGoSam_la_SOURCES = \
+GoSam/GoSamAmplitude.cc
+
+
+###############
if HAVE_VBFNLO
-SUBDIRS += VBFNLO
+pkglib_LTLIBRARIES += HwMatchboxVBFNLO.la
endif
-if HAVE_NJET
-SUBDIRS += NJet
+HwMatchboxVBFNLO_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 2:1:0
+HwMatchboxVBFNLO_la_CPPFLAGS = $(AM_CPPFLAGS)
+HwMatchboxVBFNLO_la_CPPFLAGS += -I$(VBFNLOINCLUDE)
+HwMatchboxVBFNLO_la_CPPFLAGS += -DVBFNLOLIB=$(VBFNLOLIB)
+
+HwMatchboxVBFNLO_la_SOURCES = \
+VBFNLO/VBFNLOAmplitude.cc \
+VBFNLO/VBFNLOPhasespace.cc
+
+
+###############
+
+if HAVE_OPENLOOPS
+pkglib_LTLIBRARIES += HwMatchboxOpenLoops.la
endif
-if HAVE_GOSAM
-SUBDIRS += GoSam
+HwMatchboxOpenLoops_la_SOURCES = \
+OpenLoops/OpenLoopsAmplitude.cc
+
+HwMatchboxOpenLoops_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 12:0:0
+
+HwMatchboxOpenLoops_la_CPPFLAGS = $(AM_CPPFLAGS) \
+-DOPENLOOPSLIBS="\"$(OPENLOOPSLIBS)\"" \
+-DOPENLOOPSPREFIX="\"$(OPENLOOPSPREFIX)\""
+
+##############
+
+
+if HAVE_NJET
+pkglib_LTLIBRARIES += HwMatchboxNJet.la
endif
-if HAVE_OPENLOOPS
-SUBDIRS += OpenLoops
+HwMatchboxNJet_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 12:0:0
+
+HwMatchboxNJet_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(NJETINCLUDEPATH) \
+-DNJET_PREFIX="\"$(NJETPREFIX)\"" \
+-DNJET_LIBS="\"$(NJETLIBPATH)\""
+
+HwMatchboxNJet_la_SOURCES = \
+NJet/NJetsAmplitude.cc
+
+
+
+##############
+
+if HAVE_MADGRAPH
+pkglib_LTLIBRARIES += HwMatchboxMadGraph.la
endif
-if HAVE_MADGRAPH
-SUBDIRS += MadGraph
-endif
+HwMatchboxMadGraph_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 3:0:0
+
+HwMatchboxMadGraph_la_SOURCES = \
+MadGraph/MadGraphAmplitude.cc
+
+HwMatchboxMadGraph_la_CPPFLAGS = $(AM_CPPFLAGS) \
+-DHERWIG_BINDIR="\"$(bindir)\"" \
+-DHERWIG_INCLUDEDIR="\"$(includedir)\"" \
+-DHERWIG_PKGDATADIR="\"$(pkgdatadir)\"" \
+-DMADGRAPH_PREFIX="\"$(MADGRAPHPREFIX)\""
+
+
+
+
+
+
+
diff --git a/MatrixElement/Matchbox/External/NJet/Makefile.am b/MatrixElement/Matchbox/External/NJet/Makefile.am
--- a/MatrixElement/Matchbox/External/NJet/Makefile.am
+++ b/MatrixElement/Matchbox/External/NJet/Makefile.am
@@ -1,9 +1,2 @@
-pkglib_LTLIBRARIES = HwMatchboxNJet.la
-HwMatchboxNJet_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 12:0:0
+EXTRA_DIST = NJetsAmplitude.h NJetsAmplitude.cc
-HwMatchboxNJet_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(NJETINCLUDEPATH) \
--DNJET_PREFIX="\"$(NJETPREFIX)\"" \
--DNJET_LIBS="\"$(NJETLIBPATH)\""
-
-HwMatchboxNJet_la_SOURCES = \
-NJetsAmplitude.h NJetsAmplitude.cc
diff --git a/MatrixElement/Matchbox/External/OpenLoops/Makefile.am b/MatrixElement/Matchbox/External/OpenLoops/Makefile.am
--- a/MatrixElement/Matchbox/External/OpenLoops/Makefile.am
+++ b/MatrixElement/Matchbox/External/OpenLoops/Makefile.am
@@ -1,8 +1,3 @@
-pkglib_LTLIBRARIES = HwMatchboxOpenLoops.la
-HwMatchboxOpenLoops_la_SOURCES = \
-OpenLoopsAmplitude.h OpenLoopsAmplitude.cc
-HwMatchboxOpenLoops_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 12:0:0
+EXTRA_DIST = OpenLoopsAmplitude.h OpenLoopsAmplitude.cc
-HwMatchboxOpenLoops_la_CPPFLAGS = $(AM_CPPFLAGS) \
--DOPENLOOPSLIBS="\"$(OPENLOOPSLIBS)\"" \
--DOPENLOOPSPREFIX="\"$(OPENLOOPSPREFIX)\""
+
diff --git a/MatrixElement/Matchbox/External/VBFNLO/Makefile.am b/MatrixElement/Matchbox/External/VBFNLO/Makefile.am
--- a/MatrixElement/Matchbox/External/VBFNLO/Makefile.am
+++ b/MatrixElement/Matchbox/External/VBFNLO/Makefile.am
@@ -1,16 +1,5 @@
-pkglib_LTLIBRARIES = HwMatchboxVBFNLO.la
-
-HwMatchboxVBFNLO_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 2:1:0
-
-HwMatchboxVBFNLO_la_CPPFLAGS = $(AM_CPPFLAGS)
-HwMatchboxVBFNLO_la_CPPFLAGS += -I$(VBFNLOINCLUDE)
-HwMatchboxVBFNLO_la_CPPFLAGS += -DVBFNLOLIB=$(VBFNLOLIB)
-
-#HwMatchboxVBFNLO_la_LIBADD = \
-#-L$(VBFNLOLIBS) \
-#-lVBFNLO -lVBFNLOAmplitudes -lVBFNLOUtilities -lVBFNLOLoops \
-#-lHELAS -lVBFNLOPDFsets -lVBFNLOPhasespace -lVBFspecific -lgfortran
-
-HwMatchboxVBFNLO_la_SOURCES = \
-VBFNLOAmplitude.h VBFNLOAmplitude.cc \
-VBFNLOPhasespace.h VBFNLOPhasespace.cc
+EXTRA_DIST = \
+VBFNLOAmplitude.h \
+VBFNLOAmplitude.cc \
+VBFNLOPhasespace.h \
+VBFNLOPhasespace.cc
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,2226 +1,2226 @@
// -*- 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" + ap->first->name() + 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);
if ( virtualsAreDRbar )
(**virt).useDRbar();
if ( virtualsAreDR )
(**virt).useDR();
else
(**virt).useCDR();
if ( virtualsAreCS )
(**virt).useCS();
if ( virtualsAreBDK )
(**virt).useBDK();
if ( virtualsAreExpanded )
(**virt).useExpanded();
}
for ( vector<Ptr<MatchboxInsertionOperator>::ptr>::const_iterator virt
= DipoleRepository::insertionPKOperators(dipoleSet()).begin();
virt != DipoleRepository::insertionPKOperators(dipoleSet()).end(); ++virt ) {
(**virt).factory(this);
if ( virtualsAreDRbar )
(**virt).useDRbar();
if ( virtualsAreDR )
(**virt).useDR();
else
(**virt).useCDR();
if ( virtualsAreCS )
(**virt).useCS();
if ( virtualsAreBDK )
(**virt).useBDK();
if ( virtualsAreExpanded )
(**virt).useExpanded();
}
}
}
// 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/Phasespace/Makefile.am b/MatrixElement/Matchbox/Phasespace/Makefile.am
--- a/MatrixElement/Matchbox/Phasespace/Makefile.am
+++ b/MatrixElement/Matchbox/Phasespace/Makefile.am
@@ -1,56 +1,68 @@
noinst_LTLIBRARIES = libHwMatchboxPhasespace.la
-libHwMatchboxPhasespace_la_SOURCES = \
-FFLightInvertedTildeKinematics.cc \
+libHwMatchboxPhasespace_la_SOURCES = $(ALL_H_FILES) Phasespace__all.cc
+
+BUILT_SOURCES = Phasespace__all.cc
+DISTCLEANFILES = Phasespace__all.cc
+
+Phasespace__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_CC_FILES)
+
+ALL_H_FILES = \
FFLightInvertedTildeKinematics.h \
-FFLightTildeKinematics.cc \
FFLightTildeKinematics.h \
-FFMassiveInvertedTildeKinematics.cc \
FFMassiveInvertedTildeKinematics.h \
-FFMassiveTildeKinematics.cc \
FFMassiveTildeKinematics.h \
-FILightInvertedTildeKinematics.cc \
FILightInvertedTildeKinematics.h \
-FILightTildeKinematics.cc \
FILightTildeKinematics.h \
-FIMassiveInvertedTildeKinematics.cc \
FIMassiveInvertedTildeKinematics.h \
-FIMassiveTildeKinematics.cc \
FIMassiveTildeKinematics.h \
-IFLightInvertedTildeKinematics.cc \
IFLightInvertedTildeKinematics.h \
-IFLightTildeKinematics.cc \
IFLightTildeKinematics.h \
-IFMassiveInvertedTildeKinematics.cc \
IFMassiveInvertedTildeKinematics.h \
-IFMassiveTildeKinematics.cc \
IFMassiveTildeKinematics.h \
-IILightInvertedTildeKinematics.cc \
IILightInvertedTildeKinematics.h \
-IILightTildeKinematics.cc \
IILightTildeKinematics.h \
-InvertedTildeKinematics.cc \
InvertedTildeKinematics.fh \
InvertedTildeKinematics.h \
-MatchboxPhasespace.cc \
MatchboxPhasespace.h \
-MatchboxRambo.cc \
MatchboxRambo.h \
-PhasespaceHelpers.cc \
PhasespaceHelpers.h \
RandomHelpers.h \
-TildeKinematics.cc \
TildeKinematics.fh \
TildeKinematics.h \
-TreePhasespace.cc \
TreePhasespace.h \
-TreePhasespaceChannels.cc \
TreePhasespaceChannels.h \
MatchboxReference.h \
+FlatInvertiblePhasespace.h \
+FlatInvertibleLabframePhasespace.h \
+PhasespaceCouplings.h
+
+ALL_CC_FILES = \
+FFLightInvertedTildeKinematics.cc \
+FFLightTildeKinematics.cc \
+FFMassiveInvertedTildeKinematics.cc \
+FFMassiveTildeKinematics.cc \
+FILightInvertedTildeKinematics.cc \
+FILightTildeKinematics.cc \
+FIMassiveInvertedTildeKinematics.cc \
+FIMassiveTildeKinematics.cc \
+IFLightInvertedTildeKinematics.cc \
+IFLightTildeKinematics.cc \
+IFMassiveInvertedTildeKinematics.cc \
+IFMassiveTildeKinematics.cc \
+IILightInvertedTildeKinematics.cc \
+IILightTildeKinematics.cc \
+InvertedTildeKinematics.cc \
+MatchboxPhasespace.cc \
+MatchboxRambo.cc \
+PhasespaceHelpers.cc \
+TildeKinematics.cc \
+TreePhasespace.cc \
+TreePhasespaceChannels.cc \
MatchboxReference.cc \
-FlatInvertiblePhasespace.h \
FlatInvertiblePhasespace.cc \
-FlatInvertibleLabframePhasespace.h \
FlatInvertibleLabframePhasespace.cc \
-PhasespaceCouplings.h \
PhasespaceCouplings.cc
diff --git a/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.cc b/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.cc
--- a/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.cc
+++ b/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.cc
@@ -1,557 +1,557 @@
// -*- C++ -*-
//
// MatchboxPhasespace.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 MatchboxPhasespace class.
//
#include "MatchboxPhasespace.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Command.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "Herwig/MatrixElement/Matchbox/Utility/ProcessData.h"
#include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h"
using namespace Herwig;
MatchboxPhasespace::MatchboxPhasespace()
: singularCutoff(10*GeV), theUseMassGenerators(false),
theLoopParticleIdMin(200001), theLoopParticleIdMax(200100) {}
MatchboxPhasespace::~MatchboxPhasespace() {}
void MatchboxPhasespace::cloneDependencies(const std::string&) {}
Ptr<MatchboxFactory>::tcptr MatchboxPhasespace::factory() const {
return lastMatchboxXComb()->factory();
}
Ptr<ProcessData>::tptr MatchboxPhasespace::processData() const {
return factory()->processData();
}
double MatchboxPhasespace::generateKinematics(const double* r,
vector<Lorentz5Momentum>& momenta) {
cPDVector::const_iterator pd = mePartonData().begin() + 2;
vector<Lorentz5Momentum>::iterator p = momenta.begin() + 2;
double massJacobian = 1.;
Energy summ = ZERO;
if ( useMassGenerators() ) {
Energy gmass = ZERO;
tGenericMassGeneratorPtr mgen;
Energy maxMass =
(!haveX1X2() && momenta.size() > 3) ?
sqrt(lastSHat()) : sqrt(lastS());
for ( ; pd != mePartonData().end(); ++pd, ++p ) {
mgen = processData()->massGenerator(*pd);
if ( mgen && !isInvertible() ) {
Energy massMax = min((**pd).massMax(),maxMass);
Energy massMin = (**pd).massMin();
if ( massMin > massMax )
return 0.0;
gmass = mgen->mass(massJacobian,**pd,massMin,massMax,r[0]);
++r;
} else if ( (**pd).hardProcessWidth() != ZERO ) {
Energy massMax = min((**pd).massMax(),maxMass);
Energy massMin = (**pd).massMin();
if ( massMin > massMax )
return 0.0;
// use a standard Breit Wigner here which we can invert
// see invertKinematics as well
double bwILow =
atan((sqr(massMin)-sqr((**pd).hardProcessMass()))/((**pd).hardProcessMass() * (**pd).hardProcessWidth()));
double bwIUp =
atan((sqr(massMax)-sqr((**pd).hardProcessMass()))/((**pd).hardProcessMass() * (**pd).hardProcessWidth()));
gmass = sqrt(sqr((**pd).hardProcessMass()) +
(**pd).hardProcessMass()*(**pd).hardProcessWidth()*tan(bwILow+r[0]*(bwIUp-bwILow)));
++r;
} else {
gmass = (**pd).hardProcessMass();
}
maxMass -= gmass;
p->setMass(gmass);
summ += gmass;
}
} else {
for ( ; pd != mePartonData().end(); ++pd, ++p ) {
summ += (**pd).hardProcessMass();
p->setMass((**pd).hardProcessMass());
}
}
if ( momenta.size() > 3 && !haveX1X2() ) {
if ( summ > (momenta[0]+momenta[1]).m() )
return 0.0;
}
double weight = momenta.size() > 3 ?
generateTwoToNKinematics(r,momenta) :
generateTwoToOneKinematics(r,momenta);
return weight*massJacobian;
}
double MatchboxPhasespace::generateTwoToOneKinematics(const double* r,
vector<Lorentz5Momentum>& momenta) {
double tau = momenta[2].mass2()/lastXCombPtr()->lastS();
double ltau = log(tau)/2.;
double y = ltau - 2.*r[0]*ltau;
double x1 = sqrt(tau)*exp(y);
double x2 = sqrt(tau)*exp(-y);
ThreeVector<Energy> p1 =
x1*(lastXCombPtr()->lastParticles().first->momentum().vect());
ThreeVector<Energy> p2 =
x2*(lastXCombPtr()->lastParticles().second->momentum().vect());
ThreeVector<Energy> q = p1 + p2;
momenta[0] = Lorentz5Momentum(momenta[0].mass(),p1);
momenta[1] = Lorentz5Momentum(momenta[1].mass(),p2);
momenta[2] = Lorentz5Momentum(momenta[2].mass(),q);
lastXCombPtr()->lastX1X2(make_pair(x1,x2));
lastXCombPtr()->lastSHat((momenta[0]+momenta[1]).m2());
fillDiagramWeights();
return -4.*Constants::pi*ltau;
}
double MatchboxPhasespace::invertKinematics(const vector<Lorentz5Momentum>& momenta,
double* r) const {
if ( useMassGenerators() ) {
Energy gmass = ZERO;
Energy maxMass =
(!haveX1X2() && momenta.size() > 3) ?
sqrt((momenta[0]+momenta[1]).m2()) : sqrt(lastS());
cPDVector::const_iterator pd = mePartonData().begin() + 2;
vector<Lorentz5Momentum>::const_iterator p = momenta.begin() + 2;
for ( ; pd != mePartonData().end(); ++pd, ++p ) {
if ( (**pd).hardProcessWidth() != ZERO ) {
Energy massMax = min((**pd).massMax(),maxMass);
Energy massMin = (**pd).massMin();
if ( massMin > massMax )
return 0.0;
double bwILow =
atan((sqr(massMin)-sqr((**pd).hardProcessMass()))/((**pd).hardProcessMass() * (**pd).hardProcessWidth()));
double bwIUp =
atan((sqr(massMax)-sqr((**pd).hardProcessMass()))/((**pd).hardProcessMass() * (**pd).hardProcessWidth()));
gmass = p->mass();
double bw =
atan((sqr(gmass)-sqr((**pd).hardProcessMass()))/((**pd).hardProcessMass() * (**pd).hardProcessWidth()));
r[0] = (bw-bwILow)/(bwIUp-bwILow);
++r;
} else {
gmass = (**pd).hardProcessMass();
}
maxMass -= gmass;
}
}
return momenta.size() > 3 ?
invertTwoToNKinematics(momenta,r) :
invertTwoToOneKinematics(momenta,r);
}
double MatchboxPhasespace::invertTwoToOneKinematics(const vector<Lorentz5Momentum>& momenta,
double* r) const {
double tau = momenta[2].mass2()/lastXCombPtr()->lastS();
double ltau = log(tau)/2.;
r[0] = (ltau - (momenta[0]+momenta[1]).rapidity())/(2.*ltau);
return -4.*Constants::pi*ltau;
}
void MatchboxPhasespace::setCoupling(long a, long b, long c,
double coupling, bool includeCrossings) {
cPDPtr A = getParticleData(a);
cPDPtr B = getParticleData(b);
cPDPtr C = getParticleData(c);
if ( !A || !B || !C ) {
generator()->log() << "Warning: could not determine particle data for ids "
<< a << " " << b << " " << c << " when setting coupling in MatchboxPhasespace.\n"
<< flush;
return;
}
if ( !includeCrossings ) {
theCouplings->couplings()[LTriple(a,b,c)] = coupling;
return;
}
if ( A->CC() ) {
theCouplings->couplings()[LTriple(-a,b,c)] = coupling;
theCouplings->couplings()[LTriple(-a,c,b)] = coupling;
} else {
theCouplings->couplings()[LTriple(a,b,c)] = coupling;
theCouplings->couplings()[LTriple(a,c,b)] = coupling;
}
if ( B->CC() ) {
theCouplings->couplings()[LTriple(-b,a,c)] = coupling;
theCouplings->couplings()[LTriple(-b,c,a)] = coupling;
} else {
theCouplings->couplings()[LTriple(b,a,c)] = coupling;
theCouplings->couplings()[LTriple(b,c,a)] = coupling;
}
if ( C->CC() ) {
theCouplings->couplings()[LTriple(-c,a,b)] = coupling;
theCouplings->couplings()[LTriple(-c,b,a)] = coupling;
} else {
theCouplings->couplings()[LTriple(c,a,b)] = coupling;
theCouplings->couplings()[LTriple(c,b,a)] = coupling;
}
}
string MatchboxPhasespace::doSetCoupling(string in) {
istringstream is(in);
long a,b,c; double coupling;
is >> a >> b >> c >> coupling;
if ( !is )
return "MatchboxPhasespace: error in setting coupling.";
setCoupling(a,b,c,coupling,true);
return "";
}
string MatchboxPhasespace::doSetPhysicalCoupling(string in) {
istringstream is(in);
long a,b,c; double coupling;
is >> a >> b >> c >> coupling;
if ( !is )
return "MatchboxPhasespace: error in setting coupling.";
setCoupling(a,b,c,coupling,false);
return "";
}
pair<double,Lorentz5Momentum>
MatchboxPhasespace::timeLikeWeight(const Tree2toNDiagram& diag,
int branch, double flatCut) const {
pair<int,int> children = diag.children(branch);
if ( children.first == -1 ) {
return make_pair(1.,meMomenta()[diag.externalId(branch)]);
}
pair<double,Lorentz5Momentum> res
= timeLikeWeight(diag,children.first,flatCut);
pair<double,Lorentz5Momentum> other
= timeLikeWeight(diag,children.second,flatCut);
res.first *= other.first;
res.second += other.second;
LTriple vertexKey(diag.allPartons()[branch]->id(),
diag.allPartons()[children.first]->id(),
diag.allPartons()[children.second]->id());
map<LTriple,double>::const_iterator cit = theCouplings->couplings().find(vertexKey);
if ( cit != theCouplings->couplings().end() ){
res.first *= cit->second;
}else{
if(factory()->verboseDia())
- cout<<"\n MatchboxPhasespace no coupling for (timelike) :" << vertexKey.get<0>()
- <<" "<<vertexKey.get<1>()<<" " <<vertexKey.get<2>();
+ cout<<"\n MatchboxPhasespace no coupling for (timelike) :" << std::get<0>(vertexKey)
+ <<" "<< std::get<1>(vertexKey)<<" " << std::get<2>(vertexKey);
}
Energy2 mass2 = sqr(diag.allPartons()[branch]->hardProcessMass());
Energy2 width2 = sqr(diag.allPartons()[branch]->hardProcessWidth());
if ( abs(diag.allPartons()[branch]->id()) >= theLoopParticleIdMin
&& abs(diag.allPartons()[branch]->id()) <= theLoopParticleIdMax ) { // "loop particle"
if ( abs((res.second.m2()-mass2)/lastSHat()) > flatCut ) {
res.first /=
abs((res.second.m2()-mass2)/GeV2);
res.first *=
log(abs((res.second.m2()-mass2)/GeV2)); // normal. of the argument in the log?
}
} else {
if ( width2 == ZERO ) {
if ( abs((res.second.m2()-mass2)/lastSHat()) > flatCut )
res.first /=
abs((res.second.m2()-mass2)/GeV2);
} else {
res.first /=
(sqr((res.second.m2()-mass2)/GeV2) +
mass2*width2/sqr(GeV2))/(abs(res.second.m2()/GeV2));
}
}
return res;
}
double MatchboxPhasespace::spaceLikeWeight(const Tree2toNDiagram& diag,
const Lorentz5Momentum& incoming,
int branch, double flatCut) const {
if ( branch == -1 )
return 1.;
pair<int,int> children = diag.children(branch);
pair<double,Lorentz5Momentum> res =
timeLikeWeight(diag,children.second,flatCut);
LTriple vertexKey(diag.allPartons()[branch]->id(),
diag.allPartons()[children.first]->id(),
diag.allPartons()[children.second]->id());
if ( children.first == diag.nSpace() - 1 ) {
if ( diag.allPartons()[children.first]->CC() )
vertexKey = LTriple(diag.allPartons()[branch]->id(),
diag.allPartons()[children.second]->id(),
diag.allPartons()[children.first]->CC()->id());
else
vertexKey = LTriple(diag.allPartons()[branch]->id(),
diag.allPartons()[children.second]->id(),
diag.allPartons()[children.first]->id());
}
map<LTriple,double>::const_iterator cit = theCouplings->couplings().find(vertexKey);
if ( cit != theCouplings->couplings().end() ){
res.first *= cit->second;
}else{
if(factory()->verboseDia())
- cout<<"\n MatchboxPhasespace no coupling for (space) :"<< vertexKey.get<0>()
- <<" "<<vertexKey.get<1>()<<" " <<vertexKey.get<2>();
+ cout<<"\n MatchboxPhasespace no coupling for (space) :"<< std::get<0>(vertexKey)
+ <<" "<< std::get<1>(vertexKey)<<" " << std::get<2>(vertexKey);
}
if ( children.first == diag.nSpace() - 1 ) {
return res.first;
}
res.second = incoming - res.second;
Energy2 mass2 = sqr(diag.allPartons()[children.first]->hardProcessMass());
Energy2 width2 = sqr(diag.allPartons()[children.first]->hardProcessWidth());
if ( abs(diag.allPartons()[children.first]->id()) >= theLoopParticleIdMin
&& (diag.allPartons()[children.first]->id()) <= theLoopParticleIdMax ) { // "loop particle"
if ( abs((res.second.m2()-mass2)/lastSHat()) > flatCut ) {
res.first /=
abs((res.second.m2()-mass2)/GeV2);
res.first *=
log(abs((res.second.m2()-mass2)/GeV2)); // normal. of the argument in the log?
}
} else {
if ( width2 == ZERO ) {
if ( abs((res.second.m2()-mass2)/lastSHat()) > flatCut )
res.first /=
abs((res.second.m2()-mass2)/GeV2);
} else {
res.first /=
(sqr((res.second.m2()-mass2)/GeV2) +
mass2*width2/sqr(GeV2))/(abs(res.second.m2()/GeV2));
}
}
return
res.first * spaceLikeWeight(diag,res.second,children.first,flatCut);
}
void MatchboxPhasespace::fillDiagramWeights(double flatCut) {
diagramWeights().clear();
for ( StandardXComb::DiagramVector::const_iterator d =
lastXComb().diagrams().begin(); d != lastXComb().diagrams().end(); ++d ) {
diagramWeights()[(**d).id()] =
spaceLikeWeight(dynamic_cast<const Tree2toNDiagram&>(**d),meMomenta()[0],0,flatCut);
}
}
Selector<MEBase::DiagramIndex>
MatchboxPhasespace::selectDiagrams(const MEBase::DiagramVector& diags) const {
Selector<MEBase::DiagramIndex> ret;
for ( MEBase::DiagramIndex d = 0; d < diags.size(); ++d ) {
ret.insert(diagramWeight(dynamic_cast<const Tree2toNDiagram&>(*diags[d])),d);
}
return ret;
}
bool MatchboxPhasespace::matchConstraints(const vector<Lorentz5Momentum>& momenta) {
if ( singularLimits().empty() )
return true;
lastSingularLimit() = singularLimits().begin();
for ( ; lastSingularLimit() != singularLimits().end(); ++lastSingularLimit() ) {
if ( lastSingularLimit()->first == lastSingularLimit()->second &&
momenta[lastSingularLimit()->first].t() < singularCutoff )
break;
if ( lastSingularLimit()->first != lastSingularLimit()->second &&
sqrt(momenta[lastSingularLimit()->first]*
momenta[lastSingularLimit()->second]) < singularCutoff ) {
bool match = true;
for ( set<pair<size_t,size_t> >::const_iterator other =
singularLimits().begin(); other != singularLimits().end(); ++other ) {
if ( other == lastSingularLimit() )
continue;
if ( other->first == other->second &&
momenta[other->first].t() < singularCutoff ) {
match = false;
break;
}
if ( other->first != other->second &&
sqrt(momenta[other->first]*
momenta[other->second]) < singularCutoff ) {
match = false;
break;
}
}
if ( match )
break;
}
}
return lastSingularLimit() != singularLimits().end();
}
int MatchboxPhasespace::nDim(const cPDVector& data) const {
int ndimps = nDimPhasespace(data.size()-2);
if ( useMassGenerators() ) {
for ( cPDVector::const_iterator pd = data.begin();
pd != data.end(); ++pd ) {
if ( (**pd).massGenerator() ||
(**pd).hardProcessWidth() != ZERO ) {
++ndimps;
}
}
}
return ndimps;
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void MatchboxPhasespace::persistentOutput(PersistentOStream & os) const {
os << theLastXComb
<< ounit(singularCutoff,GeV) << theUseMassGenerators
<< theLoopParticleIdMin << theLoopParticleIdMax
<< theCouplings;
}
void MatchboxPhasespace::persistentInput(PersistentIStream & is, int) {
is >> theLastXComb
>> iunit(singularCutoff,GeV) >> theUseMassGenerators
>> theLoopParticleIdMin >> theLoopParticleIdMax
>> theCouplings;
lastMatchboxXComb(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).
DescribeAbstractClass<MatchboxPhasespace,HandlerBase>
describeMatchboxPhasespace("Herwig::MatchboxPhasespace", "Herwig.so");
void MatchboxPhasespace::Init() {
static ClassDocumentation<MatchboxPhasespace> documentation
("MatchboxPhasespace defines an abstract interface to a phase "
"space generator.");
static Parameter<MatchboxPhasespace,Energy> interfaceSingularCutoff
("SingularCutoff",
"[debug] Cutoff below which a region is considered singular.",
&MatchboxPhasespace::singularCutoff, GeV, 10.0*GeV, 0.0*GeV, 0*GeV,
false, false, Interface::lowerlim);
/*
static Switch<MatchboxPhasespace,bool> interfaceUseMassGenerators
("UseMassGenerators",
"Use mass generators instead of fixed masses.",
&MatchboxPhasespace::theUseMassGenerators, false, false, false);
static SwitchOption interfaceUseMassGeneratorsYes
(interfaceUseMassGenerators,
"Yes",
"Use mass generators.",
true);
static SwitchOption interfaceUseMassGeneratorsNo
(interfaceUseMassGenerators,
"No",
"Do not use mass generators.",
false);
*/
static Command<MatchboxPhasespace> interfaceSetCoupling
("SetCoupling",
"",
&MatchboxPhasespace::doSetCoupling, false);
static Command<MatchboxPhasespace> interfaceSetPhysicalCoupling
("SetPhysicalCoupling",
"",
&MatchboxPhasespace::doSetPhysicalCoupling, false);
static Parameter<MatchboxPhasespace,int> interfaceLoopParticleIdMin
("LoopParticleIdMin",
"First id in a range of id's meant to denote fictitious "
"'ghost' particles to be used by the diagram generator "
"in loop induced processes.",
&MatchboxPhasespace::theLoopParticleIdMin, 200001, 0, 0,
false, false, Interface::lowerlim);
static Parameter<MatchboxPhasespace,int> interfaceLoopParticleIdMax
("LoopParticleIdMax",
"Last id in a range of id's meant to denote fictitious "
"'ghost' particles to be used by the diagram generator "
"in loop induced processes.",
&MatchboxPhasespace::theLoopParticleIdMax, 200100, 0, 0,
false, false, Interface::lowerlim);
static Reference<MatchboxPhasespace,PhasespaceCouplings> interfaceCouplingData
("CouplingData",
"Set the storage for the couplings.",
&MatchboxPhasespace::theCouplings, false, false, true, false, false);
}
diff --git a/MatrixElement/Matchbox/Phasespace/PhasespaceCouplings.h b/MatrixElement/Matchbox/Phasespace/PhasespaceCouplings.h
--- a/MatrixElement/Matchbox/Phasespace/PhasespaceCouplings.h
+++ b/MatrixElement/Matchbox/Phasespace/PhasespaceCouplings.h
@@ -1,142 +1,139 @@
// -*- C++ -*-
//
// PhasespaceCouplings.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_PhasespaceCouplings_H
#define Herwig_PhasespaceCouplings_H
//
// This is the declaration of the PhasespaceCouplings class.
//
#include "ThePEG/Handlers/HandlerBase.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
-#include <boost/tuple/tuple.hpp>
-#include <boost/tuple/tuple_comparison.hpp>
-
namespace Herwig {
using namespace ThePEG;
-typedef boost::tuple<long,long,long> LTriple;
+typedef std::tuple<long,long,long> LTriple;
inline PersistentOStream& operator<<(PersistentOStream& os, const LTriple& t) {
- os << t.get<0>() << t.get<1>() << t.get<2>();
+ os << std::get<0>(t) << std::get<1>(t) << std::get<2>(t);
return os;
}
inline PersistentIStream& operator>>(PersistentIStream& is, LTriple& t) {
- is >> t.get<0>() >> t.get<1>() >> t.get<2>();
+ is >> std::get<0>(t) >> std::get<1>(t) >> std::get<2>(t);
return is;
}
/**
*
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief Store couplings for the phasespace generator.
*
* @see \ref PhasespaceCouplingsInterfaces "The interfaces"
* defined for PhasespaceCouplings.
*/
class PhasespaceCouplings: public HandlerBase {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
PhasespaceCouplings();
/**
* The destructor.
*/
virtual ~PhasespaceCouplings();
//@}
public:
/**
* Couplings to be used in diagram weighting
*/
map<LTriple,double>& couplings() { return theCouplings; }
/**
* Couplings to be used in diagram weighting
*/
const map<LTriple,double>& couplings() const { return theCouplings; }
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:
/**
* Couplings to be used in diagram weighting
*/
map<LTriple,double> theCouplings;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
PhasespaceCouplings & operator=(const PhasespaceCouplings &);
};
}
#endif /* Herwig_PhasespaceCouplings_H */
diff --git a/MatrixElement/Matchbox/Scales/Makefile.am b/MatrixElement/Matchbox/Scales/Makefile.am
--- a/MatrixElement/Matchbox/Scales/Makefile.am
+++ b/MatrixElement/Matchbox/Scales/Makefile.am
@@ -1,30 +1,28 @@
pkglib_LTLIBRARIES = HwMatchboxScales.la
HwMatchboxScales_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 2:1:0
HwMatchboxScales_la_SOURCES = \
MatchboxHtScale.h \
MatchboxLeptonMassScale.h \
MatchboxLeptonPtScale.h \
MatchboxParticlePtScale.h \
MatchboxPtScale.h \
MatchboxHtScale.cc \
MatchboxLeptonMassScale.cc \
MatchboxLeptonPtScale.cc \
MatchboxParticlePtScale.cc \
-MatchboxPtScale.cc\
-MatchboxScale.h \
-MatchboxScale.cc \
+MatchboxPtScale.cc \
MatchboxSHatScale.h \
MatchboxSHatScale.cc \
MatchboxTopMassScale.h \
MatchboxTopMassScale.cc \
MatchboxTopMTScale.h \
MatchboxTopMTScale.cc \
MatchboxTopSumMTScale.h \
MatchboxTopSumMTScale.cc \
MatchboxTopMinMTScale.h \
MatchboxTopMinMTScale.cc \
MatchboxTriVecScales.h \
MatchboxTriVecScales.cc
diff --git a/MatrixElement/Matchbox/Scales/MatchboxScale.cc.in b/MatrixElement/Matchbox/Scales/MatchboxScale.cc.in
deleted file mode 100644
--- a/MatrixElement/Matchbox/Scales/MatchboxScale.cc.in
+++ /dev/null
@@ -1,183 +0,0 @@
-// -*- C++ -*-
-//
-// MatchboxScale.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 MatchboxScale class.
-//
-
-#include "MatchboxScale.h"
-#include "ThePEG/Interface/ClassDocumentation.h"
-#include "ThePEG/Interface/Switch.h"
-#include "ThePEG/Interface/Reference.h"
-#include "ThePEG/Interface/Parameter.h"
-#include "ThePEG/EventRecord/Particle.h"
-#include "ThePEG/Repository/Repository.h"
-#include "ThePEG/Repository/UseRandom.h"
-#include "ThePEG/Repository/EventGenerator.h"
-#include "ThePEG/Utilities/DescribeClass.h"
-#include "ThePEG/Interface/Command.h"
-#include "ThePEG/Utilities/DynamicLoader.h"
-
-
-#include "ThePEG/Persistency/PersistentOStream.h"
-#include "ThePEG/Persistency/PersistentIStream.h"
-
-using namespace Herwig;
-
-//external function which will be filled in doFunktion(..)
-Energy2 renScale(vector<Lorentz5Momentum> jet, vector<Lorentz5Momentum> lepton, vector<Lorentz5Momentum> boson);
-
-
-MatchboxScale::MatchboxScale()
- {}
-
-MatchboxScale::~MatchboxScale() {}
-
-IBPtr MatchboxScale::clone() const {
- return new_ptr(*this);
-}
-
-IBPtr MatchboxScale::fullclone() const {
- return new_ptr(*this);
-}
-
-
-
-
-string MatchboxScale::doFunction(string in) {
- string cmd = "Makefile";
- ofstream makeFile(cmd.c_str());
- cmd = "Scale.cc";
- ofstream scaleFile(cmd.c_str());
- scaleFile<< "#include \"Herwig/MatrixElement/Matchbox/Scales/MatchboxScale.h\"\n" ;
- scaleFile<< "using namespace Herwig ;\n" ;
- scaleFile<< "Energy2 renScale(vector<Lorentz5Momentum> jet, vector<Lorentz5Momentum> lepton, vector<Lorentz5Momentum> boson){\n" ;
- scaleFile<< "return \n"<< in.c_str();
- scaleFile<< ";}\n" ;
- scaleFile<< flush ;
-
- makeFile<< "THEPEG=@THEPEGPATH@\n" ;
- makeFile<< "HERWIG=@prefix@\n" ;
- makeFile<< "INCLUDE=-I $(THEPEG)/include -I $(HERWIG)/include\n" ;
- makeFile<< "LIBPATH=@THEPEGLDFLAGS@\n" ;
- makeFile<< "SHARED_FLAG=@SHARED_FLAG@ @APPLE_DSO_FLAGS@ \n";
- makeFile<< "all: \n" ;
- makeFile<< "\tg++ $(SHARED_FLAG) -g3 -fPIC -o "<<scalePath<<"Scale.so $(INCLUDE) $(LIBPATH) @THEPEGLIB@ Scale.cc\n" ;
- makeFile<< flush ;
-
-
- cmd = "make";
- int st = std::system(cmd.c_str());
- Repository::clog() << "scale compilation returned " << st << "\n";
- return "";
-
-}
-
-
-struct PtLargerMB {
- inline bool operator()(const LorentzMomentum& a,
- const LorentzMomentum& b) const {
- return a.perp() > b.perp();
- }
-};
-
-
-
-bool loadlib=false;
-
-Energy2 MatchboxScale::renormalizationScale() const {
- tcPDVector pd (mePartonData().begin() + 2, mePartonData().end());
- vector<LorentzMomentum> p (meMomenta().begin() + 2, meMomenta().end());
- tcPDPtr t1 = mePartonData()[0];
- tcPDPtr t2 = mePartonData()[1];
- tcCutsPtr cuts = lastCutsPtr();
- theJetFinder->cluster(pd, p, cuts, t1, t2);
-
-
- vector<Lorentz5Momentum> jet;
- vector<Lorentz5Momentum> lepton;
- vector<Lorentz5Momentum> boson;
-
- tcPDVector::const_iterator itpd = pd.begin();
- for (vector<LorentzMomentum>::const_iterator itp = p.begin() ;
- itp != p.end(); ++itp, ++itpd ) {
- if ( (**itpd).coloured() ) {
- jet.push_back(*itp);
- }
- if ( abs((**itpd).id())>=22&&abs((**itpd).id())<=25 ) {
- boson.push_back(*itp);
- }
- if ( abs((**itpd).id())> 10&&abs((**itpd).id())< 17 ) {
- lepton.push_back(*itp);
- }
-
- }
-
-
- std::sort(jet.begin(),jet.end(),PtLargerMB());
-
-
- if (!loadlib)
- if ( !DynamicLoader::load(scalePath+"Scale.so") ) assert(0);
-
- return renScale(jet,lepton,boson);
-}
-
-Energy2 MatchboxScale::factorizationScale() const {
- return renormalizationScale();
-}
-
-// If needed, insert default implementations of virtual function defined
-// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
-
-
-void MatchboxScale::persistentOutput(PersistentOStream & os) const {
- os << theJetFinder << scalePath;
-}
-
-void MatchboxScale::persistentInput(PersistentIStream & is, int) {
- is >> theJetFinder >> scalePath ;
-}
-
-
-// *** 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<MatchboxScale,MatchboxScaleChoice>
- describeHerwigMatchboxScale("Herwig::MatchboxScale", "HwMatchboxScales.so");
-
-void MatchboxScale::Init() {
-
- static ClassDocumentation<MatchboxScale> documentation
- ("MatchboxScale implements scale choices related to transverse momenta.");
-
- static Reference<MatchboxScale,JetFinder> interfaceJetFinder
- ("JetFinder",
- "A reference to the jet finder.",
- &MatchboxScale::theJetFinder, false, false, true, false, false);
-
- static Command<MatchboxScale> interfaceFunction
- ("Function",
- "Set the scale function.",
- &MatchboxScale::doFunction, false);
-
-
-
-
- static Parameter<MatchboxScale,string> interfaceScalePath
- ("ScalePath",
- "Prefix for the scalepath.",
- &MatchboxScale::scalePath, "",
- false, false);
-
-}
-
-
diff --git a/MatrixElement/Matchbox/Scales/MatchboxScale.h b/MatrixElement/Matchbox/Scales/MatchboxScale.h
deleted file mode 100644
--- a/MatrixElement/Matchbox/Scales/MatchboxScale.h
+++ /dev/null
@@ -1,133 +0,0 @@
-// -*- C++ -*-
-//
-// MatchboxScale.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_MatchboxScale_H
-#define Herwig_MatchboxScale_H
-//
-// This is the declaration of the MatchboxScale class.
-//
-
-#include "Herwig/MatrixElement/Matchbox/Utility/MatchboxScaleChoice.h"
-#include "ThePEG/PDT/MatcherBase.h"
-#include "ThePEG/Cuts/JetFinder.h"
-
-namespace Herwig {
-
-using namespace ThePEG;
-
-/**
- * \ingroup Matchbox
- * \author Johannes Bellm
- *
- * \brief MatchboxScale implements scale choices related to an input formula.
- *
- */
-class MatchboxScale: public MatchboxScaleChoice {
-
-public:
-
- /** @name Standard constructors and destructors. */
- //@{
- /**
- * The default constructor.
- */
- MatchboxScale();
-
- /**
- * The destructor.
- */
- virtual ~MatchboxScale();
- //@}
-
-public:
-
- /**
- * Return the renormalization scale. This default version returns
- * shat.
- */
- virtual Energy2 renormalizationScale() const;
-
- /**
- * Return the factorization scale. This default version returns
- * shat.
- */
- virtual Energy2 factorizationScale() const;
-
- string doFunction(string in);
-
-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;
- //@}
-
-private:
-
- /**
- * Reference to the jet finder
- */
- Ptr<JetFinder>::ptr theJetFinder;
-
-
-
- string scalePath;
-
-// 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.
- */
- MatchboxScale & operator=(const MatchboxScale &);
-
-};
-
-}
-
-#endif /* Herwig_MatchboxScale_H */
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(!isnan(res));
+ 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()->buildStorage();
readBasis();
}
void ColourBasis::dofinish() {
HandlerBase::dofinish();
writeBasis();
}
void ColourBasis::doinitrun() {
HandlerBase::doinitrun();
if ( theSearchPath.empty() && factory() )
theSearchPath = factory()->buildStorage();
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/MatrixElement/Powheg/MEPP2GammaGammaPowheg.cc b/MatrixElement/Powheg/MEPP2GammaGammaPowheg.cc
--- a/MatrixElement/Powheg/MEPP2GammaGammaPowheg.cc
+++ b/MatrixElement/Powheg/MEPP2GammaGammaPowheg.cc
@@ -1,2047 +1,2047 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the MEPP2GammaGammaPowheg class.
//
#include "MEPP2GammaGammaPowheg.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "ThePEG/Cuts/Cuts.h"
#include "ThePEG/Utilities/SimplePhaseSpace.h"
#include "Herwig/Models/StandardModel/StandardModel.h"
#include "Herwig/Utilities/Maths.h"
#include "Herwig/Shower/RealEmissionProcess.h"
#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
// The following static variable is needed for the type
// description system in ThePEG.
DescribeClass<MEPP2GammaGammaPowheg,Herwig::HwMEBase>
describeMEPP2GammaGammaPowheg("Herwig::MEPP2GammaGammaPowheg",
"HwMEHadron.so HwPowhegMEHadron.so");
unsigned int MEPP2GammaGammaPowheg::orderInAlphaS() const {
return 0;
}
unsigned int MEPP2GammaGammaPowheg::orderInAlphaEW() const {
return 2;
}
IBPtr MEPP2GammaGammaPowheg::clone() const {
return new_ptr(*this);
}
IBPtr MEPP2GammaGammaPowheg::fullclone() const {
return new_ptr(*this);
}
MEPP2GammaGammaPowheg::MEPP2GammaGammaPowheg()
: contrib_(1), power_(0.1), process_(0), threeBodyProcess_(0),
maxflavour_(5), alphaS_(0.), fixedAlphaS_(false),
supressionFunction_(0), supressionScale_(0), lambda_(20.*GeV),
preQCDqqbarq_(5.), preQCDqqbarqbar_(0.5), preQCDqg_(50.), preQCDgqbar_(50.),
preQEDqqbarq_(40.), preQEDqqbarqbar_(0.5), preQEDqgq_(1.), preQEDgqbarqbar_(1.),
minpT_(2.*GeV), scaleChoice_(0), scalePreFactor_(1.)
{}
void MEPP2GammaGammaPowheg::getDiagrams() const {
tcPDPtr gamma = getParticleData(ParticleID::gamma);
tcPDPtr g = getParticleData(ParticleID::g);
for(int ix=1;ix<=maxflavour_;++ix) {
tcPDPtr qk = getParticleData(ix);
tcPDPtr qb = qk->CC();
// gamma gamma
if(process_==0 || process_ == 1) {
add(new_ptr((Tree2toNDiagram(3), qk, qk, qb, 1, gamma, 2, gamma, -1)));
add(new_ptr((Tree2toNDiagram(3), qk, qk, qb, 2, gamma, 1, gamma, -2)));
}
// gamma +jet
if(process_==0 || process_ == 2) {
add(new_ptr((Tree2toNDiagram(3), qk, qb, qb, 1, gamma,
2, g, -4)));
add(new_ptr((Tree2toNDiagram(3), qk, qk, qb, 2, gamma,
1, g, -5)));
add(new_ptr((Tree2toNDiagram(3), qk, qk, g, 1, gamma,
2, qk, -6)));
add(new_ptr((Tree2toNDiagram(2), qk, g, 1, qk, 3, gamma,
3, qk, -7)));
add(new_ptr((Tree2toNDiagram(3), g, qb, qb, 2, gamma,
1, qb, -8)));
add(new_ptr((Tree2toNDiagram(2), g, qb, 1, qb, 3, gamma,
3, qb, -9)));
}
// gamma + jet + gamma
if((process_==0 && contrib_==1) || process_ == 3) {
// gamma + g + gamma
if(threeBodyProcess_==0 || threeBodyProcess_==1) {
add(new_ptr((Tree2toNDiagram(4), qk, qk, qk, qb, 1, gamma,
2, gamma, 3, g, -10)));
add(new_ptr((Tree2toNDiagram(4), qk, qk, qk, qb, 3, gamma,
2, gamma, 1, g, -12)));
}
// Z + q + gamma
if(threeBodyProcess_==0 || threeBodyProcess_==2) {
add(new_ptr((Tree2toNDiagram(4),qk,qk,qk,g,1,gamma,2,gamma,3,qk, -20)));
add(new_ptr((Tree2toNDiagram(4),qk,qk,qk,g,2,gamma,1,gamma,3,qk, -21)));
add(new_ptr((Tree2toNDiagram(3),qk,qk,g,1,gamma,2,qk,5,gamma,5,qk,-22)));
}
// Z + qbar + gamma
if(threeBodyProcess_==0 || threeBodyProcess_==3) {
add(new_ptr((Tree2toNDiagram(4),g,qb,qb,qb,3,gamma,2,gamma,1,qb ,-30)));
add(new_ptr((Tree2toNDiagram(4),g,qb,qb,qb,2,gamma,3,gamma,1,qb ,-31)));
add(new_ptr((Tree2toNDiagram(3),g,qb,qb ,2,gamma,1,qb,5,gamma,5,qb,-32)));
}
}
}
}
Energy2 MEPP2GammaGammaPowheg::scale() const {
Energy2 scale;
if(scaleChoice_==0) {
Energy pt;
if(meMomenta()[2].perp(meMomenta()[0].vect())>=
meMomenta()[3].perp(meMomenta()[0].vect())){
pt = meMomenta()[2].perp(meMomenta()[0].vect());
} else {
pt = meMomenta()[3].perp(meMomenta()[0].vect());
}
scale = sqr(pt);
}
else if(scaleChoice_==1) {
scale = sHat();
}
return scalePreFactor_*scale;
}
int MEPP2GammaGammaPowheg::nDim() const {
return HwMEBase::nDim() + ( contrib_>=1 ? 3 : 0 );
}
bool MEPP2GammaGammaPowheg::generateKinematics(const double * r) {
// radiative variables
if(contrib_>=1) {
zTilde_ = r[nDim()-1];
vTilde_ = r[nDim()-2];
phi_ = Constants::twopi*r[nDim()-3];
}
// set the jacobian
jacobian(1.0);
// set up the momenta
for ( int i = 2, N = meMomenta().size(); i < N; ++i )
meMomenta()[i] = Lorentz5Momentum(ZERO);
// generate sHat
Energy2 shat(sHat());
if(mePartonData().size()==5) {
double eps = sqr(meMomenta()[2].mass())/shat;
jacobian(jacobian()*(1.-eps));
shat *= eps+zTilde_*(1.-eps);
}
// momenta of the core process
double ctmin = -1.0, ctmax = 1.0;
Energy q = ZERO;
try {
q = SimplePhaseSpace::
getMagnitude(shat, meMomenta()[2].mass(), ZERO);
}
catch ( ImpossibleKinematics ) {
return false;
}
Energy e = 0.5*sqrt(shat);
Energy2 m22 = meMomenta()[2].mass2();
Energy2 e0e2 = 2.0*e*sqrt(sqr(q) + m22);
Energy2 e1e2 = 2.0*e*sqrt(sqr(q) + m22);
Energy2 e0e3 = 2.0*e*sqrt(sqr(q));
Energy2 e1e3 = 2.0*e*sqrt(sqr(q));
Energy2 pq = 2.0*e*q;
if(mePartonData().size()==4) {
Energy2 thmin = lastCuts().minTij(mePartonData()[0], mePartonData()[2]);
if ( thmin > ZERO ) ctmax = min(ctmax, (e0e2 - m22 - thmin)/pq);
thmin = lastCuts().minTij(mePartonData()[1], mePartonData()[2]);
if ( thmin > ZERO ) ctmin = max(ctmin, (thmin + m22 - e1e2)/pq);
thmin = lastCuts().minTij(mePartonData()[1], mePartonData()[3]);
if ( thmin > ZERO ) ctmax = min(ctmax, (e1e3 - thmin)/pq);
thmin = lastCuts().minTij(mePartonData()[0], mePartonData()[3]);
if ( thmin > ZERO ) ctmin = max(ctmin, (thmin - e0e3)/pq);
Energy ptmin = max(lastCuts().minKT(mePartonData()[2]),
lastCuts().minKT(mePartonData()[3]));
if ( ptmin > ZERO ) {
double ctm = 1.0 - sqr(ptmin/q);
if ( ctm <= 0.0 ) return false;
ctmin = max(ctmin, -sqrt(ctm));
ctmax = min(ctmax, sqrt(ctm));
}
double ymin2 = lastCuts().minYStar(mePartonData()[2]);
double ymax2 = lastCuts().maxYStar(mePartonData()[2]);
double ymin3 = lastCuts().minYStar(mePartonData()[3]);
double ymax3 = lastCuts().maxYStar(mePartonData()[3]);
double ytot = lastCuts().Y() + lastCuts().currentYHat();
if ( ymin2 + ytot > -0.9*Constants::MaxRapidity )
ctmin = max(ctmin, sqrt(sqr(q) + m22)*tanh(ymin2)/q);
if ( ymax2 + ytot < 0.9*Constants::MaxRapidity )
ctmax = min(ctmax, sqrt(sqr(q) + m22)*tanh(ymax2)/q);
if ( ymin3 + ytot > -0.9*Constants::MaxRapidity )
ctmax = min(ctmax, tanh(-ymin3));
if ( ymax3 + ytot < 0.9*Constants::MaxRapidity )
ctmin = max(ctmin, tanh(-ymax3));
if ( ctmin >= ctmax ) return false;
}
double cth = getCosTheta(ctmin, ctmax, r[0]);
Energy pt = q*sqrt(1.0-sqr(cth));
phi(rnd(2.0*Constants::pi));
meMomenta()[2].setVect(Momentum3( pt*sin(phi()), pt*cos(phi()), q*cth));
meMomenta()[3].setVect(Momentum3(-pt*sin(phi()), -pt*cos(phi()), -q*cth));
meMomenta()[2].rescaleEnergy();
meMomenta()[3].rescaleEnergy();
// jacobian
tHat(pq*cth + m22 - e0e2);
uHat(m22 - shat - tHat());
jacobian(pq/shat*Constants::pi*jacobian());
// end for 2->2 processes
if(mePartonData().size()==4) {
vector<LorentzMomentum> out(2);
out[0] = meMomenta()[2];
out[1] = meMomenta()[3];
tcPDVector tout(2);
tout[0] = mePartonData()[2];
tout[1] = mePartonData()[3];
if ( !lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]) )
return false;
return true;
}
// special for 2-3 processes
pair<double,double> x = make_pair(lastX1(),lastX2());
// partons
pair<tcPDPtr,tcPDPtr> partons = make_pair(mePartonData()[0],mePartonData()[1]);
// If necessary swap the particle data objects so that
// first beam gives the incoming quark
if(lastPartons().first ->dataPtr()!=partons.first) {
swap(x.first,x.second);
}
// use vTilde to select the dipole for emission
// gamma gamma g processes
if(mePartonData()[4]->id()==ParticleID::g) {
if(vTilde_<=0.5) {
dipole_ = IIQCD1;
vTilde_ = 4.*vTilde_;
}
else {
dipole_ = IIQCD2;
vTilde_ = 4.*(vTilde_-0.25);
}
jacobian(2.*jacobian());
}
// gamma gamma q processes
else if(mePartonData()[4]->id()>0&&mePartonData()[4]->id()<6) {
if(vTilde_<=1./3.) {
dipole_ = IIQCD2;
vTilde_ = 3.*vTilde_;
}
else if(vTilde_<=2./3.) {
dipole_ = IFQED1;
vTilde_ = 3.*vTilde_-1.;
}
else {
dipole_ = FIQED1;
vTilde_ = 3.*vTilde_-2.;
}
jacobian(3.*jacobian());
}
// gamma gamma qbar processes
else if(mePartonData()[4]->id()<0&&mePartonData()[4]->id()>-6) {
if(vTilde_<=1./3.) {
dipole_ = IIQCD1;
vTilde_ = 3.*vTilde_;
}
else if(vTilde_<=2./3.) {
dipole_ = IFQED2;
vTilde_ = 3.*vTilde_-1.;
}
else {
dipole_ = FIQED2;
vTilde_ = 3.*vTilde_-2.;
}
jacobian(3.*jacobian());
}
else {
assert(false);
}
// initial-initial dipoles
if(dipole_<=4) {
double z = shat/sHat();
double vt = vTilde_*(1.-z);
double vJac = 1.-z;
Energy pT = sqrt(shat*vt*(1.-vt-z)/z);
if(pT<MeV) return false;
double rapidity;
Energy rs=sqrt(lastS());
Lorentz5Momentum pcmf;
// emission from first beam
if(dipole_<=2) {
rapidity = -log(x.second*sqrt(lastS())/pT*vt);
pcmf = Lorentz5Momentum(ZERO,ZERO,
0.5*rs*(x.first*z-x.second),
0.5*rs*(x.first*z+x.second));
}
// emission from second beam
else {
rapidity = log(x.first *sqrt(lastS())/pT*vt);
pcmf = Lorentz5Momentum(ZERO,ZERO,
0.5*rs*(x.first-x.second*z),
0.5*rs*(x.first+x.second*z));
}
pcmf.rescaleMass();
Boost blab(pcmf.boostVector());
// emission from the quark radiation
vector<Lorentz5Momentum> pnew(5);
pnew [0] = Lorentz5Momentum(ZERO,ZERO,0.5*rs*x.first,
0.5*rs*x.first,ZERO);
pnew [1] = Lorentz5Momentum(ZERO,ZERO,-0.5*rs*x.second,
0.5*rs*x.second,ZERO) ;
pnew [2] = meMomenta()[2];
pnew [3] = meMomenta()[3];
pnew [4] = Lorentz5Momentum(pT*cos(phi_),pT*sin(phi_),
pT*sinh(rapidity),
pT*cosh(rapidity), ZERO);
pnew[4].rescaleEnergy();
Lorentz5Momentum K = pnew [0]+pnew [1]-pnew [4];
Lorentz5Momentum Kt = pcmf;
Lorentz5Momentum Ksum = K+Kt;
Energy2 K2 = K.m2();
Energy2 Ksum2 = Ksum.m2();
for(unsigned int ix=2;ix<4;++ix) {
pnew [ix].boost(blab);
pnew [ix] = pnew [ix] - 2.*Ksum*(Ksum*pnew [ix])/Ksum2
+2*K*(Kt*pnew [ix])/K2;
pnew[ix].rescaleEnergy();
}
pcmf = Lorentz5Momentum(ZERO,ZERO,
0.5*rs*(x.first-x.second),
0.5*rs*(x.first+x.second));
pcmf.rescaleMass();
blab = pcmf.boostVector();
for(unsigned int ix=0;ix<pnew.size();++ix)
pnew[ix].boost(-blab);
// phase-space prefactors
jacobian(jacobian()*vJac);
if(dipole_%2!=0) swap(pnew[3],pnew[4]);
for(unsigned int ix=2;ix<meMomenta().size();++ix)
meMomenta()[ix] = pnew[ix];
}
else if(dipole_<=8) {
double x = shat/sHat();
double z = vTilde_;
double x1 = -1./x;
double x3 = 1.-z/x;
double x2 = 2.+x1-x3;
double xT = sqrt(4.*(1-x)*(1-z)*z/x);
// rotate the momenta into the Breit-frame
Lorentz5Momentum pin,pcmf;
if(dipole_<=6) {
pin = x*meMomenta()[0];
pcmf = pin+meMomenta()[1];
}
else {
pin = x*meMomenta()[1];
pcmf = pin+meMomenta()[0];
}
Boost bv = pcmf.boostVector();
meMomenta()[2].boost(bv);
meMomenta()[3].boost(bv);
Lorentz5Momentum q = meMomenta()[3]-pin;
Axis axis(q.vect().unit());
LorentzRotation rot;
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
rot = LorentzRotation();
if(axis.perp2()>1e-20) {
rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
rot.rotateX(Constants::pi);
}
if(abs(1.-q.e()/q.vect().mag())>1e-6)
rot.boostZ(q.e()/q.vect().mag());
pin *= rot;
if(pin.perp2()/GeV2>1e-20) {
Boost trans = -1./pin.e()*pin.vect();
trans.setZ(0.);
rot.boost(trans);
}
rot.invert();
Energy Q = sqrt(-q.m2());
meMomenta()[4] = rot*Lorentz5Momentum( 0.5*Q*xT*cos(phi_), 0.5*Q*xT*sin(phi_),
-0.5*Q*x2,0.5*Q*sqrt(sqr(x2)+sqr(xT)));
meMomenta()[3] = rot*Lorentz5Momentum(-0.5*Q*xT*cos(phi_),-0.5*Q*xT*sin(phi_),
-0.5*Q*x3,0.5*Q*sqrt(sqr(x3)+sqr(xT)));
double ratio;
if(dipole_<=6) {
ratio = 2.*((meMomenta()[3]+meMomenta()[4])*meMomenta()[0])/sHat();
}
else {
ratio = 2.*((meMomenta()[3]+meMomenta()[4])*meMomenta()[1])/sHat();
}
jacobian(jacobian()*ratio);
}
else {
assert(false);
}
vector<LorentzMomentum> out(3);
tcPDVector tout(3);
for(unsigned int ix=0;ix<3;++ix) {
out[ix] = meMomenta() [2+ix];
tout[ix] = mePartonData()[2+ix];
}
return lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]);
}
double MEPP2GammaGammaPowheg::me2() const {
// Born configurations
if(mePartonData().size()==4) {
// gamma gamma core process
if(mePartonData()[3]->id()==ParticleID::gamma) {
return 2.*Constants::twopi*alphaEM_*
loGammaGammaME(mePartonData(),meMomenta(),true);
}
// V jet core process
else if(mePartonData()[3]->id()==ParticleID::g) {
return 2.*Constants::twopi*alphaS_*
loGammagME(mePartonData(),meMomenta(),true);
}
else if(mePartonData()[3]->id()>0) {
return 2.*Constants::twopi*alphaS_*
loGammaqME(mePartonData(),meMomenta(),true);
}
else if(mePartonData()[3]->id()<0) {
return 2.*Constants::twopi*alphaS_*
loGammaqbarME(mePartonData(),meMomenta(),true);
}
else
assert(false);
}
// hard emission configurations
else {
if(mePartonData()[4]->id()==ParticleID::g)
return sHat()*realGammaGammagME (mePartonData(),meMomenta(),dipole_,Hard,true);
else if(mePartonData()[4]->id()>0&&mePartonData()[4]->id()<6)
return sHat()*realGammaGammaqME (mePartonData(),meMomenta(),dipole_,Hard,true);
else if(mePartonData()[4]->id()<0&&mePartonData()[4]->id()>-6)
return sHat()*realGammaGammaqbarME(mePartonData(),meMomenta(),dipole_,Hard,true);
else
assert(false);
}
}
CrossSection MEPP2GammaGammaPowheg::dSigHatDR() const {
// couplings
if(!fixedAlphaS_) alphaS_ = SM().alphaS(scale());
alphaEM_ = SM().alphaEM();
// cross section
CrossSection preFactor =
jacobian()/(16.0*sqr(Constants::pi)*sHat())*sqr(hbarc);
loME_ = me2();
if( contrib_== 0 || mePartonData().size()==5 ||
(mePartonData().size()==4&& mePartonData()[3]->coloured()))
return loME_*preFactor;
else
return NLOWeight()*preFactor;
}
Selector<MEBase::DiagramIndex>
MEPP2GammaGammaPowheg::diagrams(const DiagramVector & diags) const {
if(mePartonData().size()==4) {
if(mePartonData()[3]->id()==ParticleID::gamma) {
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i ){
sel.insert(meInfo()[abs(diags[i]->id())], i);
}
return sel;
}
else {
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i ){
sel.insert(meInfo()[abs(diags[i]->id())%2], i);
}
return sel;
}
}
else {
Selector<DiagramIndex> sel;
for ( DiagramIndex i = 0; i < diags.size(); ++i ) {
if(abs(diags[i]->id()) == 10 && dipole_ == IIQCD2 )
sel.insert(1., i);
else if(abs(diags[i]->id()) == 12 && dipole_ == IIQCD1 )
sel.insert(1., i);
else if(abs(diags[i]->id()) == 20 && dipole_ == IIQCD2 )
sel.insert(1., i);
else if(abs(diags[i]->id()) == 21 && dipole_ == IFQED1 )
sel.insert(1., i);
else if(abs(diags[i]->id()) == 22 && dipole_ == FIQED1 )
sel.insert(1., i);
else
sel.insert(0., i);
}
return sel;
}
}
Selector<const ColourLines *>
MEPP2GammaGammaPowheg::colourGeometries(tcDiagPtr diag) const {
// colour lines for V gamma
static ColourLines cs("1 -2");
static ColourLines ct("1 2 -3");
// colour lines for q qbar -> V g
static const ColourLines cqqbar[2]={ColourLines("1 -2 5,-3 -5"),
ColourLines("1 5,-5 2 -3")};
// colour lines for q g -> V q
static const ColourLines cqg [2]={ColourLines("1 2 -3,3 5"),
ColourLines("1 -2,2 3 5")};
// colour lines for g qbar -> V qbar
static const ColourLines cgqbar[2]={ColourLines("-3 -2 1,-1 -5"),
ColourLines("-2 1,-1 -3 -5")};
// colour lines for q qbar -> V gamma g
static const ColourLines cqqbarg[4]={ColourLines("1 2 3 7,-4 -7"),
ColourLines("1 2 7,-4 3 -7"),
ColourLines("1 7,-4 3 2 -7"),
ColourLines("1 2 7,-4 3 -7")};
// colour lines for q g -> V gamma q
static const ColourLines cqgq [3]={ColourLines("1 2 3 -4,4 7"),
ColourLines("1 2 3 -4,4 7"),
ColourLines("1 2 -3,3 5 7")};
// colour lines for gbar -> V gamma qbar
static const ColourLines cqbargqbar[3]={ColourLines("1 -2 -3 -4,-1 -7"),
ColourLines("1 -2 -3 -4,-1 -7"),
ColourLines("1 -2 -3,-1 -5 -7")};
Selector<const ColourLines *> sel;
switch(abs(diag->id())) {
case 1 :case 2 :
sel.insert(1.0, &ct);
break;
case 3 :
sel.insert(1.0, &cs);
break;
case 4 :
sel.insert(1.0, &cqqbar[0]);
break;
case 5:
sel.insert(1.0, &cqqbar[1]);
break;
case 6:
sel.insert(1.0, &cqg[0]);
break;
case 7:
sel.insert(1.0, &cqg[1]);
break;
case 8:
sel.insert(1.0, &cgqbar[0]);
break;
case 9:
sel.insert(1.0, &cgqbar[1]);
break;
case 10: case 11: case 12: case 13:
sel.insert(1.0, &cqqbarg[abs(diag->id())-10]);
break;
case 20: case 21: case 22:
sel.insert(1.0, &cqgq[abs(diag->id())-20]);
break;
case 30: case 31: case 32:
sel.insert(1.0, &cqbargqbar[abs(diag->id())-30]);
break;
default:
assert(false);
}
return sel;
}
void MEPP2GammaGammaPowheg::persistentOutput(PersistentOStream & os) const {
os << FFPvertex_ << FFGvertex_
<< contrib_ << power_ << gluon_ << prefactor_
<< process_ << threeBodyProcess_<< maxflavour_
<< alphaS_ << fixedAlphaS_
<< supressionFunction_ << supressionScale_ << ounit(lambda_,GeV)
<< alphaQCD_ << alphaQED_ << ounit(minpT_,GeV)
<< preQCDqqbarq_ << preQCDqqbarqbar_ << preQCDqg_ << preQCDgqbar_
<< preQEDqqbarq_ << preQEDqqbarqbar_ << preQEDqgq_ << preQEDgqbarqbar_
<< scaleChoice_ << scalePreFactor_;
}
void MEPP2GammaGammaPowheg::persistentInput(PersistentIStream & is, int) {
is >> FFPvertex_ >> FFGvertex_
>> contrib_ >> power_ >> gluon_ >> prefactor_
>> process_ >> threeBodyProcess_ >> maxflavour_
>> alphaS_ >> fixedAlphaS_
>> supressionFunction_ >> supressionScale_ >> iunit(lambda_,GeV)
>> alphaQCD_ >> alphaQED_ >> iunit(minpT_,GeV)
>> preQCDqqbarq_ >> preQCDqqbarqbar_ >> preQCDqg_ >> preQCDgqbar_
>> preQEDqqbarq_ >> preQEDqqbarqbar_ >> preQEDqgq_ >> preQEDgqbarqbar_
>> scaleChoice_ >> scalePreFactor_;
}
void MEPP2GammaGammaPowheg::Init() {
static ClassDocumentation<MEPP2GammaGammaPowheg> documentation
("TheMEPP2GammaGammaPowheg class implements gamma gamma production at NLO");
static Switch<MEPP2GammaGammaPowheg,unsigned int> interfaceProcess
("Process",
"Which processes to include",
&MEPP2GammaGammaPowheg::process_, 0, false, false);
static SwitchOption interfaceProcessAll
(interfaceProcess,
"All",
"Include all the processes",
0);
static SwitchOption interfaceProcessGammaGamma
(interfaceProcess,
"GammaGamma",
"Only include gamma gamma",
1);
static SwitchOption interfaceProcessVJet
(interfaceProcess,
"VJet",
"Only include gamma + jet",
2);
static SwitchOption interfaceProcessHard
(interfaceProcess,
"Hard",
"Only include hard radiation contributions",
3);
static Switch<MEPP2GammaGammaPowheg,unsigned int> interfaceThreeBodyProcess
("ThreeBodyProcess",
"The possible three body processes to include",
&MEPP2GammaGammaPowheg::threeBodyProcess_, 0, false, false);
static SwitchOption interfaceThreeBodyProcessAll
(interfaceThreeBodyProcess,
"All",
"Include all processes",
0);
static SwitchOption interfaceThreeBodyProcessqqbar
(interfaceThreeBodyProcess,
"qqbar",
"Only include q qbar -> gamma gamma g processes",
1);
static SwitchOption interfaceThreeBodyProcessqg
(interfaceThreeBodyProcess,
"qg",
"Only include q g -> gamma gamma q processes",
2);
static SwitchOption interfaceThreeBodyProcessgqbar
(interfaceThreeBodyProcess,
"gqbar",
"Only include g qbar -> gamma gamma qbar processes",
3);
static Switch<MEPP2GammaGammaPowheg,unsigned int> interfaceContribution
("Contribution",
"Which contributions to the cross section to include",
&MEPP2GammaGammaPowheg::contrib_, 1, false, false);
static SwitchOption interfaceContributionLeadingOrder
(interfaceContribution,
"LeadingOrder",
"Just generate the leading order cross section",
0);
static SwitchOption interfaceContributionPositiveNLO
(interfaceContribution,
"PositiveNLO",
"Generate the positive contribution to the full NLO cross section",
1);
static SwitchOption interfaceContributionNegativeNLO
(interfaceContribution,
"NegativeNLO",
"Generate the negative contribution to the full NLO cross section",
2);
static Parameter<MEPP2GammaGammaPowheg,int> interfaceMaximumFlavour
("MaximumFlavour",
"The maximum flavour allowed for the incoming quarks",
&MEPP2GammaGammaPowheg::maxflavour_, 5, 1, 5,
false, false, Interface::limited);
static Parameter<MEPP2GammaGammaPowheg,double> interfaceAlphaS
("AlphaS",
"The value of alphaS to use if using a fixed alphaS",
&MEPP2GammaGammaPowheg::alphaS_, 0.118, 0.0, 0.2,
false, false, Interface::limited);
static Switch<MEPP2GammaGammaPowheg,bool> interfaceFixedAlphaS
("FixedAlphaS",
"Use a fixed value of alphaS",
&MEPP2GammaGammaPowheg::fixedAlphaS_, false, false, false);
static SwitchOption interfaceFixedAlphaSYes
(interfaceFixedAlphaS,
"Yes",
"Use a fixed alphaS",
true);
static SwitchOption interfaceFixedAlphaSNo
(interfaceFixedAlphaS,
"No",
"Use a running alphaS",
false);
static Switch<MEPP2GammaGammaPowheg,unsigned int> interfaceSupressionFunction
("SupressionFunction",
"Choice of the supression function",
&MEPP2GammaGammaPowheg::supressionFunction_, 0, false, false);
static SwitchOption interfaceSupressionFunctionNone
(interfaceSupressionFunction,
"None",
"Default POWHEG approach",
0);
static SwitchOption interfaceSupressionFunctionThetaFunction
(interfaceSupressionFunction,
"ThetaFunction",
"Use theta functions at scale Lambda",
1);
static SwitchOption interfaceSupressionFunctionSmooth
(interfaceSupressionFunction,
"Smooth",
"Supress high pT by pt^2/(pt^2+lambda^2)",
2);
static Parameter<MEPP2GammaGammaPowheg,Energy> interfaceSupressionScale
("SupressionScale",
"The square of the scale for the supression function",
&MEPP2GammaGammaPowheg::lambda_, GeV, 20.0*GeV, 0.0*GeV, 0*GeV,
false, false, Interface::lowerlim);
static Switch<MEPP2GammaGammaPowheg,unsigned int> interfaceSupressionScaleChoice
("SupressionScaleChoice",
"Choice of the supression scale",
&MEPP2GammaGammaPowheg::supressionScale_, 0, false, false);
static SwitchOption interfaceSupressionScaleChoiceFixed
(interfaceSupressionScaleChoice,
"Fixed",
"Use a fixed scale",
0);
static SwitchOption interfaceSupressionScaleChoiceVariable
(interfaceSupressionScaleChoice,
"Variable",
"Use the pT of the hard process as the scale",
1);
static Reference<MEPP2GammaGammaPowheg,ShowerAlpha> interfaceShowerAlphaQCD
("ShowerAlphaQCD",
"Reference to the object calculating the QCD coupling for the shower",
&MEPP2GammaGammaPowheg::alphaQCD_, false, false, true, false, false);
static Reference<MEPP2GammaGammaPowheg,ShowerAlpha> interfaceShowerAlphaQED
("ShowerAlphaQED",
"Reference to the object calculating the QED coupling for the shower",
&MEPP2GammaGammaPowheg::alphaQED_, false, false, true, false, false);
static Parameter<MEPP2GammaGammaPowheg,double> interfacepreQCDqqbarq
("preQCDqqbarq",
"The constant for the Sudakov overestimate for the "
"q qbar -> V Gamma +g with emission from the q",
&MEPP2GammaGammaPowheg::preQCDqqbarq_, 23.0, 0.0, 1000.0,
false, false, Interface::limited);
static Parameter<MEPP2GammaGammaPowheg,double> interfacepreQCDqqbarqbar
("preQCDqqbarqbar",
"The constant for the Sudakov overestimate for the "
"q qbar -> V Gamma +g with emission from the qbar",
&MEPP2GammaGammaPowheg::preQCDqqbarqbar_, 23.0, 0.0, 1000.0,
false, false, Interface::limited);
static Switch<MEPP2GammaGammaPowheg,unsigned int> interfaceScaleChoice
("ScaleChoice",
"The scale choice to use",
&MEPP2GammaGammaPowheg::scaleChoice_, 0, false, false);
static SwitchOption interfaceScaleChoicepT
(interfaceScaleChoice,
"pT",
"Use the pT of the photons",
0);
static SwitchOption interfaceScaleChoiceMGammaGamma
(interfaceScaleChoice,
"MGammaGamma",
"Use the mass of the photon pair",
1);
static Parameter<MEPP2GammaGammaPowheg,double> interfaceScalePreFactor
("ScalePreFactor",
"Prefactor to change factorization/renormalisation scale",
&MEPP2GammaGammaPowheg::scalePreFactor_, 1.0, 0.1, 10.0,
false, false, Interface::limited);
// prefactor_.push_back(preQCDqg_);
// prefactor_.push_back(preQCDgqbar_);
// prefactor_.push_back(preQEDqqbarq_);
// prefactor_.push_back(preQEDqqbarqbar_);
// prefactor_.push_back(preQEDqgq_);
// prefactor_.push_back(preQEDgqbarqbar_);
}
double MEPP2GammaGammaPowheg::NLOWeight() const {
// if leading-order return
if(contrib_==0) return loME_;
// prefactors
CFfact_ = 4./3.*alphaS_/Constants::twopi;
TRfact_ = 1./2.*alphaS_/Constants::twopi;
// scale
Energy2 mu2 = scale();
// virtual pieces
double virt = CFfact_*subtractedVirtual();
// extract the partons and stuff for the real emission
// and collinear counter terms
// hadrons
pair<tcBeamPtr,tcBeamPtr> hadrons=
make_pair(dynamic_ptr_cast<tcBeamPtr>(lastParticles().first->dataPtr() ),
dynamic_ptr_cast<tcBeamPtr>(lastParticles().second->dataPtr()));
// momentum fractions
pair<double,double> x = make_pair(lastX1(),lastX2());
// partons
pair<tcPDPtr,tcPDPtr> partons = make_pair(mePartonData()[0],mePartonData()[1]);
// If necessary swap the particle data objects so that
// first beam gives the incoming quark
if(lastPartons().first ->dataPtr()!=partons.first) {
swap(x.first,x.second);
swap(hadrons.first,hadrons.second);
}
// convert the values of z tilde to z
pair<double,double> z;
pair<double,double> zJac;
double rhomax(pow(1.-x.first,1.-power_));
double rho = zTilde_*rhomax;
z.first = 1.-pow(rho,1./(1.-power_));
zJac.first = rhomax*pow(1.-z.first,power_)/(1.-power_);
rhomax = pow(1.-x.second,1.-power_);
rho = zTilde_*rhomax;
z.second = 1.-pow(rho,1./(1.-power_));
zJac.second = rhomax*pow(1.-z.second,power_)/(1.-power_);
// calculate the PDFs
pair<double,double> oldqPDF =
make_pair(hadrons.first ->pdf()->xfx(hadrons.first ,partons.first ,scale(),
x.first )/x.first ,
hadrons.second->pdf()->xfx(hadrons.second,partons.second,scale(),
x.second)/x.second);
// real/coll q/qbar
pair<double,double> newqPDF =
make_pair(hadrons.first ->pdf()->xfx(hadrons.first ,partons.first ,scale(),
x.first /z.first )*z.first /x.first ,
hadrons.second->pdf()->xfx(hadrons.second,partons.second,scale(),
x.second/z.second)*z.second/x.second);
// real/coll gluon
pair<double,double> newgPDF =
make_pair(hadrons.first ->pdf()->xfx(hadrons.first ,gluon_,scale(),
x.first /z.first )*z.first /x.first ,
hadrons.second->pdf()->xfx(hadrons.second,gluon_,scale(),
x.second/z.second)*z.second/x.second);
// coll terms
// g -> q
double collGQ = collinearGluon(mu2,zJac.first,z.first,
oldqPDF.first,newgPDF.first);
// g -> qbar
double collGQbar = collinearGluon(mu2,zJac.second,z.second,
oldqPDF.second,newgPDF.second);
// q -> q
double collQQ = collinearQuark(x.first ,mu2,zJac.first ,z.first ,
oldqPDF.first ,newqPDF.first );
// qbar -> qbar
double collQbarQbar = collinearQuark(x.second,mu2,zJac.second,z.second,
oldqPDF.second,newqPDF.second);
// collinear remnants
double coll = collQQ+collQbarQbar+collGQ+collGQbar;
// real emission contribution
double real1 = subtractedReal(x,z. first,zJac. first,oldqPDF. first,
newqPDF. first,newgPDF. first, true);
double real2 = subtractedReal(x,z.second,zJac.second,oldqPDF.second,
newqPDF.second,newgPDF.second,false);
// the total weight
double wgt = loME_ + loME_*virt + loME_*coll + real1 + real2;
return contrib_ == 1 ? max(0.,wgt) : max(0.,-wgt);
}
double MEPP2GammaGammaPowheg::loGammaGammaME(const cPDVector & particles,
const vector<Lorentz5Momentum> & momenta,
bool first) const {
double output(0.);
// analytic formula for speed
if(!first) {
Energy2 th = (momenta[0]-momenta[2]).m2();
Energy2 uh = (momenta[0]-momenta[3]).m2();
output = 4./3.*Constants::pi*SM().alphaEM(ZERO)*(th/uh+uh/th)*
pow(double(particles[0]->iCharge())/3.,4);
}
// HE code result
else {
// wavefunctions for the incoming fermions
SpinorWaveFunction em_in( momenta[0],particles[0],incoming);
SpinorBarWaveFunction ep_in( momenta[1],particles[1],incoming);
// wavefunctions for the outgoing bosons
VectorWaveFunction v1_out(momenta[2],particles[2],outgoing);
VectorWaveFunction v2_out(momenta[3],particles[3],outgoing);
vector<SpinorWaveFunction> f1;
vector<SpinorBarWaveFunction> a1;
vector<VectorWaveFunction> v1,v2;
// calculate the wavefunctions
for(unsigned int ix=0;ix<2;++ix) {
em_in.reset(ix);
f1.push_back(em_in);
ep_in.reset(ix);
a1.push_back(ep_in);
v1_out.reset(2*ix);
v1.push_back(v1_out);
v2_out.reset(2*ix);
v2.push_back(v2_out);
}
vector<double> me(4,0.0);
me_.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1,PDT::Spin1));
vector<Complex> diag(2,0.0);
SpinorWaveFunction inter;
for(unsigned int ihel1=0;ihel1<2;++ihel1) {
for(unsigned int ihel2=0;ihel2<2;++ihel2) {
for(unsigned int ohel1=0;ohel1<2;++ohel1) {
for(unsigned int ohel2=0;ohel2<2;++ohel2) {
inter = FFPvertex_->evaluate(ZERO,5,f1[ihel1].particle(),
f1[ihel1],v1[ohel1]);
diag[0] = FFPvertex_->evaluate(ZERO,inter,a1[ihel2],v2[ohel2]);
inter = FFPvertex_->evaluate(ZERO,5,f1[ihel1].particle(),
f1[ihel1] ,v2[ohel2]);
diag[1] = FFPvertex_->evaluate(ZERO,inter,a1[ihel2],v1[ohel1]);
// individual diagrams
for (size_t ii=0; ii<2; ++ii) me[ii] += std::norm(diag[ii]);
// full matrix element
diag[0] += diag[1];
output += std::norm(diag[0]);
// storage of the matrix element for spin correlations
me_(ihel1,ihel2,2*ohel1,2*ohel2) = diag[0];
}
}
}
}
// store diagram info, etc.
DVector save(3);
for (size_t i = 0; i < 3; ++i) save[i] = 0.25 * me[i];
meInfo(save);
// spin and colour factors
output *= 0.125/3./norm(FFPvertex_->norm());
}
return output;
}
double MEPP2GammaGammaPowheg::loGammaqME(const cPDVector & particles,
const vector<Lorentz5Momentum> & momenta,
bool first) const {
double output(0.);
// analytic formula for speed
if(!first) {
Energy2 sh = (momenta[0]+momenta[1]).m2();
Energy2 th = (momenta[0]-momenta[2]).m2();
Energy2 uh = (momenta[0]-momenta[3]).m2();
output = -1./3./sh/th*(sh*sh+th*th+2.*uh*(sh+th+uh))*
4.*Constants::pi*SM().alphaEM(ZERO)*
sqr(particles[0]->iCharge()/3.);
}
// HE result
else {
vector<SpinorWaveFunction> fin;
vector<VectorWaveFunction> gin;
vector<SpinorBarWaveFunction> fout;
vector<VectorWaveFunction> vout;
SpinorWaveFunction qin (momenta[0],particles[0],incoming);
VectorWaveFunction glin(momenta[1],particles[1],incoming);
VectorWaveFunction wout(momenta[2],particles[2],outgoing);
SpinorBarWaveFunction qout(momenta[3],particles[3],outgoing);
// polarization states for the particles
for(unsigned int ix=0;ix<2;++ix) {
qin.reset(ix) ;
fin.push_back(qin);
qout.reset(ix);
fout.push_back(qout);
glin.reset(2*ix);
gin.push_back(glin);
wout.reset(2*ix);
vout.push_back(wout);
}
me_.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1,
PDT::Spin1,PDT::Spin1Half));
// compute the matrix elements
double me[3]={0.,0.,0.};
Complex diag[2];
SpinorWaveFunction inters;
SpinorBarWaveFunction interb;
for(unsigned int ihel1=0;ihel1<2;++ihel1) {
for(unsigned int ihel2=0;ihel2<2;++ihel2) {
for(unsigned int ohel1=0;ohel1<2;++ohel1) {
// intermediates for the diagrams
interb= FFGvertex_->evaluate(scale(),5,particles[3],
fout[ohel1],gin[ihel2]);
inters= FFGvertex_->evaluate(scale(),5,particles[0],
fin[ihel1],gin[ihel2]);
for(unsigned int vhel=0;vhel<2;++vhel) {
diag[0] = FFPvertex_->evaluate(ZERO,fin[ihel1],interb,vout[vhel]);
diag[1] = FFPvertex_->evaluate(ZERO,inters,fout[ohel1],vout[vhel]);
// diagram contributions
me[1] += norm(diag[0]);
me[2] += norm(diag[1]);
// total
diag[0] += diag[1];
me[0] += norm(diag[0]);
me_(ihel1,2*ihel2,2*vhel,ohel1) = diag[0];
}
}
}
}
// results
// initial state spin and colour average
double colspin = 1./24./4.;
// and C_F N_c from matrix element
colspin *= 4.;
DVector save;
for(unsigned int ix=0;ix<3;++ix) {
me[ix] *= colspin;
if(ix>0) save.push_back(me[ix]);
}
meInfo(save);
output = me[0]/norm(FFGvertex_->norm());
}
return output;
}
double MEPP2GammaGammaPowheg::loGammaqbarME(const cPDVector & particles,
const vector<Lorentz5Momentum> & momenta,
bool first) const {
double output(0.);
// analytic formula for speed
if(!first) {
Energy2 sh = (momenta[0]+momenta[1]).m2();
Energy2 uh = (momenta[0]-momenta[2]).m2();
Energy2 th = (momenta[0]-momenta[3]).m2();
output = -1./3./sh/th*(sh*sh+th*th+2.*uh*(sh+th+uh))*
4.*Constants::pi*SM().alphaEM()*
sqr(particles[1]->iCharge()/3.);
}
// HE result
else {
vector<SpinorBarWaveFunction> ain;
vector<VectorWaveFunction> gin;
vector<SpinorWaveFunction> aout;
vector<VectorWaveFunction> vout;
VectorWaveFunction glin (momenta[0],particles[0],incoming);
SpinorBarWaveFunction qbin (momenta[1],particles[1],incoming);
VectorWaveFunction wout (momenta[2],particles[2],outgoing);
SpinorWaveFunction qbout(momenta[3],particles[3],outgoing);
// polarization states for the particles
for(unsigned int ix=0;ix<2;++ix) {
qbin .reset(ix );
ain .push_back(qbin );
qbout.reset(ix );
aout.push_back(qbout);
glin.reset(2*ix);
gin.push_back(glin);
wout.reset(2*ix);
vout.push_back(wout);
}
// if calculation spin corrections construct the me
me_.reset(ProductionMatrixElement(PDT::Spin1,PDT::Spin1Half,
PDT::Spin1,PDT::Spin1Half));
// compute the matrix elements
double me[3]={0.,0.,0.};
Complex diag[2];
SpinorWaveFunction inters;
SpinorBarWaveFunction interb;
for(unsigned int ihel1=0;ihel1<2;++ihel1) {
for(unsigned int ihel2=0;ihel2<2;++ihel2) {
for(unsigned int ohel1=0;ohel1<2;++ohel1) {
// intermediates for the diagrams
inters= FFGvertex_->evaluate(scale(),5,particles[3],
aout[ohel1],gin[ihel1]);
interb= FFGvertex_->evaluate(scale(),5,particles[1],
ain[ihel2],gin[ihel1]);
for(unsigned int vhel=0;vhel<2;++vhel) {
diag[0]= FFPvertex_->evaluate(ZERO,inters,ain[ihel2],vout[vhel]);
diag[1]= FFPvertex_->evaluate(ZERO,aout[ohel1],interb,vout[vhel]);
// diagram contributions
me[1] += norm(diag[0]);
me[2] += norm(diag[1]);
// total
diag[0] += diag[1];
me[0] += norm(diag[0]);
me_(2*ihel1,ihel2,2*vhel,ohel1) = diag[0];
}
}
}
}
// results
// initial state spin and colour average
double colspin = 1./24./4.;
// and C_F N_c from matrix element
colspin *= 4.;
DVector save;
for(unsigned int ix=0;ix<3;++ix) {
me[ix] *= colspin;
if(ix>0) save.push_back(me[ix]);
}
meInfo(save);
output = me[0]/norm(FFGvertex_->norm());
}
return output;
}
double MEPP2GammaGammaPowheg::loGammagME(const cPDVector & particles,
const vector<Lorentz5Momentum> & momenta,
bool first) const {
double output(0.);
// analytic formula for speed
if(!first) {
Energy2 uh = (momenta[0]-momenta[2]).m2();
Energy2 th = (momenta[0]-momenta[3]).m2();
output = 8./9.*double((th*th+uh*uh)/uh/th)*
4.*Constants::pi*SM().alphaEM(ZERO)*
sqr(particles[0]->iCharge()/3.);
}
else {
vector<SpinorWaveFunction> fin;
vector<SpinorBarWaveFunction> ain;
vector<VectorWaveFunction> gout;
vector<VectorWaveFunction> vout;
SpinorWaveFunction qin (momenta[0],particles[0],incoming);
SpinorBarWaveFunction qbin(momenta[1],particles[1],incoming);
VectorWaveFunction wout(momenta[2],particles[2],outgoing);
VectorWaveFunction glout(momenta[3],particles[3],outgoing);
// polarization states for the particles
for(unsigned int ix=0;ix<2;++ix) {
qin.reset(ix) ;
fin.push_back(qin);
qbin.reset(ix) ;
ain.push_back(qbin);
glout.reset(2*ix);
gout.push_back(glout);
wout.reset(2*ix);
vout.push_back(wout);
}
// if calculation spin corrections construct the me
if(first) me_.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1,PDT::Spin1));
// compute the matrix elements
double me[3]={0.,0.,0.};
Complex diag[2];
SpinorWaveFunction inters;
SpinorBarWaveFunction interb;
for(unsigned int ihel1=0;ihel1<2;++ihel1) {
for(unsigned int ihel2=0;ihel2<2;++ihel2) {
for(unsigned int ohel1=0;ohel1<2;++ohel1) {
// intermediates for the diagrams
inters= FFGvertex_->evaluate(scale(),5,particles[0],
fin[ihel1],gout[ohel1]);
interb= FFGvertex_->evaluate(scale(),5,particles[1],
ain[ihel2],gout[ohel1]);
for(unsigned int vhel=0;vhel<2;++vhel) {
diag[0]= FFPvertex_->evaluate(ZERO,fin[ihel1],interb,vout[vhel]);
diag[1]= FFPvertex_->evaluate(ZERO,inters,ain[ihel2],vout[vhel]);
// diagram contributions
me[1] += norm(diag[0]);
me[2] += norm(diag[1]);
// total
diag[0] += diag[1];
me[0] += norm(diag[0]);
if(first) me_(ihel1,ihel2,vhel,2*ohel1) = diag[0];
}
}
}
}
// results
// initial state spin and colour average
double colspin = 1./9./4.;
// and C_F N_c from matrix element
colspin *= 4.;
DVector save;
for(unsigned int ix=0;ix<3;++ix) {
me[ix] *= colspin;
if(ix>0) save.push_back(me[ix]);
}
meInfo(save);
output = me[0]/norm(FFGvertex_->norm());
}
return output;
}
InvEnergy2 MEPP2GammaGammaPowheg::
realGammaGammagME(const cPDVector & particles,
const vector<Lorentz5Momentum> & momenta,
DipoleType dipole, RadiationType rad,
bool ) const {
// matrix element
double sum = realME(particles,momenta);
// loop over the QCD and QCD dipoles
InvEnergy2 dipoles[2];
pair<double,double> supress[2];
// compute the two dipole terms
unsigned int iemit = 4, ihard = 3;
double x = (momenta[0]*momenta[1]-momenta[iemit]*momenta[1]-
momenta[iemit]*momenta[0])/(momenta[0]*momenta[1]);
Lorentz5Momentum Kt = momenta[0]+momenta[1]-momenta[iemit];
vector<Lorentz5Momentum> pa(4),pb(4);
// momenta for q -> q g/gamma emission
pa[0] = x*momenta[0];
pa[1] = momenta[1];
Lorentz5Momentum K = pa[0]+pa[1];
Lorentz5Momentum Ksum = K+Kt;
Energy2 K2 = K.m2();
Energy2 Ksum2 = Ksum.m2();
pa[2] = momenta[2]-2.*Ksum*(Ksum*momenta[2])/Ksum2+2*K*(Kt*momenta[2])/K2;
pa[2].setMass(momenta[2].mass());
pa[3] = momenta[ihard]
-2.*Ksum*(Ksum*momenta[ihard])/Ksum2+2*K*(Kt*momenta[ihard])/K2;
pa[3].setMass(ZERO);
cPDVector part(particles.begin(),--particles.end());
part[3] = particles[ihard];
// first leading-order matrix element
double lo1 = loGammaGammaME(part,pa);
// first dipole
dipoles[0] = 1./(momenta[0]*momenta[iemit])/x*(2./(1.-x)-(1.+x))*lo1;
supress[0] = supressionFunction(momenta[iemit].perp(),pa[3].perp());
// momenta for qbar -> qbar g/gamma emission
pb[0] = momenta[0];
pb[1] = x*momenta[1];
K = pb[0]+pb[1];
Ksum = K+Kt;
K2 = K.m2();
Ksum2 = Ksum.m2();
pb[2] = momenta[2]-2.*Ksum*(Ksum*momenta[2])/Ksum2+2*K*(Kt*momenta[2])/K2;
pb[2].setMass(momenta[2].mass());
pb[3] = momenta[ihard]
-2.*Ksum*(Ksum*momenta[ihard])/Ksum2+2*K*(Kt*momenta[ihard])/K2;
pb[3].setMass(ZERO);
// second LO matrix element
double lo2 = loGammaGammaME(part,pb);
// second dipole
dipoles[1] = 1./(momenta[1]*momenta[iemit])/x*(2./(1.-x)-(1.+x))*lo2;
supress[1] = supressionFunction(momenta[iemit].perp(),pb[3].perp());
for(unsigned int ix=0;ix<2;++ix) dipoles[ix] *= 4./3.;
// denominator for the matrix element
InvEnergy2 denom = abs(dipoles[0]) + abs(dipoles[1]);
// contribution
if( denom==ZERO || dipoles[(dipole-1)/2]==ZERO ) return ZERO;
sum *= abs(dipoles[(dipole-1)/2])/denom;
// final coupling factors
InvEnergy2 output;
if(rad==Subtraction) {
output = alphaS_*alphaEM_*
(sum*UnitRemoval::InvE2*supress[(dipole-1)/2].first
- dipoles[(dipole-1)/2]);
}
else {
output = alphaS_*alphaEM_*sum*UnitRemoval::InvE2;
if(rad==Hard) output *=supress[(dipole-1)/2].second;
else if(rad==Shower) output *=supress[(dipole-1)/2].first ;
}
return output;
}
InvEnergy2 MEPP2GammaGammaPowheg::realGammaGammaqME(const cPDVector & particles,
const vector<Lorentz5Momentum> & momenta,
DipoleType dipole, RadiationType rad,
bool ) const {
double sum = realME(particles,momenta);
// initial-state QCD dipole
double x = (momenta[0]*momenta[1]-momenta[4]*momenta[1]-
momenta[4]*momenta[0])/(momenta[0]*momenta[1]);
Lorentz5Momentum Kt = momenta[0]+momenta[1]-momenta[4];
vector<Lorentz5Momentum> pa(4);
pa[0] = momenta[0];
pa[1] = x*momenta[1];
Lorentz5Momentum K = pa[0]+pa[1];
Lorentz5Momentum Ksum = K+Kt;
Energy2 K2 = K.m2();
Energy2 Ksum2 = Ksum.m2();
pa[2] = momenta[2]-2.*Ksum*(Ksum*momenta[2])/Ksum2+2*K*(Kt*momenta[2])/K2;
pa[2].setMass(momenta[2].mass());
pa[3] = momenta[3]
-2.*Ksum*(Ksum*momenta[3])/Ksum2+2*K*(Kt*momenta[3])/K2;
pa[3].setMass(ZERO);
cPDVector part(particles.begin(),--particles.end());
part[1] = particles[4]->CC();
double lo1 = loGammaGammaME(part,pa);
InvEnergy2 D1 = 0.5/(momenta[1]*momenta[4])/x*(1.-2.*x*(1.-x))*lo1;
// initial-final QED dipole
vector<Lorentz5Momentum> pb(4);
x = 1.-(momenta[3]*momenta[4])/(momenta[4]*momenta[0]+momenta[0]*momenta[3]);
pb[3] = momenta[4]+momenta[3]-(1.-x)*momenta[0];
pb[0] = x*momenta[0];
pb[1] = momenta[1];
pb[2] = momenta[2];
double z = momenta[0]*momenta[3]/(momenta[0]*momenta[3]+momenta[0]*momenta[4]);
part[1] = particles[1];
part[3] = particles[4];
double lo2 = loGammaqME(part,pb);
Energy pT = sqrt(-(pb[0]-pb[3]).m2()*(1.-x)*(1.-z)*z/x);
InvEnergy2 DF = 1./(momenta[4]*momenta[3])/x*(1./(1.-x+z)-2.+z)*lo2;
InvEnergy2 DI = 1./(momenta[0]*momenta[3])/x*(1./(1.-x+z)-1.-x)*lo2;
DI *= sqr(double(particles[0]->iCharge())/3.);
DF *= sqr(double(particles[0]->iCharge())/3.);
InvEnergy2 denom = abs(D1)+abs(DI)+abs(DF);
pair<double,double> supress;
InvEnergy2 term;
if ( dipole == IFQED1 ) {
term = DI;
supress = supressionFunction(pT,pb[3].perp());
}
else if( dipole == FIQED1 ) {
term = DF;
supress = supressionFunction(pT,pb[3].perp());
}
else {
term = D1;
supress = supressionFunction(momenta[4].perp(),pa[3].perp());
}
if( denom==ZERO || term == ZERO ) return ZERO;
sum *= abs(term)/denom;
// final coupling factors
InvEnergy2 output;
if(rad==Subtraction) {
output = alphaS_*alphaEM_*
(sum*UnitRemoval::InvE2*supress.first - term);
}
else {
output = alphaS_*alphaEM_*sum*UnitRemoval::InvE2;
if(rad==Hard) output *= supress.second;
else if(rad==Shower) output *= supress.first ;
}
// final coupling factors
return output;
}
InvEnergy2 MEPP2GammaGammaPowheg::
realGammaGammaqbarME(const cPDVector & particles,
const vector<Lorentz5Momentum> & momenta,
DipoleType dipole, RadiationType rad,
bool) const {
double sum = realME(particles,momenta);
// initial-state QCD dipole
double x = (momenta[0]*momenta[1]-momenta[4]*momenta[1]-momenta[4]*momenta[0])/
(momenta[0]*momenta[1]);
Lorentz5Momentum Kt = momenta[0]+momenta[1]-momenta[4];
vector<Lorentz5Momentum> pa(4);
pa[0] = x*momenta[0];
pa[1] = momenta[1];
Lorentz5Momentum K = pa[0]+pa[1];
Lorentz5Momentum Ksum = K+Kt;
Energy2 K2 = K.m2();
Energy2 Ksum2 = Ksum.m2();
pa[2] = momenta[2]-2.*Ksum*(Ksum*momenta[2])/Ksum2+2*K*(Kt*momenta[2])/K2;
pa[2].setMass(momenta[2].mass());
pa[3] = momenta[3]
-2.*Ksum*(Ksum*momenta[3])/Ksum2+2*K*(Kt*momenta[3])/K2;
pa[3].setMass(ZERO);
cPDVector part(particles.begin(),--particles.end());
part[0] = particles[4]->CC();
double lo1 = loGammaGammaME(part,pa);
InvEnergy2 D1 = 0.5/(momenta[0]*momenta[4])/x*(1.-2.*x*(1.-x))*lo1;
// initial-final QED dipole
vector<Lorentz5Momentum> pb(4);
x = 1.-(momenta[3]*momenta[4])/(momenta[4]*momenta[1]+momenta[1]*momenta[3]);
pb[3] = momenta[4]+momenta[3]-(1.-x)*momenta[1];
pb[0] = momenta[0];
pb[1] = x*momenta[1];
pb[2] = momenta[2];
double z = momenta[1]*momenta[3]/(momenta[1]*momenta[3]+momenta[1]*momenta[4]);
part[0] = particles[0];
part[3] = particles[4];
double lo2 = loGammaqbarME(part,pb);
Energy pT = sqrt(-(pb[1]-pb[3]).m2()*(1.-x)*(1.-z)*z/x);
InvEnergy2 DF = 1./(momenta[4]*momenta[3])/x*(2./(1.-x+z)-2.+z)*lo2;
InvEnergy2 DI = 1./(momenta[0]*momenta[3])/x*(2./(1.-x+z)-1.-x)*lo2;
InvEnergy2 term;
DI *= sqr(double(particles[1]->iCharge())/3.);
DF *= sqr(double(particles[1]->iCharge())/3.);
InvEnergy2 denom = abs(D1)+abs(DI)+abs(DF);
pair<double,double> supress;
if ( dipole == IFQED2 ) {
term = DI;
supress = supressionFunction(pT,pb[3].perp());
}
else if( dipole == FIQED2 ) {
term = DF;
supress = supressionFunction(pT,pb[3].perp());
}
else {
term = D1;
supress = supressionFunction(momenta[4].perp(),pa[3].perp());
}
if( denom==ZERO || dipole==ZERO ) return ZERO;
sum *= abs(term)/denom;
// final coupling factors
InvEnergy2 output;
if(rad==Subtraction) {
output = alphaS_*alphaEM_*
(sum*UnitRemoval::InvE2*supress.first - term);
}
else {
output = alphaS_*alphaEM_*sum*UnitRemoval::InvE2;
if(rad==Hard) output *= supress.second;
else if(rad==Shower) output *= supress.first ;
}
// final coupling factors
return output;
}
double MEPP2GammaGammaPowheg::
realME(const cPDVector & particles,
const vector<Lorentz5Momentum> & momenta) const {
vector<SpinorWaveFunction> qin;
vector<SpinorBarWaveFunction> qbarin;
vector<VectorWaveFunction> wout,pout,gout;
SpinorWaveFunction q_in;
SpinorBarWaveFunction qbar_in;
VectorWaveFunction g_out;
VectorWaveFunction v_out (momenta[2],particles[2],outgoing);
VectorWaveFunction p_out (momenta[3],particles[3],outgoing);
// q qbar -> gamma gamma g
if(particles[4]->id()==ParticleID::g) {
q_in = SpinorWaveFunction (momenta[0],particles[0],incoming);
qbar_in = SpinorBarWaveFunction (momenta[1],particles[1],incoming);
g_out = VectorWaveFunction (momenta[4],particles[4],outgoing);
}
// q g -> gamma gamma q
else if(particles[4]->id()>0) {
q_in = SpinorWaveFunction (momenta[0],particles[0],incoming);
qbar_in = SpinorBarWaveFunction (momenta[4],particles[4],outgoing);
g_out = VectorWaveFunction (momenta[1],particles[1],incoming);
}
else if(particles[4]->id()<0) {
q_in = SpinorWaveFunction (momenta[4],particles[4],outgoing);
qbar_in = SpinorBarWaveFunction (momenta[1],particles[1],incoming);
g_out = VectorWaveFunction (momenta[0],particles[0],incoming);
}
else assert(false);
for(unsigned int ix=0;ix<2;++ix) {
q_in.reset(ix);
qin.push_back(q_in);
qbar_in.reset(ix);
qbarin.push_back(qbar_in);
g_out.reset(2*ix);
gout.push_back(g_out);
p_out.reset(2*ix);
pout.push_back(p_out);
v_out.reset(2*ix);
wout.push_back(v_out);
}
vector<Complex> diag(6 , 0.);
Energy2 mu2 = scale();
double sum(0.);
for(unsigned int ihel1=0;ihel1<2;++ihel1) {
for(unsigned int ihel2=0;ihel2<2;++ihel2) {
for(unsigned int whel=0;whel<2;++whel) {
for(unsigned int phel=0;phel<2;++phel) {
for(unsigned int ghel=0;ghel<2;++ghel) {
// first diagram
SpinorWaveFunction inters1 =
FFPvertex_->evaluate(ZERO,5,qin[ihel1].particle(),qin[ihel1],pout[phel]);
SpinorBarWaveFunction inters2 =
FFPvertex_->evaluate(ZERO,5,qin[ihel1].particle()->CC(),
qbarin[ihel2],wout[whel]);
diag[0] = FFGvertex_->evaluate(mu2,inters1,inters2,gout[ghel]);
// second diagram
SpinorWaveFunction inters3 =
FFGvertex_->evaluate(mu2,5,qin[ihel1].particle(),qin[ihel1],gout[ghel]);
SpinorBarWaveFunction inters4 =
FFPvertex_->evaluate(ZERO,5,qbarin[ihel2].particle(),
qbarin[ihel2],pout[phel]);
diag[1] = FFPvertex_->evaluate(ZERO,inters3,inters4,wout[whel]);
// fourth diagram
diag[2] = FFPvertex_->evaluate(ZERO,inters3,inters2,pout[phel]);
// fifth diagram
SpinorBarWaveFunction inters5 =
FFGvertex_->evaluate(mu2,5,qbarin[ihel2].particle(),
qbarin[ihel2],gout[ghel]);
diag[3] =
FFPvertex_->evaluate(ZERO,inters1,inters5,wout[whel]);
// sixth diagram
SpinorWaveFunction inters6 =
FFPvertex_->evaluate(ZERO,5,qbarin[ihel2].particle()->CC(),
qin[ihel1],wout[whel]);
diag[4] = FFGvertex_->evaluate(mu2,inters6,inters4,gout[ghel]);
// eighth diagram
diag[5] = FFPvertex_->evaluate(ZERO,inters6,inters5,pout[phel]);
// sum
Complex dsum = std::accumulate(diag.begin(),diag.end(),Complex(0.));
sum += norm(dsum);
}
}
}
}
}
// divide out the em and strong couplings
sum /= norm(FFGvertex_->norm()*FFPvertex_->norm());
// final spin and colour factors spin = 1/4 colour = 4/9
if(particles[4]->id()==ParticleID::g) sum /= 9.;
// final spin and colour factors spin = 1/4 colour = 4/(3*8)
else sum /= 24.;
// finally identical particle factor
return 0.5*sum;
}
double MEPP2GammaGammaPowheg::subtractedVirtual() const {
double v = 1+tHat()/sHat();
double born = (1-v)/v+v/(1-v);
double finite_term = born*
(2./3.*sqr(Constants::pi)-3.+sqr(log(v))+sqr(log(1-v))+3.*log(1-v))+
2.+2.*log(v)+2.*log(1-v)+3.*(1-v)/v*(log(v)-log(1-v))+
(2.+v/(1-v))*sqr(log(v))+(2.+(1-v)/v)*sqr(log(1-v));
double virt = ((6.-(2./3.)*sqr(Constants::pi))*
born-2.+finite_term);
return virt/born;
}
double MEPP2GammaGammaPowheg::subtractedReal(pair<double,double> x, double z,
double zJac, double oldqPDF, double newqPDF,
double newgPDF,bool order) const {
double vt = vTilde_*(1.-z);
double vJac = 1.-z;
Energy pT = sqrt(sHat()*vt*(1.-vt-z)/z);
// rapidities
double rapidity;
if(order) {
rapidity = -log(x.second*sqrt(lastS())/pT*vt);
}
else {
rapidity = log(x.first *sqrt(lastS())/pT*vt);
}
// CMS system
Energy rs=sqrt(lastS());
Lorentz5Momentum pcmf = Lorentz5Momentum(ZERO,ZERO,0.5*rs*(x.first-x.second),
0.5*rs*(x.first+x.second));
pcmf.rescaleMass();
Boost blab(pcmf.boostVector());
// emission from the quark radiation
vector<Lorentz5Momentum> pnew(5);
if(order) {
pnew [0] = Lorentz5Momentum(ZERO,ZERO,0.5*rs*x.first/z,
0.5*rs*x.first/z,ZERO);
pnew [1] = Lorentz5Momentum(ZERO,ZERO,-0.5*rs*x.second,
0.5*rs*x.second,ZERO) ;
}
else {
pnew[0] = Lorentz5Momentum(ZERO,ZERO,0.5*rs*x.first,
0.5*rs*x.first,ZERO);
pnew[1] = Lorentz5Momentum(ZERO,ZERO,-0.5*rs*x.second/z,
0.5*rs*x.second/z,ZERO) ;
}
pnew [2] = meMomenta()[2];
pnew [3] = meMomenta()[3];
pnew [4] = Lorentz5Momentum(pT*cos(phi_),pT*sin(phi_),
pT*sinh(rapidity),
pT*cosh(rapidity), ZERO);
Lorentz5Momentum K = pnew [0]+pnew [1]-pnew [4];
Lorentz5Momentum Kt = pcmf;
Lorentz5Momentum Ksum = K+Kt;
Energy2 K2 = K.m2();
Energy2 Ksum2 = Ksum.m2();
for(unsigned int ix=2;ix<4;++ix) {
pnew [ix].boost(blab);
pnew [ix] = pnew [ix] - 2.*Ksum*(Ksum*pnew [ix])/Ksum2
+2*K*(Kt*pnew [ix])/K2;
}
// phase-space prefactors
double phase = zJac*vJac/z;
// real emission q qbar
vector<double> output(4,0.);
double realQQ(0.),realGQ(0.);
if(!(zTilde_<1e-7 || vt<1e-7 || 1.-z-vt < 1e-7 )) {
cPDVector particles(mePartonData());
particles.push_back(gluon_);
// calculate the full 2->3 matrix element
realQQ = sHat()*phase*newqPDF/oldqPDF*
realGammaGammagME(particles,pnew,order ? IIQCD1 : IIQCD2,Subtraction,false);
if(order) {
particles[0] = gluon_;
particles[4] = mePartonData()[0]->CC();
realGQ = sHat()*phase*newgPDF/oldqPDF*
realGammaGammaqbarME(particles,pnew,IIQCD2,Subtraction,false);
}
else {
particles[1] = gluon_;
particles[4] = mePartonData()[1]->CC();
realGQ = sHat()*phase*newgPDF/oldqPDF*
realGammaGammaqME (particles,pnew,IIQCD1,Subtraction,false);
}
}
// return the answer
return realQQ+realGQ;
}
double MEPP2GammaGammaPowheg::collinearQuark(double x, Energy2 mu2, double jac, double z,
double oldPDF, double newPDF) const {
if(1.-z < 1.e-8) return 0.;
return CFfact_*(
// this bit is multiplied by LO PDF
sqr(Constants::pi)/3.-5.+2.*sqr(log(1.-x ))
+(1.5+2.*log(1.-x ))*log(sHat()/mu2)
// NLO PDF bit
+jac /z * newPDF /oldPDF *
(1.-z -(1.+z )*log(sqr(1.-z )/z )
-(1.+z )*log(sHat()/mu2)-2.*log(z )/(1.-z ))
// + function bit
+jac /z *(newPDF /oldPDF -z )*
2./(1.-z )*log(sHat()*sqr(1.-z )/mu2));
}
double MEPP2GammaGammaPowheg::collinearGluon(Energy2 mu2, double jac, double z,
double oldPDF, double newPDF) const {
if(1.-z < 1.e-8) return 0.;
return TRfact_*jac/z*newPDF/oldPDF*
((sqr(z)+sqr(1.-z))*log(sqr(1.-z)*sHat()/z/mu2)
+2.*z*(1.-z));
}
void MEPP2GammaGammaPowheg::doinit() {
HwMEBase::doinit();
vector<unsigned int> mopt(2,1);
massOption(mopt);
// get the vertices we need
// get a pointer to the standard model object in the run
static const tcHwSMPtr hwsm
= dynamic_ptr_cast<tcHwSMPtr>(standardModel());
if (!hwsm) throw InitException() << "hwsm pointer is null in"
<< " MEPP2GammaGamma::doinit()"
<< Exception::abortnow;
// get pointers to all required Vertex objects
FFPvertex_ = hwsm->vertexFFP();
FFGvertex_ = hwsm->vertexFFG();
gluon_ = getParticleData(ParticleID::g);
// sampling factors
prefactor_.push_back(preQCDqqbarq_);
prefactor_.push_back(preQCDqqbarqbar_);
prefactor_.push_back(preQCDqg_);
prefactor_.push_back(preQCDgqbar_);
prefactor_.push_back(preQEDqqbarq_);
prefactor_.push_back(preQEDqqbarqbar_);
prefactor_.push_back(preQEDqgq_);
prefactor_.push_back(preQEDgqbarqbar_);
}
RealEmissionProcessPtr MEPP2GammaGammaPowheg::
generateHardest(RealEmissionProcessPtr born,
- ShowerInteraction::Type inter) {
+ ShowerInteraction inter) {
beams_.clear();
partons_.clear();
bool QCDAllowed = inter !=ShowerInteraction::QED;
bool QEDAllowed = inter !=ShowerInteraction::QCD;
// find the incoming particles
// and get the particles to be showered
ParticleVector incoming,particlesToShower;
pair<double,double> x;
for(unsigned int ix=0;ix<born->bornIncoming().size();++ix) {
incoming.push_back( born->bornIncoming()[ix] );
beams_.push_back(dynamic_ptr_cast<tcBeamPtr>(born->hadrons()[ix]->dataPtr()));
partons_.push_back( born->bornIncoming()[ix]->dataPtr() );
particlesToShower.push_back( born->bornIncoming()[ix] );
if(ix==0) x.first = incoming.back()->momentum().rho()/born->hadrons()[ix]->momentum().rho();
else x.second = incoming.back()->momentum().rho()/born->hadrons()[ix]->momentum().rho();
}
// find the parton which should be first
if( ( particlesToShower[1]->id() > 0 && particlesToShower[0]->id() < 0 ) ||
( particlesToShower[0]->id() == ParticleID::g &&
particlesToShower[1]->id() < 6 && particlesToShower[1]->id() > 0 ) ) {
swap(particlesToShower[0],particlesToShower[1]);
swap(partons_[0],partons_[1]);
swap(beams_ [0],beams_ [1]);
swap(x.first ,x.second );
}
// check that quark is along +ve z direction
quarkplus_ = particlesToShower[0]->momentum().z() > ZERO;
// outgoing partons
for(unsigned int ix=0;ix<born->bornOutgoing().size();++ix) {
particlesToShower.push_back( born->bornOutgoing()[ix] );
}
if(particlesToShower.size()!=4) return RealEmissionProcessPtr();
if(particlesToShower[2]->id()!=ParticleID::gamma)
swap(particlesToShower[2],particlesToShower[3]);
if(particlesToShower[3]->id()==ParticleID::gamma) {
if(QCDAllowed) return hardQCDEmission(born,particlesToShower,x);
}
else {
if(QEDAllowed) return hardQEDEmission(born,particlesToShower,x);
}
return born;
}
RealEmissionProcessPtr MEPP2GammaGammaPowheg::
hardQCDEmission(RealEmissionProcessPtr born,
ParticleVector particlesToShower,
pair<double,double> x) {
Energy rootS = sqrt(lastS());
// limits on the rapidity of the jet
double minyj = -8.0,maxyj = 8.0;
// generate the hard emission
vector<Energy> pT;
Energy pTmax(-GeV);
cPDVector selectedParticles;
vector<Lorentz5Momentum> selectedMomenta;
int iemit(-1);
for(unsigned int ix=0;ix<4;++ix) {
pT.push_back(0.5*generator()->maximumCMEnergy());
double a = alphaQCD_->overestimateValue()/Constants::twopi*
prefactor_[ix]*(maxyj-minyj);
cPDVector particles;
for(unsigned int iy=0;iy<particlesToShower.size();++iy)
particles.push_back(particlesToShower[iy]->dataPtr());
if(ix<2) particles.push_back(gluon_);
else if(ix==2) {
particles.push_back(particles[0]->CC());
particles[0] = gluon_;
}
else {
particles.push_back(particles[1]->CC());
particles[1] = gluon_;
}
vector<Lorentz5Momentum> momenta(5);
do {
pT[ix] *= pow(UseRandom::rnd(),1./a);
double y = UseRandom::rnd()*(maxyj-minyj)+ minyj;
double vt,z;
if(ix%2==0) {
vt = pT[ix]*exp(-y)/rootS/x.second;
z = (1.-pT[ix]*exp(-y)/rootS/x.second)/(1.+pT[ix]*exp( y)/rootS/x.first );
if(z>1.||z<x.first) continue;
}
else {
vt = pT[ix]*exp( y)/rootS/x.first ;
z = (1.-pT[ix]*exp( y)/rootS/x.first )/(1.+pT[ix]*exp(-y)/rootS/x.second );
if(z>1.||z<x.second) continue;
}
if(vt>1.-z || vt<0.) continue;
if(ix%2==0) {
momenta[0] = particlesToShower[0]->momentum()/z;
momenta[1] = particlesToShower[1]->momentum();
}
else {
momenta[0] = particlesToShower[0]->momentum();
momenta[1] = particlesToShower[1]->momentum()/z;
}
double phi = Constants::twopi*UseRandom::rnd();
momenta[2] = particlesToShower[2]->momentum();
momenta[3] = particlesToShower[3]->momentum();
if(!quarkplus_) y *= -1.;
momenta[4] = Lorentz5Momentum(pT[ix]*cos(phi),pT[ix]*sin(phi),
pT[ix]*sinh(y),pT[ix]*cosh(y), ZERO);
Lorentz5Momentum K = momenta[0] + momenta[1] - momenta[4];
Lorentz5Momentum Kt = momenta[2]+momenta[3];
Lorentz5Momentum Ksum = K+Kt;
Energy2 K2 = K.m2(), Ksum2 = Ksum.m2();
for(unsigned int iy=2;iy<4;++iy) {
momenta [iy] = momenta [iy] - 2.*Ksum*(Ksum*momenta [iy])/Ksum2
+2*K*(Kt*momenta [iy])/K2;
}
// matrix element piece
double wgt = alphaQCD_->ratio(sqr(pT[ix]))*z/(1.-vt)/prefactor_[ix]/loME_;
if(ix==0)
wgt *= sqr(pT[ix])*realGammaGammagME(particles,momenta,IIQCD1,Shower,false);
else if(ix==1)
wgt *= sqr(pT[ix])*realGammaGammagME(particles,momenta,IIQCD2,Shower,false);
else if(ix==2)
wgt *= sqr(pT[ix])*realGammaGammaqbarME(particles,momenta,IIQCD1,Shower,false);
else if(ix==3)
wgt *= sqr(pT[ix])*realGammaGammaqME(particles,momenta,IIQCD2,Shower,false);
wgt *= 4.*Constants::pi/alphaS_;
// pdf piece
double pdf[2];
if(ix%2==0) {
pdf[0] = beams_[0]->pdf()->xfx(beams_[0],partons_ [0],
scale(), x.first ) /x.first;
pdf[1] = beams_[0]->pdf()->xfx(beams_[0],particles[0],
scale()+sqr(pT[ix]),x.first /z)*z/x.first;
}
else {
pdf[0] = beams_[1]->pdf()->xfx(beams_[1],partons_ [1],
scale() ,x.second ) /x.second;
pdf[1] = beams_[1]->pdf()->xfx(beams_[1],particles[1],
scale()+sqr(pT[ix]),x.second/z)*z/x.second;
}
if(pdf[0]<=0.||pdf[1]<=0.) continue;
wgt *= pdf[1]/pdf[0];
if(wgt>1.) generator()->log() << "Weight greater than one in "
<< "MEPP2GammaGammaPowheg::hardQCDEmission() "
<< "for channel " << ix
<< " Weight = " << wgt << "\n";
if(UseRandom::rnd()<wgt) break;
}
while(pT[ix]>minpT_);
if(pT[ix]>minpT_ && pT[ix]>pTmax) {
pTmax = pT[ix];
selectedParticles = particles;
selectedMomenta = momenta;
iemit=ix;
}
}
// if no emission
if(pTmax<ZERO) {
born->pT()[ShowerInteraction::QCD] = minpT_;
return born;
}
// construct the HardTree object needed to perform the showers
// create the partons
ParticleVector newparticles;
newparticles.push_back(selectedParticles[0]->produceParticle(selectedMomenta[0]));
newparticles.push_back(selectedParticles[1]->produceParticle(selectedMomenta[1]));
for(unsigned int ix=2;ix<particlesToShower.size();++ix) {
newparticles.push_back(particlesToShower[ix]->dataPtr()->
produceParticle(selectedMomenta[ix]));
}
newparticles.push_back(selectedParticles[4]->produceParticle(selectedMomenta[4]));
// identify the type of process
// gluon emission
if(newparticles.back()->id()==ParticleID::g) {
newparticles[4]->incomingColour(newparticles[0]);
newparticles[4]->incomingColour(newparticles[1],true);
}
// quark
else if(newparticles.back()->id()>0) {
iemit=1;
newparticles[4]->incomingColour(newparticles[1]);
newparticles[1]-> colourConnect(newparticles[0]);
}
// antiquark
else {
iemit=0;
newparticles[4]->incomingColour(newparticles[0],true);
newparticles[1]-> colourConnect(newparticles[0]);
}
// add incoming
int ispect = iemit==0 ? 1 : 0;
if(particlesToShower[0]==born->bornIncoming()[0]) {
born->incoming().push_back(newparticles[0]);
born->incoming().push_back(newparticles[1]);
}
else {
born->incoming().push_back(newparticles[1]);
born->incoming().push_back(newparticles[0]);
swap(iemit,ispect);
}
// add the outgoing
for(unsigned int ix=2;ix<newparticles.size();++ix)
born->outgoing().push_back(newparticles[ix]);
// emitter spectator etc
born->emitter (iemit );
born->spectator(ispect);
born->emitted(4);
// x values
pair<double,double> xnew;
for(unsigned int ix=0;ix<2;++ix) {
double x = born->incoming()[ix]->momentum().rho()/born->hadrons()[ix]->momentum().rho();
if(ix==0) xnew.first = x;
else xnew.second = x;
}
born->x(xnew);
// max pT
born->pT()[ShowerInteraction::QCD] = pTmax;
born->interaction(ShowerInteraction::QCD);
// return the process
return born;
}
RealEmissionProcessPtr MEPP2GammaGammaPowheg::
hardQEDEmission(RealEmissionProcessPtr born,
ParticleVector particlesToShower,
pair<double,double> x) {
// return if not emission from quark
if(particlesToShower[0]->id()!=ParticleID::g &&
particlesToShower[1]->id()!=ParticleID::g )
return RealEmissionProcessPtr();
// generate the hard emission
vector<Energy> pT;
Energy pTmax(-GeV);
cPDVector selectedParticles;
vector<Lorentz5Momentum> selectedMomenta;
int iemit(-1);
pair<double,double> mewgt(make_pair(0.,0.));
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
selectedParticles.push_back(particlesToShower[ix]->dataPtr());
selectedMomenta.push_back(particlesToShower[ix]->momentum());
}
selectedParticles.push_back(getParticleData(ParticleID::gamma));
swap(selectedParticles[3],selectedParticles[4]);
selectedMomenta.push_back(Lorentz5Momentum());
swap(selectedMomenta[3],selectedMomenta[4]);
Lorentz5Momentum pin,pout;
double xB;
unsigned int iloc;
if(particlesToShower[0]->dataPtr()->charged()) {
pin = particlesToShower[0]->momentum();
xB = x.first;
iloc = 6;
}
else {
pin = particlesToShower[1]->momentum();
xB = x.second;
iloc = 7;
}
pout = particlesToShower[3]->momentum();
Lorentz5Momentum q = pout-pin;
Axis axis(q.vect().unit());
LorentzRotation rot;
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
rot = LorentzRotation();
if(axis.perp2()>1e-20) {
rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
rot.rotateX(Constants::pi);
}
if(abs(1.-q.e()/q.vect().mag())>1e-6)
rot.boostZ(q.e()/q.vect().mag());
Lorentz5Momentum ptemp = rot*pin;
if(ptemp.perp2()/GeV2>1e-20) {
Boost trans = -1./ptemp.e()*ptemp.vect();
trans.setZ(0.);
rot.boost(trans);
}
rot.invert();
Energy Q = sqrt(-q.m2());
double xT = sqrt((1.-xB)/xB);
double xTMin = 2.*minpT_/Q;
double wgt(0.);
double a = alphaQED_->overestimateValue()*prefactor_[iloc]/Constants::twopi;
Lorentz5Momentum p1,p2,p3;
do {
wgt = 0.;
// intergration variables dxT/xT^3
xT *= 1./sqrt(1.-2.*log(UseRandom::rnd())/a*sqr(xT));
// dz
double zp = UseRandom::rnd();
double xp = 1./(1.+0.25*sqr(xT)/zp/(1.-zp));
if(xT<xTMin) break;
// check allowed
if(xp<xB||xp>1.) continue;
// phase-space piece of the weight
wgt = 4.*sqr(1.-xp)*(1.-zp)*zp/prefactor_[iloc]/loME_;
// coupling
Energy2 pT2 = 0.25*sqr(Q*xT);
wgt *= alphaQED_->ratio(pT2);
// matrix element
wgt *= 4.*Constants::pi/alphaEM_;
// PDF
double pdf[2];
if(iloc==6) {
pdf[0] = beams_[0]->pdf()->
xfx(beams_[0],partons_[0],scale() ,x.first );
pdf[1] = beams_[0]->pdf()->
xfx(beams_[0],partons_[0],scale()+pT2,x.first /xp);
}
else {
pdf[0] = beams_[1]->pdf()->
xfx(beams_[1],partons_[1],scale() ,x.second );
pdf[1] = beams_[1]->pdf()->
xfx(beams_[1],partons_[1],scale()+pT2,x.second/xp);
}
if(pdf[0]<=0.||pdf[1]<=0.) {
wgt = 0.;
continue;
}
wgt *= pdf[1]/pdf[0];
// matrix element piece
double phi = Constants::twopi*UseRandom::rnd();
double x2 = 1.-(1.-zp)/xp;
double x3 = 2.-1./xp-x2;
p1=Lorentz5Momentum(ZERO,ZERO,0.5*Q/xp,0.5*Q/xp,ZERO);
p2=Lorentz5Momentum( 0.5*Q*xT*cos(phi), 0.5*Q*xT*sin(phi),
-0.5*Q*x2,0.5*Q*sqrt(sqr(xT)+sqr(x2)));
p3=Lorentz5Momentum(-0.5*Q*xT*cos(phi),-0.5*Q*xT*sin(phi),
-0.5*Q*x3,0.5*Q*sqrt(sqr(xT)+sqr(x3)));
selectedMomenta[iloc-6] = rot*p1;
selectedMomenta[3] = rot*p3;
selectedMomenta[4] = rot*p2;
if(iloc==6) {
mewgt.first =
sqr(Q)*realGammaGammaqME(selectedParticles,selectedMomenta,IFQED1,Shower,false);
mewgt.second =
sqr(Q)*realGammaGammaqME(selectedParticles,selectedMomenta,FIQED1,Shower,false);
wgt *= mewgt.first+mewgt.second;
}
else {
mewgt.first =
sqr(Q)*realGammaGammaqbarME(selectedParticles,selectedMomenta,IFQED2,Shower,false);
mewgt.second =
sqr(Q)*realGammaGammaqbarME(selectedParticles,selectedMomenta,FIQED2,Shower,false);
wgt *= mewgt.first+mewgt.second;
}
if(wgt>1.) generator()->log() << "Weight greater than one in "
<< "MEPP2GammaGammaPowheg::hardQEDEmission() "
<< "for IF channel "
<< " Weight = " << wgt << "\n";
}
while(xT>xTMin&&UseRandom::rnd()>wgt);
// if no emission
if(xT<xTMin) {
born->pT()[ShowerInteraction::QED] = minpT_;
return born;
}
pTmax = 0.5*xT*Q;
iemit = mewgt.first>mewgt.second ? 2 : 3;
// construct the object needed to perform the showers
// create the partons
ParticleVector newparticles;
newparticles.push_back(selectedParticles[0]->produceParticle(selectedMomenta[0]));
newparticles.push_back(selectedParticles[1]->produceParticle(selectedMomenta[1]));
for(unsigned int ix=2;ix<particlesToShower.size();++ix) {
newparticles.push_back(particlesToShower[ix]->
dataPtr()->produceParticle(selectedMomenta[ix==2 ? 2 : 4 ]));
}
newparticles.push_back(selectedParticles[3]->produceParticle(selectedMomenta[3]));
// make the colour connections
bool col = newparticles[3]->id()<0;
if(particlesToShower[0]->dataPtr()->charged()) {
newparticles[3]->incomingColour(newparticles[1],col);
newparticles[1]->colourConnect (newparticles[0],col);
}
else {
newparticles[3]->incomingColour(newparticles[0],col);
newparticles[0]->colourConnect (newparticles[1],col);
}
bool FSR = iemit==3;
// add incoming particles
if(particlesToShower[0]==born->bornIncoming()[0]) {
born->incoming().push_back(newparticles[0]);
born->incoming().push_back(newparticles[1]);
}
else {
born->incoming().push_back(newparticles[1]);
born->incoming().push_back(newparticles[0]);
}
// IS radiatng particle
unsigned int iemitter = born->incoming()[0]->dataPtr()->charged() ? 0 : 1;
// add outgoing particles
if(particlesToShower[2]==born->bornOutgoing()[0]) {
born->outgoing().push_back(newparticles[2]);
born->outgoing().push_back(newparticles[3]);
}
else {
born->outgoing().push_back(newparticles[3]);
born->outgoing().push_back(newparticles[2]);
}
born->outgoing().push_back(newparticles[4]);
// outgoing radiating particle
unsigned int ispectator = born->outgoing()[0]->dataPtr()->charged() ? 2 : 3;
// get emitter and spectator right
if(FSR) swap(iemitter,ispectator);
born->emitter (iemitter );
born->spectator(ispectator);
born->emitted(4);
// x values
pair<double,double> xnew;
for(unsigned int ix=0;ix<2;++ix) {
double x = born->incoming()[ix]->momentum().rho()/born->hadrons()[ix]->momentum().rho();
if(ix==0) xnew.first = x;
else xnew.second = x;
}
born->x(xnew);
// max pT
born->pT()[ShowerInteraction::QED] = pTmax;
// return the process
born->interaction(ShowerInteraction::QED);
return born;
}
diff --git a/MatrixElement/Powheg/MEPP2GammaGammaPowheg.h b/MatrixElement/Powheg/MEPP2GammaGammaPowheg.h
--- a/MatrixElement/Powheg/MEPP2GammaGammaPowheg.h
+++ b/MatrixElement/Powheg/MEPP2GammaGammaPowheg.h
@@ -1,542 +1,542 @@
// -*- C++ -*-
#ifndef HERWIG_MEPP2GammaGammaPowheg_H
#define HERWIG_MEPP2GammaGammaPowheg_H
//
// This is the declaration of the MEPP2GammaGammaPowheg class.
//
#include "Herwig/MatrixElement/HwMEBase.h"
#include "ThePEG/Helicity/Vertex/Vector/FFVVertex.h"
#include "Herwig/MatrixElement/ProductionMatrixElement.h"
#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h"
namespace Herwig {
using namespace ThePEG;
/**
* Here is the documentation of the MEPP2GammaGammaPowheg class.
*
* @see \ref MEPP2GammaGammaPowhegInterfaces "The interfaces"
* defined for MEPP2GammaGammaPowheg.
*/
class MEPP2GammaGammaPowheg: public HwMEBase {
enum DipoleType { IIQCD1=2, IIQCD2=4,
IFQED1=5, FIQED1=6, IFQED2=7, FIQED2=8 };
enum RadiationType {Subtraction,Hard,Shower};
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
MEPP2GammaGammaPowheg();
//@}
/** @name Member functions for the generation of hard QCD radiation */
//@{
/**
* Has a POWHEG style correction
*/
virtual POWHEGType hasPOWHEGCorrection() {return ISR;}
/**
* Apply the POWHEG style correction
*/
virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr,
- ShowerInteraction::Type);
+ ShowerInteraction);
//@}
public:
/** @name Virtual functions required by the MEBase class. */
//@{
/**
* Return the order in \f$\alpha_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaS() const;
/**
* Return the order in \f$\alpha_{EW}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInAlphaEW() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* The number of internal degrees of freedom used in the matrix
* element.
*/
virtual int nDim() const;
/**
* Generate internal degrees of freedom given nDim() uniform
* random numbers in the interval \f$ ]0,1[ \f$. To help the phase space
* generator, the dSigHatDR should be a smooth function of these
* numbers, although this is not strictly necessary.
* @param r a pointer to the first of nDim() consecutive random numbers.
* @return true if the generation succeeded, otherwise false.
*/
virtual bool generateKinematics(const double * r);
/**
* Return the matrix element squared differential in the variables
* given by the last call to generateKinematics().
*/
virtual CrossSection dSigHatDR() const;
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
/**
* Get diagram selector. With the information previously supplied with the
* setKinematics method, a derived class may optionally
* override this method to weight the given diagrams with their
* (although certainly not physical) relative probabilities.
* @param dv the diagrams to be weighted.
* @return a Selector relating the given diagrams to their weights.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
* @param diag the diagram chosen.
* @return the possible colour geometries weighted by their
* relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) 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:
/**
* Calculate of the full next-to-leading order weight
*/
virtual double NLOWeight() const;
/**
* Leading-order matrix element for \f$q\bar q\to \gamma\gamma\f$
*/
double loGammaGammaME(const cPDVector & particles,
const vector<Lorentz5Momentum> & momenta,
bool first=false) const;
/**
* Leading-order matrix element for \f$qg\to \gamma q\f$
*/
double loGammaqME(const cPDVector & particles,
const vector<Lorentz5Momentum> & momenta,
bool first=false) const;
/**
* Leading-order matrix element for \f$g\bar q\to \gamma \bar q\f$
*/
double loGammaqbarME(const cPDVector & particles,
const vector<Lorentz5Momentum> & momenta,
bool first=false) const;
/**
* Leading-order matrix element for \f$q\bar q\to \gamma g\f$
*/
double loGammagME(const cPDVector & particles,
const vector<Lorentz5Momentum> & momenta,
bool first=false) const;
/**
* Real emission matrix element for \f$q\bar q\to \gamma \gamma g\f$
*/
InvEnergy2 realGammaGammagME(const cPDVector & particles,
const vector<Lorentz5Momentum> & momenta,
DipoleType dipole, RadiationType rad,
bool first=false) const;
/**
* Real emission matrix element for \f$qg\to \gamma \gamma q\f$
*/
InvEnergy2 realGammaGammaqME(const cPDVector & particles,
const vector<Lorentz5Momentum> & momenta,
DipoleType dipole, RadiationType rad,
bool first=false) const;
/**
* Real emission matrix element for \f$g\bar q\to \gamma \gamma \bar q\f$
*/
InvEnergy2 realGammaGammaqbarME(const cPDVector & particles,
const vector<Lorentz5Momentum> & momenta,
DipoleType dipole, RadiationType rad,
bool first=false) const;
/**
* The dipole subtractedvirtual contribution
*/
double subtractedVirtual() const;
/**
* Subtracted real contribution
*/
double subtractedReal(pair<double,double> x, double z,
double zJac, double oldqPDF, double newqPDF,
double newgPDF,bool order) const;
/**
* Calculate of the collinear counterterms
*/
//@{
/**
* Quark collinear counter term
*/
double collinearQuark(double x, Energy2 mu2, double jac, double z,
double oldPDF, double newPDF) const;
/**
* Gluon collinear counter term
*/
double collinearGluon(Energy2 mu2, double jac, double z,
double oldPDF, double newPDF) const;
//@}
/**
* The real matrix element divided by \f$2 g_S^2\f$, to be implemented in the
* inheriting classes.
* @param particles The ParticleData objects of the particles
* @param momenta The momenta of the particles
*/
double realME(const cPDVector & particles,
const vector<Lorentz5Momentum> & momenta) const;
/**
* Generate hard QCD emission
*/
RealEmissionProcessPtr hardQCDEmission(RealEmissionProcessPtr,
ParticleVector,
pair<double,double>);
/**
* Generate hard QED emission
*/
RealEmissionProcessPtr hardQEDEmission(RealEmissionProcessPtr,
ParticleVector,
pair<double,double>);
/**
* The supression function
*/
pair<double,double> supressionFunction(Energy pT,Energy scale) const {
if(supressionScale_==0) scale = lambda_;
Energy2 scale2 = sqr(scale), pT2 = sqr(pT);
switch( supressionFunction_ ) {
case 0:
return make_pair(1.,0.);
case 1:
if(pT < scale ) return make_pair(1.,0.);
else return make_pair(0.,1.);
case 2:
return make_pair(scale2/(pT2+scale2),pT2/(pT2+scale2));
default:
assert(false);
}
}
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();
//@}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEPP2GammaGammaPowheg & operator=(const MEPP2GammaGammaPowheg &);
private:
/**
* Vertices
*/
//@{
/**
* FFPVertex
*/
AbstractFFVVertexPtr FFPvertex_;
/**
* FFGVertex
*/
AbstractFFVVertexPtr FFGvertex_;
//@}
/**
* Kinematic variables for the real radiation
*/
//@{
/**
* First variable
*/
mutable double zTilde_;
/**
* Second variable
*/
mutable double vTilde_;
/**
* Azimuthal angle
*/
mutable double phi_;
//@}
/**
* Whether to generate the positive, negative or leading order contribution
*/
unsigned int contrib_;
/**
* Power for sampling \f$x_p\f$
*/
double power_;
/**
* Pointer to the gluon ParticleData object
*/
tcPDPtr gluon_;
/**
* Processes
*/
unsigned int process_;
/**
* Processes
*/
unsigned int threeBodyProcess_;
/**
* Allowed flavours of the incoming quarks
*/
int maxflavour_;
/**
* Factor for \f$C_F\f$ dependent pieces
*/
mutable double CFfact_;
/**
* Factor for \f$T_R\f$ dependent pieces
*/
mutable double TRfact_;
/**
* Strong coupling
*/
mutable double alphaS_;
/**
* Use a fixed value of \f$\alpha_S\f$
*/
bool fixedAlphaS_;
/**
* Electromagnetic coupling
*/
mutable double alphaEM_;
/**
* Leading-order matrix element
*/
mutable double loME_;
/**
* The matrix element
*/
mutable ProductionMatrixElement me_;
/**
* the selected dipole
*/
mutable DipoleType dipole_;
/**
* Supression Function
*/
//@{
/**
* Choice of the supression function
*/
unsigned int supressionFunction_;
/**
* Choice for the scale in the supression function
*/
unsigned int supressionScale_;
/**
* Scalar for the supression function
*/
Energy lambda_;
//@}
/**
* Hard emission stuff
*/
//@{
/**
* Whether the quark is in the + or - z direction
*/
bool quarkplus_;
//@}
/**
* Properties of the incoming particles
*/
//@{
/**
* Pointers to the BeamParticleData objects
*/
vector<tcBeamPtr> beams_;
/**
* Pointers to the ParticleDataObjects for the partons
*/
vector<tcPDPtr> partons_;
//@}
/**
* Constants for the sampling. The distribution is assumed to have the
* form \f$\frac{c}{{\rm GeV}}\times\left(\frac{{\rm GeV}}{p_T}\right)^n\f$
*/
//@{
/**
* The prefactor, \f$c\f$ for the \f$q\bar{q}\f$ channel
*/
double preQCDqqbarq_;
/**
* The prefactor, \f$c\f$ for the \f$q\bar{q}\f$ channel
*/
double preQCDqqbarqbar_;
/**
* The prefactor, \f$c\f$ for the \f$qg\f$ channel
*/
double preQCDqg_;
/**
* The prefactor, \f$c\f$ for the \f$g\bar{q}\f$ channel
*/
double preQCDgqbar_;
double preQEDqqbarq_;
double preQEDqqbarqbar_;
double preQEDqgq_;
double preQEDgqbarqbar_;
/**
* The prefactors as a vector for easy use
*/
vector<double> prefactor_;
//@}
/**
* The transverse momentum of the jet
*/
Energy minpT_;
/**
* Pointer to the object calculating the strong coupling
*/
ShowerAlphaPtr alphaQCD_;
/**
* Pointer to the object calculating the EM
*/
ShowerAlphaPtr alphaQED_;
/**
* Scale choice
*/
unsigned int scaleChoice_;
/**
* Scale factor
*/
double scalePreFactor_;
};
}
#endif /* HERWIG_MEPP2GammaGammaPowheg_H */
diff --git a/MatrixElement/Powheg/MEPP2VVPowheg.cc b/MatrixElement/Powheg/MEPP2VVPowheg.cc
--- a/MatrixElement/Powheg/MEPP2VVPowheg.cc
+++ b/MatrixElement/Powheg/MEPP2VVPowheg.cc
@@ -1,5278 +1,5278 @@
// -*- C++ -*-
//
// MEPP2VVPowheg.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 MEPP2VVPowheg class.
//
#include "MEPP2VVPowheg.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "Herwig/Models/StandardModel/StandardModel.h"
#include "Herwig/MatrixElement/HardVertex.h"
#include "Herwig/Decay/GeneralDecayMatrixElement.h"
#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h"
#include "Herwig/Shower/QTilde/Base/Branching.h"
#include "Herwig/Shower/RealEmissionProcess.h"
using namespace Herwig;
MEPP2VVPowheg::MEPP2VVPowheg() :
tiny(1.e-10), CF_(4./3.), TR_(0.5), NC_(3.),
contrib_(1), channels_(0), nlo_alphaS_opt_(0) , fixed_alphaS_(0.1180346226),
removebr_(1), scaleopt_(1), mu_F_(100.*GeV), mu_UV_(100.*GeV),
ckm_(3,vector<Complex>(3,0.0)),
helicityConservation_(true),
realMESpinCorrelations_(true), power_(2.0),
preqqbar_(3.7),preqg_(16.0),pregqbar_(11.0),
b0_((11.-2./3.*5.)/4./Constants::pi),
LambdaQCD_(91.118*GeV*exp(-1./2./((11.-2./3.*5.)/4./Constants::pi)/0.118)),
min_pT_(2.*GeV){
massOption(vector<unsigned int>(2,1));
}
void MEPP2VVPowheg::persistentOutput(PersistentOStream & os) const {
os << contrib_ << channels_ << nlo_alphaS_opt_ << fixed_alphaS_
<< removebr_ << scaleopt_ << ounit(mu_F_,GeV) << ounit(mu_UV_,GeV)
<< ckm_ << helicityConservation_
<< FFPvertex_ << FFWvertex_ << FFZvertex_ << WWWvertex_ << FFGvertex_
<< realMESpinCorrelations_
<< showerAlphaS_ << power_
<< preqqbar_ << preqg_ << pregqbar_ << prefactor_
<< b0_ << ounit(LambdaQCD_,GeV)
<< ounit( min_pT_,GeV );
}
void MEPP2VVPowheg::persistentInput(PersistentIStream & is, int) {
is >> contrib_ >> channels_ >> nlo_alphaS_opt_ >> fixed_alphaS_
>> removebr_ >> scaleopt_ >> iunit(mu_F_,GeV) >> iunit(mu_UV_,GeV)
>> ckm_ >> helicityConservation_
>> FFPvertex_ >> FFWvertex_ >> FFZvertex_ >> WWWvertex_ >> FFGvertex_
>> realMESpinCorrelations_
>> showerAlphaS_ >> power_
>> preqqbar_ >> preqg_ >> pregqbar_ >> prefactor_
>> b0_ >> iunit(LambdaQCD_,GeV)
>> iunit( min_pT_, GeV );
}
ClassDescription<MEPP2VVPowheg> MEPP2VVPowheg::initMEPP2VVPowheg;
// Definition of the static class description member.
void MEPP2VVPowheg::Init() {
static ClassDocumentation<MEPP2VVPowheg> documentation
("The MEPP2VVPowheg class implements the NLO matrix elements for the production of"
"pairs of electroweak vector bosons.",
"The calcultaion of $W^+W^-$, $W^\\pm Z^0$ and $Z^0Z^0$ production"
" in hadron collisions at next-to-leading order in the POWHEG scheme"
" is described in \\cite{Hamilton:2010mb}.",
"\\bibitem{Hamilton:2010mb}\n"
" K.~Hamilton,\n"
"%``A positive-weight next-to-leading order simulation of weak boson pair\n"
"%production,''\n"
"JHEP {\bf 1101} (2011) 009\n"
"[arXiv:1009.5391 [hep-ph]].\n"
"%%CITATION = JHEPA,1101,009;%%\n");
static Switch<MEPP2VVPowheg,unsigned int> interfaceContribution
("Contribution",
"Which contributions to the cross section to include",
&MEPP2VVPowheg::contrib_, 1, false, false);
static SwitchOption interfaceContributionLeadingOrder
(interfaceContribution,
"LeadingOrder",
"Just generate the leading order cross section",
0);
static SwitchOption interfaceContributionPositiveNLO
(interfaceContribution,
"PositiveNLO",
"Generate the positive contribution to the full NLO cross section",
1);
static SwitchOption interfaceContributionNegativeNLO
(interfaceContribution,
"NegativeNLO",
"Generate the negative contribution to the full NLO cross section",
2);
static Switch<MEPP2VVPowheg,unsigned int> interfaceChannels
("Channels",
"Which channels to include in the cross section",
&MEPP2VVPowheg::channels_, 0, false, false);
static SwitchOption interfaceChannelsAll
(interfaceChannels,
"All",
"All channels required for the full NLO cross section: qqb, qg, gqb",
0);
static SwitchOption interfaceChannelsAnnihilation
(interfaceChannels,
"Annihilation",
"Only include the qqb annihilation channel, omitting qg and gqb channels",
1);
static SwitchOption interfaceChannelsCompton
(interfaceChannels,
"Compton",
"Only include the qg and gqb compton channels, omitting all qqb processes",
2);
static Switch<MEPP2VVPowheg,unsigned int> interfaceNLOalphaSopt
("NLOalphaSopt",
"An option allowing you to supply a fixed value of alpha_S "
"through the FixedNLOAlphaS interface.",
&MEPP2VVPowheg::nlo_alphaS_opt_, 0, false, false);
static SwitchOption interfaceNLOalphaSoptRunningAlphaS
(interfaceNLOalphaSopt,
"RunningAlphaS",
"Use the usual running QCD coupling evaluated at scale mu_UV2()",
0);
static SwitchOption interfaceNLOalphaSoptFixedAlphaS
(interfaceNLOalphaSopt,
"FixedAlphaS",
"Use a constant QCD coupling for comparison/debugging purposes",
1);
static Parameter<MEPP2VVPowheg,double> interfaceFixedNLOalphaS
("FixedNLOalphaS",
"The value of alphaS to use for the nlo weight if nlo_alphaS_opt_=1",
&MEPP2VVPowheg::fixed_alphaS_, 0.1180346226, 0., 1.0,
false, false, Interface::limited);
static Switch<MEPP2VVPowheg,unsigned int> interfaceremovebr
("removebr",
"Whether to multiply the event weights by the MCFM branching ratios",
&MEPP2VVPowheg::removebr_, 1, false, false);
static SwitchOption interfaceProductionCrossSection
(interfaceremovebr,
"true",
"Do not multiply in the branching ratios (default running)",
1);
static SwitchOption interfaceIncludeBRs
(interfaceremovebr,
"false",
"Multiply by MCFM branching ratios for comparison/debugging purposes",
0);
static Switch<MEPP2VVPowheg,unsigned int> interfaceScaleOption
("ScaleOption",
"Option for running / fixing EW and QCD factorization & renormalization scales",
&MEPP2VVPowheg::scaleopt_, 1, false, false);
static SwitchOption interfaceDynamic
(interfaceScaleOption,
"Dynamic",
"QCD factorization & renormalization scales are sqr(pV1+pV2). "
"EW scale is (mV1^2+mV2^2)/2 (similar to MCatNLO)",
1);
static SwitchOption interfaceFixed
(interfaceScaleOption,
"Fixed",
"QCD factorization fixed to value by FactorizationScaleValue."
"EW and QCD renormalization scales fixed by RenormalizationScaleValue.",
2);
static Parameter<MEPP2VVPowheg,Energy> interfaceFactorizationScaleValue
("FactorizationScaleValue",
"Value to use for the QCD factorization scale if fixed scales"
"have been requested with the ScaleOption interface.",
&MEPP2VVPowheg::mu_F_, GeV, 100.0*GeV, 50.0*GeV, 500.0*GeV,
true, false, Interface::limited);
static Parameter<MEPP2VVPowheg,Energy> interfaceRenormalizationScaleValue
("RenormalizationScaleValue",
"Value to use for the EW and QCD renormalization scales if fixed "
"scales have been requested with the ScaleOption interface.",
&MEPP2VVPowheg::mu_UV_, GeV, 100.0*GeV, 50.0*GeV, 500.0*GeV,
true, false, Interface::limited);
static Switch<MEPP2VVPowheg,bool> interfaceSpinCorrelations
("SpinCorrelations",
"Flag to select leading order spin correlations or a "
"calculation taking into account the real NLO effects",
&MEPP2VVPowheg::realMESpinCorrelations_, 1, false, false);
static SwitchOption interfaceSpinCorrelationsLeadingOrder
(interfaceSpinCorrelations,
"LeadingOrder",
"Decay bosons using a leading order 2->2 calculation of the "
"production spin density matrix",
0);
static SwitchOption interfaceSpinCorrelationsRealNLO
(interfaceSpinCorrelations,
"RealNLO",
"Decay bosons using a production spin density matrix which "
"takes into account the effects of real radiation",
1);
static Reference<MEPP2VVPowheg,ShowerAlpha> interfaceCoupling
("Coupling",
"The object calculating the strong coupling constant",
&MEPP2VVPowheg::showerAlphaS_, false, false, true, false, false);
static Parameter<MEPP2VVPowheg,double> interfacePower
("Power",
"The power for the sampling of the matrix elements",
&MEPP2VVPowheg::power_, 2.0, 1.0, 10.0,
false, false, Interface::limited);
static Parameter<MEPP2VVPowheg,double> interfacePrefactorqqbar
("Prefactorqqbar",
"The prefactor for the sampling of the q qbar channel",
&MEPP2VVPowheg::preqqbar_, 5.0, 0.0, 1000.0,
false, false, Interface::limited);
static Parameter<MEPP2VVPowheg,double> interfacePrefactorqg
("Prefactorqg",
"The prefactor for the sampling of the q g channel",
&MEPP2VVPowheg::preqg_, 3.0, 0.0, 1000.0,
false, false, Interface::limited);
static Parameter<MEPP2VVPowheg,double> interfacePrefactorgqbar
("Prefactorgqbar",
"The prefactor for the sampling of the g qbar channel",
&MEPP2VVPowheg::pregqbar_, 3.0, 0.0, 1000.0,
false, false, Interface::limited);
static Parameter<MEPP2VVPowheg, Energy> interfacepTMin
("minPt",
"The pT cut on hardest emision generation"
"2*(1-Beta)*exp(-sqr(intrinsicpT/RMS))/sqr(RMS)",
&MEPP2VVPowheg::min_pT_, GeV, 2.*GeV, ZERO, 100000.0*GeV,
false, false, Interface::limited);
}
Energy2 MEPP2VVPowheg::scale() const {
// N.B. This scale is the electroweak scale!
// It is used in the evaluation of the LO code
// in the MEPP2VV base class. This means it
// should appear in the denominator of the
// NLOweight here and all other LO parts like
// the function for the lumi ratio (Lhat). It
// should also be used for evaluating any EW
// parameters / vertices in the numerator.
// The scaleopt_ == 1 "running" option is
// chosen to be like the MC@NLO one (it ought
// to be more like sHat instead?).
return scaleopt_ == 1 ?
// 0.5*(meMomenta()[2].m2()+meMomenta()[3].m2()) : sqr(mu_UV_);
sHat() : sqr(mu_UV_);
}
Energy2 MEPP2VVPowheg::mu_F2() const {
return scaleopt_ == 1 ?
// ((H_.k1r()).m2()+k1r_perp2_lab_+(H_.k2r()).m2()+k2r_perp2_lab_)/2. : sqr(mu_F_);
sHat() : sqr(mu_F_);
}
Energy2 MEPP2VVPowheg::mu_UV2() const {
return scaleopt_ == 1 ?
// ((H_.k1r()).m2()+k1r_perp2_lab_+(H_.k2r()).m2()+k2r_perp2_lab_)/2. : sqr(mu_UV_);
sHat() : sqr(mu_UV_);
}
void MEPP2VVPowheg::doinit() {
MEPP2VV::doinit();
// get the vertices we need
// get a pointer to the standard model object in the run
static const tcHwSMPtr hwsm
= dynamic_ptr_cast<tcHwSMPtr>(standardModel());
if (!hwsm) throw InitException()
<< "missing hwsm pointer in MEPP2VVPowheg::doinit()"
<< Exception::abortnow;
// get pointers to all required Vertex objects
FFPvertex_ = hwsm->vertexFFP();
FFZvertex_ = hwsm->vertexFFZ();
WWWvertex_ = hwsm->vertexWWW();
FFWvertex_ = hwsm->vertexFFW();
FFGvertex_ = hwsm->vertexFFG();
// get the ckm object
Ptr<StandardCKM>::pointer
theCKM=dynamic_ptr_cast<Ptr<StandardCKM>::pointer>(SM().CKM());
if(!theCKM) throw InitException() << "MEPP2VVPowheg::doinit() "
<< "the CKM object must be the Herwig one"
<< Exception::runerror;
unsigned int ix,iy;
// get the CKM matrix (unsquared for interference)
vector< vector<Complex > > CKM(theCKM->getUnsquaredMatrix(SM().families()));
for(ix=0;ix<3;++ix){for(iy=0;iy<3;++iy){ckm_[ix][iy]=CKM[ix][iy];}}
// insert the different prefactors in the vector for easy look up
prefactor_.push_back(preqqbar_);
prefactor_.push_back(preqg_);
prefactor_.push_back(pregqbar_);
}
int MEPP2VVPowheg::nDim() const {
int output = MEPP2VV::nDim();
// See related comment in MEPP2VVPowheg::generateKinematics!
if(contrib_>0) output += 2;
return output;
}
bool MEPP2VVPowheg::generateKinematics(const double * r) {
// N.B. A fix was made to make theta2 a radiative
// variable in r4532. Originally theta2 was take to
// be the azimuthal angle coming from the generation
// of the Born kinematics inherited from MEPP2VV i.e.
// before the change theta2 was a random number between
// 0 and 2pi. On changing theta2 was set to be
// theta2 = (*(r+3)) * 2.*Constants::pi;
// and nDim returned if(contrib_>0) output += 3;
// In the months following it was noticed that agreement
// with MCFM was per mille at Tevatron energies but got
// close to 1 percent for LHC energies (for all VV
// processes). After searching back up the svn branch
// running 2M events each time, the change was spotted
// to occur on r4532. Changing:
// if(contrib_>0) output += 3;
// in ::nDim() and also,
// xt = (*(r +nDim() -3));
// y = (*(r +nDim() -2)) * 2. - 1.;
// theta2 = (*(r +nDim() -1)) * 2.*Constants::pi;
// did not fix the problem. The following code gives the
// same good level of agreement at LHC and TVT:
double xt( -999.);
double y( -999.);
double theta2( -999.);
if(contrib_>0) {
// Generate the radiative integration variables:
xt = (*(r +nDim() -2));
y = (*(r +nDim() -1)) * 2. - 1.;
// KH 19th August - next line changed for phi in 0->pi not 0->2pi
// theta2 = UseRandom::rnd() * 2.*Constants::pi;
theta2 = UseRandom::rnd() *Constants::pi;
}
// Continue with lo matrix element code:
bool output(MEPP2VV::generateKinematics(r));
// Work out the kinematics for the leading order / virtual process
// and also get the leading order luminosity function:
getKinematics(xt,y,theta2);
return output;
}
double MEPP2VVPowheg::me2() const {
double output(0.0);
useMe();
output = MEPP2VV::me2();
double mcfm_brs(1.);
if(!removebr_) {
switch(MEPP2VV::process()) {
case 1: // W+(->e+,nu_e) W-(->e-,nu_ebar) (MCFM: 61 [nproc])
mcfm_brs *= 0.109338816;
mcfm_brs *= 0.109338816;
break;
case 2: // W+/-(mu+,nu_mu / mu-,nu_mubar) Z(nu_e,nu_ebar)
// (MCFM: 72+77 [nproc])
mcfm_brs *= 0.109338816;
mcfm_brs *= 0.06839002;
break;
case 3: // Z(mu-,mu+) Z(e-,e+) (MCFM: 86 [nproc])
mcfm_brs *= 0.034616433;
mcfm_brs *= 0.034616433;
mcfm_brs *= 2.; // as identical particle factor 1/2 is now obsolete.
break;
case 4: // W+(mu+,nu_mu) Z(nu_e,nu_ebar) (MCFM: 72 [nproc])
mcfm_brs *= 0.109338816;
mcfm_brs *= 0.06839002;
break;
case 5: // W-(mu-,nu_mubar) Z(nu_e,nu_ebar) (MCFM: 77 [nproc])
mcfm_brs *= 0.109338816;
mcfm_brs *= 0.06839002;
break;
}
}
// Store the value of the leading order squared matrix element:
lo_me2_ = output;
output *= NLOweight();
output *= mcfm_brs;
return output;
}
void MEPP2VVPowheg::getKinematics(double xt, double y, double theta2) {
// In this member we want to get the lo_lumi_ as this is a
// common denominator in the NLO weight. We want also the
// bornVVKinematics object and all of the realVVKinematics
// objects needed for the NLO weight.
// Check if the W- is first in W+W- production. Already confirmed
// mePartonData()[0] is a quark, and mePartonData()[1] is an antiquark.
// We assume mePartonData[2] and mePartonData[3] are, respectively,
// W+/- Z, W+/- W-/+, or Z Z.
bool wminus_first(false);
if((mePartonData()[2]->id()==-24)&&(mePartonData()[3]->id()==24))
wminus_first=true;
// Now get all data on the LO process needed for the NLO computation:
// The +z hadron in the lab:
hadron_A_=dynamic_ptr_cast<Ptr<BeamParticleData>::transient_const_pointer>
(lastParticles().first->dataPtr());
// The -z hadron in the lab:
hadron_B_=dynamic_ptr_cast<Ptr<BeamParticleData>::transient_const_pointer>
(lastParticles().second->dataPtr());
// Leading order momentum fractions:
double xa(lastX1()); // The +z momentum fraction in the lab.
double xb(lastX2()); // The -z momentum fraction in the lab.
// Particle data for incoming +z & -z QCD particles respectively:
ab_ = lastPartons().first ->dataPtr(); // The +z momentum parton in the lab.
bb_ = lastPartons().second->dataPtr(); // The -z momentum parton in the lab.
// We checked TVT & LHC for all VV channels with 10K events:
// lastParticles().first ->momentum().z() is always positive
// lastParticles().second->momentum().z() is always negative
// lastParticles().first ->momentum().z()*xa=lastPartons().first ->momentum().z() 1 in 10^6
// lastParticles().second->momentum().z()*xb=lastPartons().second->momentum().z() 1 in 10^6
// Set the quark and antiquark data pointers.
quark_ = mePartonData()[0];
antiquark_ = mePartonData()[1];
if(quark_->id()<0) swap(quark_,antiquark_);
// Now in _our_ calculation we basically define the +z axis as being
// given by the direction of the incoming quark for q+qb & q+g processes
// and the incoming gluon for g+qbar processes. So now we might need to
// flip the values of hadron_A_, hadron_B_, ab_, bb_, xa, xb accordingly:
if(ab_->id()!=quark_->id()) {
swap(hadron_A_,hadron_B_);
swap(ab_,bb_);
swap(xa,xb);
}
// So hadron_A_ is the thing containing a quark (ab_) with momentum frac xa,
// hadron_B_ is the thing containing an antiquark (bb_) with momentum frac xb.
// Now get the partonic flux for the Born process:
lo_lumi_ = hadron_A_->pdf()->xfx(hadron_A_,ab_,scale(),xa)/xa
* hadron_B_->pdf()->xfx(hadron_B_,bb_,scale(),xb)/xb;
// For W+W- events make sure k1 corresponds to the W+ momentum:
if(MEPP2VV::process()==1&&wminus_first) swap(meMomenta()[2],meMomenta()[3]);
// Create the object containing all 2->2 __kinematic__ information:
B_ = bornVVKinematics(meMomenta(),xa,xb);
// We checked that meMomenta()[0] (quark) is in the +z direction and meMomenta()[1]
// is in the -z direction (antiquark).
// Revert momentum swap in case meMomenta and mePartonData correlation
// needs preserving for other things.
if(MEPP2VV::process()==1&&wminus_first) swap(meMomenta()[2],meMomenta()[3]);
// Check the Born kinematics objects is internally consistent:
// B_.sanityCheck();
// If we are going beyond leading order then lets calculate all of
// the necessary real emission kinematics.
if(contrib_>0) {
// Soft limit of the 2->3 real emission kinematics:
S_ = realVVKinematics(B_, 1., y, theta2);
// Soft-collinear limit of the 2->3 kinematics (emission in +z direction):
SCp_ = realVVKinematics(B_, 1., 1., theta2);
// Soft-collinear limit of the 2->3 kinematics (emission in -z direction):
SCm_ = realVVKinematics(B_, 1.,-1., theta2);
// Collinear limit of the 2->3 kinematics (emission in +z direction):
Cp_ = realVVKinematics(B_, xt, 1., theta2);
// Collinear limit of the 2->3 kinematics (emission in -z direction):
Cm_ = realVVKinematics(B_, xt,-1., theta2);
// The resolved 2->3 real emission kinematics:
H_ = realVVKinematics(B_, xt, y, theta2);
// Borrowed from VVhardGenerator (lab momenta of k1,k2):
Energy pT(sqrt(H_.pT2_in_lab()));
LorentzRotation yzRotation;
yzRotation.setRotateX(-atan2(pT/GeV,sqrt(B_.sb())/GeV));
LorentzRotation boostFrompTisZero;
boostFrompTisZero.setBoostY(-pT/sqrt(B_.sb()+pT*pT));
LorentzRotation boostFromYisZero;
boostFromYisZero.setBoostZ(tanh(B_.Yb()));
k1r_perp2_lab_ = (boostFromYisZero*boostFrompTisZero*yzRotation*(H_.k1r())).perp2();
k2r_perp2_lab_ = (boostFromYisZero*boostFrompTisZero*yzRotation*(H_.k2r())).perp2();
// Check all the real kinematics objects are internally consistent:
// S_.sanityCheck();
// SCp_.sanityCheck();
// SCm_.sanityCheck();
// Cp_.sanityCheck();
// Cm_.sanityCheck();
// H_.sanityCheck();
}
return;
}
double MEPP2VVPowheg::NLOweight() const {
// If only leading order is required return 1:
if(contrib_==0) return lo_me()/lo_me2_;
// Calculate alpha_S and alpha_S/(2*pi).
alphaS_ = nlo_alphaS_opt_==1 ? fixed_alphaS_ : SM().alphaS(mu_UV2());
double alsOn2pi(alphaS_/2./pi);
// Particle data objects for the new plus and minus colliding partons.
tcPDPtr gluon;
gluon = getParticleData(ParticleID::g);
// Get the all couplings.
gW_ = sqrt(4.0*pi*SM().alphaEM(scale())/SM().sin2ThetaW());
sin2ThetaW_ = SM().sin2ThetaW();
double cosThetaW(sqrt(1.-sin2ThetaW_));
guL_ = gW_/2./cosThetaW*( 1.-4./3.*sin2ThetaW_);
gdL_ = gW_/2./cosThetaW*(-1.+2./3.*sin2ThetaW_);
guR_ = gW_/2./cosThetaW*( -4./3.*sin2ThetaW_);
gdR_ = gW_/2./cosThetaW*( +2./3.*sin2ThetaW_);
eZ_ = gW_*cosThetaW;
eZ2_ = sqr(eZ_);
// MCFM has gwsq = 0.4389585130009 -> gw = 0.662539442600115
// Here we have gW_ = 0.662888
// MCFM has xw = 0.22224653300000 -> sqrt(xw) = 0.471430306
// Here we have 0.222247
// MCFM has esq = 0.097557007645279 -> e = 0.31234117187024679
// Here we have 4.0*pi*SM().alphaEM(sqr(100.*GeV)) = 0.0976596
// If the process is W-Z instead of W+Z we must transform these
// couplings as follows, according to NPB 383(1992)3-44 Eq.3.23
if(mePartonData()[2]->id()==-24&&mePartonData()[3]->id()==23) {
swap(guL_,gdL_);
eZ_ *= -1.;
}
// Get the CKM entry. Note that this code was debugged
// considerably; the call to CKM(particle,particle)
// did not appear to work, so we extract the elements
// as follows below. The right numbers now appear to
// to be associated with the right quarks.
double Kij(-999.);
// W+Z / W-Z
if(abs(mePartonData()[2]->id())==24&&mePartonData()[3]->id()==23) {
int up_id(-999),dn_id(-999);
if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==1) {
up_id = abs(quark_->id());
dn_id = abs(antiquark_->id());
}
else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==0) {
up_id = abs(antiquark_->id());
dn_id = abs(quark_->id());
}
else {
cout << "MEPP2VVPowheg:" << endl;
cout << "WZ needs an up and a down type quark as incoming!" << endl;
}
up_id /= 2;
up_id -= 1;
dn_id -= 1;
dn_id /= 2;
Kij = sqrt(SM().CKM(up_id,dn_id));
}
// W+W-
else if(abs(mePartonData()[2]->id())==24&&abs(mePartonData()[3]->id())==24) {
if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) {
int up_ida(abs(quark_->id())/2-1);
int up_idb(abs(antiquark_->id())/2-1);
Kij = sqrt(std::norm( CKM(up_ida,0)*CKM(up_idb,0)
+ CKM(up_ida,1)*CKM(up_idb,1)
+ CKM(up_ida,2)*CKM(up_idb,2)));
}
else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) {
int dn_ida((abs(quark_->id())-1)/2);
int dn_idb((abs(antiquark_->id())-1)/2);
Kij = sqrt(std::norm( CKM(0,dn_ida)*CKM(0,dn_idb)
+ CKM(1,dn_ida)*CKM(1,dn_idb)
+ CKM(2,dn_ida)*CKM(2,dn_idb)));
}
else {
cout << "MEPP2VVPowheg:" << endl;
cout << "WW needs 2 down-type / 2 up-type!" << endl;
}
}
// ZZ
else if(mePartonData()[2]->id()==23&&mePartonData()[3]->id()==23) {
Kij = 2.*sqrt(2.)/gW_;
}
else {
cout << "MEPP2VVPowheg: incompatible final state particles!" << endl;
}
Fij2_ = sqr(gW_/2./sqrt(2.)*Kij);
// Get the leading order matrix element (this is necessary!)
M_Born_ = M_Born_WZ(B_);
// // Get the regular part of the virtual correction (only needed for sanityCheck()!)
// M_V_regular_ = M_V_regular(S_);
// // Get the q + qbar real emission matrix element (only needed for sanityCheck()!)
// t_u_M_R_qqb_ = t_u_M_R_qqb(H_);
// Calculate the integrand
double wgt(0.);
double wqqb(0.);
double wgqb(0.);
double wqg(0.);
double wqqbvirt(0.);
double wqqbcollin(0.);
double wqqbreal(0.);
double wqgcollin(0.);
double wqgreal(0.);
double wgqbcollin(0.);
double wgqbreal(0.);
if(channels_==0||channels_==1) {
// q+qb
wqqbvirt = Vtilde_universal(S_) + M_V_regular(S_)/lo_me2_;
wqqbcollin = alsOn2pi*( Ctilde_Ltilde_qq_on_x(quark_,antiquark_,Cp_)
+ Ctilde_Ltilde_qq_on_x(quark_,antiquark_,Cm_) );
wqqbreal = alsOn2pi*Rtilde_Ltilde_qqb_on_x(quark_,antiquark_);
wqqb = wqqbvirt + wqqbcollin + wqqbreal;
}
if(channels_==0||channels_==2) {
// q+g
wqgcollin = alsOn2pi*Ctilde_Ltilde_gq_on_x(quark_,gluon,Cm_);
wqgreal = alsOn2pi*Rtilde_Ltilde_qg_on_x(quark_,gluon);
wqg = wqgreal + wqgcollin;
// g+qb
wgqbcollin = alsOn2pi*Ctilde_Ltilde_gq_on_x(gluon,antiquark_,Cp_);
wgqbreal = alsOn2pi*Rtilde_Ltilde_gqb_on_x(gluon,antiquark_);
wgqb = wgqbreal+wgqbcollin;
}
// total contribution
wgt = 1.+(wqqb+wgqb+wqg);
// If restricting to qg, gqb channels then subtract the LO contribution:
if(channels_==2) wgt -= 1.;
- if(isnan(wgt)||isinf(wgt)) {
+ if(!isfinite(wgt)) {
cout << "MEPP2VVPowheg:: NLO weight "
<< "is bad: wgt = " << wgt << endl;
cout << "MEPP2VVPowheg sanityCheck invoked!" << endl;
cout << ab_->PDGName() << ", "
<< bb_->PDGName() << ", "
<< mePartonData()[2]->PDGName() << ", "
<< mePartonData()[3]->PDGName() << endl;
cout << "lo_me2_ - M_Born_ (rel) = "
<< lo_me2_-M_Born_ << " ("
<< (lo_me2_-M_Born_)/M_Born_ << ")\n";
cout << "lo_me2_, M_Born_ " << lo_me2_ << ", " << M_Born_ << endl;
cout << "xr = " << H_.xr() << " 1-xr = " << 1.-H_.xr() << " y = " << H_.y() << endl;
cout << "tkr = " << H_.tkr()/GeV2 << " ukr = " << H_.ukr()/GeV2 << endl;
cout << "root(sb) = " << sqrt(B_.sb())/GeV << endl;
cout << "sb+tb+ub = "
<< B_.sb()/GeV2 << " + "
<< B_.tb()/GeV2 << " + " << B_.ub()/GeV2 << endl;
cout << "sqrt(k12) " << sqrt(H_.k12r())/GeV << endl;
cout << "sqrt(k22) " << sqrt(H_.k22r())/GeV << endl;
cout << "sqr(Kij) " << Kij*Kij << endl;
cout << "wqqbvirt " << wqqbvirt << endl;
cout << "wqqbcollin " << wqqbcollin << endl;
cout << "wqqbreal " << wqqbreal << endl;
cout << "wqqb " << wqqb << endl;
cout << "wqgcollin " << wqgcollin << endl;
cout << "wqgreal " << wqgreal << endl;
cout << "wqg " << wqg << endl;
cout << "wgqbcollin " << wgqbcollin << endl;
cout << "wgqbreal " << wgqbreal << endl;
cout << "wgqb " << wgqb << endl;
cout << "wgt " << wgt << endl;
throw Exception() << "MEPP2VVPowheg:: NLO weight "
<< "is bad: " << wgt
<< Exception::eventerror;
}
return contrib_==1 ? max(0.,wgt) : max(0.,-wgt);
}
double MEPP2VVPowheg::Lhat_ab(tcPDPtr a, tcPDPtr b,
realVVKinematics Kinematics) const {
if(!(abs(a->id())<=6||a->id()==21)||!(abs(b->id())<=6||b->id()==21))
cout << "MEPP2VVPowheg::Lhat_ab: Error,"
<< "particle a = " << a->PDGName() << ", "
<< "particle b = " << b->PDGName() << endl;
double nlo_lumi(-999.);
double x1(Kinematics.x1r()),x2(Kinematics.x2r());
nlo_lumi = (hadron_A_->pdf()->xfx(hadron_A_,a,mu_F2(),x1)/x1)
* (hadron_B_->pdf()->xfx(hadron_B_,b,mu_F2(),x2)/x2);
return nlo_lumi / lo_lumi_;
}
double MEPP2VVPowheg::Vtilde_universal(realVVKinematics S) const {
double xbar_y = S.xbar();
double y = S.y();
double eta1b(S.bornVariables().eta1b());
double eta2b(S.bornVariables().eta2b());
Energy2 sb(S.s2r());
return alphaS_/2./pi*CF_
* ( log(sb/mu_F2())
* (3. + 4.*log(eta1b)+4.*log(eta2b))
+ 8.*sqr(log(eta1b)) +8.*sqr(log(eta2b))
- 2.*sqr(pi)/3.
)
+ alphaS_/2./pi*CF_
* ( 8./(1.+y)*log(sqrt(1.-xbar_y)/eta2b)
+ 8./(1.-y)*log(sqrt(1.-xbar_y)/eta1b)
);
}
double MEPP2VVPowheg::Ctilde_Ltilde_qq_on_x(tcPDPtr a, tcPDPtr b,
realVVKinematics C) const {
if(C.y()!= 1.&&C.y()!=-1.)
cout << "\nCtilde_qq::y value not allowed.";
if(C.y()== 1.&&!(abs(a->id())>0&&abs(a->id())<7))
cout << "\nCtilde_qq::for Cqq^plus a must be a quark! id = "
<< a->id() << "\n";
if(C.y()==-1.&&!(abs(b->id())>0&&abs(b->id())<7))
cout << "\nCtilde_qq::for Cqq^minus b must be a quark! id = "
<< b->id() << "\n";
double xt = C.xt();
double x = C.xr();
double etab = C.y() == 1. ? C.bornVariables().eta1b()
: C.bornVariables().eta2b() ;
Energy2 sb(C.s2r());
if(fabs(1.-xt)<=tiny||fabs(1.-H_.xr())<=tiny) return 0.;
return ( ( (1./(1.-xt))*log(sb/mu_F2()/x)+4.*log(etab)/(1.-xt)
+ 2.*log(1.-xt)/(1.-xt)
)*CF_*(1.+sqr(x))
+ sqr(etab)*CF_*(1.-x)
)*Lhat_ab(a,b,C) / x
- ( ( (1./(1.-xt))*log(sb/mu_F2() )+4.*log(etab)/(1.-xt)
+ 2.*log(1.-xt)/(1.-xt)
)*CF_*2.
)*Lhat_ab(a,b,S_);
}
double MEPP2VVPowheg::Ctilde_Ltilde_gq_on_x(tcPDPtr a, tcPDPtr b,
realVVKinematics C) const {
if(C.y()!= 1.&&C.y()!=-1.)
cout << "\nCtilde_gq::y value not allowed.";
if(C.y()== 1.&&a->id()!=21)
cout << "\nCtilde_gq::for Cgq^plus a must be a gluon! id = "
<< a->id() << "\n";
if(C.y()==-1.&&b->id()!=21)
cout << "\nCtilde_gq::for Cgq^minus b must be a gluon! id = "
<< b->id() << "\n";
double xt = C.xt();
double x = C.xr();
double etab = C.y() == 1. ? C.bornVariables().eta1b()
: C.bornVariables().eta2b() ;
Energy2 sb(C.s2r());
return ( ( (1./(1.-xt))*log(sb/mu_F2()/x)+4.*log(etab)/(1.-xt)
+ 2.*log(1.-xt)/(1.-xt)
)*(1.-x)*TR_*(sqr(x)+sqr(1.-x))
+ sqr(etab)*TR_*2.*x*(1.-x)
)*Lhat_ab(a,b,C) / x;
}
double MEPP2VVPowheg::Rtilde_Ltilde_qqb_on_x(tcPDPtr a , tcPDPtr b) const {
if(!(abs(a->id())<=6||a->id()==21)||!(abs(b->id())<=6||b->id()==21))
cout << "MEPP2VVPowheg::Rtilde_Ltilde_qqb_on_x: Error,"
<< "particle a = " << a->PDGName() << ", "
<< "particle b = " << b->PDGName() << endl;
double xt(H_.xt());
double y(H_.y());
Energy2 s(H_.sr());
Energy2 sCp(Cp_.sr());
Energy2 sCm(Cm_.sr());
Energy2 t_u_M_R_qqb_H (t_u_M_R_qqb(H_ ));
Energy2 t_u_M_R_qqb_Cp(t_u_M_R_qqb(Cp_));
Energy2 t_u_M_R_qqb_Cm(t_u_M_R_qqb(Cm_));
// Energy2 t_u_M_R_qqb_H (t_u_M_R_qqb_hel_amp(H_));
// Energy2 t_u_M_R_qqb_Cp(8.*pi*alphaS_*Cp_.sr()/Cp_.xr()
// *CF_*(1.+sqr(Cp_.xr()))*lo_me2_);
// Energy2 t_u_M_R_qqb_Cm(8.*pi*alphaS_*Cm_.sr()/Cm_.xr()
// *CF_*(1.+sqr(Cm_.xr()))*lo_me2_);
int config(0);
if(fabs(1.-xt)<=tiny||fabs(1.-H_.xr())<=tiny) return 0.;
if(fabs(1.-y )<=tiny) { t_u_M_R_qqb_H = t_u_M_R_qqb_Cp ; config = 1; }
if(fabs(1.+y )<=tiny) { t_u_M_R_qqb_H = t_u_M_R_qqb_Cm ; config = -1; }
if(fabs(H_.tkr()/s)<=tiny) { t_u_M_R_qqb_H = t_u_M_R_qqb_Cp ; config = 1; }
if(fabs(H_.ukr()/s)<=tiny) { t_u_M_R_qqb_H = t_u_M_R_qqb_Cm ; config = -1; }
if(config== 0)
return
( ( (t_u_M_R_qqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qqb_Cp*Lhat_ab(a,b,Cp_)/sCp)
)*2./(1.-y)/(1.-xt)
+ ( (t_u_M_R_qqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qqb_Cm*Lhat_ab(a,b,Cm_)/sCm)
)*2./(1.+y)/(1.-xt)
) / lo_me2_ / 8. / pi / alphaS_;
else if(config== 1)
return
( (t_u_M_R_qqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qqb_Cm*Lhat_ab(a,b,Cm_)/sCm)
)*2./(1.+y)/(1.-xt) / lo_me2_ / 8. / pi / alphaS_;
else if(config==-1)
return
( (t_u_M_R_qqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qqb_Cp*Lhat_ab(a,b,Cp_)/sCp)
)*2./(1.-y)/(1.-xt) / lo_me2_ / 8. / pi / alphaS_;
else
throw Exception()
<< "MEPP2VVPowheg::Rtilde_Ltilde_qqb_on_x\n"
<< "The configuration is not identified as hard / soft / fwd collinear or bwd collinear."
<< "config = " << config << "\n"
<< "xt = " << xt << " 1.-xt = " << 1.-xt << "\n"
<< "y = " << y << " 1.-y = " << 1.-y << "\n"
<< Exception::eventerror;
}
double MEPP2VVPowheg::Rtilde_Ltilde_gqb_on_x(tcPDPtr a , tcPDPtr b) const {
if(!(abs(a->id())<=6||a->id()==21)||!(abs(b->id())<=6||b->id()==21))
cout << "MEPP2VVPowheg::Rtilde_Ltilde_gqb_on_x: Error,"
<< "particle a = " << a->PDGName() << ", "
<< "particle b = " << b->PDGName() << endl;
double xt(H_.xt());
double y(H_.y());
Energy2 s(H_.sr());
Energy2 sCp(Cp_.sr());
Energy2 sCm(Cm_.sr());
Energy2 t_u_M_R_gqb_H (t_u_M_R_gqb(H_ ));
Energy2 t_u_M_R_gqb_Cp(t_u_M_R_gqb(Cp_));
Energy2 t_u_M_R_gqb_Cm(t_u_M_R_gqb(Cm_));
// Energy2 t_u_M_R_gqb_H (t_u_M_R_gqb_hel_amp(H_));
// Energy2 t_u_M_R_gqb_Cp(8.*pi*alphaS_*Cp_.sr()/Cp_.xr()*(1.-Cp_.xr())
// *TR_*(sqr(Cp_.xr())+sqr(1.-Cp_.xr()))*lo_me2_);
// Energy2 t_u_M_R_gqb_Cm(t_u_M_R_gqb(Cm_));
// // Energy2 t_u_M_R_gqb_Cm(t_u_M_R_gqb_hel_amp(Cm_));
int config(0);
if(fabs(1.-xt)<=tiny||fabs(1.-H_.xr())<=tiny) return 0.;
if(fabs(1.-y )<=tiny) { t_u_M_R_gqb_H = t_u_M_R_gqb_Cp ; config = 1; }
if(fabs(1.+y )<=tiny) { t_u_M_R_gqb_H = t_u_M_R_gqb_Cm ; config = -1; }
if(fabs(H_.tkr()/s)<=tiny) { t_u_M_R_gqb_H = t_u_M_R_gqb_Cp ; config = 1; }
if(fabs(H_.ukr()/s)<=tiny) { t_u_M_R_gqb_H = t_u_M_R_gqb_Cm ; config = -1; }
if(config== 0)
return
( ( (t_u_M_R_gqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_gqb_Cp*Lhat_ab(a,b,Cp_)/sCp)
)*2./(1.-y)/(1.-xt)
+ ( (t_u_M_R_gqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_gqb_Cm*Lhat_ab(a,b,Cm_)/sCm)
)*2./(1.+y)/(1.-xt)
) / lo_me2_ / 8. / pi / alphaS_;
else if(config== 1)
return
( (t_u_M_R_gqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_gqb_Cm*Lhat_ab(a,b,Cm_)/sCm)
)*2./(1.+y)/(1.-xt) / lo_me2_ / 8. / pi / alphaS_;
else if(config==-1)
return
( (t_u_M_R_gqb_H*Lhat_ab(a,b,H_)/s - t_u_M_R_gqb_Cp*Lhat_ab(a,b,Cp_)/sCp)
)*2./(1.-y)/(1.-xt) / lo_me2_ / 8. / pi / alphaS_;
else
throw Exception()
<< "MEPP2VVPowheg::Rtilde_Ltilde_gqb_on_x\n"
<< "The configuration is not identified as hard / soft / fwd collinear or bwd collinear."
<< "config = " << config << "\n"
<< "xt = " << xt << " 1.-xt = " << 1.-xt << "\n"
<< "y = " << y << " 1.-y = " << 1.-y << "\n"
<< Exception::eventerror;
}
double MEPP2VVPowheg::Rtilde_Ltilde_qg_on_x(tcPDPtr a , tcPDPtr b) const {
if(!(abs(a->id())<=6||a->id()==21)||!(abs(b->id())<=6||b->id()==21))
cout << "MEPP2VVPowheg::Rtilde_Ltilde_qg_on_x: Error,"
<< "particle a = " << a->PDGName() << ", "
<< "particle b = " << b->PDGName() << endl;
double xt(H_.xt());
double y(H_.y());
Energy2 s(H_.sr());
Energy2 sCp(Cp_.sr());
Energy2 sCm(Cm_.sr());
Energy2 t_u_M_R_qg_H (t_u_M_R_qg(H_ ));
Energy2 t_u_M_R_qg_Cp(t_u_M_R_qg(Cp_));
Energy2 t_u_M_R_qg_Cm(t_u_M_R_qg(Cm_));
// Energy2 t_u_M_R_qg_H (t_u_M_R_qg_hel_amp(H_));
// Energy2 t_u_M_R_qg_Cp(t_u_M_R_qg(Cp_));
// // Energy2 t_u_M_R_qg_Cp(t_u_M_R_qg_hel_amp(Cp_));
// Energy2 t_u_M_R_qg_Cm(8.*pi*alphaS_*Cm_.sr()/Cm_.xr()*(1.-Cm_.xr())
// *TR_*(sqr(Cm_.xr())+sqr(1.-Cm_.xr()))*lo_me2_);
int config(0);
if(fabs(1.-xt)<=tiny||fabs(1.-H_.xr())<=tiny) return 0.;
if(fabs(1.-y )<=tiny) { t_u_M_R_qg_H = t_u_M_R_qg_Cp ; config = 1; }
if(fabs(1.+y )<=tiny) { t_u_M_R_qg_H = t_u_M_R_qg_Cm ; config = -1; }
if(fabs(H_.tkr()/s)<=tiny) { t_u_M_R_qg_H = t_u_M_R_qg_Cp ; config = 1; }
if(fabs(H_.ukr()/s)<=tiny) { t_u_M_R_qg_H = t_u_M_R_qg_Cm ; config = -1; }
if(config== 0)
return
( ( (t_u_M_R_qg_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qg_Cp*Lhat_ab(a,b,Cp_)/sCp)
)*2./(1.-y)/(1.-xt)
+ ( (t_u_M_R_qg_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qg_Cm*Lhat_ab(a,b,Cm_)/sCm)
)*2./(1.+y)/(1.-xt)
) / lo_me2_ / 8. / pi / alphaS_;
else if(config== 1)
return
( (t_u_M_R_qg_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qg_Cm*Lhat_ab(a,b,Cm_)/sCm)
)*2./(1.+y)/(1.-xt) / lo_me2_ / 8. / pi / alphaS_;
else if(config==-1)
return
( (t_u_M_R_qg_H*Lhat_ab(a,b,H_)/s - t_u_M_R_qg_Cp*Lhat_ab(a,b,Cp_)/sCp)
)*2./(1.-y)/(1.-xt) / lo_me2_ / 8. / pi / alphaS_;
else
throw Exception()
<< "MEPP2VVPowheg::Rtilde_Ltilde_qg_on_x\n"
<< "The configuration is not identified as hard / soft / fwd collinear or bwd collinear."
<< "config = " << config << "\n"
<< "xt = " << xt << " 1.-xt = " << 1.-xt << "\n"
<< "y = " << y << " 1.-y = " << 1.-y << "\n"
<< Exception::eventerror;
}
/***************************************************************************/
// The following three functions are identically \tilde{I}_{4,t},
// \tilde{I}_{3,WZ} and \tilde{I}_{3,W} given in Eqs. B.8,B.9,B.10
// of NPB 383(1992)3-44, respectively. They are related to / derived
// from the loop integrals in Eqs. A.3, A.5 and A.8 of the same paper.
InvEnergy4 TildeI4t(Energy2 s, Energy2 t, Energy2 mW2, Energy2 mZ2);
InvEnergy2 TildeI3WZ(Energy2 s, Energy2 mW2, Energy2 mZ2, double beta);
InvEnergy2 TildeI3W(Energy2 s, Energy2 t, Energy2 mW2);
/***************************************************************************/
// The following six functions are identically I_{dd}^{(1)}, I_{ud}^{(1)},
// I_{uu}^{(1)}, F_{u}^{(1)}, F_{d}^{(1)}, H^{(1)} from Eqs. B.4, B.5, B.3,
// B.3, B.6, B.7 of NPB 383(1992)3-44, respectively. They make up the
// one-loop matrix element. Ixx functions correspond to the graphs
// with no TGC, Fx functions are due to non-TGC graphs interfering
// with TGC graphs, while the H function is due purely to TGC graphs.
double Idd1(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2,double beta);
double Iud1(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2,double beta);
double Iuu1(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2,double beta);
Energy2 Fu1(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2,double beta);
Energy2 Fd1(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2,double beta);
Energy4 H1 (Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2);
/***************************************************************************/
// M_V_Regular is the regular part of the one-loop matrix element
// exactly as defined in Eqs. B.1 and B.2 of of NPB 383(1992)3-44.
double MEPP2VVPowheg::M_V_regular(realVVKinematics S) const {
Energy2 s(S.bornVariables().sb());
Energy2 t(S.bornVariables().tb());
Energy2 u(S.bornVariables().ub());
Energy2 mW2(S.k12r()); // N.B. the diboson masses are preserved in getting
Energy2 mZ2(S.k22r()); // the 2->2 from the 2->3 kinematics.
double beta(S.betaxr()); // N.B. for x=1 \beta_x=\beta in NPB 383(1992)3-44.
double cosThetaW(sqrt(1.-sin2ThetaW_));
double eZ2(eZ2_);
double eZ(eZ_);
double gdL(gdL_);
double guL(guL_);
double gdR(gdR_);
double guR(guR_);
// W+W-
if(abs(mePartonData()[2]->id())==24&&abs(mePartonData()[3]->id())==24) {
double e2(sqr(gW_)*sin2ThetaW_);
if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) {
// N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set!
if(quark_->id()==-antiquark_->id()) {
eZ2 = 1./2.*sqr(s-mW2)/Fij2_
* (e2*e2/s/s*(sqr( 2./3.+eZ*(guL+guR)/2./e2*s/(s-mW2/sqr(cosThetaW)))
+sqr( eZ*(guL-guR)/2./e2*s/(s-mW2/sqr(cosThetaW))))
);
eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s-mW2)
* (gW_*gW_*e2/4./s *( 2./3.+2.*eZ*guL/2./e2*s/(s-mW2/sqr(cosThetaW))));
} else {
eZ2 =0.;
eZ =0.;
}
gdL = gW_/sqrt(2.);
guL = 0.;
}
else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) {
// N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set!
if(quark_->id()==-antiquark_->id()) {
eZ2 = 1./2.*sqr(s-mW2)/Fij2_
* (e2*e2/s/s*(sqr(-1./3.+eZ*(gdL+gdR)/2./e2*s/(s-mW2/sqr(cosThetaW)))
+sqr( eZ*(gdL-gdR)/2./e2*s/(s-mW2/sqr(cosThetaW))))
);
eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s-mW2)
* (gW_*gW_*e2/4./s *(-1./3.+2.*eZ*gdL/2./e2*s/(s-mW2/sqr(cosThetaW))));
} else {
eZ2 =0.;
eZ =0.;
}
guL = gW_/sqrt(2.);
gdL = 0.;
}
}
// ZZ
else if(mePartonData()[2]->id()==23&&mePartonData()[3]->id()==23) {
eZ = 0.;
eZ2 = 0.;
double gV2,gA2;
gV2 = sqr(guL/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_);
gA2 = sqr(guL/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_);
guL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
gV2 = sqr(gdL/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_);
gA2 = sqr(gdL/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_);
gdL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) gdL = guL;
else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) guL = gdL;
else {
cout << "MEPP2VVPowheg:" << endl;
cout << "ZZ needs 2 down-type / 2 up-type!" << endl;
}
}
return 4.*pi*alphaS_*Fij2_*CF_*(1./sqr(4.*pi))/NC_
* ( gdL*gdL*Idd1(s,t,u,mW2,mZ2,beta)
+ gdL*guL*Iud1(s,t,u,mW2,mZ2,beta)
+ guL*guL*Iuu1(s,t,u,mW2,mZ2,beta)
- eZ/(s-mW2) * ( gdL*Fd1(s,t,u,mW2,mZ2,beta)
- guL*Fu1(s,t,u,mW2,mZ2,beta)
)
+ eZ2/sqr(s-mW2) * H1(s,t,u,mW2,mZ2)
);
}
/***************************************************************************/
InvEnergy4 TildeI4t(Energy2 s, Energy2 t, Energy2 mW2, Energy2 mZ2) {
double sqrBrackets;
sqrBrackets = ( sqr(log(-t/mW2))/2.+log(-t/mW2)*log(-t/mZ2)/2.
- 2.*log(-t/mW2)*log((mW2-t)/mW2)-2.*ReLi2(t/mW2)
);
swap(mW2,mZ2);
sqrBrackets+= ( sqr(log(-t/mW2))/2.+log(-t/mW2)*log(-t/mZ2)/2.
- 2.*log(-t/mW2)*log((mW2-t)/mW2)-2.*ReLi2(t/mW2)
);
swap(mW2,mZ2);
return sqrBrackets/s/t;
}
InvEnergy2 TildeI3WZ(Energy2 s, Energy2 mW2, Energy2 mZ2, double beta) {
Energy2 sig(mZ2+mW2);
Energy2 del(mZ2-mW2);
double sqrBrackets ;
sqrBrackets = ( ReLi2(2.*mW2/(sig-del*(del/s+beta)))
+ ReLi2((1.-del/s+beta)/2.)
+ sqr(log((1.-del/s+beta)/2.))/2.
+ log((1.-del/s-beta)/2.)*log((1.+del/s-beta)/2.)
);
beta *= -1;
sqrBrackets -= ( ReLi2(2.*mW2/(sig-del*(del/s+beta)))
+ ReLi2((1.-del/s+beta)/2.)
+ sqr(log((1.-del/s+beta)/2.))/2.
+ log((1.-del/s-beta)/2.)*log((1.+del/s-beta)/2.)
);
beta *= -1;
swap(mW2,mZ2);
del *= -1.;
sqrBrackets += ( ReLi2(2.*mW2/(sig-del*(del/s+beta)))
+ ReLi2((1.-del/s+beta)/2.)
+ sqr(log((1.-del/s+beta)/2.))/2.
+ log((1.-del/s-beta)/2.)*log((1.+del/s-beta)/2.)
);
swap(mW2,mZ2);
del *= -1.;
beta *= -1;
swap(mW2,mZ2);
del *= -1.;
sqrBrackets -= ( ReLi2(2.*mW2/(sig-del*(del/s+beta)))
+ ReLi2((1.-del/s+beta)/2.)
+ sqr(log((1.-del/s+beta)/2.))/2.
+ log((1.-del/s-beta)/2.)*log((1.+del/s-beta)/2.)
);
beta *= -1;
swap(mW2,mZ2);
del *= -1.;
return sqrBrackets/s/beta;
}
InvEnergy2 TildeI3W(Energy2 s, Energy2 t, Energy2 mW2) {
return
1./(mW2-t)*(sqr(log(mW2/s))/2.-sqr(log(-t/s))/2.-sqr(pi)/2.);
}
/***************************************************************************/
double Idd1(Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2, double beta) {
Energy2 sig(mZ2+mW2);
Energy2 del(mZ2-mW2);
double Val(0.);
Val += 2.*(22.*t*t+t*(19.*s-18.*sig)+18.*mW2*mZ2)/t/t
- 8.*(u*t+2*s*sig)/mW2/mZ2
- 2.*sqr(t-u)/t/s/sqr(beta);
Val += +( 2.*(8.*t*t+4.*t*(s-3.*sig)+4*sqr(sig)-5.*s*sig+s*s)/t/s/sqr(beta)
+ 4.*(t*(3.*u+s)-3.*mW2*mZ2)/t/t
+ 6.*(t+u)*sqr(t-u)/t/s/s/sqr(sqr(beta))
)*log(-t/s);
Val += +( ( 8.*t*t*(-2.*s+del)+8.*t*(-s*s+3.*s*sig-2.*del*sig)
- 2.*(s-sig)*(s*s-4.*s*sig+3.*del*sig)
)/t/s/s/beta/beta
+ 16.*s*(t-mZ2)/(t*(u+s)-mW2*mZ2)
+ 2.*(4.*t*t+t*(10.*s-3.*mZ2-9.*mW2)+12.*mW2*mZ2)/t/t
-6.*(s-del)*(t+u)*sqr(t-u)/t/s/s/s/sqr(sqr(beta))
)*log(-t/mW2);
Val += ( - ( 4.*t*t*(2.*sig-3.*s)
- 4.*t*(s-sig)*(2.*s-3.*sig)
- 2.*(s-2.*sig)*sqr(s-sig)
)/t/s/beta/beta
+ ( 4.*sig*t-3.*s*s+4.*s*sig
- 4.*(mW2*mW2+mZ2*mZ2)
)/t
- 3.*sqr(t*t-u*u)/t/s/s/sqr(sqr(beta))
)*TildeI3WZ(s,mW2,mZ2,beta);
Val += +( 4.*(t*u+2.*s*sig)/3./mW2/mZ2 - 4.*(t-2.*u)/3./t
)*pi*pi;
Val += -( 4.*s*(t*u-2.*mW2*mZ2)/t
)*TildeI4t(s,t,mW2,mZ2);
Val += ( 8.*(t-mW2)*(u*t-2.*mW2*mZ2)/t/t
)*TildeI3W(s,t,mW2);
swap(mW2,mZ2);
del *= -1;
Val += 2.*(22.*t*t+t*(19.*s-18.*sig)+18.*mW2*mZ2)/t/t
- 8.*(u*t+2*s*sig)/mW2/mZ2
- 2.*sqr(t-u)/t/s/sqr(beta);
Val += +( 2.*(8.*t*t+4.*t*(s-3.*sig)+4*sqr(sig)-5.*s*sig+s*s)/t/s/sqr(beta)
+ 4.*(t*(3.*u+s)-3.*mW2*mZ2)/t/t
+ 6.*(t+u)*sqr(t-u)/t/s/s/sqr(sqr(beta))
)*log(-t/s);
Val += +( ( 8.*t*t*(-2.*s+del)+8.*t*(-s*s+3.*s*sig-2.*del*sig)
- 2.*(s-sig)*(s*s-4.*s*sig+3.*del*sig)
)/t/s/s/beta/beta
+ 16.*s*(t-mZ2)/(t*(u+s)-mW2*mZ2)
+ 2.*(4.*t*t+t*(10.*s-3.*mZ2-9.*mW2)+12.*mW2*mZ2)/t/t
-6.*(s-del)*(t+u)*sqr(t-u)/t/s/s/s/sqr(sqr(beta))
)*log(-t/mW2);
Val += ( - ( 4.*t*t*(2.*sig-3.*s)
- 4.*t*(s-sig)*(2.*s-3.*sig)
- 2.*(s-2.*sig)*sqr(s-sig)
)/t/s/beta/beta
+ ( 4.*sig*t-3.*s*s+4.*s*sig
- 4.*(mW2*mW2+mZ2*mZ2)
)/t
- 3.*sqr(t*t-u*u)/t/s/s/sqr(sqr(beta))
)*TildeI3WZ(s,mW2,mZ2,beta);
Val += +( 4.*(t*u+2.*s*sig)/3./mW2/mZ2 - 4.*(t-2.*u)/3./t
)*pi*pi;
Val += -( 4.*s*(t*u-2.*mW2*mZ2)/t
)*TildeI4t(s,t,mW2,mZ2);
Val += ( 8.*(t-mW2)*(u*t-2.*mW2*mZ2)/t/t
)*TildeI3W(s,t,mW2);
swap(mW2,mZ2);
del *= -1;
return Val;
}
/***************************************************************************/
double Iud1(Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2, double beta) {
Energy2 sig(mZ2+mW2);
Energy2 del(mZ2-mW2);
double Val(0.);
Val += 2.*(4.*t*t+t*(9.*s-4.*sig)-18.*s*sig)/t/u
+ 8.*(t*u+2.*s*sig)/mW2/mZ2
+ 4.*s*s*(2.*t-sig)/u/(mW2*mZ2-t*(u+s))
- 2.*sqr(t-u)/u/s/sqr(beta);
Val += ( 2.*(8.*t*t-4.*t*(s+3.*sig)-(s-sig)*(3.*s+4.*sig))/u/s/sqr(beta)
+ 6.*(t+u)*sqr(t-u)/u/s/s/sqr(sqr(beta))
- 12.*s*(t-sig)/t/u
)*log(-t/s);
Val += ( (2./u/s/s/sqr(beta))*( 4.*t*t*(-2.*s+del)
+ 4.*t*(s*s+s*(mZ2+5.*mW2)-2.*sig*del)
+ (s-sig)*(3.*s*s+8.*mW2*s-3.*sig*del)
)
+ (2.*t*(18.*s+3.*mW2+mZ2)-24.*s*sig)/t/u
- 8.*s*(2.*t*t-t*(3.*s+4.*mZ2+2.*mW2)+2.*mZ2*(s+sig))
/u/(mW2*mZ2-t*(u+s))
- 8.*s*s*t*(2.*t-sig)*(t-mZ2)/u/sqr(mW2*mZ2-t*(u+s))
+ 6.*(s-del)*(s-sig)*sqr(t-u)/u/s/s/s/sqr(sqr(beta))
)*log(-t/mW2);
Val += ( -2.*(2.*t*t*(2.*sig-3.*s)+6.*sig*t*(s-sig)+sqr(s-sig)*(s+2.*sig))
/u/s/sqr(beta)
+3.*s*(4.*t-4.*sig-s)/u
-3.*sqr(s-sig)*sqr(t-u)/u/s/s/sqr(sqr(beta))
)*TildeI3WZ(s,mW2,mZ2,beta);
Val += ( 4.*(u+4.*s)/3./u - 4.*(u*t+2.*s*sig)/3./mW2/mZ2
)*pi*pi;
Val += -( 16.*s*(t-sig)*(t-mW2)/t/u
)*TildeI3W(s,t,mW2);
Val += ( 8.*s*s*(t-sig)/u
)*TildeI4t(s,t,mW2,mZ2);
swap(t,u);
Val += 2.*(4.*t*t+t*(9.*s-4.*sig)-18.*s*sig)/t/u
+ 8.*(t*u+2.*s*sig)/mW2/mZ2
+ 4.*s*s*(2.*t-sig)/u/(mW2*mZ2-t*(u+s))
- 2.*sqr(t-u)/u/s/sqr(beta);
Val += ( 2.*(8.*t*t-4.*t*(s+3.*sig)-(s-sig)*(3.*s+4.*sig))/u/s/sqr(beta)
+ 6.*(t+u)*sqr(t-u)/u/s/s/sqr(sqr(beta))
- 12.*s*(t-sig)/t/u
)*log(-t/s);
Val += ( (2./u/s/s/sqr(beta))*( 4.*t*t*(-2.*s+del)
+ 4.*t*(s*s+s*(mZ2+5.*mW2)-2.*sig*del)
+ (s-sig)*(3.*s*s+8.*mW2*s-3.*sig*del)
)
+ (2.*t*(18.*s+3.*mW2+mZ2)-24.*s*sig)/t/u
- 8.*s*(2.*t*t-t*(3.*s+4.*mZ2+2.*mW2)+2.*mZ2*(s+sig))
/u/(mW2*mZ2-t*(u+s))
- 8.*s*s*t*(2.*t-sig)*(t-mZ2)/u/sqr(mW2*mZ2-t*(u+s))
+ 6.*(s-del)*(s-sig)*sqr(t-u)/u/s/s/s/sqr(sqr(beta))
)*log(-t/mW2);
Val += ( -2.*(2.*t*t*(2.*sig-3.*s)+6.*sig*t*(s-sig)+sqr(s-sig)*(s+2.*sig))
/u/s/sqr(beta)
+3.*s*(4.*t-4.*sig-s)/u
-3.*sqr(s-sig)*sqr(t-u)/u/s/s/sqr(sqr(beta))
)*TildeI3WZ(s,mW2,mZ2,beta);
Val += ( 4.*(u+4.*s)/3./u - 4.*(u*t+2.*s*sig)/3./mW2/mZ2
)*pi*pi;
Val += -( 16.*s*(t-sig)*(t-mW2)/t/u
)*TildeI3W(s,t,mW2);
Val += ( 8.*s*s*(t-sig)/u
)*TildeI4t(s,t,mW2,mZ2);
swap(t,u);
swap(mW2,mZ2);
del *= -1;
Val += 2.*(4.*t*t+t*(9.*s-4.*sig)-18.*s*sig)/t/u
+ 8.*(t*u+2.*s*sig)/mW2/mZ2
+ 4.*s*s*(2.*t-sig)/u/(mW2*mZ2-t*(u+s))
- 2.*sqr(t-u)/u/s/sqr(beta);
Val += ( 2.*(8.*t*t-4.*t*(s+3.*sig)-(s-sig)*(3.*s+4.*sig))/u/s/sqr(beta)
+ 6.*(t+u)*sqr(t-u)/u/s/s/sqr(sqr(beta))
- 12.*s*(t-sig)/t/u
)*log(-t/s);
Val += ( (2./u/s/s/sqr(beta))*( 4.*t*t*(-2.*s+del)
+ 4.*t*(s*s+s*(mZ2+5.*mW2)-2.*sig*del)
+ (s-sig)*(3.*s*s+8.*mW2*s-3.*sig*del)
)
+ (2.*t*(18.*s+3.*mW2+mZ2)-24.*s*sig)/t/u
- 8.*s*(2.*t*t-t*(3.*s+4.*mZ2+2.*mW2)+2.*mZ2*(s+sig))
/u/(mW2*mZ2-t*(u+s))
- 8.*s*s*t*(2.*t-sig)*(t-mZ2)/u/sqr(mW2*mZ2-t*(u+s))
+ 6.*(s-del)*(s-sig)*sqr(t-u)/u/s/s/s/sqr(sqr(beta))
)*log(-t/mW2);
Val += ( -2.*(2.*t*t*(2.*sig-3.*s)+6.*sig*t*(s-sig)+sqr(s-sig)*(s+2.*sig))
/u/s/sqr(beta)
+3.*s*(4.*t-4.*sig-s)/u
-3.*sqr(s-sig)*sqr(t-u)/u/s/s/sqr(sqr(beta))
)*TildeI3WZ(s,mW2,mZ2,beta);
Val += ( 4.*(u+4.*s)/3./u - 4.*(u*t+2.*s*sig)/3./mW2/mZ2
)*pi*pi;
Val += -( 16.*s*(t-sig)*(t-mW2)/t/u
)*TildeI3W(s,t,mW2);
Val += ( 8.*s*s*(t-sig)/u
)*TildeI4t(s,t,mW2,mZ2);
swap(mW2,mZ2);
del *= -1;
swap(t,u);
swap(mW2,mZ2);
del *= -1;
Val += 2.*(4.*t*t+t*(9.*s-4.*sig)-18.*s*sig)/t/u
+ 8.*(t*u+2.*s*sig)/mW2/mZ2
+ 4.*s*s*(2.*t-sig)/u/(mW2*mZ2-t*(u+s))
- 2.*sqr(t-u)/u/s/sqr(beta);
Val += ( 2.*(8.*t*t-4.*t*(s+3.*sig)-(s-sig)*(3.*s+4.*sig))/u/s/sqr(beta)
+ 6.*(t+u)*sqr(t-u)/u/s/s/sqr(sqr(beta))
- 12.*s*(t-sig)/t/u
)*log(-t/s);
Val += ( (2./u/s/s/sqr(beta))*( 4.*t*t*(-2.*s+del)
+ 4.*t*(s*s+s*(mZ2+5.*mW2)-2.*sig*del)
+ (s-sig)*(3.*s*s+8.*mW2*s-3.*sig*del)
)
+ (2.*t*(18.*s+3.*mW2+mZ2)-24.*s*sig)/t/u
- 8.*s*(2.*t*t-t*(3.*s+4.*mZ2+2.*mW2)+2.*mZ2*(s+sig))
/u/(mW2*mZ2-t*(u+s))
- 8.*s*s*t*(2.*t-sig)*(t-mZ2)/u/sqr(mW2*mZ2-t*(u+s))
+ 6.*(s-del)*(s-sig)*sqr(t-u)/u/s/s/s/sqr(sqr(beta))
)*log(-t/mW2);
Val += ( -2.*(2.*t*t*(2.*sig-3.*s)+6.*sig*t*(s-sig)+sqr(s-sig)*(s+2.*sig))
/u/s/sqr(beta)
+3.*s*(4.*t-4.*sig-s)/u
-3.*sqr(s-sig)*sqr(t-u)/u/s/s/sqr(sqr(beta))
)*TildeI3WZ(s,mW2,mZ2,beta);
Val += ( 4.*(u+4.*s)/3./u - 4.*(u*t+2.*s*sig)/3./mW2/mZ2
)*pi*pi;
Val += -( 16.*s*(t-sig)*(t-mW2)/t/u
)*TildeI3W(s,t,mW2);
Val += ( 8.*s*s*(t-sig)/u
)*TildeI4t(s,t,mW2,mZ2);
swap(t,u);
swap(mW2,mZ2);
del *= -1;
return Val;
}
/***************************************************************************/
double Iuu1(Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2, double beta) {
double Val(Idd1(s,u,t,mW2,mZ2,beta));
return Val;
}
/***************************************************************************/
Energy2 Fd1 (Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2, double beta) {
Energy2 sig(mZ2+mW2);
Energy2 del(mZ2-mW2);
Energy2 Val(0.*GeV2);
Val += 4.*(17.*t*t+t*(11.*s-13.*sig)+17.*(s*sig+mW2*mZ2))/t
+ 16.*(s-sig)*(t*u+2.*s*sig)/mW2/mZ2
+ 4*s*s*(2.*t-sig)/(t*(u+s)-mW2*mZ2);
Val += ( 8.*(t-u)/sqr(beta)
- 4.*(3.*t*t-t*(s+3.*sig)+3.*(s*sig+mW2*mZ2))/t
)*log(-t/s);
Val += ( 8.*(t*t-t*(2.*s+3.*mW2+mZ2)+3.*(s*sig+mW2*mZ2))/t
+ 8.*s*(t*(3.*s+2.*sig)-2.*mZ2*(s+sig))/(t*(u+s)-mW2*mZ2)
+ 8.*s*s*t*(2.*t-sig)*(t-mZ2)/sqr(t*(u+s)-mW2*mZ2)
- 8.*(s-del)*(t-u)/s/sqr(beta)
)*log(-t/mW2);
Val += ( 4.*(s-sig)*(t-u)/sqr(beta)
+ 4.*(sig-3.*s)*t
+ 4.*(4.*s*sig-mZ2*mZ2-mW2*mW2)
)*TildeI3WZ(s,mW2,mZ2,beta);
Val += -( 8.*(3.*t*t+2.*t*(2.*s-sig)+2.*(s*sig+mW2*mZ2))/3./t
+ 8.*(s-sig)*(t*u+2.*s*sig)/3./mW2/mZ2
)*pi*pi;
Val += ( 4.*(s*t*t-s*(s+sig)*t+2.*s*(s*sig+mW2*mZ2))
)*TildeI4t(s,t,mW2,mZ2);
Val += -( 8.*(t-mW2)*(t*t-t*(s+sig)+2.*(s*sig+mW2*mZ2))/t
)*TildeI3W(s,t,mW2);
swap(mW2,mZ2);
del *= -1;
Val += 4.*(17.*t*t+t*(11.*s-13.*sig)+17.*(s*sig+mW2*mZ2))/t
+ 16.*(s-sig)*(t*u+2.*s*sig)/mW2/mZ2
+ 4*s*s*(2.*t-sig)/(t*(u+s)-mW2*mZ2);
Val += ( 8.*(t-u)/sqr(beta)
- 4.*(3.*t*t-t*(s+3.*sig)+3.*(s*sig+mW2*mZ2))/t
)*log(-t/s);
Val += ( 8.*(t*t-t*(2.*s+3.*mW2+mZ2)+3.*(s*sig+mW2*mZ2))/t
+ 8.*s*(t*(3.*s+2.*sig)-2.*mZ2*(s+sig))/(t*(u+s)-mW2*mZ2)
+ 8.*s*s*t*(2.*t-sig)*(t-mZ2)/sqr(t*(u+s)-mW2*mZ2)
- 8.*(s-del)*(t-u)/s/sqr(beta)
)*log(-t/mW2);
Val += ( 4.*(s-sig)*(t-u)/sqr(beta)
+ 4.*(sig-3.*s)*t
+ 4.*(4.*s*sig-mZ2*mZ2-mW2*mW2)
)*TildeI3WZ(s,mW2,mZ2,beta);
Val += -( 8.*(3.*t*t+2.*t*(2.*s-sig)+2.*(s*sig+mW2*mZ2))/3./t
+ 8.*(s-sig)*(t*u+2.*s*sig)/3./mW2/mZ2
)*pi*pi;
Val += ( 4.*(s*t*t-s*(s+sig)*t+2.*s*(s*sig+mW2*mZ2))
)*TildeI4t(s,t,mW2,mZ2);
Val += -( 8.*(t-mW2)*(t*t-t*(s+sig)+2.*(s*sig+mW2*mZ2))/t
)*TildeI3W(s,t,mW2);
swap(mW2,mZ2);
del *= -1;
return Val;
}
/***************************************************************************/
Energy2 Fu1 (Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2, double beta) {
Energy2 Val(Fd1(s,u,t,mW2,mZ2,beta));
return Val;
}
/***************************************************************************/
Energy4 H1 (Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2) {
Energy2 sig(mZ2+mW2);
Energy4 Val(0.*GeV2*GeV2);
Val = 8.*t*t+8.*t*(s-sig)+s*s+6.*s*sig+mZ2*mZ2+10.*mW2*mZ2+mW2*mW2
- sqr(s-sig)*(t*u+2.*s*sig)/mW2/mZ2;
Val *= ( 16.-8.*pi*pi/3.);
return Val;
}
Energy2 t_u_Rdd(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1 , Energy2 q2,
Energy2 mW2, Energy2 mZ2);
Energy2 t_u_Rud(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1 , Energy2 q2,
Energy2 q1h, Energy2 q2h, Energy2 mW2, Energy2 mZ2);
Energy2 t_u_Ruu(Energy2 s , Energy2 tk , Energy2 uk, Energy2 q1h, Energy2 q2h,
Energy2 mW2, Energy2 mZ2);
Energy4 t_u_RZds(Energy2 s ,Energy2 tk , Energy2 uk , Energy2 q1, Energy2 q2,
Energy2 s2,Energy2 mW2, Energy2 mZ2);
Energy4 t_u_RZda(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1, Energy2 q2,
Energy2 s2, Energy2 mW2, Energy2 mZ2);
Energy4 t_u_RZd(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1 , Energy2 q2 ,
Energy2 s2 , Energy2 mW2, Energy2 mZ2);
Energy4 t_u_RZu(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1h, Energy2 q2h,
Energy2 s2 , Energy2 mW2, Energy2 mZ2);
Energy6 t_u_RZs(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1, Energy2 q2,
Energy2 s2, Energy2 mW2, Energy2 mZ2);
Energy6 t_u_RZa(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1, Energy2 q2,
Energy2 s2, Energy2 mW2, Energy2 mZ2);
Energy6 t_u_RZ(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1, Energy2 q2,
Energy2 s2 , Energy2 mW2, Energy2 mZ2);
/***************************************************************************/
// t_u_M_R_qqb is the real emission q + qb -> n + g matrix element
// exactly as defined in Eqs. C.1 of NPB 383(1992)3-44, multiplied by
// tk * uk!
Energy2 MEPP2VVPowheg::t_u_M_R_qqb(realVVKinematics R) const {
// First the Born variables:
Energy2 s2(R.s2r());
Energy2 mW2(R.k12r());
Energy2 mZ2(R.k22r());
// Then the rest:
Energy2 s(R.sr());
Energy2 tk(R.tkr());
Energy2 uk(R.ukr());
Energy2 q1(R.q1r());
Energy2 q2(R.q2r());
Energy2 q1h(R.q1hatr());
Energy2 q2h(R.q2hatr());
double cosThetaW(sqrt(1.-sin2ThetaW_));
double eZ2(eZ2_);
double eZ(eZ_);
double gdL(gdL_);
double guL(guL_);
double gdR(gdR_);
double guR(guR_);
// W+W-
if(abs(mePartonData()[2]->id())==24&&abs(mePartonData()[3]->id())==24) {
double e2(sqr(gW_)*sin2ThetaW_);
if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) {
// N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set!
if(quark_->id()==-antiquark_->id()) {
eZ2 = 1./2.*sqr(s2-mW2)/Fij2_
* (e2*e2/s2/s2*(sqr( 2./3.+eZ*(guL+guR)/2./e2*s2/(s2-mW2/sqr(cosThetaW)))
+sqr( eZ*(guL-guR)/2./e2*s2/(s2-mW2/sqr(cosThetaW))))
);
eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s2-mW2)
* (gW_*gW_*e2/4./s2 *( 2./3.+2.*eZ*guL/2./e2*s2/(s2-mW2/sqr(cosThetaW))));
} else {
eZ2 =0.;
eZ =0.;
}
gdL = gW_/sqrt(2.);
guL = 0.;
}
else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) {
// N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set!
if(quark_->id()==-antiquark_->id()) {
eZ2 = 1./2.*sqr(s2-mW2)/Fij2_
* (e2*e2/s2/s2*(sqr(-1./3.+eZ*(gdL+gdR)/2./e2*s2/(s2-mW2/sqr(cosThetaW)))
+sqr( eZ*(gdL-gdR)/2./e2*s2/(s2-mW2/sqr(cosThetaW))))
);
eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s2-mW2)
* (gW_*gW_*e2/4./s2 *(-1./3.+2.*eZ*gdL/2./e2*s2/(s2-mW2/sqr(cosThetaW))));
} else {
eZ2 =0.;
eZ =0.;
}
guL = gW_/sqrt(2.);
gdL = 0.;
}
}
// ZZ
else if(mePartonData()[2]->id()==23&&mePartonData()[3]->id()==23) {
eZ = 0.;
eZ2 = 0.;
double gV2,gA2;
gV2 = sqr(guL/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_);
gA2 = sqr(guL/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_);
guL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
gV2 = sqr(gdL/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_);
gA2 = sqr(gdL/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_);
gdL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) gdL = guL;
else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) guL = gdL;
else {
cout << "MEPP2VVPowheg:" << endl;
cout << "ZZ needs 2 down-type / 2 up-type!" << endl;
}
}
return -2.*pi*alphaS_*Fij2_*CF_/NC_
* ( gdL*gdL*t_u_Rdd(s,tk,uk,q1,q2,mW2,mZ2)
+ 2.*gdL*guL*t_u_Rud(s,tk,uk,q1,q2,q1h,q2h,mW2,mZ2)
+ guL*guL*t_u_Ruu(s,tk,uk,q1h,q2h,mW2,mZ2)
- 2.*eZ/(s2-mW2) * ( gdL
* t_u_RZd(s,tk,uk,q1 ,q2 ,s2,mW2,mZ2)
- guL
* t_u_RZu(s,tk,uk,q1h,q2h,s2,mW2,mZ2)
)
+ eZ2/sqr(s2-mW2) *t_u_RZ(s,tk,uk,q1,q2,s2,mW2,mZ2)
);
}
Energy2 t_u_Rdd(Energy2 s ,Energy2 tk ,Energy2 uk ,Energy2 q1,Energy2 q2,
Energy2 mW2, Energy2 mZ2) {
Energy2 Val(0.*GeV2);
Val += 4.*(q2*(uk+2.*s+q2)+q1*(s+q1))/mW2/mZ2*uk
+ 16.*(uk+s)/q2*uk
- 4.*(2.*uk+4.*s+q2)/mW2*uk
- 4.*(2.*uk+5.*s+q2+2.*q1-mW2)/mZ2*uk
+ 4.*q1*s*(s+q1)/mW2/mZ2
+ 16.*s*(s+q2-mZ2-mW2)/q1
- 4.*s*(4.*s+q2+q1)/mW2
+ 16.*mW2*mZ2*s/q1/q2
+ 4.*s
+ 16.*mZ2*(tk-2.*mW2)/q1/q2/q2*tk*uk
+ 16.*(2.*mZ2+mW2-tk)/q1/q2*tk*uk
+ 16.*mW2*(s-mZ2-mW2)/q1/q2*uk
+ 16.*mZ2*(q1-2.*mW2)/q2/q2*uk
+ 32.*mW2*mW2*mZ2/q1/q2/q2*uk
+ 16.*mW2/q1*uk
+ 4.*uk
+ 8./q2*tk*uk
+ 4.*q1/mW2/mZ2*tk*uk
- 24./q1*tk*uk
- 4./mW2*tk*uk;
swap(mW2,mZ2);
swap(q1,q2);
swap(tk,uk);
Val += 4.*(q2*(uk+2.*s+q2)+q1*(s+q1))/mW2/mZ2*uk
+ 16.*(uk+s)/q2*uk
- 4.*(2.*uk+4.*s+q2)/mW2*uk
- 4.*(2.*uk+5.*s+q2+2.*q1-mW2)/mZ2*uk
+ 4.*q1*s*(s+q1)/mW2/mZ2
+ 16.*s*(s+q2-mZ2-mW2)/q1
- 4.*s*(4.*s+q2+q1)/mW2
+ 16.*mW2*mZ2*s/q1/q2
+ 4.*s
+ 16.*mZ2*(tk-2.*mW2)/q1/q2/q2*tk*uk
+ 16.*(2.*mZ2+mW2-tk)/q1/q2*tk*uk
+ 16.*mW2*(s-mZ2-mW2)/q1/q2*uk
+ 16.*mZ2*(q1-2.*mW2)/q2/q2*uk
+ 32.*mW2*mW2*mZ2/q1/q2/q2*uk
+ 16.*mW2/q1*uk
+ 4.*uk
+ 8./q2*tk*uk
+ 4.*q1/mW2/mZ2*tk*uk
- 24./q1*tk*uk
- 4./mW2*tk*uk;
swap(mW2,mZ2);
swap(q1,q2);
swap(tk,uk);
return Val;
}
Energy2 t_u_Rud(Energy2 s ,Energy2 tk ,Energy2 uk ,Energy2 q1,Energy2 q2,
Energy2 q1h,Energy2 q2h,Energy2 mW2, Energy2 mZ2) {
Energy2 Val(0.*GeV2);
Val += (uk*s*(uk+3.*s+q1h)+s*s*(s+mZ2)-(s+uk)*(2.*mZ2*s+3.*mW2*s+mW2*q1h)
) * 8./q1/q2h/q2*uk
- (uk*(uk+3.*s+q1h-mW2)-(q2+s)*(q2-s)+s*(q2-mW2)+q1h*(q2-mW2)+mW2*q2
) * 4.*s/mZ2/q1/q2h*uk
- 4.*((s+uk+q2h-2.*mZ2)*(s+q1h-mZ2)-mZ2*q1)/mW2/q2*uk
+ 4.*(2.*s*uk+2.*mW2*uk+5.*s*s+2.*q1h*s-2.*mZ2*s)/q1/q2h*uk
+ 4.*(2.*s*uk-s*s-2.*q1h*s+2.*mW2*s+2.*mW2*q1h)/q1/q2h/q2*tk*uk
+ ((2.*uk+s)*(s+q1h)+s*(q2+q2h)+2.*q2*(s+q2h)-q1*s+q1*q2+q1h*q2h
) /mW2/mZ2*uk
+ 8.*s*(uk-q1h+mZ2)/q1/q2*uk
+ 4.*s*(-uk+s-q2+q1+q1h)/mZ2/q2h*uk
+ 4.*s*(-uk-q2+q1h)/mZ2/q1*uk
+ 8.*(mZ2*uk-s*s+mW2*s-2.*mZ2*q1-2.*mZ2*q1h)/q2h/q2*uk
+ 2.*(-uk-9.*s-4.*q2-5.*q2h-3.*q1-4.*q1h+8.*mZ2)/mW2*uk
+ 2.*(-4.*uk+3.*s+5.*q1+4.*q1h)/q2h*uk
+ 2.*(s*tk+q2*tk+s*s-q2*q2+q1h*q2)/mW2/mZ2*tk
- 8.*s*(tk+s+q1h)/mW2/q2*tk
+ 2.*(-tk+3.*s+q2-q1h)/mW2*tk
- 8.*s*s*s/q1h/q2
- 2.*s*q2*(s+q2)/mW2/mZ2
+ 2.*s*(2.*s+q2)/mZ2
+ 2.*s*(2.*s+q2)/mW2
- 16.*s*s/q1h
- 2.*s
- 16.*s*s/q1h/q2*tk
- 8.*s/q2*tk
- 16.*s/q1h*tk
+ 6.*s/mZ2*tk
+ 4.*s/q1*uk
+ 4.*s/mZ2*uk
+ 12.*uk
+ 4.*s*(tk+q1h-mW2)/mZ2/q1/q2h*tk*uk
+ 2.*(s+4.*q1+5.*q1h-4.*mZ2)/q2*uk
- 4.*s*s*s/q1h/q1/q2h/q2*tk*uk
- 4.*s*s/q1h/q2h/q2*tk*uk
- 4.*s*s/q1h/q1/q2*tk*uk
+ 8.*s*s/mW2/q1h/q2*tk*uk
- 4.*s*s/q1h/q1/q2h*tk*uk
+ 4.*(s+mZ2)/mW2/q2*tk*uk
- 4.*s/q1h/q2h*tk*uk
- 4.*s/q1h/q1*tk*uk
+ 12.*s/mW2/q1h*tk*uk
- (s+4.*q2)/mW2/mZ2*tk*uk
- 4.*(s+2.*mZ2)/q2h/q2*tk*uk
- 4.*(3.*s+2.*q1h)/q1/q2*tk*uk
- 8.*mW2/q1/q2h*tk*uk
+ 8./q2h*tk*uk
+ 8./q1*tk*uk;
swap(mW2,mZ2);
swap(q1,q2);
swap(tk,uk);
swap(q1h,q2h); // Note this swap is done in accordance with MC@NLO.
// It is not in NPB 383(1992)3-44 Eq.C.4!
Val += (uk*s*(uk+3.*s+q1h)+s*s*(s+mZ2)-(s+uk)*(2.*mZ2*s+3.*mW2*s+mW2*q1h)
) * 8./q1/q2h/q2*uk
- (uk*(uk+3.*s+q1h-mW2)-(q2+s)*(q2-s)+s*(q2-mW2)+q1h*(q2-mW2)+mW2*q2
) * 4.*s/mZ2/q1/q2h*uk
- 4.*((s+uk+q2h-2.*mZ2)*(s+q1h-mZ2)-mZ2*q1)/mW2/q2*uk
+ 4.*(2.*s*uk+2.*mW2*uk+5.*s*s+2.*q1h*s-2.*mZ2*s)/q1/q2h*uk
+ 4.*(2.*s*uk-s*s-2.*q1h*s+2.*mW2*s+2.*mW2*q1h)/q1/q2h/q2*tk*uk
+ ((2.*uk+s)*(s+q1h)+s*(q2+q2h)+2.*q2*(s+q2h)-q1*s+q1*q2+q1h*q2h
) /mW2/mZ2*uk
+ 8.*s*(uk-q1h+mZ2)/q1/q2*uk
+ 4.*s*(-uk+s-q2+q1+q1h)/mZ2/q2h*uk
+ 4.*s*(-uk-q2+q1h)/mZ2/q1*uk
+ 8.*(mZ2*uk-s*s+mW2*s-2.*mZ2*q1-2.*mZ2*q1h)/q2h/q2*uk
+ 2.*(-uk-9.*s-4.*q2-5.*q2h-3.*q1-4.*q1h+8.*mZ2)/mW2*uk
+ 2.*(-4.*uk+3.*s+5.*q1+4.*q1h)/q2h*uk
+ 2.*(s*tk+q2*tk+s*s-q2*q2+q1h*q2)/mW2/mZ2*tk
- 8.*s*(tk+s+q1h)/mW2/q2*tk
+ 2.*(-tk+3.*s+q2-q1h)/mW2*tk
- 8.*s*s*s/q1h/q2
- 2.*s*q2*(s+q2)/mW2/mZ2
+ 2.*s*(2.*s+q2)/mZ2
+ 2.*s*(2.*s+q2)/mW2
- 16.*s*s/q1h
- 2.*s
- 16.*s*s/q1h/q2*tk
- 8.*s/q2*tk
- 16.*s/q1h*tk
+ 6.*s/mZ2*tk
+ 4.*s/q1*uk
+ 4.*s/mZ2*uk
+ 12.*uk
+ 4.*s*(tk+q1h-mW2)/mZ2/q1/q2h*tk*uk
+ 2.*(s+4.*q1+5.*q1h-4.*mZ2)/q2*uk
- 4.*s*s*s/q1h/q1/q2h/q2*tk*uk
- 4.*s*s/q1h/q2h/q2*tk*uk
- 4.*s*s/q1h/q1/q2*tk*uk
+ 8.*s*s/mW2/q1h/q2*tk*uk
- 4.*s*s/q1h/q1/q2h*tk*uk
+ 4.*(s+mZ2)/mW2/q2*tk*uk
- 4.*s/q1h/q2h*tk*uk
- 4.*s/q1h/q1*tk*uk
+ 12.*s/mW2/q1h*tk*uk
- (s+4.*q2)/mW2/mZ2*tk*uk
- 4.*(s+2.*mZ2)/q2h/q2*tk*uk
- 4.*(3.*s+2.*q1h)/q1/q2*tk*uk
- 8.*mW2/q1/q2h*tk*uk
+ 8./q2h*tk*uk
+ 8./q1*tk*uk;
swap(mW2,mZ2);
swap(q1,q2);
swap(tk,uk);
swap(q1h,q2h); // Note this swap is done in accordance with MC@NLO.
// It is not in NPB 383(1992)3-44 Eq.C.4!
swap(tk,uk);
swap(q1,q2h);
swap(q2,q1h);
Val += (uk*s*(uk+3.*s+q1h)+s*s*(s+mZ2)-(s+uk)*(2.*mZ2*s+3.*mW2*s+mW2*q1h)
) * 8./q1/q2h/q2*uk
- (uk*(uk+3.*s+q1h-mW2)-(q2+s)*(q2-s)+s*(q2-mW2)+q1h*(q2-mW2)+mW2*q2
) * 4.*s/mZ2/q1/q2h*uk
- 4.*((s+uk+q2h-2.*mZ2)*(s+q1h-mZ2)-mZ2*q1)/mW2/q2*uk
+ 4.*(2.*s*uk+2.*mW2*uk+5.*s*s+2.*q1h*s-2.*mZ2*s)/q1/q2h*uk
+ 4.*(2.*s*uk-s*s-2.*q1h*s+2.*mW2*s+2.*mW2*q1h)/q1/q2h/q2*tk*uk
+ ((2.*uk+s)*(s+q1h)+s*(q2+q2h)+2.*q2*(s+q2h)-q1*s+q1*q2+q1h*q2h
) /mW2/mZ2*uk
+ 8.*s*(uk-q1h+mZ2)/q1/q2*uk
+ 4.*s*(-uk+s-q2+q1+q1h)/mZ2/q2h*uk
+ 4.*s*(-uk-q2+q1h)/mZ2/q1*uk
+ 8.*(mZ2*uk-s*s+mW2*s-2.*mZ2*q1-2.*mZ2*q1h)/q2h/q2*uk
+ 2.*(-uk-9.*s-4.*q2-5.*q2h-3.*q1-4.*q1h+8.*mZ2)/mW2*uk
+ 2.*(-4.*uk+3.*s+5.*q1+4.*q1h)/q2h*uk
+ 2.*(s*tk+q2*tk+s*s-q2*q2+q1h*q2)/mW2/mZ2*tk
- 8.*s*(tk+s+q1h)/mW2/q2*tk
+ 2.*(-tk+3.*s+q2-q1h)/mW2*tk
- 8.*s*s*s/q1h/q2
- 2.*s*q2*(s+q2)/mW2/mZ2
+ 2.*s*(2.*s+q2)/mZ2
+ 2.*s*(2.*s+q2)/mW2
- 16.*s*s/q1h
- 2.*s
- 16.*s*s/q1h/q2*tk
- 8.*s/q2*tk
- 16.*s/q1h*tk
+ 6.*s/mZ2*tk
+ 4.*s/q1*uk
+ 4.*s/mZ2*uk
+ 12.*uk
+ 4.*s*(tk+q1h-mW2)/mZ2/q1/q2h*tk*uk
+ 2.*(s+4.*q1+5.*q1h-4.*mZ2)/q2*uk
- 4.*s*s*s/q1h/q1/q2h/q2*tk*uk
- 4.*s*s/q1h/q2h/q2*tk*uk
- 4.*s*s/q1h/q1/q2*tk*uk
+ 8.*s*s/mW2/q1h/q2*tk*uk
- 4.*s*s/q1h/q1/q2h*tk*uk
+ 4.*(s+mZ2)/mW2/q2*tk*uk
- 4.*s/q1h/q2h*tk*uk
- 4.*s/q1h/q1*tk*uk
+ 12.*s/mW2/q1h*tk*uk
- (s+4.*q2)/mW2/mZ2*tk*uk
- 4.*(s+2.*mZ2)/q2h/q2*tk*uk
- 4.*(3.*s+2.*q1h)/q1/q2*tk*uk
- 8.*mW2/q1/q2h*tk*uk
+ 8./q2h*tk*uk
+ 8./q1*tk*uk;
swap(tk,uk);
swap(q1,q2h);
swap(q2,q1h);
swap(mW2,mZ2);
swap(q1,q1h);
swap(q2,q2h);
Val += (uk*s*(uk+3.*s+q1h)+s*s*(s+mZ2)-(s+uk)*(2.*mZ2*s+3.*mW2*s+mW2*q1h)
) * 8./q1/q2h/q2*uk
- (uk*(uk+3.*s+q1h-mW2)-(q2+s)*(q2-s)+s*(q2-mW2)+q1h*(q2-mW2)+mW2*q2
) * 4.*s/mZ2/q1/q2h*uk
- 4.*((s+uk+q2h-2.*mZ2)*(s+q1h-mZ2)-mZ2*q1)/mW2/q2*uk
+ 4.*(2.*s*uk+2.*mW2*uk+5.*s*s+2.*q1h*s-2.*mZ2*s)/q1/q2h*uk
+ 4.*(2.*s*uk-s*s-2.*q1h*s+2.*mW2*s+2.*mW2*q1h)/q1/q2h/q2*tk*uk
+ ((2.*uk+s)*(s+q1h)+s*(q2+q2h)+2.*q2*(s+q2h)-q1*s+q1*q2+q1h*q2h
) /mW2/mZ2*uk
+ 8.*s*(uk-q1h+mZ2)/q1/q2*uk
+ 4.*s*(-uk+s-q2+q1+q1h)/mZ2/q2h*uk
+ 4.*s*(-uk-q2+q1h)/mZ2/q1*uk
+ 8.*(mZ2*uk-s*s+mW2*s-2.*mZ2*q1-2.*mZ2*q1h)/q2h/q2*uk
+ 2.*(-uk-9.*s-4.*q2-5.*q2h-3.*q1-4.*q1h+8.*mZ2)/mW2*uk
+ 2.*(-4.*uk+3.*s+5.*q1+4.*q1h)/q2h*uk
+ 2.*(s*tk+q2*tk+s*s-q2*q2+q1h*q2)/mW2/mZ2*tk
- 8.*s*(tk+s+q1h)/mW2/q2*tk
+ 2.*(-tk+3.*s+q2-q1h)/mW2*tk
- 8.*s*s*s/q1h/q2
- 2.*s*q2*(s+q2)/mW2/mZ2
+ 2.*s*(2.*s+q2)/mZ2
+ 2.*s*(2.*s+q2)/mW2
- 16.*s*s/q1h
- 2.*s
- 16.*s*s/q1h/q2*tk
- 8.*s/q2*tk
- 16.*s/q1h*tk
+ 6.*s/mZ2*tk
+ 4.*s/q1*uk
+ 4.*s/mZ2*uk
+ 12.*uk
+ 4.*s*(tk+q1h-mW2)/mZ2/q1/q2h*tk*uk
+ 2.*(s+4.*q1+5.*q1h-4.*mZ2)/q2*uk
- 4.*s*s*s/q1h/q1/q2h/q2*tk*uk
- 4.*s*s/q1h/q2h/q2*tk*uk
- 4.*s*s/q1h/q1/q2*tk*uk
+ 8.*s*s/mW2/q1h/q2*tk*uk
- 4.*s*s/q1h/q1/q2h*tk*uk
+ 4.*(s+mZ2)/mW2/q2*tk*uk
- 4.*s/q1h/q2h*tk*uk
- 4.*s/q1h/q1*tk*uk
+ 12.*s/mW2/q1h*tk*uk
- (s+4.*q2)/mW2/mZ2*tk*uk
- 4.*(s+2.*mZ2)/q2h/q2*tk*uk
- 4.*(3.*s+2.*q1h)/q1/q2*tk*uk
- 8.*mW2/q1/q2h*tk*uk
+ 8./q2h*tk*uk
+ 8./q1*tk*uk;
swap(mW2,mZ2);
swap(q1,q1h);
swap(q2,q2h);
return Val;
}
Energy2 t_u_Ruu(Energy2 s ,Energy2 tk ,Energy2 uk ,Energy2 q1h,Energy2 q2h,
Energy2 mW2, Energy2 mZ2) {
return t_u_Rdd(s,tk,uk,q1h,q2h,mZ2,mW2);
}
Energy4 t_u_RZds(Energy2 s ,Energy2 tk ,Energy2 uk ,Energy2 q1,Energy2 q2,
Energy2 s2, Energy2 mW2, Energy2 mZ2) {
Energy4 Val(0.*GeV2*GeV2);
Energy2 sig(mZ2+mW2);
Val += ( q1*q2*(5./2.*s*s+5.*s*tk+3.*tk*tk)+(tk*uk*uk+q1*q1*q2)*(tk+s)
+ q1*(tk*tk*uk+s*uk*uk-s*s*tk+s*s*uk)+q1*q1*q1*(uk+s)-q1*q1*s*s2
) * 8./q1/q2
- ( tk*tk*(4.*uk+s+q1-2.*q2)+tk*(sqr(q1+q2)-q1*s-3.*q2*s-2.*q1*q1)
- q1*s*(4.*s-2.*q1-q2)+tk*uk*(q1+3.*s)
) * 4.*sig/q1/q2
- 4.*sig*sig*(s*(2.*s+q1)+tk*(uk+5./2.*tk+5.*s+q1+q2)
)/mW2/mZ2
+ 2.*sig*s2*(4.*sqr(s+tk)+tk*(uk+s+4.*q1+2.*q2)+2.*q1*(2.*s+q1)
)/mW2/mZ2
+ 4.*sig*sig*(s2+s-q1+q2)/q1/q2*tk
- 16.*mW2*mZ2*(tk*uk/2.+q2*tk-q1*s)/q1/q2
- 4.*s2*s2*q1*(tk+s+q1)/mW2/mZ2
+ sig*sig*sig*(uk+tk)/mW2/mZ2
+ 4.*mW2*mZ2*sig*(uk+tk)/q1/q2;
swap(mW2,mZ2);
swap(q1,q2);
swap(tk,uk);
Val += ( q1*q2*(5./2.*s*s+5.*s*tk+3.*tk*tk)+(tk*uk*uk+q1*q1*q2)*(tk+s)
+ q1*(tk*tk*uk+s*uk*uk-s*s*tk+s*s*uk)+q1*q1*q1*(uk+s)-q1*q1*s*s2
) * 8./q1/q2
- ( tk*tk*(4.*uk+s+q1-2.*q2)+tk*(sqr(q1+q2)-q1*s-3.*q2*s-2.*q1*q1)
- q1*s*(4.*s-2.*q1-q2)+tk*uk*(q1+3.*s)
) * 4.*sig/q1/q2
- 4.*sig*sig*(s*(2.*s+q1)+tk*(uk+5./2.*tk+5.*s+q1+q2)
)/mW2/mZ2
+ 2.*sig*s2*(4.*sqr(s+tk)+tk*(uk+s+4.*q1+2.*q2)+2.*q1*(2.*s+q1)
)/mW2/mZ2
+ 4.*sig*sig*(s2+s-q1+q2)/q1/q2*tk
- 16.*mW2*mZ2*(tk*uk/2.+q2*tk-q1*s)/q1/q2
- 4.*s2*s2*q1*(tk+s+q1)/mW2/mZ2
+ sig*sig*sig*(uk+tk)/mW2/mZ2
+ 4.*mW2*mZ2*sig*(uk+tk)/q1/q2;
swap(mW2,mZ2);
swap(q1,q2);
swap(tk,uk);
return Val;
}
Energy4 t_u_RZda(Energy2 s ,Energy2 tk ,Energy2 uk ,Energy2 q1,Energy2 q2,
Energy2 s2, Energy2 mW2, Energy2 mZ2) {
Energy4 Val(0.*GeV2*GeV2);
Val += 4.*mZ2*(2.*uk*uk-s*tk+q1*(uk-tk-s+q1+0.5*q2)+q2*(s-3.*q2)
) /q1/q2*tk
- 4.*mZ2*mZ2*(q1-tk-2.*s-q2)/q1/q2*tk
- 2.*mZ2*(tk+2.*s+2.*q2)/mW2*tk
- 2.*s2*(s+2.*q2)/mZ2*tk
+ 8.*mW2*mZ2*mZ2/q1/q2*tk
+ 2.*mZ2*mZ2/mW2*tk;
swap(mW2,mZ2); // N.B. Here we subtract!
Val -= 4.*mZ2*(2.*uk*uk-s*tk+q1*(uk-tk-s+q1+0.5*q2)+q2*(s-3.*q2)
) /q1/q2*tk
- 4.*mZ2*mZ2*(q1-tk-2.*s-q2)/q1/q2*tk
- 2.*mZ2*(tk+2.*s+2.*q2)/mW2*tk
- 2.*s2*(s+2.*q2)/mZ2*tk
+ 8.*mW2*mZ2*mZ2/q1/q2*tk
+ 2.*mZ2*mZ2/mW2*tk;
swap(mW2,mZ2);
swap(q1,q2); // N.B. Here we subtract!
swap(tk,uk);
Val -= 4.*mZ2*(2.*uk*uk-s*tk+q1*(uk-tk-s+q1+0.5*q2)+q2*(s-3.*q2)
) /q1/q2*tk
- 4.*mZ2*mZ2*(q1-tk-2.*s-q2)/q1/q2*tk
- 2.*mZ2*(tk+2.*s+2.*q2)/mW2*tk
- 2.*s2*(s+2.*q2)/mZ2*tk
+ 8.*mW2*mZ2*mZ2/q1/q2*tk
+ 2.*mZ2*mZ2/mW2*tk;
swap(q1,q2);
swap(tk,uk);
swap(mW2,mZ2); // N.B. Here we add!
swap(q1,q2);
swap(tk,uk);
Val += 4.*mZ2*(2.*uk*uk-s*tk+q1*(uk-tk-s+q1+0.5*q2)+q2*(s-3.*q2)
) /q1/q2*tk
- 4.*mZ2*mZ2*(q1-tk-2.*s-q2)/q1/q2*tk
- 2.*mZ2*(tk+2.*s+2.*q2)/mW2*tk
- 2.*s2*(s+2.*q2)/mZ2*tk
+ 8.*mW2*mZ2*mZ2/q1/q2*tk
+ 2.*mZ2*mZ2/mW2*tk;
swap(mW2,mZ2);
swap(q1,q2);
swap(tk,uk);
return Val;
}
Energy4 t_u_RZd(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1 , Energy2 q2 ,
Energy2 s2, Energy2 mW2, Energy2 mZ2) {
Energy4 Val(0.*GeV2*GeV2);
Val = t_u_RZds(s,tk,uk,q1,q2,s2,mW2,mZ2)
+ t_u_RZda(s,tk,uk,q1,q2,s2,mW2,mZ2);
return Val;
}
Energy4 t_u_RZu(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1h, Energy2 q2h,
Energy2 s2, Energy2 mW2, Energy2 mZ2) {
Energy4 Val(0.*GeV2*GeV2);
Val = t_u_RZd(s,tk,uk,q1h,q2h,s2,mZ2,mW2);
return Val;
}
Energy6 t_u_RZs(Energy2 s,Energy2 tk,Energy2 uk,Energy2 q1,Energy2 q2,
Energy2 s2,Energy2 mW2,Energy2 mZ2) {
Energy6 Val(0.*GeV2*GeV2*GeV2);
Energy2 sig(mZ2+mW2);
Val += 2.*sig*sig*s2*( tk*(3.*uk+9.*tk+19.*s+6.*q1+4.*q2)+8.*s*s+6.*q1*s
+ 2.*q1*q1
)/mW2/mZ2
- 2.*sig*sig*sig*(tk*(3.*uk+6.*tk+11.*s+2.*q1+2.*q2)+2.*s*(2.*s+q1))
/ mW2/mZ2
- 2.*sig*s2*s2*(tk*(uk+4.*tk+9.*s+6.*q1+2.*q2)+4.*sqr(s+q1)-2.*q1*s)
/mW2/mZ2
- 16.*sig*(2.*tk*(uk/2.-tk-s+q1+q2)-s*(3.*s/2.-2.*q1))
+ 8.*s2*(s*(s/2.+tk)+4.*q1*(tk+s+q1))
+ 4.*s2*s2*s2*q1*(tk+s+q1)/mW2/mZ2
+ 8.*sig*sig*(2.*tk+s/2.)
+ 2.*sig*sig*sig*sig*tk/mW2/mZ2
+ 32.*mW2*mZ2*s;
swap(mW2,mZ2);
swap(q1,q2);
swap(tk,uk);
Val += 2.*sig*sig*s2*( tk*(3.*uk+9.*tk+19.*s+6.*q1+4.*q2)+8.*s*s+6.*q1*s
+ 2.*q1*q1
)/mW2/mZ2
- 2.*sig*sig*sig*(tk*(3.*uk+6.*tk+11.*s+2.*q1+2.*q2)+2.*s*(2.*s+q1))
/ mW2/mZ2
- 2.*sig*s2*s2*(tk*(uk+4.*tk+9.*s+6.*q1+2.*q2)+4.*sqr(s+q1)-2.*q1*s)
/mW2/mZ2
- 16.*sig*(2.*tk*(uk/2.-tk-s+q1+q2)-s*(3.*s/2.-2.*q1))
+ 8.*s2*(s*(s/2.+tk)+4.*q1*(tk+s+q1))
+ 4.*s2*s2*s2*q1*(tk+s+q1)/mW2/mZ2
+ 8.*sig*sig*(2.*tk+s/2.)
+ 2.*sig*sig*sig*sig*tk/mW2/mZ2
+ 32.*mW2*mZ2*s;
swap(mW2,mZ2);
swap(q1,q2);
swap(tk,uk);
return Val;
}
Energy6 t_u_RZa(Energy2 s,Energy2 tk,Energy2 uk,Energy2 q1,Energy2 q2,
Energy2 s2,Energy2 mW2,Energy2 mZ2) {
Energy6 Val(0.*GeV2*GeV2*GeV2);
Val += - 2.*mZ2*(2.*tk+11.*s+18.*q2)*tk
- 2.*mZ2*mZ2*(2.*tk+3.*s+2.*q2)/mW2*tk
+ 2.*mZ2*s2*(tk+3.*s+4.*q2)/mW2*tk
- 2.*s2*s2*(s+2.*q2)/mW2*tk
+ 2.*mZ2*mZ2*mZ2/mW2*tk
+ 20.*mZ2*mZ2*tk;
swap(mW2,mZ2);
Val -= - 2.*mZ2*(2.*tk+11.*s+18.*q2)*tk
- 2.*mZ2*mZ2*(2.*tk+3.*s+2.*q2)/mW2*tk
+ 2.*mZ2*s2*(tk+3.*s+4.*q2)/mW2*tk
- 2.*s2*s2*(s+2.*q2)/mW2*tk
+ 2.*mZ2*mZ2*mZ2/mW2*tk
+ 20.*mZ2*mZ2*tk;
swap(mW2,mZ2);
swap(q1,q2);
swap(tk,uk);
Val -= - 2.*mZ2*(2.*tk+11.*s+18.*q2)*tk
- 2.*mZ2*mZ2*(2.*tk+3.*s+2.*q2)/mW2*tk
+ 2.*mZ2*s2*(tk+3.*s+4.*q2)/mW2*tk
- 2.*s2*s2*(s+2.*q2)/mW2*tk
+ 2.*mZ2*mZ2*mZ2/mW2*tk
+ 20.*mZ2*mZ2*tk;
swap(q1,q2);
swap(tk,uk);
swap(mW2,mZ2);
swap(q1,q2);
swap(tk,uk);
Val += - 2.*mZ2*(2.*tk+11.*s+18.*q2)*tk
- 2.*mZ2*mZ2*(2.*tk+3.*s+2.*q2)/mW2*tk
+ 2.*mZ2*s2*(tk+3.*s+4.*q2)/mW2*tk
- 2.*s2*s2*(s+2.*q2)/mW2*tk
+ 2.*mZ2*mZ2*mZ2/mW2*tk
+ 20.*mZ2*mZ2*tk;
swap(mW2,mZ2);
swap(q1,q2);
swap(tk,uk);
return Val;
}
Energy6 t_u_RZ(Energy2 s , Energy2 tk , Energy2 uk , Energy2 q1, Energy2 q2,
Energy2 s2, Energy2 mW2, Energy2 mZ2) {
Energy6 Val(0.*GeV2*GeV2*GeV2);
Val = t_u_RZs(s,tk,uk,q1,q2,s2,mW2,mZ2)
+ t_u_RZa(s,tk,uk,q1,q2,s2,mW2,mZ2);
return Val;
}
/***************************************************************************/
// t_u_M_R_qg is the real emission q + qb -> n + g matrix element
// exactly as defined in Eqs. C.9 of NPB 383(1992)3-44, multiplied by
// tk * uk!
Energy2 MEPP2VVPowheg::t_u_M_R_qg(realVVKinematics R) const {
// First the Born variables:
Energy2 s2(R.s2r());
Energy2 mW2(R.k12r());
Energy2 mZ2(R.k22r());
// Then the rest:
Energy2 s(R.sr());
Energy2 tk(R.tkr());
Energy2 uk(R.ukr());
Energy2 q1(R.q1r());
Energy2 q2(R.q2r());
Energy2 q1h(R.q1hatr());
Energy2 q2h(R.q2hatr());
Energy2 w1(R.w1r());
Energy2 w2(R.w2r());
double cosThetaW(sqrt(1.-sin2ThetaW_));
double eZ2(eZ2_);
double eZ(eZ_);
double gdL(gdL_);
double guL(guL_);
double gdR(gdR_);
double guR(guR_);
// W+W-
if(abs(mePartonData()[2]->id())==24&&abs(mePartonData()[3]->id())==24) {
double e2(sqr(gW_)*sin2ThetaW_);
if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) {
// N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set!
if(quark_->id()==-antiquark_->id()) {
eZ2 = 1./2.*sqr(s2-mW2)/Fij2_
* (e2*e2/s2/s2*(sqr( 2./3.+eZ*(guL+guR)/2./e2*s2/(s2-mW2/sqr(cosThetaW)))
+sqr( eZ*(guL-guR)/2./e2*s2/(s2-mW2/sqr(cosThetaW))))
);
eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s2-mW2)
* (gW_*gW_*e2/4./s2 *( 2./3.+2.*eZ*guL/2./e2*s2/(s2-mW2/sqr(cosThetaW))));
} else {
eZ2 =0.;
eZ =0.;
}
gdL = gW_/sqrt(2.);
guL = 0.;
}
else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) {
// N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set!
if(quark_->id()==-antiquark_->id()) {
eZ2 = 1./2.*sqr(s2-mW2)/Fij2_
* (e2*e2/s2/s2*(sqr(-1./3.+eZ*(gdL+gdR)/2./e2*s2/(s2-mW2/sqr(cosThetaW)))
+sqr( eZ*(gdL-gdR)/2./e2*s2/(s2-mW2/sqr(cosThetaW))))
);
eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s2-mW2)
* (gW_*gW_*e2/4./s2 *(-1./3.+2.*eZ*gdL/2./e2*s2/(s2-mW2/sqr(cosThetaW))));
} else {
eZ2 =0.;
eZ =0.;
}
guL = gW_/sqrt(2.);
gdL = 0.;
}
}
// ZZ
else if(mePartonData()[2]->id()==23&&mePartonData()[3]->id()==23) {
eZ = 0.;
eZ2 = 0.;
double gV2,gA2;
gV2 = sqr(guL/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_);
gA2 = sqr(guL/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_);
guL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
gV2 = sqr(gdL/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_);
gA2 = sqr(gdL/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_);
gdL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) gdL = guL;
else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) guL = gdL;
else {
cout << "MEPP2VVPowheg:" << endl;
cout << "ZZ needs 2 down-type / 2 up-type!" << endl;
}
}
Energy2 Val(0.*GeV2);
swap(s,tk);
swap(q2,w2);
swap(q2h,w1);
Val = -2.*pi*alphaS_*Fij2_*CF_/NC_
* ( gdL*gdL*t_u_Rdd(s,tk,uk,q1,q2,mW2,mZ2)
+ 2.*gdL*guL*t_u_Rud(s,tk,uk,q1,q2,q1h,q2h,mW2,mZ2)
+ guL*guL*t_u_Ruu(s,tk,uk,q1h,q2h,mW2,mZ2)
- 2.*eZ/(s2-mW2) * ( gdL
* t_u_RZd(s,tk,uk,q1 ,q2 ,s2,mW2,mZ2)
- guL
* t_u_RZu(s,tk,uk,q1h,q2h,s2,mW2,mZ2)
)
+ eZ2/sqr(s2-mW2) *t_u_RZ(s,tk,uk,q1,q2,s2,mW2,mZ2)
);
swap(s,tk);
swap(q2,w2);
swap(q2h,w1);
Val *= -tk/s * TR_/CF_;
return Val;
}
/***************************************************************************/
// t_u_M_R_gqb is the real emission g + qb -> n + q matrix element
// exactly as defined in Eqs. C.9 of NPB 383(1992)3-44, multiplied by
// tk * uk!
Energy2 MEPP2VVPowheg::t_u_M_R_gqb(realVVKinematics R) const {
// First the Born variables:
Energy2 s2(R.s2r());
Energy2 mW2(R.k12r());
Energy2 mZ2(R.k22r());
// Then the rest:
Energy2 s(R.sr());
Energy2 tk(R.tkr());
Energy2 uk(R.ukr());
Energy2 q1(R.q1r());
Energy2 q2(R.q2r());
Energy2 q1h(R.q1hatr());
Energy2 q2h(R.q2hatr());
Energy2 w1(R.w1r());
Energy2 w2(R.w2r());
double cosThetaW(sqrt(1.-sin2ThetaW_));
double eZ2(eZ2_);
double eZ(eZ_);
double gdL(gdL_);
double guL(guL_);
double gdR(gdR_);
double guR(guR_);
// W+W-
if(abs(mePartonData()[2]->id())==24&&abs(mePartonData()[3]->id())==24) {
double e2(sqr(gW_)*sin2ThetaW_);
if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) {
// N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set!
if(quark_->id()==-antiquark_->id()) {
eZ2 = 1./2.*sqr(s2-mW2)/Fij2_
* (e2*e2/s2/s2*(sqr( 2./3.+eZ*(guL+guR)/2./e2*s2/(s2-mW2/sqr(cosThetaW)))
+sqr( eZ*(guL-guR)/2./e2*s2/(s2-mW2/sqr(cosThetaW))))
);
eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s2-mW2)
* (gW_*gW_*e2/4./s2 *( 2./3.+2.*eZ*guL/2./e2*s2/(s2-mW2/sqr(cosThetaW))));
} else {
eZ2 =0.;
eZ =0.;
}
gdL = gW_/sqrt(2.);
guL = 0.;
}
else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) {
// N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set!
if(quark_->id()==-antiquark_->id()) {
eZ2 = 1./2.*sqr(s2-mW2)/Fij2_
* (e2*e2/s2/s2*(sqr(-1./3.+eZ*(gdL+gdR)/2./e2*s2/(s2-mW2/sqr(cosThetaW)))
+sqr( eZ*(gdL-gdR)/2./e2*s2/(s2-mW2/sqr(cosThetaW))))
);
eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s2-mW2)
* (gW_*gW_*e2/4./s2 *(-1./3.+2.*eZ*gdL/2./e2*s2/(s2-mW2/sqr(cosThetaW))));
} else {
eZ2 =0.;
eZ =0.;
}
guL = gW_/sqrt(2.);
gdL = 0.;
}
}
// ZZ
else if(mePartonData()[2]->id()==23&&mePartonData()[3]->id()==23) {
eZ = 0.;
eZ2 = 0.;
double gV2,gA2;
gV2 = sqr(guL/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_);
gA2 = sqr(guL/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_);
guL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
gV2 = sqr(gdL/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_);
gA2 = sqr(gdL/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_);
gdL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) gdL = guL;
else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) guL = gdL;
else {
cout << "MEPP2VVPowheg:" << endl;
cout << "ZZ needs 2 down-type / 2 up-type!" << endl;
}
}
Energy2 Val(0.*GeV2);
swap(s,uk);
swap(q1,w1);
swap(q1h,w2);
Val = -2.*pi*alphaS_*Fij2_*CF_/NC_
* ( gdL*gdL*t_u_Rdd(s,tk,uk,q1,q2,mW2,mZ2)
+ 2.*gdL*guL*t_u_Rud(s,tk,uk,q1,q2,q1h,q2h,mW2,mZ2)
+ guL*guL*t_u_Ruu(s,tk,uk,q1h,q2h,mW2,mZ2)
- 2.*eZ/(s2-mW2) * ( gdL
* t_u_RZd(s,tk,uk,q1 ,q2 ,s2,mW2,mZ2)
- guL
* t_u_RZu(s,tk,uk,q1h,q2h,s2,mW2,mZ2)
)
+ eZ2/sqr(s2-mW2) *t_u_RZ(s,tk,uk,q1,q2,s2,mW2,mZ2)
);
swap(s,uk);
swap(q1,w1);
swap(q1h,w2);
Val *= -uk/s * TR_/CF_;
return Val;
}
/***************************************************************************/
// The following six functions are I_{dd}^{(0)}, I_{ud}^{(0)},
// I_{uu}^{(0)}, F_{u}^{(0)}, F_{d}^{(0)}, H^{(0)} from Eqs. 3.9 - 3.14
// They make up the Born matrix element. Ixx functions correspond to the
// graphs with no TGC, Fx functions are due to non-TGC graphs interfering
// with TGC graphs, while the H function is due purely to TGC graphs.
double Idd0(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2);
double Iud0(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2);
double Iuu0(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2);
Energy2 Fu0(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2);
Energy2 Fd0(Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2);
Energy4 H0 (Energy2 s,Energy2 t,Energy2 u,Energy2 mW2,Energy2 mZ2);
/***************************************************************************/
// M_Born_WZ is the Born matrix element exactly as defined in Eqs. 3.3-3.14
// of of NPB 383(1992)3-44 (with a spin*colour averaging factor 1./4./NC_/NC_).
double MEPP2VVPowheg::M_Born_WZ(bornVVKinematics B) const {
Energy2 s(B.sb());
Energy2 t(B.tb());
Energy2 u(B.ub());
Energy2 mW2(B.k12b()); // N.B. the diboson masses are preserved in getting
Energy2 mZ2(B.k22b()); // the 2->2 from the 2->3 kinematics.
double cosThetaW(sqrt(1.-sin2ThetaW_));
double eZ2(eZ2_);
double eZ(eZ_);
double gdL(gdL_);
double guL(guL_);
double gdR(gdR_);
double guR(guR_);
// W+W-
if(abs(mePartonData()[2]->id())==24&&abs(mePartonData()[3]->id())==24) {
double e2(sqr(gW_)*sin2ThetaW_);
if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) {
// N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set!
if(quark_->id()==-antiquark_->id()) {
eZ2 = 1./2.*sqr(s-mW2)/Fij2_
* (e2*e2/s/s*(sqr( 2./3.+eZ*(guL+guR)/2./e2*s/(s-mW2/sqr(cosThetaW)))
+sqr( eZ*(guL-guR)/2./e2*s/(s-mW2/sqr(cosThetaW))))
);
eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s-mW2)
* (gW_*gW_*e2/4./s *( 2./3.+2.*eZ*guL/2./e2*s/(s-mW2/sqr(cosThetaW))));
} else {
eZ2 =0.;
eZ =0.;
}
gdL = gW_/sqrt(2.);
guL = 0.;
}
else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) {
// N.B. OLD eZ used to calculate new eZ2 *then* new eZ is set!
if(quark_->id()==-antiquark_->id()) {
eZ2 = 1./2.*sqr(s-mW2)/Fij2_
* (e2*e2/s/s*(sqr(-1./3.+eZ*(gdL+gdR)/2./e2*s/(s-mW2/sqr(cosThetaW)))
+sqr( eZ*(gdL-gdR)/2./e2*s/(s-mW2/sqr(cosThetaW))))
);
eZ = -1./2./Fij2_/(gW_*gW_/4./sqrt(Fij2_))*(s-mW2)
* (gW_*gW_*e2/4./s *(-1./3.+2.*eZ*gdL/2./e2*s/(s-mW2/sqr(cosThetaW))));
} else {
eZ2 =0.;
eZ =0.;
}
guL = gW_/sqrt(2.);
gdL = 0.;
}
}
// ZZ
else if(mePartonData()[2]->id()==23&&mePartonData()[3]->id()==23) {
eZ = 0.;
eZ2 = 0.;
double gV2,gA2;
gV2 = sqr(guL/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_);
gA2 = sqr(guL/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_);
guL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
gV2 = sqr(gdL/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_);
gA2 = sqr(gdL/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_);
gdL = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
if(abs(quark_->id())%2==0&&abs(antiquark_->id())%2==0) gdL = guL;
else if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) guL = gdL;
else {
cout << "MEPP2VVPowheg:" << endl;
cout << "ZZ needs 2 down-type / 2 up-type!" << endl;
}
}
return Fij2_/2./NC_
* (
gdL*gdL*Idd0(s,t,u,mW2,mZ2)
+ 2.*gdL*guL*Iud0(s,t,u,mW2,mZ2)
+ guL*guL*Iuu0(s,t,u,mW2,mZ2)
- 2.*eZ/(s-mW2) * ( gdL*Fd0(s,t,u,mW2,mZ2)
- guL*Fu0(s,t,u,mW2,mZ2)
)
+ eZ2/sqr(s-mW2) * H0(s,t,u,mW2,mZ2)
);
}
/***************************************************************************/
double Idd0(Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2) {
return 8.*((u*t/mW2/mZ2-1.)/4.+s/2.*(mW2+mZ2)/mW2/mZ2)
+ 8.*(u/t-mW2*mZ2/t/t);
}
/***************************************************************************/
double Iud0(Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2) {
return - 8.*((u*t/mW2/mZ2-1.)/4.+s/2.*(mW2+mZ2)/mW2/mZ2)
+ 8.*s/t/u*(mW2+mZ2);
}
/***************************************************************************/
double Iuu0(Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2) {
return Idd0(s,u,t,mW2,mZ2);
}
/***************************************************************************/
Energy2 Fd0 (Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2) {
return - 8.*s*( (u*t/mW2/mZ2-1.)*(1.-(mW2+mZ2)/s-4.*mW2*mZ2/s/t)/4.
+ (mW2+mZ2)/2./mW2/mZ2*(s-mW2-mZ2+2.*mW2*mZ2/t)
);
}
/***************************************************************************/
Energy2 Fu0 (Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2) {
return Fd0(s,u,t,mW2,mZ2);
}
/***************************************************************************/
Energy4 H0 (Energy2 s, Energy2 t, Energy2 u, Energy2 mW2, Energy2 mZ2) {
return 8.*s*s*(u*t/mW2/mZ2-1.)*( 1./4.-(mW2+mZ2)/2./s
+ (sqr(mW2+mZ2)+8.*mW2*mZ2)/4./s/s
)
+ 8.*s*s*(mW2+mZ2)/mW2/mZ2*(s/2.-mW2-mZ2+sqr(mW2-mZ2)/2./s);
}
/***************************************************************************/
bool MEPP2VVPowheg::sanityCheck() const {
bool alarm(false);
Energy2 prefacs(8.*pi*alphaS_*S_.sr() /S_.xr() );
Energy2 prefacsp(8.*pi*alphaS_*SCp_.sr() /SCp_.xr() );
Energy2 prefacsm(8.*pi*alphaS_*SCm_.sr() /SCm_.xr() );
Energy2 prefacp(8.*pi*alphaS_*Cp_.sr()/Cp_.xr());
Energy2 prefacm(8.*pi*alphaS_*Cm_.sr()/Cm_.xr());
double xp(Cp_.xr());
double xm(Cm_.xr());
double M_B_WW(M_Born_WW(B_));
double M_B_ZZ(M_Born_ZZ(B_));
double M_V_reg_WW(M_V_regular_WW(S_));
double M_V_reg_ZZ(M_V_regular_ZZ(S_));
Energy2 t_u_qqb_WW(t_u_M_R_qqb_WW(H_));
Energy2 t_u_qqb_ZZ(t_u_M_R_qqb_ZZ(H_));
// Check that the native leading order Herwig matrix
// element is equivalent to the WZ leading order matrix
// element in NPB 383 (1992) 3-44, with the relevant WZ->WW
// WZ->ZZ transformation applied (M_Born_).
// if(fabs((lo_me2_ - M_Born_)/M_Born_)>1.e-2) {
// alarm=true;
// cout << "lo_me2_ - M_Born_ (%) = "
// << lo_me2_ - M_Born_ << " ("
// << (lo_me2_ - M_Born_)/M_Born_*100. << ")\n";
// }
// Check that the transformation from NPB 383 (1992) 3-44 WZ
// matrix elements to WW matrix elements actually works, by
// comparing them to the explicit WW matrix elements in
// NPB 410 (1993) 280-324.
if(abs(mePartonData()[2]->id())==24&&abs(mePartonData()[3]->id())==24) {
if(fabs((M_Born_ -M_B_WW )/M_B_WW )>1.e-6) {
alarm=true;
cout << "WZ->WW transformation error!\n";
cout << "M_Born_ - M_B_WW (rel) = "
<< M_Born_ - M_B_WW << " ("
<< (M_Born_ - M_B_WW)/M_B_WW << ")\n";
cout << "M_Born_ = " << M_Born_ << endl;
cout << "M_B_WW = " << M_B_WW << endl;
}
if(fabs((M_V_regular_-M_V_reg_WW)/M_V_reg_WW)>1.e-6) {
alarm=true;
cout << "WZ->WW transformation error!\n";
cout << "M_V_regular_ - M_V_reg_WW (rel) = "
<< M_V_regular_ - M_V_reg_WW << " ("
<< (M_V_regular_ - M_V_reg_WW)/M_V_reg_WW << ")\n";
cout << "M_V_regular_ = " << M_V_regular_ << endl;
cout << "M_V_reg_WW = " << M_V_reg_WW << endl;
}
if(fabs((t_u_M_R_qqb_-t_u_qqb_WW)/t_u_qqb_WW)>1.e-6) {
alarm=true;
cout << "WZ->WW transformation error!\n";
cout << "t_u_M_R_qqb_ - t_u_qqb_WW (rel) = "
<< (t_u_M_R_qqb_ - t_u_qqb_WW)/GeV2 << " ("
<< (t_u_M_R_qqb_ - t_u_qqb_WW)/t_u_qqb_WW << ")\n";
cout << "t_u_M_R_qqb_ = " << t_u_M_R_qqb_/GeV2 << endl;
cout << "t_u_qqb_WW = " << t_u_qqb_WW /GeV2 << endl;
}
}
// Check that the transformation from NPB 383 (1992) 3-44 WZ
// matrix elements to ZZ matrix elements actually works, by
// comparing them to the explicit ZZ matrix elements in
// NPB 357 (1991) 409-438.
if(abs(mePartonData()[2]->id())==23&&abs(mePartonData()[3]->id())==23) {
if(fabs((M_Born_ -M_B_ZZ )/M_B_ZZ )>1.e-6) {
alarm=true;
cout << "WZ->ZZ transformation error!\n";
cout << "M_Born_ - M_B_ZZ (rel) = "
<< M_Born_ - M_B_ZZ << " ("
<< (M_Born_ - M_B_ZZ)/M_B_ZZ << ")\n";
cout << "M_Born_ = " << M_Born_ << endl;
cout << "M_B_ZZ = " << M_B_ZZ << endl;
}
if(fabs((M_V_regular_-M_V_reg_ZZ)/M_V_reg_ZZ)>1.e-6) {
alarm=true;
cout << "WZ->ZZ transformation error!\n";
cout << "M_V_regular_ - M_V_reg_ZZ (rel) = "
<< M_V_regular_ - M_V_reg_ZZ << " ("
<< (M_V_regular_ - M_V_reg_ZZ)/M_V_reg_ZZ << ")\n";
cout << "M_V_regular_ = " << M_V_regular_ << endl;
cout << "M_V_reg_ZZ = " << M_V_reg_ZZ << endl;
}
if(fabs((t_u_M_R_qqb_-t_u_qqb_ZZ)/t_u_qqb_ZZ)>1.e-6) {
alarm=true;
cout << "WZ->ZZ transformation error!\n";
cout << "t_u_M_R_qqb_ - t_u_qqb_ZZ (rel) = "
<< (t_u_M_R_qqb_ - t_u_qqb_ZZ)/GeV2 << " ("
<< (t_u_M_R_qqb_ - t_u_qqb_ZZ)/t_u_qqb_ZZ << ")\n";
cout << "t_u_M_R_qqb_ = " << t_u_M_R_qqb_/GeV2 << endl;
cout << "t_u_qqb_ZZ = " << t_u_qqb_ZZ /GeV2 << endl;
}
}
// Check the soft limit of the q + qbar matrix element.
Energy2 absDiff_qqbs
= t_u_M_R_qqb(S_) - prefacs*2.*CF_*M_Born_;
double relDiff_qqbs = absDiff_qqbs / t_u_M_R_qqb(S_);
if(fabs(relDiff_qqbs)>1.e-6) {
alarm=true;
cout << "\n";
cout << "t_u_M_R_qqb(S_) " << t_u_M_R_qqb(S_) /GeV2 << endl;
cout << "t_u_M_R_qqb(S_)-8*pi*alphaS*sHat/x*2*Cab*M_Born_ (rel):\n"
<< absDiff_qqbs / GeV2 << " (" << relDiff_qqbs << ")\n";
}
// Check the positive soft-collinearlimit of the q + qbar matrix element.
Energy2 absDiff_qqbsp
= t_u_M_R_qqb(SCp_) - prefacsp*2.*CF_*M_Born_;
double relDiff_qqbsp = absDiff_qqbsp / t_u_M_R_qqb(SCp_);
if(fabs(relDiff_qqbsp)>1.e-6) {
alarm=true;
cout << "\n";
cout << "t_u_M_R_qqb(SCp_) " << t_u_M_R_qqb(SCp_)/GeV2 << endl;
cout << "t_u_M_R_qqb(SCp_)-8*pi*alphaS*sHat/x*2*Cab*M_Born_ (rel):\n"
<< absDiff_qqbsp / GeV2 << " (" << relDiff_qqbsp << ")\n";
}
// Check the negative soft-collinearlimit of the q + qbar matrix element.
Energy2 absDiff_qqbsm
= t_u_M_R_qqb(SCm_) - prefacsm*2.*CF_*M_Born_;
double relDiff_qqbsm = absDiff_qqbsm / t_u_M_R_qqb(SCm_);
if(fabs(relDiff_qqbsm)>1.e-6) {
alarm=true;
cout << "\n";
cout << "t_u_M_R_qqb(SCm_) " << t_u_M_R_qqb(SCm_)/GeV2 << endl;
cout << "t_u_M_R_qqb(SCm_)-8*pi*alphaS*sHat/x*2*Cab*M_Born_ (rel):\n"
<< absDiff_qqbsm / GeV2 << " (" << relDiff_qqbsm << ")\n";
}
// Check the positive collinearlimit of the q + qbar matrix element.
Energy2 absDiff_qqbp
= t_u_M_R_qqb(Cp_) - prefacp*CF_*(1.+xp*xp)*M_Born_;
double relDiff_qqbp = absDiff_qqbp / t_u_M_R_qqb(Cp_);
if(fabs(relDiff_qqbp)>1.e-6) {
alarm=true;
cout << "\n";
cout << "t_u_M_R_qqb(Cp_) " << t_u_M_R_qqb(Cp_) /GeV2 << endl;
cout << "t_u_M_R_qqb(Cp_)-8*pi*alphaS*sHat/x*(1-x)*Pqq*M_Born_ (rel):\n"
<< absDiff_qqbp / GeV2 << " (" << relDiff_qqbp << ")\n";
}
// Check the negative collinearlimit of the q + qbar matrix element.
Energy2 absDiff_qqbm
= t_u_M_R_qqb(Cm_) - prefacm*CF_*(1.+xm*xm)*M_Born_;
double relDiff_qqbm = absDiff_qqbm / t_u_M_R_qqb(Cm_);
if(fabs(relDiff_qqbm)>1.e-6) {
alarm=true;
cout << "\n";
cout << "t_u_M_R_qqb(Cm_) " << t_u_M_R_qqb(Cm_) /GeV2 << endl;
cout << "t_u_M_R_qqb(Cm_)-8*pi*alphaS*sHat/x*(1-x)*Pqq*M_Born_ (rel):\n"
<< absDiff_qqbm / GeV2 << " (" << relDiff_qqbm << ")\n";
}
// Check the positive collinear limit of the g + qbar matrix element.
Energy2 absDiff_gqbp
= t_u_M_R_gqb(Cp_) - prefacp*(1.-xp)*TR_*(xp*xp+sqr(1.-xp))*M_Born_;
double relDiff_gqbp = absDiff_gqbp/ t_u_M_R_gqb(Cp_);
if(fabs(relDiff_gqbp)>1.e-6) {
alarm=true;
cout << "\n";
cout << "t_u_M_R_gqb(Cp_) " << t_u_M_R_gqb(Cp_) /GeV2 << endl;
cout << "t_u_M_R_gqb(Cp_)-8*pi*alphaS*sHat/x*(1-x)*Pgq*M_Born_ (rel):\n"
<< absDiff_gqbp / GeV2 << " (" << relDiff_gqbp << ")\n";
}
// Check the negative collinear limit of the q + g matrix element.
Energy2 absDiff_qgm
= t_u_M_R_qg(Cm_) - prefacm*(1.-xm)*TR_*(xm*xm+sqr(1.-xm))*M_Born_;
double relDiff_qgm = absDiff_qgm / t_u_M_R_qg(Cm_);
if(fabs(relDiff_qgm)>1.e-6) {
alarm=true;
cout << "\n";
cout << "t_u_M_R_qg(Cm_) " << t_u_M_R_qg(Cm_) /GeV2 << endl;
cout << "t_u_M_R_qg(Cm_)-8*pi*alphaS*sHat/x*(1-x)*Pgq*M_Born_ (rel):\n"
<< absDiff_qgm / GeV2 << " (" << relDiff_qgm << ")\n";
}
return alarm;
}
/***************************************************************************/
// M_Born_ZZ is the Born matrix element exactly as defined in Eqs. 2.18-2.19
// of of NPB 357(1991)409-438.
double MEPP2VVPowheg::M_Born_ZZ(bornVVKinematics B) const {
Energy2 s(B.sb());
Energy2 t(B.tb());
Energy2 u(B.ub());
Energy2 mZ2(B.k22b()); // the 2->2 from the 2->3 kinematics.
double cosThetaW(sqrt(1.-sin2ThetaW_));
double gV2,gA2,gX,gY,gZ;
gV2 = sqr(guL_/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_);
gA2 = sqr(guL_/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_);
gX = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
gV2 = sqr(gdL_/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_);
gA2 = sqr(gdL_/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_);
gY = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
gZ = gX;
if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) gZ = gY;
return 1./NC_*sqr(gZ*2.)*(t/u+u/t+4.*mZ2*s/t/u-mZ2*mZ2*(1./t/t+1./u/u));
}
/***************************************************************************/
// M_V_regular_ZZ is the one-loop ZZ matrix element exactly as defined in
// Eqs. B.1 & B.2 of NPB 357(1991)409-438.
double MEPP2VVPowheg::M_V_regular_ZZ(realVVKinematics S) const {
Energy2 s(S.bornVariables().sb());
Energy2 t(S.bornVariables().tb());
Energy2 u(S.bornVariables().ub());
Energy2 mZ2(S.k22r()); // the 2->2 from the 2->3 kinematics.
double beta(S.betaxr()); // N.B. for x=1 \beta_x=\beta in NPB 383(1992)3-44.
double cosThetaW(sqrt(1.-sin2ThetaW_));
double gV2,gA2,gX,gY,gZ;
gV2 = sqr(guL_/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_);
gA2 = sqr(guL_/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_);
gX = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
gV2 = sqr(gdL_/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_);
gA2 = sqr(gdL_/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_);
gY = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
gZ = gX;
if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) gZ = gY;
double M_V_reg(0.);
M_V_reg = 2.*s*sqr(gZ*2.)*4.*pi*alphaS_*CF_/NC_/sqr(4.*pi)/2.
*( 2.*sqr(t+mZ2)/sqr(beta)/s/t/u + 4.*s/(t-mZ2)/u
- ( 16.*t*t*t+(28.*s-68.*mZ2)*t*t+(18.*s*s-36.*mZ2*s+88.*mZ2*mZ2)*t
+ 18.*mZ2*mZ2*s-36.*mZ2*mZ2*mZ2
)/t/t/s/u
+ ( 12.*s/(t-mZ2)/u-4.*mZ2*s/sqr(t-mZ2)/u+2.*(t+4.*s)/s/u
- 6.*(s*s+mZ2*mZ2)/s/t/u+6.*mZ2*mZ2*(2.*mZ2-s)/t/t/s/u
)*log(-t/mZ2)
+ ( - ( 5.*t*t*t+(8.*s-18.*mZ2)*t*t+(6.*s*s+25.*mZ2*mZ2)*t
+ 6.*mZ2*mZ2*s-12.*mZ2*mZ2*mZ2
)/t/t/s/u
- 12.*mZ2*sqr(t+mZ2)/sqr(sqr(beta))/s/s/t/u
+ ( 3.*t*t-26.*mZ2*t-25.*mZ2*mZ2)/sqr(beta)/s/t/u
)*log(s/mZ2)
+ ( (-2.*t*t+8.*mZ2*t-2.*s*s-12.*mZ2*mZ2)/u + 4.*mZ2*mZ2*(2.*mZ2-s)/t/u)
/ (s*t)
* ( 2.*sqr(log(-t/mZ2))-4.*log(-t/mZ2)*log((mZ2-t)/mZ2)-4.*ReLi2(t/mZ2))
+ ( 4.*(t*t-5.*mZ2*t+s*s+10.*mZ2*mZ2)/s/u
+ 4.*mZ2*(-s*s+2.*mZ2*s-10.*mZ2*mZ2)/s/t/u
+ 8.*mZ2*mZ2*mZ2*(2.*mZ2-s)/t/t/s/u
)
/ (t-mZ2)
* (pi*pi/2.+log(-t/mZ2)*log(-t/s)-1./2.*sqr(log(-t/mZ2)))
+ ( ( (2.*s-3.*mZ2)*t*t+(6.*mZ2*mZ2-8.*mZ2*s)*t+2.*s*s*s-4.*mZ2*s*s
+ 12.*mZ2*mZ2*s-3.*mZ2*mZ2*mZ2
) /s/t/u
+ 12.*mZ2*mZ2*sqr(t+mZ2)/sqr(sqr(beta))/s/s/t/u
- (mZ2*t*t-30.*mZ2*mZ2*t-27.*mZ2*mZ2*mZ2)/beta/beta/s/t/u
)
/ (beta*s)
* (pi*pi/3.+sqr(log((1.-beta)/(1.+beta)))+4.*ReLi2(-(1.-beta)/(1.+beta)))
+ (4.*(t+4.*s-4.*mZ2)/3./s/u+4.*sqr(s-2.*mZ2)/3./s/t/u)*pi*pi
);
swap(t,u);
M_V_reg += 2.*s*sqr(gZ*2.)*4.*pi*alphaS_*CF_/NC_/sqr(4.*pi)/2.
*( 2.*sqr(t+mZ2)/sqr(beta)/s/t/u + 4.*s/(t-mZ2)/u
- ( 16.*t*t*t+(28.*s-68.*mZ2)*t*t+(18.*s*s-36.*mZ2*s+88.*mZ2*mZ2)*t
+ 18.*mZ2*mZ2*s-36.*mZ2*mZ2*mZ2
)/t/t/s/u
+ ( 12.*s/(t-mZ2)/u-4.*mZ2*s/sqr(t-mZ2)/u+2.*(t+4.*s)/s/u
- 6.*(s*s+mZ2*mZ2)/s/t/u+6.*mZ2*mZ2*(2.*mZ2-s)/t/t/s/u
)*log(-t/mZ2)
+ ( - ( 5.*t*t*t+(8.*s-18.*mZ2)*t*t+(6.*s*s+25.*mZ2*mZ2)*t
+ 6.*mZ2*mZ2*s-12.*mZ2*mZ2*mZ2
)/t/t/s/u
- 12.*mZ2*sqr(t+mZ2)/sqr(sqr(beta))/s/s/t/u
+ ( 3.*t*t-26.*mZ2*t-25.*mZ2*mZ2)/sqr(beta)/s/t/u
)*log(s/mZ2)
+ ( (-2.*t*t+8.*mZ2*t-2.*s*s-12.*mZ2*mZ2)/u + 4.*mZ2*mZ2*(2.*mZ2-s)/t/u)
/ (s*t)
* ( 2.*sqr(log(-t/mZ2))-4.*log(-t/mZ2)*log((mZ2-t)/mZ2)-4.*ReLi2(t/mZ2))
+ ( 4.*(t*t-5.*mZ2*t+s*s+10.*mZ2*mZ2)/s/u
+ 4.*mZ2*(-s*s+2.*mZ2*s-10.*mZ2*mZ2)/s/t/u
+ 8.*mZ2*mZ2*mZ2*(2.*mZ2-s)/t/t/s/u
)
/ (t-mZ2)
* (pi*pi/2.+log(-t/mZ2)*log(-t/s)-1./2.*sqr(log(-t/mZ2)))
+ ( ( (2.*s-3.*mZ2)*t*t+(6.*mZ2*mZ2-8.*mZ2*s)*t+2.*s*s*s-4.*mZ2*s*s
+ 12.*mZ2*mZ2*s-3.*mZ2*mZ2*mZ2
) /s/t/u
+ 12.*mZ2*mZ2*sqr(t+mZ2)/sqr(sqr(beta))/s/s/t/u
- (mZ2*t*t-30.*mZ2*mZ2*t-27.*mZ2*mZ2*mZ2)/beta/beta/s/t/u
)
/ (beta*s)
* (pi*pi/3.+sqr(log((1.-beta)/(1.+beta)))+4.*ReLi2(-(1.-beta)/(1.+beta)))
+ (4.*(t+4.*s-4.*mZ2)/3./s/u+4.*sqr(s-2.*mZ2)/3./s/t/u)*pi*pi
);
return M_V_reg;
}
/***************************************************************************/
// t_u_M_R_qqb_ZZ is the real emission q + qb -> n + g matrix element
// exactly as defined in Eqs. C.1 of NPB 357(1991)409-438, multiplied by
// tk * uk!
Energy2 MEPP2VVPowheg::t_u_M_R_qqb_ZZ(realVVKinematics R) const {
// First the Born variables:
Energy2 mZ2(R.k22r());
// Then the rest:
Energy2 s(R.sr());
Energy2 tk(R.tkr());
Energy2 uk(R.ukr());
Energy2 q1(R.q1r());
Energy2 q2(R.q2r());
Energy2 q1h(R.q1hatr());
Energy2 q2h(R.q2hatr());
double cosThetaW(sqrt(1.-sin2ThetaW_));
double gV2,gA2,gX,gY,gZ;
gV2 = sqr(guL_/2.-gW_/2./cosThetaW*2./3.*sin2ThetaW_);
gA2 = sqr(guL_/2.+gW_/2./cosThetaW*2./3.*sin2ThetaW_);
gX = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
gV2 = sqr(gdL_/2.+gW_/2./cosThetaW*1./3.*sin2ThetaW_);
gA2 = sqr(gdL_/2.-gW_/2./cosThetaW*1./3.*sin2ThetaW_);
gY = sqrt(gV2*gV2+gA2*gA2+6.*gA2*gV2)/2.;
gZ = gX;
if(abs(quark_->id())%2==1&&abs(antiquark_->id())%2==1) gZ = gY;
Energy2 t_u_qqb(0.*GeV2);
t_u_qqb = (2.*s)*sqr(gZ*2.)*4.*pi*alphaS_*CF_/NC_/2.
* ( - ( tk*uk*uk+2.*s*uk*uk-tk*tk*uk
- 2.*s*tk*uk+mZ2*(tk*tk-uk*uk+2.*s*uk-2.*s*tk-2.*s*s)
)/q1h/q1/q2h/s*tk
+ 2.*(tk*uk*uk-mZ2*uk*(s+3.*tk)+mZ2*mZ2*(2.*uk-s))/q1/q2/s
+ ( tk*uk*(uk+s)-mZ2*(uk*uk+3.*tk*uk+3.*s*uk+s*tk)
+ 2.*mZ2*mZ2*(uk+tk+2.*s)
)/q1h/q1/q2/s*tk
+ ( tk*(uk*uk+tk*uk-s*s)+mZ2*(4.*s*uk-3.*tk*uk-tk*tk+4.*s*s)
)/q1h/q2/s
- ( tk*uk+s*uk-s*tk-s*s+2.*mZ2*(s-tk) ) /q1h/q1/s*tk
+ q2*(tk*uk-s*uk-2.*s*tk-2.*s*s)/q1/q2h/s
+ 2.*(tk*uk-tk*tk-s*tk-s*s+mZ2*(2.*s-uk))/q1/s
- 2.*mZ2*(uk*uk-2.*mZ2*uk+2.*mZ2*mZ2)/q1/q1/q2/s*tk
+ (2.*s*uk+tk*tk+3.*s*tk+2*s*s)/q1h/s
+ q1*(uk+s)*(uk+tk)/q1h/q2h/s
+ (tk*uk+s*uk+3.*s*tk+2.*s*s-mZ2*(uk+tk+2.*s))/q1h/q2h/s*uk
+ (uk-tk)/2./q1h/q2h/s*(q1*(uk+s)/q2/tk-q2*(tk+s)/q1/uk)*tk*uk
+ (tk-2.*mZ2)*(uk-2.*mZ2)/q1h/q1/q2h/q2*tk*uk
- (q1*q1+q2*q2)/q1/q2
- 2.*mZ2*(q2-2.*mZ2)/q1/q1/s*tk
);
swap(tk ,uk );
swap(q1 ,q2 );
swap(q1h,q2h);
t_u_qqb += (2.*s)*sqr(gZ*2.)*4.*pi*alphaS_*CF_/NC_/2.
* ( - ( tk*uk*uk+2.*s*uk*uk-tk*tk*uk
- 2.*s*tk*uk+mZ2*(tk*tk-uk*uk+2.*s*uk-2.*s*tk-2.*s*s)
)/q1h/q1/q2h/s*tk
+ 2.*(tk*uk*uk-mZ2*uk*(s+3.*tk)+mZ2*mZ2*(2.*uk-s))/q1/q2/s
+ ( tk*uk*(uk+s)-mZ2*(uk*uk+3.*tk*uk+3.*s*uk+s*tk)
+ 2.*mZ2*mZ2*(uk+tk+2.*s)
)/q1h/q1/q2/s*tk
+ ( tk*(uk*uk+tk*uk-s*s)+mZ2*(4.*s*uk-3.*tk*uk-tk*tk+4.*s*s)
)/q1h/q2/s
- ( tk*uk+s*uk-s*tk-s*s+2.*mZ2*(s-tk) ) /q1h/q1/s*tk
+ q2*(tk*uk-s*uk-2.*s*tk-2.*s*s)/q1/q2h/s
+ 2.*(tk*uk-tk*tk-s*tk-s*s+mZ2*(2.*s-uk))/q1/s
- 2.*mZ2*(uk*uk-2.*mZ2*uk+2.*mZ2*mZ2)/q1/q1/q2/s*tk
+ (2.*s*uk+tk*tk+3.*s*tk+2*s*s)/q1h/s
+ q1*(uk+s)*(uk+tk)/q1h/q2h/s
+ (tk*uk+s*uk+3.*s*tk+2.*s*s-mZ2*(uk+tk+2.*s))/q1h/q2h/s*uk
+ (uk-tk)/2./q1h/q2h/s*(q1*(uk+s)/q2/tk-q2*(tk+s)/q1/uk)*tk*uk
+ (tk-2.*mZ2)*(uk-2.*mZ2)/q1h/q1/q2h/q2*tk*uk
- (q1*q1+q2*q2)/q1/q2
- 2.*mZ2*(q2-2.*mZ2)/q1/q1/s*tk
);
swap(tk ,uk );
swap(q1 ,q2 );
swap(q1h,q2h);
swap(q1 ,q1h);
swap(q2 ,q2h);
t_u_qqb += (2.*s)*sqr(gZ*2.)*4.*pi*alphaS_*CF_/NC_/2.
* ( - ( tk*uk*uk+2.*s*uk*uk-tk*tk*uk
- 2.*s*tk*uk+mZ2*(tk*tk-uk*uk+2.*s*uk-2.*s*tk-2.*s*s)
)/q1h/q1/q2h/s*tk
+ 2.*(tk*uk*uk-mZ2*uk*(s+3.*tk)+mZ2*mZ2*(2.*uk-s))/q1/q2/s
+ ( tk*uk*(uk+s)-mZ2*(uk*uk+3.*tk*uk+3.*s*uk+s*tk)
+ 2.*mZ2*mZ2*(uk+tk+2.*s)
)/q1h/q1/q2/s*tk
+ ( tk*(uk*uk+tk*uk-s*s)+mZ2*(4.*s*uk-3.*tk*uk-tk*tk+4.*s*s)
)/q1h/q2/s
- ( tk*uk+s*uk-s*tk-s*s+2.*mZ2*(s-tk) ) /q1h/q1/s*tk
+ q2*(tk*uk-s*uk-2.*s*tk-2.*s*s)/q1/q2h/s
+ 2.*(tk*uk-tk*tk-s*tk-s*s+mZ2*(2.*s-uk))/q1/s
- 2.*mZ2*(uk*uk-2.*mZ2*uk+2.*mZ2*mZ2)/q1/q1/q2/s*tk
+ (2.*s*uk+tk*tk+3.*s*tk+2*s*s)/q1h/s
+ q1*(uk+s)*(uk+tk)/q1h/q2h/s
+ (tk*uk+s*uk+3.*s*tk+2.*s*s-mZ2*(uk+tk+2.*s))/q1h/q2h/s*uk
+ (uk-tk)/2./q1h/q2h/s*(q1*(uk+s)/q2/tk-q2*(tk+s)/q1/uk)*tk*uk
+ (tk-2.*mZ2)*(uk-2.*mZ2)/q1h/q1/q2h/q2*tk*uk
- (q1*q1+q2*q2)/q1/q2
- 2.*mZ2*(q2-2.*mZ2)/q1/q1/s*tk
);
swap(q1 ,q1h);
swap(q2 ,q2h);
swap(tk ,uk );
swap(q1 ,q2h);
swap(q2 ,q1h);
t_u_qqb += (2.*s)*sqr(gZ*2.)*4.*pi*alphaS_*CF_/NC_/2.
* ( - ( tk*uk*uk+2.*s*uk*uk-tk*tk*uk
- 2.*s*tk*uk+mZ2*(tk*tk-uk*uk+2.*s*uk-2.*s*tk-2.*s*s)
)/q1h/q1/q2h/s*tk
+ 2.*(tk*uk*uk-mZ2*uk*(s+3.*tk)+mZ2*mZ2*(2.*uk-s))/q1/q2/s
+ ( tk*uk*(uk+s)-mZ2*(uk*uk+3.*tk*uk+3.*s*uk+s*tk)
+ 2.*mZ2*mZ2*(uk+tk+2.*s)
)/q1h/q1/q2/s*tk
+ ( tk*(uk*uk+tk*uk-s*s)+mZ2*(4.*s*uk-3.*tk*uk-tk*tk+4.*s*s)
)/q1h/q2/s
- ( tk*uk+s*uk-s*tk-s*s+2.*mZ2*(s-tk) ) /q1h/q1/s*tk
+ q2*(tk*uk-s*uk-2.*s*tk-2.*s*s)/q1/q2h/s
+ 2.*(tk*uk-tk*tk-s*tk-s*s+mZ2*(2.*s-uk))/q1/s
- 2.*mZ2*(uk*uk-2.*mZ2*uk+2.*mZ2*mZ2)/q1/q1/q2/s*tk
+ (2.*s*uk+tk*tk+3.*s*tk+2*s*s)/q1h/s
+ q1*(uk+s)*(uk+tk)/q1h/q2h/s
+ (tk*uk+s*uk+3.*s*tk+2.*s*s-mZ2*(uk+tk+2.*s))/q1h/q2h/s*uk
+ (uk-tk)/2./q1h/q2h/s*(q1*(uk+s)/q2/tk-q2*(tk+s)/q1/uk)*tk*uk
+ (tk-2.*mZ2)*(uk-2.*mZ2)/q1h/q1/q2h/q2*tk*uk
- (q1*q1+q2*q2)/q1/q2
- 2.*mZ2*(q2-2.*mZ2)/q1/q1/s*tk
);
swap(tk ,uk );
swap(q1 ,q2h);
swap(q2 ,q1h);
return t_u_qqb;
}
/***************************************************************************/
// M_B_WW is the Born matrix element exactly as defined in Eqs. 3.2-3.8
// of of NPB 410(1993)280-384.
double MEPP2VVPowheg::M_Born_WW(bornVVKinematics B) const {
Energy2 s(B.sb());
Energy2 t(B.tb());
Energy2 u(B.ub());
Energy2 mW2(B.k12b()); // N.B. the diboson masses are preserved in getting
bool up_type = abs(quark_->id())%2==0 ? true : false;
double Qi = up_type ? 2./3. : -1./3. ;
double giL = up_type ? guL_/2. : gdL_/2.;
double giR = up_type ? guR_/2. : gdR_/2.;
double e2 = sqr(gW_)*sin2ThetaW_;
double cos2ThetaW(1.-sin2ThetaW_);
double ctt_i(gW_*gW_*gW_*gW_/16.);
InvEnergy2 cts_i(gW_*gW_*e2/4./s *(Qi+2.*eZ_*giL/e2*s/(s-mW2/cos2ThetaW)));
InvEnergy4 css_i(e2*e2/s/s*(sqr(Qi+eZ_*(giL+giR)/e2*s/(s-mW2/cos2ThetaW))
+sqr( eZ_*(giL-giR)/e2*s/(s-mW2/cos2ThetaW)))
);
ctt_i *= 8.*Fij2_/gW_/gW_;
cts_i *= sqrt(8.*Fij2_/gW_/gW_);
if(quark_->id()!=-antiquark_->id()) {
cts_i = 0./GeV2;
css_i = 0./GeV2/GeV2;
}
if(!up_type) swap(t,u);
double signf = up_type ? 1. : -1.;
return 1./4./NC_
* (
ctt_i*( 16.*(u*t/mW2/mW2-1.)*(1./4.+mW2*mW2/t/t)+16.*s/mW2)
- cts_i*( 16.*(u*t/mW2/mW2-1.)*(s/4.-mW2/2.-mW2*mW2/t)
+ 16.*s*(s/mW2-2.+2.*mW2/t)
)
*signf
+
css_i*( 8.*(u*t/mW2/mW2-1.)*(s*s/4.-s*mW2+3.*mW2*mW2)
+ 8.*s*s*(s/mW2-4.)
)
);
}
/***************************************************************************/
// M_V_regular_WW is the regular part of the one-loop WW matrix element
// exactly as defined in Eqs. C.1 - C.7 of of NPB 410(1993)280-324 ***
// modulo a factor 1/(2s) ***, which is a flux factor that those authors
// absorb in the matrix element.
double MEPP2VVPowheg::M_V_regular_WW(realVVKinematics S) const {
Energy2 s(S.bornVariables().sb());
Energy2 t(S.bornVariables().tb());
Energy2 u(S.bornVariables().ub());
Energy2 mW2(S.k12r()); // N.B. the diboson masses are preserved in getting
double beta(S.betaxr()); // N.B. for x=1 \beta_x=\beta in NPB 383(1992)3-44.
bool up_type = abs(quark_->id())%2==0 ? true : false;
double Qi = up_type ? 2./3. : -1./3.;
double giL = up_type ? guL_/2. : gdL_/2.;
double giR = up_type ? guR_/2. : gdR_/2.;
double e2 = sqr(gW_)*sin2ThetaW_;
double cos2ThetaW(1.-sin2ThetaW_);
double ctt_i(gW_*gW_*gW_*gW_/16.);
InvEnergy2 cts_i(gW_*gW_*e2/4./s *(Qi+2.*eZ_*giL/e2*s/(s-mW2/cos2ThetaW)));
InvEnergy4 css_i(e2*e2/s/s*(sqr(Qi+eZ_*(giL+giR)/e2*s/(s-mW2/cos2ThetaW))
+sqr( eZ_*(giL-giR)/e2*s/(s-mW2/cos2ThetaW)))
);
ctt_i *= 8.*Fij2_/gW_/gW_;
cts_i *= sqrt(8.*Fij2_/gW_/gW_);
if(quark_->id()!=-antiquark_->id()) {
cts_i = 0./GeV2;
css_i = 0./GeV2/GeV2;
}
if(!up_type) swap(t,u);
double signf = up_type ? 1. : -1.;
InvEnergy4 TildeI4 = ( 2.*sqr(log(-t/mW2))-4.*log((mW2-t)/mW2)*log(-t/mW2)
- 4.*ReLi2(t/mW2) )/s/t;
InvEnergy2 TildeI3t = 1./(mW2-t)
*(sqr(log(mW2/s))/2.-sqr(log(-t/s))/2.-pi*pi/2.);
InvEnergy2 TildeI3l = 1./s/beta*( 4.*ReLi2((beta-1.)/(beta+1.))
+ sqr(log((1.-beta)/(1.+beta)))
+ pi*pi/3.);
double Fup1_st(0.);
Fup1_st = 4.*(80.*t*t+73.*s*t-140.*mW2*t+72.*mW2*mW2)/t/t
- 4.*sqr(4.*t+s)/s/beta/beta/t
- 128.*(t+2.*s)/mW2
+ 64.*t*(t+s)/mW2/mW2
- (32.*(t*t-3.*s*t-3.*mW2*mW2)/t/t+128.*s/(t-mW2))*log(-t/mW2)
+ ( 8.*(6.*t*t+8.*s*t-19.*mW2*t+12.*mW2*mW2)/t/t
- (32.*t*t-128.*s*t-26.*s*s)/s/beta/beta/t
+ 6.*sqr(4.*t+s)/s/sqr(sqr(beta))/t
)*log(s/mW2)
+ 32.*s*(2.*mW2*mW2/t-u)*TildeI4
- 64.*(t-mW2)*(2.*mW2*mW2/t/t-u/t)*TildeI3t
+ ( (16.*t*(4.*mW2-u)-49.*s*s+72.*mW2*s-48.*mW2*mW2)/2./t
+ 2.*(8.*t*t-14.*s*t-3.*s*s)/beta/beta/t
- 3.*sqr(4.*t+s)/2./sqr(sqr(beta))/t
)*TildeI3l
+ 32./3.*( 2.*(t+2.*s)/mW2
- (3.*t+2.*s-4.*mW2)/t
- t*(t+s)/mW2/mW2
)*pi*pi;
Energy2 Jup1_st(0.*GeV2);
Jup1_st = -128.*(t*t+2.*s*t+2.*s*s)/mW2
- 16.*(t*t-21.*s*t-26.*mW2*t+34.*mW2*s+17.*mW2*mW2)/t
+ 64.*s*t*(t+s)/mW2/mW2 +32.*s*s/(t-mW2)
+ ( 16.*(t-5.*s+2.*mW2)-48.*mW2*(2.*s+mW2)/t
+ 64.*s*(2.*t+s)/(t-mW2) - 32.*s*s*t/sqr(t-mW2)
)*log(-t/mW2)
+ ( 16.*(4.*t+s)/beta/beta
- 16.*(3.*t-2.*s)
+ 48.*mW2*(2.*t-2.*s-mW2)/t
)*log(s/mW2)
+ 16.*s*(t*(2.*s+u)-2.*mW2*(2.*s+mW2))*TildeI4
+ 32.*(t-mW2)*(2.*mW2*(2.*s+mW2)/t-2.*s-u)*TildeI3t
+ ( 32.*s*t-12.*s*s+32.*mW2*mW2
- 16.*mW2*(2.*t+7.*s)-4.*s*(4.*t+s)/beta/beta
)*TildeI3l
+ 32./3.*( 2.*(t*t+2.*s*t+2.*s*s)/mW2
- s*t*(t+s)/mW2/mW2-2.*mW2*(2.*t-2.*s-mW2)/t-t-4.*s
)*pi*pi;
Energy4 Kup1_st(0.*GeV2*GeV2);
Kup1_st = 16.*( 12.*t*t+20.*s*t-24.*mW2*t+17.*s*s-4.*mW2*s+12.*mW2*mW2
+ s*s*t*(t+s)/mW2/mW2-2.*s*(2.*t*t+3.*s*t+2.*s*s)/mW2)
*(2.-pi*pi/3.);
return pi*alphaS_*CF_/NC_/(sqr(4.*pi))
* ( ctt_i*Fup1_st - cts_i*Jup1_st*signf + css_i*Kup1_st );
}
/***************************************************************************/
// t_u_M_R_qqb is the real emission q + qb -> n + g matrix element
// exactly as defined in Eqs. C.1 of NPB 383(1992)3-44, multiplied by
// tk * uk!
Energy2 MEPP2VVPowheg::t_u_M_R_qqb_WW(realVVKinematics R) const {
// First the Born variables:
Energy2 s2(R.s2r());
Energy2 mW2(R.k12r());
// Then the rest:
Energy2 s(R.sr());
Energy2 tk(R.tkr());
Energy2 uk(R.ukr());
Energy2 q1(R.q1r());
Energy2 q2(R.q2r());
Energy2 q1h(R.q1hatr());
Energy2 q2h(R.q2hatr());
bool up_type = abs(quark_->id())%2==0 ? true : false;
double Qi = up_type ? 2./3. : -1./3.;
double giL = up_type ? guL_/2. : gdL_/2.;
double giR = up_type ? guR_/2. : gdR_/2.;
double e2 = sqr(gW_)*sin2ThetaW_;
double cos2ThetaW(1.-sin2ThetaW_);
double ctt_i(gW_*gW_*gW_*gW_/16.);
InvEnergy2 cts_i(gW_*gW_*e2/4./s2*(Qi+2.*eZ_*giL/e2*s2/(s2-mW2/cos2ThetaW)));
InvEnergy4 css_i(e2*e2/s2/s2*(sqr(Qi+eZ_*(giL+giR)/e2*s2/(s2-mW2/cos2ThetaW))
+sqr( eZ_*(giL-giR)/e2*s2/(s2-mW2/cos2ThetaW)))
);
ctt_i *= 8.*Fij2_/gW_/gW_;
cts_i *= sqrt(8.*Fij2_/gW_/gW_);
if(quark_->id()!=-antiquark_->id()) {
cts_i = 0./GeV2;
css_i = 0./GeV2/GeV2;
}
if(!up_type) {
swap(q1,q1h);
swap(q2,q2h);
}
double signf = up_type ? 1. : -1.;
Energy2 t_u_Xup(0.*GeV2);
Energy4 t_u_Yup(0.*GeV2*GeV2);
Energy6 t_u_Zup(0.*GeV2*GeV2*GeV2);
t_u_Xup = 32.*mW2*(tk*uk+3.*q2*uk+q2*s+q1*q2)/q1/q2/q2*tk
+ 32.*mW2*q1/q2/q2*uk
- 64.*mW2*s/q2
- 32.*tk*(uk-q2)/q1/q2*tk
+ 64.*mW2*mW2*mW2/q1/q1/q2*tk
- 16.*(2.*tk-2.*s-q2)/q2*uk
+ 16.*s*(2.*s+2.*q1+q2/2.)/q2
- 8.*(4.*tk+uk+9.*s+2.*q2+2.*q1)/mW2*tk
- 16.*s*(2.*s+q1)/mW2
- 64.*mW2*mW2*(tk*uk+q2*tk+q1*uk-q2*s/2.)/q1/q2/q2
+ 8.*s2*q1*(tk+s+q1)/mW2/mW2;
swap(tk,uk);
swap(q1,q2);
t_u_Xup += 32.*mW2*(tk*uk+3.*q2*uk+q2*s+q1*q2)/q1/q2/q2*tk
+ 32.*mW2*q1/q2/q2*uk
- 64.*mW2*s/q2
- 32.*tk*(uk-q2)/q1/q2*tk
+ 64.*mW2*mW2*mW2/q1/q1/q2*tk
- 16.*(2.*tk-2.*s-q2)/q2*uk
+ 16.*s*(2.*s+2.*q1+q2/2.)/q2
- 8.*(4.*tk+uk+9.*s+2.*q2+2.*q1)/mW2*tk
- 16.*s*(2.*s+q1)/mW2
- 64.*mW2*mW2*(tk*uk+q2*tk+q1*uk-q2*s/2.)/q1/q2/q2
+ 8.*s2*q1*(tk+s+q1)/mW2/mW2;
swap(tk,uk);
swap(q1,q2);
t_u_Yup = - 16.*tk*(uk*(uk+s+q1)+q2*(s-2.*q1))/q1/q2*tk
- 32.*mW2*mW2*s/q2
- 32.*mW2*mW2*mW2/q1/q2*tk
+ 16.*(2.*q2*uk+s*s+q1*s+5.*q2*s+q1*q2+2.*q2*q2)/q2*tk
- 16.*(q2*q2+s*s-q2*s)/q1*tk
+ 16.*s*(q1*s+3./2.*q2*s+q1*q2-q1*q1)/q2
+ 16.*mW2*tk*(4.*uk+s+q1-2.*q2)/q1/q2*tk
+ 16.*mW2*(3.*s*uk+q1*uk-q1*s-3.*q2*s-q1*q1+q2*q2)/q1/q2*tk
+ 16.*mW2*s*(q2-4.*s+2.*q1)/q2
- 8.*s2*(4.*tk+uk+9.*s+4.*q1+2.*q2)/mW2*tk
- 16.*s2*(2.*s*s+2.*q1*s+q1*q1)/mW2
- 32.*mW2*mW2*(tk+uk/2.+2.*s-q1)/q1/q2*tk
+ 8.*s2*s2*q1*(tk+s+q1)/mW2/mW2;
swap(tk,uk);
swap(q1,q2);
t_u_Yup += - 16.*tk*(uk*(uk+s+q1)+q2*(s-2.*q1))/q1/q2*tk
- 32.*mW2*mW2*s/q2
- 32.*mW2*mW2*mW2/q1/q2*tk
+ 16.*(2.*q2*uk+s*s+q1*s+5.*q2*s+q1*q2+2.*q2*q2)/q2*tk
- 16.*(q2*q2+s*s-q2*s)/q1*tk
+ 16.*s*(q1*s+3./2.*q2*s+q1*q2-q1*q1)/q2
+ 16.*mW2*tk*(4.*uk+s+q1-2.*q2)/q1/q2*tk
+ 16.*mW2*(3.*s*uk+q1*uk-q1*s-3.*q2*s-q1*q1+q2*q2)/q1/q2*tk
+ 16.*mW2*s*(q2-4.*s+2.*q1)/q2
- 8.*s2*(4.*tk+uk+9.*s+4.*q1+2.*q2)/mW2*tk
- 16.*s2*(2.*s*s+2.*q1*s+q1*q1)/mW2
- 32.*mW2*mW2*(tk+uk/2.+2.*s-q1)/q1/q2*tk
+ 8.*s2*s2*q1*(tk+s+q1)/mW2/mW2;
swap(tk,uk);
swap(q1,q2);
t_u_Zup = 8.*s2*(9.*tk+3.*uk+20.*s+10.*q1+4.*q2)*tk
+ 8.*s2*(17./2.*s*s+10.*q1*s+6.*q1*q1)
- 4.*s2*s2*(4.*tk+uk+9.*s+6.*q1+2.*q2)/mW2*tk
- 8.*s2*s2*(2.*s*s+3.*q1*s+2.*q1*q1)/mW2
- 16.*mW2*(2.*tk+5.*uk+7.*s+6.*q1+6.*q2)*tk
- 16.*mW2*s*(s+6.*q1)
+ 4.*s2*s2*s2*q1*(tk+s+q1)/mW2/mW2
+ 48.*mW2*mW2*s2;
swap(tk,uk);
swap(q1,q2);
t_u_Zup += 8.*s2*(9.*tk+3.*uk+20.*s+10.*q1+4.*q2)*tk
+ 8.*s2*(17./2.*s*s+10.*q1*s+6.*q1*q1)
- 4.*s2*s2*(4.*tk+uk+9.*s+6.*q1+2.*q2)/mW2*tk
- 8.*s2*s2*(2.*s*s+3.*q1*s+2.*q1*q1)/mW2
- 16.*mW2*(2.*tk+5.*uk+7.*s+6.*q1+6.*q2)*tk
- 16.*mW2*s*(s+6.*q1)
+ 4.*s2*s2*s2*q1*(tk+s+q1)/mW2/mW2
+ 48.*mW2*mW2*s2;
swap(tk,uk);
swap(q1,q2);
return -pi*alphaS_*CF_/NC_
* ( ctt_i*t_u_Xup - cts_i*t_u_Yup*signf + css_i*t_u_Zup );
}
/***************************************************************************/
// The game here is to get this helicity amplitude squared to return all the
// same values as t_u_M_R_qqb above, TIMES a further factor tk*uk!
Energy2 MEPP2VVPowheg::t_u_M_R_qqb_hel_amp(realVVKinematics R) const {
using namespace ThePEG::Helicity;
// qqb_hel_amps_.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1Half,
// PDT::Spin1,PDT::Spin1,
// PDT::Spin1));
double sum_hel_amps_sqr(0.);
tcPDPtr p1data(quark_);
tcPDPtr p2data(antiquark_);
tcPDPtr k1data(mePartonData()[2]);
tcPDPtr k2data(mePartonData()[3]);
tcPDPtr kdata(getParticleData(ParticleID::g));
if(k1data->id()==-24&&k2data->id()==24) swap(k1data,k2data);
SpinorWaveFunction qSpinor(R.p1r(),p1data,incoming);
SpinorBarWaveFunction qbSpinor(R.p2r(),p2data,incoming);
vector<SpinorWaveFunction> q;
vector<SpinorBarWaveFunction> qb;
for(unsigned int ix=0;ix<2;ix++) {
qSpinor.reset(ix);
qbSpinor.reset(ix);
q.push_back(qSpinor);
qb.push_back(qbSpinor);
}
VectorWaveFunction v1Polarization(R.k1r(),k1data,outgoing);
VectorWaveFunction v2Polarization(R.k2r(),k2data,outgoing);
vector<VectorWaveFunction> v1;
vector<VectorWaveFunction> v2;
for(unsigned int ix=0;ix<3;ix++) {
v1Polarization.reset(ix);
v2Polarization.reset(ix);
v1.push_back(v1Polarization);
v2.push_back(v2Polarization);
}
VectorWaveFunction gPolarization(R.kr(),kdata,outgoing);
vector<VectorWaveFunction> g;
for(unsigned int ix=0;ix<3;ix+=2) {
gPolarization.reset(ix);
g.push_back(gPolarization);
}
AbstractFFVVertexPtr ffg = FFGvertex_;
AbstractFFVVertexPtr ffv1 = k1data->id()==23 ? FFZvertex_ : FFWvertex_;
AbstractFFVVertexPtr ffv2 = k2data->id()==23 ? FFZvertex_ : FFWvertex_;
// Collecting information for intermediate fermions
vector<tcPDPtr> tc;
if(abs(k1data->id())==24&&abs(k2data->id())==24) {
if(abs(p1data->id())%2==0)
for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(1+2*ix));
else
for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(2+2*ix));
}
else if(k1data->id()==23&&k2data->id()==23) tc.push_back(p1data);
else if(abs(k1data->id())==24&&k2data->id()==23) tc.push_back(p2data);
// Loop over helicities summing the relevant diagrams
for(unsigned int p1hel=0;p1hel<2;++p1hel) {
for(unsigned int p2hel=0;p2hel<2;++p2hel) {
for(unsigned int khel=0;khel<2;++khel) {
SpinorWaveFunction p1_k = ffg->evaluate(mu_UV2(),5,p1data,q[p1hel],g[khel]);
SpinorBarWaveFunction p2_k = ffg->evaluate(mu_UV2(),5,p2data,qb[p2hel],g[khel]);
for(unsigned int k1hel=0;k1hel<3;++k1hel) {
for(unsigned int k2hel=0;k2hel<3;++k2hel) {
// If helicity is exactly conserved (massless quarks) skip if p1hel=p2hel
// but if the production ME is required first fill it with (0.,0.).
if((p1hel==p2hel)&&helicityConservation_) {
// if(getMatrix) {
// if(khel==0)
// qqb_hel_amps_(p1hel,p2hel,k1hel,k2hel,0) = Complex(0.,0.);
// else
// qqb_hel_amps_(p1hel,p2hel,k1hel,k2hel,2) = Complex(0.,0.);
// }
continue;
}
vector<Complex> diagrams;
// Get all t-channel diagram contributions
tcPDPtr intermediate_t;
for(unsigned int ix=0;ix<tc.size();ix++) {
intermediate_t = (!(k1data->id()==24&&k2data->id()==-24)) ? p2data : tc[ix];
SpinorWaveFunction p1_v1 = ffv1->evaluate(scale(),5,intermediate_t,q[p1hel],v1[k1hel]);
SpinorBarWaveFunction p2_v2 = ffv2->evaluate(scale(),5,intermediate_t,qb[p2hel],v2[k2hel]);
// First calculate all the off-shell fermion currents
// Now calculate the 6 t-channel diagrams
// q+qb->g+v1+v2, q+qb->v1+g+v2, q+qb->v1+v2+g
if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==1))) {
diagrams.push_back(ffv1->evaluate(scale(),p1_k,p2_v2,v1[k1hel]));
diagrams.push_back(ffg->evaluate(mu_UV2(),p1_v1,p2_v2,g[khel]));
diagrams.push_back(ffv2->evaluate(scale(),p1_v1,p2_k,v2[k2hel]));
}
intermediate_t = (!(k1data->id()==24&&k2data->id()==-24)) ? p1data : tc[ix];
SpinorWaveFunction p1_v2 = ffv2->evaluate(scale(),5,intermediate_t,q[p1hel],v2[k2hel]);
SpinorBarWaveFunction p2_v1 = ffv1->evaluate(scale(),5,intermediate_t,qb[p2hel],v1[k1hel]);
// q+qb->g+v2+v1, q+qb->v2+g+v1, q+qb->v2+v1+g
if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==0))) {
diagrams.push_back(ffv2->evaluate(scale(),p1_k,p2_v1,v2[k2hel]));
diagrams.push_back(ffg->evaluate(mu_UV2(),p1_v2,p2_v1,g[khel]));
diagrams.push_back(ffv1->evaluate(scale(),p1_v2,p2_k,v1[k1hel]));
}
}
// Note: choosing 3 as the second argument in WWWvertex_->evaluate()
// sets option 3 in thepeg/Helicity/Vertex/VertexBase.cc , which
// means the propagator does not contain a width factor (which is
// good re. gauge invariance).
// If W+Z / W-Z calculate the two V+jet-like s-channel diagrams
if(abs(k1data->id())==24&&k2data->id()==23) {
// The off-shell s-channel boson current
VectorWaveFunction k1_k2 =
WWWvertex_->evaluate(scale(),3,k1data->CC(),v2[k2hel],v1[k1hel]);
// q+qb->g+v1*->g+v1+v2, q+qb->v1*+g->v1+v2+g
diagrams.push_back(ffv1->evaluate(scale(),p1_k,qb[p2hel],k1_k2));
diagrams.push_back(ffv1->evaluate(scale(),q[p1hel],p2_k,k1_k2));
}
// If W+W- calculate the four V+jet-like s-channel diagrams
if((k1data->id()==24&&k2data->id()==-24)&&(p1data->id()==-p2data->id())) {
// The off-shell s-channel boson current
VectorWaveFunction k1_k2;
// q+qb->g+Z0*->g+v1+v2,q+qb->Z0*+g->v1+v2+g,
tcPDPtr Z0 = getParticleData(ParticleID::Z0);
k1_k2 = WWWvertex_->evaluate(scale(),3,Z0,v2[k2hel],v1[k1hel]);
diagrams.push_back(FFZvertex_->evaluate(scale(),p1_k,qb[p2hel],k1_k2));
diagrams.push_back(FFZvertex_->evaluate(scale(),q[p1hel],p2_k,k1_k2));
// q+qb->g+gamma*->g+v1+v2,q+qb->gamma*+g->v1+v2+g,
tcPDPtr gamma = getParticleData(ParticleID::gamma);
k1_k2 = WWWvertex_->evaluate(scale(),3,gamma,v2[k2hel],v1[k1hel]);
diagrams.push_back(FFPvertex_->evaluate(scale(),p1_k,qb[p2hel],k1_k2));
diagrams.push_back(FFPvertex_->evaluate(scale(),q[p1hel],p2_k,k1_k2));
}
// Add up all diagrams to get the total amplitude:
Complex hel_amp(0.);
for(unsigned int ix=0;ix<diagrams.size();ix++) hel_amp += diagrams[ix];
// If we need to fill the production ME we do it here:
// if(getMatrix) {
// if(khel==0)
// qqb_hel_amps_(p1hel,p2hel,k1hel,k2hel,0) = hel_amp;
// else
// qqb_hel_amps_(p1hel,p2hel,k1hel,k2hel,2) = hel_amp;
// }
sum_hel_amps_sqr += norm(hel_amp);
}
}
}
}
}
// Fill up the remaining bits of the production ME, corresponding
// to longitudinal gluon polarization, with (0.,0.).
// if(getMatrix) {
// for(unsigned int p1hel=0;p1hel<2;++p1hel) {
// for(unsigned int p2hel=0;p2hel<2;++p2hel) {
// for(unsigned int k1hel=0;k1hel<3;++k1hel) {
// for(unsigned int k2hel=0;k2hel<3;++k2hel) {
// qqb_hel_amps_(p1hel,p2hel,k1hel,k2hel,1) = Complex(0.,0.);
// }
// }
// }
// }
// }
// Spin and colour averaging factors = 1/4 * CF * 1/3 = 1/9
sum_hel_amps_sqr /= 9.;
// Symmetry factor for identical Z bosons in the final state
if(k1data->id()==23&&k2data->id()==23) sum_hel_amps_sqr /= 2.;
return sum_hel_amps_sqr*R.tkr()*R.ukr()*UnitRemoval::InvE2;
}
/***************************************************************************/
// The game here is to get this helicity amplitude squared to return all the
// same values as t_u_M_R_qg above, TIMES a further factor tk*uk!
Energy2 MEPP2VVPowheg::t_u_M_R_qg_hel_amp(realVVKinematics R) const {
using namespace ThePEG::Helicity;
// qg_hel_amps_.reset(ProductionMatrixElement(PDT::Spin1Half,PDT::Spin1,
// PDT::Spin1,PDT::Spin1,
// PDT::Spin1Half));
double sum_hel_amps_sqr(0.);
tcPDPtr p1data(quark_);
tcPDPtr p2data(getParticleData(ParticleID::g));
tcPDPtr k1data(mePartonData()[2]);
tcPDPtr k2data(mePartonData()[3]);
tcPDPtr kdata (antiquark_->CC());
if(k1data->id()==-24&&k2data->id()==24) swap(k1data,k2data);
SpinorWaveFunction qinSpinor(R.p1r(),p1data,incoming);
SpinorBarWaveFunction qoutSpinor(R.kr(),kdata,outgoing);
vector<SpinorWaveFunction> qin;
vector<SpinorBarWaveFunction> qout;
for(unsigned int ix=0;ix<2;ix++) {
qinSpinor.reset(ix);
qoutSpinor.reset(ix);
qin.push_back(qinSpinor);
qout.push_back(qoutSpinor);
}
VectorWaveFunction v1Polarization(R.k1r(),k1data,outgoing);
VectorWaveFunction v2Polarization(R.k2r(),k2data,outgoing);
vector<VectorWaveFunction> v1;
vector<VectorWaveFunction> v2;
for(unsigned int ix=0;ix<3;ix++) {
v1Polarization.reset(ix);
v2Polarization.reset(ix);
v1.push_back(v1Polarization);
v2.push_back(v2Polarization);
}
VectorWaveFunction gPolarization(R.p2r(),p2data,incoming);
vector<VectorWaveFunction> g;
for(unsigned int ix=0;ix<3;ix+=2) {
gPolarization.reset(ix);
g.push_back(gPolarization);
}
AbstractFFVVertexPtr ffg = FFGvertex_;
AbstractFFVVertexPtr ffv1 = k1data->id()==23 ? FFZvertex_ : FFWvertex_;
AbstractFFVVertexPtr ffv2 = k2data->id()==23 ? FFZvertex_ : FFWvertex_;
// Collecting information for intermediate fermions
vector<tcPDPtr> tc;
if(abs(k1data->id())==24&&abs(k2data->id())==24) {
if(abs(p1data->id())%2==0)
for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(1+2*ix));
else
for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(2+2*ix));
}
else if(k1data->id()==23&&k2data->id()==23) tc.push_back(p1data);
else if(abs(k1data->id())==24&&k2data->id()==23) tc.push_back(kdata->CC());
// Loop over helicities summing the relevant diagrams
for(unsigned int p1hel=0;p1hel<2;++p1hel) {
for(unsigned int p2hel=0;p2hel<2;++p2hel) {
for(unsigned int khel=0;khel<2;++khel) {
SpinorWaveFunction p1_p2 = ffg->evaluate(mu_UV2(),5,p1data,qin[p1hel],g[p2hel]);
SpinorBarWaveFunction p2_k = ffg->evaluate(mu_UV2(),5,kdata->CC(),qout[khel],g[p2hel]);
for(unsigned int k1hel=0;k1hel<3;++k1hel) {
for(unsigned int k2hel=0;k2hel<3;++k2hel) {
// If helicity is exactly conserved (massless quarks) skip if p1hel!=khel
// but if the production ME is required first fill it with (0.,0.).
if((p1hel!=khel)&&helicityConservation_) {
// if(getMatrix) {
// if(p2hel==0)
// qg_hel_amps_(p1hel,0,k1hel,k2hel,khel) = Complex(0.,0.);
// else
// qg_hel_amps_(p1hel,2,k1hel,k2hel,khel) = Complex(0.,0.);
// }
continue;
}
vector<Complex> diagrams;
// Get all t-channel diagram contributions
tcPDPtr intermediate_q;
for(unsigned int ix=0;ix<tc.size();ix++) {
intermediate_q = (!(k1data->id()==24&&k2data->id()==-24)) ? antiquark_ : tc[ix];
SpinorWaveFunction p1_v1 = ffv1->evaluate(scale(),5,intermediate_q,qin[p1hel],v1[k1hel]);
SpinorBarWaveFunction k_v2 = ffv2->evaluate(scale(),5,intermediate_q,qout[khel],v2[k2hel]);
// First calculate all the off-shell fermion currents
// Now calculate the 6 abelian diagrams
// q+g->v1+v2+q with 2 t-channel propagators, 1 s- and 1 t-channel and 2 t-channel ones.
if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==1))) {
diagrams.push_back(ffv2->evaluate(scale(),p1_v1,p2_k,v2[k2hel]));
diagrams.push_back(ffg->evaluate(mu_UV2(),p1_v1,k_v2,g[p2hel]));
diagrams.push_back(ffv1->evaluate(scale(),p1_p2,k_v2,v1[k1hel]));
}
intermediate_q = (!(k1data->id()==24&&k2data->id()==-24)) ? p1data : tc[ix];
SpinorWaveFunction p1_v2 = ffv2->evaluate(scale(),5,intermediate_q,qin[p1hel],v2[k2hel]);
SpinorBarWaveFunction k_v1 = ffv1->evaluate(scale(),5,intermediate_q,qout[khel],v1[k1hel]);
// q+g->v2+v1+q, with 2 t-channel propagators, 1 s- and 1 t-channel and 2 t-channel ones.
if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==0))) {
diagrams.push_back(ffv1->evaluate(scale(),p1_v2,p2_k,v1[k1hel]));
diagrams.push_back(ffg->evaluate(mu_UV2(),p1_v2,k_v1,g[p2hel]));
diagrams.push_back(ffv2->evaluate(scale(),p1_p2,k_v1,v2[k2hel]));
}
}
// If W+Z / W-Z calculate the two V+jet-like s-channel diagrams
if(abs(k1data->id())==24&&k2data->id()==23) {
// The off-shell s-channel boson current
VectorWaveFunction k1_k2 =
WWWvertex_->evaluate(scale(),3,k1data->CC(),v2[k2hel],v1[k1hel]);
// q+qb->g+v1*->g+v1+v2, q+qb->v1*+g->v1+v2+g
diagrams.push_back(ffv1->evaluate(scale(),p1_p2,qout[khel],k1_k2));
diagrams.push_back(ffv1->evaluate(scale(),qin[p1hel],p2_k,k1_k2));
}
// If W+W- calculate the four V+jet-like s-channel diagrams
if((k1data->id()==24&&k2data->id()==-24)&&(p1data->id()==kdata->id())) {
// The off-shell s-channel boson current
VectorWaveFunction k1_k2;
// q+qb->g+Z0*->g+v1+v2,q+qb->Z0*+g->v1+v2+g,
tcPDPtr Z0 = getParticleData(ParticleID::Z0);
k1_k2 = WWWvertex_->evaluate(scale(),3,Z0,v2[k2hel],v1[k1hel]);
diagrams.push_back(FFZvertex_->evaluate(scale(),p1_p2,qout[khel],k1_k2));
diagrams.push_back(FFZvertex_->evaluate(scale(),qin[p1hel],p2_k,k1_k2));
// q+qb->g+gamma*->g+v1+v2,q+qb->gamma*+g->v1+v2+g,
tcPDPtr gamma = getParticleData(ParticleID::gamma);
k1_k2 = WWWvertex_->evaluate(scale(),3,gamma,v2[k2hel],v1[k1hel]);
diagrams.push_back(FFPvertex_->evaluate(scale(),p1_p2,qout[khel],k1_k2));
diagrams.push_back(FFPvertex_->evaluate(scale(),qin[p1hel],p2_k,k1_k2));
}
// Add up all diagrams to get the total amplitude:
Complex hel_amp(0.);
for(unsigned int ix=0;ix<diagrams.size();ix++) hel_amp += diagrams[ix];
// If we need to fill the production ME we do it here:
// if(getMatrix) {
// if(p2hel==0)
// qg_hel_amps_(p1hel,0,k1hel,k2hel,khel) = hel_amp;
// else
// qg_hel_amps_(p1hel,2,k1hel,k2hel,khel) = hel_amp;
// }
sum_hel_amps_sqr += norm(hel_amp);
}
}
}
}
}
// Fill up the remaining bits of the production ME, corresponding
// to longitudinal gluon polarization, with (0.,0.).
// if(getMatrix) {
// for(unsigned int p1hel=0;p1hel<2;++p1hel) {
// for(unsigned int k1hel=0;k1hel<3;++k1hel) {
// for(unsigned int k2hel=0;k2hel<3;++k2hel) {
// for(unsigned int khel=0;khel<2;++khel) {
// qg_hel_amps_(p1hel,1,k1hel,k2hel,khel) = Complex(0.,0.);
// }
// }
// }
// }
// }
// Spin and colour averaging factors = 1/4 * TR * 1/3 = 1/24
sum_hel_amps_sqr /= 24.;
// Symmetry factor for identical Z bosons in the final state
if(k1data->id()==23&&k2data->id()==23) sum_hel_amps_sqr /= 2.;
return sum_hel_amps_sqr*R.tkr()*R.ukr()*UnitRemoval::InvE2;
}
/***************************************************************************/
// The game here is to get this helicity amplitude squared to return all the
// same values as t_u_M_R_gqb above, TIMES a further factor tk*uk!
Energy2 MEPP2VVPowheg::t_u_M_R_gqb_hel_amp(realVVKinematics R) const {
using namespace ThePEG::Helicity;
// gqb_hel_amps_.reset(ProductionMatrixElement(PDT::Spin1,PDT::Spin1Half,
// PDT::Spin1,PDT::Spin1,
// PDT::Spin1Half));
double sum_hel_amps_sqr(0.);
tcPDPtr p1data(getParticleData(ParticleID::g));
tcPDPtr p2data(antiquark_);
tcPDPtr k1data(mePartonData()[2]);
tcPDPtr k2data(mePartonData()[3]);
tcPDPtr kdata (quark_->CC());
if(k1data->id()==-24&&k2data->id()==24) swap(k1data,k2data);
SpinorBarWaveFunction qbinSpinor(R.p2r(),p2data,incoming);
SpinorWaveFunction qboutSpinor(R.kr(),kdata,outgoing);
vector<SpinorBarWaveFunction> qbin;
vector<SpinorWaveFunction> qbout;
for(unsigned int ix=0;ix<2;ix++) {
qbinSpinor.reset(ix);
qboutSpinor.reset(ix);
qbin.push_back(qbinSpinor);
qbout.push_back(qboutSpinor);
}
VectorWaveFunction v1Polarization(R.k1r(),k1data,outgoing);
VectorWaveFunction v2Polarization(R.k2r(),k2data,outgoing);
vector<VectorWaveFunction> v1;
vector<VectorWaveFunction> v2;
for(unsigned int ix=0;ix<3;ix++) {
v1Polarization.reset(ix);
v2Polarization.reset(ix);
v1.push_back(v1Polarization);
v2.push_back(v2Polarization);
}
VectorWaveFunction gPolarization(R.p1r(),p1data,incoming);
vector<VectorWaveFunction> g;
for(unsigned int ix=0;ix<3;ix+=2) {
gPolarization.reset(ix);
g.push_back(gPolarization);
}
AbstractFFVVertexPtr ffg = FFGvertex_;
AbstractFFVVertexPtr ffv1 = k1data->id()==23 ? FFZvertex_ : FFWvertex_;
AbstractFFVVertexPtr ffv2 = k2data->id()==23 ? FFZvertex_ : FFWvertex_;
// Collecting information for intermediate fermions
vector<tcPDPtr> tc;
if(abs(k1data->id())==24&&abs(k2data->id())==24) {
if(abs(p2data->id())%2==0)
for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(1+2*ix));
else
for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(2+2*ix));
}
else if(k1data->id()==23&&k2data->id()==23) tc.push_back(p2data);
else if(abs(k1data->id())==24&&k2data->id()==23) tc.push_back(kdata->CC());
// Loop over helicities summing the relevant diagrams
for(unsigned int p1hel=0;p1hel<2;++p1hel) {
for(unsigned int p2hel=0;p2hel<2;++p2hel) {
for(unsigned int khel=0;khel<2;++khel) {
SpinorBarWaveFunction p1_p2 = ffg->evaluate(mu_UV2(),5,p2data,qbin[p2hel],g[p1hel]);
SpinorWaveFunction p1_k = ffg->evaluate(mu_UV2(),5,kdata->CC(),qbout[khel],g[p1hel]);
for(unsigned int k1hel=0;k1hel<3;++k1hel) {
for(unsigned int k2hel=0;k2hel<3;++k2hel) {
// If helicity is exactly conserved (massless quarks) skip if p2hel!=khel
// but if the production ME is required first fill it with (0.,0.).
if((p2hel!=khel)&&helicityConservation_) {
// if(getMatrix) {
// if(p1hel==0)
// gqb_hel_amps_(0,p2hel,k1hel,k2hel,khel) = Complex(0.,0.);
// else
// gqb_hel_amps_(2,p2hel,k1hel,k2hel,khel) = Complex(0.,0.);
// }
continue;
}
vector<Complex> diagrams;
// Get all t-channel diagram contributions
tcPDPtr intermediate_q;
for(unsigned int ix=0;ix<tc.size();ix++) {
intermediate_q = (!(k1data->id()==24&&k2data->id()==-24)) ? quark_ : tc[ix];
SpinorBarWaveFunction p2_v1 = ffv1->evaluate(scale(),5,intermediate_q,qbin[p2hel],v1[k1hel]);
SpinorWaveFunction k_v2 = ffv2->evaluate(scale(),5,intermediate_q,qbout[khel],v2[k2hel]);
// First calculate all the off-shell fermion currents
// Now calculate the 6 abelian diagrams q+g->v1+v2+q
// with 2 t-channel propagators, 1 s- and 1 t-channel
// and 2 t-channel ones.
if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p2data->id())%2==0))) {
diagrams.push_back(ffv2->evaluate(scale(),p1_k,p2_v1,v2[k2hel]));
diagrams.push_back(ffg->evaluate(mu_UV2(),k_v2,p2_v1,g[p1hel]));
diagrams.push_back(ffv1->evaluate(scale(),k_v2,p1_p2,v1[k1hel]));
}
intermediate_q = (!(k1data->id()==24&&k2data->id()==-24)) ? p2data : tc[ix];
SpinorBarWaveFunction p2_v2 = ffv2->evaluate(scale(),5,intermediate_q,qbin[p2hel],v2[k2hel]);
SpinorWaveFunction k_v1 = ffv1->evaluate(scale(),5,intermediate_q,qbout[khel],v1[k1hel]);
// q+g->v2+v1+q, with 2 t-channel propagators, 1 s- and 1 t-channel and 2 t-channel ones.
if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p2data->id())%2==1))) {
diagrams.push_back(ffv1->evaluate(scale(),p1_k,p2_v2,v1[k1hel]));
diagrams.push_back(ffg->evaluate(mu_UV2(),k_v1,p2_v2,g[p1hel]));
diagrams.push_back(ffv2->evaluate(scale(),k_v1,p1_p2,v2[k2hel]));
}
}
// If W+Z / W-Z calculate the two V+jet-like s-channel diagrams
if(abs(k1data->id())==24&&k2data->id()==23) {
// The off-shell s-channel boson current
VectorWaveFunction k1_k2 =
WWWvertex_->evaluate(scale(),3,k1data->CC(),v2[k2hel],v1[k1hel]);
// q+qb->g+v1*->g+v1+v2, q+qb->v1*+g->v1+v2+g
diagrams.push_back(ffv1->evaluate(scale(),qbout[khel],p1_p2,k1_k2));
diagrams.push_back(ffv1->evaluate(scale(),p1_k,qbin[p2hel],k1_k2));
}
// If W+W- calculate the four V+jet-like s-channel diagrams
if((k1data->id()==24&&k2data->id()==-24)&&(p2data->id()==kdata->id())) {
// The off-shell s-channel boson current
VectorWaveFunction k1_k2;
// q+qb->g+Z0*->g+v1+v2,q+qb->Z0*+g->v1+v2+g,
tcPDPtr Z0 = getParticleData(ParticleID::Z0);
k1_k2 = WWWvertex_->evaluate(scale(),3,Z0,v2[k2hel],v1[k1hel]);
diagrams.push_back(FFZvertex_->evaluate(scale(),qbout[khel],p1_p2,k1_k2));
diagrams.push_back(FFZvertex_->evaluate(scale(),p1_k,qbin[p2hel],k1_k2));
// q+qb->g+gamma*->g+v1+v2,q+qb->gamma*+g->v1+v2+g,
tcPDPtr gamma = getParticleData(ParticleID::gamma);
k1_k2 = WWWvertex_->evaluate(scale(),3,gamma,v2[k2hel],v1[k1hel]);
diagrams.push_back(FFPvertex_->evaluate(scale(),qbout[khel],p1_p2,k1_k2));
diagrams.push_back(FFPvertex_->evaluate(scale(),p1_k,qbin[p2hel],k1_k2));
}
// Add up all diagrams to get the total amplitude:
Complex hel_amp(0.);
for(unsigned int ix=0;ix<diagrams.size();ix++) hel_amp += diagrams[ix];
// If we need to fill the production ME we do it here:
// if(getMatrix) {
// if(p1hel==0)
// gqb_hel_amps_(0,p2hel,k1hel,k2hel,khel) = hel_amp;
// else
// gqb_hel_amps_(2,p2hel,k1hel,k2hel,khel) = hel_amp;
// }
sum_hel_amps_sqr += norm(hel_amp);
}
}
}
}
}
// Fill up the remaining bits of the production ME, corresponding
// to longitudinal gluon polarization, with (0.,0.).
// if(getMatrix) {
// for(unsigned int p2hel=0;p2hel<2;++p2hel) {
// for(unsigned int k1hel=0;k1hel<3;++k1hel) {
// for(unsigned int k2hel=0;k2hel<3;++k2hel) {
// for(unsigned int khel=0;khel<2;++khel) {
// gqb_hel_amps_(1,p2hel,k1hel,k2hel,khel) = Complex(0.,0.);
// }
// }
// }
// }
// }
// Spin and colour averaging factors = 1/4 * TR * 1/3 = 1/24
sum_hel_amps_sqr /= 24.;
// Symmetry factor for identical Z bosons in the final state
if(k1data->id()==23&&k2data->id()==23) sum_hel_amps_sqr /= 2.;
return sum_hel_amps_sqr*R.tkr()*R.ukr()*UnitRemoval::InvE2;
}
double MEPP2VVPowheg::lo_me() const {
using namespace ThePEG::Helicity;
double sum_hel_amps_sqr(0.);
tcPDPtr p1data(quark_);
tcPDPtr p2data(antiquark_);
tcPDPtr k1data(mePartonData()[2]);
tcPDPtr k2data(mePartonData()[3]);
if(k1data->id()==-24&&k2data->id()==24) swap(k1data,k2data); // Should never actually occur.
SpinorWaveFunction qSpinor(B_.p1b(),p1data,incoming);
SpinorBarWaveFunction qbSpinor(B_.p2b(),p2data,incoming);
vector<SpinorWaveFunction> q;
vector<SpinorBarWaveFunction> qb;
for(unsigned int ix=0;ix<2;ix++) {
qSpinor.reset(ix);
qbSpinor.reset(ix);
q.push_back(qSpinor);
qb.push_back(qbSpinor);
}
VectorWaveFunction v1Polarization(B_.k1b(),k1data,outgoing);
VectorWaveFunction v2Polarization(B_.k2b(),k2data,outgoing);
vector<VectorWaveFunction> v1;
vector<VectorWaveFunction> v2;
for(unsigned int ix=0;ix<3;ix++) {
v1Polarization.reset(ix);
v2Polarization.reset(ix);
v1.push_back(v1Polarization);
v2.push_back(v2Polarization);
}
AbstractFFVVertexPtr ffv1 = k1data->id()==23 ? FFZvertex_ : FFWvertex_;
AbstractFFVVertexPtr ffv2 = k2data->id()==23 ? FFZvertex_ : FFWvertex_;
// Collecting information for intermediate fermions
vector<tcPDPtr> tc;
if(abs(k1data->id())==24&&abs(k2data->id())==24) {
if(abs(p1data->id())%2==0)
for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(1+2*ix));
else
for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(2+2*ix));
}
else if(k1data->id()==23&&k2data->id()==23) tc.push_back(p1data);
else if(abs(k1data->id())==24&&k2data->id()==23) tc.push_back(p2data);
// Loop over helicities summing the relevant diagrams
for(unsigned int p1hel=0;p1hel<2;++p1hel) {
for(unsigned int p2hel=0;p2hel<2;++p2hel) {
if((p1hel==p2hel)&&helicityConservation_) continue;
for(unsigned int k1hel=0;k1hel<3;++k1hel) {
for(unsigned int k2hel=0;k2hel<3;++k2hel) {
vector<Complex> diagrams;
// Get all t-channel diagram contributions
tcPDPtr intermediate_t;
for(unsigned int ix=0;ix<tc.size();ix++) {
intermediate_t = (!(k1data->id()==24&&k2data->id()==-24)) ? p2data : tc[ix];
SpinorWaveFunction p1_v1 = ffv1->evaluate(scale(),5,intermediate_t,q[p1hel],v1[k1hel]);
// First calculate all the off-shell fermion currents
// Now calculate the 6 t-channel diagrams
// q+qb->v1+v2
if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==1)))
diagrams.push_back(ffv2->evaluate(scale(),p1_v1,qb[p2hel],v2[k2hel]));
intermediate_t = (!(k1data->id()==24&&k2data->id()==-24)) ? p1data : tc[ix];
SpinorWaveFunction p1_v2 = ffv2->evaluate(scale(),5,intermediate_t,q[p1hel],v2[k2hel]);
// q+qb->v2+v1
if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==0)))
diagrams.push_back(ffv1->evaluate(scale(),p1_v2,qb[p2hel],v1[k1hel]));
}
// If W+Z / W-Z calculate the two V+jet-like s-channel diagrams
if(abs(k1data->id())==24&&k2data->id()==23) {
// The off-shell s-channel boson current
VectorWaveFunction k1_k2 =
WWWvertex_->evaluate(scale(),3,k1data->CC(),v2[k2hel],v1[k1hel]);
// q+qb->v1*->v1+v2
diagrams.push_back(ffv1->evaluate(scale(),q[p1hel],qb[p2hel],k1_k2));
}
// If W+W- calculate the four V+jet-like s-channel diagrams
if((k1data->id()==24&&k2data->id()==-24)&&(p1data->id()==-p2data->id())) {
// The off-shell s-channel boson current
VectorWaveFunction k1_k2;
// q+qb->Z0*->v1+v2
tcPDPtr Z0 = getParticleData(ParticleID::Z0);
k1_k2 = WWWvertex_->evaluate(scale(),3,Z0,v2[k2hel],v1[k1hel]);
diagrams.push_back(FFZvertex_->evaluate(scale(),q[p1hel],qb[p2hel],k1_k2));
// q+qb->gamma*->v1+v2
tcPDPtr gamma = getParticleData(ParticleID::gamma);
k1_k2 = WWWvertex_->evaluate(scale(),3,gamma,v2[k2hel],v1[k1hel]);
diagrams.push_back(FFPvertex_->evaluate(scale(),q[p1hel],qb[p2hel],k1_k2));
}
// Add up all diagrams to get the total amplitude:
Complex hel_amp(0.);
for(unsigned int ix=0;ix<diagrams.size();ix++) hel_amp += diagrams[ix];
// If we need to fill the production ME we do it here:
// if(getMatrix) lo_hel_amps_(p1hel,p2hel,k1hel,k2hel) = hel_amp;
sum_hel_amps_sqr += norm(hel_amp);
}
}
}
}
// Spin and colour averaging factors = 1/4 * 1/3 = 1/12
sum_hel_amps_sqr /= 12.;
// Symmetry factor for identical Z bosons in the final state
if(k1data->id()==23&&k2data->id()==23) sum_hel_amps_sqr /= 2.;
return sum_hel_amps_sqr;
}
RealEmissionProcessPtr MEPP2VVPowheg::generateHardest(RealEmissionProcessPtr born,
- ShowerInteraction::Type inter) {
+ ShowerInteraction inter) {
if(inter==ShowerInteraction::QED) return RealEmissionProcessPtr();
// Now we want to set these data vectors according to the particles we've
// received from the current 2->2 hard collision:
vector<PPtr> particlesToShower;
for(unsigned int ix=0;ix<born->bornIncoming().size();++ix)
particlesToShower.push_back(born->bornIncoming()[ix]);
qProgenitor_ = particlesToShower[0];
qbProgenitor_ = particlesToShower[1];
showerQuark_ = particlesToShower[0];
showerAntiquark_ = particlesToShower[1];
qHadron_ = dynamic_ptr_cast<tcBeamPtr>(born->hadrons()[0]->dataPtr());
qbHadron_ = dynamic_ptr_cast<tcBeamPtr>(born->hadrons()[1]->dataPtr());
if(showerQuark_->id()<0) {
swap(qProgenitor_,qbProgenitor_);
swap(showerQuark_,showerAntiquark_);
swap(qHadron_,qbHadron_);
}
// In _our_ calculation we basically define the +z axis as being given
// by the direction of the incoming quark for q+qb & q+g processes and
// the incoming gluon for g+qbar processes. So now we might need to flip
// the beams, bjorken x values, colliding partons accordingly:
flipped_ = showerQuark_->momentum().z()<ZERO ? true : false;
vector<unsigned int> cmap;
// undecayed gauge bosons
if(born->bornOutgoing().size()==2) {
for(unsigned int ix=0;ix<born->bornOutgoing().size();++ix) {
particlesToShower.push_back(born->bornOutgoing()[ix]);
}
V1_ = particlesToShower[2];
V2_ = particlesToShower[3];
}
else if(born->bornOutgoing().size()==4) {
// If the vector bosons have decayed already then we may want to
// to get the children_ (and any associated photons) to correct
// spin correlations:
children_.clear();
map<ColinePtr,ColinePtr> clines;
for(unsigned int ix=0;ix<born->bornOutgoing().size();++ix) {
tPPtr original = born->bornOutgoing()[ix];
PPtr copy = original->dataPtr()->produceParticle(original->momentum());
children_.push_back(copy);
cmap.push_back(ix);
// sort out colour
if(original->colourLine()) {
map<ColinePtr,ColinePtr>::iterator cit = clines.find(original->colourLine());
if(cit!=clines.end()) {
cit->second->addColoured(copy);
}
else {
ColinePtr newline = new_ptr(ColourLine());
clines[original->colourLine()] = newline;
newline->addColoured(copy);
}
}
// and anticolour
else if(original->antiColourLine()) {
map<ColinePtr,ColinePtr>::iterator cit = clines.find(original->antiColourLine());
if(cit!=clines.end()) {
cit->second->addAntiColoured(copy);
}
else {
ColinePtr newline = new_ptr(ColourLine());
clines[original->antiColourLine()] = newline;
newline->addAntiColoured(copy);
}
}
}
assert(children_.size()==4);
PPtr V[2];
for(unsigned int ix=0;ix<2;++ix) {
int charge =
children_[0+2*ix]->dataPtr()->iCharge()+
children_[1+2*ix]->dataPtr()->iCharge();
Lorentz5Momentum psum =children_[0+2*ix]->momentum()+
children_[1+2*ix]->momentum();
psum.rescaleMass();
if(charge==-3)
V[ix] = getParticleData(ParticleID::Wminus)->produceParticle(psum);
else if(charge==0)
V[ix] = getParticleData(ParticleID::Z0)->produceParticle(psum);
else if(charge==3)
V[ix] = getParticleData(ParticleID::Wplus)->produceParticle(psum);
else
assert(false);
}
V1_ = V[0];
V2_ = V[1];
if(children_[0]->id()<0) {
swap(children_[0],children_[1]);
swap(cmap[0],cmap[1]);
}
if(children_[2]->id()<0) {
swap(children_[2],children_[3]);
swap(cmap[2],cmap[3]);
}
}
else
assert(false);
gluon_ = getParticleData(ParticleID::g)->produceParticle();
// Abort the run if V1_ and V2_ are not just pointers to different gauge bosons
if(!V1_||!V2_)
throw Exception()
<< "MEPP2VVPowheg::generateHardest()\n"
<< "one or both of the gauge boson pointers is null." << Exception::abortnow;
if(!(abs(V1_->id())==24||V1_->id()==23)||!(abs(V2_->id())==24||V2_->id()==23))
throw Exception()
<< "MEPP2VVPowheg::generateHardest()\nmisidentified gauge bosons"
<< "V1_ = " << V1_->PDGName() << "\n"
<< "V2_ = " << V2_->PDGName() << "\n"
<< Exception::abortnow;
// Order the gauge bosons in the same way as in the NLO calculation
// (the same way as in the NLO matrix element):
// W+(->e+,nu_e) W-(->e-,nu_ebar) (MCFM: 61 [nproc])
bool order = false;
if((V1_->id()==-24&&V2_->id()== 24) ||
// W+/-(mu+,nu_mu / mu-,nu_mubar) Z(nu_e,nu_ebar) (MCFM: 72+77 [nproc])
(V1_->id()== 23&&abs(V2_->id())== 24) ) {
swap(V1_,V2_);
order = true;
swap(cmap[0],cmap[2]);
swap(cmap[1],cmap[3]);
swap(children_[0],children_[2]);
swap(children_[1],children_[3]);
}
// *** N.B. ***
// We should not have to do a swap in the ZZ case, even if the different
// (off-shell) masses of the Z's are taken into account by generating
// the Born variables using the WZ LO/NLO matrix element(s), because
// those transformed matrix elements are, according to mathematica,
// symmetric in the momenta (and therefore also the masses) of the 2 Z's.
// Now we want to construct a bornVVKinematics object. The
// constructor for that needs all 4 momenta, q, qbar, V1_, V2_
// in that order, as well as the Bjorken xq and xqbar.
// Get the momenta first:
vector<Lorentz5Momentum> theBornMomenta;
theBornMomenta.push_back(showerQuark_->momentum());
theBornMomenta.push_back(showerAntiquark_->momentum());
theBornMomenta.push_back(V1_->momentum());
theBornMomenta.push_back(V2_->momentum());
// N.B. if the showerQuark_ travels in the -z direction the born kinematics object
// will detect this and rotate all particles by pi about the y axis!
// Leading order momentum fractions:
tcPPtr qHadron = generator()->currentEvent()->primaryCollision()->incoming().first;
tcPPtr qbHadron = generator()->currentEvent()->primaryCollision()->incoming().second;
assert(qHadron->children().size()>0&&qbHadron->children().size()>0);
if(qHadron->children()[0]->id()<0) swap(qHadron,qbHadron);
// quark and antiquark momentum fractions respectively
double xa = showerQuark_ ->momentum().z()/qHadron ->momentum().z();
double xb = showerAntiquark_->momentum().z()/qbHadron->momentum().z();
// Create the object containing all 2->2 __kinematic__ information:
B_ = bornVVKinematics(theBornMomenta,xa,xb);
// lo_me_ is the colour & spin averaged n-body matrix element squared:
lo_me_ = lo_me(true);
// Attempt to generate some radiative variables and their kinematics:
vector<Lorentz5Momentum> theRealMomenta;
channel_ = 999;
if(!getEvent(theRealMomenta,channel_)) {
born->pT()[ShowerInteraction::QCD] = min_pT_;
return born;
}
// Set the maximum pT for subsequent emissions:
born->pT()[ShowerInteraction::QCD] = pT_ < min_pT_ ? min_pT_ : pT_;
// Determine whether the quark or antiquark emitted:
fermionNumberOfMother_=0;
if((channel_==0&&theRealMomenta[0].z()/theRealMomenta[4].z()>=ZERO)||
channel_==2) fermionNumberOfMother_ = 1;
else if((channel_==0&&theRealMomenta[0].z()/theRealMomenta[4].z()<ZERO)||
channel_==1) fermionNumberOfMother_ = -1;
assert(fermionNumberOfMother_!=0);
// If the quark in the original tree was travelling in the -z direction
// then we need to unflip the event (flips are automatically carried out
// when the original quark travels in the in -z direction when the
// bornVVKinematics object is created):
if(flipped_)
for(unsigned int ix=0;ix<theRealMomenta.size();ix++)
theRealMomenta[ix].rotateY(-Constants::pi);
// Randomly rotate the event about the beam axis:
double randomPhi(UseRandom::rnd()*2.*Constants::pi);
for(unsigned int ix=0;ix<theRealMomenta.size();ix++)
theRealMomenta[ix].rotateZ(randomPhi);
// Warn if momentum conservation is not obeyed:
Lorentz5Momentum inMinusOut(theRealMomenta[0]+theRealMomenta[1]
-theRealMomenta[2]-theRealMomenta[3]
-theRealMomenta[4]);
if(inMinusOut.t()>0.1*GeV||inMinusOut.x()>0.1*GeV||
inMinusOut.y()>0.1*GeV||inMinusOut.z()>0.1*GeV)
cout << "MEPP2VVPowheg::generateHardest\n"
<< "Momentum imbalance in V1 V2 rest frame\n"
<< "P_in minus P_out = " << inMinusOut/GeV << endl;
// From the radiative kinematics we now have to form ShowerParticle objects:
PPtr p1,p2,k;
PPtr k1 = V1_->dataPtr()->produceParticle(theRealMomenta[2]);
PPtr k2 = V2_->dataPtr()->produceParticle(theRealMomenta[3]);
// q+qbar -> V1+V2+g
if(channel_==0) {
p1 = showerQuark_ ->dataPtr()->produceParticle(theRealMomenta[0]);
p2 = showerAntiquark_->dataPtr()->produceParticle(theRealMomenta[1]);
k = gluon_ ->dataPtr()->produceParticle(theRealMomenta[4]);
k->incomingColour(p1);
k->incomingColour(p2,true);
}
// q+g -> V1+V2+q
else if(channel_==1) {
p1 = showerQuark_ ->dataPtr() ->produceParticle(theRealMomenta[0]);
p2 = gluon_ ->dataPtr() ->produceParticle(theRealMomenta[1]);
k = showerAntiquark_->dataPtr()->CC()->produceParticle(theRealMomenta[4]);
k->incomingColour(p2);
p2->colourConnect(p1);
}
// g+qbar -> V1+V2+qbar
else {
p1 = gluon_ ->dataPtr() ->produceParticle(theRealMomenta[0]);
p2 = showerAntiquark_->dataPtr() ->produceParticle(theRealMomenta[1]);
k = showerQuark_ ->dataPtr()->CC()->produceParticle(theRealMomenta[4]);
k->incomingColour(p1,true);
p1->colourConnect(p2,true);
}
Lorentz5Momentum pmother,pspect;
if(fermionNumberOfMother_==1) {
pmother = theRealMomenta[0]-theRealMomenta[4];
pspect = theRealMomenta[1];
}
else {
pmother = theRealMomenta[1]-theRealMomenta[4];
pspect = theRealMomenta[0];
}
unsigned int iemit = fermionNumberOfMother_==1 ? 0 : 1;
unsigned int ispect = fermionNumberOfMother_==1 ? 1 : 0;
// fill the output
if(showerQuark_ !=born->bornIncoming()[0]) {
born->incoming().push_back(p2);
born->incoming().push_back(p1);
swap(iemit,ispect);
}
else {
born->incoming().push_back(p1);
born->incoming().push_back(p2);
}
born->emitter (iemit);
born->spectator(ispect);
pair<double,double> xnew;
for(unsigned int ix=0;ix<born->incoming().size();++ix) {
double x = born->incoming()[ix]->momentum().rho()/born->hadrons()[ix]->momentum().rho();
if(ix==0) xnew.first = x;
else if (ix==1) xnew.second = x;
}
born->x(xnew);
born->interaction(ShowerInteraction::QCD);
// if gauge bosons not decayed, we're done
if(born->bornOutgoing().size()==2) {
born->emitted(4);
if(!order) {
born->outgoing().push_back(k1);
born->outgoing().push_back(k2);
}
else {
born->outgoing().push_back(k2);
born->outgoing().push_back(k1);
}
born->outgoing().push_back(k);
return born;
}
// Recalculate the hard vertex for this event:
// For spin correlations, if an emission occurs go calculate the relevant
// combination of amplitudes for the ProductionMatrixElement.
if(realMESpinCorrelations_) {
// Here we reset the realVVKinematics n+1 momenta to be those
// of the lab frame in order to calculate the spin correlations.
// Note that these momenta are not used for anything else after
// this.
R_.p1r(theRealMomenta[0]);
R_.p2r(theRealMomenta[1]);
R_.k1r(theRealMomenta[2]);
R_.k2r(theRealMomenta[3]);
R_.kr (theRealMomenta[4]);
if(channel_==0) t_u_M_R_qqb_hel_amp(R_,true);
else if(channel_==1) t_u_M_R_qg_hel_amp (R_,true);
else if(channel_==2) t_u_M_R_gqb_hel_amp(R_,true);
recalculateVertex();
}
born->emitted(6);
for(unsigned int ix=0;ix<children_.size();++ix)
born->outgoing().push_back(children_[cmap[ix]]);
born->outgoing().push_back(k);
// return the result
return born;
}
double MEPP2VVPowheg::getResult(int channel, realVVKinematics R, Energy pT) {
// This routine should return the integrand of the exact Sudakov form factor,
// defined precisely as
// KH 19th August - next 2 lines changed for phi in 0->pi not 0->2pi
// \Delta(pT) = exp[ - \int_{pT}^{pTmax} dpT dYk d\phi/pi * getResult(...) ]
// (Where phi is in 0->pi NOT 0->2*pi !)
// Get pi for the prefactor:
using Constants::pi;
// Get the VV invariant mass^2:
Energy2 p2 = B_.sb();
// Get the momentum fractions for the n+1 body event:
double x1 = R.x1r();
double x2 = R.x2r();
// Reject the event if the x1 and x2 values are outside the phase space:
if(x1<0.||x1>1.||x2<0.||x2>1.||x1*x2<p2/sqr(generator()->maximumCMEnergy())) return 0.;
// Get the momentum fractions for the n body event:
double x1b = B_.x1b();
double x2b = B_.x2b();
// Get the mandelstam variables needed to calculate the n+1 body matrix element:
Energy2 s = R.sr() ;
Energy2 t_u_MR_o_MB;
double lo_lumi, nlo_lumi;
// The luminosity function for the leading order n-body process:
lo_lumi = qHadron_ ->pdf()->xfx(qHadron_ ,showerQuark_ ->dataPtr(),PDFScale_,x1b)*
qbHadron_->pdf()->xfx(qbHadron_,showerAntiquark_->dataPtr(),PDFScale_,x2b);
// Now we calculate the luminosity functions (product of the two pdfs) for the
// real emission process(es) and also their matrix elements:
// q + qbar -> V + V + g
if(channel==0) {
nlo_lumi = qHadron_ ->pdf()->xfx(qHadron_ ,showerQuark_ ->dataPtr() ,PDFScale_,x1)
* qbHadron_->pdf()->xfx(qbHadron_,showerAntiquark_->dataPtr() ,PDFScale_,x2);
t_u_MR_o_MB = t_u_M_R_qqb_hel_amp(R,false)/lo_me_;
}
// q + g -> V + V + q
else if(channel==1) {
nlo_lumi = qHadron_ ->pdf()->xfx(qHadron_ ,showerQuark_->dataPtr() ,PDFScale_,x1)
* qbHadron_->pdf()->xfx(qbHadron_,getParticleData(ParticleID::g),PDFScale_,x2);
t_u_MR_o_MB = t_u_M_R_qg_hel_amp(R,false)/lo_me_;
}
// g + qbar -> V + V + qbar
else {
nlo_lumi = qHadron_ ->pdf()->xfx(qHadron_ ,getParticleData(ParticleID::g),PDFScale_,x1)
* qbHadron_->pdf()->xfx(qbHadron_,showerAntiquark_->dataPtr() ,PDFScale_,x2);
t_u_MR_o_MB = t_u_M_R_gqb_hel_amp(R,false)/lo_me_;
}
// Multiply ratio of the real emission matrix elements to the Born matrix element
// by the ratio of the pdfs for the real emission and born processes to get theWeight
if(lo_lumi<=0.||nlo_lumi<=0.)
return 0.;
else
return t_u_MR_o_MB * ( nlo_lumi/lo_lumi * p2/s )
* sqr(p2/s)/8./pi/pi
/ pT / p2
* GeV;
}
bool MEPP2VVPowheg::getEvent(vector<Lorentz5Momentum> & theRealMomenta,
unsigned int & channel) {
// Invariant mass of the colliding hadrons:
Energy2 S = sqr(generator()->maximumCMEnergy());
// Born variables which are preserved (mass and rapidity of the diboson system):
Energy2 p2 = B_.sb();
double Yb = B_.Yb();
// Born variables which are not preserved but are needed (the momentum fractions):
double x1b(B_.x1b()), x2b(B_.x2b());
double x12b(x1b*x1b), x22b(x2b*x2b);
// Maximum jet pT (half of the hadronic C.O.M. energy. N.B. this is overestimated a lot):
Energy starting_pT = sqrt(S)/2.;
// Initialize the pT_ *integration limit* i.e. the pT of the generated emission:
pT_ = ZERO;
// The pT *integration variable*:
Energy pT;
// The x_1 & x_2 momentum fractions corresponding to incoming momenta p1 & p2:
double x1_(-999.), x2_(-999.);
double x1 (-999.), x2 (-999.);
// The jet rapidity *integration variable* and its limits:
double Yk, minYk(-8.0), maxYk(8.0);
// The theta2 integration variable (the azimuthal angle of the gluon w.r.t
// V1 in the V1 & V2 rest frame:
double theta2;
// The realVVKinematics object corresponding to the current integration
// set of integration variables:
realVVKinematics R;
// The veto algorithm rejection weight and a corresponding flag:
double rejectionWeight;
bool rejectEmission ;
// Initialize the flag indicating the selected radiation channel:
channel=999;
// Some product of constants used for the crude distribution:
double a(0.);
for(int j=0;j<3;j++) {
pT=starting_pT;
a =(maxYk-minYk)*prefactor_[j]/2./b0_;
do {
// Generate next pT according to exp[- \int^{pTold}_{pT} dpT a*(power-1)/(pT^power)]
// pT = GeV/pow( pow(GeV/pT,power_-1.) - log(UseRandom::rnd())/a
// , 1./(power_-1.) );
// Generate next pT according to exp[- \int^{pTold}_{pT} dpT alpha1loop*prefactor/pT ]
pT = LambdaQCD_*exp( 0.5*exp( log(log(sqr(pT/LambdaQCD_)))+log(UseRandom::rnd())/a ) );
// Generate rapidity of the jet:
Yk = minYk + UseRandom::rnd()*(maxYk - minYk);
// Generate the theta2 radiative variable:
// KH 19th August - next line changed for phi in 0->pi not 0->2pi
// theta2 = UseRandom::rnd() * 2.*Constants::pi;
theta2 = UseRandom::rnd() * Constants::pi;
// eT of the diboson system:
Energy eT = sqrt(pT*pT+p2);
// Calculate the eT and then solve for x_{\oplus} & x_{\ominus}:
x1 = (pT*exp( Yk)+eT*exp( Yb))/sqrt(S);
x2 = (pT*exp(-Yk)+eT*exp(-Yb))/sqrt(S);
// Calculate the xr radiative variable:
double xr(p2/(x1*x2*S));
// Then use this to calculate the y radiative variable:
double y(-((xr+1.)/(xr-1.))*(xr*sqr(x1/x1b)-1.)/(xr*sqr(x1/x1b)+1.));
// The y value above should equal the one commented out below this line:
// double y( ((xr+1.)/(xr-1.))*(xr*sqr(x2/x2b)-1.)/(xr*sqr(x2/x2b)+1.));
// Now we get the lower limit on the x integration, xbar:
double omy(1.-y), opy(1.+y);
double xbar1 = 2.*opy*x12b/(sqrt(sqr(1.+x12b)*sqr(omy)+16.*y*x12b)+omy*(1.-x1b)*(1.+x1b));
double xbar2 = 2.*omy*x22b/(sqrt(sqr(1.+x22b)*sqr(opy)-16.*y*x22b)+opy*(1.-x2b)*(1.+x2b));
double xbar = max(xbar1,xbar2);
// Now we can calculate xtilde:
double xt = (xr-xbar)/(1.-xbar);
// Finally we can make the realVVKinematics object:
R = realVVKinematics(B_,xt,y,theta2);
// The next thing we have to do is set the QCD, EW and PDF scales using R:
setTheScales(pT);
// ... and so calculate rejection weight:
rejectionWeight = getResult(j,R,pT);
// If generating according to exp[- \int^{pTold}_{pT} dpT a*(power-1)/(pT^power)]
// rejectionWeight/= showerAlphaS_->overestimateValue()*prefactor_[j]*pow(GeV/pT,power_);
// If generating according to exp[- \int^{pTold}_{pT} dpT alpha1loop*prefactor/pT ]
rejectionWeight/= 1./b0_/log(sqr(pT/LambdaQCD_))*prefactor_[j]*GeV/pT;
rejectEmission = UseRandom::rnd()>rejectionWeight;
// The event is a no-emission event if pT goes past min_pT_ - basically set to
// outside the histogram bounds (hopefully histogram objects just ignore it then).
if(pT<min_pT_) {
pT=ZERO;
rejectEmission = false;
}
if(rejectionWeight>1.) {
ostringstream stream;
stream << "MEPP2VVPowheg::getEvent weight for channel " << j
<< " is greater than one: " << rejectionWeight << endl;
generator()->logWarning( Exception(stream.str(), Exception::warning) );
}
}
while(rejectEmission);
// set pT of emission etc
if(pT>pT_) {
channel = j;
pT_ = pT;
Yk_ = Yk;
R_ = R ;
x1_ = x1;
x2_ = x2;
}
}
// Was this an (overall) no emission event?
if(pT_<min_pT_) {
pT_ = ZERO;
channel = 3;
}
if(channel==3) return false;
if(channel>3) throw Exception()
<< "MEPP2VVPowheg::getEvent() channel = " << channel
<< " pT = " << pT/GeV << " pT_ = " << pT_/GeV
<< Exception::abortnow;
// Work out the momenta in the lab frame, reserving the mass and rapidity
// of the VV system:
LorentzRotation yzRotation;
yzRotation.setRotateX(-atan2(pT_/GeV,sqrt(p2)/GeV));
LorentzRotation boostFrompTisZero;
boostFrompTisZero.setBoostY(-pT_/sqrt(p2+pT_*pT_));
LorentzRotation boostFromYisZero;
boostFromYisZero.setBoostZ(tanh(Yb));
theRealMomenta.resize(5);
theRealMomenta[0] = Lorentz5Momentum(ZERO,ZERO, x1_*sqrt(S)/2., x1_*sqrt(S)/2.,ZERO);
theRealMomenta[1] = Lorentz5Momentum(ZERO,ZERO,-x2_*sqrt(S)/2., x2_*sqrt(S)/2.,ZERO);
theRealMomenta[2] = boostFromYisZero*boostFrompTisZero*yzRotation*(R_.k1r());
theRealMomenta[3] = boostFromYisZero*boostFrompTisZero*yzRotation*(R_.k2r());
theRealMomenta[4] = Lorentz5Momentum(ZERO, pT_, pT_*sinh(Yk_), pT_*cosh(Yk_),ZERO);
return true;
}
void MEPP2VVPowheg::setTheScales(Energy pT) {
// Work out the scales we want to use in the matrix elements and the pdfs:
// Scale for alpha_S: pT^2 of the diboson system.
QCDScale_ = max(pT*pT,sqr(min_pT_));
// Scale for real emission PDF:
// pT^2+mVV^2 - as mcfm does in the case of a single W/Z boson).
// Energy2 PDFScale_ = max(R.pT2_in_lab(),sqr(min_pT_))+R.s2r();
// pT^2 - as advocated by Nason & Ridolfi for ZZ production & Alioli et al for gg->h:
PDFScale_ = max(pT*pT,sqr(min_pT_));
// Scale of electroweak vertices: mVV^2 the invariant mass of the diboson system.
// EWScale_ = B_.sb();
// ... And this choice is more like what can be seen in mcatnlo_vbmain.f (weird).
EWScale_ = 0.5*(B_.k12b()+B_.k22b());
return;
}
/***************************************************************************/
// This is identical to the code in the Powheg matrix element. It should
// equal t_u_M_R_qqb in there, which is supposed to be the real emission ME
// times tk*uk.
Energy2 MEPP2VVPowheg::t_u_M_R_qqb_hel_amp(realVVKinematics R, bool getMatrix) const {
using namespace ThePEG::Helicity;
ProductionMatrixElement qqb_hel_amps(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1 ,PDT::Spin1 ,
PDT::Spin1);
double sum_hel_amps_sqr(0.);
tcPDPtr p1data(showerQuark_->dataPtr());
tcPDPtr p2data(showerAntiquark_->dataPtr());
tcPDPtr k1data(V1_->dataPtr());
tcPDPtr k2data(V2_->dataPtr());
tcPDPtr kdata(getParticleData(ParticleID::g));
if(k1data->id()==-24&&k2data->id()==24) swap(k1data,k2data);
SpinorWaveFunction qSpinor(R.p1r(),p1data,incoming);
SpinorBarWaveFunction qbSpinor(R.p2r(),p2data,incoming);
vector<SpinorWaveFunction> q;
vector<SpinorBarWaveFunction> qb;
for(unsigned int ix=0;ix<2;ix++) {
qSpinor.reset(ix);
qbSpinor.reset(ix);
q.push_back(qSpinor);
qb.push_back(qbSpinor);
}
VectorWaveFunction v1Polarization(R.k1r(),k1data,outgoing);
VectorWaveFunction v2Polarization(R.k2r(),k2data,outgoing);
vector<VectorWaveFunction> v1;
vector<VectorWaveFunction> v2;
for(unsigned int ix=0;ix<3;ix++) {
v1Polarization.reset(ix);
v2Polarization.reset(ix);
v1.push_back(v1Polarization);
v2.push_back(v2Polarization);
}
VectorWaveFunction gPolarization(R.kr(),kdata,outgoing);
vector<VectorWaveFunction> g;
for(unsigned int ix=0;ix<3;ix+=2) {
gPolarization.reset(ix);
g.push_back(gPolarization);
}
AbstractFFVVertexPtr ffg = FFGvertex_;
AbstractFFVVertexPtr ffv1 = k1data->id()==23 ? FFZvertex_ : FFWvertex_;
AbstractFFVVertexPtr ffv2 = k2data->id()==23 ? FFZvertex_ : FFWvertex_;
// Collecting information for intermediate fermions
vector<tcPDPtr> tc;
if(abs(k1data->id())==24&&abs(k2data->id())==24) {
if(abs(p1data->id())%2==0)
for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(1+2*ix));
else
for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(2+2*ix));
}
else if(k1data->id()==23&&k2data->id()==23) tc.push_back(p1data);
else if(abs(k1data->id())==24&&k2data->id()==23) tc.push_back(p2data);
// Loop over helicities summing the relevant diagrams
for(unsigned int p1hel=0;p1hel<2;++p1hel) {
for(unsigned int p2hel=0;p2hel<2;++p2hel) {
for(unsigned int khel=0;khel<2;++khel) {
SpinorWaveFunction p1_k = ffg->evaluate(QCDScale_,5,p1data,q[p1hel],g[khel]);
SpinorBarWaveFunction p2_k = ffg->evaluate(QCDScale_,5,p2data,qb[p2hel],g[khel]);
for(unsigned int k1hel=0;k1hel<3;++k1hel) {
for(unsigned int k2hel=0;k2hel<3;++k2hel) {
// If helicity is exactly conserved (massless quarks) skip if p1hel=p2hel
// but if the production ME is required first fill it with (0.,0.).
if((p1hel==p2hel)&&helicityConservation_) {
if(getMatrix) {
if(khel==0)
qqb_hel_amps(p1hel,p2hel,k1hel,k2hel,0) = Complex(0.,0.);
else
qqb_hel_amps(p1hel,p2hel,k1hel,k2hel,2) = Complex(0.,0.);
}
continue;
}
vector<Complex> diagrams;
// Get all t-channel diagram contributions
tcPDPtr intermediate_t;
for(unsigned int ix=0;ix<tc.size();ix++) {
intermediate_t = (!(k1data->id()==24&&k2data->id()==-24)) ? p2data : tc[ix];
// Note: choosing 5 as the second argument ffvX_->evaluate() sets
// option 5 in thepeg/Helicity/Vertex/VertexBase.cc, which makes
// the (fermion) propagator denominator massless: 1/p^2.
// If W+Z / W-Z calculate the two V+jet-like s-channel diagrams
SpinorWaveFunction p1_v1 = ffv1->evaluate(EWScale_,5,intermediate_t,q[p1hel],v1[k1hel]);
SpinorBarWaveFunction p2_v2 = ffv2->evaluate(EWScale_,5,intermediate_t,qb[p2hel],v2[k2hel]);
// First calculate all the off-shell fermion currents
// Now calculate the 6 t-channel diagrams
// q+qb->g+v1+v2, q+qb->v1+g+v2, q+qb->v1+v2+g
if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==1))) {
diagrams.push_back(ffv1->evaluate(EWScale_,p1_k,p2_v2,v1[k1hel]));
diagrams.push_back(ffg->evaluate(QCDScale_,p1_v1,p2_v2,g[khel]));
diagrams.push_back(ffv2->evaluate(EWScale_,p1_v1,p2_k,v2[k2hel]));
}
intermediate_t = (!(k1data->id()==24&&k2data->id()==-24)) ? p1data : tc[ix];
SpinorWaveFunction p1_v2 = ffv2->evaluate(EWScale_,5,intermediate_t,q[p1hel],v2[k2hel]);
SpinorBarWaveFunction p2_v1 = ffv1->evaluate(EWScale_,5,intermediate_t,qb[p2hel],v1[k1hel]);
// q+qb->g+v2+v1, q+qb->v2+g+v1, q+qb->v2+v1+g
if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==0))) {
diagrams.push_back(ffv2->evaluate(EWScale_,p1_k,p2_v1,v2[k2hel]));
diagrams.push_back(ffg->evaluate(QCDScale_,p1_v2,p2_v1,g[khel]));
diagrams.push_back(ffv1->evaluate(EWScale_,p1_v2,p2_k,v1[k1hel]));
}
}
// Note: choosing 3 as the second argument in WWWvertex_->evaluate()
// sets option 3 in thepeg/Helicity/Vertex/VertexBase.cc , which
// means the propagator does not contain a width factor (which is
// good re. gauge invariance).
// If W+Z / W-Z calculate the two V+jet-like s-channel diagrams
if(abs(k1data->id())==24&&k2data->id()==23) {
// The off-shell s-channel boson current
VectorWaveFunction k1_k2 =
WWWvertex_->evaluate(EWScale_,3,k1data->CC(),v2[k2hel],v1[k1hel]);
// q+qb->g+v1*->g+v1+v2, q+qb->v1*+g->v1+v2+g
diagrams.push_back(ffv1->evaluate(EWScale_,p1_k,qb[p2hel],k1_k2));
diagrams.push_back(ffv1->evaluate(EWScale_,q[p1hel],p2_k,k1_k2));
}
// If W+W- calculate the four V+jet-like s-channel diagrams
if((k1data->id()==24&&k2data->id()==-24)&&(p1data->id()==-p2data->id())) {
// The off-shell s-channel boson current
VectorWaveFunction k1_k2;
// q+qb->g+Z0*->g+v1+v2,q+qb->Z0*+g->v1+v2+g,
tcPDPtr Z0 = getParticleData(ParticleID::Z0);
k1_k2 = WWWvertex_->evaluate(EWScale_,3,Z0,v2[k2hel],v1[k1hel]);
diagrams.push_back(FFZvertex_->evaluate(EWScale_,p1_k,qb[p2hel],k1_k2));
diagrams.push_back(FFZvertex_->evaluate(EWScale_,q[p1hel],p2_k,k1_k2));
// q+qb->g+gamma*->g+v1+v2,q+qb->gamma*+g->v1+v2+g,
tcPDPtr gamma = getParticleData(ParticleID::gamma);
k1_k2 = WWWvertex_->evaluate(EWScale_,3,gamma,v2[k2hel],v1[k1hel]);
diagrams.push_back(FFPvertex_->evaluate(EWScale_,p1_k,qb[p2hel],k1_k2));
diagrams.push_back(FFPvertex_->evaluate(EWScale_,q[p1hel],p2_k,k1_k2));
}
// Add up all diagrams to get the total amplitude:
Complex hel_amp(0.);
for(unsigned int ix=0;ix<diagrams.size();ix++) hel_amp += diagrams[ix];
// If we need to fill the production ME we do it here:
if(getMatrix) {
if(khel==0)
qqb_hel_amps(p1hel,p2hel,k1hel,k2hel,0) = hel_amp;
else
qqb_hel_amps(p1hel,p2hel,k1hel,k2hel,2) = hel_amp;
}
sum_hel_amps_sqr += norm(hel_amp);
}
}
}
}
}
// Fill up the remaining bits of the production ME, corresponding
// to longitudinal gluon polarization, with (0.,0.).
if(getMatrix) {
for(unsigned int p1hel=0;p1hel<2;++p1hel) {
for(unsigned int p2hel=0;p2hel<2;++p2hel) {
for(unsigned int k1hel=0;k1hel<3;++k1hel) {
for(unsigned int k2hel=0;k2hel<3;++k2hel) {
qqb_hel_amps(p1hel,p2hel,k1hel,k2hel,1) = Complex(0.,0.);
}
}
}
}
}
// Calculate the production density matrix:
if(getMatrix) {
for(unsigned int k1hel=0;k1hel<3;++k1hel) {
for(unsigned int k1helpr=0;k1helpr<3;++k1helpr) {
for(unsigned int k2hel=0;k2hel<3;++k2hel) {
for(unsigned int k2helpr=0;k2helpr<3;++k2helpr) {
Complex theElement(0.,0.);
// For each k1hel, k1helpr, k2hel, k2helpr sum over fermion and gluon spins...
for(unsigned int p1hel=0;p1hel<2;++p1hel) {
for(unsigned int p2hel=0;p2hel<2;++p2hel) {
for(unsigned int khel=0;khel<3;khel+=2) {
theElement += qqb_hel_amps(p1hel,p2hel,k1hel ,k2hel ,khel)
*conj(qqb_hel_amps(p1hel,p2hel,k1helpr,k2helpr,khel));
}
}
}
// ...and then set the production matrix element to the sum:
productionMatrix_[k1hel][k1helpr][k2hel][k2helpr] = theElement;
}
}
}
}
}
// Spin and colour averaging factors = 1/4 * CF * 1/3 = 1/9
sum_hel_amps_sqr /= 9.;
// Symmetry factor for identical Z bosons in the final state
if(k1data->id()==23&&k2data->id()==23) sum_hel_amps_sqr /= 2.;
return sum_hel_amps_sqr*R.tkr()*R.ukr()*UnitRemoval::InvE2;
}
/***************************************************************************/
// This is identical to the code in the Powheg matrix element. It should
// equal t_u_M_R_qg in there, which is supposed to be the real emission ME
// times tk*uk.
Energy2 MEPP2VVPowheg::t_u_M_R_qg_hel_amp(realVVKinematics R, bool getMatrix) const {
using namespace ThePEG::Helicity;
ProductionMatrixElement qg_hel_amps(PDT::Spin1Half,PDT::Spin1,
PDT::Spin1,PDT::Spin1,
PDT::Spin1Half);
double sum_hel_amps_sqr(0.);
tcPDPtr p1data(showerQuark_->dataPtr());
tcPDPtr p2data(getParticleData(ParticleID::g));
tcPDPtr k1data(V1_->dataPtr());
tcPDPtr k2data(V2_->dataPtr());
tcPDPtr kdata (showerAntiquark_->dataPtr()->CC());
if(k1data->id()==-24&&k2data->id()==24) swap(k1data,k2data);
SpinorWaveFunction qinSpinor(R.p1r(),p1data,incoming);
SpinorBarWaveFunction qoutSpinor(R.kr(),kdata,outgoing);
vector<SpinorWaveFunction> qin;
vector<SpinorBarWaveFunction> qout;
for(unsigned int ix=0;ix<2;ix++) {
qinSpinor.reset(ix);
qoutSpinor.reset(ix);
qin.push_back(qinSpinor);
qout.push_back(qoutSpinor);
}
VectorWaveFunction v1Polarization(R.k1r(),k1data,outgoing);
VectorWaveFunction v2Polarization(R.k2r(),k2data,outgoing);
vector<VectorWaveFunction> v1;
vector<VectorWaveFunction> v2;
for(unsigned int ix=0;ix<3;ix++) {
v1Polarization.reset(ix);
v2Polarization.reset(ix);
v1.push_back(v1Polarization);
v2.push_back(v2Polarization);
}
VectorWaveFunction gPolarization(R.p2r(),p2data,incoming);
vector<VectorWaveFunction> g;
for(unsigned int ix=0;ix<3;ix+=2) {
gPolarization.reset(ix);
g.push_back(gPolarization);
}
AbstractFFVVertexPtr ffg = FFGvertex_;
AbstractFFVVertexPtr ffv1 = k1data->id()==23 ? FFZvertex_ : FFWvertex_;
AbstractFFVVertexPtr ffv2 = k2data->id()==23 ? FFZvertex_ : FFWvertex_;
// Collecting information for intermediate fermions
vector<tcPDPtr> tc;
if(abs(k1data->id())==24&&abs(k2data->id())==24) {
if(abs(p1data->id())%2==0)
for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(1+2*ix));
else
for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(2+2*ix));
}
else if(k1data->id()==23&&k2data->id()==23) tc.push_back(p1data);
else if(abs(k1data->id())==24&&k2data->id()==23) tc.push_back(kdata->CC());
// Loop over helicities summing the relevant diagrams
for(unsigned int p1hel=0;p1hel<2;++p1hel) {
for(unsigned int p2hel=0;p2hel<2;++p2hel) {
for(unsigned int khel=0;khel<2;++khel) {
SpinorWaveFunction p1_p2 = ffg->evaluate(QCDScale_,5,p1data,qin[p1hel],g[p2hel]);
SpinorBarWaveFunction p2_k = ffg->evaluate(QCDScale_,5,kdata->CC(),qout[khel],g[p2hel]);
for(unsigned int k1hel=0;k1hel<3;++k1hel) {
for(unsigned int k2hel=0;k2hel<3;++k2hel) {
// If helicity is exactly conserved (massless quarks) skip if p1hel!=khel
// but if the production ME is required first fill it with (0.,0.).
if((p1hel!=khel)&&helicityConservation_) {
if(getMatrix) {
if(p2hel==0)
qg_hel_amps(p1hel,0,k1hel,k2hel,khel) = Complex(0.,0.);
else
qg_hel_amps(p1hel,2,k1hel,k2hel,khel) = Complex(0.,0.);
}
continue;
}
vector<Complex> diagrams;
// Get all t-channel diagram contributions
tcPDPtr intermediate_q;
for(unsigned int ix=0;ix<tc.size();ix++) {
intermediate_q = (!(k1data->id()==24&&k2data->id()==-24)) ? showerAntiquark_->dataPtr() : tc[ix];
SpinorWaveFunction p1_v1 = ffv1->evaluate(EWScale_,5,intermediate_q,qin[p1hel],v1[k1hel]);
SpinorBarWaveFunction k_v2 = ffv2->evaluate(EWScale_,5,intermediate_q,qout[khel],v2[k2hel]);
// First calculate all the off-shell fermion currents
// Now calculate the 6 abelian diagrams
// q+g->v1+v2+q with 2 t-channel propagators, 1 s- and 1 t-channel and 2 t-channel ones.
if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==1))) {
diagrams.push_back(ffv2->evaluate(EWScale_,p1_v1,p2_k,v2[k2hel]));
diagrams.push_back(ffg->evaluate(QCDScale_,p1_v1,k_v2,g[p2hel]));
diagrams.push_back(ffv1->evaluate(EWScale_,p1_p2,k_v2,v1[k1hel]));
}
intermediate_q = (!(k1data->id()==24&&k2data->id()==-24)) ? p1data : tc[ix];
SpinorWaveFunction p1_v2 = ffv2->evaluate(EWScale_,5,intermediate_q,qin[p1hel],v2[k2hel]);
SpinorBarWaveFunction k_v1 = ffv1->evaluate(EWScale_,5,intermediate_q,qout[khel],v1[k1hel]);
// q+g->v2+v1+q, with 2 t-channel propagators, 1 s- and 1 t-channel and 2 t-channel ones.
if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==0))) {
diagrams.push_back(ffv1->evaluate(EWScale_,p1_v2,p2_k,v1[k1hel]));
diagrams.push_back(ffg->evaluate(QCDScale_,p1_v2,k_v1,g[p2hel]));
diagrams.push_back(ffv2->evaluate(EWScale_,p1_p2,k_v1,v2[k2hel]));
}
}
// Note: choosing 3 as the second argument in WWWvertex_->evaluate()
// sets option 3 in thepeg/Helicity/Vertex/VertexBase.cc , which
// means the propagator does not contain a width factor (which is
// good re. gauge invariance).
// If W+Z / W-Z calculate the two V+jet-like s-channel diagrams
if(abs(k1data->id())==24&&k2data->id()==23) {
// The off-shell s-channel boson current
VectorWaveFunction k1_k2 =
WWWvertex_->evaluate(EWScale_,3,k1data->CC(),v2[k2hel],v1[k1hel]);
// q+qb->g+v1*->g+v1+v2, q+qb->v1*+g->v1+v2+g
diagrams.push_back(ffv1->evaluate(EWScale_,p1_p2,qout[khel],k1_k2));
diagrams.push_back(ffv1->evaluate(EWScale_,qin[p1hel],p2_k,k1_k2));
}
// If W+W- calculate the four V+jet-like s-channel diagrams
if((k1data->id()==24&&k2data->id()==-24)&&(p1data->id()==kdata->id())) {
// The off-shell s-channel boson current
VectorWaveFunction k1_k2;
// q+qb->g+Z0*->g+v1+v2,q+qb->Z0*+g->v1+v2+g,
tcPDPtr Z0 = getParticleData(ParticleID::Z0);
k1_k2 = WWWvertex_->evaluate(EWScale_,3,Z0,v2[k2hel],v1[k1hel]);
diagrams.push_back(FFZvertex_->evaluate(EWScale_,p1_p2,qout[khel],k1_k2));
diagrams.push_back(FFZvertex_->evaluate(EWScale_,qin[p1hel],p2_k,k1_k2));
// q+qb->g+gamma*->g+v1+v2,q+qb->gamma*+g->v1+v2+g,
tcPDPtr gamma = getParticleData(ParticleID::gamma);
k1_k2 = WWWvertex_->evaluate(EWScale_,3,gamma,v2[k2hel],v1[k1hel]);
diagrams.push_back(FFPvertex_->evaluate(EWScale_,p1_p2,qout[khel],k1_k2));
diagrams.push_back(FFPvertex_->evaluate(EWScale_,qin[p1hel],p2_k,k1_k2));
}
// Add up all diagrams to get the total amplitude:
Complex hel_amp(0.);
for(unsigned int ix=0;ix<diagrams.size();ix++) hel_amp += diagrams[ix];
// If we need to fill the production ME we do it here:
if(getMatrix) {
if(p2hel==0)
qg_hel_amps(p1hel,0,k1hel,k2hel,khel) = hel_amp;
else
qg_hel_amps(p1hel,2,k1hel,k2hel,khel) = hel_amp;
}
sum_hel_amps_sqr += norm(hel_amp);
}
}
}
}
}
// Fill up the remaining bits of the production ME, corresponding
// to longitudinal gluon polarization, with (0.,0.).
if(getMatrix) {
for(unsigned int p1hel=0;p1hel<2;++p1hel) {
for(unsigned int k1hel=0;k1hel<3;++k1hel) {
for(unsigned int k2hel=0;k2hel<3;++k2hel) {
for(unsigned int khel=0;khel<2;++khel) {
qg_hel_amps(p1hel,1,k1hel,k2hel,khel) = Complex(0.,0.);
}
}
}
}
}
// Calculate the production density matrix:
if(getMatrix) {
for(unsigned int k1hel=0;k1hel<3;++k1hel) {
for(unsigned int k1helpr=0;k1helpr<3;++k1helpr) {
for(unsigned int k2hel=0;k2hel<3;++k2hel) {
for(unsigned int k2helpr=0;k2helpr<3;++k2helpr) {
Complex theElement(0.,0.);
// For each k1hel, k1helpr, k2hel, k2helpr sum over fermion and gluon spins...
for(unsigned int p1hel=0;p1hel<2;++p1hel) {
for(unsigned int p2hel=0;p2hel<3;p2hel+=2) {
for(unsigned int khel=0;khel<2;++khel) {
theElement += qg_hel_amps(p1hel,p2hel,k1hel ,k2hel ,khel)
*conj(qg_hel_amps(p1hel,p2hel,k1helpr,k2helpr,khel));
}
}
}
// ...and then set the production matrix element to the sum:
productionMatrix_[k1hel][k1helpr][k2hel][k2helpr] = theElement;
}
}
}
}
}
// Spin and colour averaging factors = 1/4 * TR * 1/3 = 1/24
sum_hel_amps_sqr /= 24.;
// Symmetry factor for identical Z bosons in the final state
if(k1data->id()==23&&k2data->id()==23) sum_hel_amps_sqr /= 2.;
return sum_hel_amps_sqr*R.tkr()*R.ukr()*UnitRemoval::InvE2;
}
/***************************************************************************/
// This is identical to the code in the Powheg matrix element. It should
// equal t_u_M_R_gqb in there, which is supposed to be the real emission ME
// times tk*uk.
Energy2 MEPP2VVPowheg::t_u_M_R_gqb_hel_amp(realVVKinematics R, bool getMatrix) const {
using namespace ThePEG::Helicity;
ProductionMatrixElement gqb_hel_amps(PDT::Spin1,PDT::Spin1Half,
PDT::Spin1,PDT::Spin1,
PDT::Spin1Half);
double sum_hel_amps_sqr(0.);
tcPDPtr p1data(getParticleData(ParticleID::g));
tcPDPtr p2data(showerAntiquark_->dataPtr());
tcPDPtr k1data(V1_->dataPtr());
tcPDPtr k2data(V2_->dataPtr());
tcPDPtr kdata (showerQuark_->dataPtr()->CC());
if(k1data->id()==-24&&k2data->id()==24) swap(k1data,k2data);
SpinorBarWaveFunction qbinSpinor(R.p2r(),p2data,incoming);
SpinorWaveFunction qboutSpinor(R.kr(),kdata,outgoing);
vector<SpinorBarWaveFunction> qbin;
vector<SpinorWaveFunction> qbout;
for(unsigned int ix=0;ix<2;ix++) {
qbinSpinor.reset(ix);
qboutSpinor.reset(ix);
qbin.push_back(qbinSpinor);
qbout.push_back(qboutSpinor);
}
VectorWaveFunction v1Polarization(R.k1r(),k1data,outgoing);
VectorWaveFunction v2Polarization(R.k2r(),k2data,outgoing);
vector<VectorWaveFunction> v1;
vector<VectorWaveFunction> v2;
for(unsigned int ix=0;ix<3;ix++) {
v1Polarization.reset(ix);
v2Polarization.reset(ix);
v1.push_back(v1Polarization);
v2.push_back(v2Polarization);
}
VectorWaveFunction gPolarization(R.p1r(),p1data,incoming);
vector<VectorWaveFunction> g;
for(unsigned int ix=0;ix<3;ix+=2) {
gPolarization.reset(ix);
g.push_back(gPolarization);
}
AbstractFFVVertexPtr ffg = FFGvertex_;
AbstractFFVVertexPtr ffv1 = k1data->id()==23 ? FFZvertex_ : FFWvertex_;
AbstractFFVVertexPtr ffv2 = k2data->id()==23 ? FFZvertex_ : FFWvertex_;
// Collecting information for intermediate fermions
vector<tcPDPtr> tc;
if(abs(k1data->id())==24&&abs(k2data->id())==24) {
if(abs(p2data->id())%2==0)
for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(1+2*ix));
else
for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(2+2*ix));
}
else if(k1data->id()==23&&k2data->id()==23) tc.push_back(p2data);
else if(abs(k1data->id())==24&&k2data->id()==23) tc.push_back(kdata->CC());
// Loop over helicities summing the relevant diagrams
for(unsigned int p1hel=0;p1hel<2;++p1hel) {
for(unsigned int p2hel=0;p2hel<2;++p2hel) {
for(unsigned int khel=0;khel<2;++khel) {
SpinorBarWaveFunction p1_p2 = ffg->evaluate(QCDScale_,5,p2data,qbin[p2hel],g[p1hel]);
SpinorWaveFunction p1_k = ffg->evaluate(QCDScale_,5,kdata->CC(),qbout[khel],g[p1hel]);
for(unsigned int k1hel=0;k1hel<3;++k1hel) {
for(unsigned int k2hel=0;k2hel<3;++k2hel) {
// If helicity is exactly conserved (massless quarks) skip if p2hel!=khel
// but if the production ME is required first fill it with (0.,0.).
if((p2hel!=khel)&&helicityConservation_) {
if(getMatrix) {
if(p1hel==0)
gqb_hel_amps(0,p2hel,k1hel,k2hel,khel) = Complex(0.,0.);
else
gqb_hel_amps(2,p2hel,k1hel,k2hel,khel) = Complex(0.,0.);
}
continue;
}
vector<Complex> diagrams;
// Get all t-channel diagram contributions
tcPDPtr intermediate_q;
for(unsigned int ix=0;ix<tc.size();ix++) {
intermediate_q = (!(k1data->id()==24&&k2data->id()==-24)) ? showerQuark_->dataPtr() : tc[ix];
SpinorBarWaveFunction p2_v1 = ffv1->evaluate(EWScale_,5,intermediate_q,qbin[p2hel],v1[k1hel]);
SpinorWaveFunction k_v2 = ffv2->evaluate(EWScale_,5,intermediate_q,qbout[khel],v2[k2hel]);
// First calculate all the off-shell fermion currents
// Now calculate the 6 abelian diagrams q+g->v1+v2+q
// with 2 t-channel propagators, 1 s- and 1 t-channel
// and 2 t-channel ones.
if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p2data->id())%2==0))) {
diagrams.push_back(ffv2->evaluate(EWScale_,p1_k,p2_v1,v2[k2hel]));
diagrams.push_back(ffg->evaluate(QCDScale_,k_v2,p2_v1,g[p1hel]));
diagrams.push_back(ffv1->evaluate(EWScale_,k_v2,p1_p2,v1[k1hel]));
}
intermediate_q = (!(k1data->id()==24&&k2data->id()==-24)) ? p2data : tc[ix];
SpinorBarWaveFunction p2_v2 = ffv2->evaluate(EWScale_,5,intermediate_q,qbin[p2hel],v2[k2hel]);
SpinorWaveFunction k_v1 = ffv1->evaluate(EWScale_,5,intermediate_q,qbout[khel],v1[k1hel]);
// q+g->v2+v1+q, with 2 t-channel propagators, 1 s- and 1 t-channel and 2 t-channel ones.
if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p2data->id())%2==1))) {
diagrams.push_back(ffv1->evaluate(EWScale_,p1_k,p2_v2,v1[k1hel]));
diagrams.push_back(ffg->evaluate(QCDScale_,k_v1,p2_v2,g[p1hel]));
diagrams.push_back(ffv2->evaluate(EWScale_,k_v1,p1_p2,v2[k2hel]));
}
}
// Note: choosing 3 as the second argument in WWWvertex_->evaluate()
// sets option 3 in thepeg/Helicity/Vertex/VertexBase.cc , which
// means the propagator does not contain a width factor (which is
// good re. gauge invariance).
// If W+Z / W-Z calculate the two V+jet-like s-channel diagrams
if(abs(k1data->id())==24&&k2data->id()==23) {
// The off-shell s-channel boson current
VectorWaveFunction k1_k2 =
WWWvertex_->evaluate(EWScale_,3,k1data->CC(),v2[k2hel],v1[k1hel]);
// q+qb->g+v1*->g+v1+v2, q+qb->v1*+g->v1+v2+g
diagrams.push_back(ffv1->evaluate(EWScale_,qbout[khel],p1_p2,k1_k2));
diagrams.push_back(ffv1->evaluate(EWScale_,p1_k,qbin[p2hel],k1_k2));
}
// If W+W- calculate the four V+jet-like s-channel diagrams
if((k1data->id()==24&&k2data->id()==-24)&&(p2data->id()==kdata->id())) {
// The off-shell s-channel boson current
VectorWaveFunction k1_k2;
// q+qb->g+Z0*->g+v1+v2,q+qb->Z0*+g->v1+v2+g,
tcPDPtr Z0 = getParticleData(ParticleID::Z0);
k1_k2 = WWWvertex_->evaluate(EWScale_,3,Z0,v2[k2hel],v1[k1hel]);
diagrams.push_back(FFZvertex_->evaluate(EWScale_,qbout[khel],p1_p2,k1_k2));
diagrams.push_back(FFZvertex_->evaluate(EWScale_,p1_k,qbin[p2hel],k1_k2));
// q+qb->g+gamma*->g+v1+v2,q+qb->gamma*+g->v1+v2+g,
tcPDPtr gamma = getParticleData(ParticleID::gamma);
k1_k2 = WWWvertex_->evaluate(EWScale_,3,gamma,v2[k2hel],v1[k1hel]);
diagrams.push_back(FFPvertex_->evaluate(EWScale_,qbout[khel],p1_p2,k1_k2));
diagrams.push_back(FFPvertex_->evaluate(EWScale_,p1_k,qbin[p2hel],k1_k2));
}
// Add up all diagrams to get the total amplitude:
Complex hel_amp(0.);
for(unsigned int ix=0;ix<diagrams.size();ix++) hel_amp += diagrams[ix];
// If we need to fill the production ME we do it here:
if(getMatrix) {
if(p1hel==0)
gqb_hel_amps(0,p2hel,k1hel,k2hel,khel) = hel_amp;
else
gqb_hel_amps(2,p2hel,k1hel,k2hel,khel) = hel_amp;
}
sum_hel_amps_sqr += norm(hel_amp);
}
}
}
}
}
// Fill up the remaining bits of the production ME, corresponding
// to longitudinal gluon polarization, with (0.,0.).
if(getMatrix) {
for(unsigned int p2hel=0;p2hel<2;++p2hel) {
for(unsigned int k1hel=0;k1hel<3;++k1hel) {
for(unsigned int k2hel=0;k2hel<3;++k2hel) {
for(unsigned int khel=0;khel<2;++khel) {
gqb_hel_amps(1,p2hel,k1hel,k2hel,khel) = Complex(0.,0.);
}
}
}
}
}
// Calculate the production density matrix:
if(getMatrix) {
for(unsigned int k1hel=0;k1hel<3;++k1hel) {
for(unsigned int k1helpr=0;k1helpr<3;++k1helpr) {
for(unsigned int k2hel=0;k2hel<3;++k2hel) {
for(unsigned int k2helpr=0;k2helpr<3;++k2helpr) {
Complex theElement(0.,0.);
// For each k1hel, k1helpr, k2hel, k2helpr sum over fermion and gluon spins...
for(unsigned int p1hel=0;p1hel<3;p1hel+=2) {
for(unsigned int p2hel=0;p2hel<2;++p2hel) {
for(unsigned int khel=0;khel<2;++khel) {
theElement += gqb_hel_amps(p1hel,p2hel,k1hel ,k2hel ,khel)
*conj(gqb_hel_amps(p1hel,p2hel,k1helpr,k2helpr,khel));
}
}
}
// ...and then set the production matrix element to the sum:
productionMatrix_[k1hel][k1helpr][k2hel][k2helpr] = theElement;
}
}
}
}
}
// Spin and colour averaging factors = 1/4 * TR * 1/3 = 1/24
sum_hel_amps_sqr /= 24.;
// Symmetry factor for identical Z bosons in the final state
if(k1data->id()==23&&k2data->id()==23) sum_hel_amps_sqr /= 2.;
return sum_hel_amps_sqr*R.tkr()*R.ukr()*UnitRemoval::InvE2;
}
/***************************************************************************/
// This returns exactly the same value as lo_me2_ when you put it in MEPP2VVPowheg.cc
double MEPP2VVPowheg::lo_me(bool getMatrix) const {
using namespace ThePEG::Helicity;
ProductionMatrixElement lo_hel_amps(PDT::Spin1Half,PDT::Spin1Half,
PDT::Spin1 ,PDT::Spin1);
double sum_hel_amps_sqr(0.);
tcPDPtr p1data(showerQuark_->dataPtr());
tcPDPtr p2data(showerAntiquark_->dataPtr());
tcPDPtr k1data(V1_->dataPtr());
tcPDPtr k2data(V2_->dataPtr());
if(k1data->id()==-24&&k2data->id()==24) swap(k1data,k2data); // Should never actually occur.
// If you want to reproduce the spin correlations of MEPP2VV
// you should evaluate this ME using the lab frame momenta
// instead of the bornVVKinematics ones (partonic C.O.M. frame).
SpinorWaveFunction qSpinor;
SpinorBarWaveFunction qbSpinor;
if(!getMatrix) {
qSpinor=SpinorWaveFunction(B_.p1b(),p1data,incoming);
qbSpinor=SpinorBarWaveFunction(B_.p2b(),p2data,incoming);
} else {
qSpinor=SpinorWaveFunction(showerQuark_->momentum(),p1data,incoming);
qbSpinor=SpinorBarWaveFunction(showerAntiquark_->momentum(),p2data,incoming);
}
vector<SpinorWaveFunction> q;
vector<SpinorBarWaveFunction> qb;
for(unsigned int ix=0;ix<2;ix++) {
qSpinor.reset(ix);
qbSpinor.reset(ix);
q.push_back(qSpinor);
qb.push_back(qbSpinor);
}
// If you want to reproduce the spin correlations of MEPP2VV
// you should evaluate this ME using the lab frame momenta
// instead of the bornVVKinematics ones (partonic C.O.M. frame).
VectorWaveFunction v1Polarization;
VectorWaveFunction v2Polarization;
if(!getMatrix) {
v1Polarization=VectorWaveFunction(B_.k1b(),k1data,outgoing);
v2Polarization=VectorWaveFunction(B_.k2b(),k2data,outgoing);
} else {
v1Polarization=VectorWaveFunction(V1_->momentum(),k1data,outgoing);
v2Polarization=VectorWaveFunction(V2_->momentum(),k2data,outgoing);
}
vector<VectorWaveFunction> v1;
vector<VectorWaveFunction> v2;
for(unsigned int ix=0;ix<3;ix++) {
v1Polarization.reset(ix);
v2Polarization.reset(ix);
v1.push_back(v1Polarization);
v2.push_back(v2Polarization);
}
AbstractFFVVertexPtr ffv1 = k1data->id()==23 ? FFZvertex_ : FFWvertex_;
AbstractFFVVertexPtr ffv2 = k2data->id()==23 ? FFZvertex_ : FFWvertex_;
// Collecting information for intermediate fermions
vector<tcPDPtr> tc;
if(abs(k1data->id())==24&&abs(k2data->id())==24) {
if(abs(p1data->id())%2==0)
for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(1+2*ix));
else
for(int ix=0;ix<3;++ix) tc.push_back(getParticleData(2+2*ix));
}
else if(k1data->id()==23&&k2data->id()==23) tc.push_back(p1data);
else if(abs(k1data->id())==24&&k2data->id()==23) tc.push_back(p2data);
// Loop over helicities summing the relevant diagrams
for(unsigned int p1hel=0;p1hel<2;++p1hel) {
for(unsigned int p2hel=0;p2hel<2;++p2hel) {
for(unsigned int k1hel=0;k1hel<3;++k1hel) {
for(unsigned int k2hel=0;k2hel<3;++k2hel) {
if((p1hel==p2hel)&&helicityConservation_) {
lo_hel_amps(p1hel,p2hel,k1hel,k2hel) = Complex(0.,0.);
continue;
}
vector<Complex> diagrams;
// Get all t-channel diagram contributions
tcPDPtr intermediate_t;
for(unsigned int ix=0;ix<tc.size();ix++) {
intermediate_t = (!(k1data->id()==24&&k2data->id()==-24)) ? p2data : tc[ix];
SpinorWaveFunction p1_v1 = ffv1->evaluate(EWScale_,5,intermediate_t,q[p1hel],v1[k1hel]);
// First calculate all the off-shell fermion currents
// Now calculate the 6 t-channel diagrams
// q+qb->v1+v2
if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==1)))
diagrams.push_back(ffv2->evaluate(EWScale_,p1_v1,qb[p2hel],v2[k2hel]));
intermediate_t = (!(k1data->id()==24&&k2data->id()==-24)) ? p1data : tc[ix];
SpinorWaveFunction p1_v2 = ffv2->evaluate(EWScale_,5,intermediate_t,q[p1hel],v2[k2hel]);
// q+qb->v2+v1
if(!((k1data->id()==24&&k2data->id()==-24)&&(abs(p1data->id())%2==0)))
diagrams.push_back(ffv1->evaluate(EWScale_,p1_v2,qb[p2hel],v1[k1hel]));
}
// Note: choosing 3 as the second argument in WWWvertex_->evaluate()
// sets option 3 in thepeg/Helicity/Vertex/VertexBase.cc , which
// means the propagator does not contain a width factor (which is
// good re. gauge invariance).
// If W+Z / W-Z calculate the two V+jet-like s-channel diagrams
if(abs(k1data->id())==24&&k2data->id()==23) {
// The off-shell s-channel boson current
VectorWaveFunction k1_k2 =
WWWvertex_->evaluate(EWScale_,3,k1data->CC(),v2[k2hel],v1[k1hel]);
// q+qb->v1*->v1+v2
diagrams.push_back(ffv1->evaluate(EWScale_,q[p1hel],qb[p2hel],k1_k2));
}
// If W+W- calculate the four V+jet-like s-channel diagrams
if((k1data->id()==24&&k2data->id()==-24)&&(p1data->id()==-p2data->id())) {
// The off-shell s-channel boson current
VectorWaveFunction k1_k2;
// q+qb->Z0*->v1+v2
tcPDPtr Z0 = getParticleData(ParticleID::Z0);
k1_k2 = WWWvertex_->evaluate(EWScale_,3,Z0,v2[k2hel],v1[k1hel]);
diagrams.push_back(FFZvertex_->evaluate(EWScale_,q[p1hel],qb[p2hel],k1_k2));
// q+qb->gamma*->v1+v2
tcPDPtr gamma = getParticleData(ParticleID::gamma);
k1_k2 = WWWvertex_->evaluate(EWScale_,3,gamma,v2[k2hel],v1[k1hel]);
diagrams.push_back(FFPvertex_->evaluate(EWScale_,q[p1hel],qb[p2hel],k1_k2));
}
// Add up all diagrams to get the total amplitude:
Complex hel_amp(0.);
for(unsigned int ix=0;ix<diagrams.size();ix++) hel_amp += diagrams[ix];
// If we need to fill the production ME we do it here:
if(getMatrix) lo_hel_amps(p1hel,p2hel,k1hel,k2hel) = hel_amp;
sum_hel_amps_sqr += norm(hel_amp);
}
}
}
}
// Calculate the production density matrix:
if(getMatrix) {
for(unsigned int k1hel=0;k1hel<3;++k1hel) {
for(unsigned int k1helpr=0;k1helpr<3;++k1helpr) {
for(unsigned int k2hel=0;k2hel<3;++k2hel) {
for(unsigned int k2helpr=0;k2helpr<3;++k2helpr) {
Complex theElement(0.,0.);
// For each k1hel, k1helpr, k2hel, k2helpr sum over the fermion spins...
for(unsigned int p1hel=0;p1hel<2;++p1hel) {
for(unsigned int p2hel=0;p2hel<2;++p2hel) {
if((p1hel==p2hel)&&helicityConservation_) continue;
theElement += lo_hel_amps(p1hel,p2hel,k1hel ,k2hel )
*conj(lo_hel_amps(p1hel,p2hel,k1helpr,k2helpr));
}
}
// ...and then set the production matrix element to the sum:
productionMatrix_[k1hel][k1helpr][k2hel][k2helpr] = theElement;
}
}
}
}
}
// Spin and colour averaging factors = 1/4 * 1/3 = 1/12
sum_hel_amps_sqr /= 12.;
// Symmetry factor for identical Z bosons in the final state
if(k1data->id()==23&&k2data->id()==23) sum_hel_amps_sqr /= 2.;
return sum_hel_amps_sqr;
}
/***************************************************************************/
// This member selects a [2-body] decay mode and assigns children to the
// vector bosons with momenta which are isotropic in their rest frames.
bool MEPP2VVPowheg::isotropicDecayer() {
using namespace ThePEG::Helicity;
// Generate the children's momenta isotropically in
// the rest frames of V1 and V2:
double cth,phi;
// First V1's children:
cth = UseRandom::rnd()*2.-1.;
phi = UseRandom::rnd()*2.*Constants::pi;
Energy m1(V1_->momentum().m());
Energy m3(children_[0]->data().constituentMass());
Energy m4(children_[1]->data().constituentMass());
Energy p34(triangleFn(sqr(m1),sqr(m3),sqr(m4))
/2./m1);
- if(isnan(p34/GeV)||cth>1.||cth<-1.) return false;
+ if(std::isnan(double(p34/MeV))||cth>1.||cth<-1.) return false;
Energy pT34(p34*sqrt(1.-cth)*sqrt(1.+cth));
Lorentz5Momentum k3(pT34*sin(phi),pT34*cos(phi),p34 *cth,
sqrt(p34*p34+sqr(m3)),m3);
Lorentz5Momentum k4(-k3);
k4.setE(sqrt(p34*p34+sqr(m4)));
k4.setTau(m4);
Boost boostToV1RF(R_.k1r().boostVector());
k3.boost(boostToV1RF);
k3.rescaleRho();
k4.boost(boostToV1RF);
k4.rescaleRho();
// Second V2's children:
cth = UseRandom::rnd()*2.-1.;
phi = UseRandom::rnd()*2.*Constants::pi;
Energy m2(V2_->momentum().m());
Energy m5(children_[2]->data().constituentMass());
Energy m6(children_[3]->data().constituentMass());
Energy p56(triangleFn(sqr(m2),sqr(m5),sqr(m6))
/2./m2);
- if(isnan(p56/GeV)||cth>1.||cth<-1.) return false;
+ if(std::isnan(double(p56/MeV))||cth>1.||cth<-1.) return false;
Energy pT56(p56*sqrt(1.-cth)*sqrt(1.+cth));
Lorentz5Momentum k5(pT56*sin(phi),pT56*cos(phi),p56*cth,
sqrt(p56*p56+sqr(m5)),m5);
Lorentz5Momentum k6(-k5);
k6.setE(sqrt(p56*p56+sqr(m6)));
k6.setTau(m6);
Boost boostToV2RF(R_.k2r().boostVector());
k5.boost(boostToV2RF);
k5.rescaleRho();
k6.boost(boostToV2RF);
k6.rescaleRho();
// Assign the momenta to the children:
children_[0]->set5Momentum(k3);
children_[1]->set5Momentum(k4);
children_[2]->set5Momentum(k5);
children_[3]->set5Momentum(k6);
return true;
}
// Override 2->2 production matrix here:
void MEPP2VVPowheg::recalculateVertex() {
// Zero the squared amplitude; this equals sum_hel_amps_sqr if all
// is working as it should:
Complex productionMatrix2(0.,0.);
for(unsigned int k1hel=0;k1hel<3;++k1hel)
for(unsigned int k2hel=0;k2hel<3;++k2hel)
productionMatrix2 += productionMatrix_[k1hel][k1hel][k2hel][k2hel];
// Get the vector wavefunctions:
VectorWaveFunction v1Polarization;
VectorWaveFunction v2Polarization;
v1Polarization=VectorWaveFunction(R_.k1r(),V1_->dataPtr(),outgoing);
v2Polarization=VectorWaveFunction(R_.k2r(),V2_->dataPtr(),outgoing);
vector<VectorWaveFunction> v1;
vector<VectorWaveFunction> v2;
for(unsigned int ix=0;ix<3;ix++) {
v1Polarization.reset(ix);
v2Polarization.reset(ix);
v1.push_back(v1Polarization);
v2.push_back(v2Polarization);
}
AbstractFFVVertexPtr ffv1 = V1_->id()==23 ? FFZvertex_ : FFWvertex_;
AbstractFFVVertexPtr ffv2 = V2_->id()==23 ? FFZvertex_ : FFWvertex_;
bool vetoed(true);
while(vetoed) {
// Decay the bosons isotropically in their rest frames:
isotropicDecayer();
// Get the spinor wavefunctions:
SpinorWaveFunction k3Spinor(children_[0]->momentum(),children_[0]->dataPtr(),outgoing);
SpinorBarWaveFunction k4Spinor(children_[1]->momentum(),children_[1]->dataPtr(),outgoing);
SpinorWaveFunction k5Spinor(children_[2]->momentum(),children_[2]->dataPtr(),outgoing);
SpinorBarWaveFunction k6Spinor(children_[3]->momentum(),children_[3]->dataPtr(),outgoing);
vector<SpinorWaveFunction> k3,k5;
vector<SpinorBarWaveFunction> k4,k6;
for(unsigned int ix=0;ix<2;ix++) {
k3Spinor.reset(ix);
k4Spinor.reset(ix);
k3.push_back(k3Spinor);
k4.push_back(k4Spinor);
k5Spinor.reset(ix);
k6Spinor.reset(ix);
k5.push_back(k5Spinor);
k6.push_back(k6Spinor);
}
DecayMEPtr decayAmps(new_ptr(GeneralDecayMatrixElement(PDT::Spin1,PDT::Spin1Half,PDT::Spin1Half)));
for(unsigned int k1hel=0;k1hel<3;++k1hel) {
for(unsigned int k3hel=0;k3hel<2;++k3hel) {
for(unsigned int k4hel=0;k4hel<2;++k4hel) {
(*decayAmps)(k1hel,k3hel,k4hel) =
ffv1->evaluate(EWScale_,k3[k3hel],k4[k4hel],v1[k1hel]);
}
}
}
Complex V1decayMatrix[3][3];
for(unsigned int k1hel=0;k1hel<3;++k1hel) {
for(unsigned int k1helpr=0;k1helpr<3;++k1helpr) {
Complex theElement(0.,0.);
for(unsigned int k3hel=0;k3hel<2;++k3hel) {
for(unsigned int k4hel=0;k4hel<2;++k4hel) {
theElement += (*decayAmps)(k1hel,k3hel,k4hel)
*conj((*decayAmps)(k1helpr,k3hel,k4hel));
}
}
V1decayMatrix[k1hel][k1helpr] = theElement;
}
}
Complex V1decayMatrix2(0.,0.);
for(unsigned int k1hel=0;k1hel<3;++k1hel) V1decayMatrix2 += V1decayMatrix[k1hel][k1hel];
for(unsigned int k2hel=0;k2hel<3;++k2hel) {
for(unsigned int k5hel=0;k5hel<2;++k5hel) {
for(unsigned int k6hel=0;k6hel<2;++k6hel) {
(*decayAmps)(k2hel,k5hel,k6hel) =
ffv2->evaluate(EWScale_,k5[k5hel],k6[k6hel],v2[k2hel]);
}
}
}
Complex V2decayMatrix[3][3];
for(unsigned int k2hel=0;k2hel<3;++k2hel) {
for(unsigned int k2helpr=0;k2helpr<3;++k2helpr) {
Complex theElement(0.,0.);
for(unsigned int k5hel=0;k5hel<2;++k5hel) {
for(unsigned int k6hel=0;k6hel<2;++k6hel) {
theElement += (*decayAmps)(k2hel,k5hel,k6hel)
*conj((*decayAmps)(k2helpr,k5hel,k6hel));
}
}
V2decayMatrix[k2hel][k2helpr] = theElement;
}
}
Complex V2decayMatrix2(0.,0.);
for(unsigned int k2hel=0;k2hel<3;++k2hel) V2decayMatrix2 += V2decayMatrix[k2hel][k2hel];
// Contract the production matrix and the decay matrices:
Complex meTimesV1V2denominators(0.,0.);
for(unsigned int k1hel=0;k1hel<3;++k1hel) {
for(unsigned int k1helpr=0;k1helpr<3;++k1helpr) {
for(unsigned int k2hel=0;k2hel<3;++k2hel) {
for(unsigned int k2helpr=0;k2helpr<3;++k2helpr) {
meTimesV1V2denominators +=
productionMatrix_[k1hel][k1helpr][k2hel][k2helpr]
*V1decayMatrix[k1hel][k1helpr]
*V2decayMatrix[k2hel][k2helpr];
}
}
}
}
if(imag(meTimesV1V2denominators)/real(meTimesV1V2denominators)>1.e-7)
cout << "MEPP2VVPowheg warning\n"
<< "the matrix element's imaginary part is large "
<< meTimesV1V2denominators << endl;
if(imag(productionMatrix2)/real(productionMatrix2)>1.e-7)
cout << "MEPP2VVPowheg warning\n"
<< "the production matrix element's imaginary part is large "
<< productionMatrix2 << endl;
if(imag(V1decayMatrix2)/real(V1decayMatrix2)>1.e-7)
cout << "MEPP2VVPowheg warning\n"
<< "the V1 decay matrix element's imaginary part is large "
<< V1decayMatrix2 << endl;
if(imag(V2decayMatrix2)/real(V2decayMatrix2)>1.e-7)
cout << "MEPP2VVPowheg warning\n"
<< "the V2 decay matrix element's imaginary part is large "
<< V2decayMatrix2 << endl;
// Need branching ratio at least in here I would think --->
double decayWeight( real(meTimesV1V2denominators)
/ real(productionMatrix2*V1decayMatrix2*V2decayMatrix2));
if(decayWeight>1.)
cout << "MEPP2VVPowheg::recalculateVertex decayWeight > 1., decayWeight = "
<< decayWeight << endl;
if(decayWeight<0.)
cout << "MEPP2VVPowheg::recalculateVertex decayWeight < 0., decayWeight = "
<< decayWeight << endl;
if(UseRandom::rnd()<decayWeight) vetoed = false;
else vetoed = true;
}
return;
}
Energy2 MEPP2VVPowheg::triangleFn(Energy2 m12,Energy2 m22, Energy2 m32) {
Energy4 lambda2(m12*m12+m22*m22+m32*m32-2.*m12*m22-2.*m12*m32-2.*m22*m32);
if(lambda2>=ZERO) {
return sqrt(lambda2);
} else {
generator()->log()
<< "MEPP2VVPowheg::triangleFn "
<< "kinematic instability, imaginary triangle function\n";
return -999999.*GeV2;
}
}
diff --git a/MatrixElement/Powheg/MEPP2VVPowheg.h b/MatrixElement/Powheg/MEPP2VVPowheg.h
--- a/MatrixElement/Powheg/MEPP2VVPowheg.h
+++ b/MatrixElement/Powheg/MEPP2VVPowheg.h
@@ -1,873 +1,873 @@
// -*- C++ -*-
#ifndef HERWIG_MEPP2VVPowheg_H
#define HERWIG_MEPP2VVPowheg_H
//
// This is the declaration of the MEPP2VVPowheg class.
//
#include "Herwig/MatrixElement/Hadron/MEPP2VV.h"
#include "Herwig/MatrixElement/Powheg/VVKinematics.h"
#include "Herwig/Utilities/Maths.h"
#include "Herwig/Models/StandardModel/StandardCKM.h"
#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h"
namespace Herwig {
using namespace ThePEG;
using Math::ReLi2;
using Constants::pi;
/**
* Here is the documentation of the MEPP2VVPowheg class.
*
* @see \ref MEPP2VVPowhegInterfaces "The interfaces"
* defined for MEPP2VVPowheg.
*/
class MEPP2VVPowheg: public MEPP2VV {
public:
/**
* The default constructor.
*/
MEPP2VVPowheg();
/** @name Member functions for the generation of hard QCD radiation */
//@{
/**
* Has a POWHEG style correction
*/
virtual POWHEGType hasPOWHEGCorrection() {return ISR;}
/**
* Apply the POWHEG style correction
*/
virtual RealEmissionProcessPtr generateHardest(RealEmissionProcessPtr,
- ShowerInteraction::Type inter);
+ ShowerInteraction inter);
//@}
public:
/**
* Generate internal degrees of freedom given nDim() uniform
* random numbers in the interval \f$ ]0,1[ \f$. To help the phase space
* generator, the dSigHatDR should be a smooth function of these
* numbers, although this is not strictly necessary.
* @param r a pointer to the first of nDim() consecutive random numbers.
* @return true if the generation succeeded, otherwise false.
*/
virtual bool generateKinematics(const double * r);
/**
* The number of internal degrees of freedom used in the matrix
* element.
*/
virtual int nDim() const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
virtual double me2() const;
/**
* Return the scale associated with the last set phase space point.
*/
virtual Energy2 scale() const;
/**
* This member check the collinear limits of the
* real emission matrix elements are equal to the
* appropriate combinations of Born ME's multiplied
* by the splitting functions.
*/
bool sanityCheck() const;
/**
* Return the CKM matrix elements.
*/
Complex CKM(int ix,int iy) const { return ckm_[ix][iy]; }
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();
//@}
public:
/**
* Function to set the born variables.
*/
void getKinematics(double xt, double y, double theta2);
/**
* Calculate the correction weight with which leading-order
* configurations are re-weighted.
*/
double NLOweight() const;
/**
* Calculate the ratio of the NLO luminosity to the LO
* luminosity function for the \f$q\bar{q}\f$ initiated channel.
*/
double Lhat_ab(tcPDPtr a, tcPDPtr b, realVVKinematics Kinematics) const;
/**
* Calculate the universal soft-virtual contribution to the NLO weight.
*/
double Vtilde_universal(realVVKinematics S) const;
/**
* Function for calculation of the \f$q\bar{q}\f$ initiated real
* contribution.
*/
double Ctilde_Ltilde_qq_on_x(tcPDPtr a,tcPDPtr b,realVVKinematics C) const;
/**
* Function for calculation of the \f$gq\f$ initiated real
* contribution.
*/
double Ctilde_Ltilde_gq_on_x(tcPDPtr a,tcPDPtr b,realVVKinematics C) const;
/**
* Function for calculation of the \f$q\bar{q}\f$ initiated real
* contribution.
*/
double Rtilde_Ltilde_qqb_on_x(tcPDPtr a,tcPDPtr b) const;
/**
* Function for calculation of the \f$qg\f$ initiated real
* contribution.
*/
double Rtilde_Ltilde_qg_on_x(tcPDPtr a,tcPDPtr b) const;
/**
* Function for calculation of the \f$gqb\f$ initiated real
* contribution.
*/
double Rtilde_Ltilde_gqb_on_x(tcPDPtr a,tcPDPtr b) const;
/**
* The regular part of the virtual correction matrix element(s).
* For WZ production this is given by Equation B.2 in NPB 383 (1992)
* 3-44 *** modulo a factor 1/(2s) ***, which is a flux factor that
* those authors absorb in the matrix element.
*/
double M_V_regular(realVVKinematics S) const;
/**
* Member variable to store the
* regular part of the virtual correction matrix element(s).
* For WZ production this is given by Equation B.2 in NPB 383 (1992)
* 3-44 *** modulo a factor 1/(2s) ***, which is a flux factor that
* those authors absorb in the matrix element.
*/
mutable double M_V_regular_;
/**
* The matrix element q + qb -> n + g times tk*uk
*/
Energy2 t_u_M_R_qqb(realVVKinematics R) const;
/**
* Member variable to store the matrix element q + qb -> n + g times tk*uk
*/
mutable Energy2 t_u_M_R_qqb_;
/**
* The matrix element q + g -> n + q times tk*uk
*/
Energy2 t_u_M_R_qg(realVVKinematics R) const;
/**
* Member variable to store the matrix element q + g -> n + q times tk*uk
*/
mutable Energy2 t_u_M_R_qg_;
/**
* The matrix element g + qb -> n + q times tk*uk
*/
Energy2 t_u_M_R_gqb(realVVKinematics R) const;
/**
* Member variable to store the matrix element g + qb -> n + q times tk*uk
*/
mutable Energy2 t_u_M_R_gqb_;
/**
* The matrix element q + qb -> n + g times (tk*uk)^2 - using helicity amplitudes
*/
Energy2 t_u_M_R_qqb_hel_amp(realVVKinematics R) const;
/**
* Member variable to store the
* matrix element q + qb -> n + g times (tk*uk)^2 - using helicity amplitudes
*/
mutable Energy2 t_u_M_R_qqb_hel_amp_;
/**
* The matrix element q + g -> n + q times (tk*uk)^2 - using helicity amplitudes
*/
Energy2 t_u_M_R_qg_hel_amp(realVVKinematics R) const;
/**
* Member variable to store the
* matrix element q + g -> n + q times (tk*uk)^2 - using helicity amplitudes
*/
mutable Energy2 t_u_M_R_qg_hel_amp_;
/**
* The matrix element g + qb -> n + qb times (tk*uk)^2 - using helicity amplitudes
*/
Energy2 t_u_M_R_gqb_hel_amp(realVVKinematics R) const;
/**
* Member variable to store the
* matrix element g + qb -> n + qb times (tk*uk)^2 - using helicity amplitudes
*/
mutable Energy2 t_u_M_R_gqb_hel_amp_;
/**
* The leading order matrix element - using helicity amplitudes
*/
double lo_me() const;
/**
* The Born matrix element as given in Equation 3.1 - 3.3 in NPB 383
* (1992) *** modulo a factor 1/(2s) ***, which is a flux factor that
* those authors absorb in the matrix element.
*/
double M_Born_WZ(bornVVKinematics B) const;
/**
* Member variable to store the
* Born matrix element as given in Equation 3.1 - 3.3 in NPB 383
* (1992) *** modulo a factor 1/(2s) ***, which is a flux factor that
* those authors absorb in the matrix element.
*/
mutable double M_Born_;
/**
* The Born matrix element as given in Equation 2.18 - 2.19 in NPB 357
* (1991) *** modulo a factor 1/(2s) ***, which is a flux factor that
* those authors absorb in the matrix element.
*/
double M_Born_ZZ(bornVVKinematics B) const;
/**
* M_V_regular_ZZ is the regular part of the one-loop ZZ matrix element
* exactly as defined in Eqs. B.1 & B.2 of NPB 357(1991)409-438 ***
* modulo a factor 1/(2s) ***, which is a flux factor that
* those authors absorb in the matrix element.
*/
double M_V_regular_ZZ(realVVKinematics S) const;
/**
* t_u_M_R_qqb_ZZ is the q + qb -> n + g times tk*uk real emission
* matrix element as defined in Eq. C.1 of NPB 357(1991)409-438 ***
* modulo a factor 1/(2s) ***, which is a flux factor that
* those authors absorb in the matrix element.
*/
Energy2 t_u_M_R_qqb_ZZ(realVVKinematics R) const;
/**
* The Born matrix element as given in Equation 3.2 - 3.8 in NPB 410
* (1993) *** modulo a factor 1/(2s) ***, which is a flux factor that
* those authors absorb in the matrix element.
*/
double M_Born_WW(bornVVKinematics B) const;
/**
* M_V_regular_WW is the regular part of the one-loop WW matrix element
* exactly as defined in Eqs. C.1 - C.7 of of NPB 410(1993)280-324 ***
* modulo a factor 1/(2s) ***, which is a flux factor that
* those authors absorb in the matrix element.
*/
double M_V_regular_WW(realVVKinematics S) const;
/**
* t_u_M_R_qqb_WW is the q + qb -> n + g times tk*uk real emission
* matrix element as defined in Eq. D.1-D.5 of NPB 410(1993)280-324 ***
* modulo a factor 1/(2s) ***, which is a flux factor that
* those authors absorb in the matrix element.
*/
Energy2 t_u_M_R_qqb_WW(realVVKinematics R) const;
/**
* Return the factorion scale squared.
*/
Energy2 mu_F2() const;
/**
* Return the renormalisation scale squared.
*/
Energy2 mu_UV2() const;
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
inline virtual IBPtr clone() const { return new_ptr(*this); }
/** Make a clone of this object, possibly modifying the cloned object
* to make it sane.
* @return a pointer to the new object.
*/
inline virtual IBPtr fullclone() const { return new_ptr(*this); }
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MEPP2VVPowheg> initMEPP2VVPowheg;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MEPP2VVPowheg & operator=(const MEPP2VVPowheg &);
private:
/**
* Parameters for the NLO weight
*/
//@{
/**
* Parameter to determine when to use limiting value of real emission
* matrix elements, to avoid rounding error issues.
*/
double tiny;
/**
* The BeamParticleData object for the plus and minus direction hadrons
*/
tcBeamPtr hadron_A_;
tcBeamPtr hadron_B_;
/**
* Born / virtual 2->2 kinematics.
*/
bornVVKinematics B_;
/**
* Soft limit of the 2->3 real emission kinematics.
*/
realVVKinematics S_;
/**
* Soft-collinear limit of the 2->3 kinematics (emission in +z direction).
*/
realVVKinematics SCp_;
/**
* The collinear limit of the 2->3 kinematics (emission in -z direction).
*/
realVVKinematics SCm_;
/**
* The collinear limit of the 2->3 kinematics (emission in +z direction).
*/
realVVKinematics Cp_;
/**
* The collinear limit of the 2->3 kinematics (emission in -z direction).
*/
realVVKinematics Cm_;
/**
* The resolved 2->3 real emission kinematics:
*/
realVVKinematics H_;
/**
* The ParticleData object for the plus and minus lo partons
*/
tcPDPtr ab_, bb_;
/**
* The ParticleData object for the quark and antiquark
* (which can be in a different order to ab_ and bb_).
*/
tcPDPtr quark_, antiquark_;
/**
* Values of the PDF's before radiation
*/
double lo_lumi_;
/**
* The value of the leading order qqbar->VV matrix element
*/
mutable double lo_me2_;
/**
* The CF_ colour factor
*/
double CF_;
/**
* The TR_ colour factor
*/
double TR_;
/**
* The number of colours
*/
double NC_;
/**
* The weak coupling and the sin (squared) of the Weinberg angle
*/
mutable double gW_, sin2ThetaW_;
/**
* The up and down, left handed, quark-boson couplings
*/
mutable double guL_, gdL_;
/**
* The up and down, right handed, quark-boson couplings (for WW & ZZ)
*/
mutable double guR_, gdR_;
/**
* The TGC coupling
*/
mutable double eZ_;
/**
* The TGC coupling squared. This is useful for debugging purposes
* when one wants to turn of t-channel * TGC interference contributions
* but leave the pure TGC contributions intact. It is also needed in
* order to transform WZ matrix elements into WW ones.
*/
mutable double eZ2_;
/**
* The CKM factor (Fij^2)
*/
mutable double Fij2_;
/**
* Whether to generate the positive, negative or leading order contribution
*/
unsigned int contrib_;
/**
* Whether to generate all channels contributions or just qqb or just
* qg+gqb contributions
*/
unsigned int channels_;
/**
* Whether to use a fixed or a running QCD coupling for the NLO weight
*/
unsigned int nlo_alphaS_opt_;
/**
* The value of alphaS to use for the nlo weight if nlo_alphaS_opt_=1
*/
double fixed_alphaS_;
/**
* Flag to remove or multiply in MCFM branching fractions for testing
*/
unsigned int removebr_;
/**
* Selects a dynamic (sHat) or fixed factorization scale
*/
unsigned int scaleopt_;
/**
* The factorization scale
*/
Energy mu_F_;
/**
* The renormalization scale
*/
Energy mu_UV_;
/**
* The pT of V1 in a radiative event in the lab frame (for scale setting only)
*/
Energy2 k1r_perp2_lab_;
/**
* The pT of V2 in a radiative event in the lab frame (for scale setting only)
*/
Energy2 k2r_perp2_lab_;
/**
* The ckm matrix elements (unsquared, to allow interference)
*/
vector< vector<Complex> > ckm_;
/**
* Option to impose helicity conservation on the real NLO ME's (greatly improves evaluation time).
*/
bool helicityConservation_;
/**
* The q + qb -> v1 + v2 + g helicity amplitudes
*/
mutable ProductionMatrixElement qqb_hel_amps_;
/**
* The q + g -> v1 + v2 + q helicity amplitudes
*/
mutable ProductionMatrixElement qg_hel_amps_;
/**
* The g + qb -> v1 + v2 + qb helicity amplitudes
*/
mutable ProductionMatrixElement gqb_hel_amps_;
//@}
/**
* The vertices
*/
//@{
/**
* The photon fermion-antifermion vertex
*/
AbstractFFVVertexPtr FFPvertex_;
/**
* The W fermion-antifermion vertex
*/
AbstractFFVVertexPtr FFWvertex_;
/**
* The Z fermion-antifermionvertex
*/
AbstractFFVVertexPtr FFZvertex_;
/**
* The triple electroweak gauge boson vertex
*/
AbstractVVVVertexPtr WWWvertex_;
/**
* The quark-antiquark gluon vertex
*/
AbstractFFVVertexPtr FFGvertex_;
//@}
/**
* The value of \f$\alpha_S\f$ used for the calculation
*/
mutable double alphaS_;
protected:
/**
* Returns the matrix element for a given type of process,
* rapidity of the jet \f$y_j\f$ and transverse momentum \f$p_T\f$
* @param emis_type the type of emission,
* (0 is \f$q\bar{q}\to Vg\f$, 1 is \f$qg\to Vq\f$ and 2 is \f$g\bar{q}\to V\bar{q}\f$)
* @param pT The transverse momentum of the jet
* @param R The object containing the kinematics
*/
double getResult(int emis_type, realVVKinematics R, Energy pT);
/**
* generates the hardest emission (yj,p)
* @param pnew The momenta of the new particles
* @param emissiontype The type of emission, as for getResult
* @return Whether not an emission was generated
*/
bool getEvent(vector<Lorentz5Momentum> & pnew,unsigned int & emissiontype);
/**
* sets the QCD, EW and PDF scales
* @param pT The pT of the current step in the veto algorithm
*/
void setTheScales(Energy pT);
/**
* The matrix element q + qb -> n + g times tk*uk
*/
Energy2 t_u_M_R_qqb_hel_amp(realVVKinematics R, bool getMatrix) const;
/**
* The matrix element q + g -> n + q times tk*uk
*/
Energy2 t_u_M_R_qg_hel_amp(realVVKinematics R, bool getMatrix) const;
/**
* The matrix element g + qb -> n + q times tk*uk
*/
Energy2 t_u_M_R_gqb_hel_amp(realVVKinematics R, bool getMatrix) const;
/**
* The matrix element for the kinematical configuration
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
* @return the matrix element scaled with sHat() to give a
* dimensionless number.
*/
double lo_me(bool getMatrix) const;
/**
* Recalculate hard vertex to include spin correlations for radiative events.
*/
void recalculateVertex();
/**
* Member which selects a two body decay mode for each vector
* boson and distributes decay products isotropically
*/
bool isotropicDecayer();
/**
* The triangle function lambda(x,y,z)=sqrt(x^2+y^2+z^2-2*x*y-2*y*z-2*x*z)
*/
Energy2 triangleFn(Energy2,Energy2,Energy2);
private:
/**
* If this boolean is true the n+1 body helicity amplitudes will be
* used to calculate a hard vertex based on those kinematics for spin
* correlations in the decays.
*/
bool realMESpinCorrelations_;
/**
* The colour & spin averaged n-body (leading order) matrix element squared.
*/
double lo_me_;
/**
* The resolved 2->3 real emission kinematics.
*/
realVVKinematics R_;
/**
* This specifies the emitting configuration:
* 1: q + qbar -> V1 + V2 + g
* 2: q + g -> V1 + V2 + q
* 3: g + qbar -> V1 + V2 + qbar.
*/
unsigned int channel_;
/**
* Identifies the space-like mother of the branching
* as quark (+1) or antiquark (-1):
*/
int fermionNumberOfMother_;
/**
* Pointer to the object calculating the strong coupling
*/
ShowerAlphaPtr showerAlphaS_;
/**
* Constants for the sampling. The distribution is assumed to have the
* form \f$\frac{c}{{\rm GeV}}\times\left(\frac{{\rm GeV}}{p_T}\right)^n\f$
*/
//@{
/**
* The power, \f$n\f$, for the sampling
*/
double power_;
/**
* The prefactor, \f$c\f$ for the \f$q\bar{q}\f$ channel
*/
double preqqbar_;
/**
* The prefactor, \f$c\f$ for the \f$qg\f$ channel
*/
double preqg_;
/**
* The prefactor, \f$c\f$ for the \f$g\bar{q}\f$ channel
*/
double pregqbar_;
/**
* The QCD beta function divided by 4pi, (11-2/3*nf)/4/pi, with nf = 5.
*/
double b0_;
/**
* The fundamental QCD scale in the one-loop alpha_{S} used for the crude
* (not the very crude) overestimate of the Sudakov exponent. The default
* value is set so such that alphaS(MZ), neglecting all flavour threshold
* effects i.e. MZ*exp(-1/2/b0_/alphaS(MZ)).
*/
Energy LambdaQCD_;
/**
* The prefactors as a vector for easy use
*/
vector<double> prefactor_;
//@}
/**
* Properties of the incoming particles
*/
//@{
/**
* Pointers to the ShowerProgenitor objects for the partons
*/
PPtr qProgenitor_;
PPtr qbProgenitor_;
/**
* Pointers to the Shower particle objects for the partons
*/
PPtr showerQuark_;
PPtr showerAntiquark_;
/**
* Pointers to the BeamParticleData objects
*/
tcBeamPtr qHadron_;
tcBeamPtr qbHadron_;
//@}
/**
* Properties of the boson and jets
*/
//@{
/**
* Pointers to the Shower particle objects for the partons
*/
PPtr gluon_;
PPtr V1_;
PPtr V2_;
vector<PPtr> children_;
/**
* Flag indicating if the q & qbar are flipped or not i.e. this
* is true if q enters from the -z direction in the lab frame.
*/
bool flipped_;
/**
* the rapidity of the jet
*/
double Yk_;
/**
* The transverse momentum of the jet
*/
Energy pT_;
//@}
/**
* The transverse momentum of the jet
*/
Energy min_pT_;
// Work out the scales we want to use in the matrix elements and the pdfs:
/**
* Scale for alpha_S: pT^2 of the diboson system.
*/
Energy2 QCDScale_;
/**
* Scale for real emission PDF:
*/
Energy2 PDFScale_;
/**
* Scale of electroweak vertices: mVV^2 the invariant mass of the diboson system.
*/
Energy2 EWScale_;
/**
* A matrix to hold the home-grown production matrix element
*/
mutable Complex productionMatrix_[3][3][3][3];
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MEPP2VVPowheg. */
template <>
struct BaseClassTrait<Herwig::MEPP2VVPowheg,1> {
/** Typedef of the first base class of MEPP2VVPowheg. */
typedef Herwig::MEPP2VV NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MEPP2VVPowheg class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MEPP2VVPowheg>
: public ClassTraitsBase<Herwig::MEPP2VVPowheg> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MEPP2VVPowheg"; }
/**
* The name of a file containing the dynamic library where the class
* MEPP2VVPowheg is implemented. It may also include several, space-separated,
* libraries if the class MEPP2VVPowheg depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwMEHadron.so HwPowhegMEHadron.so"; }
};
/** @endcond */
}
#endif /* HERWIG_MEPP2VVPowheg_H */
diff --git a/MatrixElement/Powheg/MEPP2WHPowheg.cc b/MatrixElement/Powheg/MEPP2WHPowheg.cc
--- a/MatrixElement/Powheg/MEPP2WHPowheg.cc
+++ b/MatrixElement/Powheg/MEPP2WHPowheg.cc
@@ -1,389 +1,389 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the MEPP2WHPowheg class.
//
#include "MEPP2WHPowheg.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "ThePEG/Repository/EventGenerator.h"
using namespace Herwig;
MEPP2WHPowheg::MEPP2WHPowheg()
: _gluon(), TR_(0.5), CF_(4./3.),
_contrib(1) ,_nlo_alphaS_opt(0), _fixed_alphaS(0.115895),
_a(0.5) ,_p(0.7) , _eps(1.0e-8), _scaleopt(1),
_fixedScale(100.*GeV), _scaleFact(1.)
{}
ClassDescription<MEPP2WHPowheg> MEPP2WHPowheg::initMEPP2WHPowheg;
// Definition of the static class description member.
void MEPP2WHPowheg::persistentOutput(PersistentOStream & os) const {
os << _contrib << _nlo_alphaS_opt << _fixed_alphaS
<< _a << _p << _gluon
<< _scaleopt
<< ounit(_fixedScale,GeV) << _scaleFact;
}
void MEPP2WHPowheg::persistentInput(PersistentIStream & is, int) {
is >> _contrib >> _nlo_alphaS_opt >> _fixed_alphaS
>> _a >> _p >> _gluon
>> _scaleopt
>> iunit(_fixedScale,GeV) >> _scaleFact;
}
void MEPP2WHPowheg::Init() {
static ClassDocumentation<MEPP2WHPowheg> documentation
("The MEPP2WHPowheg class implements the matrix element for the Bjorken"
" process q qbar -> WH",
"The PP$\\to$W Higgs POWHEG matrix element is described in \\cite{Hamilton:2009za}.",
"%\\cite{Hamilton:2009za}\n"
"\\bibitem{Hamilton:2009za}\n"
" K.~Hamilton, P.~Richardson and J.~Tully,\n"
" ``A Positive-Weight Next-to-Leading Order Monte Carlo Simulation for Higgs\n"
" Boson Production,''\n"
" JHEP {\\bf 0904} (2009) 116\n"
" [arXiv:0903.4345 [hep-ph]].\n"
" %%CITATION = JHEPA,0904,116;%%\n"
);
static Switch<MEPP2WHPowheg,unsigned int> interfaceContribution
("Contribution",
"Which contributions to the cross section to include",
&MEPP2WHPowheg::_contrib, 1, false, false);
static SwitchOption interfaceContributionLeadingOrder
(interfaceContribution,
"LeadingOrder",
"Just generate the leading order cross section",
0);
static SwitchOption interfaceContributionPositiveNLO
(interfaceContribution,
"PositiveNLO",
"Generate the positive contribution to the full NLO cross section",
1);
static SwitchOption interfaceContributionNegativeNLO
(interfaceContribution,
"NegativeNLO",
"Generate the negative contribution to the full NLO cross section",
2);
static Switch<MEPP2WHPowheg,unsigned int> interfaceNLOalphaSopt
("NLOalphaSopt",
"Whether to use a fixed or a running QCD coupling for the NLO weight",
&MEPP2WHPowheg::_nlo_alphaS_opt, 0, false, false);
static SwitchOption interfaceNLOalphaSoptRunningAlphaS
(interfaceNLOalphaSopt,
"RunningAlphaS",
"Use the usual running QCD coupling evaluated at scale scale()",
0);
static SwitchOption interfaceNLOalphaSoptFixedAlphaS
(interfaceNLOalphaSopt,
"FixedAlphaS",
"Use a constant QCD coupling for comparison/debugging purposes",
1);
static Parameter<MEPP2WHPowheg,double> interfaceFixedNLOalphaS
("FixedNLOalphaS",
"The value of alphaS to use for the nlo weight if _nlo_alphaS_opt=1",
&MEPP2WHPowheg::_fixed_alphaS, 0.115895, 0., 1.0,
false, false, Interface::limited);
static Parameter<MEPP2WHPowheg,double> interfaceCorrectionCoefficient
("CorrectionCoefficient",
"The magnitude of the correction term to reduce the negative contribution",
&MEPP2WHPowheg::_a, 0.5, -10., 10.0,
false, false, Interface::limited);
static Parameter<MEPP2WHPowheg,double> interfaceCorrectionPower
("CorrectionPower",
"The power of the correction term to reduce the negative contribution",
&MEPP2WHPowheg::_p, 0.7, 0.0, 1.0,
false, false, Interface::limited);
static Switch<MEPP2WHPowheg,unsigned int> interfaceFactorizationScaleOption
("FactorizationScaleOption",
"Option for the scale to be used",
&MEPP2WHPowheg::_scaleopt, 1, false, false);
static SwitchOption interfaceScaleOptionFixed
(interfaceFactorizationScaleOption,
"Fixed",
"Use a fixed scale",
0);
static SwitchOption interfaceScaleOptionsHat
(interfaceFactorizationScaleOption,
"Dynamic",
"Use the mass of the vector boson-Higgs boson system",
1);
static Parameter<MEPP2WHPowheg,Energy> interfaceFactorizationScaleValue
("FactorizationScaleValue",
"The fixed scale to use if required",
&MEPP2WHPowheg::_fixedScale, GeV, 100.0*GeV, 10.0*GeV, 1000.0*GeV,
false, false, Interface::limited);
static Parameter<MEPP2WHPowheg,double> interfaceScaleFactor
("ScaleFactor",
"The factor used before sHat if using a running scale",
&MEPP2WHPowheg::_scaleFact, 1.0, 0.0, 10.0,
false, false, Interface::limited);
}
void MEPP2WHPowheg::doinit() {
// gluon ParticleData object
_gluon = getParticleData(ParticleID::g);
MEPP2WH::doinit();
}
Energy2 MEPP2WHPowheg::scale() const {
return _scaleopt == 0 ? sqr(_fixedScale) : _scaleFact*sHat();
}
int MEPP2WHPowheg::nDim() const {
return 7;
}
bool MEPP2WHPowheg::generateKinematics(const double * r) {
_xt=*(r+5);
_v =*(r+6);
return MEPP2WH::generateKinematics(r);
}
CrossSection MEPP2WHPowheg::dSigHatDR() const {
// Get Born momentum fractions xbar_a and xbar_b:
_xb_a = lastX1();
_xb_b = lastX2();
return MEPP2WH::dSigHatDR()*NLOweight();
}
double MEPP2WHPowheg::NLOweight() const {
// If only leading order is required return 1:
if(_contrib==0) return 1.;
useMe();
// Get particle data for QCD particles:
_parton_a=mePartonData()[0];
_parton_b=mePartonData()[1];
// get BeamParticleData objects for PDF's
_hadron_A=dynamic_ptr_cast<Ptr<BeamParticleData>::transient_const_pointer>
(lastParticles().first->dataPtr());
_hadron_B=dynamic_ptr_cast<Ptr<BeamParticleData>::transient_const_pointer>
(lastParticles().second->dataPtr());
// If necessary swap the particle data vectors so that _xb_a,
// mePartonData[0], beam[0] relate to the inbound quark:
if(!(lastPartons().first ->dataPtr()==_parton_a&&
lastPartons().second->dataPtr()==_parton_b)) {
swap(_xb_a ,_xb_b);
swap(_hadron_A,_hadron_B);
}
// calculate the PDF's for the Born process
_oldq = _hadron_A->pdf()->xfx(_hadron_A,_parton_a,scale(),_xb_a)/_xb_a;
_oldqbar = _hadron_B->pdf()->xfx(_hadron_B,_parton_b,scale(),_xb_b)/_xb_b;
// Calculate alpha_S
_alphaS2Pi = _nlo_alphaS_opt==1 ? _fixed_alphaS : SM().alphaS(scale());
_alphaS2Pi /= 2.*Constants::pi;
// Calculate the invariant mass of the dilepton pair
_mll2 = sHat();
_mu2 = scale();
// Calculate the integrand
// q qbar contribution
double wqqvirt = Vtilde_qq();
double wqqcollin = Ctilde_qq(x(_xt,1.),1.) + Ctilde_qq(x(_xt,0.),0.);
double wqqreal = Ftilde_qq(_xt,_v);
double wqq = wqqvirt+wqqcollin+wqqreal;
// q g contribution
double wqgcollin = Ctilde_qg(x(_xt,0.),0.);
double wqgreal = Ftilde_qg(_xt,_v);
double wqg = wqgreal+wqgcollin;
// g qbar contribution
double wgqbarcollin = Ctilde_gq(x(_xt,1.),1.);
double wgqbarreal = Ftilde_gq(_xt,_v);
double wgqbar = wgqbarreal+wgqbarcollin;
// total
double wgt = 1.+(wqq+wqg+wgqbar);
// KMH - 06/08 - This seems to give wrong NLO results for
// associated Higgs so I'm omitting it.
// //trick to try and reduce neg wgt contribution
// if(_xt<1.-_eps)
// wgt += _a*(1./pow(1.-_xt,_p)-(1.-pow(_eps,1.-_p))/(1.-_p)/(1.-_eps));
// return the answer
- assert(!isinf(wgt)&&!isnan(wgt));
+ assert(isfinite(wgt));
return _contrib==1 ? max(0.,wgt) : max(0.,-wgt);
}
double MEPP2WHPowheg::x(double xt, double v) const {
double x0(xbar(v));
return x0+(1.-x0)*xt;
}
double MEPP2WHPowheg::x_a(double x, double v) const {
if(x==1.) return _xb_a;
if(v==0.) return _xb_a;
if(v==1.) return _xb_a/x;
return (_xb_a/sqrt(x))*sqrt((1.-(1.-x)*(1.-v))/(1.-(1.-x)*v));
}
double MEPP2WHPowheg::x_b(double x, double v) const {
if(x==1.) return _xb_b;
if(v==0.) return _xb_b/x;
if(v==1.) return _xb_b;
return (_xb_b/sqrt(x))*sqrt((1.-(1.-x)*v)/(1.-(1.-x)*(1.-v)));
}
double MEPP2WHPowheg::xbar(double v) const {
double xba2(sqr(_xb_a)), xbb2(sqr(_xb_b)), omv(-999.);
double xbar1(-999.), xbar2(-999.);
if(v==1.) return _xb_a;
if(v==0.) return _xb_b;
omv = 1.-v;
xbar1=4.* v*xba2/
(sqrt(sqr(1.+xba2)*4.*sqr(omv)+16.*(1.-2.*omv)*xba2)+2.*omv*(1.-_xb_a)*(1.+_xb_a));
xbar2=4.*omv*xbb2/
(sqrt(sqr(1.+xbb2)*4.*sqr( v)+16.*(1.-2.* v)*xbb2)+2.* v*(1.-_xb_b)*(1.+_xb_b));
return max(xbar1,xbar2);
}
double MEPP2WHPowheg::Ltilde_qq(double x, double v) const {
if(x==1.) return 1.;
double xa(x_a(x,v)),xb(x_b(x,v));
double newq = (_hadron_A->pdf()->xfx(_hadron_A,_parton_a,scale(), xa)/ xa);
double newqbar = (_hadron_B->pdf()->xfx(_hadron_B,_parton_b,scale(), xb)/ xb);
return( newq * newqbar / _oldq / _oldqbar );
}
double MEPP2WHPowheg::Ltilde_qg(double x, double v) const {
double xa(x_a(x,v)),xb(x_b(x,v));
double newq = (_hadron_A->pdf()->xfx(_hadron_A,_parton_a,scale(), xa)/ xa);
double newg2 = (_hadron_B->pdf()->xfx(_hadron_B,_gluon ,scale(), xb)/ xb);
return( newq * newg2 / _oldq / _oldqbar );
}
double MEPP2WHPowheg::Ltilde_gq(double x, double v) const {
double xa(x_a(x,v)),xb(x_b(x,v));
double newg1 = (_hadron_A->pdf()->xfx(_hadron_A,_gluon ,scale(), xa)/ xa);
double newqbar = (_hadron_B->pdf()->xfx(_hadron_B,_parton_b,scale(), xb)/ xb);
return( newg1 * newqbar / _oldq / _oldqbar );
}
double MEPP2WHPowheg::Vtilde_qq() const {
return _alphaS2Pi*CF_*(-3.*log(_mu2/_mll2)+(2.*sqr(Constants::pi)/3.)-8.);
}
double MEPP2WHPowheg::Ccalbar_qg(double x) const {
return (sqr(x)+sqr(1.-x))*(log(_mll2/(_mu2*x))+2.*log(1.-x))+2.*x*(1.-x);
}
double MEPP2WHPowheg::Ctilde_qg(double x, double v) const {
return _alphaS2Pi*TR_ * ((1.-xbar(v))/x) * Ccalbar_qg(x)*Ltilde_qg(x,v);
}
double MEPP2WHPowheg::Ctilde_gq(double x, double v) const {
return _alphaS2Pi*TR_ * ((1.-xbar(v))/x) * Ccalbar_qg(x)*Ltilde_gq(x,v);
}
double MEPP2WHPowheg::Ctilde_qq(double x, double v) const {
double wgt
= ((1.-x)/x+(1.+x*x)/(1.-x)/x*(2.*log(1.-x)-log(x)))*Ltilde_qq(x,v)
- 4.*log(1.-x)/(1.-x)
+ 2./(1.-xbar(v))*log(1.-xbar(v))*log(1.-xbar(v))
+ (2./(1.-xbar(v))*log(1.-xbar(v))-2./(1.-x)+(1.+x*x)/x/(1.-x)*Ltilde_qq(x,v))
*log(_mll2/_mu2);
return _alphaS2Pi*CF_*(1.-xbar(v))*wgt;
}
double MEPP2WHPowheg::Fcal_qq(double x, double v) const {
return (sqr(1.-x)*(1.-2.*v*(1.-v))+2.*x)/x*Ltilde_qq(x,v);
}
double MEPP2WHPowheg::Fcal_qg(double x, double v) const {
return ((1.-xbar(v))/x)*
(2.*x*(1.-x)*v+sqr((1.-x)*v)+sqr(x)+sqr(1.-x))*Ltilde_qg(x,v);
}
double MEPP2WHPowheg::Fcal_gq(double x, double v) const {
return ((1.-xbar(v))/x)*
(2.*x*(1.-x)*(1.-v)+sqr((1.-x)*(1.-v))+sqr(x)+sqr(1.-x))*Ltilde_gq(x,v);
}
double MEPP2WHPowheg::Ftilde_qg(double xt, double v) const {
return _alphaS2Pi*TR_*
( Fcal_qg(x(xt,v),v) - Fcal_qg(x(xt,0.),0.) )/v;
}
double MEPP2WHPowheg::Ftilde_gq(double xt, double v) const {
return _alphaS2Pi*TR_*
( Fcal_gq(x(xt,v),v) - Fcal_gq(x(xt,1.),1.) )/(1.-v);
}
double MEPP2WHPowheg::Ftilde_qq(double xt, double v) const {
double eps(1e-10);
// is emission into regular or singular region?
if(xt>=0. && xt<1.-eps && v>eps && v<1.-eps) {
// x<1, v>0, v<1 (regular emission, neither soft or collinear):
return _alphaS2Pi*CF_*
(( ( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,1.),1.) ) / (1.-v)+
( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,0.),0.) ) / v )/(1.-xt)
+ ( log(1.-xbar(v)) - log(1.-_xb_a))*2./(1.-v)
+ ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v);
}
else {
// make sure emission is actually in the allowed phase space:
if(!(v>=0. && v<=1. && xt>=0. && xt<=1.)) {
ostringstream s;
s << "MEPP2WHPowheg::Ftilde_qq : \n" << "xt(" << xt << ") and / or v("
<< v << ") not in the phase space.";
generator()->logWarning(Exception(s.str(),Exception::warning));
return 0.;
}
// is emission soft singular?
if(xt>=1.-eps) {
// x=1:
if(v<=eps) {
// x==1, v=0 (soft and collinear with particle b):
return _alphaS2Pi*CF_*
( ( log(1.-xbar(v)) - log(1.-_xb_a))*2./(1.-v)
);
} else if(v>=1.-eps) {
// x==1, v=1 (soft and collinear with particle a):
return _alphaS2Pi*CF_*
( ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v
);
} else {
// x==1, 0<v<1 (soft wide angle emission):
return _alphaS2Pi*CF_*
( ( log(1.-xbar(v)) - log(1.-_xb_a))*2./(1.-v)
+ ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v
);
}
} else {
// x<1:
if(v<=eps) {
// x<1 but v=0 (collinear with particle b, but not soft):
return _alphaS2Pi*CF_*
( ( ( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,1.),1.) ) / (1.-v)
)/(1.-xt)
+ ( log(1.-xbar(v)) - log(1.-_xb_a))*2./(1.-v)
);
} else if(v>=1.-eps) {
// x<1 but v=1 (collinear with particle a, but not soft):
return _alphaS2Pi*CF_*
( ( ( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,0.),0.) ) / v
)/(1.-xt)
+ ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v
);
}
}
}
return 0.;
}
diff --git a/MatrixElement/Powheg/MEPP2ZHPowheg.cc b/MatrixElement/Powheg/MEPP2ZHPowheg.cc
--- a/MatrixElement/Powheg/MEPP2ZHPowheg.cc
+++ b/MatrixElement/Powheg/MEPP2ZHPowheg.cc
@@ -1,388 +1,388 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the MEPP2ZHPowheg class.
//
#include "MEPP2ZHPowheg.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "ThePEG/PDT/DecayMode.h"
using namespace Herwig;
MEPP2ZHPowheg::MEPP2ZHPowheg()
: _gluon(), TR_(0.5), CF_(4./3.),
_contrib(1) ,_nlo_alphaS_opt(0), _fixed_alphaS(0.115895),
_a(0.5) ,_p(0.7) , _eps(1.0e-8), _scaleopt(1),
_fixedScale(100.*GeV), _scaleFact(1.)
{}
void MEPP2ZHPowheg::persistentOutput(PersistentOStream & os) const {
os << _contrib << _nlo_alphaS_opt << _fixed_alphaS
<< _a << _p << _gluon
<< _scaleopt
<< ounit(_fixedScale,GeV) << _scaleFact;
}
void MEPP2ZHPowheg::persistentInput(PersistentIStream & is, int) {
is >> _contrib >> _nlo_alphaS_opt >> _fixed_alphaS
>> _a >> _p >> _gluon
>> _scaleopt
>> iunit(_fixedScale,GeV) >> _scaleFact;
}
ClassDescription<MEPP2ZHPowheg> MEPP2ZHPowheg::initMEPP2ZHPowheg;
// Definition of the static class description member.
void MEPP2ZHPowheg::Init() {
static ClassDocumentation<MEPP2ZHPowheg> documentation
("The MEPP2ZHPowheg class implements the matrix element for q qbar -> Z H",
"The PP$\\to$Z Higgs POWHEG matrix element is described in \\cite{Hamilton:2009za}.",
"\\bibitem{Hamilton:2009za}\n"
" K.~Hamilton, P.~Richardson and J.~Tully,\n"
" %``A Positive-Weight Next-to-Leading Order Monte Carlo Simulation for Higgs\n"
" %Boson Production,''\n"
" JHEP {\\bf 0904} (2009) 116\n"
" [arXiv:0903.4345 [hep-ph]].\n"
" %%CITATION = JHEPA,0904,116;%%\n"
);
static Switch<MEPP2ZHPowheg,unsigned int> interfaceContribution
("Contribution",
"Which contributions to the cross section to include",
&MEPP2ZHPowheg::_contrib, 1, false, false);
static SwitchOption interfaceContributionLeadingOrder
(interfaceContribution,
"LeadingOrder",
"Just generate the leading order cross section",
0);
static SwitchOption interfaceContributionPositiveNLO
(interfaceContribution,
"PositiveNLO",
"Generate the positive contribution to the full NLO cross section",
1);
static SwitchOption interfaceContributionNegativeNLO
(interfaceContribution,
"NegativeNLO",
"Generate the negative contribution to the full NLO cross section",
2);
static Switch<MEPP2ZHPowheg,unsigned int> interfaceNLOalphaSopt
("NLOalphaSopt",
"Whether to use a fixed or a running QCD coupling for the NLO weight",
&MEPP2ZHPowheg::_nlo_alphaS_opt, 0, false, false);
static SwitchOption interfaceNLOalphaSoptRunningAlphaS
(interfaceNLOalphaSopt,
"RunningAlphaS",
"Use the usual running QCD coupling evaluated at scale scale()",
0);
static SwitchOption interfaceNLOalphaSoptFixedAlphaS
(interfaceNLOalphaSopt,
"FixedAlphaS",
"Use a constant QCD coupling for comparison/debugging purposes",
1);
static Parameter<MEPP2ZHPowheg,double> interfaceFixedNLOalphaS
("FixedNLOalphaS",
"The value of alphaS to use for the nlo weight if _nlo_alphaS_opt=1",
&MEPP2ZHPowheg::_fixed_alphaS, 0.115895, 0., 1.0,
false, false, Interface::limited);
static Parameter<MEPP2ZHPowheg,double> interfaceCorrectionCoefficient
("CorrectionCoefficient",
"The magnitude of the correction term to reduce the negative contribution",
&MEPP2ZHPowheg::_a, 0.5, -10., 10.0,
false, false, Interface::limited);
static Parameter<MEPP2ZHPowheg,double> interfaceCorrectionPower
("CorrectionPower",
"The power of the correction term to reduce the negative contribution",
&MEPP2ZHPowheg::_p, 0.7, 0.0, 1.0,
false, false, Interface::limited);
static Switch<MEPP2ZHPowheg,unsigned int> interfaceFactorizationScaleOption
("FactorizationScaleOption",
"Option for the scale to be used",
&MEPP2ZHPowheg::_scaleopt, 1, false, false);
static SwitchOption interfaceScaleOptionFixed
(interfaceFactorizationScaleOption,
"Fixed",
"Use a fixed scale",
0);
static SwitchOption interfaceScaleOptionsHat
(interfaceFactorizationScaleOption,
"Dynamic",
"Use the mass of the vector boson-Higgs boson system",
1);
static Parameter<MEPP2ZHPowheg,Energy> interfaceFactorizationScaleValue
("FactorizationScaleValue",
"The fixed scale to use if required",
&MEPP2ZHPowheg::_fixedScale, GeV, 100.0*GeV, 10.0*GeV, 1000.0*GeV,
false, false, Interface::limited);
static Parameter<MEPP2ZHPowheg,double> interfaceScaleFactor
("ScaleFactor",
"The factor used before sHat if using a running scale",
&MEPP2ZHPowheg::_scaleFact, 1.0, 0.0, 10.0,
false, false, Interface::limited);
}
void MEPP2ZHPowheg::doinit() {
// gluon ParticleData object
_gluon = getParticleData(ParticleID::g);
MEPP2ZH::doinit();
}
Energy2 MEPP2ZHPowheg::scale() const {
return _scaleopt == 0 ? sqr(_fixedScale) : _scaleFact*sHat();
}
int MEPP2ZHPowheg::nDim() const {
return 7;
}
bool MEPP2ZHPowheg::generateKinematics(const double * r) {
_xt=*(r+5);
_v =*(r+6);
return MEPP2ZH::generateKinematics(r);
}
CrossSection MEPP2ZHPowheg::dSigHatDR() const {
// Get Born momentum fractions xbar_a and xbar_b:
_xb_a = lastX1();
_xb_b = lastX2();
return MEPP2ZH::dSigHatDR()*NLOweight();
}
double MEPP2ZHPowheg::NLOweight() const {
// If only leading order is required return 1:
if(_contrib==0) return 1.;
useMe();
// Get particle data for QCD particles:
_parton_a=mePartonData()[0];
_parton_b=mePartonData()[1];
// get BeamParticleData objects for PDF's
_hadron_A=dynamic_ptr_cast<Ptr<BeamParticleData>::transient_const_pointer>
(lastParticles().first->dataPtr());
_hadron_B=dynamic_ptr_cast<Ptr<BeamParticleData>::transient_const_pointer>
(lastParticles().second->dataPtr());
// If necessary swap the particle data vectors so that _xb_a,
// mePartonData[0], beam[0] relate to the inbound quark:
if(!(lastPartons().first ->dataPtr()==_parton_a&&
lastPartons().second->dataPtr()==_parton_b)) {
swap(_xb_a ,_xb_b);
swap(_hadron_A,_hadron_B);
}
// calculate the PDF's for the Born process
_oldq = _hadron_A->pdf()->xfx(_hadron_A,_parton_a,scale(),_xb_a)/_xb_a;
_oldqbar = _hadron_B->pdf()->xfx(_hadron_B,_parton_b,scale(),_xb_b)/_xb_b;
// Calculate alpha_S
_alphaS2Pi = _nlo_alphaS_opt==1 ? _fixed_alphaS : SM().alphaS(scale());
_alphaS2Pi /= 2.*Constants::pi;
// Calculate the invariant mass of the dilepton pair
_mll2 = sHat();
_mu2 = scale();
// Calculate the integrand
// q qbar contribution
double wqqvirt = Vtilde_qq();
double wqqcollin = Ctilde_qq(x(_xt,1.),1.) + Ctilde_qq(x(_xt,0.),0.);
double wqqreal = Ftilde_qq(_xt,_v);
double wqq = wqqvirt+wqqcollin+wqqreal;
// q g contribution
double wqgcollin = Ctilde_qg(x(_xt,0.),0.);
double wqgreal = Ftilde_qg(_xt,_v);
double wqg = wqgreal+wqgcollin;
// g qbar contribution
double wgqbarcollin = Ctilde_gq(x(_xt,1.),1.);
double wgqbarreal = Ftilde_gq(_xt,_v);
double wgqbar = wgqbarreal+wgqbarcollin;
// total
double wgt = 1.+(wqq+wqg+wgqbar);
// KMH - 06/08 - This seems to give wrong NLO results for
// associated Higgs so I'm omitting it.
// //trick to try and reduce neg wgt contribution
// if(_xt<1.-_eps)
// wgt += _a*(1./pow(1.-_xt,_p)-(1.-pow(_eps,1.-_p))/(1.-_p)/(1.-_eps));
// return the answer
- assert(!isinf(wgt)&&!isnan(wgt));
+ assert(isfinite(wgt));
return _contrib==1 ? max(0.,wgt) : max(0.,-wgt);
}
double MEPP2ZHPowheg::x(double xt, double v) const {
double x0(xbar(v));
return x0+(1.-x0)*xt;
}
double MEPP2ZHPowheg::x_a(double x, double v) const {
if(x==1.) return _xb_a;
if(v==0.) return _xb_a;
if(v==1.) return _xb_a/x;
return (_xb_a/sqrt(x))*sqrt((1.-(1.-x)*(1.-v))/(1.-(1.-x)*v));
}
double MEPP2ZHPowheg::x_b(double x, double v) const {
if(x==1.) return _xb_b;
if(v==0.) return _xb_b/x;
if(v==1.) return _xb_b;
return (_xb_b/sqrt(x))*sqrt((1.-(1.-x)*v)/(1.-(1.-x)*(1.-v)));
}
double MEPP2ZHPowheg::xbar(double v) const {
double xba2(sqr(_xb_a)), xbb2(sqr(_xb_b)), omv(-999.);
double xbar1(-999.), xbar2(-999.);
if(v==1.) return _xb_a;
if(v==0.) return _xb_b;
omv = 1.-v;
xbar1=4.* v*xba2/
(sqrt(sqr(1.+xba2)*4.*sqr(omv)+16.*(1.-2.*omv)*xba2)+2.*omv*(1.-_xb_a)*(1.+_xb_a));
xbar2=4.*omv*xbb2/
(sqrt(sqr(1.+xbb2)*4.*sqr( v)+16.*(1.-2.* v)*xbb2)+2.* v*(1.-_xb_b)*(1.+_xb_b));
return max(xbar1,xbar2);
}
double MEPP2ZHPowheg::Ltilde_qq(double x, double v) const {
if(x==1.) return 1.;
double xa(x_a(x,v)),xb(x_b(x,v));
double newq = (_hadron_A->pdf()->xfx(_hadron_A,_parton_a,scale(), xa)/ xa);
double newqbar = (_hadron_B->pdf()->xfx(_hadron_B,_parton_b,scale(), xb)/ xb);
return( newq * newqbar / _oldq / _oldqbar );
}
double MEPP2ZHPowheg::Ltilde_qg(double x, double v) const {
double xa(x_a(x,v)),xb(x_b(x,v));
double newq = (_hadron_A->pdf()->xfx(_hadron_A,_parton_a,scale(), xa)/ xa);
double newg2 = (_hadron_B->pdf()->xfx(_hadron_B,_gluon ,scale(), xb)/ xb);
return( newq * newg2 / _oldq / _oldqbar );
}
double MEPP2ZHPowheg::Ltilde_gq(double x, double v) const {
double xa(x_a(x,v)),xb(x_b(x,v));
double newg1 = (_hadron_A->pdf()->xfx(_hadron_A,_gluon ,scale(), xa)/ xa);
double newqbar = (_hadron_B->pdf()->xfx(_hadron_B,_parton_b,scale(), xb)/ xb);
return( newg1 * newqbar / _oldq / _oldqbar );
}
double MEPP2ZHPowheg::Vtilde_qq() const {
return _alphaS2Pi*CF_*(-3.*log(_mu2/_mll2)+(2.*sqr(Constants::pi)/3.)-8.);
}
double MEPP2ZHPowheg::Ccalbar_qg(double x) const {
return (sqr(x)+sqr(1.-x))*(log(_mll2/(_mu2*x))+2.*log(1.-x))+2.*x*(1.-x);
}
double MEPP2ZHPowheg::Ctilde_qg(double x, double v) const {
return _alphaS2Pi*TR_ * ((1.-xbar(v))/x) * Ccalbar_qg(x)*Ltilde_qg(x,v);
}
double MEPP2ZHPowheg::Ctilde_gq(double x, double v) const {
return _alphaS2Pi*TR_ * ((1.-xbar(v))/x) * Ccalbar_qg(x)*Ltilde_gq(x,v);
}
double MEPP2ZHPowheg::Ctilde_qq(double x, double v) const {
double wgt
= ((1.-x)/x+(1.+x*x)/(1.-x)/x*(2.*log(1.-x)-log(x)))*Ltilde_qq(x,v)
- 4.*log(1.-x)/(1.-x)
+ 2./(1.-xbar(v))*log(1.-xbar(v))*log(1.-xbar(v))
+ (2./(1.-xbar(v))*log(1.-xbar(v))-2./(1.-x)+(1.+x*x)/x/(1.-x)*Ltilde_qq(x,v))
*log(_mll2/_mu2);
return _alphaS2Pi*CF_*(1.-xbar(v))*wgt;
}
double MEPP2ZHPowheg::Fcal_qq(double x, double v) const {
return (sqr(1.-x)*(1.-2.*v*(1.-v))+2.*x)/x*Ltilde_qq(x,v);
}
double MEPP2ZHPowheg::Fcal_qg(double x, double v) const {
return ((1.-xbar(v))/x)*
(2.*x*(1.-x)*v+sqr((1.-x)*v)+sqr(x)+sqr(1.-x))*Ltilde_qg(x,v);
}
double MEPP2ZHPowheg::Fcal_gq(double x, double v) const {
return ((1.-xbar(v))/x)*
(2.*x*(1.-x)*(1.-v)+sqr((1.-x)*(1.-v))+sqr(x)+sqr(1.-x))*Ltilde_gq(x,v);
}
double MEPP2ZHPowheg::Ftilde_qg(double xt, double v) const {
return _alphaS2Pi*TR_*
( Fcal_qg(x(xt,v),v) - Fcal_qg(x(xt,0.),0.) )/v;
}
double MEPP2ZHPowheg::Ftilde_gq(double xt, double v) const {
return _alphaS2Pi*TR_*
( Fcal_gq(x(xt,v),v) - Fcal_gq(x(xt,1.),1.) )/(1.-v);
}
double MEPP2ZHPowheg::Ftilde_qq(double xt, double v) const {
double eps(1e-10);
// is emission into regular or singular region?
if(xt>=0. && xt<1.-eps && v>eps && v<1.-eps) {
// x<1, v>0, v<1 (regular emission, neither soft or collinear):
return _alphaS2Pi*CF_*
(( ( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,1.),1.) ) / (1.-v)+
( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,0.),0.) ) / v )/(1.-xt)
+ ( log(1.-xbar(v)) - log(1.-_xb_a))*2./(1.-v)
+ ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v);
}
else {
// make sure emission is actually in the allowed phase space:
if(!(v>=0. && v<=1. && xt>=0. && xt<=1.)) {
ostringstream s;
s << "MEPP2ZHPowheg::Ftilde_qq : \n" << "xt(" << xt << ") and / or v("
<< v << ") not in the phase space.";
generator()->logWarning(Exception(s.str(),Exception::warning));
return 0.;
}
// is emission soft singular?
if(xt>=1.-eps) {
// x=1:
if(v<=eps) {
// x==1, v=0 (soft and collinear with particle b):
return _alphaS2Pi*CF_*
( ( log(1.-xbar(v)) - log(1.-_xb_a))*2./(1.-v)
);
} else if(v>=1.-eps) {
// x==1, v=1 (soft and collinear with particle a):
return _alphaS2Pi*CF_*
( ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v
);
} else {
// x==1, 0<v<1 (soft wide angle emission):
return _alphaS2Pi*CF_*
( ( log(1.-xbar(v)) - log(1.-_xb_a))*2./(1.-v)
+ ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v
);
}
} else {
// x<1:
if(v<=eps) {
// x<1 but v=0 (collinear with particle b, but not soft):
return _alphaS2Pi*CF_*
( ( ( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,1.),1.) ) / (1.-v)
)/(1.-xt)
+ ( log(1.-xbar(v)) - log(1.-_xb_a))*2./(1.-v)
);
} else if(v>=1.-eps) {
// x<1 but v=1 (collinear with particle a, but not soft):
return _alphaS2Pi*CF_*
( ( ( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,0.),0.) ) / v
)/(1.-xt)
+ ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v
);
}
}
}
return 0.;
}
diff --git a/MatrixElement/Powheg/MEqq2W2ffPowheg.cc b/MatrixElement/Powheg/MEqq2W2ffPowheg.cc
--- a/MatrixElement/Powheg/MEqq2W2ffPowheg.cc
+++ b/MatrixElement/Powheg/MEqq2W2ffPowheg.cc
@@ -1,389 +1,389 @@
// -*- C++ -*-
//
// MEqq2W2ffPowheg.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 MEqq2W2ffPowheg class.
//
#include "MEqq2W2ffPowheg.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "Herwig/Models/StandardModel/StandardModel.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "Herwig/Utilities/Maths.h"
using namespace Herwig;
using Herwig::Math::ReLi2;
MEqq2W2ffPowheg::MEqq2W2ffPowheg() :
_gluon(), TR_(0.5), CF_(4./3.),
_contrib(1) ,_nlo_alphaS_opt(0), _fixed_alphaS(0.115895),
_a(0.5) ,_p(0.7) , _eps(1.0e-8), _scaleopt(1),
_fixedScale(100.*GeV), _scaleFact(1.) {
massOption(vector<unsigned int>(2,1));
}
void MEqq2W2ffPowheg::doinit() {
// gluon ParticleData object
_gluon = getParticleData(ParticleID::g);
MEqq2W2ff::doinit();
}
Energy2 MEqq2W2ffPowheg::scale() const {
return _scaleopt == 0 ? sqr(_fixedScale) : _scaleFact*sHat();
}
void MEqq2W2ffPowheg::persistentOutput(PersistentOStream & os) const {
os << _contrib << _nlo_alphaS_opt << _fixed_alphaS << _a << _p << _gluon
<< _scaleopt << ounit(_fixedScale,GeV) << _scaleFact;
}
void MEqq2W2ffPowheg::persistentInput(PersistentIStream & is, int) {
is >> _contrib >> _nlo_alphaS_opt >> _fixed_alphaS >> _a >> _p >> _gluon
>> _scaleopt >> iunit(_fixedScale,GeV) >> _scaleFact;
}
ClassDescription<MEqq2W2ffPowheg> MEqq2W2ffPowheg::initMEqq2W2ffPowheg;
// Definition of the static class description member.
void MEqq2W2ffPowheg::Init() {
static ClassDocumentation<MEqq2W2ffPowheg> documentation
("The MEqq2W2ffPowheg class implements the matrix element for"
"q qbar to Standard Model fermions via W exchange using helicity amplitude"
"techniques including the NLO correction in the POWHEG formalism",
"The qq$\\to$W$\\to$ff POWHEG matrix element is described in \\cite{Hamilton:2008pd}.",
"%\\cite{Hamilton:2008pd}\n"
"\\bibitem{Hamilton:2008pd}\n"
" K.~Hamilton, P.~Richardson and J.~Tully,\n"
" ``A Positive-Weight Next-to-Leading Order Monte Carlo Simulation of Drell-Yan\n"
" Vector Boson Production,''\n"
" JHEP {\\bf 0810} (2008) 015\n"
" [arXiv:0806.0290 [hep-ph]].\n"
" %%CITATION = JHEPA,0810,015;%%\n");
static Switch<MEqq2W2ffPowheg,unsigned int> interfaceContribution
("Contribution",
"Which contributions to the cross section to include",
&MEqq2W2ffPowheg::_contrib, 1, false, false);
static SwitchOption interfaceContributionLeadingOrder
(interfaceContribution,
"LeadingOrder",
"Just generate the leading order cross section",
0);
static SwitchOption interfaceContributionPositiveNLO
(interfaceContribution,
"PositiveNLO",
"Generate the positive contribution to the full NLO cross section",
1);
static SwitchOption interfaceContributionNegativeNLO
(interfaceContribution,
"NegativeNLO",
"Generate the negative contribution to the full NLO cross section",
2);
static Switch<MEqq2W2ffPowheg,unsigned int> interfaceNLOalphaSopt
("NLOalphaSopt",
"Whether to use a fixed or a running QCD coupling for the NLO weight",
&MEqq2W2ffPowheg::_nlo_alphaS_opt, 0, false, false);
static SwitchOption interfaceNLOalphaSoptRunningAlphaS
(interfaceNLOalphaSopt,
"RunningAlphaS",
"Use the usual running QCD coupling evaluated at scale scale()",
0);
static SwitchOption interfaceNLOalphaSoptFixedAlphaS
(interfaceNLOalphaSopt,
"FixedAlphaS",
"Use a constant QCD coupling for comparison/debugging purposes",
1);
static Parameter<MEqq2W2ffPowheg,double> interfaceFixedNLOalphaS
("FixedNLOalphaS",
"The value of alphaS to use for the nlo weight if _nlo_alphaS_opt=1",
&MEqq2W2ffPowheg::_fixed_alphaS, 0.115895, 0., 1.0,
false, false, Interface::limited);
static Parameter<MEqq2W2ffPowheg,double> interfaceCorrectionCoefficient
("CorrectionCoefficient",
"The magnitude of the correction term to reduce the negative contribution",
&MEqq2W2ffPowheg::_a, 0.5, -10., 10.0,
false, false, Interface::limited);
static Parameter<MEqq2W2ffPowheg,double> interfaceCorrectionPower
("CorrectionPower",
"The power of the correction term to reduce the negative contribution",
&MEqq2W2ffPowheg::_p, 0.7, 0.0, 1.0,
false, false, Interface::limited);
static Switch<MEqq2W2ffPowheg,unsigned int> interfaceScaleOption
("ScaleOption",
"Option for the scale to be used",
&MEqq2W2ffPowheg::_scaleopt, 1, false, false);
static SwitchOption interfaceScaleOptionFixed
(interfaceScaleOption,
"Fixed",
"Use a fixed scale",
0);
static SwitchOption interfaceScaleOptionsHat
(interfaceScaleOption,
"Dynamic",
"Use the off-shell vector boson mass as the scale",
1);
static Parameter<MEqq2W2ffPowheg,Energy> interfaceFixedScale
("FixedScale",
"The fixed scale to use if required",
&MEqq2W2ffPowheg::_fixedScale, GeV, 100.0*GeV, 10.0*GeV, 1000.0*GeV,
false, false, Interface::limited);
static Parameter<MEqq2W2ffPowheg,double> interfaceScaleFactor
("ScaleFactor",
"The factor used before sHat if using a running scale",
&MEqq2W2ffPowheg::_scaleFact, 1.0, 0.0, 10.0,
false, false, Interface::limited);
}
int MEqq2W2ffPowheg::nDim() const {
return 3;
}
bool MEqq2W2ffPowheg::generateKinematics(const double * r) {
_xt=*(r+1);
_v =*(r+2);
return MEqq2W2ff::generateKinematics(r);
}
CrossSection MEqq2W2ffPowheg::dSigHatDR() const {
// Get Born momentum fractions xbar_a and xbar_b:
_xb_a = lastX1();
_xb_b = lastX2();
return MEqq2W2ff::dSigHatDR()*NLOweight();
}
double MEqq2W2ffPowheg::NLOweight() const {
// If only leading order is required return 1:
if(_contrib==0) return 1.;
useMe();
// Get particle data for QCD particles:
_parton_a=mePartonData()[0];
_parton_b=mePartonData()[1];
// get BeamParticleData objects for PDF's
_hadron_A=dynamic_ptr_cast<Ptr<BeamParticleData>::transient_const_pointer>
(lastParticles().first->dataPtr());
_hadron_B=dynamic_ptr_cast<Ptr<BeamParticleData>::transient_const_pointer>
(lastParticles().second->dataPtr());
// If necessary swap the particle data vectors so that _xb_a,
// mePartonData[0], beam[0] relate to the inbound quark:
if(!(lastPartons().first ->dataPtr()==_parton_a&&
lastPartons().second->dataPtr()==_parton_b)) {
swap(_xb_a ,_xb_b);
swap(_hadron_A,_hadron_B);
}
// calculate the PDF's for the Born process
_oldq = _hadron_A->pdf()->xfx(_hadron_A,_parton_a,scale(),_xb_a)/_xb_a;
_oldqbar = _hadron_B->pdf()->xfx(_hadron_B,_parton_b,scale(),_xb_b)/_xb_b;
// Calculate alpha_S
_alphaS2Pi = _nlo_alphaS_opt==1 ? _fixed_alphaS : SM().alphaS(scale());
_alphaS2Pi /= 2.*Constants::pi;
// Calculate the invariant mass of the dilepton pair
_mll2 = sHat();
_mu2 = scale();
// Calculate the integrand
// q qbar contribution
double wqqvirt = Vtilde_qq();
double wqqcollin = Ctilde_qq(x(_xt,1.),1.) + Ctilde_qq(x(_xt,0.),0.);
double wqqreal = Ftilde_qq(_xt,_v);
double wqq = wqqvirt+wqqcollin+wqqreal;
// q g contribution
double wqgcollin = Ctilde_qg(x(_xt,0.),0.);
double wqgreal = Ftilde_qg(_xt,_v);
double wqg = wqgreal+wqgcollin;
// g qbar contribution
double wgqbarcollin = Ctilde_gq(x(_xt,1.),1.);
double wgqbarreal = Ftilde_gq(_xt,_v);
double wgqbar = wgqbarreal+wgqbarcollin;
// total
double wgt = 1.+(wqq+wqg+wgqbar);
//trick to try and reduce neg wgt contribution
if(_xt<1.-_eps)
wgt += _a*(1./pow(1.-_xt,_p)-(1.-pow(_eps,1.-_p))/(1.-_p)/(1.-_eps));
// return the answer
- assert(!isinf(wgt)&&!isnan(wgt));
+ assert(isfinite(wgt));
return _contrib==1 ? max(0.,wgt) : max(0.,-wgt);
}
double MEqq2W2ffPowheg::x(double xt, double v) const {
double x0(xbar(v));
return x0+(1.-x0)*xt;
}
double MEqq2W2ffPowheg::x_a(double x, double v) const {
if(x==1.) return _xb_a;
if(v==0.) return _xb_a;
if(v==1.) return _xb_a/x;
return (_xb_a/sqrt(x))*sqrt((1.-(1.-x)*(1.-v))/(1.-(1.-x)*v));
}
double MEqq2W2ffPowheg::x_b(double x, double v) const {
if(x==1.) return _xb_b;
if(v==0.) return _xb_b/x;
if(v==1.) return _xb_b;
return (_xb_b/sqrt(x))*sqrt((1.-(1.-x)*v)/(1.-(1.-x)*(1.-v)));
}
double MEqq2W2ffPowheg::xbar(double v) const {
double xba2(sqr(_xb_a)), xbb2(sqr(_xb_b)), omv(-999.);
double xbar1(-999.), xbar2(-999.);
if(v==1.) return _xb_a;
if(v==0.) return _xb_b;
omv = 1.-v;
xbar1=4.* v*xba2/
(sqrt(sqr(1.+xba2)*4.*sqr(omv)+16.*(1.-2.*omv)*xba2)+2.*omv*(1.-_xb_a)*(1.+_xb_a));
xbar2=4.*omv*xbb2/
(sqrt(sqr(1.+xbb2)*4.*sqr( v)+16.*(1.-2.* v)*xbb2)+2.* v*(1.-_xb_b)*(1.+_xb_b));
return max(xbar1,xbar2);
}
double MEqq2W2ffPowheg::Ltilde_qq(double x, double v) const {
if(x==1.) return 1.;
double xa(x_a(x,v)),xb(x_b(x,v));
double newq = (_hadron_A->pdf()->xfx(_hadron_A,_parton_a,scale(), xa)/ xa);
double newqbar = (_hadron_B->pdf()->xfx(_hadron_B,_parton_b,scale(), xb)/ xb);
return( newq * newqbar / _oldq / _oldqbar );
}
double MEqq2W2ffPowheg::Ltilde_qg(double x, double v) const {
double xa(x_a(x,v)),xb(x_b(x,v));
double newq = (_hadron_A->pdf()->xfx(_hadron_A,_parton_a,scale(), xa)/ xa);
double newg2 = (_hadron_B->pdf()->xfx(_hadron_B,_gluon ,scale(), xb)/ xb);
return( newq * newg2 / _oldq / _oldqbar );
}
double MEqq2W2ffPowheg::Ltilde_gq(double x, double v) const {
double xa(x_a(x,v)),xb(x_b(x,v));
double newg1 = (_hadron_A->pdf()->xfx(_hadron_A,_gluon ,scale(), xa)/ xa);
double newqbar = (_hadron_B->pdf()->xfx(_hadron_B,_parton_b,scale(), xb)/ xb);
return( newg1 * newqbar / _oldq / _oldqbar );
}
double MEqq2W2ffPowheg::Vtilde_qq() const {
return _alphaS2Pi*CF_*(-3.*log(_mu2/_mll2)+(2.*sqr(Constants::pi)/3.)-8.);
}
double MEqq2W2ffPowheg::Ccalbar_qg(double x) const {
return (sqr(x)+sqr(1.-x))*(log(_mll2/(_mu2*x))+2.*log(1.-x))+2.*x*(1.-x);
}
double MEqq2W2ffPowheg::Ctilde_qg(double x, double v) const {
return _alphaS2Pi*TR_ * ((1.-xbar(v))/x) * Ccalbar_qg(x)*Ltilde_qg(x,v);
}
double MEqq2W2ffPowheg::Ctilde_gq(double x, double v) const {
return _alphaS2Pi*TR_ * ((1.-xbar(v))/x) * Ccalbar_qg(x)*Ltilde_gq(x,v);
}
double MEqq2W2ffPowheg::Ctilde_qq(double x, double v) const {
double wgt
= ((1.-x)/x+(1.+x*x)/(1.-x)/x*(2.*log(1.-x)-log(x)))*Ltilde_qq(x,v)
- 4.*log(1.-x)/(1.-x)
+ 2./(1.-xbar(v))*log(1.-xbar(v))*log(1.-xbar(v))
+ (2./(1.-xbar(v))*log(1.-xbar(v))-2./(1.-x)+(1.+x*x)/x/(1.-x)*Ltilde_qq(x,v))
*log(_mll2/_mu2);
return _alphaS2Pi*CF_*(1.-xbar(v))*wgt;
}
double MEqq2W2ffPowheg::Fcal_qq(double x, double v) const {
return (sqr(1.-x)*(1.-2.*v*(1.-v))+2.*x)/x*Ltilde_qq(x,v);
}
double MEqq2W2ffPowheg::Fcal_qg(double x, double v) const {
return ((1.-xbar(v))/x)*
(2.*x*(1.-x)*v+sqr((1.-x)*v)+sqr(x)+sqr(1.-x))*Ltilde_qg(x,v);
}
double MEqq2W2ffPowheg::Fcal_gq(double x, double v) const {
return ((1.-xbar(v))/x)*
(2.*x*(1.-x)*(1.-v)+sqr((1.-x)*(1.-v))+sqr(x)+sqr(1.-x))*Ltilde_gq(x,v);
}
double MEqq2W2ffPowheg::Ftilde_qg(double xt, double v) const {
return _alphaS2Pi*TR_*
( Fcal_qg(x(xt,v),v) - Fcal_qg(x(xt,0.),0.) )/v;
}
double MEqq2W2ffPowheg::Ftilde_gq(double xt, double v) const {
return _alphaS2Pi*TR_*
( Fcal_gq(x(xt,v),v) - Fcal_gq(x(xt,1.),1.) )/(1.-v);
}
double MEqq2W2ffPowheg::Ftilde_qq(double xt, double v) const {
double eps(1e-10);
// is emission into regular or singular region?
if(xt>=0. && xt<1.-eps && v>eps && v<1.-eps) {
// x<1, v>0, v<1 (regular emission, neither soft or collinear):
return _alphaS2Pi*CF_*
(( ( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,1.),1.) ) / (1.-v)+
( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,0.),0.) ) / v )/(1.-xt)
+ ( log(1.-xbar(v)) - log(1.-_xb_a))*2./(1.-v)
+ ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v);
}
else {
// make sure emission is actually in the allowed phase space:
if(!(v>=0. && v<=1. && xt>=0. && xt<=1.)) {
ostringstream s;
s << "MEqq2W2ffPowheg::Ftilde_qq : \n" << "xt(" << xt << ") and / or v("
<< v << ") not in the phase space.";
generator()->logWarning(Exception(s.str(),Exception::warning));
return 0.;
}
// is emission soft singular?
if(xt>=1.-eps) {
// x=1:
if(v<=eps) {
// x==1, v=0 (soft and collinear with particle b):
return _alphaS2Pi*CF_*
( ( log(1.-xbar(v)) - log(1.-_xb_a))*2./(1.-v)
);
} else if(v>=1.-eps) {
// x==1, v=1 (soft and collinear with particle a):
return _alphaS2Pi*CF_*
( ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v
);
} else {
// x==1, 0<v<1 (soft wide angle emission):
return _alphaS2Pi*CF_*
( ( log(1.-xbar(v)) - log(1.-_xb_a))*2./(1.-v)
+ ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v
);
}
} else {
// x<1:
if(v<=eps) {
// x<1 but v=0 (collinear with particle b, but not soft):
return _alphaS2Pi*CF_*
( ( ( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,1.),1.) ) / (1.-v)
)/(1.-xt)
+ ( log(1.-xbar(v)) - log(1.-_xb_a))*2./(1.-v)
);
} else if(v>=1.-eps) {
// x<1 but v=1 (collinear with particle a, but not soft):
return _alphaS2Pi*CF_*
( ( ( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,0.),0.) ) / v
)/(1.-xt)
+ ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v
);
}
}
}
return 0.;
}
diff --git a/MatrixElement/Powheg/MEqq2gZ2ffPowheg.cc b/MatrixElement/Powheg/MEqq2gZ2ffPowheg.cc
--- a/MatrixElement/Powheg/MEqq2gZ2ffPowheg.cc
+++ b/MatrixElement/Powheg/MEqq2gZ2ffPowheg.cc
@@ -1,394 +1,394 @@
// -*- C++ -*-
//
// MEqq2gZ2ffPowheg.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 MEqq2gZ2ffPowheg class.
//
#include "MEqq2gZ2ffPowheg.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "Herwig/Models/StandardModel/StandardModel.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "Herwig/Utilities/Maths.h"
using namespace Herwig;
using Herwig::Math::ReLi2;
MEqq2gZ2ffPowheg::MEqq2gZ2ffPowheg() :
_gluon(), TR_(0.5), CF_(4./3.),
_contrib(1) ,_nlo_alphaS_opt(0), _fixed_alphaS(0.115895),
_a(0.5) ,_p(0.7) , _eps(1.0e-8), _scaleopt(1),
_fixedScale(100.*GeV), _scaleFact(1.) {
massOption(vector<unsigned int>(2,1));
}
void MEqq2gZ2ffPowheg::doinit() {
// gluon ParticleData object
_gluon = getParticleData(ParticleID::g);
MEqq2gZ2ff::doinit();
}
Energy2 MEqq2gZ2ffPowheg::scale() const {
return _scaleopt == 0 ? sqr(_fixedScale) : _scaleFact*sHat();
}
void MEqq2gZ2ffPowheg::persistentOutput(PersistentOStream & os) const {
os << _contrib << _nlo_alphaS_opt << _fixed_alphaS << _a << _p << _gluon
<< _scaleopt << ounit(_fixedScale,GeV) << _scaleFact;
}
void MEqq2gZ2ffPowheg::persistentInput(PersistentIStream & is, int) {
is >> _contrib >> _nlo_alphaS_opt >> _fixed_alphaS >> _a >> _p >> _gluon
>> _scaleopt >> iunit(_fixedScale,GeV) >> _scaleFact;
}
ClassDescription<MEqq2gZ2ffPowheg> MEqq2gZ2ffPowheg::initMEqq2gZ2ffPowheg;
// Definition of the static class description member.
void MEqq2gZ2ffPowheg::Init() {
static ClassDocumentation<MEqq2gZ2ffPowheg> documentation
("The MEqq2gZ2ffPowheg class implements the matrix element for"
"q qbar to Standard Model fermions via Z and photon exchange using"
" helicity amplitude techniques including the NLO correction in"
" the POWHEG formalism",
"The qq$\\to\\gamma/Z\\to$ff POWHEG matrix element is described in \\cite{Hamilton:2008pd}.",
"%\\cite{Hamilton:2008pd}\n"
"\\bibitem{Hamilton:2008pd}\n"
" K.~Hamilton, P.~Richardson and J.~Tully,\n"
" %``A Positive-Weight Next-to-Leading Order Monte Carlo Simulation of Drell-Yan\n"
" %Vector Boson Production,''\n"
" JHEP {\\bf 0810} (2008) 015\n"
" [arXiv:0806.0290 [hep-ph]].\n"
" %%CITATION = JHEPA,0810,015;%%\n"
);
static Switch<MEqq2gZ2ffPowheg,unsigned int> interfaceContribution
("Contribution",
"Which contributions to the cross section to include",
&MEqq2gZ2ffPowheg::_contrib, 1, false, false);
static SwitchOption interfaceContributionLeadingOrder
(interfaceContribution,
"LeadingOrder",
"Just generate the leading order cross section",
0);
static SwitchOption interfaceContributionPositiveNLO
(interfaceContribution,
"PositiveNLO",
"Generate the positive contribution to the full NLO cross section",
1);
static SwitchOption interfaceContributionNegativeNLO
(interfaceContribution,
"NegativeNLO",
"Generate the negative contribution to the full NLO cross section",
2);
static Switch<MEqq2gZ2ffPowheg,unsigned int> interfaceNLOalphaSopt
("NLOalphaSopt",
"Whether to use a fixed or a running QCD coupling for the NLO weight",
&MEqq2gZ2ffPowheg::_nlo_alphaS_opt, 0, false, false);
static SwitchOption interfaceNLOalphaSoptRunningAlphaS
(interfaceNLOalphaSopt,
"RunningAlphaS",
"Use the usual running QCD coupling evaluated at scale scale()",
0);
static SwitchOption interfaceNLOalphaSoptFixedAlphaS
(interfaceNLOalphaSopt,
"FixedAlphaS",
"Use a constant QCD coupling for comparison/debugging purposes",
1);
static Parameter<MEqq2gZ2ffPowheg,double> interfaceFixedNLOalphaS
("FixedNLOalphaS",
"The value of alphaS to use for the nlo weight if _nlo_alphaS_opt=1",
&MEqq2gZ2ffPowheg::_fixed_alphaS, 0.115895, 0., 1.0,
false, false, Interface::limited);
static Parameter<MEqq2gZ2ffPowheg,double> interfaceCorrectionCoefficient
("CorrectionCoefficient",
"The magnitude of the correction term to reduce the negative contribution",
&MEqq2gZ2ffPowheg::_a, 0.5, -10., 10.0,
false, false, Interface::limited);
static Parameter<MEqq2gZ2ffPowheg,double> interfaceCorrectionPower
("CorrectionPower",
"The power of the correction term to reduce the negative contribution",
&MEqq2gZ2ffPowheg::_p, 0.7, 0.0, 1.0,
false, false, Interface::limited);
static Switch<MEqq2gZ2ffPowheg,unsigned int> interfaceScaleOption
("ScaleOption",
"Option for the scale to be used",
&MEqq2gZ2ffPowheg::_scaleopt, 1, false, false);
static SwitchOption interfaceScaleOptionFixed
(interfaceScaleOption,
"Fixed",
"Use a fixed scale",
0);
static SwitchOption interfaceScaleOptionsHat
(interfaceScaleOption,
"Dynamic",
"Use the off-shell vector boson mass as the scale",
1);
static Parameter<MEqq2gZ2ffPowheg,Energy> interfaceFixedScale
("FixedScale",
"The fixed scale to use if required",
&MEqq2gZ2ffPowheg::_fixedScale, GeV, 100.0*GeV, 10.0*GeV, 1000.0*GeV,
false, false, Interface::limited);
static Parameter<MEqq2gZ2ffPowheg,double> interfaceScaleFactor
("ScaleFactor",
"The factor used before sHat if using a running scale",
&MEqq2gZ2ffPowheg::_scaleFact, 1.0, 0.0, 10.0,
false, false, Interface::limited);
}
int MEqq2gZ2ffPowheg::nDim() const {
return HwMEBase::nDim() + ( _contrib>=1 ? 2 : 0 );
}
bool MEqq2gZ2ffPowheg::generateKinematics(const double * r) {
if(_contrib>=1) {
_xt=*(r+1);
_v =*(r+2);
}
return MEqq2gZ2ff::generateKinematics(r);
}
CrossSection MEqq2gZ2ffPowheg::dSigHatDR() const {
// Get Born momentum fractions xbar_a and xbar_b:
_xb_a = lastX1();
_xb_b = lastX2();
return MEqq2gZ2ff::dSigHatDR()*NLOweight();
}
double MEqq2gZ2ffPowheg::NLOweight() const {
// If only leading order is required return 1:
if(_contrib==0) return 1.;
useMe();
// Get particle data for QCD particles:
_parton_a=mePartonData()[0];
_parton_b=mePartonData()[1];
// get BeamParticleData objects for PDF's
_hadron_A=dynamic_ptr_cast<Ptr<BeamParticleData>::transient_const_pointer>
(lastParticles().first->dataPtr());
_hadron_B=dynamic_ptr_cast<Ptr<BeamParticleData>::transient_const_pointer>
(lastParticles().second->dataPtr());
// If necessary swap the particle data vectors so that _xb_a,
// mePartonData[0], beam[0] relate to the inbound quark:
if(!(lastPartons().first ->dataPtr()==_parton_a&&
lastPartons().second->dataPtr()==_parton_b)) {
swap(_xb_a ,_xb_b);
swap(_hadron_A,_hadron_B);
}
// calculate the PDF's for the Born process
_oldq = _hadron_A->pdf()->xfx(_hadron_A,_parton_a,scale(),_xb_a)/_xb_a;
_oldqbar = _hadron_B->pdf()->xfx(_hadron_B,_parton_b,scale(),_xb_b)/_xb_b;
// Calculate alpha_S
_alphaS2Pi = _nlo_alphaS_opt==1 ? _fixed_alphaS : SM().alphaS(scale());
_alphaS2Pi /= 2.*Constants::pi;
// Calculate the invariant mass of the dilepton pair
_mll2 = sHat();
_mu2 = scale();
// Calculate the integrand
// q qbar contribution
double wqqvirt = Vtilde_qq();
double wqqcollin = Ctilde_qq(x(_xt,1.),1.) + Ctilde_qq(x(_xt,0.),0.);
double wqqreal = Ftilde_qq(_xt,_v);
double wqq = wqqvirt+wqqcollin+wqqreal;
// q g contribution
double wqgcollin = Ctilde_qg(x(_xt,0.),0.);
double wqgreal = Ftilde_qg(_xt,_v);
double wqg = wqgreal+wqgcollin;
// g qbar contribution
double wgqbarcollin = Ctilde_gq(x(_xt,1.),1.);
double wgqbarreal = Ftilde_gq(_xt,_v);
double wgqbar = wgqbarreal+wgqbarcollin;
// total
double wgt = 1.+(wqq+wqg+wgqbar);
//trick to try and reduce neg wgt contribution
if(_xt<1.-_eps)
wgt += _a*(1./pow(1.-_xt,_p)-(1.-pow(_eps,1.-_p))/(1.-_p)/(1.-_eps));
- assert(!isinf(wgt)&&!isnan(wgt));
+ assert(isfinite(wgt));
// return the answer
return _contrib==1 ? max(0.,wgt) : max(0.,-wgt);
}
double MEqq2gZ2ffPowheg::x(double xt, double v) const {
double x0(xbar(v));
return x0+(1.-x0)*xt;
}
double MEqq2gZ2ffPowheg::x_a(double x, double v) const {
if(x==1.) return _xb_a;
if(v==0.) return _xb_a;
if(v==1.) return _xb_a/x;
return (_xb_a/sqrt(x))*sqrt((1.-(1.-x)*(1.-v))/(1.-(1.-x)*v));
}
double MEqq2gZ2ffPowheg::x_b(double x, double v) const {
if(x==1.) return _xb_b;
if(v==0.) return _xb_b/x;
if(v==1.) return _xb_b;
return (_xb_b/sqrt(x))*sqrt((1.-(1.-x)*v)/(1.-(1.-x)*(1.-v)));
}
double MEqq2gZ2ffPowheg::xbar(double v) const {
double xba2(sqr(_xb_a)), xbb2(sqr(_xb_b)), omv(-999.);
double xbar1(-999.), xbar2(-999.);
if(v==1.) return _xb_a;
if(v==0.) return _xb_b;
omv = 1.-v;
xbar1=4.* v*xba2/
(sqrt(sqr(1.+xba2)*4.*sqr(omv)+16.*(1.-2.*omv)*xba2)+2.*omv*(1.-_xb_a)*(1.+_xb_a));
xbar2=4.*omv*xbb2/
(sqrt(sqr(1.+xbb2)*4.*sqr( v)+16.*(1.-2.* v)*xbb2)+2.* v*(1.-_xb_b)*(1.+_xb_b));
return max(xbar1,xbar2);
}
double MEqq2gZ2ffPowheg::Ltilde_qq(double x, double v) const {
if(x==1.) return 1.;
double xa(x_a(x,v)),xb(x_b(x,v));
double newq = (_hadron_A->pdf()->xfx(_hadron_A,_parton_a,scale(), xa)/ xa);
double newqbar = (_hadron_B->pdf()->xfx(_hadron_B,_parton_b,scale(), xb)/ xb);
return( newq * newqbar / _oldq / _oldqbar );
}
double MEqq2gZ2ffPowheg::Ltilde_qg(double x, double v) const {
double xa(x_a(x,v)),xb(x_b(x,v));
double newq = (_hadron_A->pdf()->xfx(_hadron_A,_parton_a,scale(), xa)/ xa);
double newg2 = (_hadron_B->pdf()->xfx(_hadron_B,_gluon ,scale(), xb)/ xb);
return( newq * newg2 / _oldq / _oldqbar );
}
double MEqq2gZ2ffPowheg::Ltilde_gq(double x, double v) const {
double xa(x_a(x,v)),xb(x_b(x,v));
double newg1 = (_hadron_A->pdf()->xfx(_hadron_A,_gluon ,scale(), xa)/ xa);
double newqbar = (_hadron_B->pdf()->xfx(_hadron_B,_parton_b,scale(), xb)/ xb);
return( newg1 * newqbar / _oldq / _oldqbar );
}
double MEqq2gZ2ffPowheg::Vtilde_qq() const {
return _alphaS2Pi*CF_*(-3.*log(_mu2/_mll2)+(2.*sqr(Constants::pi)/3.)-8.);
}
double MEqq2gZ2ffPowheg::Ccalbar_qg(double x) const {
return (sqr(x)+sqr(1.-x))*(log(_mll2/(_mu2*x))+2.*log(1.-x))+2.*x*(1.-x);
}
double MEqq2gZ2ffPowheg::Ctilde_qg(double x, double v) const {
return _alphaS2Pi*TR_ * ((1.-xbar(v))/x) * Ccalbar_qg(x)*Ltilde_qg(x,v);
}
double MEqq2gZ2ffPowheg::Ctilde_gq(double x, double v) const {
return _alphaS2Pi*TR_ * ((1.-xbar(v))/x) * Ccalbar_qg(x)*Ltilde_gq(x,v);
}
double MEqq2gZ2ffPowheg::Ctilde_qq(double x, double v) const {
double wgt
= ((1.-x)/x+(1.+x*x)/(1.-x)/x*(2.*log(1.-x)-log(x)))*Ltilde_qq(x,v)
- 4.*log(1.-x)/(1.-x)
+ 2./(1.-xbar(v))*log(1.-xbar(v))*log(1.-xbar(v))
+ (2./(1.-xbar(v))*log(1.-xbar(v))-2./(1.-x)+(1.+x*x)/x/(1.-x)*Ltilde_qq(x,v))
*log(_mll2/_mu2);
return _alphaS2Pi*CF_*(1.-xbar(v))*wgt;
}
double MEqq2gZ2ffPowheg::Fcal_qq(double x, double v) const {
return (sqr(1.-x)*(1.-2.*v*(1.-v))+2.*x)/x*Ltilde_qq(x,v);
}
double MEqq2gZ2ffPowheg::Fcal_qg(double x, double v) const {
return ((1.-xbar(v))/x)*
(2.*x*(1.-x)*v+sqr((1.-x)*v)+sqr(x)+sqr(1.-x))*Ltilde_qg(x,v);
}
double MEqq2gZ2ffPowheg::Fcal_gq(double x, double v) const {
return ((1.-xbar(v))/x)*
(2.*x*(1.-x)*(1.-v)+sqr((1.-x)*(1.-v))+sqr(x)+sqr(1.-x))*Ltilde_gq(x,v);
}
double MEqq2gZ2ffPowheg::Ftilde_qg(double xt, double v) const {
return _alphaS2Pi*TR_*
( Fcal_qg(x(xt,v),v) - Fcal_qg(x(xt,0.),0.) )/v;
}
double MEqq2gZ2ffPowheg::Ftilde_gq(double xt, double v) const {
return _alphaS2Pi*TR_*
( Fcal_gq(x(xt,v),v) - Fcal_gq(x(xt,1.),1.) )/(1.-v);
}
double MEqq2gZ2ffPowheg::Ftilde_qq(double xt, double v) const {
double eps(1e-10);
// is emission into regular or singular region?
if(xt>=0. && xt<1.-eps && v>eps && v<1.-eps) {
// x<1, v>0, v<1 (regular emission, neither soft or collinear):
return _alphaS2Pi*CF_*
(( ( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,1.),1.) ) / (1.-v)+
( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,0.),0.) ) / v )/(1.-xt)
+ ( log(1.-xbar(v)) - log(1.-_xb_a))*2./(1.-v)
+ ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v);
}
else {
// make sure emission is actually in the allowed phase space:
if(!(v>=0. && v<=1. && xt>=0. && xt<=1.)) {
ostringstream s;
s << "MEqq2gZ2ffPowheg::Ftilde_qq : \n" << "xt(" << xt << ") and / or v("
<< v << ") not in the phase space.";
generator()->logWarning(Exception(s.str(),Exception::warning));
return 0.;
}
// is emission soft singular?
if(xt>=1.-eps) {
// x=1:
if(v<=eps) {
// x==1, v=0 (soft and collinear with particle b):
return _alphaS2Pi*CF_*
( ( log(1.-xbar(v)) - log(1.-_xb_a))*2./(1.-v)
);
} else if(v>=1.-eps) {
// x==1, v=1 (soft and collinear with particle a):
return _alphaS2Pi*CF_*
( ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v
);
} else {
// x==1, 0<v<1 (soft wide angle emission):
return _alphaS2Pi*CF_*
( ( log(1.-xbar(v)) - log(1.-_xb_a))*2./(1.-v)
+ ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v
);
}
} else {
// x<1:
if(v<=eps) {
// x<1 but v=0 (collinear with particle b, but not soft):
return _alphaS2Pi*CF_*
( ( ( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,1.),1.) ) / (1.-v)
)/(1.-xt)
+ ( log(1.-xbar(v)) - log(1.-_xb_a))*2./(1.-v)
);
} else if(v>=1.-eps) {
// x<1 but v=1 (collinear with particle a, but not soft):
return _alphaS2Pi*CF_*
( ( ( Fcal_qq(x(xt, v), v) - Fcal_qq(x(xt,0.),0.) ) / v
)/(1.-xt)
+ ( log(1.-xbar(v)) - log(1.-_xb_b))*2./v
);
}
}
}
return 0.;
}
diff --git a/MatrixElement/Reweighters/ReweightEW.h b/MatrixElement/Reweighters/ReweightEW.h
--- a/MatrixElement/Reweighters/ReweightEW.h
+++ b/MatrixElement/Reweighters/ReweightEW.h
@@ -1,178 +1,174 @@
// -*- C++ -*-
#ifndef Herwig_ReweightEW_H
#define Herwig_ReweightEW_H
//
// This is the declaration of the ReweightEW class.
//
#include "ThePEG/MatrixElement/ReweightBase.h"
-#include <boost/array.hpp>
+#include <array>
namespace Herwig {
using namespace ThePEG;
/**
* Here is the documentation of the ReweightEW class.
*
* @see \ref ReweightEWInterfaces "The interfaces"
* defined for ReweightEW.
*/
class ReweightEW: public ReweightBase {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
ReweightEW();
/**
* The destructor.
*/
virtual ~ReweightEW();
//@}
public:
/**
* Return the weight for the kinematical configuation provided by
* the assigned XComb object (in the LastXCombInfo base class).
*/
virtual double weight() const;
/**
* Return values of the last evaluation (double/doubles in GeV2)
*/
double lastS() const {return thelasts;}
double lastT() const {return thelastt;}
double lastK() const {return thelastk;}
void setSTK(double s, double t, double K);
/** @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;
//@}
private:
/**
* The last s
*/
mutable double thelasts;
/**
* The last t
*/
mutable double thelastt;
/**
* The last K-factor
*/
mutable double thelastk;
/**
* The table of K factors to be read from file
*/
-
- // tab[40000][5];
-
- boost::array<boost::array<double,6>,40001> tab;
- // boost::array<boost::array<double,6>,250001> tab;
+ std::array<std::array<double,6>,40001> tab;
/**
* EW K factor filename
*/
string filename;
public:
/**
* Computation of K factors from table (s and t in GeV)
*/
double EWKFac(unsigned int f, double s, double t) const;
private:
/**
* initialize tables
*/
void inittable();
private:
/**
* Describe a concrete base class with persistent data.
*/
static ClassDescription<ReweightEW> initReweightEW;
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();
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
ReweightEW & operator=(const ReweightEW &);
};
}
#endif /* Herwig_ReweightEW_H */
diff --git a/Models/ADD/Makefile.am b/Models/ADD/Makefile.am
--- a/Models/ADD/Makefile.am
+++ b/Models/ADD/Makefile.am
@@ -1,13 +1,29 @@
-if WANT_BSM
-pkglib_LTLIBRARIES = HwADDModel.la
-endif
-HwADDModel_la_SOURCES = ADDModel.fh ADDModel.cc ADDModel.h \
-ADDModelFFGRVertex.cc ADDModelFFGRVertex.h \
-ADDModelFFGGRVertex.cc ADDModelFFGGRVertex.h \
-ADDModelFFWGRVertex.cc ADDModelFFWGRVertex.h \
-ADDModelSSGRVertex.cc ADDModelSSGRVertex.h \
-ADDModelVVGRVertex.cc ADDModelVVGRVertex.h \
-ADDModelGGGGRVertex.cc ADDModelGGGGRVertex.h \
-ADDModelWWWGRVertex.cc ADDModelWWWGRVertex.h \
-GravitonMassGenerator.h GravitonMassGenerator.cc
-HwADDModel_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 3:0:0
+BUILT_SOURCES = ADD__all.cc
+DISTCLEANFILES = ADD__all.cc
+
+ADD__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+ADDModel.fh ADDModel.h \
+ADDModelFFGRVertex.h \
+ADDModelFFGGRVertex.h \
+ADDModelFFWGRVertex.h \
+ADDModelSSGRVertex.h \
+ADDModelVVGRVertex.h \
+ADDModelGGGGRVertex.h \
+ADDModelWWWGRVertex.h \
+GravitonMassGenerator.h
+
+ALL_CC_FILES = \
+ADDModel.cc \
+ADDModelFFGRVertex.cc \
+ADDModelFFGGRVertex.cc \
+ADDModelFFWGRVertex.cc \
+ADDModelSSGRVertex.cc \
+ADDModelVVGRVertex.cc \
+ADDModelGGGGRVertex.cc \
+ADDModelWWWGRVertex.cc \
+GravitonMassGenerator.cc
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/HardProcessConstructor.h b/Models/General/HardProcessConstructor.h
--- a/Models/General/HardProcessConstructor.h
+++ b/Models/General/HardProcessConstructor.h
@@ -1,224 +1,244 @@
// -*- C++ -*-
#ifndef HERWIG_HardProcessConstructor_H
#define HERWIG_HardProcessConstructor_H
//
// This is the declaration of the HardProcessConstructor class.
//
#include "ThePEG/Interface/Interfaced.h"
#include "HPDiagram.h"
#include "Herwig/Models/StandardModel/StandardModel.h"
#include "ThePEG/Handlers/SubProcessHandler.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Handlers/StandardEventHandler.h"
#include "Herwig/MatrixElement/General/GeneralHardME.h"
#include "HardProcessConstructor.fh"
namespace Herwig {
using namespace ThePEG;
/**
* Here is the documentation of the HardProcessConstructor class.
*
* @see \ref HardProcessConstructorInterfaces "The interfaces"
* defined for HardProcessConstructor.
*/
class HardProcessConstructor: public Interfaced {
public:
/** Vector of HPDiagrams. */
typedef vector<HPDiagram> HPDVector;
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
HardProcessConstructor() : debug_(false) {}
//@}
/**
* The main function to create diagrams etc for the processes
*/
virtual void constructDiagrams() = 0;
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:
/** Functions to set up colour flows and matrix elements. */
//@{
/**
* Determine whether the ordering of the outgoing states is the same
* as the ordering in the matrix elements
* @param diag The diagram to question
*/
void fixFSOrder(HPDiagram & diag);
/**
* Assign a diagram to the appropriate colour flow(s).
* @param diag The diagram to assign
*/
void assignToCF(HPDiagram & diag);
/**
* Assign a $s$-channel diagram to the appropriate colour flow(s).
* @param diag The diagram to assign
*/
void sChannelCF(HPDiagram & diag);
/**
* Assign a $t$-channel diagram to the appropriate colour flow(s).
* @param diag The diagram to assign
*/
void tChannelCF(HPDiagram & diag);
/**
* Assign a $u$-channel diagram to the appropriate colour flow(s).
* @param diag The diagram to assign
*/
void uChannelCF(HPDiagram & diag);
/**
* Assign a $u$-channel diagram to the appropriate colour flow(s).
* @param diag The diagram to assign
*/
void fourPointCF(HPDiagram & diag);
//@}
/**
* Pointer to the model being used
*/
tHwSMPtr model() const {return model_;}
/**
* Pointer to the sub process handler
*/
tSubHdlPtr subProcess() const {return subProcess_;}
/**
* Whether to print the debug information with the matrix
* element. This is here solely so it can be passed to
* a matrix element that is created here.
*/
bool debug() const {return debug_;}
/**
* Get the correct colour factor matrix.
* @param extpart Vector of external ParticleData pointers
*/
GeneralHardME::ColourStructure colourFlow(const tcPDVector & extpart) const;
/**
* Search for a diagram that has already been created
* @param diagram The diagram to search for
* @param group The group of diagrams to search through
*/
bool duplicate(const HPDiagram & diagram,
const HPDVector & group) 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();
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is an abstract class with persistent data.
*/
static AbstractClassDescription<HardProcessConstructor> initHardProcessConstructor;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
HardProcessConstructor & operator=(const HardProcessConstructor &);
private:
/**
* Pointer to the model being used
*/
tHwSMPtr model_;
/**
* Pointer to the sub process handler
*/
tSubHdlPtr subProcess_;
/**
* Whether to print the debug information with the matrix
* element. This is here solely so it can be passed to
* a matrix element that is created here.
*/
bool debug_;
};
+namespace HPC_helper {
+ // Helper functor for find_if in duplicate function.
+ class SameIncomingAs {
+ public:
+ SameIncomingAs(tPDPair in) : a(in.first->id()), b(in.second->id()) {}
+ bool operator()(tPDPair ppair) const {
+ long id1(ppair.first->id()), id2(ppair.second->id());
+ return ( id1 == a && id2 == b ) || ( id1 == b && id2 == a );
+ }
+ private:
+ long a, b;
+ };
+
+ inline bool duplicateIncoming(tPDPair ppair,const vector<tPDPair> &incPairs) {
+ vector<tPDPair>::const_iterator it =
+ find_if( incPairs.begin(), incPairs.end(), SameIncomingAs(ppair) );
+ return it != incPairs.end();
+ }
+}
+
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of HardProcessConstructor. */
template <>
struct BaseClassTrait<Herwig::HardProcessConstructor,1> {
/** Typedef of the first base class of HardProcessConstructor. */
typedef Interfaced NthBase;
};
/** This template specialization informs ThePEG about the name of
* the HardProcessConstructor class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::HardProcessConstructor>
: public ClassTraitsBase<Herwig::HardProcessConstructor> {
/** Return a platform-independent class name */
static string className() { return "Herwig::HardProcessConstructor"; }
};
/** @endcond */
}
#endif /* HERWIG_HardProcessConstructor_H */
diff --git a/Models/General/Makefile.am b/Models/General/Makefile.am
--- a/Models/General/Makefile.am
+++ b/Models/General/Makefile.am
@@ -1,30 +1,53 @@
-noinst_LTLIBRARIES = libHwModelGenerator.la
-libHwModelGenerator_la_SOURCES = \
-ModelGenerator.h ModelGenerator.fh ModelGenerator.cc\
-DecayConstructor.cc DecayConstructor.h DecayConstructor.fh \
-NBodyDecayConstructorBase.cc NBodyDecayConstructorBase.h \
+BUILT_SOURCES = ModelGenerator__all.cc
+DISTCLEANFILES = ModelGenerator__all.cc
+
+ModelGenerator__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+ModelGenerator.h ModelGenerator.fh \
+DecayConstructor.h DecayConstructor.fh \
+NBodyDecayConstructorBase.h \
NBodyDecayConstructorBase.fh \
-TwoBodyDecayConstructor.cc TwoBodyDecayConstructor.h \
+TwoBodyDecayConstructor.h \
TwoToTwoProcessConstructor.h TwoToTwoProcessConstructor.fh \
+HardProcessConstructor.h HardProcessConstructor.fh \
+HiggsVectorBosonProcessConstructor.h \
+HiggsVBFProcessConstructor.h \
+QQHiggsProcessConstructor.h \
+HPDiagram.h \
+ThreeBodyDecayConstructor.h \
+FourBodyDecayConstructor.h \
+WeakCurrentDecayConstructor.h \
+ResonantProcessConstructor.h \
+ResonantProcessConstructor.fh \
+VVSLoopVertex.fh VVSLoopVertex.h \
+GenericHGGVertex.h \
+GenericHPPVertex.h \
+BSMWidthGenerator.h BSMWidthGenerator.fh \
+PrototypeVertex.h \
+TBDiagram.h TwoBodyDecay.h\
+BSMModel.h
+
+ALL_CC_FILES = \
+ModelGenerator.cc\
+DecayConstructor.cc \
+NBodyDecayConstructorBase.cc \
+TwoBodyDecayConstructor.cc \
TwoToTwoProcessConstructor.cc \
-HardProcessConstructor.h HardProcessConstructor.fh \
HardProcessConstructor.cc \
-HiggsVectorBosonProcessConstructor.h \
HiggsVectorBosonProcessConstructor.cc \
-HiggsVBFProcessConstructor.h \
HiggsVBFProcessConstructor.cc \
-QQHiggsProcessConstructor.h \
QQHiggsProcessConstructor.cc \
-HPDiagram.h \
-ThreeBodyDecayConstructor.h ThreeBodyDecayConstructor.cc \
-FourBodyDecayConstructor.h FourBodyDecayConstructor.cc \
-WeakCurrentDecayConstructor.h WeakCurrentDecayConstructor.cc \
-ResonantProcessConstructor.cc ResonantProcessConstructor.h \
-ResonantProcessConstructor.fh \
-VVSLoopVertex.fh VVSLoopVertex.h VVSLoopVertex.cc \
-GenericHGGVertex.h GenericHGGVertex.cc \
-GenericHPPVertex.h GenericHPPVertex.cc \
-BSMWidthGenerator.h BSMWidthGenerator.fh BSMWidthGenerator.cc \
-PrototypeVertex.h PrototypeVertex.cc \
-TBDiagram.h TwoBodyDecay.h\
-BSMModel.h BSMModel.cc
+ThreeBodyDecayConstructor.cc \
+FourBodyDecayConstructor.cc \
+WeakCurrentDecayConstructor.cc \
+ResonantProcessConstructor.cc \
+VVSLoopVertex.cc \
+GenericHGGVertex.cc \
+GenericHPPVertex.cc \
+BSMWidthGenerator.cc \
+PrototypeVertex.cc \
+BSMModel.cc
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/Models/General/ResonantProcessConstructor.cc b/Models/General/ResonantProcessConstructor.cc
--- a/Models/General/ResonantProcessConstructor.cc
+++ b/Models/General/ResonantProcessConstructor.cc
@@ -1,388 +1,368 @@
// -*- C++ -*-
//
// ResonantProcessConstructor.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 ResonantProcessConstructor class.
//
#include "ResonantProcessConstructor.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
using namespace Herwig;
IBPtr ResonantProcessConstructor::clone() const {
return new_ptr(*this);
}
IBPtr ResonantProcessConstructor::fullclone() const {
return new_ptr(*this);
}
void ResonantProcessConstructor::persistentOutput(PersistentOStream & os) const {
os << incoming_ << intermediates_ << outgoing_
<< processOption_ << scaleChoice_ << scaleFactor_;
}
void ResonantProcessConstructor::persistentInput(PersistentIStream & is, int) {
is >> incoming_ >> intermediates_ >> outgoing_
>> processOption_ >> scaleChoice_ >> scaleFactor_;
}
ClassDescription<ResonantProcessConstructor>
ResonantProcessConstructor::initResonantProcessConstructor;
// Definition of the static class description member.
void ResonantProcessConstructor::Init() {
static ClassDocumentation<ResonantProcessConstructor> documentation
("This class is designed solely to contruct resonant processes using"
"a provided set of intermediate particles");
static RefVector<ResonantProcessConstructor, ParticleData> interfaceOffshell
("Intermediates",
"A vector of offshell particles for resonant diagrams",
&ResonantProcessConstructor::intermediates_, -1, false, false, true,
false);
static RefVector<ResonantProcessConstructor, ParticleData> interfaceIncoming
("Incoming",
"A vector of incoming particles for resonant diagrams",
&ResonantProcessConstructor::incoming_, -1, false, false, true,
false);
static RefVector<ResonantProcessConstructor, ParticleData> interfaceOutgoing
("Outgoing",
"A vector of outgoing particles for resonant diagrams",
&ResonantProcessConstructor::outgoing_, -1, false, false, true,
false);
static Switch<ResonantProcessConstructor,unsigned int> interfaceProcesses
("Processes",
"Whether to generate inclusive or exclusive processes",
&ResonantProcessConstructor::processOption_, 0, false, false);
static SwitchOption interfaceProcessesSingleParticleInclusive
(interfaceProcesses,
"SingleParticleInclusive",
"Require at least one particle from the list of outgoing particles"
" in the hard process",
0);
static SwitchOption interfaceProcessesTwoParticleInclusive
(interfaceProcesses,
"TwoParticleInclusive",
"Require that both the particles in the hard processes are in the"
" list of outgoing particles",
1);
static SwitchOption interfaceProcessesExclusive
(interfaceProcesses,
"Exclusive",
"Require that both the particles in the hard processes are in the"
" list of outgoing particles in every hard process",
2);
static SwitchOption interfaceProcessesInclusive
(interfaceProcesses,
"Inclusive",
"Generate all modes which are allowed for the on-shell intermediate particle",
3);
static Switch<ResonantProcessConstructor,unsigned int> interfaceScaleChoice
("ScaleChoice",
"&ResonantProcessConstructor::scaleChoice_",
&ResonantProcessConstructor::scaleChoice_, 1, false, false);
static SwitchOption interfaceScaleChoicesHat
(interfaceScaleChoice,
"sHat",
"Always use sHat",
1);
static SwitchOption interfaceScaleChoiceTransverseMass
(interfaceScaleChoice,
"TransverseMass",
"Always use the transverse mass",
2);
static SwitchOption interfaceScaleChoiceGeometicMean
(interfaceScaleChoice,
"MaxMT",
"Use the maximum of m^2+p_T^2 for the two particles",
3);
static Parameter<ResonantProcessConstructor,double> interfaceScaleFactor
("ScaleFactor",
"The prefactor used in the scale calculation. The scale used is"
" sHat multiplied by this prefactor",
&ResonantProcessConstructor::scaleFactor_, 1.0, 0.0, 10.0,
false, false, Interface::limited);
}
void ResonantProcessConstructor::doinit() {
HardProcessConstructor::doinit();
if(processOption_==2&&outgoing_.size()!=2)
throw InitException()
<< "Exclusive processes require exactly"
<< " two outgoing particles but " << outgoing_.size()
<< "have been inserted in ResonantProcessConstructor::doinit()."
<< Exception::runerror;
}
-namespace {
- // Helper functor for find_if in duplicate function.
- class SameIncomingAs {
- public:
- SameIncomingAs(tPDPair in) : a(in.first->id()), b(in.second->id()) {}
- bool operator()(tPDPair ppair) const {
- long id1(ppair.first->id()), id2(ppair.second->id());
- return ( id1 == a && id2 == b ) || ( id1 == b && id2 == a );
- }
- private:
- long a, b;
- };
-
- bool duplicateIncoming(tPDPair ppair,const vector<tPDPair> &incPairs) {
- vector<tPDPair>::const_iterator it =
- find_if( incPairs.begin(), incPairs.end(), SameIncomingAs(ppair) );
- return it != incPairs.end();
- }
-}
-
void ResonantProcessConstructor::constructDiagrams() {
size_t ninc = incoming_.size() , ninter = intermediates_.size();
if(ninc == 0 || ninter == 0 || !subProcess() ) return;
// find the incoming particle pairs
vector<tPDPair> incPairs;
for(PDVector::size_type i = 0; i < ninc; ++i) {
for(PDVector::size_type j = 0; j < ninc; ++j) {
tPDPair inc = make_pair(incoming_[i], incoming_[j]);
if( (inc.first->iSpin() > inc.second->iSpin()) ||
(inc.first->iSpin() == inc.second->iSpin() &&
inc.first->id() < inc.second->id()) )
swap(inc.first, inc.second);
- if( !duplicateIncoming(inc,incPairs) ) {
+ if( !HPC_helper::duplicateIncoming(inc,incPairs) ) {
incPairs.push_back(inc);
}
}
}
size_t nvertices = model()->numberOfVertices();
//To construct resonant diagrams loop over the incoming particles, intermediates
//and vertices to find allowed diagrams. Need to exclude the diagrams that have
//the intermediate as an external particle as well
for(vector<tcPDPair>::size_type is = 0; is < incPairs.size(); ++is) {
tPDPair ppi = incPairs[is];
for(vector<PDPtr>::size_type ik = 0; ik < ninter ; ++ik) {
long ipart = intermediates_[ik]->id();
for(size_t iv = 0; iv < nvertices; ++iv) {
VBPtr vertex = model()->vertex(iv);
if(vertex->getNpoint() > 3) continue;
long part1 = ppi.first->CC() ? -ppi.first->id() : ppi.first->id();
long part2 = ppi.second->CC() ? -ppi.second->id() : ppi.second->id();
if(vertex->allowed(part1, part2, ipart) ||
vertex->allowed(part1, ipart, part2) ||
vertex->allowed(part2, part1, ipart) ||
vertex->allowed(part2, ipart, part1) ||
vertex->allowed(ipart, part1, part2) ||
vertex->allowed(ipart, part2, part1) ) {
constructVertex2(make_pair(ppi.first->id(), ppi.second->id()), vertex,
intermediates_[ik]);
}
}
}
}
//Create matrix element for each process
const HPDVector::size_type ndiags = diagrams_.size();
for(HPDVector::size_type ix = 0; ix < ndiags; ++ix)
createMatrixElement(diagrams_[ix]);
}
void ResonantProcessConstructor::
constructVertex2(IDPair in, VertexBasePtr vertex,
PDPtr partc) {
//We have the left hand part of the diagram, just need all the possibilities
//for the RHS
size_t nvertices = model()->numberOfVertices();
if(processOption_!=3) {
for(size_t io = 0; io < outgoing_.size(); ++io) {
tcPDPtr outa = outgoing_[io];
for(size_t iv = 0; iv < nvertices; ++iv) {
VBPtr vertex2 = model()->vertex(iv);
if(vertex2->getNpoint() > 3) continue;
tPDSet outb = search(vertex2, partc->id(), incoming, outa->id(), outgoing,
outgoing);
for(tPDSet::const_iterator ita = outb.begin(); ita != outb.end(); ++ita)
makeResonantDiagram(in, partc, outa->id(),(**ita).id(),
make_pair(vertex, vertex2));
}
}
}
else {
long idRes = !partc->CC() ? partc->id() : partc->CC()->id();
for(size_t iv = 0; iv < nvertices; ++iv) {
VBPtr vertex2 = model()->vertex(iv);
if(vertex2->getNpoint() > 3) continue;
for(unsigned int ix = 0;ix < 3; ++ix) {
vector<long> pdlist = vertex2->search(ix, idRes);
for(unsigned int iy=0;iy<pdlist.size();iy+=3) {
long out1 = ix==0 ? pdlist.at(iy+1) : pdlist.at(iy );
long out2 = ix==2 ? pdlist.at(iy+1) : pdlist.at(iy+2);
if(partc->mass() < getParticleData(out1)->mass() +
getParticleData(out2)->mass()) continue;
makeResonantDiagram(in, partc, out1, out2,
make_pair(vertex, vertex2));
}
}
}
}
}
void ResonantProcessConstructor::
makeResonantDiagram(IDPair in, PDPtr offshell, long outa, long outb,
VBPair vertpair) {
assert(vertpair.first && vertpair.second);
if( abs(outa) == abs(offshell->id()) ||
abs(outb) == abs(offshell->id())) return;
HPDiagram newdiag(in,make_pair(outa,outb));
newdiag.intermediate = offshell;
newdiag.vertices = vertpair;
newdiag.channelType = HPDiagram::sChannel;
fixFSOrder(newdiag);
assignToCF(newdiag);
if(duplicate(newdiag,diagrams_)) return;
// if inclusive enforce the exclusivity
if(processOption_==1) {
PDVector::const_iterator loc =
std::find(outgoing_.begin(),outgoing_.end(),
getParticleData(newdiag.outgoing. first));
if(loc==outgoing_.end()) return;
loc =
std::find(outgoing_.begin(),outgoing_.end(),
getParticleData(newdiag.outgoing.second));
if(loc==outgoing_.end()) return;
}
else if(processOption_==2) {
if(!((newdiag.outgoing. first==outgoing_[0]->id()&&
newdiag.outgoing.second==outgoing_[1]->id())||
(newdiag.outgoing. first==outgoing_[1]->id()&&
newdiag.outgoing.second==outgoing_[0]->id())))
return;
}
// add to the list
diagrams_.push_back(newdiag);
}
set<tPDPtr>
ResonantProcessConstructor::search(VBPtr vertex, long part1, direction d1,
long part2, direction d2, direction d3) {
if(d1 == incoming && getParticleData(part1)->CC()) part1 = -part1;
if(d2 == incoming && getParticleData(part2)->CC()) part2 = -part2;
vector<long> ext;
tPDSet third;
for(unsigned int ix = 0;ix < 3; ++ix) {
vector<long> pdlist = vertex->search(ix, part1);
ext.insert(ext.end(), pdlist.begin(), pdlist.end());
}
for(unsigned int ix = 0; ix < ext.size(); ix += 3) {
long id0 = ext.at(ix);
long id1 = ext.at(ix+1);
long id2 = ext.at(ix+2);
int pos;
if((id0 == part1 && id1 == part2) ||
(id0 == part2 && id1 == part1))
pos = ix + 2;
else if((id0 == part1 && id2 == part2) ||
(id0 == part2 && id2 == part1))
pos = ix + 1;
else if((id1 == part1 && id2 == part2) ||
(id1 == part2 && id2 == part1))
pos = ix;
else
pos = -1;
if(pos >= 0) {
tPDPtr p = getParticleData(ext[pos]);
if(d3 == incoming && p->CC()) p = p->CC();
third.insert(p);
}
}
return third;
}
IDPair ResonantProcessConstructor::
find(long part, const vector<PDPtr> & out) const {
vector<PDPtr>::size_type iloc(0);
bool found(false);
do {
if(out[iloc]->id() == part) found = true;
else ++iloc;
}
while(found == false && iloc < out.size());
//found offshell
IDPair outids;
if(iloc == 0)
outids = make_pair(out[1]->id(), out[2]->id());
else if(iloc == 1)
outids = make_pair(out[0]->id(), out[2]->id());
else
outids = make_pair(out[0]->id(), out[1]->id());
return outids;
}
void ResonantProcessConstructor::
createMatrixElement(const HPDiagram & diag) const {
vector<tcPDPtr> extpart(4);
extpart[0] = getParticleData(diag.incoming.first);
extpart[1] = getParticleData(diag.incoming.second);
extpart[2] = getParticleData(diag.outgoing.first);
extpart[3] = getParticleData(diag.outgoing.second);
string objectname ("/Herwig/MatrixElements/");
string classname = MEClassname(extpart, diag.intermediate, objectname);
GeneralHardMEPtr matrixElement = dynamic_ptr_cast<GeneralHardMEPtr>
(generator()->preinitCreate(classname, objectname));
if( !matrixElement ) {
throw RPConstructorError()
<< "ResonantProcessConstructor::createMatrixElement "
<< "- No matrix element object could be created for "
<< "the process "
<< extpart[0]->PDGName() << " " << extpart[0]->iSpin() << ","
<< extpart[1]->PDGName() << " " << extpart[1]->iSpin() << "->"
<< extpart[2]->PDGName() << " " << extpart[2]->iSpin() << ","
<< extpart[3]->PDGName() << " " << extpart[3]->iSpin()
<< ". Constructed class name: \"" << classname << "\"\n"
<< Exception::warning;
return;
}
matrixElement->setProcessInfo(HPDVector(1, diag),
colourFlow(extpart), debug(),scaleChoice_-1,scaleFactor_);
generator()->preinitInterface(subProcess(), "MatrixElements",
subProcess()->MEs().size(),
"insert", matrixElement->fullName());
}
string ResonantProcessConstructor::
MEClassname(const vector<tcPDPtr> & extpart, tcPDPtr inter,
string & objname) const {
string classname("Herwig::ME");
for(vector<tcPDPtr>::size_type ix = 0; ix < extpart.size(); ++ix) {
if(ix == 2) classname += "2";
if(extpart[ix]->iSpin() == PDT::Spin0) classname += "s";
else if(extpart[ix]->iSpin() == PDT::Spin1) classname += "v";
else if(extpart[ix]->iSpin() == PDT::Spin1Half) classname += "f";
else if(extpart[ix]->iSpin() == PDT::Spin2) classname += "t";
else
throw RPConstructorError()
<< "MEClassname() : Encountered an unknown spin for "
<< extpart[ix]->PDGName() << " while constructing MatrixElement "
<< "classname " << extpart[ix]->iSpin() << Exception::warning;
}
objname += "ME" + extpart[0]->PDGName() + extpart[1]->PDGName() + "2"
+ inter->PDGName() + "2"
+ extpart[2]->PDGName() + extpart[3]->PDGName();
return classname;
}
diff --git a/Models/General/TwoToTwoProcessConstructor.cc b/Models/General/TwoToTwoProcessConstructor.cc
--- a/Models/General/TwoToTwoProcessConstructor.cc
+++ b/Models/General/TwoToTwoProcessConstructor.cc
@@ -1,650 +1,617 @@
// -*- C++ -*-
//
// TwoToTwoProcessConstructor.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 TwoToTwoProcessConstructor class.
//
#include "TwoToTwoProcessConstructor.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include <sstream>
using std::stringstream;
using namespace Herwig;
-namespace {
- // Helper functor for find_if in duplicate function.
- class SameIncomingAs {
- public:
- SameIncomingAs(tPDPair in) : a(in.first->id()), b(in.second->id()) {}
- bool operator()(tPDPair ppair) const {
- long id1(ppair.first->id()), id2(ppair.second->id());
- return ( id1 == a && id2 == b ) || ( id1 == b && id2 == a );
- }
- private:
- long a, b;
- };
-
- bool duplicateIncoming(tPDPair ppair, const vector<tPDPair> & incPairs ) {
- vector<tPDPair>::const_iterator it =
- find_if( incPairs.begin(), incPairs.end(), SameIncomingAs(ppair) );
- return it != incPairs.end();
- }
-}
-
TwoToTwoProcessConstructor::TwoToTwoProcessConstructor() :
Nout_(0), nv_(0), allDiagrams_(true),
processOption_(0), scaleChoice_(0), scaleFactor_(1.)
{}
IBPtr TwoToTwoProcessConstructor::clone() const {
return new_ptr(*this);
}
IBPtr TwoToTwoProcessConstructor::fullclone() const {
return new_ptr(*this);
}
void TwoToTwoProcessConstructor::doinit() {
HardProcessConstructor::doinit();
if(processOption_==2&&outgoing_.size()!=2)
throw InitException()
<< "Exclusive processes require exactly"
<< " two outgoing particles but " << outgoing_.size()
<< "have been inserted in TwoToTwoProcessConstructor::doinit()."
<< Exception::runerror;
Nout_ = outgoing_.size();
PDVector::size_type ninc = incoming_.size();
// exit if nothing to do
if(Nout_==0||ninc==0) return;
//create vector of initial-state pairs
for(PDVector::size_type i = 0; i < ninc; ++i) {
for(PDVector::size_type j = 0; j < ninc; ++j) {
tPDPair inc = make_pair(incoming_[i], incoming_[j]);
if( (inc.first->iSpin() > inc.second->iSpin()) ||
(inc.first->iSpin() == inc.second->iSpin() &&
inc.first->id() < inc.second->id()) )
swap(inc.first, inc.second);
- if( !duplicateIncoming(inc,incPairs_) ) {
+ if( !HPC_helper::duplicateIncoming(inc,incPairs_) ) {
incPairs_.push_back(inc);
}
}
}
// excluded vertices
excludedVertexSet_ =
set<VertexBasePtr>(excludedVertexVector_.begin(),
excludedVertexVector_.end());
}
void TwoToTwoProcessConstructor::persistentOutput(PersistentOStream & os) const {
os << vertices_ << incoming_ << outgoing_
<< allDiagrams_ << processOption_
<< scaleChoice_ << scaleFactor_ << excluded_ << excludedExternal_
<< excludedVertexVector_ << excludedVertexSet_;
}
void TwoToTwoProcessConstructor::persistentInput(PersistentIStream & is, int) {
is >> vertices_ >> incoming_ >> outgoing_
>> allDiagrams_ >> processOption_
>> scaleChoice_ >> scaleFactor_ >> excluded_ >> excludedExternal_
>> excludedVertexVector_ >> excludedVertexSet_;
}
ClassDescription<TwoToTwoProcessConstructor>
TwoToTwoProcessConstructor::initTwoToTwoProcessConstructor;
// Definition of the static class description member.
void TwoToTwoProcessConstructor::Init() {
static ClassDocumentation<TwoToTwoProcessConstructor> documentation
("TwoToTwoProcessConstructor constructs the possible diagrams for "
"a process given the external particles");
static RefVector<TwoToTwoProcessConstructor,ThePEG::ParticleData> interfaceIn
("Incoming",
"Pointers to incoming particles",
&TwoToTwoProcessConstructor::incoming_, -1, false, false, true, false);
static RefVector<TwoToTwoProcessConstructor,ThePEG::ParticleData> interfaceOut
("Outgoing",
"Pointers to incoming particles",
&TwoToTwoProcessConstructor::outgoing_, -1, false, false, true, false);
static Switch<TwoToTwoProcessConstructor,bool> interfaceIncludeAllDiagrams
("IncludeEW",
"Switch to decide which diagrams to include in ME calc.",
&TwoToTwoProcessConstructor::allDiagrams_, true, false, false);
static SwitchOption interfaceIncludeAllDiagramsOff
(interfaceIncludeAllDiagrams,
"No",
"Only include QCD diagrams",
false);
static SwitchOption interfaceIncludeAllDiagramsOn
(interfaceIncludeAllDiagrams,
"Yes",
"Include EW+QCD.",
true);
static Switch<TwoToTwoProcessConstructor,unsigned int> interfaceProcesses
("Processes",
"Whether to generate inclusive or exclusive processes",
&TwoToTwoProcessConstructor::processOption_, 0, false, false);
static SwitchOption interfaceProcessesSingleParticleInclusive
(interfaceProcesses,
"SingleParticleInclusive",
"Require at least one particle from the list of outgoing particles"
" in the hard process",
0);
static SwitchOption interfaceProcessesTwoParticleInclusive
(interfaceProcesses,
"TwoParticleInclusive",
"Require that both the particles in the hard processes are in the"
" list of outgoing particles",
1);
static SwitchOption interfaceProcessesExclusive
(interfaceProcesses,
"Exclusive",
"Require that both the particles in the hard processes are in the"
" list of outgoing particles in every hard process",
2);
static Switch<TwoToTwoProcessConstructor,unsigned int> interfaceScaleChoice
("ScaleChoice",
"&TwoToTwoProcessConstructor::scaleChoice_",
&TwoToTwoProcessConstructor::scaleChoice_, 0, false, false);
static SwitchOption interfaceScaleChoiceDefault
(interfaceScaleChoice,
"Default",
"Use if sHat if intermediates all colour neutral, otherwise the transverse mass",
0);
static SwitchOption interfaceScaleChoicesHat
(interfaceScaleChoice,
"sHat",
"Always use sHat",
1);
static SwitchOption interfaceScaleChoiceTransverseMass
(interfaceScaleChoice,
"TransverseMass",
"Always use the transverse mass",
2);
static SwitchOption interfaceScaleChoiceGeometicMean
(interfaceScaleChoice,
"MaxMT",
"Use the maximum of m^2+p_T^2 for the two particles",
3);
static Parameter<TwoToTwoProcessConstructor,double> interfaceScaleFactor
("ScaleFactor",
"The prefactor used in the scale calculation. The scale used is"
" that defined by scaleChoice multiplied by this prefactor",
&TwoToTwoProcessConstructor::scaleFactor_, 1.0, 0.0, 10.0,
false, false, Interface::limited);
static RefVector<TwoToTwoProcessConstructor,ThePEG::ParticleData> interfaceExcluded
("Excluded",
"Particles which are not allowed as intermediates",
&TwoToTwoProcessConstructor::excluded_, -1, false, false, true, false, false);
static RefVector<TwoToTwoProcessConstructor,ParticleData> interfaceExcludedExternal
("ExcludedExternal",
"Particles which are not allowed as outgoing particles",
&TwoToTwoProcessConstructor::excludedExternal_, -1,
false, false, true, false, false);
static RefVector<TwoToTwoProcessConstructor,VertexBase> interfaceExcludedVertices
("ExcludedVertices",
"Vertices which are not included in the 2 -> 2 scatterings",
&TwoToTwoProcessConstructor::excludedVertexVector_, -1, false, false, true, true, false);
}
-namespace {
- // Helper functor for find_if below.
- class SameProcessAs {
- public:
- SameProcessAs(const HPDiagram & diag) : a(diag) {}
- bool operator()(const HPDiagram & b) const {
- return a.sameProcess(b);
- }
- private:
- HPDiagram a;
- };
-}
-
void TwoToTwoProcessConstructor::constructDiagrams() {
if(incPairs_.empty() || outgoing_.empty() || !subProcess() ) return;
nv_ = model()->numberOfVertices();
//make sure vertices are initialised
for(unsigned int ix = 0; ix < nv_; ++ix ) {
VertexBasePtr vertex = model()->vertex(ix);
if(excludedVertexSet_.find(vertex) !=
excludedVertexSet_.end()) continue;
vertices_.push_back(vertex);
}
nv_ = vertices_.size();
//Create necessary diagrams
vector<tcPDPair>::size_type is;
PDVector::size_type os;
for(is = 0; is < incPairs_.size(); ++is) {
tPDPair ppi = incPairs_[is];
for(os = 0; os < Nout_; ++os) {
long fs = outgoing_[os]->id();
for(size_t iv = 0; iv < nv_; ++iv) {
tVertexBasePtr vertexA = vertices_[iv];
//This skips an effective vertex and the EW ones if
// we only want the strong diagrams
if( !allDiagrams_ && vertexA->orderInGs() == 0 )
continue;
if(vertexA->getNpoint() == 3) {
//scattering diagrams
createTChannels(ppi, fs, vertexA);
//resonance diagrams
if( vertexA->isIncoming(ppi.first) &&
vertexA->isIncoming(ppi.second) )
createSChannels(ppi, fs, vertexA);
}
else
makeFourPointDiagrams(ppi.first->id(), ppi.second->id(),
fs, vertexA);
}
}
}
//need to find all of the diagrams that relate to the same process
//first insert them into a map which uses the '<' operator
//to sort the diagrams
multiset<HPDiagram> grouped;
HPDVector::iterator dit = processes_.begin();
HPDVector::iterator dend = processes_.end();
bool abort=false;
for( ; dit != dend; ++dit) {
// check for on-shell s-channel
tPDPtr out1 = getParticleData(dit->outgoing.first );
tPDPtr out2 = getParticleData(dit->outgoing.second);
if(dit->channelType == HPDiagram::sChannel &&
dit->intermediate->width()==ZERO &&
dit->intermediate->mass() > out1->mass()+ out2->mass()) {
tPDPtr in1 = getParticleData(dit->incoming.first );
tPDPtr in2 = getParticleData(dit->incoming.second);
generator()->log() << dit->intermediate->PDGName()
<< " can be on-shell in the process "
<< in1 ->PDGName() << " " << in2->PDGName() << " -> "
<< out1->PDGName() << " " << out2->PDGName()
<< " but has zero width.\nEither set the width, enable "
<< "calculation of its decays, and hence the width,\n"
<< "or disable it as a potential intermediate using\n"
<< "insert " << fullName() << ":Excluded 0 "
<< dit->intermediate->fullName() << "\n---\n";
abort = true;
}
grouped.insert(*dit);
}
if(abort) throw Exception() << "One or more processes with zero width"
<< " resonant intermediates"
<< Exception::runerror;
assert( processes_.size() == grouped.size() );
processes_.clear();
typedef multiset<HPDiagram>::const_iterator set_iter;
set_iter it = grouped.begin(), iend = grouped.end();
while( it != iend ) {
pair<set_iter,set_iter> range = grouped.equal_range(*it);
set_iter itb = range.first;
HPDVector process;
for( ; itb != range.second; ++itb ) {
process.push_back(*itb);
}
// if inclusive enforce the exclusivity
if(processOption_==2) {
if(!((process[0].outgoing. first==outgoing_[0]->id()&&
process[0].outgoing.second==outgoing_[1]->id())||
(process[0].outgoing. first==outgoing_[1]->id()&&
process[0].outgoing.second==outgoing_[0]->id()))) {
process.clear();
it = range.second;
continue;
}
}
if(find(excludedExternal_.begin(),excludedExternal_.end(),
getParticleData(process[0].outgoing. first))!=excludedExternal_.end()) {
process.clear();
it = range.second;
continue;
}
if(find(excludedExternal_.begin(),excludedExternal_.end(),
getParticleData(process[0].outgoing.second))!=excludedExternal_.end()) {
process.clear();
it = range.second;
continue;
}
// finally if the process is allow assign the colour flows
for(unsigned int ix=0;ix<process.size();++ix) assignToCF(process[ix]);
// create the matrix element
createMatrixElement(process);
process.clear();
it = range.second;
}
}
void TwoToTwoProcessConstructor::
createSChannels(tcPDPair inpp, long fs, tVertexBasePtr vertex) {
//Have 2 incoming particle and a vertex, find the possible offshell
//particles
pair<long,long> inc = make_pair(inpp.first->id(), inpp.second->id());
tPDSet offshells = search(vertex, inpp.first->id(), incoming,
inpp.second->id(), incoming, outgoing);
tPDSet::const_iterator it;
for(it = offshells.begin(); it != offshells.end(); ++it) {
if(find(excluded_.begin(),excluded_.end(),*it)!=excluded_.end()) continue;
for(size_t iv = 0; iv < nv_; ++iv) {
tVertexBasePtr vertexB = vertices_[iv];
if( vertexB->getNpoint() != 3) continue;
if( !allDiagrams_ && vertexB->orderInGs() == 0 ) continue;
tPDSet final;
if( vertexB->isOutgoing(getParticleData(fs)) &&
vertexB->isIncoming(*it) )
final = search(vertexB, (*it)->id(), incoming, fs,
outgoing, outgoing);
//Now make diagrams
if(!final.empty())
makeDiagrams(inc, fs, final, *it, HPDiagram::sChannel,
make_pair(vertex, vertexB), make_pair(true,true));
}
}
}
void TwoToTwoProcessConstructor::
createTChannels(tPDPair inpp, long fs, tVertexBasePtr vertex) {
pair<long,long> inc = make_pair(inpp.first->id(), inpp.second->id());
//first try a with c
tPDSet offshells = search(vertex, inpp.first->id(), incoming, fs,
outgoing, outgoing);
tPDSet::const_iterator it;
for(it = offshells.begin(); it != offshells.end(); ++it) {
if(find(excluded_.begin(),excluded_.end(),*it)!=excluded_.end()) continue;
for(size_t iv = 0; iv < nv_; ++iv) {
tVertexBasePtr vertexB = vertices_[iv];
if( vertexB->getNpoint() != 3 ) continue;
if( !allDiagrams_ && vertexB->orderInGs() == 0 ) continue;
tPDSet final;
if( vertexB->isIncoming(inpp.second) )
final = search(vertexB, inc.second, incoming, (*it)->id(),
incoming, outgoing);
if( !final.empty() )
makeDiagrams(inc, fs, final, *it, HPDiagram::tChannel,
make_pair(vertex, vertexB), make_pair(true,true));
}
}
//now try b with c
offshells = search(vertex, inpp.second->id(), incoming, fs,
outgoing, incoming);
for(it = offshells.begin(); it != offshells.end(); ++it) {
if(find(excluded_.begin(),excluded_.end(),*it)!=excluded_.end()) continue;
for(size_t iv = 0; iv < nv_; ++iv) {
tVertexBasePtr vertexB = vertices_[iv];
if( vertexB->getNpoint() != 3 ) continue;
if( !allDiagrams_ && vertexB->orderInGs() == 0 ) continue;
tPDSet final;
if( vertexB->isIncoming(inpp.first) )
final = search(vertexB, inc.first, incoming, (*it)->id(),
outgoing, outgoing);
if( !final.empty() )
makeDiagrams(inc, fs, final, *it, HPDiagram::tChannel,
make_pair(vertexB, vertex), make_pair(true, false));
}
}
}
void TwoToTwoProcessConstructor::makeFourPointDiagrams(long parta, long partb,
long partc, VBPtr vert) {
if(processOption_>=1) {
PDVector::const_iterator loc = find(outgoing_.begin(),outgoing_.end(),
getParticleData(partc));
if(loc==outgoing_.end()) return;
}
tPDSet ext = search(vert, parta, incoming, partb,incoming, partc, outgoing);
if( ext.empty() ) return;
IDPair in(parta, partb);
for(tPDSet::const_iterator iter=ext.begin(); iter!=ext.end();
++iter) {
if(processOption_>=1) {
PDVector::const_iterator loc = find(outgoing_.begin(),outgoing_.end(),
*iter);
if(loc==outgoing_.end()) continue;
}
HPDiagram nhp(in,make_pair(partc, (*iter)->id()));
nhp.vertices = make_pair(vert, vert);
nhp.channelType = HPDiagram::fourPoint;
fixFSOrder(nhp);
if( !duplicate(nhp, processes_) ) processes_.push_back(nhp);
}
}
void
TwoToTwoProcessConstructor::makeDiagrams(IDPair in, long out1, const tPDSet & out2,
PDPtr inter, HPDiagram::Channel chan,
VBPair vertexpair, BPair cross) {
if(processOption_>=1) {
PDVector::const_iterator loc = find(outgoing_.begin(),outgoing_.end(),
getParticleData(out1));
if(loc==outgoing_.end()) return;
}
for(tPDSet::const_iterator it = out2.begin(); it != out2.end(); ++it) {
if(processOption_>=1) {
PDVector::const_iterator loc = find(outgoing_.begin(),outgoing_.end(),
*it);
if(loc==outgoing_.end()) continue;
}
HPDiagram nhp( in,make_pair(out1, (*it)->id()) );
nhp.intermediate = inter;
nhp.vertices = vertexpair;
nhp.channelType = chan;
nhp.ordered = cross;
fixFSOrder(nhp);
if( !duplicate(nhp, processes_) ) processes_.push_back(nhp);
}
}
set<tPDPtr>
TwoToTwoProcessConstructor::search(VBPtr vertex, long part1, direction d1,
long part2, direction d2, direction d3) {
if(vertex->getNpoint() != 3) return tPDSet();
if(d1 == incoming && getParticleData(part1)->CC()) part1 = -part1;
if(d2 == incoming && getParticleData(part2)->CC()) part2 = -part2;
vector<long> ext;
tPDSet third;
for(unsigned int ix = 0;ix < 3; ++ix) {
vector<long> pdlist = vertex->search(ix, part1);
ext.insert(ext.end(), pdlist.begin(), pdlist.end());
}
for(unsigned int ix = 0; ix < ext.size(); ix += 3) {
long id0 = ext.at(ix);
long id1 = ext.at(ix+1);
long id2 = ext.at(ix+2);
int pos;
if((id0 == part1 && id1 == part2) ||
(id0 == part2 && id1 == part1))
pos = ix + 2;
else if((id0 == part1 && id2 == part2) ||
(id0 == part2 && id2 == part1))
pos = ix + 1;
else if((id1 == part1 && id2 == part2) ||
(id1 == part2 && id2 == part1))
pos = ix;
else
pos = -1;
if(pos >= 0) {
tPDPtr p = getParticleData(ext[pos]);
if(d3 == incoming && p->CC()) p = p->CC();
third.insert(p);
}
}
return third;
}
set<tPDPtr>
TwoToTwoProcessConstructor::search(VBPtr vertex,
long part1, direction d1,
long part2, direction d2,
long part3, direction d3,
direction d4) {
if(vertex->getNpoint() != 4) return tPDSet();
if(d1 == incoming && getParticleData(part1)->CC()) part1 = -part1;
if(d2 == incoming && getParticleData(part2)->CC()) part2 = -part2;
if(d3 == incoming && getParticleData(part3)->CC()) part3 = -part3;
vector<long> ext;
tPDSet fourth;
for(unsigned int ix = 0;ix < 4; ++ix) {
vector<long> pdlist = vertex->search(ix, part1);
ext.insert(ext.end(), pdlist.begin(), pdlist.end());
}
for(unsigned int ix = 0;ix < ext.size(); ix += 4) {
long id0 = ext.at(ix); long id1 = ext.at(ix + 1);
long id2 = ext.at(ix + 2); long id3 = ext.at(ix + 3);
int pos;
if((id0 == part1 && id1 == part2 && id2 == part3) ||
(id0 == part1 && id1 == part3 && id2 == part2) ||
(id0 == part2 && id1 == part1 && id2 == part3) ||
(id0 == part2 && id1 == part3 && id2 == part1) ||
(id0 == part3 && id1 == part1 && id2 == part2) ||
(id0 == part3 && id1 == part2 && id2 == part1))
pos = ix + 3;
else if((id0 == part1 && id1 == part2 && id3 == part3) ||
(id0 == part1 && id1 == part3 && id3 == part2) ||
(id0 == part2 && id1 == part1 && id3 == part3) ||
(id0 == part2 && id1 == part3 && id3 == part1) ||
(id0 == part3 && id1 == part1 && id3 == part2) ||
(id0 == part3 && id1 == part2 && id3 == part1))
pos = ix + 2;
else if((id0 == part1 && id2 == part2 && id3 == part3) ||
(id0 == part1 && id2 == part3 && id3 == part2) ||
(id0 == part2 && id2 == part1 && id3 == part3) ||
(id0 == part2 && id2 == part3 && id3 == part1) ||
(id0 == part3 && id2 == part1 && id3 == part2) ||
(id0 == part3 && id2 == part2 && id3 == part1))
pos = ix + 1;
else if((id1 == part1 && id2 == part2 && id3 == part3) ||
(id1 == part1 && id2 == part3 && id3 == part2) ||
(id1 == part2 && id2 == part1 && id3 == part3) ||
(id1 == part2 && id2 == part3 && id3 == part1) ||
(id1 == part3 && id2 == part1 && id3 == part2) ||
(id1 == part3 && id2 == part2 && id3 == part1))
pos = ix;
else
pos = -1;
if(pos >= 0) {
tPDPtr p = getParticleData(ext[pos]);
if(d4 == incoming && p->CC())
p = p->CC();
fourth.insert(p);
}
}
return fourth;
}
void
TwoToTwoProcessConstructor::createMatrixElement(const HPDVector & process) const {
if ( process.empty() ) return;
// external particles
tcPDVector extpart(4);
extpart[0] = getParticleData(process[0].incoming.first);
extpart[1] = getParticleData(process[0].incoming.second);
extpart[2] = getParticleData(process[0].outgoing.first);
extpart[3] = getParticleData(process[0].outgoing.second);
// create the object
string objectname ("/Herwig/MatrixElements/");
string classname = MEClassname(extpart, objectname);
GeneralHardMEPtr matrixElement = dynamic_ptr_cast<GeneralHardMEPtr>
(generator()->preinitCreate(classname, objectname));
if( !matrixElement ) {
std::stringstream message;
message << "TwoToTwoProcessConstructor::createMatrixElement "
<< "- No matrix element object could be created for "
<< "the process "
<< extpart[0]->PDGName() << " " << extpart[0]->iSpin() << ","
<< extpart[1]->PDGName() << " " << extpart[1]->iSpin() << "->"
<< extpart[2]->PDGName() << " " << extpart[2]->iSpin() << ","
<< extpart[3]->PDGName() << " " << extpart[3]->iSpin()
<< ". Constructed class name: \"" << classname << "\"";
generator()->logWarning(TwoToTwoProcessConstructorError(message.str(),Exception::warning));
return;
}
// choice for the scale
unsigned int scale;
if(scaleChoice_==0) {
// check coloured initial and final state
bool inColour = ( extpart[0]->coloured() ||
extpart[1]->coloured());
bool outColour = ( extpart[2]->coloured() ||
extpart[3]->coloured());
if(inColour&&outColour) {
bool coloured = false;
for(unsigned int ix=0;ix<process.size();++ix) {
if(process[ix].intermediate&&
process[ix].intermediate->coloured()) {
coloured = true;
break;
}
}
scale = coloured ? 1 : 0;
}
else {
scale = 0;
}
}
else {
scale = scaleChoice_-1;
}
// set the information
matrixElement->setProcessInfo(process, colourFlow(extpart),
debug(), scale, scaleFactor_);
// insert it
generator()->preinitInterface(subProcess(), "MatrixElements",
subProcess()->MEs().size(),
"insert", matrixElement->fullName());
}
string TwoToTwoProcessConstructor::MEClassname(const vector<tcPDPtr> & extpart,
string & objname) const {
string classname("Herwig::ME");
for(vector<tcPDPtr>::size_type ix = 0; ix < extpart.size(); ++ix) {
if(ix == 2) classname += "2";
if(extpart[ix]->iSpin() == PDT::Spin0) classname += "s";
else if(extpart[ix]->iSpin() == PDT::Spin1) classname += "v";
else if(extpart[ix]->iSpin() == PDT::Spin1Half) classname += "f";
else if(extpart[ix]->iSpin() == PDT::Spin2) classname += "t";
else {
std::stringstream message;
message << "MEClassname() : Encountered an unknown spin for "
<< extpart[ix]->PDGName() << " while constructing MatrixElement "
<< "classname " << extpart[ix]->iSpin();
generator()->logWarning(TwoToTwoProcessConstructorError(message.str(),Exception::warning));
}
}
objname += "ME" + extpart[0]->PDGName() + extpart[1]->PDGName() + "2"
+ extpart[2]->PDGName() + extpart[3]->PDGName();
return classname;
}
diff --git a/Models/LH/Makefile.am b/Models/LH/Makefile.am
--- a/Models/LH/Makefile.am
+++ b/Models/LH/Makefile.am
@@ -1,16 +1,33 @@
-if WANT_BSM
-pkglib_LTLIBRARIES = HwLHModel.la
-endif
-HwLHModel_la_SOURCES = \
-LHModel.h LHModel.fh LHModel.cc \
-LHFFZVertex.h LHFFZVertex.cc \
-LHFFPVertex.h LHFFPVertex.cc \
-LHFFGVertex.h LHFFGVertex.cc \
-LHFFWVertex.h LHFFWVertex.cc \
-LHWWWVertex.h LHWWWVertex.cc \
-LHWWWWVertex.h LHWWWWVertex.cc \
-LHFFHVertex.h LHFFHVertex.cc \
-LHWWHVertex.h LHWWHVertex.cc \
-LHWHHVertex.h LHWHHVertex.cc \
-LHWWHHVertex.h LHWWHHVertex.cc
-HwLHModel_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 4:0:0
+BUILT_SOURCES = LH__all.cc
+DISTCLEANFILES = LH__all.cc
+
+LH__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+LHModel.h LHModel.fh \
+LHFFZVertex.h \
+LHFFPVertex.h \
+LHFFGVertex.h \
+LHFFWVertex.h \
+LHWWWVertex.h \
+LHWWWWVertex.h \
+LHFFHVertex.h \
+LHWWHVertex.h \
+LHWHHVertex.h \
+LHWWHHVertex.h
+
+ALL_CC_FILES = \
+LHModel.cc \
+LHFFZVertex.cc \
+LHFFPVertex.cc \
+LHFFGVertex.cc \
+LHFFWVertex.cc \
+LHWWWVertex.cc \
+LHWWWWVertex.cc \
+LHFFHVertex.cc \
+LHWWHVertex.cc \
+LHWHHVertex.cc \
+LHWWHHVertex.cc
diff --git a/Models/LHTP/Makefile.am b/Models/LHTP/Makefile.am
--- a/Models/LHTP/Makefile.am
+++ b/Models/LHTP/Makefile.am
@@ -1,17 +1,31 @@
-if WANT_BSM
-pkglib_LTLIBRARIES = HwLHTPModel.la
-endif
-HwLHTPModel_la_SOURCES = \
-LHTPModel.fh LHTPModel.cc LHTPModel.h \
-LHTPWWHVertex.cc LHTPWWHVertex.h \
-LHTPFFGVertex.cc LHTPFFGVertex.h \
-LHTPFFPVertex.cc LHTPFFPVertex.h \
-LHTPFFWVertex.cc LHTPFFWVertex.h \
-LHTPFFZVertex.cc LHTPFFZVertex.h \
-LHTPWWWVertex.cc LHTPWWWVertex.h \
-LHTPHHHVertex.cc LHTPHHHVertex.h \
-LHTPWHHVertex.cc LHTPWHHVertex.h \
-LHTPFFHVertex.cc LHTPFFHVertex.h
-HwLHTPModel_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 4:0:0
-HwLHTPModel_la_LIBADD= $(GSLLIBS)
-HwLHTPModel_la_CPPFLAGS= $(AM_CPPFLAGS) $(GSLINCLUDE)
+BUILT_SOURCES = LHTP__all.cc
+DISTCLEANFILES = LHTP__all.cc
+
+LHTP__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+LHTPModel.fh LHTPModel.h \
+LHTPWWHVertex.h \
+LHTPFFGVertex.h \
+LHTPFFPVertex.h \
+LHTPFFWVertex.h \
+LHTPFFZVertex.h \
+LHTPWWWVertex.h \
+LHTPHHHVertex.h \
+LHTPWHHVertex.h \
+LHTPFFHVertex.h
+
+ALL_CC_FILES = \
+LHTPModel.cc \
+LHTPWWHVertex.cc \
+LHTPFFGVertex.cc \
+LHTPFFPVertex.cc \
+LHTPFFWVertex.cc \
+LHTPFFZVertex.cc \
+LHTPWWWVertex.cc \
+LHTPHHHVertex.cc \
+LHTPWHHVertex.cc \
+LHTPFFHVertex.cc
diff --git a/Models/Leptoquarks/Makefile.am b/Models/Leptoquarks/Makefile.am
--- a/Models/Leptoquarks/Makefile.am
+++ b/Models/Leptoquarks/Makefile.am
@@ -1,10 +1,19 @@
-if WANT_BSM
-pkglib_LTLIBRARIES = HwLeptoquarkModel.la
-endif
-HwLeptoquarkModel_la_SOURCES = \
-LeptoquarkModel.cc LeptoquarkModel.h LeptoquarkModel.fh \
-LeptoquarkModelSLQSLQGGVertex.h LeptoquarkModelSLQSLQGGVertex.cc \
-LeptoquarkModelSLQFFVertex.h LeptoquarkModelSLQFFVertex.cc \
-LeptoquarkModelSLQSLQGVertex.h LeptoquarkModelSLQSLQGVertex.cc
+BUILT_SOURCES = Leptoquark__all.cc
+DISTCLEANFILES = Leptoquark__all.cc
-HwLeptoquarkModel_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 4:0:0
+Leptoquark__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+LeptoquarkModel.h LeptoquarkModel.fh \
+LeptoquarkModelSLQSLQGGVertex.h \
+LeptoquarkModelSLQFFVertex.h \
+LeptoquarkModelSLQSLQGVertex.h
+
+ALL_CC_FILES = \
+LeptoquarkModel.cc \
+LeptoquarkModelSLQSLQGGVertex.cc \
+LeptoquarkModelSLQFFVertex.cc \
+LeptoquarkModelSLQSLQGVertex.cc
diff --git a/Models/Makefile.am b/Models/Makefile.am
--- a/Models/Makefile.am
+++ b/Models/Makefile.am
@@ -1,3 +1,144 @@
SUBDIRS = RSModel StandardModel General Susy UED Zprime \
Transplanckian ADD Leptoquarks Sextet TTbAsymm \
LH LHTP Feynrules
+
+noinst_LTLIBRARIES = libHwStandardModel.la
+libHwStandardModel_la_SOURCES = \
+StandardModel/SM__all.cc
+
+noinst_LTLIBRARIES += libHwModelGenerator.la
+libHwModelGenerator_la_SOURCES = \
+General/ModelGenerator__all.cc
+
+
+
+if WANT_BSM
+
+pkglib_LTLIBRARIES = \
+HwRSModel.la \
+HwUED.la \
+HwSusy.la \
+HwNMSSM.la \
+HwRPV.la \
+HwZprimeModel.la \
+HwTransplanck.la \
+HwADDModel.la \
+HwLeptoquarkModel.la \
+HwSextetModel.la \
+HwTTbAModel.la \
+HwLHModel.la \
+HwLHTPModel.la
+
+endif
+
+#############
+
+HwRSModel_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 9:0:0
+
+HwRSModel_la_SOURCES = \
+RSModel/RS__all.cc
+
+#############
+
+HwUED_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 9:0:0
+
+HwUED_la_SOURCES = \
+UED/UED__all.cc
+
+#############
+
+HwSusy_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 11:0:0
+
+HwSusy_la_SOURCES = \
+Susy/Susy__all.cc
+
+#############
+
+HwNMSSM_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 4:0:0
+
+HwNMSSM_la_SOURCES = \
+Susy/NMSSM/NMSSM__all.cc
+
+#############
+
+HwRPV_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 2:0:0
+
+HwRPV_la_SOURCES = \
+Susy/RPV/RPV__all.cc
+
+#############
+
+HwZprimeModel_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 2:0:0
+
+HwZprimeModel_la_SOURCES = \
+Zprime/ZprimeModel.cc Zprime/ZprimeModelZPQQVertex.cc
+
+#############
+
+HwTransplanck_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 3:0:0
+
+HwTransplanck_la_SOURCES = \
+Transplanckian/METRP2to2.cc
+
+#############
+
+HwADDModel_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 3:0:0
+
+HwADDModel_la_SOURCES = \
+ADD/ADD__all.cc
+
+#############
+
+HwLeptoquarkModel_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 4:0:0
+
+HwLeptoquarkModel_la_SOURCES = \
+Leptoquarks/Leptoquark__all.cc
+
+#############
+
+HwSextetModel_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 2:0:0
+
+HwSextetModel_la_SOURCES = \
+Sextet/Sextet__all.cc
+
+#############
+
+HwTTbAModel_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 2:0:0
+
+HwTTbAModel_la_SOURCES = \
+TTbAsymm/TTbA__all.cc
+
+#############
+
+HwLHModel_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 4:0:0
+
+HwLHModel_la_SOURCES = \
+LH/LH__all.cc
+
+#############
+
+HwLHTPModel_la_CPPFLAGS = \
+$(AM_CPPFLAGS) $(GSLINCLUDE)
+
+HwLHTPModel_la_LDFLAGS = \
+$(AM_LDFLAGS) -module -version-info 4:0:0
+
+HwLHTPModel_la_LIBADD = \
+$(GSLLIBS)
+
+HwLHTPModel_la_SOURCES = \
+LHTP/LHTP__all.cc
+
+#############
diff --git a/Models/RSModel/Makefile.am b/Models/RSModel/Makefile.am
--- a/Models/RSModel/Makefile.am
+++ b/Models/RSModel/Makefile.am
@@ -1,12 +1,27 @@
-if WANT_BSM
-pkglib_LTLIBRARIES = HwRSModel.la
-endif
-HwRSModel_la_SOURCES = RSModel.fh RSModel.cc RSModel.h \
-RSModelFFGRVertex.cc RSModelFFGRVertex.h \
-RSModelFFGGRVertex.cc RSModelFFGGRVertex.h \
-RSModelFFWGRVertex.cc RSModelFFWGRVertex.h \
-RSModelSSGRVertex.cc RSModelSSGRVertex.h \
-RSModelVVGRVertex.cc RSModelVVGRVertex.h \
-RSModelWWWGRVertex.cc RSModelWWWGRVertex.h\
-RSModelGGGGRVertex.cc RSModelGGGGRVertex.h
-HwRSModel_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 9:0:0
+BUILT_SOURCES = RS__all.cc
+DISTCLEANFILES = RS__all.cc
+
+RS__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+RSModel.fh RSModel.h \
+RSModelFFGRVertex.h \
+RSModelFFGGRVertex.h \
+RSModelFFWGRVertex.h \
+RSModelSSGRVertex.h \
+RSModelVVGRVertex.h \
+RSModelWWWGRVertex.h \
+RSModelGGGGRVertex.h
+
+ALL_CC_FILES = \
+RSModel.cc \
+RSModelFFGRVertex.cc \
+RSModelFFGGRVertex.cc \
+RSModelFFWGRVertex.cc \
+RSModelSSGRVertex.cc \
+RSModelVVGRVertex.cc \
+RSModelWWWGRVertex.cc \
+RSModelGGGGRVertex.cc
diff --git a/Models/Sextet/Makefile.am b/Models/Sextet/Makefile.am
--- a/Models/Sextet/Makefile.am
+++ b/Models/Sextet/Makefile.am
@@ -1,13 +1,26 @@
-if WANT_BSM
-pkglib_LTLIBRARIES = HwSextetModel.la
-endif
-HwSextetModel_la_SOURCES = SextetParticles.h \
-SextetModel.cc SextetModel.h SextetModel.fh \
-SextetGSSVertex.cc SextetGSSVertex.h \
-SextetGGSSVertex.cc SextetGGSSVertex.h \
-SextetGVVVertex.cc SextetGVVVertex.h \
-SextetGGVVVertex.cc SextetGGVVVertex.h \
-SextetFFSVertex.cc SextetFFSVertex.h \
-SextetFFVVertex.cc SextetFFVVertex.h
+BUILT_SOURCES = Sextet__all.cc
+DISTCLEANFILES = Sextet__all.cc
-HwSextetModel_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 2:0:0
+Sextet__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+SextetParticles.h \
+SextetModel.h SextetModel.fh \
+SextetGSSVertex.h \
+SextetGGSSVertex.h \
+SextetGVVVertex.h \
+SextetGGVVVertex.h \
+SextetFFSVertex.h \
+SextetFFVVertex.h
+
+ALL_CC_FILES = \
+SextetModel.cc \
+SextetGSSVertex.cc \
+SextetGGSSVertex.cc \
+SextetGVVVertex.cc \
+SextetGGVVVertex.cc \
+SextetFFSVertex.cc \
+SextetFFVVertex.cc
diff --git a/Models/StandardModel/Makefile.am b/Models/StandardModel/Makefile.am
--- a/Models/StandardModel/Makefile.am
+++ b/Models/StandardModel/Makefile.am
@@ -1,24 +1,55 @@
-noinst_LTLIBRARIES = libHwStandardModel.la
-libHwStandardModel_la_SOURCES = \
- StandardModel.fh StandardModel.h StandardModel.cc\
- RunningMassBase.h RunningMassBase.cc \
- RunningMass.h RunningMass.cc\
- StandardCKM.h StandardCKM.cc \
- O2AlphaS.h O2AlphaS.cc \
- AlphaEM.h AlphaEM.cc \
- SMFFGVertex.cc SMFFGVertex.h \
- SMFFHVertex.cc SMFFHVertex.h \
- SMFFPVertex.cc SMFFPVertex.h \
- SMFFWVertex.cc SMFFWVertex.h \
- SMFFZVertex.cc SMFFZVertex.h \
- SMGGGGVertex.cc SMGGGGVertex.h \
- SMGGGVertex.cc SMGGGVertex.h \
- SMWWHVertex.cc SMWWHVertex.h \
- SMWWWVertex.cc SMWWWVertex.h \
- SMWWWWVertex.cc SMWWWWVertex.h \
- SMHGGVertex.cc SMHGGVertex.h \
- SMHPPVertex.cc SMHPPVertex.h\
- SMHHHVertex.cc SMHHHVertex.h \
- SMWWHHVertex.cc SMWWHHVertex.h \
- GenericSVVVertex.cc GenericSVVVertex.h \
- GenericVVVVertex.cc GenericVVVVertex.h
+BUILT_SOURCES = SM__all.cc
+DISTCLEANFILES = SM__all.cc
+
+SM__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+StandardModel.fh StandardModel.h \
+RunningMassBase.h \
+RunningMass.h \
+StandardCKM.h \
+O2AlphaS.h \
+AlphaEM.h \
+SMFFGVertex.h \
+SMFFHVertex.h \
+SMFFPVertex.h \
+SMFFWVertex.h \
+SMFFZVertex.h \
+SMGGGGVertex.h \
+SMGGGVertex.h \
+SMWWHVertex.h \
+SMWWWVertex.h \
+SMWWWWVertex.h \
+SMHGGVertex.h \
+SMHPPVertex.h\
+SMHHHVertex.h \
+SMWWHHVertex.h \
+GenericSVVVertex.h \
+GenericVVVVertex.h
+
+ALL_CC_FILES = \
+StandardModel.cc\
+RunningMassBase.cc \
+RunningMass.cc\
+StandardCKM.cc \
+O2AlphaS.cc \
+AlphaEM.cc \
+SMFFGVertex.cc \
+SMFFHVertex.cc \
+SMFFPVertex.cc \
+SMFFWVertex.cc \
+SMFFZVertex.cc \
+SMGGGGVertex.cc \
+SMGGGVertex.cc \
+SMWWHVertex.cc \
+SMWWWVertex.cc \
+SMWWWWVertex.cc \
+SMHGGVertex.cc \
+SMHPPVertex.cc \
+SMHHHVertex.cc \
+SMWWHHVertex.cc \
+GenericSVVVertex.cc \
+GenericVVVVertex.cc
diff --git a/Models/Susy/Makefile.am b/Models/Susy/Makefile.am
--- a/Models/Susy/Makefile.am
+++ b/Models/Susy/Makefile.am
@@ -1,34 +1,71 @@
SUBDIRS = NMSSM RPV
-if WANT_BSM
-pkglib_LTLIBRARIES = HwSusy.la
-endif
-HwSusy_la_SOURCES = SusyBase.cc SusyBase.h SusyBase.fh \
-MSSM.cc MSSM.h MSSM.fh\
-MixingMatrix.h MixingMatrix.fh MixingMatrix.cc\
-SSCFSVertex.cc SSCFSVertex.h \
-SSGFSVertex.cc SSGFSVertex.h \
-SSHSFSFVertex.cc SSHSFSFVertex.h \
-SSNFSVertex.cc SSNFSVertex.h \
-SSWSSVertex.cc SSWSSVertex.h \
-SSWGSSVertex.cc SSWGSSVertex.h \
-SSGSSVertex.cc SSGSSVertex.h \
-SSGGSQSQVertex.cc SSGGSQSQVertex.h \
-SSGSGSGVertex.cc SSGSGSGVertex.h \
-SSNNZVertex.cc SSNNZVertex.h \
-SSCCZVertex.cc SSCCZVertex.h \
-SSCNWVertex.cc SSCNWVertex.h \
-SSFFHVertex.cc SSFFHVertex.h \
-SSGOGOHVertex.cc SSGOGOHVertex.h \
-SSWWHVertex.cc SSWWHVertex.h \
-SSWWHHVertex.cc SSWWHHVertex.h \
-SSWHHVertex.cc SSWHHVertex.h \
-SSHHHVertex.cc SSHHHVertex.h \
-SSHGGVertex.cc SSHGGVertex.h \
-SSHPPVertex.cc SSHPPVertex.h \
-SSNNPVertex.h SSNNPVertex.cc \
-SSGNGVertex.h SSGNGVertex.cc \
-SSNCTVertex.h SSNCTVertex.cc \
-SSGVNHVertex.h SSGVNHVertex.cc\
-SSGVNVVertex.h SSGVNVVertex.cc\
-SSGVFSVertex.h SSGVFSVertex.cc
-HwSusy_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 11:0:0
+
+BUILT_SOURCES = Susy__all.cc
+DISTCLEANFILES = Susy__all.cc
+
+Susy__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+SusyBase.h SusyBase.fh \
+MSSM.h MSSM.fh\
+MixingMatrix.h MixingMatrix.fh \
+SSCFSVertex.h \
+SSGFSVertex.h \
+SSHSFSFVertex.h \
+SSNFSVertex.h \
+SSWSSVertex.h \
+SSWGSSVertex.h \
+SSGSSVertex.h \
+SSGGSQSQVertex.h \
+SSGSGSGVertex.h \
+SSNNZVertex.h \
+SSCCZVertex.h \
+SSCNWVertex.h \
+SSFFHVertex.h \
+SSGOGOHVertex.h \
+SSWWHVertex.h \
+SSWWHHVertex.h \
+SSWHHVertex.h \
+SSHHHVertex.h \
+SSHGGVertex.h \
+SSHPPVertex.h \
+SSNNPVertex.h \
+SSGNGVertex.h \
+SSNCTVertex.h \
+SSGVNHVertex.h \
+SSGVNVVertex.h \
+SSGVFSVertex.h
+
+ALL_CC_FILES = \
+SusyBase.cc \
+MSSM.cc \
+MixingMatrix.cc\
+SSCFSVertex.cc \
+SSGFSVertex.cc \
+SSHSFSFVertex.cc \
+SSNFSVertex.cc \
+SSWSSVertex.cc \
+SSWGSSVertex.cc \
+SSGSSVertex.cc \
+SSGGSQSQVertex.cc \
+SSGSGSGVertex.cc \
+SSNNZVertex.cc \
+SSCCZVertex.cc \
+SSCNWVertex.cc \
+SSFFHVertex.cc \
+SSGOGOHVertex.cc \
+SSWWHVertex.cc \
+SSWWHHVertex.cc \
+SSWHHVertex.cc \
+SSHHHVertex.cc \
+SSHGGVertex.cc \
+SSHPPVertex.cc \
+SSNNPVertex.cc \
+SSGNGVertex.cc \
+SSNCTVertex.cc \
+SSGVNHVertex.cc\
+SSGVNVVertex.cc\
+SSGVFSVertex.cc
diff --git a/Models/Susy/NMSSM/Makefile.am b/Models/Susy/NMSSM/Makefile.am
--- a/Models/Susy/NMSSM/Makefile.am
+++ b/Models/Susy/NMSSM/Makefile.am
@@ -1,15 +1,31 @@
-if WANT_BSM
-pkglib_LTLIBRARIES = HwNMSSM.la
-endif
-HwNMSSM_la_SOURCES = \
-NMSSM.cc NMSSM.h NMSSM.fh \
-NMSSMFFHVertex.h NMSSMFFHVertex.cc \
-NMSSMWWHVertex.h NMSSMWWHVertex.cc \
-NMSSMWHHVertex.h NMSSMWHHVertex.cc \
-NMSSMHSFSFVertex.h NMSSMHSFSFVertex.cc\
-NMSSMGOGOHVertex.h NMSSMGOGOHVertex.cc \
-NMSSMHHHVertex.h NMSSMHHHVertex.cc \
-NMSSMGGHVertex.h NMSSMGGHVertex.cc \
-NMSSMPPHVertex.h NMSSMPPHVertex.cc \
-NMSSMWWHHVertex.h NMSSMWWHHVertex.cc
-HwNMSSM_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 4:0:0
+BUILT_SOURCES = NMSSM__all.cc
+DISTCLEANFILES = NMSSM__all.cc
+
+NMSSM__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+NMSSM.h NMSSM.fh \
+NMSSMFFHVertex.h \
+NMSSMWWHVertex.h \
+NMSSMWHHVertex.h \
+NMSSMHSFSFVertex.h \
+NMSSMGOGOHVertex.h \
+NMSSMHHHVertex.h \
+NMSSMGGHVertex.h \
+NMSSMPPHVertex.h \
+NMSSMWWHHVertex.h
+
+ALL_CC_FILES = \
+NMSSM.cc \
+NMSSMFFHVertex.cc \
+NMSSMWWHVertex.cc \
+NMSSMWHHVertex.cc \
+NMSSMHSFSFVertex.cc\
+NMSSMGOGOHVertex.cc \
+NMSSMHHHVertex.cc \
+NMSSMGGHVertex.cc \
+NMSSMPPHVertex.cc \
+NMSSMWWHHVertex.cc
diff --git a/Models/Susy/RPV/Makefile.am b/Models/Susy/RPV/Makefile.am
--- a/Models/Susy/RPV/Makefile.am
+++ b/Models/Susy/RPV/Makefile.am
@@ -1,15 +1,32 @@
-if WANT_BSM
-pkglib_LTLIBRARIES = HwRPV.la
-endif
-HwRPV_la_SOURCES = \
-RPV.cc RPV.h RPV.fh \
-RPVLLEVertex.h RPVLLEVertex.cc\
-RPVLQDVertex.h RPVLQDVertex.cc\
-RPVUDDVertex.h RPVUDDVertex.cc\
-RPVFFZVertex.h RPVFFZVertex.cc\
-RPVFFWVertex.h RPVFFWVertex.cc\
-RPVWSSVertex.h RPVWSSVertex.cc\
-RPVFFSVertex.h RPVFFSVertex.cc\
-RPVWWHVertex.h RPVWWHVertex.cc\
-RPVSSSVertex.h RPVSSSVertex.cc
-HwRPV_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 2:0:0
+BUILT_SOURCES = RPV__all.cc
+DISTCLEANFILES = RPV__all.cc
+
+RPV__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+RPV.h RPV.fh \
+RPVhelper.h \
+RPVLLEVertex.h \
+RPVLQDVertex.h \
+RPVUDDVertex.h \
+RPVFFZVertex.h \
+RPVFFWVertex.h \
+RPVWSSVertex.h \
+RPVFFSVertex.h \
+RPVWWHVertex.h \
+RPVSSSVertex.h
+
+ALL_CC_FILES = \
+RPV.cc \
+RPVLLEVertex.cc\
+RPVLQDVertex.cc\
+RPVUDDVertex.cc\
+RPVFFZVertex.cc\
+RPVFFWVertex.cc\
+RPVWSSVertex.cc\
+RPVFFSVertex.cc\
+RPVWWHVertex.cc\
+RPVSSSVertex.cc
diff --git a/Models/Susy/RPV/RPVFFWVertex.cc b/Models/Susy/RPV/RPVFFWVertex.cc
--- a/Models/Susy/RPV/RPVFFWVertex.cc
+++ b/Models/Susy/RPV/RPVFFWVertex.cc
@@ -1,286 +1,267 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the RPVFFWVertex class.
//
#include "RPVFFWVertex.h"
#include "ThePEG/Interface/ClassDocumentation.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/Models/StandardModel/StandardCKM.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
+#include "RPVhelper.h"
using namespace Herwig;
-namespace {
-
- unsigned int neutralinoIndex(long id) {
- if(id> 1000000) {
- return id<1000025 ? id-1000022 : (id-1000005)/10;
- }
- else if(abs(id)<=16) {
- return (abs(id)-4)/2;
- }
- else {
- return id-13;
- }
- }
-
- unsigned int charginoIndex(long id) {
- return abs(id)>1000000 ? (abs(id)-1000024)/13 : (abs(id)-7)/2;
- }
-
-}
-
RPVFFWVertex::RPVFFWVertex() : _diagonal(false), _ckm(3,vector<Complex>(3,0.0)),
_sw(0.), _couplast(0.), _q2last(ZERO),
_id1last(0), _id2last(0), _leftlast(0.),
_rightlast(0.), _interactions(0) {
orderInGs(0);
orderInGem(1);
}
IBPtr RPVFFWVertex::clone() const {
return new_ptr(*this);
}
IBPtr RPVFFWVertex::fullclone() const {
return new_ptr(*this);
}
void RPVFFWVertex::doinit() {
// SUSY mixing matrices
tSusyBasePtr model = dynamic_ptr_cast<SusyBasePtr>(generator()->standardModel());
if(!model)
throw InitException() << "RPVFFWVertex::doinit() - The model pointer is null!"
<< Exception::abortnow;
_theN = model->neutralinoMix();
_theU = model->charginoUMix();
_theV = model->charginoVMix();
if(!_theN || !_theU || ! _theV)
throw InitException() << "RPVFFWVertex::doinit() - "
<< "A mixing matrix pointer is null."
<< " N: " << _theN << " U: " << _theU << " V: "
<< _theV << Exception::abortnow;
// SM interactions
if(_interactions==0 || _interactions==1) {
// particles for outgoing W-
// quarks
for(int ix=1;ix<6;ix+=2) {
for(int iy=2;iy<7;iy+=2) {
bool isOff = iy/2 != (ix+1)/2;
if ( isOff && _diagonal )
continue;
addToList(-ix, iy, -24);
}
}
// leptons
for(int ix=11;ix<17;ix+=2) {
int inu = model->majoranaNeutrinos() ? (ix+23)/2 : ix+1;
addToList(-ix, inu, -24);
}
// particles for outgoing W+
// quarks
for(int ix=2;ix<7;ix+=2) {
for(int iy=1;iy<6;iy+=2) {
bool isOff = ix/2 != (iy+1)/2;
if ( isOff && _diagonal )
continue;
addToList(-ix, iy, 24);
}
}
// leptons
for(int ix=11;ix<17;ix+=2) {
int inu = model->majoranaNeutrinos() ? (ix+23)/2 : -ix-1;
addToList(inu, ix, 24);
}
}
// neutralino and chargino
if(_interactions==0 || _interactions==2) {
vector<long> neu(4);
neu[0] = 1000022; neu[1] = 1000023;
neu[2] = 1000025; neu[3] = 1000035;
if(_theN->size().first==7) {
if(model->majoranaNeutrinos()) {
neu.push_back(17);
neu.push_back(18);
neu.push_back(19);
}
else {
neu.push_back(12);
neu.push_back(14);
neu.push_back(16);
}
}
vector<long> cha(2);
cha[0] = 1000024; cha[1] = 1000037;
if(_theV->size().first==5) {
cha.push_back(-11);
cha.push_back(-13);
cha.push_back(-15);
}
// sign == -1 outgoing W-, sign == +1 outgoing W+
for(int sign = -1; sign < 2; sign += 2) {
for(unsigned int ine = 0; ine < neu.size(); ++ine) {
for(unsigned int ic = 0; ic < cha.size(); ++ic ) {
if(ic>1&&ine>3&&ic==ine-2) continue;
addToList(-sign*cha[ic], neu[ine], sign*24);
}
}
}
}
Helicity::FFVVertex::doinit();
// CKM matric
if ( !_diagonal ) {
Ptr<CKMBase>::transient_pointer CKM = model->CKM();
// cast the CKM object to the HERWIG one
ThePEG::Ptr<Herwig::StandardCKM>::transient_const_pointer
hwCKM = ThePEG::dynamic_ptr_cast< ThePEG::Ptr<Herwig::StandardCKM>::
transient_const_pointer>(CKM);
if(hwCKM) {
vector< vector<Complex > > CKM;
CKM = hwCKM->getUnsquaredMatrix(generator()->standardModel()->families());
for(unsigned int ix=0;ix<3;++ix) {
for(unsigned int iy=0;iy<3;++iy) {
_ckm[ix][iy]=CKM[ix][iy];
}
}
}
else {
throw Exception() << "Must have access to the Herwig::StandardCKM object"
<< "for the CKM matrix in RPVFFWVertex::doinit()"
<< Exception::runerror;
}
}
_sw = sqrt(sin2ThetaW());
}
void RPVFFWVertex::persistentOutput(PersistentOStream & os) const {
os << _sw << _theN << _theU << _theV << _diagonal << _ckm << _interactions;
}
void RPVFFWVertex::persistentInput(PersistentIStream & is, int) {
is >> _sw >> _theN >> _theU >> _theV >> _diagonal >> _ckm >> _interactions;
}
// The following static variable is needed for the type
// description system in ThePEG.
DescribeClass<RPVFFWVertex,Helicity::FFVVertex>
describeHerwigRPVFFWVertex("Herwig::RPVFFWVertex", "HwSusy.so HwRPV.so");
void RPVFFWVertex::Init() {
static ClassDocumentation<RPVFFWVertex> documentation
("The couplings of the fermions to the W boson in the RPV model"
" with bilinear R-parity violation");
static Switch<RPVFFWVertex,unsigned int> interfaceInteractions
("Interactions",
"Which interactions to include",
&RPVFFWVertex::_interactions, 0, false, false);
static SwitchOption interfaceInteractionsAll
(interfaceInteractions,
"All",
"Include all the interactions",
0);
static SwitchOption interfaceInteractionsSM
(interfaceInteractions,
"SM",
"Only include the MS terms",
1);
static SwitchOption interfaceInteractionsSUSY
(interfaceInteractions,
"SUSY",
"Include the neutralino/chargino terms",
2);
static Switch<RPVFFWVertex,bool> interfaceDiagonal
("Diagonal",
"Use a diagonal CKM matrix (ignoring the CKM object of the StandardModel).",
&RPVFFWVertex::_diagonal, false, false, false);
static SwitchOption interfaceDiagonalYes
(interfaceDiagonal,
"Yes",
"Use a diagonal CKM matrix.",
true);
static SwitchOption interfaceDiagonalNo
(interfaceDiagonal,
"No",
"Use the CKM object as used by the StandardModel.",
false);
}
void RPVFFWVertex::setCoupling(Energy2 q2,tcPDPtr part1,
tcPDPtr part2,tcPDPtr part3) {
assert(abs(part3->id()) == ParticleID::Wplus);
// normalization
// first the overall normalisation
if(q2 != _q2last||_couplast==0.) {
_couplast = weakCoupling(q2);
_q2last=q2;
}
norm(_couplast);
// left and right couplings for quarks
if(abs(part1->id()) <= 6) {
int iferm=abs(part1->id());
int ianti=abs(part2->id());
if(iferm%2!=0) swap(iferm,ianti);
iferm = iferm/2;
ianti = (ianti+1)/2;
assert( iferm>=1 && iferm<=3 && ianti>=1 && ianti<=3);
left(-sqrt(0.5)*_ckm[iferm-1][ianti-1]);
right(0.);
}
else {
long neu, cha;
if(part1->charged()) {
cha = part1->id();
neu = part2->id();
}
else {
cha = part2->id();
neu = part1->id();
}
if(_theV->size().first==2&&abs(neu)<=16) {
left(-sqrt(0.5));
right(0.);
}
else {
if(cha != _id1last || neu != _id2last) {
_id1last = cha;
_id2last = neu;
- unsigned int eigc = charginoIndex(cha);
- unsigned int eign = neutralinoIndex(neu);
+ unsigned int eigc = RPV_helper::charginoIndex(cha);
+ unsigned int eign = RPV_helper::neutralinoIndex(neu);
_leftlast = (*_theN)(eign, 1)*conj((*_theV)(eigc, 0)) -
( (*_theN)(eign, 3)*conj((*_theV)(eigc, 1))/sqrt(2));
_rightlast = conj((*_theN)(eign, 1))*(*_theU)(eigc, 0) +
( conj((*_theN)(eign, 2))*(*_theU)(eigc, 1)/sqrt(2));
if(_theV->size().first==5) {
for(unsigned int k=0;k<3;++k)
_rightlast += ( conj((*_theN)(eign, 4+k))*(*_theU)(eigc, 2+k)/sqrt(2));
}
}
Complex ltemp = _leftlast;
Complex rtemp = _rightlast;
bool chapart = abs(cha)>1000000 ? cha>0 : cha<0;
// conjugate if +ve chargino
if(chapart) {
ltemp = conj(ltemp);
rtemp = conj(rtemp);
}
if((part1->id()==cha&&chapart)||(part2->id()==cha&&!chapart)) {
Complex temp = ltemp;
ltemp = -rtemp;
rtemp = -temp;
}
left (ltemp);
right(rtemp);
}
}
}
diff --git a/Models/Susy/RPV/RPVFFZVertex.cc b/Models/Susy/RPV/RPVFFZVertex.cc
--- a/Models/Susy/RPV/RPVFFZVertex.cc
+++ b/Models/Susy/RPV/RPVFFZVertex.cc
@@ -1,308 +1,290 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the RPVFFZVertex class.
//
#include "RPVFFZVertex.h"
#include "ThePEG/Interface/ClassDocumentation.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/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
+#include "RPVhelper.h"
+
using namespace Herwig;
-namespace {
-
- unsigned int neutralinoIndex(long id) {
- if(id> 1000000) {
- return id<1000025 ? id-1000022 : (id-1000005)/10;
- }
- else if(abs(id)<=16) {
- return (abs(id)-4)/2;
- }
- else {
- return id-13;
- }
- }
-
- unsigned int charginoIndex(long id) {
- return abs(id)>1000000 ? (abs(id)-1000024)/13 : (abs(id)-7)/2;
- }
-
-}
-
RPVFFZVertex::RPVFFZVertex() : _sw(0.), _cw(0.), _id1last(0),
_id2last(0), _q2last(), _couplast(0.),
_leftlast(0.), _rightlast(0.),
_gl(17,0.0), _gr(17,0.0), _gblast(0),
_interactions(0) {
orderInGem(1);
orderInGs(0);
}
IBPtr RPVFFZVertex::clone() const {
return new_ptr(*this);
}
IBPtr RPVFFZVertex::fullclone() const {
return new_ptr(*this);
}
void RPVFFZVertex::persistentOutput(PersistentOStream & os) const {
os << _sw << _cw << _theN << _theU << _theV
<< _gl << _gr << _interactions;
}
void RPVFFZVertex::persistentInput(PersistentIStream & is, int) {
is >> _sw >> _cw >> _theN >> _theU >> _theV
>> _gl >> _gr >> _interactions;
}
// The following static variable is needed for the type
// description system in ThePEG.
DescribeClass<RPVFFZVertex,Helicity::FFVVertex>
describeHerwigRPVFFZVertex("Herwig::RPVFFZVertex", "HwSusy.so HwRPV.so");
void RPVFFZVertex::Init() {
static ClassDocumentation<RPVFFZVertex> documentation
("The RPVFFZVertex class implements trhe coupling of the Z to all"
" fermion-antifermion pairs in models with bilinear RPV.");
static Switch<RPVFFZVertex,unsigned int> interfaceInteractions
("Interactions",
"Which interactions to include",
&RPVFFZVertex::_interactions, 0, false, false);
static SwitchOption interfaceInteractionsAll
(interfaceInteractions,
"All",
"Include all the interactions",
0);
static SwitchOption interfaceInteractionsSM
(interfaceInteractions,
"SM",
"Only include what would have been the interactions with the SM"
" fermions in the absence of mixing",
1);
static SwitchOption interfaceInteractionsNeutralino
(interfaceInteractions,
"Neutralino",
"Only include what would have been the interactions with the "
"neutralinos in the absence of mixing",
2);
static SwitchOption interfaceInteractionsChargino
(interfaceInteractions,
"Chargino",
"Only include what would have been the interactions with the "
"charginos in the absence of mixing",
3);
}
void RPVFFZVertex::doinit() {
// extract the mixing matrices
tSusyBasePtr model = dynamic_ptr_cast<SusyBasePtr>(generator()->standardModel());
if(!model) throw InitException() << "RPVFFZVertex::doinit() - "
<< "The model pointer is null."
<< Exception::abortnow;
_theN = model->neutralinoMix();
_theU = model->charginoUMix();
_theV = model->charginoVMix();
if( !_theN || !_theU || !_theV )
throw InitException() << "RPVFFZVertex::doinit - "
<< "A mixing matrix pointer is null. U: "
<< _theU << " V: " << _theV << " N: " << _theN
<< Exception::abortnow;
// Standard Model fermions
if(_interactions==0||_interactions==1) {
// PDG codes for the particles
// the quarks
for(int ix=1;ix<7;++ix) {
addToList(-ix, ix, 23);
}
// the leptons
for(int ix=11;ix<17;ix+=2) {
addToList(-ix, ix, 23);
}
for(int ix=12;ix<17;ix+=2) {
if(_theN->size().first==7) {
long inu = (ix-12)/2+17;
addToList( inu, inu, 23);
}
else
addToList(-ix, ix, 23);
}
}
// neutralinos
if(_interactions==0||_interactions==2) {
vector<long> neu(4);
neu[0] = 1000022; neu[1] = 1000023;
neu[2] = 1000025; neu[3] = 1000035;
if(_theN->size().first==7) {
if(model->majoranaNeutrinos()) {
neu.push_back(17);
neu.push_back(18);
neu.push_back(19);
}
else {
neu.push_back(12);
neu.push_back(14);
neu.push_back(16);
}
}
for(unsigned int i = 0; i < neu.size(); ++i) {
for(unsigned int j = 0; j < neu.size(); ++j) {
if(!(i>3&&i==j)) addToList(neu[i], neu[j], 23);
}
}
}
// charginos
if(_interactions==0||_interactions==3) {
addToList(-1000024, 1000024, 22);
addToList(-1000037, 1000037, 22);
vector<long> cha(2);
cha[0] = 1000024; cha[1] = 1000037;
if(_theV->size().first==5) {
cha.push_back(-11);
cha.push_back(-13);
cha.push_back(-15);
}
for(unsigned int i = 0; i < cha.size(); ++i) {
for(unsigned int j = 0; j < cha.size(); ++j) {
if(!(i>1&&i==j)) addToList(-cha[i], cha[j], 23);
}
}
}
Helicity::FFVVertex::doinit();
// weak mixing
double sw2 = sin2ThetaW();
_cw = sqrt(1. - sw2);
_sw = sqrt( sw2 );
// Standard Model couplings
for(int ix=1;ix<4;++ix) {
_gl[2*ix-1] = -0.25*(model->vd() + model->ad() );
_gl[2*ix ] = -0.25*(model->vu() + model->au() );
_gl[2*ix+9 ] = -0.25*(model->ve() + model->ae() );
_gl[2*ix+10] = -0.25*(model->vnu() + model->anu());
_gr[2*ix-1] = -0.25*(model->vd() - model->ad() );
_gr[2*ix ] = -0.25*(model->vu() - model->au() );
_gr[2*ix+9 ] = -0.25*(model->ve() - model->ae() );
_gr[2*ix+10] = -0.25*(model->vnu() - model->anu());
}
}
void RPVFFZVertex::setCoupling(Energy2 q2,tcPDPtr part1,
tcPDPtr part2,tcPDPtr part3) {
// first the overall normalisation
if(q2!=_q2last||_couplast==0.) {
_couplast = electroMagneticCoupling(q2);
_q2last=q2;
}
long iferm1(part1->id()), iferm2(part2->id()), boson(part3->id());
long iferm = abs(iferm1);
// chargino coupling to the photon
if(part3->id()==ParticleID::gamma) {
assert(iferm == abs(iferm2));
_gblast = boson;
_id1last = iferm1;
_id2last = iferm2;
_leftlast = -1.;
_rightlast = -1.;
}
// coupling to the Z
else {
assert(part3->id()==ParticleID::Z0);
// quarks
if(iferm<=6) {
_leftlast = _gl[iferm]/(_sw*_cw);
_rightlast = _gr[iferm]/(_sw*_cw);
}
// charged leptons and charginos
else if(part1->iCharge()!=0) {
if(boson != _gblast || iferm1 != _id1last || iferm2 != _id2last) {
_gblast = boson;
_id1last = iferm1;
_id2last = iferm2;
unsigned int ic1(0);
if(_theV->size().first==2&&iferm<=16) {
_leftlast = -_gr[iferm];
_rightlast = -_gl[iferm];
}
else {
- ic1 = charginoIndex(iferm1);
- unsigned int ic2 = charginoIndex(iferm2);
+ ic1 = RPV_helper::charginoIndex(iferm1);
+ unsigned int ic2 = RPV_helper::charginoIndex(iferm2);
_leftlast = -(*_theV)(ic1, 0)*conj((*_theV)(ic2, 0)) -
0.5*(*_theV)(ic1, 1)*conj((*_theV)(ic2, 1));
_rightlast = -conj((*_theU)(ic1, 0))*(*_theU)(ic2, 0) -
0.5*conj((*_theU)(ic1, 1))*(*_theU)(ic2, 1);
if(abs(iferm1) == abs(iferm2)) {
_leftlast += sqr(_sw);
_rightlast += sqr(_sw);
}
if(_theV->size().first==5) {
for(unsigned int ix=0;ix<3;++ix) {
_rightlast += -0.5*(*_theU)(ic1, 2+ix)*conj((*_theU)(ic2, 2+ix));
}
}
}
if((ic1<2&&iferm1>0)||(ic1>=2&&iferm1<0)) {
Complex temp = _leftlast;
_leftlast = -_rightlast;
_rightlast = -temp;
}
Complex temp = _leftlast;
_leftlast = -_rightlast;
_rightlast = -temp;
_leftlast /= _sw*_cw;
_rightlast /= _sw*_cw;
}
}
// neutrinos and neutralinos
else {
// case where only 4x4 matrix and neutrino
if(_theN->size().first==4&&iferm<=16) {
assert(iferm==12||iferm==14||iferm==16);
_leftlast = _gl[iferm]/(_sw*_cw);
_rightlast = _gr[iferm]/(_sw*_cw);
}
// neutralino
else {
long ic1 = part2->id();
long ic2 = part1->id();
assert(ic1 == ParticleID::SUSY_chi_10 || ic1 == ParticleID::SUSY_chi_20 ||
ic1 == ParticleID::SUSY_chi_30 || ic1 == ParticleID::SUSY_chi_40 ||
abs(ic1) == 12 || abs(ic1) == 14 || abs(ic1) == 16 ||
abs(ic1) == 17 || abs(ic1) == 18 || abs(ic1) == 19 );
assert(ic2 == ParticleID::SUSY_chi_10 || ic2 == ParticleID::SUSY_chi_20 ||
ic2 == ParticleID::SUSY_chi_30 || ic2 == ParticleID::SUSY_chi_40 ||
abs(ic2) == 12 || abs(ic2) == 14 || abs(ic2) == 16 ||
abs(ic2) == 17 || abs(ic2) == 18 || abs(ic2) == 19 );
if(ic1 != _id1last || ic2 != _id2last) {
_id1last = ic1;
_id2last = ic2;
- unsigned int neu1 = neutralinoIndex(ic1);
- unsigned int neu2 = neutralinoIndex(ic2);
+ unsigned int neu1 = RPV_helper::neutralinoIndex(ic1);
+ unsigned int neu2 = RPV_helper::neutralinoIndex(ic2);
_leftlast = 0.5*( (*_theN)(neu1, 3)*conj((*_theN)(neu2, 3)) -
(*_theN)(neu1, 2)*conj((*_theN)(neu2, 2)) );
if(_theN->size().first>4) {
for(unsigned int k=0;k<3;++k)
_leftlast -= 0.5*(*_theN)(neu1, 4+k)*conj((*_theN)(neu2, 4+k));
}
_rightlast = -conj(_leftlast);
_leftlast /= _sw*_cw;
_rightlast /= _sw*_cw;
}
}
}
}
norm ( _couplast);
left ( _leftlast);
right(_rightlast);
}
diff --git a/Models/Susy/RPV/RPVhelper.h b/Models/Susy/RPV/RPVhelper.h
new file mode 100644
--- /dev/null
+++ b/Models/Susy/RPV/RPVhelper.h
@@ -0,0 +1,28 @@
+#ifndef HERWIG_RPV_HELPER_H
+#define HERWIG_RPV_HELPER_H
+
+namespace Herwig {
+
+namespace RPV_helper {
+
+ unsigned int neutralinoIndex(long id) {
+ if(id> 1000000) {
+ return id<1000025 ? id-1000022 : (id-1000005)/10;
+ }
+ else if(abs(id)<=16) {
+ return (abs(id)-4)/2;
+ }
+ else {
+ return id-13;
+ }
+ }
+
+ unsigned int charginoIndex(long id) {
+ return abs(id)>1000000 ? (abs(id)-1000024)/13 : (abs(id)-7)/2;
+ }
+
+}
+
+}
+
+#endif
diff --git a/Models/TTbAsymm/Makefile.am b/Models/TTbAsymm/Makefile.am
--- a/Models/TTbAsymm/Makefile.am
+++ b/Models/TTbAsymm/Makefile.am
@@ -1,11 +1,21 @@
-if WANT_BSM
-pkglib_LTLIBRARIES = HwTTbAModel.la
-endif
-HwTTbAModel_la_SOURCES = \
-TTbAModel.cc TTbAModel.h TTbAModel.fh \
-TTbAModelWPTDVertex.h TTbAModelWPTDVertex.cc \
-TTbAModelZPQQVertex.h TTbAModelZPQQVertex.cc \
-TTbAModelAGQQVertex.h TTbAModelAGQQVertex.cc \
-TTbAModelSU2XVertex.h TTbAModelSU2XVertex.cc
+BUILT_SOURCES = TTbA__all.cc
+DISTCLEANFILES = TTbA__all.cc
-HwTTbAModel_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 2:0:0
+TTbA__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+TTbAModel.h TTbAModel.fh \
+TTbAModelWPTDVertex.h \
+TTbAModelZPQQVertex.h \
+TTbAModelAGQQVertex.h \
+TTbAModelSU2XVertex.h
+
+ALL_CC_FILES = \
+TTbAModel.cc \
+TTbAModelWPTDVertex.cc \
+TTbAModelZPQQVertex.cc \
+TTbAModelAGQQVertex.cc \
+TTbAModelSU2XVertex.cc
diff --git a/Models/Transplanckian/Makefile.am b/Models/Transplanckian/Makefile.am
--- a/Models/Transplanckian/Makefile.am
+++ b/Models/Transplanckian/Makefile.am
@@ -1,5 +1,1 @@
-if WANT_BSM
-pkglib_LTLIBRARIES = HwTransplanck.la
-endif
-HwTransplanck_la_SOURCES = METRP2to2.cc METRP2to2.h
-HwTransplanck_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 3:0:0
+EXTRA_DIST = METRP2to2.cc METRP2to2.h
diff --git a/Models/UED/Makefile.am b/Models/UED/Makefile.am
--- a/Models/UED/Makefile.am
+++ b/Models/UED/Makefile.am
@@ -1,20 +1,41 @@
-if WANT_BSM
-pkglib_LTLIBRARIES = HwUED.la
-endif
-HwUED_la_SOURCES = \
-UEDBase.cc UEDBase.h UEDBase.fh \
-UEDF1F1Z0Vertex.cc UEDF1F1Z0Vertex.h \
-UEDF1F1G0Vertex.cc UEDF1F1G0Vertex.h \
-UEDF1F0G1Vertex.cc UEDF1F0G1Vertex.h \
-UEDG1G1G0Vertex.cc UEDG1G1G0Vertex.h \
-UEDG0G0G1G1Vertex.cc UEDG0G0G1G1Vertex.h \
-UEDF1F1P0Vertex.cc UEDF1F1P0Vertex.h \
-UEDF1F1W0Vertex.cc UEDF1F1W0Vertex.h \
-UEDF1F0W1Vertex.cc UEDF1F0W1Vertex.h \
-UEDP0H1H1Vertex.cc UEDP0H1H1Vertex.h \
-UEDZ0H1H1Vertex.cc UEDZ0H1H1Vertex.h \
-UEDW0A1H1Vertex.cc UEDW0A1H1Vertex.h \
-UEDZ0A1h1Vertex.cc UEDZ0A1h1Vertex.h \
-UEDW0W1W1Vertex.cc UEDW0W1W1Vertex.h \
-UEDF1F0H1Vertex.cc UEDF1F0H1Vertex.h
-HwUED_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 9:0:0
+BUILT_SOURCES = UED__all.cc
+DISTCLEANFILES = UED__all.cc
+
+UED__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_H_FILES) $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+UEDBase.h UEDBase.fh \
+UEDF1F1Z0Vertex.h \
+UEDF1F1G0Vertex.h \
+UEDF1F0G1Vertex.h \
+UEDG1G1G0Vertex.h \
+UEDG0G0G1G1Vertex.h \
+UEDF1F1P0Vertex.h \
+UEDF1F1W0Vertex.h \
+UEDF1F0W1Vertex.h \
+UEDP0H1H1Vertex.h \
+UEDZ0H1H1Vertex.h \
+UEDW0A1H1Vertex.h \
+UEDZ0A1h1Vertex.h \
+UEDW0W1W1Vertex.h \
+UEDF1F0H1Vertex.h
+
+ALL_CC_FILES = \
+UEDBase.cc \
+UEDF1F1Z0Vertex.cc \
+UEDF1F1G0Vertex.cc \
+UEDF1F0G1Vertex.cc \
+UEDG1G1G0Vertex.cc \
+UEDG0G0G1G1Vertex.cc \
+UEDF1F1P0Vertex.cc \
+UEDF1F1W0Vertex.cc \
+UEDF1F0W1Vertex.cc \
+UEDP0H1H1Vertex.cc \
+UEDZ0H1H1Vertex.cc \
+UEDW0A1H1Vertex.cc \
+UEDZ0A1h1Vertex.cc \
+UEDW0W1W1Vertex.cc \
+UEDF1F0H1Vertex.cc
diff --git a/Models/Zprime/Makefile.am b/Models/Zprime/Makefile.am
--- a/Models/Zprime/Makefile.am
+++ b/Models/Zprime/Makefile.am
@@ -1,6 +1,5 @@
-if WANT_BSM
-pkglib_LTLIBRARIES = HwZprimeModel.la
-endif
-HwZprimeModel_la_SOURCES = ZprimeModel.cc ZprimeModel.h ZprimeModel.fh ZprimeModelZPQQVertex.h ZprimeModelZPQQVertex.cc
+EXTRA_DIST = \
+ZprimeModel.cc ZprimeModel.h \
+ZprimeModel.fh \
+ZprimeModelZPQQVertex.h ZprimeModelZPQQVertex.cc
-HwZprimeModel_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 2:0:0
diff --git a/PDF/MRST.cc b/PDF/MRST.cc
--- a/PDF/MRST.cc
+++ b/PDF/MRST.cc
@@ -1,836 +1,836 @@
// -*- C++ -*-
//
// MRST.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.
//
#include "MRST.h"
#include <ThePEG/PDT/ParticleData.h>
#include <ThePEG/PDT/EnumParticles.h>
#include <ThePEG/Persistency/PersistentOStream.h>
#include <ThePEG/Persistency/PersistentIStream.h>
#include <ThePEG/Repository/EventGenerator.h>
#include <ThePEG/Interface/ClassDocumentation.h>
#include <ThePEG/Interface/Parameter.h>
#include <ThePEG/Interface/Switch.h>
#include <istream>
#include <iostream>
#include <sstream>
#include <string>
using namespace ThePEG;
using namespace Herwig;
/**
* Minimum value of \f$x\f$
*/
const double MRST::xmin=1E-5;
/**
* Maximum value of \f$x\f$
*/
const double MRST::xmax=1.0;
/**
* Minimum value of \f$q^2\f$.
*/
const Energy2 MRST::qsqmin = 1.25 * GeV2;
/**
* Maximum value of \f$q^2\f$.
*/
const Energy2 MRST::qsqmax = 1E7 * GeV2;
/**
* Mass squared of the charm quark
*/
const Energy2 MRST::mc2 = 2.045 * GeV2;
/**
* Mass squared of the bottom quark
*/
const Energy2 MRST::mb2 = 18.5 * GeV2;
ClassDescription<MRST> MRST::initMRST;
MRST::MRST() : _inter(2), _xswitch(0.9),
data(np+1,vector<vector<double> >
(nx+1,vector<double>
(nq+1,0.0))),
fdata(np+1,vector<vector<double> >
(nx+1,vector<double>
(nq+1,0.0))) {
if ( ! initialized ) {
for ( int jj=1; jj < ntenth; ++jj ) {
lxxb[jj] = log10(xx[jj]/xx[ntenth]) + xx[ntenth];
}
lxxb[ntenth] = xx[ntenth];
for ( int n=1; n<=nx; n++ ) lxx[n] = log10(xx[n]);
for ( int n=1; n<=nq; n++ ) lqq[n] = log10(qq[n]);
initialized = true;
}
}
bool MRST::canHandleParticle(tcPDPtr particle) const {
// Return true if this PDF can handle the extraction of parton from the
// given particle ie. if the particle is a proton or neutron.
return ( abs(particle->id()) == ParticleID::pplus ||
abs(particle->id()) == ParticleID::n0 );
}
cPDVector MRST::partons(tcPDPtr p) const {
// Return the parton types which are described by these parton
// densities.
cPDVector ret;
if ( canHandleParticle(p) ) {
ret.push_back(getParticleData(ParticleID::g));
for ( int i = 1; i <= 5; ++i ) {
ret.push_back(getParticleData(i));
ret.push_back(getParticleData(-i));
}
}
return ret;
}
double MRST::xfx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale,
double x, double, Energy2) const {
return pdfValue(x, partonScale, particle, parton,Total);
}
double MRST::xfvx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale,
double x, double, Energy2) const {
return pdfValue(x, partonScale, particle, parton,Valence);
}
double MRST::xfsx(tcPDPtr particle, tcPDPtr parton, Energy2 partonScale,
double x, double, Energy2) const {
return pdfValue(x, partonScale, particle, parton,Sea);
}
double MRST::pdfValue(double x, Energy2 q2,
tcPDPtr particle, tcPDPtr parton, PDFType type) const {
- assert(!isnan(x) && !isinf(x));
+ assert(isfinite(x));
// reset x to min or max if outside range
if(x<xmin) x=xmin;
else if(x>xmax) x=xmax;
// reset q2 to min or max if outside range
if(q2<qsqmin) q2=qsqmin;
else if(q2>qsqmax) q2=qsqmax;
// c++ interpolation
double output(0.);
if(_inter==0||(_inter==2&&x<_xswitch)) {
// interpolation is in logx, log qsq:
double xxx=log10(x);
double qsq=log10(q2/GeV2);
// bin position
int n=locate(lxx,nx,xxx);
int m=locate(lqq,nq,qsq);
// fraction along the bin
double t=(xxx-lxx[n])/(lxx[n+1]-lxx[n]);
double u=(qsq-lqq[m])/(lqq[m+1]-lqq[m]);
bool anti = particle->id() < 0;
bool neutron = abs(particle->id()) == ParticleID::n0;
if (type==Valence) {
switch(parton->id()) {
case ParticleID::u:
output= (neutron?
(anti? 0.0: lookup(dnValence,n,m,u,t)):
(anti? 0.0: lookup(upValence,n,m,u,t)));
break;
case ParticleID::ubar:
output= (neutron?
(anti? lookup(dnValence,n,m,u,t): 0.0):
(anti? lookup(upValence,n,m,u,t): 0.0));
break;
case ParticleID::d:
output= (neutron?
(anti? 0.0: lookup(upValence,n,m,u,t)):
(anti? 0.0: lookup(dnValence,n,m,u,t)));
break;
case ParticleID::dbar:
output= (neutron?
(anti? lookup(upValence,n,m,u,t): 0.0):
(anti? lookup(dnValence,n,m,u,t): 0.0));
break;
}
}
else if(type==Sea) {
switch(parton->id()) {
case ParticleID::b:
case ParticleID::bbar:
output= lookup(bot,n,m,u,t);
break;
case ParticleID::c:
case ParticleID::cbar:
output= lookup(chm,n,m,u,t);
break;
case ParticleID::s:
case ParticleID::sbar:
output= lookup(str,n,m,u,t);
break;
case ParticleID::u:
case ParticleID::ubar:
output= (neutron? lookup(dnSea,n,m,u,t) : lookup(upSea,n,m,u,t));
break;
case ParticleID::d:
case ParticleID::dbar:
output= (neutron? lookup(upSea,n,m,u,t) : lookup(dnSea,n,m,u,t));
break;
case ParticleID::g:
output= lookup(glu,n,m,u,t);
break;
}
}
else if(type==Total) {
switch(parton->id()) {
case ParticleID::b:
case ParticleID::bbar:
output= lookup(bot,n,m,u,t);
break;
case ParticleID::c:
case ParticleID::cbar:
output= lookup(chm,n,m,u,t);
break;
case ParticleID::s:
case ParticleID::sbar:
output= lookup(str,n,m,u,t);
break;
case ParticleID::u:
output= (neutron?
(lookup(dnSea,n,m,u,t) + (anti? 0.0: lookup(dnValence,n,m,u,t))) :
(lookup(upSea,n,m,u,t) + (anti? 0.0: lookup(upValence,n,m,u,t))));
break;
case ParticleID::ubar:
output= (neutron?
(lookup(dnSea,n,m,u,t) + (anti? lookup(dnValence,n,m,u,t): 0.0)) :
(lookup(upSea,n,m,u,t) + (anti? lookup(upValence,n,m,u,t): 0.0)));
break;
case ParticleID::d:
output= (neutron?
(lookup(upSea,n,m,u,t) + (anti? 0.0: lookup(upValence,n,m,u,t))) :
(lookup(dnSea,n,m,u,t) + (anti? 0.0: lookup(dnValence,n,m,u,t))));
break;
case ParticleID::dbar:
output= (neutron?
(lookup(upSea,n,m,u,t) + (anti? lookup(upValence,n,m,u,t): 0.0)) :
(lookup(dnSea,n,m,u,t) + (anti? lookup(dnValence,n,m,u,t): 0.0)));
break;
case ParticleID::g:
output= lookup(glu,n,m,u,t);
break;
}
}
}
else {
double xxx=x;
if(x<lxxb[ntenth]) xxx = log10(x/lxxb[ntenth])+lxxb[ntenth];
int nn=0;
do ++nn;
while(xxx>lxxb[nn+1]);
double a=(xxx-lxxb[nn])/(lxxb[nn+1]-lxxb[nn]);
double qsq=q2/GeV2;
int mm=0;
do ++mm;
while(qsq>qq[mm+1]);
double b=(qsq-qq[mm])/(qq[mm+1]-qq[mm]);
double g[np+1];
for(int ii=1;ii<=np;++ii) {
g[ii]= (1.-a)*(1.-b)*fdata[ii][nn ][mm] + (1.-a)*b*fdata[ii][nn ][mm+1]
+ a*(1.-b)*fdata[ii][nn+1][mm] + a*b*fdata[ii][nn+1][mm+1];
if(nn<ntenth&&!(ii==5||ii==7)) {
double fac=(1.-b)*fdata[ii][ntenth][mm]+b*fdata[ii][ntenth][mm+1];
g[ii] = fac*pow(10.,g[ii]-fac);
}
g[ii] *= pow(1.-x,n0[ii]);
}
bool anti = particle->id() < 0;
bool neutron = abs(particle->id()) == ParticleID::n0;
if (type==Valence) {
switch(parton->id()) {
case ParticleID::u:
output= (neutron?
(anti? 0.0: g[2]):
(anti? 0.0: g[1]));
break;
case ParticleID::ubar:
output= (neutron?
(anti? g[2]: 0.0):
(anti? g[1]: 0.0));
break;
case ParticleID::d:
output= (neutron?
(anti? 0.0: g[1]):
(anti? 0.0: g[2]));
break;
case ParticleID::dbar:
output= (neutron?
(anti? g[1]: 0.0):
(anti? g[2]: 0.0));
break;
}
}
else if(type==Sea) {
switch(parton->id()) {
case ParticleID::b:
case ParticleID::bbar:
output= g[7];
break;
case ParticleID::c:
case ParticleID::cbar:
output= g[5];
break;
case ParticleID::s:
case ParticleID::sbar:
output= g[6];
break;
case ParticleID::u:
case ParticleID::ubar:
output= (neutron ? g[8] : g[4] );
break;
case ParticleID::d:
case ParticleID::dbar:
output= (neutron? g[4] : g[8] );
break;
case ParticleID::g:
output= g[3];
break;
}
}
else if(type==Total) {
switch(parton->id()) {
case ParticleID::b:
case ParticleID::bbar:
output= g[7];
break;
case ParticleID::c:
case ParticleID::cbar:
output= g[5];
break;
case ParticleID::s:
case ParticleID::sbar:
output= g[6];
break;
case ParticleID::u:
output= (neutron?
(g[8] + (anti? 0.0: g[2])) :
(g[4] + (anti? 0.0: g[1])));
break;
case ParticleID::ubar:
output= (neutron?
(g[8] + (anti? g[2]: 0.0)) :
(g[4] + (anti? g[1]: 0.0)));
break;
case ParticleID::d:
output= (neutron?
(g[4] + (anti? 0.0: g[1])) :
(g[8] + (anti? 0.0: g[2])));
break;
case ParticleID::dbar:
output= (neutron?
(g[4] + (anti? g[1]: 0.0)) :
(g[8] + (anti? g[2]: 0.0)));
break;
case ParticleID::g:
output= g[3];
break;
}
}
}
output = max(output,0.);
- assert(!isnan(output));
+ assert(!std::isnan(output));
return output;
}
void MRST::persistentOutput(PersistentOStream &out) const {
out << _file << data << fdata << _inter << _xswitch;
}
void MRST::persistentInput(PersistentIStream & in, int) {
in >> _file >> data >> fdata >> _inter >> _xswitch;
initialize(false);
}
void MRST::Init() {
static ClassDocumentation<MRST> documentation
("Implementation of the MRST PDFs",
"Implementation of the MRST LO* / LO** PDFs \\cite{Sherstnev:2007nd}.",
" %\\cite{Sherstnev:2007nd}\n"
"\\bibitem{Sherstnev:2007nd}\n"
" A.~Sherstnev and R.~S.~Thorne,\n"
" ``Parton Distributions for LO Generators,''\n"
" Eur.\\ Phys.\\ J.\\ C {\\bf 55} (2008) 553\n"
" [arXiv:0711.2473 [hep-ph]].\n"
" %%CITATION = EPHJA,C55,553;%%\n"
);
static Switch<MRST,unsigned int> interfaceInterpolation
("Interpolation",
"Whether to use cubic or linear (C++ or FORTRAN) interpolation",
&MRST::_inter, 2, false, false);
static SwitchOption interfaceInterpolationCubic
(interfaceInterpolation,
"Cubic",
"Use cubic interpolation",
0);
static SwitchOption interfaceInterpolationLinear
(interfaceInterpolation,
"Linear",
"Use Linear Interpolation",
1);;
static SwitchOption interfaceInterpolationMixed
(interfaceInterpolation,
"Mixed",
"Use cubic below xswitch and linear interpolation above",
2);
static Parameter<MRST,double> interfaceXSwitch
("XSwitch",
"Value of x to switch from cubic to linear interpolation",
&MRST::_xswitch, 0.9, 0.0, 1.0,
false, false, Interface::limited);
}
void MRST::doinitrun() {
cerr << "Warning: Herwig::MRST is obsolete and will be removed in Herwig 7.1.\n"
<< " Please switch to using a PDF set provided by LHAPDF.\n";
PDFBase::doinitrun();
#ifdef MRST_TESTING
unsigned int intersave=_inter;
tPDPtr proton=getParticleData(ParticleID::pplus);
for(unsigned int itype=0;itype<8;++itype) {
tPDPtr parton;
string name;
if(itype==0) {
name="u.top";
parton=getParticleData(ParticleID::u);
}
else if(itype==1) {
name="d.top";
parton=getParticleData(ParticleID::d);
}
else if(itype==2) {
name="ubar.top";
parton=getParticleData(ParticleID::ubar);
}
else if(itype==3) {
name="dbar.top";
parton=getParticleData(ParticleID::dbar);
}
else if(itype==4) {
name="s.top";
parton=getParticleData(ParticleID::s);
}
else if(itype==5) {
name="c.top";
parton=getParticleData(ParticleID::c);
}
else if(itype==6) {
name="b.top";
parton=getParticleData(ParticleID::b);
}
else if(itype==7) {
name="g.top";
parton=getParticleData(ParticleID::g);
}
ofstream output(name.c_str());
Energy qmin=2.0*GeV,qmax=3000.0*GeV;
int nq=10;
Energy qstep=(qmax-qmin)/nq;
for(Energy q=qmin+qstep;q<=qmax;q+=qstep) {
double nx=500;
double xmin=1e-5,xmax=1.;
double xstep=(log(xmax)-log(xmin))/nx;
output << "NEW FRAME" << endl;
output << "SET FONT DUPLEX\n";
output << "SET SCALE Y LOG\n";
output << "SET LIMITS X " << xmin << " " << xmax << endl;
if(itype==0)
output << "TITLE TOP \" up distribution for q="
<< q/GeV << "\"\n";
else if(itype==1)
output << "TITLE TOP \" down distribution for q="
<< q/GeV << "\"\n";
else if(itype==2)
output << "TITLE TOP \" ubar distribution for q="
<< q/GeV << "\"\n";
else if(itype==3)
output << "TITLE TOP \" dbar distribution for q="
<< q/GeV << "\"\n";
else if(itype==4)
output << "TITLE TOP \" strange distribution for q="
<< q/GeV << "\"\n";
else if(itype==5)
output << "TITLE TOP \" charm distribution for q="
<< q/GeV << "\"\n";
else if(itype==6)
output << "TITLE TOP \" bottom distribution for q="
<< q/GeV << "\"\n";
else if(itype==7)
output << "TITLE TOP \" gluon distribution for q="
<< q/GeV << "\"\n";
_inter=0;
for(double xl=log(xmin)+xstep;xl<=log(xmax);xl+=xstep) {
double x=exp(xl);
double val=xfl(proton,parton,q*q,-xl);
if(val>1e5) val=1e5;
output << x << '\t' << val << '\n';
}
output << "JOIN RED" << endl;
_inter=1;
for(double xl=log(xmin)+xstep;xl<=log(xmax);xl+=xstep) {
double x=exp(xl);
double val=xfl(proton,parton,q*q,-xl);
if(val>1e5) val=1e5;
output << x << '\t' << val << '\n';
}
output << "JOIN BLUE" << endl;
_inter=2;
for(double xl=log(xmin)+xstep;xl<=log(xmax);xl+=xstep) {
double x=exp(xl);
double val=xfl(proton,parton,q*q,-xl);
if(val>1e5) val=1e5;
output << x << '\t' << val << '\n';
}
output << "JOIN GREEN" << endl;
}
}
_inter=intersave;
#endif
}
void MRST::readSetup(istream &is) {
_file = dynamic_cast<istringstream*>(&is)->str();
initialize();
}
void MRST::initialize(bool reread) {
useMe();
// int i,n,m,k,l,j; // counters
double dx,dq;
int wt[][16] = {{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
{-3, 0, 0, 3, 0, 0, 0, 0,-2, 0, 0,-1, 0, 0, 0, 0},
{ 2, 0, 0,-2, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0},
{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
{ 0, 0, 0, 0,-3, 0, 0, 3, 0, 0, 0, 0,-2, 0, 0,-1},
{ 0, 0, 0, 0, 2, 0, 0,-2, 0, 0, 0, 0, 1, 0, 0, 1},
{-3, 3, 0, 0,-2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0,-2,-1, 0, 0},
{ 9,-9, 9,-9, 6, 3,-3,-6, 6,-6,-3, 3, 4, 2, 1, 2},
{-6, 6,-6, 6,-4,-2, 2, 4,-3, 3, 3,-3,-2,-1,-1,-2},
{ 2,-2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 1, 1, 0, 0},
{-6, 6,-6, 6,-3,-3, 3, 3,-4, 4, 2,-2,-2,-2,-1,-1},
{ 4,-4, 4,-4, 2, 2,-2,-2, 2,-2,-2, 2, 1, 1, 1, 1}};
// Variables used for initialising c_ij array:
double f1[np+1][nx+1][nq+1];//derivative wrt.x
double f2[np+1][nx+1][nq+1];//derivative wrt.qq
double f12[np+1][nx+1][nq+1];//cross derivative
double xxd,d1d2,cl[16],x[16],d1,d2,y[5],y1[5],y2[5],y12[5];
if(reread) {
ifstream datafile(_file.c_str());
if(!datafile) throw Exception() << "Could not open file '" << _file
<< "' in MRST::initialize()"
<< Exception::runerror;
for(int nn=1; nn<nx; nn++) {
for(int mm=1; mm<=nq; mm++) {
datafile >> data[1][nn][mm];
datafile >> data[2][nn][mm];
datafile >> data[3][nn][mm];
datafile >> data[4][nn][mm];
datafile >> data[5][nn][mm];
datafile >> data[7][nn][mm];
datafile >> data[6][nn][mm];
datafile >> data[8][nn][mm];
if(datafile.eof()) throw Exception() << "Error while reading " << _file
<< " too few data points in file"
<< "in MRST::initialize()"
<< Exception::runerror;
for(int ii=1;ii<=np;++ii) {
fdata[ii][nn][mm] = _inter==0 ? 0. :
data[ii][nn][mm]/pow(1.-xx[nn],n0[ii]);
}
}
}
for (int n=1; n<=8; ++n) {
for(int mm=1; mm<=nq; ++mm) {
data[n][nx][mm]=0.0;
}
}
double dtemp;
datafile >> dtemp;
if(!datafile.eof()) throw Exception() << "Error reading end of " << _file
<< " too many data points in file"
<< "in MRST::initialize()"
<< Exception::runerror;
datafile.close();
// calculate the FORTRAN interpolation
for(int jj=1;jj<=ntenth-1;++jj) {
for(int ii=1;ii<=np;++ii) {
if(ii==5||ii==7) continue;
for(int kk=1;kk<=nq;++kk) {
fdata[ii][jj][kk] = _inter==0 ? 0. :
log10( fdata[ii][jj][kk] / fdata[ii][ntenth][kk] ) +
fdata[ii][ntenth][kk];
}
}
}
for (int n=1; n<=np; ++n) {
for(int mm=1; mm<=nq; ++mm) {
fdata[n][nx][mm]=0.0;
}
}
}
// Now calculate the derivatives used for bicubic interpolation
for (int i=1;i<=np;i++) {
// Start by calculating the first x derivatives
// along the first x value
dx=lxx[2]-lxx[1];
for (int m=1;m<=nq;m++)
f1[i][1][m]=(data[i][2][m]-data[i][1][m])/dx;
// The along the rest (up to the last)
for (int k=2;k<nx;k++) {
for (int m=1;m<=nq;m++) {
f1[i][k][m]=polderivative(lxx[k-1],lxx[k],lxx[k+1],
data[i][k-1][m],
data[i][k][m],
data[i][k+1][m]);
}
}
// Then for the last column
dx=lxx[nx]-lxx[nx-1];
for (int m=1;m<=nq;m++)
f1[i][nx][m]=(data[i][nx][m]-data[i][nx-1][m])/dx;
if ((i!=5)&&(i!=7)) {
// then calculate the qq derivatives
// Along the first qq value
dq=lqq[2]-lqq[1];
for (int k=1;k<=nx;k++)
f2[i][k][1]=(data[i][k][2]-data[i][k][1])/dq;
// The rest up to the last qq value
for (int m=2;m<nq;m++) {
for (int k=1;k<=nx;k++)
f2[i][k][m]=polderivative(lqq[m-1],lqq[m],lqq[m+1],
data[i][k][m-1],
data[i][k][m],
data[i][k][m+1]);
}
// then for the last row
dq=lqq[nq]-lqq[nq-1];
for (int k=1;k<=nx;k++)
f2[i][k][nq]=(data[i][k][nq]-data[i][k][nq-1])/dq;
// Now, calculate the cross derivatives.
// Calculate these as x-derivatives of the y-derivatives
// ?? Could be improved by taking the average between dxdy and dydx ??
// Start by calculating the first x derivatives
// along the first x value
dx=lxx[2]-lxx[1];
for (int m=1;m<=nq;m++)
f12[i][1][m]=(f2[i][2][m]-f2[i][1][m])/dx;
// The along the rest (up to the last)
for (int k=2;k<nx;k++) {
for (int m=1;m<=nq;m++)
f12[i][k][m]=polderivative(lxx[k-1],lxx[k],lxx[k+1],
f2[i][k-1][m],f2[i][k][m],f2[i][k+1][m]);
}
// Then for the last column
dx=lxx[nx]-lxx[nx-1];
for (int m=1;m<=nq;m++)
f12[i][nx][m]=(f2[i][nx][m]-f2[i][nx-1][m])/dx;
}
if (i==5) {
// zero all elements below the charm threshold
for (int m=1;m<nqc0;m++)
for (int k=1;k<=nx;k++)
f2[i][k][m]=0.0;
// then calculate the qq derivatives
// Along the first qq value above the threshold (m=ncq0)
dq=lqq[nqc0+1]-lqq[nqc0];
for (int k=1;k<=nx;k++)
f2[i][k][nqc0]=(data[i][k][nqc0+1]-data[i][k][nqc0])/dq;
// The rest up to the last qq value
for (int m=nqc0+1;m<nq;m++) {
for (int k=1;k<=nx;k++)
f2[i][k][m]=polderivative(lqq[m-1],lqq[m],lqq[m+1],
data[i][k][m-1],
data[i][k][m],
data[i][k][m+1]);
}
// then for the last row
dq=lqq[nq]-lqq[nq-1];
for (int k=1;k<=nx;k++)
f2[i][k][nq]=(data[i][k][nq]-data[i][k][nq-1])/dq;
// Now, calculate the cross derivatives.
// Calculate these as x-derivatives of the y-derivatives
// ?? Could be improved by taking the average between dxdy and dydx ??
dx=lxx[2]-lxx[1];
for (int m=1;m<=nq;m++)
f12[i][1][m]=(f2[i][2][m]-f2[i][1][m])/dx;
// The along the rest (up to the last)
for (int k=2;k<nx;k++) {
for (int m=1;m<=nq;m++)
f12[i][k][m]=polderivative(lxx[k-1],lxx[k],lxx[k+1],
f2[i][k-1][m],f2[i][k][m],f2[i][k+1][m]);
}
// Then for the last column
dx=lxx[nx]-lxx[nx-1];
for (int m=1;m<=nq;m++)
f12[i][nx][m]=(f2[i][nx][m]-f2[i][nx-1][m])/dx;
}
if (i==7) {
// zero all elements below the bottom threshold
for (int m=1;m<nqb0;m++)
for (int k=1;k<=nx;k++)
f2[i][k][m]=0.0;
// then calculate the qq derivatives
// Along the first qq value above the threshold (m=nqb0)
dq=lqq[nqb0+1]-lqq[nqb0];
for (int k=1;k<=nx;k++)
f2[i][k][nqb0]=(data[i][k][nqb0+1]-data[i][k][nqb0])/dq;
// The rest up to the last qq value
for (int m=nqb0+1;m<nq;m++) {
for (int k=1;k<=nx;k++)
f2[i][k][m]=polderivative(lqq[m-1],lqq[m],lqq[m+1],
data[i][k][m-1],
data[i][k][m],
data[i][k][m+1]);
}
// then for the last row
dq=lqq[nq]-lqq[nq-1];
for (int k=1;k<=nx;k++)
f2[i][k][nq]=(data[i][k][nq]-data[i][k][nq-1])/dq;
// Now, calculate the cross derivatives.
// Calculate these as x-derivatives of the y-derivatives
// ?? Could be improved by taking the average between dxdy and dydx ??
dx=lxx[2]-lxx[1];
for (int m=1;m<=nq;m++)
f12[i][1][m]=(f2[i][2][m]-f2[i][1][m])/dx;
// The along the rest (up to the last)
for (int k=2;k<nx;k++) {
for (int m=1;m<=nq;m++)
f12[i][k][m]=polderivative(lxx[k-1],lxx[k],lxx[k+1],
f2[i][k-1][m],f2[i][k][m],f2[i][k+1][m]);
}
// Then for the last column
dx=lxx[nx]-lxx[nx-1];
for (int m=1;m<=nq;m++)
f12[i][nx][m]=(f2[i][nx][m]-f2[i][nx-1][m])/dx;
}
// Now calculate the coefficients c_ij
for(int n=1;n<=nx-1;n++) {
for(int m=1;m<=nq-1;m++) {
d1=lxx[n+1]-lxx[n];
d2=lqq[m+1]-lqq[m];
d1d2=d1*d2;
// Iterate around the grid and store the values of f, f_x, f_y and f_xy
y[1]=data[i][n][m];
y[2]=data[i][n+1][m];
y[3]=data[i][n+1][m+1];
y[4]=data[i][n][m+1];
y1[1]=f1[i][n][m];
y1[2]=f1[i][n+1][m];
y1[3]=f1[i][n+1][m+1];
y1[4]=f1[i][n][m+1];
y2[1]=f2[i][n][m];
y2[2]=f2[i][n+1][m];
y2[3]=f2[i][n+1][m+1];
y2[4]=f2[i][n][m+1];
y12[1]=f12[i][n][m];
y12[2]=f12[i][n+1][m];
y12[3]=f12[i][n+1][m+1];
y12[4]=f12[i][n][m+1];
for (int k=1;k<=4;k++) {
x[k-1]=y[k];
x[k+3]=y1[k]*d1;
x[k+7]=y2[k]*d2;
x[k+11]=y12[k]*d1d2;
}
for (int l=0;l<=15;l++) {
xxd=0.0;
for (int k=0;k<=15;k++) xxd+= wt[l][k]*x[k];
cl[l]=xxd;
}
int l=0;
for (int k=1;k<=4;k++)
for (int j=1;j<=4;j++) c[i][n][m][k][j]=cl[l++];
} //m
} //n
} // i
}
double MRST::xx[] =
{ 0.0, 1E-5, 2E-5, 4E-5, 6E-5, 8E-5, 1E-4, 2E-4, 4E-4, 6E-4, 8E-4,
1E-3, 2E-3, 4E-3, 6E-3, 8E-3, 1E-2, 1.4E-2, 2E-2, 3E-2, 4E-2, 6E-2, 8E-2,
.1, .125, 0.15, .175, .2, .225, 0.25, .275, .3, .325, 0.35, .375,
.4, .425, 0.45, .475, .5, .525, 0.55, .575, .6, .65, .7, .75,
.8, .9, 1. };
double MRST::lxx[] =
{ 0.0, 1E-5, 2E-5, 4E-5, 6E-5, 8E-5, 1E-4, 2E-4, 4E-4, 6E-4, 8E-4,
1E-3, 2E-3, 4E-3, 6E-3, 8E-3, 1E-2, 1.4E-2, 2E-2, 3E-2, 4E-2, 6E-2, 8E-2,
.1, .125, 0.15, .175, .2, .225, 0.25, .275, .3, .325, 0.35, .375,
.4, .425, 0.45, .475, .5, .525, 0.55, .575, .6, .65, .7, .75,
.8, .9, 1. };
double MRST::lxxb[] =
{ 0.0, 1E-5, 2E-5, 4E-5, 6E-5, 8E-5, 1E-4, 2E-4, 4E-4, 6E-4, 8E-4,
1E-3, 2E-3, 4E-3, 6E-3, 8E-3, 1E-2, 1.4E-2, 2E-2, 3E-2, 4E-2, 6E-2, 8E-2,
.1, .125, 0.15, .175, .2, .225, 0.25, .275, .3, .325, 0.35, .375,
.4, .425, 0.45, .475, .5, .525, 0.55, .575, .6, .65, .7, .75,
.8, .9, 1. };
double MRST::qq[] =
{ 0.0, 1.25, 1.5, 2., 2.5, 3.2, 4., 5., 6.4, 8., 10., 12., 18., 26., 40.,
64., 1E2, 1.6E2, 2.4E2, 4E2, 6.4E2, 1E3, 1.8E3, 3.2E3, 5.6E3,
1E4, 1.8E4, 3.2E4, 5.6E4, 1E5, 1.8E5, 3.2E5, 5.6E5, 1E6, 1.8E6,
3.2E6, 5.6E6, 1E7 };
double MRST::lqq[] =
{ 0.0, 1.25, 1.5, 2., 2.5, 3.2, 4., 5., 6.4, 8., 10., 12., 18., 26., 40.,
64., 1E2, 1.6E2, 2.4E2, 4E2, 6.4E2, 1E3, 1.8E3, 3.2E3, 5.6E3,
1E4, 1.8E4, 3.2E4, 5.6E4, 1E5, 1.8E5, 3.2E5, 5.6E5, 1E6, 1.8E6,
3.2E6, 5.6E6, 1E7 };
double MRST::n0[] =
{0,3,4,5,9,9,9,9,9};
bool MRST::initialized = false;
diff --git a/PDT/ThreeBodyAllOnCalculator.tcc b/PDT/ThreeBodyAllOnCalculator.tcc
--- a/PDT/ThreeBodyAllOnCalculator.tcc
+++ b/PDT/ThreeBodyAllOnCalculator.tcc
@@ -1,198 +1,198 @@
// -*- C++ -*-
//
// ThreeBodyAllOnCalculator.tcc 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 templated member
// functions of the ThreeBodyAllOnCalculator class.
//
using namespace Herwig;
// shift the variables for the outer integrand and give limits for the inner one
template <class T>
void ThreeBodyAllOnCalculator<T>::outerVariables(double x, Energy2 & low,
Energy2 & upp) const {
// first convert the value of x into the value of souter
if(_mapping[_thechannel]==0) {
_souter = _channelmass[_thechannel]*(_channelmass[_thechannel]+
_channelwidth[_thechannel]*tan(x));
}
else if(_mapping[_thechannel]==1) {
_souter = sqr(_channelmass[_thechannel])*(1.+1./x);
}
else {
_souter = UnitRemoval::E2 * pow(x,1./(_channelpower[_thechannel]+1.));
}
// now the limits of the inner integral
Energy ea(ZERO),eb(ZERO);
Energy rs=sqrt(_souter);
Energy2 eam2(ZERO),ebm2(ZERO);
switch(_channeltype[_thechannel]) {
case 1:
ea = 0.5*(_souter-_m2[1]+_m2[2])/rs;
eam2 = sqr(ea)-_m2[2];
eb = 0.5*(_m2[0]-_souter-_m2[3])/rs;
ebm2 = sqr(eb)-_m2[3];
break;
case 2:
ea = 0.5*(_souter-_m2[1]+_m2[3])/rs;
eam2 = sqr(ea)-_m2[3];
eb = 0.5*(_m2[0]-_souter-_m2[2])/rs;
ebm2 = sqr(eb)-_m2[2];
break;
case 3:
ea = 0.5*(_souter-_m2[2]+_m2[3])/rs;
eam2 = sqr(ea)-_m2[3];
eb = 0.5*(_m2[0]-_souter-_m2[1])/rs;
ebm2 = sqr(eb)-_m2[1];
break;
default:
assert(false);
}
Energy eam = sqrt(max(ZERO,eam2));
Energy ebm = sqrt(max(ZERO,ebm2));
Energy2 sum = sqr(ea+eb);
// calculate the limits
low = sum - sqr(eam+ebm);
upp = sum - sqr(eam-ebm);
}
template <class T>
Energy2 ThreeBodyAllOnCalculator<T>::operator ()(Energy2 y) const {
- assert(!isnan(y/MeV2));
+ assert(!std::isnan(double(y/MeV2)));
// set up the values of the s variables
Energy2 s12(ZERO),s23(ZERO),s13(ZERO),
m2sum(_m2[0]+_m2[1]+_m2[2]+_m2[3]);
switch(_channeltype[_thechannel]) {
case 1:
s12 = _souter;
s23 = y;
s13 = m2sum-s12-s23;
break;
case 2:
s23 = y;
s13 = _souter;
s12 = m2sum-s23-s13;
break;
case 3:
s23 = _souter;
s13 = y;
s12 = m2sum-s23-s13;
break;
}
// compute the jacobian
// computer the denominator for the jacobian
InvEnergy2 jacdem = ZERO;
Energy2 sjac(ZERO);
Energy2 rm2,rw2;
for(unsigned int ix=0,N=_channeltype.size(); ix<N; ++ix) {
switch(_channeltype[ix]) {
case 1:
sjac = s12;
break;
case 2:
sjac = s13;
break;
case 3:
sjac = s23;
break;
}
- assert(!isnan(sjac/MeV2));
+ assert(!std::isnan(double(sjac/MeV2)));
InvEnergy2 term;
if(_mapping[ix]==0) {
rm2 = sqr(_channelmass[ix]);
rw2 = sqr(_channelwidth[ix]);
Energy4 tmp = sqr(sjac-rm2) + rw2*rm2;
term = _channelweights[ix]*_channelmass[ix]*_channelwidth[ix]/tmp;
}
else if(_mapping[ix]==1) {
term = _channelweights[ix]*sqr(_channelmass[ix]/(sjac-sqr(_channelmass[ix])));
}
else if(_mapping[ix]==2) {
term = UnitRemoval::InvE2 * _channelweights[ix]*(_channelpower[ix]+1.)*
pow(sjac*UnitRemoval::InvE2, _channelpower[ix]);
}
else
assert(false);
jacdem += term;
}
// now computer the matrix element
return _theME.threeBodyMatrixElement(_mode,_m2[0],s12,s13,
s23,_m[1],_m[2],_m[3])/jacdem;
}
// calculate the width for a given mass
template <class T>
Energy ThreeBodyAllOnCalculator<T>::partialWidth(Energy2 q2) const {
Outer outer(this,_relerr);
_m[0] = sqrt(q2);
_m2[0]=q2;
// check the decay is kinematically allowed
if(_m[0]<_m[1]+_m[2]+_m[3]) return ZERO;
// set up for the different channels
unsigned int N = _channeltype.size();
vector<double> rupp(N,0.),rlow(N,0.);
for(unsigned int ix=0; ix<N; ++ix) {
Energy2 upp(ZERO),low(ZERO);
// work out the kinematic limits
switch(_channeltype[ix]) {
case 1:
upp = sqr(_m[0]-_m[3]);
low = sqr(_m[1]+_m[2]);
break;
case 2:
upp = sqr(_m[0]-_m[2]);
low = sqr(_m[1]+_m[3]);
break;
case 3:
upp = sqr(_m[0]-_m[1]);
low = sqr(_m[2]+_m[3]);
break;
default:
assert(false);
}
// transform them
if(_channelmass[ix] > ZERO) {
if(_channelwidth[ix] > 1e-8*MeV) {
rupp[ix] = atan2((upp-_channelmass[ix]*_channelmass[ix]),
_channelmass[ix]*_channelwidth[ix]);
rlow[ix] = atan2((low-_channelmass[ix]*_channelmass[ix]),
_channelmass[ix]*_channelwidth[ix]);
_mapping[ix] = 0;
if(rupp[ix]/rlow[ix]>0.&&_channelwidth[ix]/_channelmass[ix]<1e-6) {
_mapping[ix] = 1;
Energy2 m2=sqr(_channelmass[ix]);
rupp[ix] = m2/(low-m2);
rlow[ix] = m2/(upp-m2);
}
}
else {
_mapping[ix] = 1;
Energy2 m2=sqr(_channelmass[ix]);
rupp[ix] = m2/(low-m2);
rlow[ix] = m2/(upp-m2);
}
}
else {
_mapping[ix] = 2;
rupp[ix] = pow(upp*UnitRemoval::InvE2, _channelpower[ix]+1.);
rlow[ix] = pow(low*UnitRemoval::InvE2, _channelpower[ix]+1.);
}
}
// perform the integrals for all the different channels
Energy4 sum(ZERO);
for(unsigned int ix=0,N=_channeltype.size(); ix<N; ++ix) {
// perform the integral using GSLIntegrator class
_thechannel=ix;
GSLIntegrator intb(1e-35,_relerr,1000);
sum += _channelweights[ix] * intb.value(outer,rlow[ix],rupp[ix]);
}
// final factors
Energy3 fact = pow<3,1>(Constants::twopi * _m[0]);
return sum/fact/32.;
}
diff --git a/Sampling/BinSampler.cc b/Sampling/BinSampler.cc
--- a/Sampling/BinSampler.cc
+++ b/Sampling/BinSampler.cc
@@ -1,728 +1,728 @@
// -*- C++ -*-
//
// BinSampler.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 BinSampler class.
//
#include "BinSampler.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/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 "GeneralSampler.h"
using namespace Herwig;
BinSampler::BinSampler()
: MultiIterationStatistics(),
theBias(1.),
theWeighted(false),
theInitialPoints(1000000),
theNIterations(1),
theEnhancementFactor(1.0),
theNonZeroInPresampling(false),
theHalfPoints(false),
theMaxNewMax(30),
theReferenceWeight(1.0),
theBin(-1),
theInitialized(false),
theRemapperPoints(0),
theRemapChannelDimension(false),
theLuminosityMapperBins(0),
theGeneralMapperBins(0),
theRemapperMinSelection(0.00001),
theIntegrated(false),
theRemappersFilled(false),
theHasGrids(false),
theKappa(1.){}
BinSampler::~BinSampler() {}
IBPtr BinSampler::clone() const {
return new_ptr(*this);
}
IBPtr BinSampler::fullclone() const {
return new_ptr(*this);
}
void BinSampler::sampler(Ptr<GeneralSampler>::tptr s) {
theSampler = s;
}
Ptr<GeneralSampler>::tptr BinSampler::sampler() const {
return theSampler;
}
string BinSampler::process() const {
ostringstream os("");
const StandardEventHandler& eh = *theEventHandler;
const StandardXComb& xc = *eh.xCombs()[theBin];
os << xc.matrixElement()->name() << " : ";
os << xc.mePartonData()[0]->PDGName() << " "
<< xc.mePartonData()[1]->PDGName() << " -> ";
for ( cPDVector::const_iterator pid =
xc.mePartonData().begin() + 2;
pid != xc.mePartonData().end(); ++pid )
os << (**pid).PDGName() << " ";
return os.str();
}
string BinSampler::shortprocess() const {
ostringstream os("");
const StandardEventHandler& eh = *theEventHandler;
const StandardXComb& xc = *eh.xCombs()[theBin];
os << xc.mePartonData()[0]->id() << " "
<< xc.mePartonData()[1]->id() << " : ";
for ( cPDVector::const_iterator pid =
xc.mePartonData().begin() + 2;
pid != xc.mePartonData().end(); ++pid )
os << (**pid).id() << " ";
return os.str();
}
string BinSampler::id() const {
ostringstream os("");
const StandardEventHandler& eh = *theEventHandler;
const StandardXComb& xc = *eh.xCombs()[theBin];
string name = xc.matrixElement()->name();
string::size_type i = name.find_first_of("[");
string nameFirst = name.substr(0,i);
i = name.find_first_of("]");
string nameSecond = name.substr(i+1);
os << nameFirst << nameSecond << ":";
for ( cPDVector::const_iterator pid =
xc.mePartonData().begin();
pid != xc.mePartonData().end(); ++pid )
os << (**pid).id() << (pid != (--xc.mePartonData().end()) ? "," : "");
return os.str();
}
double BinSampler::evaluate(vector<double> p,
bool remap) {
double w = 1.0;
if ( remap && !remappers.empty() ) {
for ( size_t k = 0; k < p.size(); ++k ) {
map<size_t,Remapper>::const_iterator r =
remappers.find(k);
if ( r != remappers.end() ) {
pair<double,double> f = r->second.generate(p[k]);
p[k] = f.first;
w /= f.second;
}
}
}
try {
w *= eventHandler()->dSigDR(p) / nanobarn;
} catch (Veto&) {
w = 0.0;
} catch (...) {
throw;
}
if (randomNumberString()!="")
for ( size_t k = 0; k < p.size(); ++k ) {
RandomNumberHistograms[RandomNumberIndex(id(),k)].first.book(p[k],w);
RandomNumberHistograms[RandomNumberIndex(id(),k)].second+=w;
}
return w;
}
double BinSampler::generate() {
double w = 1.;
for ( size_t k = 0; k < lastPoint().size(); ++k ) {
lastPoint()[k] = UseRandom::rnd();
}
try {
w = evaluate(lastPoint());
} catch (Veto&) {
w = 0.0;
} catch (...) {
throw;
}
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 BinSampler::fillRemappers(bool progress) {
if ( remappers.empty() )
return;
unsigned long nanPoints = 0;
boost::progress_display* progressBar = 0;
if ( progress ) {
Repository::clog() << "warming up " << process();
progressBar = new boost::progress_display(theRemapperPoints,Repository::clog());
}
unsigned long countzero =0;
for ( unsigned long k = 0; k < theRemapperPoints; ++k,++countzero ) {
if (countzero>=theRemapperPoints)break;
double w = 1.;
for ( size_t j = 0; j < lastPoint().size(); ++j ) {
lastPoint()[j] = UseRandom::rnd();
}
try {
w = evaluate(lastPoint(),false);
} catch (Veto&) {
w = 0.0;
} catch (...) {
throw;
}
- if ( isnan(w) || isinf(w) )
+ if ( ! isfinite(w) )
++nanPoints;
if ( theNonZeroInPresampling && w==0. ){
k--;
continue;
}
if ( w != 0.0 ) {
countzero=0;
for ( map<size_t,Remapper>::iterator r = remappers.begin();
r != remappers.end(); ++r )
r->second.fill(lastPoint()[r->first],w);
}
if ( progressBar )
++(*progressBar);
}
if ( progressBar ) {
delete progressBar;
}
if ( nanPoints ) {
Repository::clog() << "Warning: " << nanPoints
<< " out of " << theRemapperPoints << " points with nan or inf "
<< "weight encountered while filling remappers.\n" << flush;
}
}
void BinSampler::saveIntegrationData() const {
XML::Element stats = MultiIterationStatistics::toXML();
stats.appendAttribute("process",id());
sampler()->grids().append(stats);
}
void BinSampler::readIntegrationData() {
if ( theIntegrated )
return;
bool haveStats = false;
list<XML::Element>::iterator sit = sampler()->grids().children().begin();
for ( ; sit != sampler()->grids().children().end(); ++sit ) {
if ( sit->type() != XML::ElementTypes::Element )
continue;
if ( sit->name() != "MultiIterationStatistics" )
continue;
string proc;
sit->getFromAttribute("process",proc);
if ( proc == id() ) {
haveStats = true;
break;
}
}
if ( haveStats ) {
MultiIterationStatistics::fromXML(*sit);
sampler()->grids().erase(sit);
theIntegrated = true;
} else {
throw Exception()
<< "\n--------------------------------------------------------------------------------\n\n"
<< "Expected integration data.\n\n"
<< "* When using the build setup make sure the integrate command has been run.\n\n"
<< "* Check the [EventGenerator].log file for further information.\n\n"
<< "* Make sure that the Herwig folder can be found and that it contains a HerwigGrids.xml file.\n\n"
<< "* If you have split the integration jobs, make sure that each integration job was finished.\n"
<< " Afterwards delete the global HerwigGrids.xml file in the Herwig subfolder\n"
<< " to automatically create an updated version of the global HerwigGrids.xml file.\n\n"
<< "--------------------------------------------------------------------------------\n"
<< Exception::abortnow;
}
}
void BinSampler::saveRemappers() const {
if ( remappers.empty() )
return;
XML::Element maps(XML::ElementTypes::Element,"Remappers");
maps.appendAttribute("process",id());
for ( map<size_t,Remapper>::const_iterator r = remappers.begin();
r != remappers.end(); ++r ) {
XML::Element rmap = r->second.toXML();
rmap.appendAttribute("dimension",r->first);
maps.append(rmap);
}
sampler()->grids().append(maps);
}
void BinSampler::setupRemappers(bool progress) {
if ( !theRemapperPoints )
return;
if ( theRemappersFilled )
return;
lastPoint().resize(dimension());
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() != "Remappers" )
continue;
string proc;
git->getFromAttribute("process",proc);
if ( proc == id() ) {
haveGrid = true;
break;
}
}
if ( haveGrid ) {
for ( list<XML::Element>::iterator cit = git->children().begin();
cit != git->children().end(); ++cit ) {
if ( cit->type() != XML::ElementTypes::Element )
continue;
if ( cit->name() != "Remapper" )
continue;
size_t dimension = 0;
cit->getFromAttribute("dimension",dimension);
remappers[dimension].fromXML(*cit);
}
sampler()->grids().erase(git);
}
if ( !haveGrid ) {
const StandardEventHandler& eh = *eventHandler();
const StandardXComb& xc = *eh.xCombs()[bin()];
const pair<int,int>& pdims = xc.partonDimensions();
set<int> remapped;
if ( theRemapChannelDimension && xc.diagrams().size() > 1 &&
dimension() > pdims.first + pdims.second ) {
remappers[pdims.first] = Remapper(xc.diagrams().size(),theRemapperMinSelection,false);
remapped.insert(pdims.first);
}
if ( theLuminosityMapperBins > 1 && dimension() >= pdims.first + pdims.second ) {
for ( int n = 0; n < pdims.first; ++n ) {
remappers[n] = Remapper(theLuminosityMapperBins,theRemapperMinSelection,true);
remapped.insert(n);
}
for ( int n = dimension() - pdims.second; n < dimension(); ++n ) {
remappers[n] = Remapper(theLuminosityMapperBins,theRemapperMinSelection,true);
remapped.insert(n);
}
}
if ( theGeneralMapperBins > 1 ) {
for ( int n = 0; n < dimension(); n++ ) {
if ( remapped.find(n) == remapped.end() ) {
remappers[n] = Remapper(theGeneralMapperBins,theRemapperMinSelection,true);
remapped.insert(n);
}
}
}
fillRemappers(progress);
for ( map<size_t,Remapper>::iterator r = remappers.begin();
r != remappers.end(); ++r ) {
r->second.finalize();
}
}
theRemappersFilled = true;
}
void BinSampler::runIteration(unsigned long points, bool progress) {
boost::progress_display* progressBar = 0;
if ( progress ) {
Repository::clog() << "integrating " << process() << " , iteration "
<< (iterations().size() + 1);
progressBar = new boost::progress_display(points,Repository::clog());
}
double w=0.;
double maxweight=0;
int numlastmax=0;
unsigned long countzero =0;
int newmax=0;
for ( unsigned long k = 0; k < points; ++k,++countzero ) {
if (countzero>=points)break;
w=abs(generate());
if(theNonZeroInPresampling && w==0.0){
k--;
continue;
}
if (w!=0.0)
countzero =0;
numlastmax++;
if (theHalfPoints&&maxweight<w&&
numlastmax<(int)(points/2.)){
if(++newmax>theMaxNewMax){
throw Exception()
<< "\n--------------------------------------------------------------------------------\n\n"
<< "To many new Maxima.\n\n"
<< "* With the option:\n\n"
<< "* set Sampler:BinSampler:HalfPoints Yes\n\n"
<< "* for every new maximum weight found until the half of the persampling points\n"
<< "* the counter is set to zero. We count the number of new maxima.\n"
<< "* You have reached: "<<newmax<<"\n"
<< "* Did you apply reasonable cuts to the process?\n"
<< "* You can set the maximum allowed new maxima by:"
<< "* set Sampler:BinSampler:MaxNewMax N\n\n"
<< "--------------------------------------------------------------------------------\n"
<< Exception::abortnow;
}
maxweight=w;
k=0;
numlastmax=0;
}
if ( progress ) {
++(*progressBar);
}
}
if ( progress ) {
Repository::clog() << "integrated ( "
<< averageWeight() << " +/- " << sqrt(averageWeightVariance())
<< " ) nb\nepsilon = "
<< (abs(maxWeight()) != 0. ? averageAbsWeight()/abs(maxWeight()) : 0.);
if ( !iterations().empty() )
Repository::clog() << " chi2 = " << chi2();
Repository::clog() << "\n";
Repository::clog() << "--------------------------------------------------------------------------------\n";
}
if ( progressBar )
delete progressBar;
}
void BinSampler::initialize(bool progress) {
lastPoint().resize(dimension());
if (randomNumberString()!="")
for(size_t i=0;i<lastPoint().size();i++){
RandomNumberHistograms[RandomNumberIndex(id(),i)] = make_pair( RandomNumberHistogram(),0.);
}
if ( initialized() )
return;
if ( !sampler()->grids().children().empty() ) {
nIterations(1);
}
if ( !integrated() ) {
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();
}
}
}
isInitialized();
}
void BinSampler::finalize(bool){
if (theRandomNumbers!="")
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);
}
}
BinSampler::RandomNumberHistogram::
RandomNumberHistogram(double low,
double up,
unsigned int nbins)
: lower(low) {
nbins = nbins + 1;
double c = up / (nbins-1.);
for ( unsigned int k = 1; k < nbins; ++k ) {
bins[low+c*k] = 0.;
binsw1[low+c*k] = 0.;
}
}
void BinSampler::RandomNumberHistogram::
dump(const std::string& folder,const std::string& prefix, const std::string& process,
const int NR) const {
ostringstream fname("");
std::string prefix2;
std::string prefix3=prefix;
std::remove_copy(prefix.begin(), prefix.end(), std::back_inserter(prefix2), '.');
prefix3=prefix2;prefix2.clear();
std::remove_copy(prefix3.begin(), prefix3.end(), std::back_inserter(prefix2), ':');
prefix3=prefix2;prefix2.clear();
std::remove_copy(prefix3.begin(), prefix3.end(), std::back_inserter(prefix2), ',');
fname << "RN-"<< NR ;
ofstream out((folder+"/"+prefix2+fname.str()+".dat").c_str());
double sumofweights=0.;
for ( map<double,double >::const_iterator b = bins.begin();b != bins.end(); ++b )
sumofweights+=b->second;
double sumofweights2=0.;
for ( map<double,double >::const_iterator b = binsw1.begin();b != binsw1.end(); ++b )
sumofweights2+=b->second;
map<double,double >::const_iterator b2 = binsw1.begin();
if ( sumofweights == 0 ) {
cerr << "Not enough statistic accumulated for "
<< process << " skipping random number diagnostic.\n"
<< flush;
return;
}
for ( map<double,double >::const_iterator b = bins.begin();
b != bins.end(); ++b, ++b2) {
out << " " << b->first
<< " " << b->second/sumofweights*100.
<< " " << b2->second/sumofweights2*100.
<< "\n" << flush;
}
double xmin = -0.01;
double xmax = 1.01;
ofstream gpout((folder+"/"+prefix2+fname.str()+".gp").c_str());
gpout << "set terminal epslatex color solid\n"
<< "set output '" << prefix2+fname.str() << "-plot.tex'\n"
<< "set xrange [" << xmin << ":" << xmax << "]\n";
gpout << "set xlabel 'rn "<<NR <<"' \n";
gpout << "set size 0.5,0.6\n";
gpout << "plot '" << prefix2+fname.str()
<< ".dat' u ($1):($2) w boxes lc rgbcolor \"blue\" t '{\\tiny "<<process <<" }',";
gpout << " '" << prefix2+fname.str();
gpout << ".dat' u ($1):($3) w boxes lc rgbcolor \"red\" t '';";
gpout << "reset\n";
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void BinSampler::persistentOutput(PersistentOStream & os) const {
MultiIterationStatistics::put(os);
os << theBias << theWeighted << theInitialPoints << theNIterations
<< theEnhancementFactor << theNonZeroInPresampling << theHalfPoints
<< theMaxNewMax << theReferenceWeight
<< theBin << theInitialized << theLastPoint
<< theEventHandler << theSampler << theRandomNumbers
<< theRemapperPoints << theRemapChannelDimension
<< theLuminosityMapperBins << theGeneralMapperBins << theKappa;
}
void BinSampler::persistentInput(PersistentIStream & is, int) {
MultiIterationStatistics::get(is);
is >> theBias >> theWeighted >> theInitialPoints >> theNIterations
>> theEnhancementFactor >> theNonZeroInPresampling >> theHalfPoints
>> theMaxNewMax >> theReferenceWeight
>> theBin >> theInitialized >> theLastPoint
>> theEventHandler >> theSampler >> theRandomNumbers
>> theRemapperPoints >> theRemapChannelDimension
>> theLuminosityMapperBins >> theGeneralMapperBins >> theKappa;
}
// *** 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<BinSampler,MultiIterationStatistics>
describeHerwigBinSampler("Herwig::BinSampler", "HwSampling.so");
void BinSampler::Init() {
static ClassDocumentation<BinSampler> documentation
("BinSampler samples XCombs bins. This default implementation performs flat MC integration.");
static Parameter<BinSampler,unsigned long> interfaceInitialPoints
("InitialPoints",
"The number of points to use for initial integration.",
&BinSampler::theInitialPoints, 1000000, 1, 0,
false, false, Interface::lowerlim);
static Parameter<BinSampler,size_t> interfaceNIterations
("NIterations",
"The number of iterations to perform initially.",
&BinSampler::theNIterations, 1, 1, 0,
false, false, Interface::lowerlim);
static Parameter<BinSampler,double> interfaceEnhancementFactor
("EnhancementFactor",
"The enhancement factor for the number of points in the next iteration.",
&BinSampler::theEnhancementFactor, 2.0, 1.0, 0,
false, false, Interface::lowerlim);
static Switch<BinSampler,bool> interfaceNonZeroInPresampling
("NonZeroInPresampling",
"Switch on to count only non zero weights in presampling.",
&BinSampler::theNonZeroInPresampling, true, false, false);
static SwitchOption interfaceNonZeroInPresamplingYes
(interfaceNonZeroInPresampling,
"Yes",
"",
true);
static SwitchOption interfaceNonZeroInPresamplingNo
(interfaceNonZeroInPresampling,
"No",
"",
false);
static Switch<BinSampler,bool> interfaceHalfPoints
("HalfPoints",
"Switch on to reset the counter of points if new maximumis was found in the first 1/2 points.",
&BinSampler::theHalfPoints, true, false, false);
static SwitchOption interfaceHalfPointsYes
(interfaceHalfPoints,
"Yes",
"",
true);
static SwitchOption interfaceHalfPointsNo
(interfaceHalfPoints,
"No",
"",
false);
static Parameter<BinSampler,int> interfaceMaxNewMax
("MaxNewMax",
"The maximum number of allowed new maxima in combination with the HalfPoints option.",
&BinSampler::theMaxNewMax, 30, 1, 0,
false, false, Interface::lowerlim);
static Parameter<BinSampler,string> interfaceRandomNumbers
("RandomNumbers",
"Prefix for distributions of the random numbers.",
&BinSampler::theRandomNumbers, "",
false, false);
static Parameter<BinSampler,unsigned long> interfaceRemapperPoints
("RemapperPoints",
"The number of points to be used for filling remappers.",
&BinSampler::theRemapperPoints, 10000, 0, 0,
false, false, Interface::lowerlim);
static Switch<BinSampler,bool> interfaceRemapChannelDimension
("RemapChannelDimension",
"Switch on remapping of the channel dimension.",
&BinSampler::theRemapChannelDimension, true, false, false);
static SwitchOption interfaceRemapChannelDimensionYes
(interfaceRemapChannelDimension,
"Yes",
"",
true);
static SwitchOption interfaceRemapChannelDimensionNo
(interfaceRemapChannelDimension,
"No",
"",
false);
static Parameter<BinSampler,unsigned long> interfaceLuminosityMapperBins
("LuminosityMapperBins",
"The number of bins to be used for remapping parton luminosities.",
&BinSampler::theLuminosityMapperBins, 0, 0, 0,
false, false, Interface::lowerlim);
static Parameter<BinSampler,unsigned long> interfaceGeneralMapperBins
("GeneralMapperBins",
"The number of bins to be used for remapping other phase space dimensions.",
&BinSampler::theGeneralMapperBins, 0, 0, 0,
false, false, Interface::lowerlim);
static Parameter<BinSampler,double> interfaceRemapperMinSelection
("RemapperMinSelection",
"The minimum bin selection probability for remappers.",
&BinSampler::theRemapperMinSelection, 0.00001, 0.0, 1.0,
false, false, Interface::limited);
static Parameter<BinSampler,double> interfaceKappa
("Kappa",
"In AllmostUnweighted mode unweight to Kappa ReferenceWeight.",
&BinSampler::theKappa, 1., 0.000001, 1.0,
false, false, Interface::limited);
}
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/CellGrids/SimpleCellGrid.h b/Sampling/CellGrids/SimpleCellGrid.h
--- a/Sampling/CellGrids/SimpleCellGrid.h
+++ b/Sampling/CellGrids/SimpleCellGrid.h
@@ -1,378 +1,376 @@
// -*- C++ -*-
//
// SimpleCellGrid.hpp is a part of ExSample
// Copyright (C) 2012-2013 Simon Platzer
//
// ExSample is licenced under version 2 of the GPL, see COPYING for details.
//
#ifndef EXSAMPLE_SimpleCellGrid_hpp_included
#define EXSAMPLE_SimpleCellGrid_hpp_included
#include "CellGrid.h"
#include <cmath>
namespace ExSample {
-using std::isnan;
-using std::isinf;
/**
* \brief A simple cell grid providing basic adaption and sampling
* \author Simon Platzer
*/
class SimpleCellGrid
: public CellGrid {
public:
/**
* Default constructor
*/
SimpleCellGrid()
: CellGrid() {}
/**
* Construct given boundaries and a weight
*/
SimpleCellGrid(const std::vector<double>& newLowerLeft,
const std::vector<double>& newUpperRight,
bool keepWeightInformation = true,
double newWeight = 0.0);
/**
* Produce a new instance of a cell grid
*/
virtual CellGrid* makeInstance() const;
/**
* Produce a new instance of a cell grid
*/
virtual CellGrid* makeInstance(const std::vector<double>& newLowerLeft,
const std::vector<double>& newUpperRight,
double newWeight = 0.0) const;
/**
* Split this cell grid in the given dimension and coordinate, if
* it is a leaf
*/
virtual void split(std::size_t newSplitDimension, double newSplitCoordinate);
virtual void splitter(size_t dim, int rat);
public:
/**
* Return the first child
*/
const SimpleCellGrid& firstChild() const {
return dynamic_cast<const SimpleCellGrid&>(CellGrid::firstChild());
}
/**
* Access the first child
*/
SimpleCellGrid& firstChild() {
return dynamic_cast<SimpleCellGrid&>(CellGrid::firstChild());
}
/**
* Return the second child
*/
const SimpleCellGrid& secondChild() const {
return dynamic_cast<const SimpleCellGrid&>(CellGrid::secondChild());
}
/**
* Access the second child
*/
SimpleCellGrid& secondChild() {
return dynamic_cast<SimpleCellGrid&>(CellGrid::secondChild());
}
public:
/**
* A simple counter to store information used for adaption
*/
struct Counter {
/**
* Default constructor
*/
Counter()
: nPoints(0.0), sumOfWeights(0.0),
sumOfSquaredWeights(0.0),
maxWeight(0.0) {}
/**
* The number of points
*/
double nPoints;
/**
* The sum of weights
*/
double sumOfWeights;
/**
* The sum of squared weights
*/
double sumOfSquaredWeights;
/**
* The maximum weight
*/
double maxWeight;
/**
* Book a point
*/
void book(double weight) {
nPoints += 1.0;
sumOfWeights += std::abs(weight);
sumOfSquaredWeights += sqr(weight);
maxWeight = std::max(std::abs(weight),maxWeight);
}
/**
* Return the average weight
*/
double averageWeight() const { return nPoints != 0.0 ? sumOfWeights/nPoints : 0.0; }
/**
* Return the variance of the weights
*/
double varianceOfAverage() const {
return
nPoints > 1.0 ?
fabs(sumOfSquaredWeights/nPoints - sqr(sumOfWeights/nPoints))/(nPoints-1) : 0.0;
}
};
/**
* Return weight information for adaption steps
*/
const std::vector<std::pair<Counter,Counter> >& weightInformation() const { return theWeightInformation; }
/**
* Access weight information for adaption steps
*/
std::vector<std::pair<Counter,Counter> >& weightInformation() { return theWeightInformation; }
/**
* Update the weight information for the given point
*/
virtual void updateWeightInformation(const std::vector<double>& p,
double w);
/**
* Adjust the reference weight
*/
void adjustReferenceWeight(double w) {
theReferenceWeight = std::max(theReferenceWeight,std::abs(w));
}
/**
* Return the reference weight
*/
double getReferenceWeight() const {
return theReferenceWeight;
}
/**
* Perform a default adaption step, splitting along the dimension
* which shows up the largest difference in average weights; if
* this exceeds gain, perform the split.
*/
virtual void adapt(double gain, double epsilon,
std::set<SimpleCellGrid*>& newCells);
/**
* Update the weights of the cells from information accumulated so
* far
*/
virtual void setWeights();
public:
/**
* Sample a point flat in this cell
*/
template<class RndGenerator>
void sampleFlatPoint(std::vector<double>& p,
RndGenerator& rnd) const {
assert(p.size() == lowerLeft().size());
for ( size_t k = 0; k < p.size(); ++k ) {
p[k] = lowerLeft()[k] + rnd.rnd()*(upperRight()[k]-lowerLeft()[k]);
}
}
/**
* Sample a point flat in this cell, keeping parameters fixed
*/
template<class RndGenerator>
void sampleFlatPoint(std::vector<double>& p,
const std::vector<bool>& parameterFlags,
RndGenerator& rnd) const {
assert(p.size() == lowerLeft().size());
for ( size_t k = 0; k < p.size(); ++k ) {
if ( parameterFlags[k] )
continue;
p[k] = lowerLeft()[k] + rnd.rnd()*(upperRight()[k]-lowerLeft()[k]);
}
}
/**
* Explore the cell grid, given a number of points to be sampled
* in each cell; the weights of the cell will contain the maximum
* weight encountered. If newCells is non-empty explore only these
* cells, otherwise explore all cells.
*/
template<class RndGenerator, class Function>
void explore(std::size_t nPoints,
RndGenerator& rnd,
Function& f,
std::set<SimpleCellGrid*>& newCells,
std::ostream& warn) {
unsigned long nanPoints = 0;
if ( !isLeaf() ) {
firstChild().explore(nPoints,rnd,f,newCells,warn);
secondChild().explore(nPoints,rnd,f,newCells,warn);
return;
}
if ( !newCells.empty() ) {
if ( newCells.find(this) == newCells.end() )
return;
}
std::vector<double> point(lowerLeft().size());
for ( std::size_t k = 0; k < nPoints; ++k ) {
sampleFlatPoint(point,rnd);
double w = f.evaluate(point);
- if ( isnan(w) || isinf(w) ) {
+ if ( ! std::isfinite(w) ) {
++nanPoints;
continue;
}
updateWeightInformation(point,std::abs(w));
}
if ( nanPoints ) {
warn << "Warning: " << nanPoints << " out of "
<< nPoints << " points with nan or inf weight encountered while "
<< "exploring a cell.\n" << std::flush;
}
}
/**
* Select a cell
*/
template<class RndGenerator>
SimpleCellGrid* selectCell(RndGenerator& rnd) {
if ( isLeaf() )
return this;
if ( firstChild().active() &&
secondChild().active() ) {
double p = firstChild().integral()/integral();
if ( rnd.rnd() <= p )
return firstChild().selectCell(rnd);
else
return secondChild().selectCell(rnd);
}
if ( firstChild().active() &&
!secondChild().active() )
return firstChild().selectCell(rnd);
else
return secondChild().selectCell(rnd);
}
/**
* Sample a point and return its weight
*/
template<class RndGenerator, class Function>
double sample(RndGenerator& rnd,
Function& f,
std::vector<double>& p,
bool unweight,
bool adjustReference) {
SimpleCellGrid* selected = selectCell(rnd);
selected->sampleFlatPoint(p,rnd);
double w = f.evaluate(p);
selected->updateWeightInformation(p,w);
double xw = integral()*w/selected->weight();
if ( adjustReference ) {
selected->adjustReferenceWeight(xw);
}
if ( unweight ) {
double r = selected->getReferenceWeight();
if ( r == 0. )
return xw;
double p = std::min(std::abs(xw),r)/r;
double sign = xw >= 0. ? 1. : -1.;
if ( p < 1 && rnd.rnd() > p )
xw = 0.;
else
xw = sign*std::max(std::abs(xw),r);
}
return xw;
}
/**
* Sample a point and return its weight
*/
template<class RndGenerator, class Function>
std::pair<double,double> generate(RndGenerator& rnd,
Function& f,
std::vector<double>& p) {
SimpleCellGrid* selected = selectCell(rnd);
selected->sampleFlatPoint(p,rnd);
double w = f.evaluate(p);
selected->updateWeightInformation(p,w);
return std::make_pair(w,selected->weight());
}
/**
* Sample a point and return its weight
*/
template<class RndGenerator, class Function>
std::pair<double,double> generate(RndGenerator& rnd,
Function& f,
std::vector<double>& p,
const std::vector<bool>& parameterFlags) {
SimpleCellGrid* selected = selectCell(rnd);
selected->sampleFlatPoint(p,parameterFlags,rnd);
double w = f.evaluate(p);
selected->updateWeightInformation(p,w);
return std::make_pair(w,selected->weight());
}
public:
/**
* Fill CellGrid data from an XML element
*/
virtual void fromXML(const XML::Element&);
/**
* Return an XML element for the data of this CellGrid
*/
virtual XML::Element toXML() const;
private:
/**
* Weight information for adaption steps
*/
std::vector<std::pair<Counter,Counter> > theWeightInformation;
/**
* The reference weight to be used for unweighting
*/
double theReferenceWeight;
};
}
#endif // EXSAMPLE_SimpleCellGrid_hpp_included
diff --git a/Sampling/GeneralSampler.cc b/Sampling/GeneralSampler.cc
--- a/Sampling/GeneralSampler.cc
+++ b/Sampling/GeneralSampler.cc
@@ -1,1036 +1,1065 @@
// -*- 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 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 the grid adaption\n"
- << "when there have been significant 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::buildStorage();
if ( prefix.empty() )
prefix = "./";
else if ( *prefix.rbegin() != '/' )
prefix += "/";
name << prefix << "integrationJob" << jobCount;
++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"
<< " for i in $(seq 0 "<< (jobCount-1) <<");do Herwig integrate --jobid=$i "<<generator()->runName()<<".run & done\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::buildStorage();
if ( prefix.empty() )
prefix = "./";
else if ( *prefix.rbegin() != '/' )
prefix += "/";
string fname = prefix + integrationList();
ifstream jobList(fname.c_str());
if ( jobList ) {
int b = 0;
while ( jobList >> b )
binsToIntegrate.insert(b);
} else {
Repository::clog()
<< "Job list '"
<< integrationList() << "' 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 ( isnan(lastSampler()->lastWeight()) || isinf(lastSampler()->lastWeight()) ) {
+ 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/GeneralStatistics.h b/Sampling/GeneralStatistics.h
--- a/Sampling/GeneralStatistics.h
+++ b/Sampling/GeneralStatistics.h
@@ -1,314 +1,314 @@
// -*- C++ -*-
//
// GeneralStatictis.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_GeneralStatistics_H
#define Herwig_GeneralStatistics_H
//
// This is the declaration of the GeneralStatistics class.
//
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig/Utilities/XML/Element.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief General Monte Carlo statistics.
*
*/
class GeneralStatistics {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
GeneralStatistics()
: theMaxWeight(0.), theMinWeight(Constants::MaxDouble),
theSumWeights(0.), theSumSquaredWeights(0.), theSumAbsWeights(0.),
theSelectedPoints(0), theAcceptedPoints(0),
theNanPoints(0), theAllPoints(0),
theLastWeight(0.) {}
/**
* The destructor.
*/
virtual ~GeneralStatistics();
//@}
public:
/**
* Return the last calculated chi^2.
*/
virtual double chi2() const { return 0.; }
/**
* Reset these statistics.
*/
void reset() {
*this = GeneralStatistics();
}
public:
/**
* Return the last weight encountered.
*/
double lastWeight() const { return theLastWeight; }
/**
* Return the maximum absolute weight
*/
double maxWeight() const { return theMaxWeight; }
/**
* Return the minimum absolute weight
*/
double minWeight() const { return theMinWeight; }
/**
* Set the maximum absolute weight
*/
void maxWeight(double w) { theMaxWeight = w; }
/**
* Set the minimum absolute weight
*/
void minWeight(double w) { theMinWeight = w; }
/**
* Return the sum of weights
*/
double sumWeights() const { return theSumWeights; }
/**
* Return the sum of squared weights
*/
double sumSquaredWeights() const { return theSumSquaredWeights; }
/**
* Return the sum of absolute weights
*/
double sumAbsWeights() const { return theSumAbsWeights; }
/**
* Return the number of selected points.
*/
unsigned long selectedPoints() const { return theSelectedPoints; }
/**
* Return the nnumber of accepted points.
*/
unsigned long acceptedPoints() const { return theAcceptedPoints; }
/**
* Return the number of points where a nan or inf weight has been
* encountered.
*/
unsigned long nanPoints() const { return theNanPoints; }
/**
* Return the number of all points.
*/
unsigned long allPoints() const { return theAllPoints; }
/**
* Return the average weight.
*/
virtual double averageWeight() const {
return selectedPoints() > 0 ? sumWeights()/selectedPoints() : 0.;
}
/**
* Return the average absolute weight.
*/
virtual double averageAbsWeight() const {
return selectedPoints() > 0 ? sumAbsWeights()/selectedPoints() : 0.;
}
/**
* Return the variance of weights.
*/
double weightVariance() const {
return
selectedPoints() > 1 ?
abs(sumSquaredWeights() - sqr(sumWeights())/selectedPoints())/(selectedPoints()-1) : 0.;
}
/**
* Return the variance of absolute weights.
*/
double absWeightVariance() const {
return
selectedPoints() > 1 ?
abs(sumSquaredWeights() - sqr(sumAbsWeights())/selectedPoints())/(selectedPoints()-1) : 0.;
}
/**
* Return the variance of the average weight.
*/
virtual double averageWeightVariance() const {
return selectedPoints() > 1 ? weightVariance()/selectedPoints() : 0.;
}
/**
* Return the variance of the average absolute weight.
*/
virtual double averageAbsWeightVariance() const {
return selectedPoints() > 1 ? absWeightVariance()/selectedPoints() : 0;
}
/**
* Select an event
*/
virtual void select(double weight, bool doIntegral = true) {
- if ( isnan(weight) || isinf(weight) ) {
+ if ( ! isfinite(weight) ) {
theLastWeight = weight;
theNanPoints += 1;
theAllPoints += 1;
return;
}
theLastWeight = weight;
theMaxWeight = max(theMaxWeight,abs(weight));
theMinWeight = min(theMinWeight,abs(weight));
if ( !doIntegral )
return;
theSumWeights += weight;
theSumSquaredWeights += sqr(weight);
theSumAbsWeights += abs(weight);
theSelectedPoints += 1;
theAllPoints += 1;
}
/**
* Accept an event.
*/
virtual void accept() {
theAcceptedPoints += 1;
}
/**
* Reject an event.
*/
virtual void reject() {
- if ( isnan(lastWeight()) || isinf(lastWeight()) ) {
+ if ( ! isfinite(lastWeight()) ) {
theNanPoints -= 1;
theAllPoints -= 1;
return;
}
theSumWeights -= lastWeight();
theSumSquaredWeights -= sqr(lastWeight());
theSumAbsWeights -= abs(lastWeight());
theSelectedPoints -= 1;
theAcceptedPoints -= 1;
theAllPoints -= 1;
}
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 put(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 get(PersistentIStream & is);
//@}
/**
* Fill statistics data from an XML element
*/
void fromXML(const XML::Element&);
/**
* Return an XML element for the data of this statistics
*/
XML::Element toXML() const;
private:
/**
* The maximum weight encountered.
*/
double theMaxWeight;
/**
* The minimum weight encountered.
*/
double theMinWeight;
/**
* The sum of weights.
*/
double theSumWeights;
/**
* The sum of weights squared.
*/
double theSumSquaredWeights;
/**
* The sum of absolute values of weights
*/
double theSumAbsWeights;
/**
* The number of selected points
*/
unsigned long theSelectedPoints;
/**
* The number of accepted points
*/
unsigned long theAcceptedPoints;
/**
* The number of points where an nan or inf weight was encountered.
*/
unsigned long theNanPoints;
/**
* The number of all points.
*/
unsigned long theAllPoints;
/**
* The last weight encountered
*/
double theLastWeight;
};
inline PersistentOStream& operator<<(PersistentOStream& os, const GeneralStatistics& s) {
s.put(os); return os;
}
inline PersistentIStream& operator>>(PersistentIStream& is, GeneralStatistics& s) {
s.get(is); return is;
}
}
#endif /* Herwig_GeneralStatistics_H */
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 ( isnan(wgt) || isinf(wgt) ) wgt = 0;
+ 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/Sampling/exsample/binary_tree.h b/Sampling/exsample/binary_tree.h
--- a/Sampling/exsample/binary_tree.h
+++ b/Sampling/exsample/binary_tree.h
@@ -1,883 +1,883 @@
// -*- C++ -*-
//
// binary_tree.h is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
//
// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
//
// ExSample is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
#ifndef EXSAMPLE_binary_tree_h_included
#define EXSAMPLE_binary_tree_h_included
#include "utility.h"
namespace exsample {
/// \brief binary_tree represents a binary tree with the ability to
/// `cascade' visitor objects down the tree
template<class Value>
class binary_tree {
public:
///@name type definitions
//@{
/// define the object type
typedef Value value_type;
//@}
public:
///@name constructors
//@{
/// default constructor
binary_tree()
: neighbours_(),
parent_(), value_(),
children_()
{ }
/// construct giving key/cell and parent
binary_tree(const value_type& thevalue,
binary_tree * theparent = 0)
: neighbours_(), parent_(theparent),
value_(new value_type(thevalue)),
children_()
{ }
/// binary_tree has a strict ownership; on copying
/// binary trees ownership is transferred
binary_tree(const binary_tree& x)
: neighbours_(x.neighbours_),
parent_(x.parent_), value_(),
children_() {
assert(x.root());
binary_tree& nc_x = const_cast<binary_tree&>(x);
value_.swap(nc_x.value_);
children_.first.swap(nc_x.children_.first);
children_.second.swap(nc_x.children_.second);
nc_x.parent_ = 0;
nc_x.neighbours_.first = 0;
nc_x.neighbours_.second = 0;
}
/// binary_tree has a strict ownership; on copying
/// binary trees ownership is transferred
binary_tree& operator=(const binary_tree& x) {
if (this == &x)
return *this;
assert(x.root());
binary_tree& nc_x = const_cast<binary_tree&>(x);
value_.swap(nc_x.value_);
children_.first.swap(nc_x.children_.first);
children_.second.swap(nc_x.children_.second);
neighbours_ = x.neighbours_;
parent_ = x.parent_;
nc_x.parent_ = 0;
nc_x.neighbours_.first = 0;
nc_x.neighbours_.second = 0;
return *this;
}
//@}
///@name standard-conforming leaf iterators
//@{
public:
class const_iterator;
/// iterator
class iterator {
public:
///@name type definitions for iterator traits
//@{
/// define the iterator category
typedef std::bidirectional_iterator_tag iterator_category;
/// define the difference_type
typedef int difference_type;
/// define the value type
typedef Value value_type;
/// define the reference type
typedef value_type& reference;
/// define the pointer type
typedef value_type * pointer;
//@}
public:
///@name constructors
//@{
/// default constructor
iterator() : pointee(0), post_end(0), pre_begin(0) { }
/// constructor taking pointee
iterator(binary_tree * p, std::size_t end = 0)
: pointee(p), post_end(end), pre_begin(0) { }
//@
public:
///@name comparisons
//@{
/// comparison
bool operator==(const iterator& x) const {
return ((pointee == x.pointee) &&
(post_end == x.post_end) &&
(pre_begin == x.pre_begin));
}
/// comparison
bool operator!=(const iterator& x) const { return !(*this == x); }
//@}
public:
///@name derefrence and indirection
//@{
/// dereference
reference operator*() { return pointee->value(); }
/// indirection
pointer operator->() { return &**this; }
/// return reference to the node
binary_tree& node() { return *pointee; }
//@}
/// return raw pointer to the element pointed to
binary_tree * get() const { return pointee; }
///@name biderectional iterator increment/decrements
//@{
/// pre-increment
iterator& operator++() {
if (post_end) { ++post_end; return *this; }
if (pre_begin) { --pre_begin; return *this; }
if(!(pointee->right_neighbour())) { post_end = 1; return *this; }
pointee = pointee->right_neighbour();
return *this;
}
/// pre-decrement
iterator& operator--() {
if (post_end) { --post_end; return *this; }
if (pre_begin) { ++pre_begin; return *this; }
if(!(pointee->left_neighbour())) { pre_begin = 1; return *this; }
pointee = pointee->left_neighbour();
return *this;
}
/// post-increment
iterator operator++(int) {
iterator tmp = *this;
++(*this);
return tmp;
}
/// post-decrement
iterator operator--(int) {
iterator tmp = *this;
--(*this);
return tmp;
}
//@}
private:
/// friend for conversion
friend class const_iterator;
/// the node pointed to
binary_tree * pointee;
/// the distance from --end() (if above --end())
std::size_t post_end;
/// the distance from begin() (if below begin())
std::size_t pre_begin;
};
/// return begin iterator
iterator begin() { return iterator(left_most()); }
/// return end iterator
iterator end() { return iterator(right_most(),1); }
/// return global begin iterator
iterator global_begin() {
if (!root())
return parent().global_begin();
return iterator(left_most());
}
/// return global end iterator
iterator global_end() {
if (!root())
return parent().global_end();
return iterator(right_most(),1);
}
/// const_iterator
class const_iterator {
public:
///@name type definitions for iterator traits
//@{
/// define the iterator category
typedef std::bidirectional_iterator_tag iterator_category;
/// define the difference type
typedef int difference_type;
/// define the value type
typedef const Value value_type;
/// define the reference type
typedef const value_type& reference;
/// define the pointer type
typedef const value_type * pointer;
//@}
public:
///@name constructors
//@{
/// default constructor
const_iterator() : pointee(0), post_end(0), pre_begin(0) { }
/// constructor taking pointee
const_iterator(const binary_tree * p, std::size_t end = 0)
: pointee(p), post_end(end), pre_begin(0) { }
/// conversion from iterator
const_iterator(const iterator& x)
: pointee(x.pointee), post_end(x.post_end), pre_begin(x.pre_begin) { }
//@}
public:
///@name comparisons
//@{
/// comparison
bool operator==(const const_iterator& x) const {
return ((pointee == x.pointee) &&
(post_end == x.post_end) &&
(pre_begin == x.pre_begin));
}
/// comparison
bool operator!=(const const_iterator& x) const { return !(*this == x); }
//@}
public:
///@name dereference and indirection
//@{
/// dereference
reference operator*() const { return pointee->value(); }
/// indirection
pointer operator->() const { return &**this; }
/// return reference to the node
const binary_tree& node() const { return *pointee; }
//@}
///@name biderectional iterator increment/decrements
//@{
/// pre-increment
const_iterator& operator++() {
if (post_end) { ++post_end; return *this; }
if (pre_begin) { --pre_begin; return *this; }
if(!(pointee->right_neighbour())) { post_end = 1; return *this; }
pointee = pointee->right_neighbour();
return *this;
}
/// pre-decrement
const_iterator& operator--() {
if (post_end) { --post_end; return *this; }
if (pre_begin) { ++pre_begin; return *this; }
if(!(pointee->left_neighbour())) { pre_begin = 1; return *this; }
pointee = pointee->left_neighbour();
return *this;
}
/// post-increment
const_iterator operator++(int) {
const_iterator tmp = *this;
++(*this);
return tmp;
}
/// post-decrement
const_iterator operator--(int) {
const_iterator tmp = *this;
--(*this);
return tmp;
}
//@}
private:
/// the node pointed to
const binary_tree * pointee;
/// the distance from --end() (if above --end())
std::size_t post_end;
/// the distance from begin() (if below begin())
std::size_t pre_begin;
};
/// return begin const_iterator
const_iterator begin() const { return const_iterator(left_most()); }
/// return end const_iterator
const_iterator end() const { return const_iterator(right_most(),1); }
/// return global begin iterator
const_iterator global_begin() const {
if (!root())
return parent().global_begin();
return iterator(left_most());
}
/// return global end iterator
const_iterator global_end() const {
if (!root())
return parent().global_end();
return iterator(right_most(),1);
}
private:
/// set the left neighbour
void left_neighbour(binary_tree * n) { neighbours_.first = n; }
/// set the right neighbour
void right_neighbour(binary_tree * n) { neighbours_.second = n; }
/// get the left neighbour
binary_tree * left_neighbour() const { return neighbours_.first; }
/// get the right neighbour
binary_tree * right_neighbour() const { return neighbours_.second; }
/// return the left-most leaf
binary_tree * left_most() {
if(leaf()) return this;
return left_child().left_most();
}
/// return the right-most leaf
binary_tree * right_most() {
if(leaf()) return this;
return right_child().right_most();
}
/// return the left-most leaf
const binary_tree * left_most() const {
if(leaf()) return this;
return left_child().left_most();
}
/// return the right-most leaf
const binary_tree * right_most() const {
if(leaf()) return this;
return right_child().right_most();
}
/// the iterator is a good friend
friend class binary_tree<value_type>::iterator;
/// the iterator is a good friend
friend class binary_tree<value_type>::const_iterator;
/// the left and right neighbours of this node
std::pair<binary_tree*,binary_tree*> neighbours_;
//@}
public:
/// return true, if this node is empty
bool empty() const { return root() && leaf() && !value_; }
/// clear this node
void clear() {
neighbours_ = std::make_pair<binary_tree*,binary_tree*>(0,0);
parent_ = 0;
value_.reset(0);
if (!leaf()) {
left_child().clear();
right_child().clear();
}
children_.first.reset(0);
children_.second.reset(0);
}
public:
/// split this node
std::pair<iterator,iterator> split(std::pair<value_type,value_type> children) {
assert(leaf());
children_.first.reset(new binary_tree(children.first,this));
children_.second.reset(new binary_tree(children.second,this));
children_.first->left_neighbour(neighbours_.first);
children_.first->right_neighbour(children_.second.get());
children_.second->left_neighbour(children_.first.get());
children_.second->right_neighbour(neighbours_.second);
// adjust original neighbours
if(neighbours_.first) {
neighbours_.first->right_neighbour(children_.first.get());
}
if (neighbours_.second) {
neighbours_.second->left_neighbour(children_.second.get());
}
neighbours_.first = 0; neighbours_.second = 0;
return std::make_pair(iterator(children_.first.get()),iterator(children_.second.get()));
}
public:
/// select using a selector
template<class Selector>
iterator select(const Selector& selector) {
if(leaf()) {
bool use = selector.use(value());
if (use) return iterator(this);
return global_end();
}
std::pair<bool,bool> which(selector.use(value(),left_child().value(),right_child().value()));
assert(!which.first || !which.second);
if (!which.first && !which.second) {
return global_end();
}
if (which.first) {
return left_child().select(selector);
}
else {
return right_child().select(selector);
}
return global_end();
}
/// generate a hash value for the sub-tree
/// selected by the given selector object
template<class Selector, unsigned long bits>
void subtree_hash(const Selector& selector, bit_container<bits>& bhash) {
bhash = bit_container<bits>();
unsigned long pos = 0;
do_subtree_hash<Selector,bits>(selector,bhash,pos);
}
/// accumulate values using a binary function
/// and accessor object
template<class Accessor, class BinaryOp>
typename BinaryOp::result_type accumulate(const Accessor& acc,
BinaryOp binary_op) const {
if (!leaf()) {
return
binary_op(left_child().accumulate(acc,binary_op),
right_child().accumulate(acc,binary_op));
}
return acc.get(value(),true);
}
/// accumulate values only from branches
/// matching a Selector
template<class Selector, class Accessor, class BinaryOp>
typename BinaryOp::result_type accumulate(const Selector& selector,
const Accessor& acc,
BinaryOp binary_op) const {
if (!leaf()) {
std::pair<bool,bool> which(selector.use(value(),left_child().value(),right_child().value()));
assert(which.first || which.second);
if (which.first && which.second) {
return
binary_op(left_child().accumulate(selector,acc,binary_op),
right_child().accumulate(selector,acc,binary_op));
} else if (which.first) {
return left_child().accumulate(selector,acc,binary_op);
} else if (which.second) {
return right_child().accumulate(selector,acc,binary_op);
}
}
return acc.get(value(),true);
}
/// accumulate values using a binary function
/// and accessor object, storing intermediate
/// values in nodes
template<class Accessor, class BinaryOp>
typename BinaryOp::result_type tree_accumulate(const Accessor& acc,
BinaryOp binary_op) {
if (!leaf()) {
acc.set(value()) =
binary_op(left_child().tree_accumulate(acc,binary_op),
right_child().tree_accumulate(acc,binary_op));
return acc.get(value(),false);
}
acc.set(value()) = acc.get(value(),true);
return acc.get(value(),true);
}
/// accumulate values only from branches
/// matching a Selector
template<class Selector, class Accessor, class BinaryOp>
typename BinaryOp::result_type tree_accumulate(const Selector& selector,
const Accessor& acc,
BinaryOp binary_op) {
if (!leaf()) {
std::pair<bool,bool> which(selector.use(value(),left_child().value(),right_child().value()));
assert(which.first || which.second);
if (which.first && which.second) {
acc.set(value()) =
binary_op(left_child().tree_accumulate(selector,acc,binary_op),
right_child().tree_accumulate(selector,acc,binary_op));
} else if (which.first) {
acc.set(value()) = left_child().tree_accumulate(selector,acc,binary_op);
} else if (which.second) {
acc.set(value()) = right_child().tree_accumulate(selector,acc,binary_op);
}
return acc.get(value(),false);
}
acc.set(value()) = acc.get(value(),true);
return acc.get(value(),true);
}
/// forward propagate a visitor to all children nodes
template<class Visitor>
void cascade(Visitor visitor) const {
if (leaf()) {
visitor.visit(value());
return;
} else visitor.visit(value(),left_child().value(),right_child().value());
left_child().cascade(visitor);
right_child().cascade(visitor);
}
/// succesively split using a generator
template<class Generator>
void generate(Generator generator) {
if (root())
value_.reset(new value_type(generator.root()));
if (generator.split()) {
std::pair<iterator,iterator> ch = split(generator.generate(value()));
ch.first.node().generate(generator);
ch.second.node().generate(generator);
}
}
public:
///@name Public member access
//@{
/// return the value held by this node
value_type& value() { return *value_; }
/// return the value held by this node
const value_type& value() const { return *value_; }
/// return true, if this is the root node
bool root() const { return !parent_; }
/// return true, if this node has got children
bool leaf() const { return !(children_.first.get() && children_.second.get()); }
//@}
public:
///@name put and get from streams
//@{
/// forward visitor writing out the tree to given ostream
template<class OStream>
struct ostream_visitor {
/// construct from ostream reference
explicit ostream_visitor(OStream& os) : os_(&os), first_time_(true) {}
/// visit a leaf node
void visit(const value_type&) {
(*os_) << "end_branch";
ostream_traits<OStream>::separator(*os_);
}
/// visit a branching
void visit(const value_type& parent,
const value_type& left, const value_type& right) {
if (first_time_) {
(*os_) << "root_node";
ostream_traits<OStream>::separator(*os_);
parent.put(*os_);
first_time_ = false;
}
(*os_) << "left_child";
ostream_traits<OStream>::separator(*os_);
left.put(*os_);
(*os_) << "right_child";
ostream_traits<OStream>::separator(*os_);
right.put(*os_);
}
private:
/// pointer to the ostream to write to
OStream* os_;
/// whether we are at the or not
bool first_time_;
};
/// generator reading binary tree from istream
template<class IStream>
struct istream_generator {
/// construct from istream reference
explicit istream_generator(IStream& is)
: is_(&is), children_(), tag_("") {}
/// copy constructor
istream_generator(const istream_generator& x)
: is_(x.is_), children_(), tag_("") {}
/// read the root node
value_type root() {
*is_ >> tag_;
assert(tag_ == "root_node");
value_type rnode;
rnode.get(*is_);
return rnode;
}
/// read children nodes
bool split() {
*is_ >> tag_;
if (tag_ == "end_branch") {
return false;
}
assert (tag_ == "left_child");
children_.first.get(*is_);
*is_ >> tag_;
assert(tag_ == "right_child");
children_.second.get(*is_);
return true;
}
/// return the children generated
std::pair<value_type,value_type> generate(const value_type&) {
return children_;
}
/// initialize a leaf
void initialize_leaf(const value_type&) {}
private:
/// pointer to the istream used
IStream* is_;
/// the children currently handled
std::pair<value_type,value_type> children_;
/// temporary storage for tags
std::string tag_;
};
/// put to ostream
template<class OStream>
void put(OStream& os) const {
if (empty()) {
os << "empty";
ostream_traits<OStream>::separator(os);
return;
} else if (root() && leaf()) {
os << "root_only";
ostream_traits<OStream>::separator(os);
value().put(os);
return;
} else {
os << "non_empty";
ostream_traits<OStream>::separator(os);
}
assert(root());
cascade(ostream_visitor<OStream>(os));
}
/// get from istream
template<class IStream>
void get(IStream& is) {
std::string state;
is >> state;
if (state == "empty") {
return;
}
if (state == "root_only") {
value_.reset(new value_type());
value().get(is);
return;
}
assert(empty());
generate(istream_generator<IStream>(is));
}
//@}
private:
/// calculate hash value
template<class Selector, unsigned long bits>
void do_subtree_hash(const Selector& selector,
bit_container<bits>& current,
unsigned long& position,
bool selected = true) const {
if (!leaf()) {
std::pair<bool,bool> which(false,false);
if (selected)
which = selector.use(value(),left_child().value(),right_child().value());
current.bit(position,which.first);
current.bit(position+1,which.second);
position += 2;
left_child().do_subtree_hash(selector,current,position,which.first && selected);
right_child().do_subtree_hash(selector,current,position,which.second && selected);
}
}
private:
///@name private member access
//@{
/// return the parent of this node
binary_tree& parent() { assert(parent_); return *parent_; }
/// return the parent of this node
const binary_tree& parent() const { assert(parent_); return *parent_; }
/// return the left child of this node
binary_tree& left_child() { assert(children_.first.get()); return *children_.first; }
/// return the left child of this node
const binary_tree& left_child() const { assert(children_.first.get()); return *children_.first; }
/// return the right child of this node
binary_tree& right_child() { assert(children_.second.get()); return *children_.second; }
/// return the right child of this node
const binary_tree& right_child() const { assert(children_.second.get()); return *children_.second; }
//@}
private:
/// the parent of this node
binary_tree * parent_;
/// the cell held by this node
- boost::scoped_ptr<value_type> value_;
+ std::unique_ptr<value_type> value_;
/// the children of this node
- std::pair<boost::scoped_ptr<binary_tree>,
- boost::scoped_ptr<binary_tree> > children_;
+ std::pair<std::unique_ptr<binary_tree>,
+ std::unique_ptr<binary_tree> > children_;
};
}
#endif // EXSAMPLE_binary_tree_h_included
diff --git a/Sampling/exsample/cell.h b/Sampling/exsample/cell.h
--- a/Sampling/exsample/cell.h
+++ b/Sampling/exsample/cell.h
@@ -1,307 +1,307 @@
// -*- C++ -*-
//
// cell.h is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
//
// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
//
// ExSample is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
#ifndef EXSAMPLE_cell_h_included
#define EXSAMPLE_cell_h_included
#include "utility.h"
#include "adaption_info.h"
#include "statistics.h"
namespace exsample {
/// \brief Information contained in a leaf cell
class cell_info {
public:
/// the default constructor
cell_info();
/// construct from boundaries and adaption info
cell_info(const std::vector<double>& ll,
const std::vector<double>& ur,
const adaption_info& ainfo);
/// construct from boundaries, flags for variables to be sampled,
/// and adaption info
cell_info(const std::vector<double>& ll,
const std::vector<double>& ur,
const std::vector<bool>& sampled_variables,
const adaption_info& ainfo);
public:
/// generate a flat trial point in this cell
template<class Random>
void select(Random&,
std::vector<double>&);
/// generate a flat trial point in this cell
/// only for the variables falgged as true
template<class Random>
void select(Random&,
std::vector<double>&,
const std::vector<bool>&);
/// indicate a function value for the given point
void selected(const std::vector<double>&,
double,
const adaption_info&);
/// indicate that a point has been
/// accepted in this cell
void accept() { ++accepted_; }
/// reject a previously accepted event
void reject() { --accepted_; }
public:
/// return true, if below efficiency threshold
bool bad(const adaption_info& ainfo) const {
return ((static_cast<double>(accepted_)/static_cast<double>(attempted_)) <
ainfo.efficiency_threshold);
}
/// suggest a split and indicate wether it is worth
/// to be performed
std::pair<std::size_t,double> get_split(const adaption_info&,
bool&) const;
/// explore this cell performing a flat sampling,
/// updating the given statistics object and pre-filling
/// the efficiency histogram by a trial unweighting
template<class Random, class Function, class SlaveStatistics>
void explore(Random&, const adaption_info&, Function*, statistics*,
SlaveStatistics& opt, double detuning);
/// explore this cell in a more refined way, which
/// is however not suited for already calculating integrals
/// and stuff
template<class Random, class Function>
void explore(Random&, const adaption_info&, Function*,
double detuning);
public:
/// get the current overestimate
double overestimate() const { return overestimate_; }
/// return the position of the last maximum
const std::vector<double>& last_max_position() const { return last_max_position_; }
/// set the current overestimate and maximum position
void overestimate(double v, const std::vector<double>& pos,
double detuning) {
overestimate_ = detuning * v;
last_max_position_ = pos;
}
/// get the volume
double volume() const { return volume_; }
/// get the lower left corner
const std::vector<double>& lower_left() const { return lower_left_; }
/// get the upper right corner
const std::vector<double>& upper_right() const { return upper_right_; }
/// get the number of attempted events
unsigned long attempted() const { return attempted_; }
/// get the number of accepted events
unsigned long accepted() const { return accepted_; }
public:
/// return the number of missing events
/// for the given parameter bin id
int parametric_missing(const bit_container<parameter_hash_bits>& id) const;
/// set the number of missing events
/// for the given parameter bin id
void parametric_missing(const bit_container<parameter_hash_bits>& id, int n);
/// increase to the number of missing events
/// for the given parameter bin id
void increase_parametric_missing(const bit_container<parameter_hash_bits>& id);
/// decrease to the number of missing events
/// for the given parameter bin id
void decrease_parametric_missing(const bit_container<parameter_hash_bits>& id);
/// return true, if the cell is compensating in
/// at least one parameter bin
bool parametric_compensating() const {
return !parametric_missing_map_.empty();
}
/// return true, if the cell contains the
/// indicated parameter point
bool contains_parameter(const std::vector<double>& point,
const std::vector<bool>& sampled) const;
public:
/// put to ostream
template<class OStream>
void put(OStream& os) const;
/// get from istream
template<class IStream>
void get(IStream& is);
private:
/// the value of the overestimate in this cell
double overestimate_;
/// the volume of this cell
double volume_;
/// the lower left corner of this cell
std::vector<double> lower_left_;
/// the upper right corner of this cell
std::vector<double> upper_right_;
/// midpoint of this cell
std::vector<double> mid_point_;
/// the position of the last encountered
/// maximum in this cell
std::vector<double> last_max_position_;
/// left-right statistics of average weight
std::vector<std::pair<double,double> > avg_weight_;
/// the number of attempts in this cell
unsigned long attempted_;
/// the number of accepted events in this cell
unsigned long accepted_;
/// an optional map of parameter bin ids
/// to the number of missing events
std::map<bit_container<parameter_hash_bits>,int> parametric_missing_map_;
};
/// \brief the general cell class
class cell {
public:
/// default constructor
cell();
/// construct from boundaries and adaption info
cell(const std::vector<double>& ll,
const std::vector<double>& ur,
const adaption_info& ainfo);
/// construct from boundaries, flags for variables to be sampled,
/// and adaption info
cell(const std::vector<double>& ll,
const std::vector<double>& ur,
const std::vector<bool>& sampled_variables,
const adaption_info& ainfo);
/// copy constructor
cell(const cell& x);
/// assignment
cell& operator=(const cell& x);
public:
/// split this cell, exploring the
/// child not containing the current overestimate
template<class Random, class Function>
std::pair<cell,cell> split(std::pair<std::size_t,double> split_d,
Random& rnd_gen,
Function* f,
const adaption_info& ainfo,
const std::vector<bool>& sampled =
std::vector<bool>(),
double detuning = 1.0);
public:
/// return the split dimension
std::size_t split_dimension() const { return split_dimension_; }
/// return the split value
double split_point() const { return split_point_; }
/// return the integral
double integral() const { return integral_; }
/// access the integral
double& integral() { return integral_; }
/// set the integral
void integral(double v) { integral_ = v; }
/// access the number of missing events
int& missing_events() { return missing_events_; }
/// return the number of missing events
int missing_events() const { return missing_events_; }
/// set the number of missing events
void missing_events(int n) { missing_events_ = n; }
/// access the cell_info object
cell_info& info() { assert(cell_info_); return *cell_info_; }
/// return the cell_info object
const cell_info& info() const { assert(cell_info_); return *cell_info_; }
public:
/// put to ostream
template<class OStream>
void put(OStream& os) const;
/// get from istream
template<class IStream>
void get(IStream& is);
private:
/// the dimension along this cell
/// was split
std::size_t split_dimension_;
/// the value, where this cell was split
double split_point_;
/// the integral of the absolute value
/// of the overestimate over all the
/// children cells
double integral_;
/// the number of missing events in this cell
int missing_events_;
/// a pointer to the cell info object,
/// if this is a leaf cell
- boost::scoped_ptr<cell_info> cell_info_;
+ std::unique_ptr<cell_info> cell_info_;
};
}
#include "cell.icc"
#endif // EXSAMPLE_cell_h_included
diff --git a/Sampling/exsample/cell.icc b/Sampling/exsample/cell.icc
--- a/Sampling/exsample/cell.icc
+++ b/Sampling/exsample/cell.icc
@@ -1,490 +1,490 @@
// -*- C++ -*-
//
// cell.icc is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
//
// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
//
// ExSample is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
namespace exsample {
template<class Random>
void cell_info::select (Random& rnd_gen,
std::vector<double>& p) {
std::transform(lower_left_.begin(),lower_left_.end(),
upper_right_.begin(),p.begin(),
rnd_gen);
++attempted_;
}
template<class Random>
void cell_info::select (Random& rnd_gen,
std::vector<double>& p,
const std::vector<bool>& sample) {
conditional_transform(lower_left_.begin(),lower_left_.end(),
upper_right_.begin(),sample.begin(),
p.begin(),rnd_gen);
++attempted_;
}
template<class Random, class Function, class SlaveStatistics>
void cell_info::explore(Random& rnd_gen,
const adaption_info& ainfo,
Function* function, statistics* stats,
SlaveStatistics& opt,
double detuning) {
function->start_presampling();
unsigned long n_sampled = 0;
std::vector<double> ll = lower_left_;
std::vector<double> ur = upper_right_;
double val = 0.;
std::vector<double> pos (ll.size());
std::vector< std::pair<double,std::vector<double> > > vals;
unsigned long ivalnonzero = 0;
while (n_sampled < ainfo.presampling_points) {
std::transform(ll.begin(),ll.end(),
ur.begin(),pos.begin(),
rnd_gen);
val = function->evaluate(pos) * detuning;
vals.push_back( std::pair<double,std::vector<double> > (val,pos) );
if ( val != 0 ) ivalnonzero++;
++n_sampled;
}
while ( ivalnonzero > 0 ) {
double avg = 0;
double err = 0;
double maxval = 0;
std::vector<double> maxpos (ll.size());
unsigned long imax;
for ( unsigned long ival=0; ival < vals.size(); ival++ ) {
val = std::abs(vals[ival].first);
if ( val == 0 ) continue;
avg += val;
err += sqr(val);
if ( val > maxval ) {
maxval = val;
maxpos = vals[ival].second;
imax = ival;
}
}
avg /= ivalnonzero;
err /= ivalnonzero;
err = sqrt(err-sqr(avg));
if ( maxval <= avg+sqrt(ivalnonzero/2.)*err ) {
overestimate_ = maxval;
last_max_position_ = maxpos;
break;
}
vals.erase(vals.begin()+imax);
ivalnonzero--;
}
for ( unsigned long ival=0; ival < vals.size(); ival++ ) {
val = vals[ival].first;
stats->presampled(val);
opt.select(val);
selected(pos,std::abs(val),ainfo);
}
function->stop_presampling();
}
template<class Random, class Function>
void cell_info::explore (Random& rnd_gen,
const adaption_info& ainfo, Function* function,
double detuning) {
function->start_presampling();
unsigned long n_sampled = 0;
std::vector<double> ll = lower_left_;
std::vector<double> ur = upper_right_;
double val = 0.;
std::vector<double> pos (ll.size());
std::vector< std::pair<double,std::vector<double> > > vals;
while (n_sampled < ainfo.presampling_points) {
std::transform(ll.begin(),ll.end(),
ur.begin(),pos.begin(),
rnd_gen);
val = function->evaluate(pos) * detuning;
if ( std::abs(val) > 0 )
vals.push_back( std::pair<double,std::vector<double> > (std::abs(val),pos) );
++n_sampled;
}
while ( vals.size() > 0 ) {
double avg = 0;
double err = 0;
double maxval = 0;
std::vector<double> maxpos (ll.size());
unsigned long imax;
for ( unsigned long ival=0; ival < vals.size(); ival++ ) {
double thisval = vals[ival].first;
avg += thisval;
err += sqr(thisval);
if ( thisval > maxval ) {
maxval = thisval;
maxpos = vals[ival].second;
imax = ival;
}
}
avg /= vals.size();
err /= vals.size();
err = sqrt(err-sqr(avg));
if ( maxval <= avg+sqrt(vals.size()/2.)*err ) {
overestimate_ = maxval;
last_max_position_ = maxpos;
break;
}
vals.erase(vals.begin()+imax);
}
function->stop_presampling();
}
template<class OStream>
void cell_info::put (OStream& os) const {
os << overestimate_;
ostream_traits<OStream>::separator(os);
os << volume_;
ostream_traits<OStream>::separator(os);
os << lower_left_.size();
ostream_traits<OStream>::separator(os);
for (std::size_t k = 0; k < lower_left_.size(); ++k) {
os << lower_left_[k];
ostream_traits<OStream>::separator(os);
}
for (std::size_t k = 0; k < upper_right_.size(); ++k) {
os << upper_right_[k];
ostream_traits<OStream>::separator(os);
}
for (std::size_t k = 0; k < mid_point_.size(); ++k) {
os << mid_point_[k];
ostream_traits<OStream>::separator(os);
}
for (std::size_t k = 0; k < last_max_position_.size(); ++k) {
os << last_max_position_[k];
ostream_traits<OStream>::separator(os);
}
for (std::size_t k = 0; k < avg_weight_.size(); ++k) {
os << avg_weight_[k].first;
ostream_traits<OStream>::separator(os);
os << avg_weight_[k].second;
ostream_traits<OStream>::separator(os);
}
os << attempted_;
ostream_traits<OStream>::separator(os);
os << accepted_;
ostream_traits<OStream>::separator(os);
os << parametric_missing_map_.size();
ostream_traits<OStream>::separator(os);
for ( std::map<bit_container<parameter_hash_bits>,int>::const_iterator p =
parametric_missing_map_.begin(); p != parametric_missing_map_.end(); ++p ) {
p->first.put(os);
os << p->second;
ostream_traits<OStream>::separator(os);
}
}
template<class IStream>
void cell_info::get (IStream& is) {
std::size_t dim;
is >> overestimate_ >> volume_ >> dim;
lower_left_.resize(dim);
for (std::size_t k = 0; k < lower_left_.size(); ++k) {
is >> lower_left_[k];
}
upper_right_.resize(dim);
for (std::size_t k = 0; k < upper_right_.size(); ++k) {
is >> upper_right_[k];
}
mid_point_.resize(dim);
for (std::size_t k = 0; k < mid_point_.size(); ++k) {
is >> mid_point_[k];
}
last_max_position_.resize(dim);
for (std::size_t k = 0; k < last_max_position_.size(); ++k) {
is >> last_max_position_[k];
}
avg_weight_.resize(dim);
for (std::size_t k = 0; k < avg_weight_.size(); ++k) {
is >> avg_weight_[k].first >> avg_weight_[k].second;
}
is >> attempted_ >> accepted_ >> dim;
for ( size_t k = 0; k < dim; ++k ) {
bit_container<parameter_hash_bits> in;
in.get(is);
is >> parametric_missing_map_[in];
}
}
template<class Random, class Function>
std::pair<cell,cell >
cell::split (std::pair<std::size_t,double> split_d,
Random& rnd_gen,
Function* function,
const adaption_info& ainfo,
const std::vector<bool>& sampled,
double detuning) {
assert(!missing_events() && !info().parametric_compensating());
split_dimension_ = split_d.first;
split_point_ = split_d.second;
std::vector<double> lower_left1 = info().lower_left();
std::vector<double> upper_right1 = info().upper_right();
std::vector<double> lower_left2 = info().lower_left();
std::vector<double> upper_right2 = info().upper_right();
upper_right1[split_dimension_] = split_point_;
lower_left2[split_dimension_] = split_point_;
std::pair<cell,cell> children;
if (sampled.empty())
children = std::pair<cell,cell>(cell(lower_left1,upper_right1,ainfo),
cell(lower_left2,upper_right2,ainfo));
else
children = std::pair<cell,cell> (cell(lower_left1,upper_right1,sampled,ainfo),
cell(lower_left2,upper_right2,sampled,ainfo));
if (info().last_max_position()[split_dimension_] <= split_point_) {
children.first.info().overestimate(info().overestimate(),info().last_max_position(),1.0);
children.second.info().explore(rnd_gen,ainfo,function,detuning);
} else {
children.second.info().overestimate(info().overestimate(),info().last_max_position(),1.0);
children.first.info().explore(rnd_gen,ainfo,function,detuning);
}
cell_info_.reset(0);
children.first.integral(children.first.info().volume() * children.first.info().overestimate());
children.second.integral(children.second.info().volume() * children.second.info().overestimate());
return children;
}
template<class OStream>
void cell::put (OStream& os) const {
os << split_dimension_;
ostream_traits<OStream>::separator(os);
os << split_point_;
ostream_traits<OStream>::separator(os);
os << integral_;
ostream_traits<OStream>::separator(os);
os << missing_events_;
ostream_traits<OStream>::separator(os);
if (cell_info_) {
os << "has_cell_info";
ostream_traits<OStream>::separator(os);
cell_info_->put(os);
} else {
os << "has_no_cell_info";
ostream_traits<OStream>::separator(os);
}
}
template<class IStream>
void cell::get (IStream& is) {
std::string info_tag;
is >> split_dimension_ >> split_point_
>> integral_ >> missing_events_
>> info_tag;
if (info_tag == "has_cell_info") {
cell_info_.reset(new cell_info());
cell_info_->get(is);
}
}
inline cell_info::cell_info()
: overestimate_(0.), volume_(0.),
lower_left_(), upper_right_(), mid_point_(),
last_max_position_(), avg_weight_(),
attempted_(0), accepted_(0) {}
inline cell_info::cell_info(const std::vector<double>& ll,
const std::vector<double>& ur,
const adaption_info& ainfo)
: overestimate_(0.), volume_(),
lower_left_(ll), upper_right_(ur), mid_point_(),
last_max_position_(),
avg_weight_(std::vector<std::pair<double,double> >
(ainfo.dimension,std::make_pair(0.,0.))),
attempted_(0), accepted_(0) {
std::vector<double> delta;
std::transform(ur.begin(),ur.end(),
ll.begin(),std::back_inserter(delta),
std::minus<double>());
volume_ =
std::accumulate(delta.begin(),delta.end(),1.,std::multiplies<double>());
std::transform(ur.begin(),ur.end(),
ll.begin(),std::back_inserter(mid_point_),
std::plus<double>());
for (std::size_t k = 0; k < ainfo.dimension; ++k)
mid_point_[k] /= 2.;
}
inline cell_info::cell_info(const std::vector<double>& ll,
const std::vector<double>& ur,
const std::vector<bool>& sampled_variables,
const adaption_info& ainfo)
: overestimate_(0.), volume_(),
lower_left_(ll), upper_right_(ur), mid_point_(),
last_max_position_(),
avg_weight_(std::vector<std::pair<double,double> >
(ainfo.dimension,std::make_pair(0.,0.))),
attempted_(0), accepted_(0) {
std::vector<double> delta;
conditional_transform(ur.begin(),ur.end(),
ll.begin(),sampled_variables.begin(),
std::back_inserter(delta),
std::minus<double>());
volume_ =
std::accumulate(delta.begin(),delta.end(),1.,std::multiplies<double>());
std::transform(ur.begin(),ur.end(),
ll.begin(),std::back_inserter(mid_point_),
std::plus<double>());
for (std::size_t k = 0; k < ainfo.dimension; ++k)
mid_point_[k] /= 2.;
}
inline int cell_info::parametric_missing(const bit_container<parameter_hash_bits>& id) const {
std::map<bit_container<parameter_hash_bits>,int>::const_iterator mit
= parametric_missing_map_.find(id);
if (mit == parametric_missing_map_.end())
return 0;
return mit->second;
}
inline void cell_info::parametric_missing(const bit_container<parameter_hash_bits>& id, int n) {
if (n == 0) {
std::map<bit_container<parameter_hash_bits>,int>::iterator mit
= parametric_missing_map_.find(id);
if (mit != parametric_missing_map_.end())
parametric_missing_map_.erase(mit);
return;
}
parametric_missing_map_[id] = n;
}
inline void cell_info::increase_parametric_missing(const bit_container<parameter_hash_bits>& id) {
std::map<bit_container<parameter_hash_bits>,int>::iterator mit
= parametric_missing_map_.find(id);
if (mit != parametric_missing_map_.end()) {
mit->second += 1;
if (mit->second == 0) parametric_missing_map_.erase(mit);
} else parametric_missing_map_[id] = 1;
}
inline void cell_info::decrease_parametric_missing(const bit_container<parameter_hash_bits>& id) {
std::map<bit_container<parameter_hash_bits>,int>::iterator mit
= parametric_missing_map_.find(id);
if (mit != parametric_missing_map_.end()) {
mit->second -= 1;
if (mit->second == 0) parametric_missing_map_.erase(mit);
} else assert(false);
}
inline void cell_info::selected(const std::vector<double>& p,
double weight,
const adaption_info& ainfo) {
for (std::size_t k = 0; k < p.size(); ++k) {
if (ainfo.adapt[k]) {
if (p[k] < mid_point_[k])
avg_weight_[k].first += weight;
else
avg_weight_[k].second += weight;
}
}
}
inline std::pair<std::size_t,double> cell_info::get_split (const adaption_info& ainfo,
bool& worth) const {
std::size_t split_d = 0;
double gain = 0.;
for (std::size_t k = 0; k < ainfo.dimension; ++k) {
double xgain = 0.;
double left = avg_weight_[k].first;
double right = avg_weight_[k].second;
if (left+right > 0.) {
xgain = std::abs(left-right)/(left+right);
}
if (xgain > gain) {
gain = xgain;
split_d = k;
}
}
worth = (gain >= ainfo.gain_threshold);
return std::make_pair(split_d,mid_point_[split_d]);
}
inline bool cell_info::contains_parameter (const std::vector<double>& point,
const std::vector<bool>& sampled) const {
std::vector<double>::const_iterator p = point.begin();
std::vector<double>::const_iterator l = lower_left_.begin();
std::vector<double>::const_iterator u = upper_right_.begin();
std::vector<bool>::const_iterator f = sampled.begin();
for (; p < point.end(); ++p, ++f, ++l, ++u)
if (!(*f)) {
if (((*l) > (*p)) ||
((*u) < (*p)))
return false;
}
return true;
}
inline cell::cell()
: split_dimension_(0), split_point_(0.),
integral_(0.), missing_events_(0),
- cell_info_(0) {}
+ cell_info_(nullptr) {}
inline cell::cell(const std::vector<double>& ll,
const std::vector<double>& ur,
const adaption_info& ainfo)
: split_dimension_(0), split_point_(0.),
integral_(0.), missing_events_(0),
cell_info_(new cell_info(ll,ur,ainfo)) {}
inline cell::cell(const std::vector<double>& ll,
const std::vector<double>& ur,
const std::vector<bool>& sampled_variables,
const adaption_info& ainfo)
: split_dimension_(0), split_point_(0.),
integral_(0.), missing_events_(0),
cell_info_(new cell_info(ll,ur,sampled_variables,ainfo)) {}
inline cell::cell(const cell& x)
: split_dimension_(x.split_dimension_),
split_point_(x.split_point_),
integral_(x.integral_),
missing_events_(x.missing_events_),
- cell_info_(0) {
+ cell_info_(nullptr) {
if (x.cell_info_)
cell_info_.reset(new cell_info(*x.cell_info_));
}
inline cell& cell::operator=(const cell& x) {
if (this == &x)
return *this;
split_dimension_ = x.split_dimension_;
split_point_ = x.split_point_;
integral_ = x.integral_;
missing_events_ = x.missing_events_;
if (x.cell_info_)
cell_info_.reset(new cell_info(*x.cell_info_));
return *this;
}
}
diff --git a/Sampling/exsample/config.h b/Sampling/exsample/config.h
--- a/Sampling/exsample/config.h
+++ b/Sampling/exsample/config.h
@@ -1,45 +1,41 @@
// -*- C++ -*-
//
// config.h is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
//
// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
//
// ExSample is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
#ifndef EXSAMPLE_config_h_included
#define EXSAMPLE_config_h_included
#include <vector>
#include <map>
#include <set>
#include <string>
#include <cmath>
#include <cassert>
#include <climits>
#include <algorithm>
#include <numeric>
#include <limits>
-#include <boost/utility.hpp>
-#include <boost/scoped_array.hpp>
-#include <boost/scoped_ptr.hpp>
-
#define EXSAMPLE_has_ThePEG
#ifdef EXSAMPLE_has_ThePEG
#include "ThePEG/Persistency/PersistentOStream.h"
#endif // EXSAMPLE_has_ThePEG
namespace exsample {
static const unsigned long parameter_hash_bits = 512;
}
#endif // EXSAMPLE_config_h_included
diff --git a/Sampling/exsample/exponential_generator.icc b/Sampling/exsample/exponential_generator.icc
--- a/Sampling/exsample/exponential_generator.icc
+++ b/Sampling/exsample/exponential_generator.icc
@@ -1,386 +1,385 @@
// -*- C++ -*-
//
// exponential_generator.icc is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
//
// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
//
// ExSample is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
namespace exsample {
template<class Function, class Random>
void exponential_generator<Function,Random>::initialize() {
adaption_info_.dimension = function_->dimension();
adaption_info_.lower_left = function_->support().first;
adaption_info_.upper_right = function_->support().second;
if (adaption_info_.adapt.empty())
adaption_info_.adapt = std::vector<bool>(adaption_info_.dimension,true);
evolution_variable_ = function_->evolution_variable();
evolution_cutoff_ = function_->evolution_cutoff();
sample_variables_ = function_->variable_flags();
sample_other_variables_ = sample_variables_;
sample_other_variables_[evolution_variable_] = false;
last_point_.resize(adaption_info_.dimension);
parametric_selector_ = parametric_selector(&last_point_,sample_other_variables_);
exponent_selector_ = parametric_selector(&last_point_,sample_variables_);
missing_accessor_ = parametric_missing_accessor(&last_parameter_bin_);
parametric_sampler_ = parametric_sampling_selector<rnd_generator<Random> >
(&last_point_,&last_parameter_bin_,sample_other_variables_,rnd_gen_);
if (initialized_) return;
splits_ = 0;
for ( std::size_t k = 0; k < adaption_info_.dimension; ++k ) {
if ( sample_other_variables_[k] )
continue;
parameter_splits_[k].push_back(adaption_info_.lower_left[k]);
parameter_splits_[k].push_back(adaption_info_.upper_right[k]);
}
root_cell_ =
binary_tree<cell>(cell(adaption_info_.lower_left,
adaption_info_.upper_right,
sample_other_variables_,
adaption_info_));
root_cell_.value().info().explore(rnd_gen_,adaption_info_,function_,detuning_);
root_cell_.value().integral(root_cell_.value().info().volume() * root_cell_.value().info().overestimate());
last_exponent_integrand_.resize(1);
check_events_ = adaption_info_.presampling_points;
initialized_ = true;
}
template<class Function, class Random>
bool exponential_generator<Function,Random>::split () {
if (adaption_info_.freeze_grid <= accepts_)
return false;
if (compensating_)
return false;
if (!(*last_cell_).info().bad(adaption_info_)) return false;
bool dosplit = false;
std::pair<std::size_t,double> sp =
(*last_cell_).info().get_split(adaption_info_,dosplit);
if (!dosplit) return false;
if (!adaption_info_.adapt[sp.first]) return false;
if (splits_ == parameter_hash_bits/2)
return false;
++splits_;
last_cell_.node().split((*last_cell_).split(sp,rnd_gen_,function_,adaption_info_,
sample_other_variables_,detuning_));
if ( !sample_other_variables_[sp.first] ) {
if ( std::find(parameter_splits_[sp.first].begin(),parameter_splits_[sp.first].end(),sp.second)
== parameter_splits_[sp.first].end() ) {
parameter_splits_[sp.first].push_back(sp.second);
std::sort(parameter_splits_[sp.first].begin(),parameter_splits_[sp.first].end());
if ( sp.first == evolution_variable_ ) {
last_exponent_integrand_.push_back(0.);
}
}
}
did_split_ = true;
last_point_ = function_->parameter_point();
root_cell_.tree_accumulate(parametric_selector_,integral_accessor_,std::plus<double>());
exponents_.clear();
get_exponent();
return true;
}
template<class Function, class Random>
void exponential_generator<Function,Random>::get_exponent () {
last_parameter_bin_.reset();
root_cell_.subtree_hash (exponent_selector_,last_parameter_bin_);
last_exponent_ = exponents_.find(last_parameter_bin_);
if (last_exponent_ != exponents_.end())
return;
exponents_[last_parameter_bin_] = linear_interpolator();
last_exponent_ = exponents_.find(last_parameter_bin_);
double old_evo = last_point_[evolution_variable_];
std::vector<double>::iterator exp_it = last_exponent_integrand_.begin();
for (std::vector<double>::iterator esp = parameter_splits_[evolution_variable_].begin();
- esp < boost::prior(parameter_splits_[evolution_variable_].end()); ++esp, ++exp_it) {
- last_point_[evolution_variable_] = (*esp + *boost::next(esp))/2.;
+ esp < std::prev(parameter_splits_[evolution_variable_].end()); ++esp, ++exp_it) {
+ last_point_[evolution_variable_] = (*esp + *std::next(esp))/2.;
*exp_it = root_cell_.accumulate(parametric_selector_,integral_accessor_,std::plus<double>());
}
- exp_it = boost::prior(last_exponent_integrand_.end());
+ exp_it = std::prev(last_exponent_integrand_.end());
double total = 0.;
- for (std::vector<double>::iterator esp = boost::prior(parameter_splits_[evolution_variable_].end());
+ for (std::vector<double>::iterator esp = std::prev(parameter_splits_[evolution_variable_].end());
esp > parameter_splits_[evolution_variable_].begin(); --esp, --exp_it) {
last_exponent_->second.set_interpolation(*esp,total);
- total += (*exp_it) * ((*esp) - (*boost::prior(esp)));
+ total += (*exp_it) * ((*esp) - (*std::prev(esp)));
}
last_exponent_->second.set_interpolation(parameter_splits_[evolution_variable_].front(),total);
last_point_[evolution_variable_] = old_evo;
}
template<class Function, class Random>
std::set<std::vector<double> >
exponential_generator<Function,Random>::parameter_points() {
std::set<std::vector<double> > res;
std::vector<double> pt(adaption_info_.dimension,0.);
recursive_parameter_points(res,pt,0);
return res;
}
template<class Function, class Random>
void exponential_generator<Function,Random>::
recursive_parameter_points(std::set<std::vector<double> >& res,
std::vector<double>& pt,
size_t current) {
if ( current == adaption_info_.dimension ) {
res.insert(pt);
return;
}
if ( sample_variables_[current] ) {
recursive_parameter_points(res,pt,current+1);
return;
}
for ( std::vector<double>::const_iterator sp =
parameter_splits_[current].begin();
- sp != boost::prior(parameter_splits_[current].end()); ++sp ) {
- pt[current] = (*sp + *boost::next(sp))/2.;
+ sp != std::prev(parameter_splits_[current].end()); ++sp ) {
+ pt[current] = (*sp + *std::next(sp))/2.;
recursive_parameter_points(res,pt,current+1);
}
}
template<class Function, class Random>
void exponential_generator<Function,Random>::compensate() {
if (!did_split_ || !docompensate_) {
assert(did_split_ || last_cell_ == root_cell_.begin());
exponents_.clear();
last_cell_->info().overestimate(last_value_,last_point_,detuning_);
last_cell_->integral(last_cell_->info().volume() * last_cell_->info().overestimate());
last_point_ = function_->parameter_point();
get_exponent();
return;
}
std::vector<double> themaxpoint = last_point_;
std::set<std::vector<double> > id_points
= parameter_points();
for ( std::set<std::vector<double> >::const_iterator id =
id_points.begin(); id != id_points.end(); ++id ) {
last_point_ = *id;
get_exponent();
}
std::map<bit_container<parameter_hash_bits>,linear_interpolator >
old_exponents = exponents_;
double old_oe = last_cell_->info().overestimate();
last_cell_->info().overestimate(last_value_,themaxpoint,detuning_);
last_cell_->integral(last_cell_->info().volume() * last_cell_->info().overestimate());
exponents_.clear();
for ( std::set<std::vector<double> >::const_iterator id =
id_points.begin(); id != id_points.end(); ++id ) {
last_point_ = *id;
get_exponent();
std::map<bit_container<parameter_hash_bits>,linear_interpolator >::iterator
old_exp = old_exponents.find(last_parameter_bin_);
std::map<bit_container<parameter_hash_bits>,linear_interpolator >::iterator
new_exp = exponents_.find(last_parameter_bin_);
assert(old_exp != old_exponents.end() && new_exp != exponents_.end());
double old_norm = 1. - std::exp(-(old_exp->second)(adaption_info_.lower_left[evolution_variable_]));
double new_norm = 1. - std::exp(-(new_exp->second)(adaption_info_.lower_left[evolution_variable_]));
for (binary_tree<cell>::iterator it = root_cell_.begin();
it != root_cell_.end(); ++it) {
if ( !it->info().contains_parameter(last_point_,sample_variables_) )
continue;
double old_int = 0.;
double new_int = 0.;
for ( std::vector<double>::const_iterator sp = parameter_splits_[evolution_variable_].begin();
- sp != boost::prior(parameter_splits_[evolution_variable_].end()); ++sp ) {
+ sp != std::prev(parameter_splits_[evolution_variable_].end()); ++sp ) {
if ( *sp >= it->info().lower_left()[evolution_variable_] &&
*sp < it->info().upper_right()[evolution_variable_] ) {
double xl = *sp;
- double xxl = *boost::next(sp);
+ double xxl = *std::next(sp);
double old_al =
(old_exp->second.interpolation()[xxl] - old_exp->second.interpolation()[xl]) /
(xxl-xl);
double old_bl =
(xxl * old_exp->second.interpolation()[xl] -
xl * old_exp->second.interpolation()[xxl]) /
(xxl-xl);
double new_al =
(new_exp->second.interpolation()[xxl] - new_exp->second.interpolation()[xl]) /
(xxl-xl);
double new_bl =
(xxl * new_exp->second.interpolation()[xl] -
xl * new_exp->second.interpolation()[xxl]) /
(xxl-xl);
if ( std::abs(old_al) > std::numeric_limits<double>::epsilon() ) {
old_int += (exp(-(old_al*xl+old_bl)) - exp(-(old_al*xxl+old_bl)))/old_al;
} else {
old_int += (xxl-xl)*exp(-old_bl);
}
if ( std::abs(new_al) > std::numeric_limits<double>::epsilon() ) {
new_int += (exp(-(new_al*xl+new_bl)) - exp(-(new_al*xxl+new_bl)))/new_al;
} else {
new_int += (xxl-xl)*exp(-new_bl);
}
}
}
double scaling;
if (it != last_cell_) {
if (old_int > std::numeric_limits<double>::epsilon() &&
new_int > std::numeric_limits<double>::epsilon())
scaling = ((old_norm * new_int) /
(new_norm * old_int)) - 1.;
else
scaling = 0.;
} else {
if (old_int > std::numeric_limits<double>::epsilon() &&
new_int > std::numeric_limits<double>::epsilon())
scaling = ((last_value_ * old_norm * new_int) /
(old_oe * new_norm * old_int)) - 1.;
else
scaling = 0.;
}
it->info().parametric_missing(last_parameter_bin_,
it->info().parametric_missing(last_parameter_bin_) +
static_cast<int>(round(scaling * it->info().attempted())));
if (it->info().parametric_missing(last_parameter_bin_) != 0) {
compensating_ = true;
}
}
}
last_point_ = function_->parameter_point();
}
template<class Function, class Random>
double exponential_generator<Function,Random>::generate () {
if (compensating_) {
compensating_ = false;
for (binary_tree<cell>::iterator it = root_cell_.begin();
it != root_cell_.end(); ++it)
if (it->info().parametric_compensating()) {
compensating_ = true;
break;
}
parametric_sampler_.compensate(compensating_);
}
last_point_ = function_->parameter_point();
if (last_point_[evolution_variable_] < evolution_cutoff_) {
return 0.;
}
unsigned long n_hit_miss = 0;
unsigned long n_select = 0;
double minus_log_r;
root_cell_.tree_accumulate(parametric_selector_,integral_accessor_,std::plus<double>());
get_exponent();
while (true) {
n_select = 0;
minus_log_r = -std::log(rnd_gen_()) + last_exponent_->second(last_point_[evolution_variable_]);
if (!last_exponent_->second.invertible(minus_log_r)) {
return 0.;
}
try {
last_point_[evolution_variable_] = last_exponent_->second.unique_inverse(minus_log_r);
} catch (constant_interpolation& c) {
last_point_[evolution_variable_] = rnd_gen_(c.range.first,c.range.second);
}
- assert(!std::isnan(last_point_[evolution_variable_]) &&
- !std::isinf(last_point_[evolution_variable_]));
+ assert(std::isfinite(last_point_[evolution_variable_]));
if (last_point_[evolution_variable_] < evolution_cutoff_) {
return 0.;
}
++attempts_;
if (compensating_) {
root_cell_.tree_accumulate(missing_accessor_,std::plus<int>());
}
if (parameter_splits_[evolution_variable_].size() > 2)
root_cell_.tree_accumulate(parametric_selector_,integral_accessor_,std::plus<double>());
if (did_split_)
while ((last_cell_ = root_cell_.select(parametric_sampler_)) == root_cell_.end()) {
root_cell_.tree_accumulate(missing_accessor_,std::plus<int>());
if(++n_select > adaption_info_.maxtry)
throw selection_maxtry();
}
else
last_cell_ = root_cell_.begin();
last_cell_->info().select(rnd_gen_,last_point_,sample_other_variables_);
last_value_ = function_->evaluate(last_point_);
assert(last_value_ >= 0.);
last_cell_->info().selected(last_point_,last_value_,adaption_info_);
if (last_value_ > last_cell_->info().overestimate()) {
if ( std::abs(last_value_)/last_cell_->info().overestimate() > 2. ) {
last_value_ =
last_cell_->info().overestimate()*
(1.+exp(2.*(2.-std::abs(last_value_)/last_cell_->info().overestimate())));
}
compensate();
throw exponential_regenerate();
}
if (last_cell_->info().attempted() % check_events_ == 0) {
if (split()) {
throw exponential_regenerate();
}
}
if (last_value_/last_cell_->info().overestimate() > rnd_gen_()) {
function_->accept(last_point_,last_value_,last_cell_->info().overestimate());
break;
}
if ( last_value_ != 0.0 ) {
function_->veto(last_point_,last_value_,last_cell_->info().overestimate());
}
if(++n_hit_miss > adaption_info_.maxtry)
throw hit_and_miss_maxtry();
}
if (last_value_ == 0.)
return 0.;
++accepts_;
++check_events_;
last_cell_->info().accept();
return 1.;
}
template<class Function, class Random>
template<class OStream>
void exponential_generator<Function,Random>::put (OStream& os) const {
os << check_events_; ostream_traits<OStream>::separator(os);
adaption_info_.put(os);
root_cell_.put(os);
os << did_split_; ostream_traits<OStream>::separator(os);
os << initialized_; ostream_traits<OStream>::separator(os);
os << evolution_variable_; ostream_traits<OStream>::separator(os);
os << evolution_cutoff_; ostream_traits<OStream>::separator(os);
os << sample_variables_; ostream_traits<OStream>::separator(os);
os << sample_other_variables_; ostream_traits<OStream>::separator(os);
os << parameter_splits_; ostream_traits<OStream>::separator(os);
// last_cell_ is selected new so we ignore it here
os << last_point_; ostream_traits<OStream>::separator(os);
os << last_value_; ostream_traits<OStream>::separator(os);
last_parameter_bin_.put(os);
os << exponents_.size(); ostream_traits<OStream>::separator(os);
for ( std::map<bit_container<parameter_hash_bits>,linear_interpolator >::const_iterator
ex = exponents_.begin(); ex != exponents_.end() ; ++ex ) {
ex->first.put(os);
ex->second.put(os);
}
os << last_exponent_integrand_; ostream_traits<OStream>::separator(os);
os << compensating_; ostream_traits<OStream>::separator(os);
os << attempts_; ostream_traits<OStream>::separator(os);
os << accepts_; ostream_traits<OStream>::separator(os);
os << splits_; ostream_traits<OStream>::separator(os);
os << docompensate_; ostream_traits<OStream>::separator(os);
}
template<class Function, class Random>
template<class IStream>
void exponential_generator<Function,Random>::get (IStream& is) {
is >> check_events_;
adaption_info_.get(is);
root_cell_.get(is);
is >> did_split_ >> initialized_ >> evolution_variable_
>> evolution_cutoff_ >> sample_variables_ >> sample_other_variables_
>> parameter_splits_;
// last_cell_ is selected new so we ignore it here
is >> last_point_ >> last_value_;
last_parameter_bin_.get(is);
size_t dim; is >> dim;
for ( size_t k = 0; k < dim ; ++k ) {
bit_container<parameter_hash_bits> key;
key.get(is);
exponents_[key].get(is);
}
is >> last_exponent_integrand_;
last_exponent_ = exponents_.find(last_parameter_bin_);
is >> compensating_ >> attempts_ >> accepts_ >> splits_ >> docompensate_;
}
}
diff --git a/Sampling/exsample/linear_interpolator.icc b/Sampling/exsample/linear_interpolator.icc
--- a/Sampling/exsample/linear_interpolator.icc
+++ b/Sampling/exsample/linear_interpolator.icc
@@ -1,111 +1,111 @@
// -*- C++ -*-
//
// linear_interpolator.icc is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
//
// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
//
// ExSample is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
namespace exsample {
inline linear_interpolator::linear_interpolator()
: interpolation_(), range_() {}
inline linear_interpolator::linear_interpolator(const std::map<double,double>& points)
: interpolation_(points) {
reset();
}
inline void linear_interpolator::set_interpolation(double point, double value) {
interpolation_[point] = value;
if (value > range_.second)
range_.second = value;
if(value < range_.first)
range_.first = value;
}
inline void linear_interpolator::reset() {
range_.first = interpolation_.begin()->second;
range_.second = interpolation_.begin()->second;
for (std::map<double,double>::const_iterator c = interpolation_.begin();
c != interpolation_.end(); ++c) {
if (c->second < range_.first)
range_.first = c->second;
if (c->second > range_.second)
range_.second = c->second;
}
}
inline double linear_interpolator::operator()(double x) const {
std::map<double, double>::const_iterator upper =
interpolation_.upper_bound(x);
if (upper == interpolation_.end()) {
upper = interpolation_.upper_bound(x-1e-10);
}
if (upper == interpolation_.end()) {
upper = interpolation_.upper_bound(x+1e-10);
}
assert(upper != interpolation_.begin() &&
upper != interpolation_.end());
- return ((upper->second-boost::prior(upper)->second)*x +
- boost::prior(upper)->second*upper->first - upper->second*boost::prior(upper)->first)/
- (upper->first - boost::prior(upper)->first);
+ return ((upper->second-std::prev(upper)->second)*x +
+ std::prev(upper)->second*upper->first - upper->second*std::prev(upper)->first)/
+ (upper->first - std::prev(upper)->first);
}
inline double linear_interpolator::unique_inverse(double f) const {
if(!invertible(f)) throw inversion_has_no_solution();
std::map<double, double>::const_iterator lower = interpolation_.begin();
bool gotone = false;
for (; lower != --interpolation_.end(); ++lower)
- if ((lower->second >= f && boost::next(lower)->second <= f) ||
- (lower->second <= f && boost::next(lower)->second >= f)) {
+ if ((lower->second >= f && std::next(lower)->second <= f) ||
+ (lower->second <= f && std::next(lower)->second >= f)) {
gotone = true;
break;
}
if(!gotone) throw inversion_has_no_solution();
- if (lower->second == boost::next(lower)->second) {
- throw constant_interpolation(lower->first,boost::next(lower)->first,lower->second);
+ if (lower->second == std::next(lower)->second) {
+ throw constant_interpolation(lower->first,std::next(lower)->first,lower->second);
}
- double xdiff = boost::next(lower)->first - lower->first;
- double wdiff = boost::next(lower)->second - lower->second;
- double woffset = lower->second * boost::next(lower)->first - boost::next(lower)->second * lower->first;
+ double xdiff = std::next(lower)->first - lower->first;
+ double wdiff = std::next(lower)->second - lower->second;
+ double woffset = lower->second * std::next(lower)->first - std::next(lower)->second * lower->first;
return (xdiff/wdiff)*(f - woffset/xdiff);
}
template<class OStream>
void linear_interpolator::put(OStream& os) const {
os << interpolation_.size();
ostream_traits<OStream>::separator(os);
for (std::map<double, double>::const_iterator p
= interpolation_.begin(); p != interpolation_.end(); ++p) {
os << p->first;
ostream_traits<OStream>::separator(os);
os << p->second;
ostream_traits<OStream>::separator(os);
}
os << range_.first;
ostream_traits<OStream>::separator(os);
os << range_.second;
ostream_traits<OStream>::separator(os);
}
template<class IStream>
void linear_interpolator::get(IStream& is) {
std::size_t size;
is >> size;
std::pair<double,double> point;
for (std::size_t k = 0; k < size; ++k) {
is >> point.first >> point.second;
interpolation_.insert(point);
}
is >> range_.first >> range_.second;
}
}
diff --git a/Sampling/exsample/utility.h b/Sampling/exsample/utility.h
--- a/Sampling/exsample/utility.h
+++ b/Sampling/exsample/utility.h
@@ -1,339 +1,339 @@
// -*- C++ -*-
//
// utility.h is part of ExSample -- A Library for Sampling Sudakov-Type Distributions
//
// Copyright (C) 2008-2011 Simon Platzer -- simon.plaetzer@desy.de
//
// ExSample is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//
//
#ifndef EXSAMPLE_utility_h_included
#define EXSAMPLE_utility_h_included
#include "config.h"
namespace exsample {
/// \brief separate quantities written to an ostream
template<class OStream>
struct ostream_traits {
/// put the separator to the ostream
static void separator(OStream& os) { os << "\n"; }
};
#ifdef EXSAMPLE_has_ThePEG
/// \brief separate quantities written to a ThePEG::PersistentOStream
template<>
struct ostream_traits<ThePEG::PersistentOStream> {
/// put the separator to the ostream
static void separator(ThePEG::PersistentOStream&) { }
};
#endif // EXSAMPLE_has_ThePEG
/// \brief Compile time conversion of unsigned long to bool
template<unsigned long>
struct static_binary {
enum { value = 1 };
};
/// \brief Compile time conversion of unsigned long to bool
template<>
struct static_binary<0> {
enum { value = 0 };
};
/// \brief Fixed-size, packed vector of bools
template<unsigned long bits>
struct bit_container {
enum {
/// the number of bits contained
n_bits = bits,
/// the number of bits fitting in a unsigned long
uint_bits = CHAR_BIT * sizeof(unsigned long),
/// the number of unsigned long segments needed
n_segments = bits / uint_bits + static_binary<bits % uint_bits>::value
};
/// the default constructor
bit_container() {
for (std::size_t i = 0; i < n_segments; ++i)
segments[i] = 0;
}
/// put all values to false
void reset() {
for (std::size_t i = 0; i < n_segments; ++i)
segments[i] = 0;
}
/// compare for equality
bool operator==(const bit_container& x) const {
for (std::size_t i = 0; i < n_segments; ++i)
if(segments[i] != x.segments[i])
return false;
return true;
}
/// compare for ordering
bool operator<(const bit_container& x) const {
for (std::size_t i = 0; i < n_segments; ++i)
if(segments[i] != x.segments[i])
return (segments[i] < x.segments[i]);
return false;
}
/// set the k'th bit
void bit(unsigned long k, bool value) {
assert(k<n_bits);
if (value)
segments[n_segments-k/uint_bits-1] |= (1ul << (k % uint_bits));
else
segments[n_segments-k/uint_bits-1] &= ~(1ul << (k % uint_bits));
}
/// get the k'th bit
bool bit(unsigned long k) const {
assert(k<n_bits);
return (segments[n_segments-k/uint_bits-1] & (1ul << (k % uint_bits)));
}
/// print to ostream
template<class OStream>
void dump(OStream& os) const {
for ( unsigned int k = 0; k < n_segments; ++k )
os << segments[k] << " ";
}
/// put to ostream
template<class OStream>
void put(OStream& os) const {
for ( size_t k = 0; k < n_segments; ++k ) {
os << segments[k];
ostream_traits<OStream>::separator(os);
}
}
/// get from istream
template<class IStream>
void get(IStream& is) {
for ( size_t k = 0; k < n_segments; ++k ) {
is >> segments[k];
}
}
private:
/// segments needed to keep the hash value
unsigned long segments[n_segments];
};
/// \brief square a number
template<class T>
T sqr(T x) {
return x*x;
}
/// \brief cube a number
template<class T>
T cube(T x) {
return x*x*x;
}
/// \brief Round a floating point value to an integer value of the
/// same type.
template<class T>
T round(T x) {
T f = std::floor(x);
T c = std::ceil(x);
if (x < (f+c)/2.)
return f;
return c;
}
/// \brief Calculate fast powers of two.
inline std::size_t two_to(std::size_t n) {
assert(n <= sizeof(std::size_t)*CHAR_BIT);
return (1 << n);
}
/// \brief Fast, zero memory-overhead one-dimensional
/// histogram with 2^n equally spaced bins
template<class Statistics>
struct fast_small_histogram {
/// default constructor
fast_small_histogram()
- : depth(0), bins(0) {}
+ : depth(0), bins(nullptr) {}
/// copy constructor
fast_small_histogram(const fast_small_histogram& x)
: depth(x.depth), bins(0) {
if (x.bins) {
bins.reset(new Statistics[two_to(depth)]);
for(std::size_t k = 0; k < two_to(depth); ++k)
bins[k] = x.bins[k];
}
}
/// assignment
fast_small_histogram& operator=(const fast_small_histogram& x) {
if (&x == this)
return *this;
depth = x.depth;
- bins.reset(0);
+ bins.reset(nullptr);
if (x.bins) {
bins.reset(new Statistics[two_to(depth)]);
for(std::size_t k = 0; k < two_to(depth); ++k)
bins[k] = x.bins[k];
}
return *this;
}
/// construct from depth d, creating 2^d bins
explicit fast_small_histogram(std::size_t d)
- : depth(d), bins(0) {
+ : depth(d), bins(nullptr) {
bins.reset(new Statistics[two_to(d)]);
}
/// return the bin from event belongs to given outer boundaries
Statistics& bin(double lower,
double upper,
double event) {
double thelower = lower;
double theupper = upper;
std::size_t bindex = 0;
std::size_t current_depth = 0;
while (true) {
double cut
= (thelower+theupper)/2.;
if (event < cut) {
theupper = cut;
} else {
thelower = cut;
bindex += two_to(depth-current_depth-1);
}
if(++current_depth == depth)
break;
}
return bins[bindex];
}
/// the depth, defining a histogram of 2^depth bins
std::size_t depth;
/// the contained statistics objects
- boost::scoped_array<Statistics> bins;
+ std::unique_ptr<Statistics[]> bins;
/// put histogram to an ostream
template<class OStream>
void put(OStream& os) const {
os << depth;
ostream_traits<OStream>::separator(os);
for (std::size_t k = 0; k < two_to(depth); ++k) {
bins[k].put(os);
}
}
/// get histogram from an istream
template<class IStream>
void get(IStream& is) {
is >> depth;
bins.reset(new Statistics[two_to(depth)]);
for(std::size_t k = 0; k < two_to(depth); ++k) {
bins[k].get(is);
}
}
};
/// \brief Generalize the transform algorithm to only apply
/// depending on a range of flags accompanying the input range
template<class FirstInputIterator,
class SecondInputIterator,
class FlagIterator,
class OutputIterator,
class BinaryOperation>
OutputIterator conditional_transform(FirstInputIterator first1,
FirstInputIterator last1,
SecondInputIterator first2,
FlagIterator firstf,
OutputIterator result,
BinaryOperation binary_op) {
for (; first1 != last1; ++first1, ++first2, ++firstf, ++result)
if (*firstf)
*result = binary_op(*first1, *first2);
return result;
}
/// \brief calculate a volume given lower left and upper right
/// corners
inline double volume(const std::vector<double>& lower_left,
const std::vector<double>& upper_right) {
std::vector<double> delta;
std::transform(upper_right.begin(),upper_right.end(),
lower_left.begin(),std::back_inserter(delta),
std::minus<double>());
return
std::accumulate(delta.begin(),delta.end(),1.,std::multiplies<double>());
}
/// \brief calculate a volume given lower left and upper right
/// corners, taking into account only part of the dimensions, which
/// are flagged with true in the correspponding random access
/// container
inline double volume(const std::vector<double>& lower_left,
const std::vector<double>& upper_right,
const std::vector<bool>& flags) {
std::vector<double> delta;
conditional_transform(upper_right.begin(),upper_right.end(),
lower_left.begin(),flags.begin(),
std::back_inserter(delta),
std::minus<double>());
return
std::accumulate(delta.begin(),delta.end(),1.,std::multiplies<double>());
}
/// \brief Exception thrown if the maximum number of attempts to
/// select a cell has been reached.
struct selection_maxtry{};
/// \brief Exception thrown, if the maximum number of misses has
/// been reached.
struct hit_and_miss_maxtry{};
/// \brief Random generator traits.
template<class Random>
struct rnd_generator {
///Generate uniform random number on [0,1]
double operator()() const {
return Random::rnd();
}
///Generate uniform random number on [0,a]
double operator()(double a) const {
return a*Random::rnd();
}
///Generate uniform random number on [a,b]
double operator()(double a, double b) const {
return (a + (b-a)*Random::rnd());
}
};
}
#endif // EXSAMPLE_utility_h_included
diff --git a/Shower/Dipole/AlphaS/alpha_s.h b/Shower/Dipole/AlphaS/alpha_s.h
--- a/Shower/Dipole/AlphaS/alpha_s.h
+++ b/Shower/Dipole/AlphaS/alpha_s.h
@@ -1,350 +1,350 @@
// -*- C++ -*-
// couplings/alpha_s.h is part of matchbox
// (C) 2008 Simon Platzer -- sp@particle.uni-karlsruhe.de
#ifndef matchbox_couplings_alpha_s_h
#define matchbox_couplings_alpha_s_h
#include <string>
-#include <boost/array.hpp>
+#include <array>
#include "ThePEG/Interface/Interfaced.h"
#include "ThePEG/StandardModel/AlphaSBase.h"
#include "gsl.h"
namespace matchbox {
using namespace ThePEG;
template<class AlphaS>
struct solve_lambda_below {
typedef AlphaS alpha_s;
inline solve_lambda_below (alpha_s* a,
unsigned int n,
Energy2 lambda2n,
Energy2 mass2)
: alpha(a), nf_in(n), lambda2_nf_in(lambda2n), threshold(mass2) {}
alpha_s * alpha;
unsigned int nf_in;
Energy2 lambda2_nf_in;
Energy2 threshold;
inline double operator () (double lambda2) {
return ((*alpha)(threshold,lambda2_nf_in,nf_in) -
(*alpha)(threshold,lambda2*MeV2,nf_in-1));
}
};
template<class AlphaS>
struct solve_lambda_above {
typedef AlphaS alpha_s;
inline solve_lambda_above (alpha_s * a,
unsigned int n,
Energy2 lambda2n,
Energy2 mass2)
: alpha(a), nf_in(n), lambda2_nf_in(lambda2n), threshold(mass2) {}
alpha_s * alpha;
unsigned int nf_in;
Energy2 lambda2_nf_in;
Energy2 threshold;
inline double operator () (double lambda2) {
return ((*alpha)(threshold,lambda2_nf_in,nf_in) -
(*alpha)(threshold,lambda2*MeV2,nf_in+1));
}
};
template<class AlphaS>
struct solve_input_lambda {
typedef AlphaS alpha_s;
inline solve_input_lambda (alpha_s * a,
unsigned int n,
double inalpha,
Energy2 inscale)
: alpha(a), nf_in(n), alpha_in(inalpha), scale_in(inscale) {}
alpha_s * alpha;
unsigned int nf_in;
double alpha_in;
Energy2 scale_in;
inline double operator () (double lambda2) {
return ((*alpha)(scale_in,lambda2*MeV2,nf_in) - alpha_in);
}
};
/**
* Base class for the strong coupling.
*
* @see \ref alpha_sInterfaces "The interfaces"
* defined for alpha_s.
*/
class alpha_s
: public AlphaSBase {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
alpha_s();
/**
* The destructor.
*/
virtual ~alpha_s();
//@}
public:
/** @name Virtual functions as required by AlphaSBase. */
//@{
/**
* The \f$\alpha_S\f$. Return the QCD coupling for a given \a scale
* using the given standard model object \a sm.
*/
virtual inline double value(Energy2 scale, const StandardModelBase &) const {
return operator() (scale);
}
/**
* Return the flavour thresholds used. The returned vector contains
* (in position <code>i</code>) the scales when the active number of
* flavours changes from <code>i</code> to <code>i+1</code>.
*/
virtual inline vector<Energy2> flavourThresholds() const {
- vector<Energy2> res (7);
- copy(quark_masses_squared_.begin(),quark_masses_squared_.end(),res.begin());
+ vector<Energy2> res (6);
+ copy(quark_masses_squared_.begin()+1,quark_masses_squared_.end(),res.begin());
return res;
}
/**
* Return the \f$\Lambda_{QCD}\f$ used for different numbers of
* active flavours.
*/
virtual inline vector<Energy> LambdaQCDs() const {
vector<Energy> res;
for (size_t k = 0; k < 7; ++k)
res.push_back(sqrt(lambda_squared_[k]));
return res;
}
//@}
public:
/// return alpha_s as function of scale
inline double operator () (Energy2 scale) const {
if ( fixed_ )
return alpha_s_in_;
assert(matched());
unsigned int active = active_flavours(scale_factor_*scale);
return operator () (scale_factor_*scale,lambda_squared_[active],active);
}
/// return alpha_s as function of scale, QCD scale
/// and number of active flavours
virtual double operator () (Energy2 scale,
Energy2 lambda2,
unsigned int nf) const = 0;
/// match thresholds and write alpha_s
/// to specified file; arguments are
/// Q_low/GeV Q_high/GeV n_steps filename
string check (string args);
public:
/// return minimum number of active flavours
inline unsigned int min_active_flavours () const { return min_active_flavours_; }
/// set minimum number of active flavours
inline void min_active_flavours (unsigned int nf) { min_active_flavours_ = nf; }
/// return maximum number of active flavours
inline unsigned int max_active_flavours () const { return max_active_flavours_; }
/// set maximum number of active flavours
inline void max_active_flavours (unsigned int nf) { max_active_flavours_ = nf; }
/// return the number of active flavours at the given scale
inline unsigned int active_flavours (Energy2 scale) const {
unsigned int active = 0;
if (scale > 0.*GeV2) {
while(quark_mass_squared(active) < scale) {
if (++active == 7)
break;
}
active -= 1;
} else {
active = 0;
}
return active;
}
/// return the lambda squared for the given number of flavours
inline Energy2 lambda_squared (unsigned int f) const {
assert(f < 7);
return lambda_squared_[f];
}
/// return the mass squared for given flavour
inline Energy2 quark_mass_squared (unsigned int f) const {
assert(f < 7);
return quark_masses_squared_[f];
}
/// set the mass squared for given flavour
inline void quark_mass_squared (unsigned int f, Energy2 m2) {
assert(f < 7);
quark_masses_squared_[f] = m2;
matched_ = false;
}
public:
/// perform the threshold matching
/// given alpha_s value at reference scale
void match_thresholds ();
/// return true, if threshold matching has been
/// performed
inline bool matched () const { return matched_; }
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 inline void doinit() throw(InitException) {
match_thresholds();
AlphaSBase::doinit();
}
//@}
/// return the scale factor
double scale_factor () const { return scale_factor_; }
public:
/** @name Functions used by the persistent I/O system. */
//@{
/**
* Function used to write out object persistently.
* @name os the persistent output stream written to.
*/
void persistentOutput(PersistentOStream & os) const;
/**
* Function used to read in object persistently.
* @name is the persistent input stream read from.
* @name 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();
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is an abstract class with persistent data.
*/
static AbstractClassDescription<alpha_s> initalpha_s;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
alpha_s & operator=(const alpha_s &);
private:
unsigned int min_active_flavours_;
unsigned int max_active_flavours_;
bool matched_;
double scale_factor_;
- boost::array<Energy2,7> quark_masses_squared_;
- boost::array<Energy2,7> lambda_squared_;
+ std::array<Energy2,7> quark_masses_squared_;
+ std::array<Energy2,7> lambda_squared_;
double alpha_s_in_;
Energy scale_in_;
pair<Energy2,Energy2> lambda_range_;
bool fixed_;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of alpha_s. */
template <>
struct BaseClassTrait<matchbox::alpha_s,1> {
/** Typedef of the first base class of alpha_s. */
typedef AlphaSBase NthBase;
};
/** This template specialization informs ThePEG about the name of
* the alpha_s class and the shared object where it is defined. */
template <>
struct ClassTraits<matchbox::alpha_s>
: public ClassTraitsBase<matchbox::alpha_s> {
/** Return a platform-independent class name */
static string className() { return "matchbox::alpha_s"; }
/**
* The name of a file containing the dynamic library where the class
* alpha_s is implemented. It may also include several, space-separated,
* libraries if the class alpha_s depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwDipoleShowerAlphaS.so"; }
};
/** @endcond */
}
#endif /* matchbox_couplings_alpha_s_h */
diff --git a/Shower/Dipole/Base/DipoleChain.cc b/Shower/Dipole/Base/DipoleChain.cc
--- a/Shower/Dipole/Base/DipoleChain.cc
+++ b/Shower/Dipole/Base/DipoleChain.cc
@@ -1,324 +1,324 @@
// -*- C++ -*-
//
// DipoleChain.cc 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.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DipoleChain class.
//
#include "DipoleChain.h"
#include "Herwig/Shower/Dipole/Utility/DipolePartonSplitter.h"
-#include <boost/utility.hpp>
+#include <iterator>
using namespace Herwig;
DipoleChain::DipoleChain()
: ggSingleDipole(false) {}
bool DipoleChain::circular () const {
return
(theDipoles.front().leftParticle() ==
theDipoles.back().rightParticle());
}
bool DipoleChain::hasLeftNeighbour (list<Dipole>::const_iterator dc) const {
if ( dc == dipoles().begin() )
return circular();
return true;
}
Dipole& DipoleChain::leftNeighbour (list<Dipole>::iterator dc) {
assert(hasLeftNeighbour(dc));
if ( dc == dipoles().begin() )
return dipoles().back();
return *(--dc);
}
const Dipole& DipoleChain::leftNeighbour (list<Dipole>::const_iterator dc) const {
assert(hasLeftNeighbour(dc));
if ( dc == dipoles().begin() )
return dipoles().back();
return *(--dc);
}
list<Dipole>::iterator DipoleChain::leftNeighbourIterator(list<Dipole>::iterator dc) {
assert(hasLeftNeighbour(dc));
if ( dc == dipoles().begin() )
return --dipoles().end();
return --dc;
}
bool DipoleChain::hasRightNeighbour (list<Dipole>::const_iterator dc) const {
if (dc == --dipoles().end())
return circular();
return true;
}
Dipole& DipoleChain::rightNeighbour (list<Dipole>::iterator dc) {
assert(hasRightNeighbour(dc));
if ( dc == --dipoles().end() )
return dipoles().front();
return *(++dc);
}
const Dipole& DipoleChain::rightNeighbour (list<Dipole>::const_iterator dc) const {
assert(hasRightNeighbour(dc));
if ( dc == --dipoles().end() )
return dipoles().front();
return *(++dc);
}
list<Dipole>::iterator DipoleChain::rightNeighbourIterator(list<Dipole>::iterator dc) {
assert(hasRightNeighbour(dc));
if ( dc == --dipoles().end() )
return dipoles().begin();
return ++dc;
}
void DipoleChain::check() {
- if ( theDipoles.begin() == boost::prior(theDipoles.end()) ) {
+ if ( theDipoles.begin() == std::prev(theDipoles.end()) ) {
if ( theDipoles.front().leftParticle()->hasColour() &&
theDipoles.front().leftParticle()->hasAntiColour() ) {
assert(theDipoles.front().rightParticle()->hasColour() &&
theDipoles.front().rightParticle()->hasAntiColour());
ggSingleDipole = true;
}
}
}
list<Dipole>::iterator DipoleChain::insertSplitting(list<Dipole>::iterator emittingDipole,
pair<Dipole,Dipole> children,
pair<list<Dipole>::iterator,list<Dipole>::iterator>& childIterators) {
assert(DipolePartonSplitter::colourConnected(children.first.leftParticle(),children.first.rightParticle()) ||
DipolePartonSplitter::colourConnected(children.second.leftParticle(),children.second.rightParticle()));
bool was_circular = circular();
if (hasLeftNeighbour(emittingDipole)) {
list<Dipole>::iterator theLeftNeighbour =
leftNeighbourIterator(emittingDipole);
theLeftNeighbour->rightParticle(children.first.leftParticle());
if ( children.first.leftParticle()->scale() < sqr(theLeftNeighbour->rightScale()) )
theLeftNeighbour->rightScale(sqrt(children.first.leftParticle()->scale()));
theLeftNeighbour->rightPDF(children.first.leftPDF());
theLeftNeighbour->rightFraction(children.first.leftFraction());
theLeftNeighbour->update();
}
if (hasRightNeighbour(emittingDipole)) {
list<Dipole>::iterator theRightNeighbour =
rightNeighbourIterator(emittingDipole);
theRightNeighbour->leftParticle(children.second.rightParticle());
if ( children.second.rightParticle()->scale() < sqr(theRightNeighbour->leftScale()) )
theRightNeighbour->leftScale(sqrt(children.second.rightParticle()->scale()));
theRightNeighbour->leftPDF(children.second.rightPDF());
theRightNeighbour->leftFraction(children.second.rightFraction());
theRightNeighbour->update();
}
if (DipolePartonSplitter::colourConnected(children.first.leftParticle(),children.first.rightParticle()) &&
DipolePartonSplitter::colourConnected(children.second.leftParticle(),children.second.rightParticle())) {
// nothing special to do, just replace the emitting dipole
// by the right one and insert the left one before it
*emittingDipole = children.second;
childIterators.second = emittingDipole;
childIterators.first = dipoles().insert(emittingDipole,children.first);
if ( ggSingleDipole ) {
ggSingleDipole = false;
Dipole miss;
miss.leftParticle(dipoles().back().rightParticle());
miss.rightParticle(dipoles().front().leftParticle());
miss.leftScale(dipoles().back().rightScale());
miss.rightScale(dipoles().front().leftScale());
miss.leftPDF(dipoles().back().rightPDF());
miss.rightPDF(dipoles().front().leftPDF());
miss.leftFraction(dipoles().back().rightFraction());
miss.rightFraction(dipoles().front().leftFraction());
miss.update();
dipoles().push_back(miss);
}
return dipoles().end();
}
if (!DipolePartonSplitter::colourConnected(children.first.leftParticle(),children.first.rightParticle())) {
if ( !was_circular && !ggSingleDipole ) {
*emittingDipole = children.second;
childIterators.second = emittingDipole;
assert(emittingDipole != dipoles().begin());
- childIterators.first = boost::prior(emittingDipole);
+ childIterators.first = std::prev(emittingDipole);
return emittingDipole;
}
*emittingDipole = children.second;
if ( ggSingleDipole ) {
ggSingleDipole = false;
Dipole miss;
miss.leftParticle(children.second.rightParticle());
miss.rightParticle(children.first.leftParticle());
miss.leftScale(children.second.rightScale());
miss.rightScale(children.first.leftScale());
miss.leftPDF(children.second.rightPDF());
miss.rightPDF(children.first.leftPDF());
miss.leftFraction(children.second.rightFraction());
miss.rightFraction(children.first.leftFraction());
miss.update();
dipoles().push_back(miss);
childIterators.first = dipoles().begin();
- childIterators.second = boost::prior(dipoles().end());
+ childIterators.second = std::prev(dipoles().end());
return dipoles().end();
}
childIterators.second = emittingDipole;
if ( emittingDipole == dipoles().begin() )
childIterators.first = --dipoles().end();
else
- childIterators.first = boost::prior(emittingDipole);
+ childIterators.first = std::prev(emittingDipole);
if ( emittingDipole == dipoles().begin() )
return dipoles().end();
dipoles().splice(dipoles().begin(),dipoles(),emittingDipole,dipoles().end());
// explicitly fix iterators in case the splice implementation
// at hand does invalidate iterators (the SGI docu says, it doesn't,
// but it seems that this behaviour is not part of the standard)
childIterators.second = dipoles().begin();
childIterators.first = --dipoles().end();
return dipoles().end();
}
if (!DipolePartonSplitter::colourConnected(children.second.leftParticle(),children.second.rightParticle())) {
if ( !was_circular && !ggSingleDipole ) {
*emittingDipole = children.first;
childIterators.first = emittingDipole;
assert(emittingDipole != --dipoles().end());
- childIterators.second = boost::next(emittingDipole);
- return boost::next(emittingDipole);
+ childIterators.second = std::next(emittingDipole);
+ return std::next(emittingDipole);
}
*emittingDipole = children.first;
if ( ggSingleDipole ) {
ggSingleDipole = false;
Dipole miss;
miss.leftParticle(children.second.rightParticle());
miss.rightParticle(children.first.leftParticle());
miss.leftScale(children.second.rightScale());
miss.rightScale(children.first.leftScale());
miss.leftPDF(children.second.rightPDF());
miss.rightPDF(children.first.leftPDF());
miss.leftFraction(children.second.rightFraction());
miss.rightFraction(children.first.leftFraction());
miss.update();
dipoles().push_front(miss);
childIterators.first = dipoles().begin();
- childIterators.second = boost::prior(dipoles().end());
+ childIterators.second = std::prev(dipoles().end());
return dipoles().end();
}
childIterators.first = emittingDipole;
if ( emittingDipole == --dipoles().end() )
childIterators.second = dipoles().begin();
else
- childIterators.second = boost::next(emittingDipole);
+ childIterators.second = std::next(emittingDipole);
if ( emittingDipole == --dipoles().end() )
return dipoles().end();
- dipoles().splice(dipoles().begin(),dipoles(),boost::next(emittingDipole),dipoles().end());
+ dipoles().splice(dipoles().begin(),dipoles(),std::next(emittingDipole),dipoles().end());
// explicitly fix iterators in case the splice implementation
// at hand does invalidate iterators (the SGI docu says, it doesn't,
// but it seems that this behaviour is not part of the standard)
childIterators.first = dipoles().begin();
childIterators.second = --dipoles().end();
return dipoles().end();
}
return dipoles().end();
}
void DipoleChain::updateDipole(list<Dipole>::iterator dip) {
dip->update();
if (hasLeftNeighbour(dip)) {
list<Dipole>::iterator theLeftNeighbour =
leftNeighbourIterator(dip);
theLeftNeighbour->rightParticle(dip->leftParticle());
theLeftNeighbour->rightPDF(dip->leftPDF());
theLeftNeighbour->rightFraction(dip->leftFraction());
theLeftNeighbour->update();
}
if (hasRightNeighbour(dip)) {
list<Dipole>::iterator theRightNeighbour =
rightNeighbourIterator(dip);
theRightNeighbour->leftParticle(dip->rightParticle());
theRightNeighbour->leftPDF(dip->rightPDF());
theRightNeighbour->leftFraction(dip->rightFraction());
theRightNeighbour->update();
}
}
void DipoleChain::print(ostream& os) const {
os << "--- DipoleChain ----------------------------------------------------------------\n";
if ( theDipoles.empty() ) {
os << " *** This DipoleChain is empty. ***\n";
} else {
os << " " << (!circular() ? "non-" : "") << "circular with "
<< theDipoles.size() << " dipoles\n";
for (list<Dipole>::const_iterator dit = theDipoles.begin();
dit != theDipoles.end(); ++dit) {
os << (*dit);
}
}
os << "--------------------------------------------------------------------------------\n";
os << flush;
}
diff --git a/Shower/Dipole/Base/DipoleEventRecord.cc b/Shower/Dipole/Base/DipoleEventRecord.cc
--- a/Shower/Dipole/Base/DipoleEventRecord.cc
+++ b/Shower/Dipole/Base/DipoleEventRecord.cc
@@ -1,814 +1,814 @@
// -*- C++ -*-
//
// DipoleEventRecord.cc 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.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DipoleEventRecord class.
//
#include "DipoleEventRecord.h"
#include "Herwig/Shower/Dipole/Utility/DipolePartonSplitter.h"
#include "Herwig/Shower/ShowerHandler.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/PDF/PartonExtractor.h"
-#include <boost/utility.hpp>
+#include <iterator>
#include <algorithm>
using namespace Herwig;
PList DipoleEventRecord::colourOrdered() {
PList colour_ordered;
size_t done_size = outgoing().size();
if (incoming().first->coloured())
++done_size;
if (incoming().second->coloured())
++done_size;
while (colour_ordered.size() != done_size) {
PPtr current;
// start with singlets, as long as we have some
if (find(colour_ordered.begin(),colour_ordered.end(),incoming().first) ==
colour_ordered.end() && incoming().first->coloured()) {
if (!incoming().first->hasColour() || !incoming().first->hasAntiColour())
current = incoming().first;
}
if (!current) {
for (PList::iterator p = outgoing().begin();
p != outgoing().end(); ++p) {
if (find(colour_ordered.begin(),colour_ordered.end(),*p) ==
colour_ordered.end() && (**p).coloured()) {
if (!(**p).hasColour() || !(**p).hasAntiColour()) {
current = *p;
break;
}
}
}
}
if (!current) {
if (find(colour_ordered.begin(),colour_ordered.end(),incoming().second) ==
colour_ordered.end() && incoming().second->coloured()) {
if (!incoming().second->hasColour() || !incoming().second->hasAntiColour())
current = incoming().second;
}
}
// then go on with anything else
if (!current) {
if (find(colour_ordered.begin(),colour_ordered.end(),incoming().first) ==
colour_ordered.end() && incoming().first->coloured()) {
current = incoming().first;
}
}
if (!current) {
for (PList::iterator p = outgoing().begin();
p != outgoing().end(); ++p) {
if (find(colour_ordered.begin(),colour_ordered.end(),*p) ==
colour_ordered.end() && (**p).coloured()) {
current = *p;
break;
}
}
}
if (!current) {
if (find(colour_ordered.begin(),colour_ordered.end(),incoming().second) ==
colour_ordered.end() && incoming().second->coloured()) {
current = incoming().second;
}
}
assert(current);
PPtr next;
Ptr<ColourLine>::ptr walk_the_line;
while (true) {
if (!walk_the_line) {
if (current->hasColour()) {
walk_the_line = current->colourLine();
}
else if (current->hasAntiColour()) {
walk_the_line = current->antiColourLine();
}
}
if (!next)
for (tPVector::const_iterator p = walk_the_line->coloured().begin();
p != walk_the_line->coloured().end(); ++p) {
if (*p == current)
continue;
if (find(outgoing().begin(),outgoing().end(),*p) != outgoing().end() ||
*p == incoming().first ||
*p == incoming().second) {
next = *p;
if (next->hasColour() && next->hasAntiColour()) {
walk_the_line = walk_the_line == next->colourLine() ? next->antiColourLine() : next->colourLine();
}
break;
}
}
if (!next)
for (tPVector::const_iterator p = walk_the_line->antiColoured().begin();
p != walk_the_line->antiColoured().end(); ++p) {
if (*p == current)
continue;
if (find(outgoing().begin(),outgoing().end(),*p) != outgoing().end() ||
*p == incoming().first ||
*p == incoming().second) {
next = *p;
if (next->hasColour() && next->hasAntiColour()) {
walk_the_line = walk_the_line == next->colourLine() ? next->antiColourLine() : next->colourLine();
}
break;
}
}
assert(next);
colour_ordered.push_back(current);
current = next;
// done if next is not a gluon or next is already in colour_ordered
if ((current->hasColour() && !current->hasAntiColour()) ||
(!current->hasColour() && current->hasAntiColour())) {
colour_ordered.push_back(current);
break;
}
if (next->hasColour() && next->hasAntiColour()) {
if (find(colour_ordered.begin(),colour_ordered.end(),next) != colour_ordered.end())
break;
}
next = PPtr();
}
}
return colour_ordered;
}
void DipoleEventRecord::popChain() {
assert(!theChains.empty());
theDoneChains.push_back(DipoleChain());
theDoneChains.back().dipoles().splice(theDoneChains.back().dipoles().begin(),theChains.front().dipoles());
theChains.pop_front();
}
void DipoleEventRecord::popChain(list<DipoleChain>::iterator ch) {
assert(!theChains.empty());
theDoneChains.push_back(DipoleChain());
theDoneChains.back().dipoles().splice(theDoneChains.back().dipoles().begin(),ch->dipoles());
theChains.erase(ch);
}
void DipoleEventRecord::popChains(const list<list<DipoleChain>::iterator>& chs) {
assert(!theChains.empty());
for ( list<list<DipoleChain>::iterator>::const_iterator ch =
chs.begin(); ch != chs.end(); ++ch ) {
theDoneChains.push_back(DipoleChain());
theDoneChains.back().dipoles().splice(theDoneChains.back().dipoles().begin(),(*ch)->dipoles());
}
for ( list<list<DipoleChain>::iterator>::const_iterator ch =
chs.begin(); ch != chs.end(); ++ch )
theChains.erase(*ch);
}
DipoleIndex
DipoleEventRecord::mergeIndex(list<Dipole>::iterator firstDipole, const pair<bool,bool>& whichFirst,
list<Dipole>::iterator secondDipole, const pair<bool,bool>& whichSecond) const {
tcPDPtr emitterData =
whichFirst.first ? firstDipole->leftParticle()->dataPtr() : firstDipole->rightParticle()->dataPtr();
tcPDPtr spectatorData =
whichSecond.first ? secondDipole->leftParticle()->dataPtr() : secondDipole->rightParticle()->dataPtr();
const PDF& emitterPDF =
whichFirst.first ? firstDipole->leftPDF() : firstDipole->rightPDF();
const PDF& spectatorPDF =
whichSecond.first ? secondDipole->leftPDF() : secondDipole->rightPDF();
return DipoleIndex(emitterData,spectatorData,emitterPDF,spectatorPDF);
}
SubleadingSplittingInfo
DipoleEventRecord::mergeSplittingInfo(list<DipoleChain>::iterator firstChain, list<Dipole>::iterator firstDipole,
const pair<bool,bool>& whichFirst,
list<DipoleChain>::iterator secondChain, list<Dipole>::iterator secondDipole,
const pair<bool,bool>& whichSecond) const {
SubleadingSplittingInfo res;
res.index(mergeIndex(firstDipole,whichFirst,secondDipole,whichSecond));
res.emitter(whichFirst.first ? firstDipole->leftParticle() : firstDipole->rightParticle());
res.spectator(whichSecond.first ? secondDipole->leftParticle() : secondDipole->rightParticle());
res.emitterX(whichFirst.first ? firstDipole->leftFraction() : firstDipole->rightFraction());
res.spectatorX(whichSecond.first ? secondDipole->leftFraction() : secondDipole->rightFraction());
res.configuration(whichFirst);
res.spectatorConfiguration(whichSecond);
res.emitterChain(firstChain);
res.emitterDipole(firstDipole);
res.spectatorChain(secondChain);
res.spectatorDipole(secondDipole);
return res;
}
void DipoleEventRecord::getSubleadingSplittings(list<SubleadingSplittingInfo>& res) {
static pair<bool,bool> left(true,false);
static pair<bool,bool> right(false,true);
res.clear();
for ( list<DipoleChain>::iterator cit = theChains.begin();
cit != theChains.end(); ++cit ) {
for ( list<Dipole>::iterator dit = cit->dipoles().begin();
dit != cit->dipoles().end(); ++dit ) {
for ( list<Dipole>::iterator djt = dit;
djt != cit->dipoles().end(); ++djt ) {
res.push_back(mergeSplittingInfo(cit,dit,left,cit,djt,left));
res.push_back(mergeSplittingInfo(cit,dit,right,cit,djt,right));
if ( dit != djt ) {
res.push_back(mergeSplittingInfo(cit,dit,left,cit,djt,right));
res.push_back(mergeSplittingInfo(cit,dit,right,cit,djt,left));
}
}
}
list<DipoleChain>::iterator cjt = cit; ++cjt;
for ( ; cjt != theChains.end(); ++cjt ) {
for ( list<Dipole>::iterator dit = cit->dipoles().begin();
dit != cit->dipoles().end(); ++dit ) {
for ( list<Dipole>::iterator djt = cjt->dipoles().begin();
djt != cjt->dipoles().end(); ++djt ) {
res.push_back(mergeSplittingInfo(cit,dit,left,cjt,djt,left));
res.push_back(mergeSplittingInfo(cit,dit,right,cjt,djt,right));
res.push_back(mergeSplittingInfo(cit,dit,left,cjt,djt,right));
res.push_back(mergeSplittingInfo(cit,dit,right,cjt,djt,left));
}
}
}
}
}
void DipoleEventRecord::splitSubleading(SubleadingSplittingInfo& dsplit,
pair<list<Dipole>::iterator,list<Dipole>::iterator>& childIterators,
DipoleChain*& firstChain, DipoleChain*& secondChain) {
if ( dsplit.emitterDipole() == dsplit.spectatorDipole() ) {
assert(dsplit.emitterChain() == dsplit.spectatorChain());
split(dsplit.emitterDipole(),dsplit.emitterChain(),dsplit,
childIterators,firstChain,secondChain,false);
} else {
// first need to recoil, then split
recoil(dsplit.spectatorDipole(),dsplit.spectatorChain(),dsplit);
split(dsplit.emitterDipole(),dsplit.emitterChain(),dsplit,
childIterators,firstChain,secondChain,true);
}
}
void DipoleEventRecord::findChains(const PList& ordered) {
theChains.clear();
theDoneChains.clear();
DipoleChain current_chain;
// this whole thing needs to have a more elegant implementation at some point
bool startIsTriplet =
(ordered.front()->hasColour() && !ordered.front()->hasAntiColour()) ||
(!ordered.front()->hasColour() && ordered.front()->hasAntiColour());
bool endIsTriplet =
(ordered.back()->hasColour() && !ordered.back()->hasAntiColour()) ||
(!ordered.back()->hasColour() && ordered.back()->hasAntiColour());
bool is33bar =
ordered.size() == 2 && startIsTriplet && endIsTriplet;
if (!is33bar) {
PList::const_iterator theStart = ordered.begin();
bool onceMore = false;
for (PList::const_iterator p = ordered.begin();
p != ordered.end(); ++p) {
PList::const_iterator next_it =
- p != --ordered.end() ? boost::next(p) : ordered.begin();
+ p != --ordered.end() ? std::next(p) : ordered.begin();
if (!DipolePartonSplitter::colourConnected(*p,*next_it)) {
// it may have happened that we need to close the chain due to another
// chain starting right now; see the above global comment for this fix
bool startIsOctet =
(**theStart).hasColour() && (**theStart).hasAntiColour();
bool endIsOctet =
(**p).hasColour() && (**p).hasAntiColour();
if ( DipolePartonSplitter::colourConnected(*p,*theStart) &&
startIsOctet && endIsOctet ) {
swap(next_it,theStart);
onceMore = true;
} else {
theStart = next_it;
current_chain.check();
theChains.push_back(current_chain);
current_chain.dipoles().clear();
continue;
}
}
pair<bool,bool> initial_state (false,false);
initial_state.first = (*p == incoming().first || *p == incoming().second);
initial_state.second = (*next_it == incoming().first || *next_it == incoming().second);
pair<int,int> which_in (-1,-1);
if (initial_state.first)
which_in.first = *p == incoming().first ? 0 : 1;
if (initial_state.second)
which_in.second = *next_it == incoming().first ? 0 : 1;
pair<double,double> xs (1.,1.);
if (initial_state.first)
xs.first = *p == incoming().first ? fractions().first : fractions().second;
if (initial_state.second)
xs.second = *next_it == incoming().first ? fractions().first : fractions().second;
pair<PDF,PDF> pdf;
if ( which_in.first == 0 )
pdf.first = pdfs().first;
else if ( which_in.first == 1 )
pdf.first = pdfs().second;
if ( which_in.second == 0 )
pdf.second = pdfs().first;
else if ( which_in.second == 1 )
pdf.second = pdfs().second;
current_chain.dipoles().push_back(Dipole(make_pair(*p,*next_it),pdf,xs));
if ( onceMore ) {
next_it = theStart;
current_chain.check();
theChains.push_back(current_chain);
current_chain.dipoles().clear();
onceMore = false;
}
}
} else {
// treat 2 -> singlet, singlet -> 2 and 1 + singlet -> 1 + singlet special
// to prevent duplicate dipole
assert(DipolePartonSplitter::colourConnected(ordered.front(),ordered.back()));
pair<bool,bool> initial_state (false,false);
initial_state.first = (ordered.front() == incoming().first || ordered.front() == incoming().second);
initial_state.second = (ordered.back() == incoming().first || ordered.back() == incoming().second);
pair<int,int> which_in (-1,-1);
if (initial_state.first)
which_in.first = ordered.front() == incoming().first ? 0 : 1;
if (initial_state.second)
which_in.second = ordered.back() == incoming().first ? 0 : 1;
pair<double,double> xs (1.,1.);
if (initial_state.first)
xs.first = ordered.front() == incoming().first ? fractions().first : fractions().second;
if (initial_state.second)
xs.second = ordered.back() == incoming().first ? fractions().first : fractions().second;
pair<PDF,PDF> pdf;
if ( which_in.first == 0 )
pdf.first = pdfs().first;
else if ( which_in.first == 1 )
pdf.first = pdfs().second;
if ( which_in.second == 0 )
pdf.second = pdfs().first;
else if ( which_in.second == 1 )
pdf.second = pdfs().second;
current_chain.dipoles().push_back(Dipole(make_pair(ordered.front(),ordered.back()),pdf,xs));
}
if (!current_chain.dipoles().empty()) {
current_chain.check();
theChains.push_back(current_chain);
}
}
void DipoleEventRecord::getAll(const ParticleVector& childs,
set<PPtr>& hardSet,
set<PPtr>& outgoingSet) {
for ( ParticleVector::const_iterator p = childs.begin();
p != childs.end(); ++p ) {
if ( ShowerHandler::currentHandler()->eventHandler()->currentCollision()->isRemnant(*p) )
continue;
if ( (**p).children().empty() ) {
if ( (**p).coloured() &&
outgoingSet.find(*p) == outgoingSet.end() )
outgoingSet.insert(*p);
else if ( !(**p).coloured() &&
hardSet.find(*p) == hardSet.end() )
hardSet.insert(*p);
} else {
getAll((**p).children(),hardSet,outgoingSet);
}
}
}
const map<PPtr,PPtr>&
DipoleEventRecord::prepare(tSubProPtr subpro,
tStdXCombPtr xc,
const pair<PDF,PDF>& pdf,
bool dipoles) {
subProcess(subpro);
outgoing().clear();
theHard.clear();
theOriginals.clear();
PPair in = subpro->incoming();
assert(ShowerHandler::currentHandler());
tPPair beam = ShowerHandler::currentHandler()->generator()->currentEvent()->incoming();
// don't take these from the XComb as it may be null
pair<double,double> xs;
ThePEG::Direction<0> dir(true);
xs.first = in.first->momentum().dirPlus()/beam.first->momentum().dirPlus();
dir.reverse();
xs.second = in.second->momentum().dirPlus()/beam.second->momentum().dirPlus();
xcombPtr(xc);
pdfs() = pdf;
fractions() = xs;
set<PPtr> allHard;
set<PPtr> allOutgoing;
getAll(in.first->children(),allHard,allOutgoing);
getAll(in.second->children(),allHard,allOutgoing);
vector<PPtr> original;
vector<PPtr> copies;
original.push_back(in.first);
original.push_back(in.second);
copy(allOutgoing.begin(),allOutgoing.end(),back_inserter(original));
for ( vector<PPtr>::const_iterator p = original.begin();
p != original.end(); ++p ) {
PPtr copy = new_ptr(Particle(**p));
copies.push_back(copy);
theOriginals[*p] = copy;
}
colourIsolate(original,copies);
incoming().first = copies[0];
ParticleVector children = incoming().first->children();
for ( ParticleVector::const_iterator c = children.begin();
c != children.end(); ++c )
incoming().first->abandonChild(*c);
incoming().second = copies[1];
children = incoming().second->children();
for ( ParticleVector::const_iterator c = children.begin();
c != children.end(); ++c )
incoming().second->abandonChild(*c);
copy(copies.begin()+2,copies.end(),back_inserter(outgoing()));
for ( set<PPtr>::const_iterator p = allHard.begin(); p != allHard.end(); ++p ) {
PPtr copy = new_ptr(Particle(**p));
theHard.push_back(copy);
theOriginals[*p] = copy;
}
if ( dipoles ) {
PList cordered = colourOrdered();
findChains(cordered);
}
PList::const_iterator XFirst, XLast;
if ( !theHard.empty() ) {
XFirst = theHard.begin();
XLast = theHard.end();
} else {
XFirst = outgoing().begin();
XLast = outgoing().end();
}
thePX = (**XFirst).momentum();
++XFirst;
for ( ; XFirst != XLast; ++XFirst )
thePX += (**XFirst).momentum();
identifyEventType();
return theOriginals;
}
void DipoleEventRecord::clear() {
ShowerEventRecord::clear();
theHard.clear();
theChains.clear();
theDoneChains.clear();
theOriginals.clear();
}
void DipoleEventRecord::update(DipoleSplittingInfo& dsplit) {
if ( incoming().first == dsplit.emitter() ) {
intermediates().push_back(dsplit.emitter());
incoming().first = dsplit.splitEmitter();
fractions().first /= dsplit.lastEmitterZ();
} else if ( incoming().first == dsplit.spectator() ) {
intermediates().push_back(dsplit.spectator());
incoming().first = dsplit.splitSpectator();
fractions().first /= dsplit.lastSpectatorZ();
}
if ( incoming().second == dsplit.emitter() ) {
intermediates().push_back(dsplit.emitter());
incoming().second = dsplit.splitEmitter();
fractions().second /= dsplit.lastEmitterZ();
} else if ( incoming().second == dsplit.spectator() ) {
intermediates().push_back(dsplit.spectator());
incoming().second = dsplit.splitSpectator();
fractions().second /= dsplit.lastSpectatorZ();
}
PList::iterator pos;
pos = find(outgoing().begin(), outgoing().end(), dsplit.emitter());
if (pos != outgoing().end()) {
intermediates().push_back(*pos);
*pos = dsplit.splitEmitter();
}
pos = find(outgoing().begin(), outgoing().end(), dsplit.spectator());
if (pos != outgoing().end()) {
intermediates().push_back(*pos);
*pos = dsplit.splitSpectator();
}
outgoing().push_back(dsplit.emission());
if (dsplit.splittingKinematics()->doesTransform()) {
for (PList::iterator p = intermediates().begin();
p != intermediates().end(); ++p) {
(**p).set5Momentum(dsplit.splittingKinematics()->transform((**p).momentum()));
}
for (PList::iterator h = theHard.begin();
h != theHard.end(); ++h) {
(**h).set5Momentum(dsplit.splittingKinematics()->transform((**h).momentum()));
}
for (PList::iterator p = outgoing().begin();
p != outgoing().end(); ++p)
if ((*p) != dsplit.splitEmitter() &&
(*p) != dsplit.splitSpectator() &&
(*p) != dsplit.emission())
(**p).set5Momentum(dsplit.splittingKinematics()->transform((**p).momentum()));
}
}
void
DipoleEventRecord::split(list<Dipole>::iterator dip,
list<DipoleChain>::iterator ch,
DipoleSplittingInfo& dsplit,
pair<list<Dipole>::iterator,list<Dipole>::iterator>& childIterators,
DipoleChain*& firstChain, DipoleChain*& secondChain,
bool colourSpectator) {
static DipoleChain empty;
pair<Dipole,Dipole> children = dip->split(dsplit,colourSpectator);
list<Dipole>::iterator breakup =
ch->insertSplitting(dip,children,childIterators);
if ( breakup == ch->dipoles().end() ) {
firstChain = &(*ch);
secondChain = &empty;
} else {
DipoleChain other;
other.dipoles().splice(other.dipoles().end(),ch->dipoles(),breakup,ch->dipoles().end());
chains().push_back(other);
firstChain = &(*ch);
secondChain = &(chains().back());
// explicitly fix iterators in case the splice implementation
// at hand does invalidate iterators (the SGI docu says, it doesn't,
// but it seems that this behaviour is not part of the standard)
childIterators.first = --firstChain->dipoles().end();
childIterators.second = secondChain->dipoles().begin();
}
if ( !colourSpectator )
update(dsplit); // otherwise done by recoil(...)
}
void DipoleEventRecord::recoil(list<Dipole>::iterator dip,
list<DipoleChain>::iterator ch,
DipoleSplittingInfo& dsplit) {
dip->recoil(dsplit);
ch->updateDipole(dip);
update(dsplit);
}
list<pair<list<Dipole>::iterator,list<DipoleChain>::iterator> >
DipoleEventRecord::inDipoles() {
list<pair<list<Dipole>::iterator,list<DipoleChain>::iterator> > res;
for ( list<DipoleChain>::iterator chit = theDoneChains.begin();
chit != theDoneChains.end(); ++chit ) {
bool haveOne = false;
for ( list<Dipole>::iterator dit = chit->dipoles().begin();
dit != chit->dipoles().end(); ++dit ) {
if ( dit->leftPDF().pdf() || dit->rightPDF().pdf() ) {
haveOne = true;
break;
}
}
if ( haveOne ) {
theChains.splice(theChains.begin(),theDoneChains,chit);
for ( list<Dipole>::iterator dit = theChains.front().dipoles().begin();
dit != theChains.front().dipoles().end(); ++dit ) {
if ( dit->leftPDF().pdf() || dit->rightPDF().pdf() ) {
res.push_back(make_pair(dit,theChains.begin()));
}
}
}
}
return res;
}
void DipoleEventRecord::transform(const SpinOneLorentzRotation& rot) {
Lorentz5Momentum tmp;
for (PList::iterator p = intermediates().begin();
p != intermediates().end(); ++p) {
tmp = (**p).momentum(); tmp = rot * tmp;
(**p).set5Momentum(tmp);
}
for (PList::iterator h = theHard.begin();
h != theHard.end(); ++h) {
tmp = (**h).momentum(); tmp = rot * tmp;
(**h).set5Momentum(tmp);
}
for (PList::iterator p = outgoing().begin();
p != outgoing().end(); ++p) {
tmp = (**p).momentum(); tmp = rot * tmp;
(**p).set5Momentum(tmp);
}
}
tPPair DipoleEventRecord::fillEventRecord(StepPtr step, bool firstInteraction, bool) {
PPtr inSubPro = subProcess()->incoming().first;
PPtr inParticle;
if ( !(inSubPro->parents().empty()) )
inParticle = inSubPro->parents()[0];
else
inParticle = inSubPro;
PPtr inParton = theOriginals[inSubPro];
theOriginals.erase(inSubPro);
updateColour(incoming().first,true);
if ( inParticle != inSubPro )
inParticle->abandonChild(inSubPro);
inParton->addChild(inSubPro);
if ( inParticle != inSubPro )
inParticle->addChild(incoming().first);
intermediates().push_back(inSubPro);
intermediates().push_back(inParton);
inSubPro = subProcess()->incoming().second;
if ( !(inSubPro->parents().empty()) )
inParticle = inSubPro->parents()[0];
else
inParticle = inSubPro;
inParton = theOriginals[inSubPro];
theOriginals.erase(inSubPro);
updateColour(incoming().second,true);
if ( inParticle != inSubPro )
inParticle->abandonChild(inSubPro);
inParton->addChild(inSubPro);
if ( inParticle != inSubPro )
inParticle->addChild(incoming().second);
intermediates().push_back(inSubPro);
intermediates().push_back(inParton);
while ( !theOriginals.empty() ) {
PPtr outSubPro = theOriginals.begin()->first;
PPtr outParton = theOriginals.begin()->second;
// workaround for OS X Mavericks LLVM libc++
#ifdef _LIBCPP_VERSION
map<PPtr,PPtr>::const_iterator beg = theOriginals.begin();
#else
map<PPtr,PPtr>::iterator beg = theOriginals.begin();
#endif
theOriginals.erase(beg);
updateColour(outParton,true);
outSubPro->addChild(outParton);
intermediates().push_back(outSubPro);
}
step->addIntermediates(intermediates().begin(),intermediates().end());
for (PList::const_iterator p = outgoing().begin();
p != outgoing().end(); ++p)
step->addDecayProduct(*p);
for (PList::const_iterator p = theHard.begin();
p != theHard.end(); ++p)
step->addDecayProduct(*p);
if ( firstInteraction &&
(incoming().first->coloured() ||
incoming().second->coloured() ) ) {
ShowerHandler::currentHandler()->lastExtractor()->newRemnants(subProcess()->incoming(),incoming(),step);
}
step->addIntermediate(incoming().first);
step->addIntermediate(incoming().second);
return incoming();
}
void DipoleEventRecord::debugLastEvent(ostream& os) const {
bool first = ShowerHandler::currentHandler()->firstInteraction();
os << "--- DipoleEventRecord ----------------------------------------------------------\n";
os << " the " << (first ? "hard" : "secondary") << " subprocess is:\n"
<< (*subProcess());
os << " using PDF's " << pdfs().first.pdf() << " and "
<< pdfs().second.pdf() << "\n";
os << " chains showering currently:\n";
for ( list<DipoleChain>::const_iterator chit = theChains.begin();
chit != theChains.end(); ++chit )
os << (*chit);
os << " chains which finished showering:\n";
for ( list<DipoleChain>::const_iterator chit = theDoneChains.begin();
chit != theDoneChains.end(); ++chit )
os << (*chit);
os << "--------------------------------------------------------------------------------\n";
os << flush;
}
diff --git a/Shower/Dipole/Base/DipoleSplittingGenerator.cc b/Shower/Dipole/Base/DipoleSplittingGenerator.cc
--- a/Shower/Dipole/Base/DipoleSplittingGenerator.cc
+++ b/Shower/Dipole/Base/DipoleSplittingGenerator.cc
@@ -1,606 +1,606 @@
// -*- C++ -*-
//
// DipoleSplittingGenerator.cc 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.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DipoleSplittingGenerator class.
//
#include <config.h>
#include "DipoleSplittingGenerator.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig/Shower/Dipole/DipoleShowerHandler.h"
using namespace Herwig;
DipoleSplittingGenerator::DipoleSplittingGenerator()
: HandlerBase(),
theExponentialGenerator(0), prepared(false), presampling(false),
theDoCompensate(false), theSplittingWeight(1.) {
if ( ShowerHandler::currentHandler() )
setGenerator(ShowerHandler::currentHandler()->generator());
}
DipoleSplittingGenerator::~DipoleSplittingGenerator() {
if ( theExponentialGenerator ) {
delete theExponentialGenerator;
theExponentialGenerator = 0;
}
}
IBPtr DipoleSplittingGenerator::clone() const {
return new_ptr(*this);
}
IBPtr DipoleSplittingGenerator::fullclone() const {
return new_ptr(*this);
}
void DipoleSplittingGenerator::wrap(Ptr<DipoleSplittingGenerator>::ptr other) {
assert(!prepared);
theOtherGenerator = other;
}
void DipoleSplittingGenerator::resetVariations() {
for ( map<string,double>::iterator w = currentWeights.begin();
w != currentWeights.end(); ++w )
w->second = 1.;
}
void DipoleSplittingGenerator::veto(const vector<double>&, double p, double r) {
double factor = 1.;
if ( splittingReweight() ) {
if ( ( ShowerHandler::currentHandler()->firstInteraction() && splittingReweight()->firstInteraction() ) ||
( !ShowerHandler::currentHandler()->firstInteraction() && splittingReweight()->secondaryInteractions() ) ) {
factor = splittingReweight()->evaluate(generatedSplitting);
theSplittingWeight *= (r-factor*p)/(r-p);
}
}
splittingKernel()->veto(generatedSplitting, factor*p, r, currentWeights);
}
void DipoleSplittingGenerator::accept(const vector<double>&, double p, double r) {
double factor = 1.;
if ( splittingReweight() ) {
if ( ( ShowerHandler::currentHandler()->firstInteraction() && splittingReweight()->firstInteraction() ) ||
( !ShowerHandler::currentHandler()->firstInteraction() && splittingReweight()->secondaryInteractions() ) ) {
factor = splittingReweight()->evaluate(generatedSplitting);
theSplittingWeight *= factor;
}
}
splittingKernel()->accept(generatedSplitting, factor*p, r, currentWeights);
}
void DipoleSplittingGenerator::prepare(const DipoleSplittingInfo& sp) {
generatedSplitting = sp;
generatedSplitting.splittingKinematics(splittingKernel()->splittingKinematics());
generatedSplitting.splittingParameters().resize(splittingKernel()->nDimAdditional());
if ( wrapping() ) {
generatedSplitting.emitterData(theSplittingKernel->emitter(generatedSplitting.index()));
generatedSplitting.spectatorData(theSplittingKernel->spectator(generatedSplitting.index()));
generatedSplitting.emissionData(theSplittingKernel->emission(generatedSplitting.index()));
parameters.resize(theOtherGenerator->nDim());
prepared = true;
return;
}
generatedSplitting.emitterData(splittingKernel()->emitter(generatedSplitting.index()));
generatedSplitting.spectatorData(splittingKernel()->spectator(generatedSplitting.index()));
generatedSplitting.emissionData(splittingKernel()->emission(generatedSplitting.index()));
presampledSplitting = generatedSplitting;
prepared = true;
parameters.resize(nDim());
theExponentialGenerator =
new exsample::exponential_generator<DipoleSplittingGenerator,UseRandom>();
theExponentialGenerator->sampling_parameters().maxtry = maxtry();
theExponentialGenerator->sampling_parameters().presampling_points = presamplingPoints();
theExponentialGenerator->sampling_parameters().freeze_grid = freezeGrid();
theExponentialGenerator->detuning(detuning());
theExponentialGenerator->docompensate(theDoCompensate);
theExponentialGenerator->function(this);
theExponentialGenerator->initialize();
}
void DipoleSplittingGenerator::fixParameters(const DipoleSplittingInfo& sp,
Energy optHardPt) {
assert(generator());
assert(!presampling);
assert(prepared);
assert(sp.index() == generatedSplitting.index());
generatedSplitting.scale(sp.scale());
parameters[3] = sp.scale()/generator()->maximumCMEnergy();
generatedSplitting.hardPt(sp.hardPt());
parameters[0] = splittingKinematics()->ptToRandom(optHardPt == ZERO ?
generatedSplitting.hardPt() :
min(generatedSplitting.hardPt(),optHardPt),
sp.scale(),
sp.emitterX(), sp.spectatorX(),
generatedSplitting.index(),
*splittingKernel());
size_t shift = 4;
if ( generatedSplitting.index().emitterPDF().pdf() &&
generatedSplitting.index().spectatorPDF().pdf() ) {
generatedSplitting.emitterX(sp.emitterX());
generatedSplitting.spectatorX(sp.spectatorX());
parameters[4] = sp.emitterX();
parameters[5] = sp.spectatorX();
shift += 2;
}
if ( generatedSplitting.index().emitterPDF().pdf() &&
!generatedSplitting.index().spectatorPDF().pdf() ) {
generatedSplitting.emitterX(sp.emitterX());
parameters[4] = sp.emitterX();
++shift;
}
if ( !generatedSplitting.index().emitterPDF().pdf() &&
generatedSplitting.index().spectatorPDF().pdf() ) {
generatedSplitting.spectatorX(sp.spectatorX());
parameters[4] = sp.spectatorX();
++shift;
}
if ( splittingKernel()->nDimAdditional() )
copy(sp.lastSplittingParameters().begin(),sp.lastSplittingParameters().end(),parameters.begin()+shift);
if ( sp.emitter() )
generatedSplitting.emitter(sp.emitter());
if ( sp.spectator() )
generatedSplitting.spectator(sp.spectator());
}
int DipoleSplittingGenerator::nDim() const {
assert(!wrapping());
assert(prepared);
int ret = 4; // 0 pt, 1 z, 2 phi, 3 scale, 4/5 xs + parameters
if ( generatedSplitting.index().emitterPDF().pdf() ) {
++ret;
}
if ( generatedSplitting.index().spectatorPDF().pdf() ) {
++ret;
}
ret += splittingKernel()->nDimAdditional();
return ret;
}
const vector<bool>& DipoleSplittingGenerator::sampleFlags() {
assert(!wrapping());
if ( !theFlags.empty() )
return theFlags;
theFlags.resize(nDim(),false);
theFlags[0] = true; theFlags[1] = true; theFlags[2] = true; // 0 pt, 1 z, 2 phi
return theFlags;
}
const pair<vector<double>,vector<double> >& DipoleSplittingGenerator::support() {
assert(!wrapping());
if ( !theSupport.first.empty() )
return theSupport;
vector<double> lower(nDim(),0.);
vector<double> upper(nDim(),1.);
pair<double,double> kSupport =
generatedSplitting.splittingKinematics()->kappaSupport(generatedSplitting);
pair<double,double> xSupport =
generatedSplitting.splittingKinematics()->xiSupport(generatedSplitting);
lower[0] = kSupport.first;
lower[1] = xSupport.first;
upper[0] = kSupport.second;
upper[1] = xSupport.second;
theSupport.first = lower;
theSupport.second = upper;
return theSupport;
}
void DipoleSplittingGenerator::startPresampling() {
assert(!wrapping());
splittingKernel()->startPresampling(generatedSplitting.index());
presampling = true;
}
void DipoleSplittingGenerator::stopPresampling() {
assert(!wrapping());
splittingKernel()->stopPresampling(generatedSplitting.index());
presampling = false;
}
bool DipoleSplittingGenerator::haveOverestimate() const {
assert(!wrapping());
assert(prepared);
return
generatedSplitting.splittingKinematics()->haveOverestimate() &&
splittingKernel()->haveOverestimate(generatedSplitting);
}
bool DipoleSplittingGenerator::overestimate(const vector<double>& point) {
assert(!wrapping());
assert(prepared);
assert(!presampling);
assert(haveOverestimate());
if ( ! generatedSplitting.splittingKinematics()->generateSplitting(point[0],point[1],point[2],
generatedSplitting,
*splittingKernel()) )
return 0.;
generatedSplitting.splittingKinematics()->prepareSplitting(generatedSplitting);
return
( generatedSplitting.splittingKinematics()->jacobianOverestimate() *
splittingKernel()->overestimate(generatedSplitting) );
}
double DipoleSplittingGenerator::invertOverestimateIntegral(double value) const {
assert(!wrapping());
assert(prepared);
assert(!presampling);
assert(haveOverestimate());
return
splittingKernel()->invertOverestimateIntegral(generatedSplitting,value);
}
double DipoleSplittingGenerator::evaluate(const vector<double>& point) {
assert(!wrapping());
assert(prepared);
assert(generator());
DipoleSplittingInfo& split =
( !presampling ? generatedSplitting : presampledSplitting );
split.continuesEvolving();
size_t shift = 4;
if ( presampling ) {
split.scale(point[3] * generator()->maximumCMEnergy());
if ( split.index().emitterPDF().pdf() &&
split.index().spectatorPDF().pdf() ) {
split.emitterX(point[4]);
split.spectatorX(point[5]);
shift += 2;
}
if ( split.index().emitterPDF().pdf() &&
!split.index().spectatorPDF().pdf() ) {
split.emitterX(point[4]);
++shift;
}
if ( !split.index().emitterPDF().pdf() &&
split.index().spectatorPDF().pdf() ) {
split.spectatorX(point[4]);
++shift;
}
if ( splittingKernel()->nDimAdditional() )
copy(point.begin()+shift,point.end(),split.splittingParameters().begin());
split.hardPt(split.splittingKinematics()->ptMax(split.scale(),
split.emitterX(),
split.spectatorX(),
split.index(),
*splittingKernel()));
}
if ( ! split.splittingKinematics()->generateSplitting(point[0],point[1],point[2],split,*splittingKernel()) ) {
split.lastValue(0.);
return 0.;
}
split.splittingKinematics()->prepareSplitting(split);
if ( split.stoppedEvolving() ) {
split.lastValue(0.);
return 0.;
}
if ( !presampling )
splittingKernel()->clearAlphaPDFCache();
double kernel = splittingKernel()->evaluate(split);
double jac = split.splittingKinematics()->jacobian();
// multiply in the profile scales when relevant
assert(ShowerHandler::currentHandler());
if ( ShowerHandler::currentHandler()->firstInteraction() &&
ShowerHandler::currentHandler()->profileScales() &&
!presampling ) {
Energy hard = ShowerHandler::currentHandler()->hardScale();
if ( hard > ZERO )
kernel *= ShowerHandler::currentHandler()->profileScales()->hardScaleProfile(hard,split.lastPt());
}
split.lastValue( abs(jac) * kernel );
- if ( isnan(split.lastValue()) || isinf(split.lastValue()) ) {
+ if ( ! isfinite(split.lastValue()) ) {
generator()->log() << "DipoleSplittingGenerator:evaluate(): problematic splitting kernel encountered for "
<< splittingKernel()->name() << "\n" << flush;
split.lastValue(0.0);
}
if ( kernel < 0. )
return 0.;
return split.lastValue();
}
void DipoleSplittingGenerator::doGenerate(map<string,double>& variations,
Energy optCutoff) {
assert(!wrapping());
double res = 0.;
Energy startPt = generatedSplitting.hardPt();
double optKappaCutoff = 0.0;
if ( optCutoff > splittingKinematics()->IRCutoff() ) {
optKappaCutoff = splittingKinematics()->ptToRandom(optCutoff,
generatedSplitting.scale(),
generatedSplitting.emitterX(),
generatedSplitting.spectatorX(),
generatedSplitting.index(),
*splittingKernel());
}
resetVariations();
theSplittingWeight = 1.;
while (true) {
try {
if ( optKappaCutoff == 0.0 ) {
res = theExponentialGenerator->generate();
} else {
res = theExponentialGenerator->generate(optKappaCutoff);
}
} catch (exsample::exponential_regenerate&) {
resetVariations();
theSplittingWeight = 1.;
generatedSplitting.hardPt(startPt);
continue;
} catch (exsample::hit_and_miss_maxtry&) {
throw DipoleShowerHandler::RedoShower();
} catch (exsample::selection_maxtry&) {
throw DipoleShowerHandler::RedoShower();
}
break;
}
for ( map<string,double>::const_iterator w = currentWeights.begin();
w != currentWeights.end(); ++w ) {
map<string,double>::iterator v = variations.find(w->first);
if ( v != variations.end() )
v->second *= w->second;
else
variations[w->first] = w->second;
}
if ( res == 0. ) {
generatedSplitting.lastPt(0.0*GeV);
generatedSplitting.didStopEvolving();
} else {
generatedSplitting.continuesEvolving();
if ( theMCCheck )
theMCCheck->book(generatedSplitting.emitterX(),
generatedSplitting.spectatorX(),
generatedSplitting.scale(),
startPt,
generatedSplitting.lastPt(),
generatedSplitting.lastZ(),
1.);
}
}
Energy DipoleSplittingGenerator::generate(const DipoleSplittingInfo& split,
map<string,double>& variations,
Energy optHardPt,
Energy optCutoff) {
fixParameters(split,optHardPt);
if ( wrapping() ) {
return theOtherGenerator->generateWrapped(generatedSplitting,variations,optHardPt,optCutoff);
}
doGenerate(variations,optCutoff);
return generatedSplitting.lastPt();
}
Energy DipoleSplittingGenerator::generateWrapped(DipoleSplittingInfo& split,
map<string,double>& variations,
Energy optHardPt,
Energy optCutoff) {
assert(!wrapping());
DipoleSplittingInfo backup = generatedSplitting;
generatedSplitting = split;
fixParameters(split,optHardPt);
try {
doGenerate(variations,optCutoff);
} catch (...) {
split = generatedSplitting;
generatedSplitting = backup;
throw;
}
Energy pt = generatedSplitting.lastPt();
split = generatedSplitting;
generatedSplitting = backup;
return pt;
}
void DipoleSplittingGenerator::completeSplitting(DipoleSplittingInfo& sp) const {
pair<bool,bool> conf = sp.configuration();
sp = generatedSplitting;
sp.configuration(conf);
}
Ptr<DipoleSplittingKernel>::tptr DipoleSplittingGenerator::splittingKernel() const {
if ( wrapping() )
return theOtherGenerator->splittingKernel();
return theSplittingKernel;
}
Ptr<DipoleSplittingReweight>::tptr DipoleSplittingGenerator::splittingReweight() const {
if ( wrapping() )
return theOtherGenerator->splittingReweight();
return theSplittingReweight;
}
Ptr<DipoleSplittingKinematics>::tptr DipoleSplittingGenerator::splittingKinematics() const {
if ( wrapping() )
return theOtherGenerator->splittingKinematics();
return theSplittingKernel->splittingKinematics();
}
void DipoleSplittingGenerator::splittingKernel(Ptr<DipoleSplittingKernel>::tptr sp) {
theSplittingKernel = sp;
if ( theSplittingKernel->mcCheck() )
theMCCheck = theSplittingKernel->mcCheck();
}
void DipoleSplittingGenerator::splittingReweight(Ptr<DipoleSplittingReweight>::tptr sp) {
theSplittingReweight = sp;
}
void DipoleSplittingGenerator::debugGenerator(ostream& os) const {
os << "--- DipoleSplittingGenerator ---------------------------------------------------\n";
os << " generating splittings using\n"
<< " splittingKernel = " << splittingKernel()->name()
<< " splittingKinematics = " << generatedSplitting.splittingKinematics()->name() << "\n"
<< " to sample splittings of type:\n";
os << generatedSplitting;
os << "--------------------------------------------------------------------------------\n";
}
void DipoleSplittingGenerator::debugLastEvent(ostream& os) const {
os << "--- DipoleSplittingGenerator ---------------------------------------------------\n";
os << " last generated event:\n";
os << generatedSplitting;
os << "--------------------------------------------------------------------------------\n";
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void DipoleSplittingGenerator::persistentOutput(PersistentOStream & os) const {
os << theOtherGenerator << theSplittingKernel << theSplittingReweight << theMCCheck << theDoCompensate;
}
void DipoleSplittingGenerator::persistentInput(PersistentIStream & is, int) {
is >> theOtherGenerator >> theSplittingKernel >> theSplittingReweight >> theMCCheck >> theDoCompensate;
}
ClassDescription<DipoleSplittingGenerator> DipoleSplittingGenerator::initDipoleSplittingGenerator;
// Definition of the static class description member.
void DipoleSplittingGenerator::Init() {
static ClassDocumentation<DipoleSplittingGenerator> documentation
("DipoleSplittingGenerator is used by the dipole shower "
"to sample splittings from a given dipole splitting kernel.");
static Reference<DipoleSplittingGenerator,DipoleSplittingKernel> interfaceSplittingKernel
("SplittingKernel",
"Set the splitting kernel to sample from.",
&DipoleSplittingGenerator::theSplittingKernel, false, false, true, false, false);
static Reference<DipoleSplittingGenerator,DipoleSplittingReweight> interfaceSplittingReweight
("SplittingReweight",
"Set the splitting reweight.",
&DipoleSplittingGenerator::theSplittingReweight, false, false, true, true, false);
static Reference<DipoleSplittingGenerator,DipoleMCCheck> interfaceMCCheck
("MCCheck",
"[debug option] MCCheck",
&DipoleSplittingGenerator::theMCCheck, false, false, true, true, false);
interfaceMCCheck.rank(-1);
}
diff --git a/Shower/Dipole/DipoleShowerHandler.cc b/Shower/Dipole/DipoleShowerHandler.cc
--- a/Shower/Dipole/DipoleShowerHandler.cc
+++ b/Shower/Dipole/DipoleShowerHandler.cc
@@ -1,999 +1,999 @@
// -*- C++ -*-
//
// DipoleShowerHandler.cc 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.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the DipoleShowerHandler class.
//
#include <config.h>
#include "DipoleShowerHandler.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig/PDF/MPIPDF.h"
#include "Herwig/PDF/MinBiasPDF.h"
#include "Herwig/PDF/HwRemDecayer.h"
#include "Herwig/Shower/Dipole/Utility/DipolePartonSplitter.h"
#include "Herwig/MatrixElement/Matchbox/Base/SubtractedME.h"
#include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h"
using namespace Herwig;
bool DipoleShowerHandler::firstWarn = true;
DipoleShowerHandler::DipoleShowerHandler()
: ShowerHandler(), chainOrderVetoScales(true),
nEmissions(0), discardNoEmissions(false), firstMCatNLOEmission(false),
realignmentScheme(0),
verbosity(0), printEvent(0), nTries(0),
didRadiate(false), didRealign(false),
theRenormalizationScaleFreeze(1.*GeV),
theFactorizationScaleFreeze(2.*GeV), theDoCompensate(false),
theFreezeGrid(500000), theDetuning(1.0),
maxPt(ZERO), muPt(ZERO) {}
DipoleShowerHandler::~DipoleShowerHandler() {}
IBPtr DipoleShowerHandler::clone() const {
return new_ptr(*this);
}
IBPtr DipoleShowerHandler::fullclone() const {
return new_ptr(*this);
}
tPPair DipoleShowerHandler::cascade(tSubProPtr sub, XCPtr,
Energy optHardPt, Energy optCutoff) {
useMe();
prepareCascade(sub);
resetWeights();
if ( !doFSR() && ! doISR() )
return sub->incoming();
eventRecord().clear();
eventRecord().prepare(sub,dynamic_ptr_cast<tStdXCombPtr>(lastXCombPtr()),pdfs());
if ( eventRecord().outgoing().empty() && !doISR() )
return sub->incoming();
if ( !eventRecord().incoming().first->coloured() &&
!eventRecord().incoming().second->coloured() &&
!doFSR() )
return sub->incoming();
nTries = 0;
while ( true ) {
try {
didRadiate = false;
didRealign = false;
if ( eventRecord().truncatedShower() ) {
throw Exception() << "Inconsistent hard emission set-up in DipoleShowerHandler::cascade. "
<< "No truncated shower needed with DipoleShowerHandler. Add "
<< "'set MEMatching:TruncatedShower No' to input file."
<< Exception::runerror;
}
hardScales(lastXCombPtr()->lastShowerScale());
if ( verbosity > 1 ) {
generator()->log() << "DipoleShowerHandler starting off:\n";
eventRecord().debugLastEvent(generator()->log());
generator()->log() << flush;
}
unsigned int nEmitted = 0;
if ( firstMCatNLOEmission ) {
if ( !eventRecord().isMCatNLOHEvent() )
nEmissions = 1;
else
nEmissions = 0;
}
if ( !firstMCatNLOEmission ) {
doCascade(nEmitted,optHardPt,optCutoff);
if ( discardNoEmissions ) {
if ( !didRadiate )
throw Veto();
if ( nEmissions )
if ( nEmissions < nEmitted )
throw Veto();
}
} else {
if ( nEmissions == 1 )
doCascade(nEmitted,optHardPt,optCutoff);
}
if ( intrinsicPtGenerator ) {
if ( eventRecord().incoming().first->coloured() &&
eventRecord().incoming().second->coloured() ) {
SpinOneLorentzRotation rot =
intrinsicPtGenerator->kick(eventRecord().incoming(),
eventRecord().intermediates());
eventRecord().transform(rot);
}
}
didRealign = realign();
constituentReshuffle();
break;
} catch (RedoShower&) {
resetWeights();
if ( ++nTries > maxtry() )
throw ShowerTriesVeto(maxtry());
eventRecord().clear();
eventRecord().prepare(sub,dynamic_ptr_cast<tStdXCombPtr>(lastXCombPtr()),pdfs());
continue;
} catch (...) {
throw;
}
}
return eventRecord().fillEventRecord(newStep(),firstInteraction(),didRealign);
}
void DipoleShowerHandler::constituentReshuffle() {
if ( constituentReshuffler ) {
constituentReshuffler->reshuffle(eventRecord().outgoing(),
eventRecord().incoming(),
eventRecord().intermediates());
}
}
void DipoleShowerHandler::hardScales(Energy2 muf) {
maxPt = generator()->maximumCMEnergy();
if ( restrictPhasespace() ) {
if ( !hardScaleIsMuF() || !firstInteraction() ) {
if ( !eventRecord().outgoing().empty() ) {
for ( PList::const_iterator p = eventRecord().outgoing().begin();
p != eventRecord().outgoing().end(); ++p )
maxPt = min(maxPt,(**p).momentum().mt());
} else {
assert(!eventRecord().hard().empty());
Lorentz5Momentum phard(ZERO,ZERO,ZERO,ZERO);
for ( PList::const_iterator p = eventRecord().hard().begin();
p != eventRecord().hard().end(); ++p )
phard += (**p).momentum();
Energy mhard = phard.m();
maxPt = mhard;
}
maxPt *= hardScaleFactor();
} else {
maxPt = hardScaleFactor()*sqrt(muf);
}
muPt = maxPt;
} else {
muPt = hardScaleFactor()*sqrt(muf);
}
for ( list<DipoleChain>::iterator ch = eventRecord().chains().begin();
ch != eventRecord().chains().end(); ++ch ) {
Energy minVetoScale = -1.*GeV;
for ( list<Dipole>::iterator dip = ch->dipoles().begin();
dip != ch->dipoles().end(); ++dip ) {
// max scale per config
Energy maxFirst = 0.0*GeV;
Energy maxSecond = 0.0*GeV;
for ( vector<Ptr<DipoleSplittingKernel>::ptr>::iterator k =
kernels.begin(); k != kernels.end(); ++k ) {
pair<bool,bool> conf = make_pair(true,false);
if ( (**k).canHandle(dip->index(conf)) ) {
Energy scale =
evolutionOrdering()->hardScale(dip->emitter(conf),dip->spectator(conf),
dip->emitterX(conf),dip->spectatorX(conf),
**k,dip->index(conf));
maxFirst = max(maxFirst,scale);
}
conf = make_pair(false,true);
if ( (**k).canHandle(dip->index(conf)) ) {
Energy scale =
evolutionOrdering()->hardScale(dip->emitter(conf),dip->spectator(conf),
dip->emitterX(conf),dip->spectatorX(conf),
**k,dip->index(conf));
maxSecond = max(maxSecond,scale);
}
}
if ( dip->leftParticle()->vetoScale() >= ZERO ) {
maxFirst = min(maxFirst,sqrt(dip->leftParticle()->vetoScale()));
if ( minVetoScale >= ZERO )
minVetoScale = min(minVetoScale,sqrt(dip->leftParticle()->vetoScale()));
else
minVetoScale = sqrt(dip->leftParticle()->vetoScale());
}
if ( dip->rightParticle()->vetoScale() >= ZERO ) {
maxSecond = min(maxSecond,sqrt(dip->rightParticle()->vetoScale()));
if ( minVetoScale >= ZERO )
minVetoScale = min(minVetoScale,sqrt(dip->rightParticle()->vetoScale()));
else
minVetoScale = sqrt(dip->rightParticle()->vetoScale());
}
maxFirst = min(maxPt,maxFirst);
dip->emitterScale(make_pair(true,false),maxFirst);
maxSecond = min(maxPt,maxSecond);
dip->emitterScale(make_pair(false,true),maxSecond);
}
if ( !evolutionOrdering()->independentDipoles() &&
chainOrderVetoScales &&
minVetoScale >= ZERO ) {
for ( list<Dipole>::iterator dip = ch->dipoles().begin();
dip != ch->dipoles().end(); ++dip ) {
dip->leftScale(min(dip->leftScale(),minVetoScale));
dip->rightScale(min(dip->rightScale(),minVetoScale));
}
}
}
}
Energy DipoleShowerHandler::getWinner(DipoleSplittingInfo& winner,
const Dipole& dip,
pair<bool,bool> conf,
Energy optHardPt,
Energy optCutoff) {
return
getWinner(winner,dip.index(conf),
dip.emitterX(conf),dip.spectatorX(conf),
conf,dip.emitter(conf),dip.spectator(conf),
dip.emitterScale(conf),optHardPt,optCutoff);
}
Energy DipoleShowerHandler::getWinner(SubleadingSplittingInfo& winner,
Energy optHardPt,
Energy optCutoff) {
return
getWinner(winner,winner.index(),
winner.emitterX(),winner.spectatorX(),
winner.configuration(),
winner.emitter(),winner.spectator(),
winner.startScale(),optHardPt,optCutoff);
}
Energy DipoleShowerHandler::getWinner(DipoleSplittingInfo& winner,
const DipoleIndex& index,
double emitterX, double spectatorX,
pair<bool,bool> conf,
tPPtr emitter, tPPtr spectator,
Energy startScale,
Energy optHardPt,
Energy optCutoff) {
if ( !index.initialStateEmitter() &&
!doFSR() ) {
winner.didStopEvolving();
return 0.0*GeV;
}
if ( index.initialStateEmitter() &&
!doISR() ) {
winner.didStopEvolving();
return 0.0*GeV;
}
DipoleSplittingInfo candidate;
candidate.index(index);
candidate.configuration(conf);
candidate.emitterX(emitterX);
candidate.spectatorX(spectatorX);
candidate.emitter(emitter);
candidate.spectator(spectator);
if ( generators().find(candidate.index()) == generators().end() )
getGenerators(candidate.index(),theSplittingReweight);
//
// NOTE -- needs proper fixing at some point
//
// For some very strange reason, equal_range gives back
// key ranges it hasn't been asked for. This particularly
// happens e.g. for FI dipoles of the same kind, but different
// PDF (hard vs MPI PDF). I can't see a reason for this,
// as DipoleIndex properly implements comparison for equality
// and (lexicographic) ordering; for the time being, we
// use equal_range, extented by an explicit check for wether
// the key is indeed what we wanted. See line after (*) comment
// below.
//
pair<GeneratorMap::iterator,GeneratorMap::iterator> gens
= generators().equal_range(candidate.index());
Energy winnerScale = 0.0*GeV;
GeneratorMap::iterator winnerGen = generators().end();
for ( GeneratorMap::iterator gen = gens.first; gen != gens.second; ++gen ) {
// (*) see NOTE above
if ( !(gen->first == candidate.index()) )
continue;
if ( startScale <= gen->second->splittingKinematics()->IRCutoff() )
continue;
Energy dScale =
gen->second->splittingKinematics()->dipoleScale(emitter->momentum(),
spectator->momentum());
// in very exceptional cases happening in DIS
- if ( isnan(dScale/GeV ) )
+ if ( std::isnan( double(dScale/MeV) ) )
throw RedoShower();
candidate.scale(dScale);
candidate.continuesEvolving();
Energy hardScale = evolutionOrdering()->maxPt(startScale,candidate,*(gen->second->splittingKernel()));
Energy maxPossible =
gen->second->splittingKinematics()->ptMax(candidate.scale(),
candidate.emitterX(), candidate.spectatorX(),
candidate.index(),
*gen->second->splittingKernel());
Energy ircutoff =
optCutoff < gen->second->splittingKinematics()->IRCutoff() ?
gen->second->splittingKinematics()->IRCutoff() :
optCutoff;
if ( maxPossible <= ircutoff ) {
continue;
}
if ( maxPossible >= hardScale )
candidate.hardPt(hardScale);
else {
hardScale = maxPossible;
candidate.hardPt(maxPossible);
}
gen->second->generate(candidate,currentWeights(),optHardPt,optCutoff);
Energy nextScale = evolutionOrdering()->evolutionScale(gen->second->lastSplitting(),*(gen->second->splittingKernel()));
if ( nextScale > winnerScale ) {
winner.fill(candidate);
gen->second->completeSplitting(winner);
winnerGen = gen;
winnerScale = nextScale;
}
reweight(reweight() * gen->second->splittingWeight());
}
if ( winnerGen == generators().end() ) {
winner.didStopEvolving();
return 0.0*GeV;
}
if ( winner.stoppedEvolving() )
return 0.0*GeV;
return winnerScale;
}
void DipoleShowerHandler::doCascade(unsigned int& emDone,
Energy optHardPt,
Energy optCutoff) {
if ( nEmissions )
if ( emDone == nEmissions )
return;
DipoleSplittingInfo winner;
DipoleSplittingInfo dipoleWinner;
while ( eventRecord().haveChain() ) {
if ( verbosity > 2 ) {
generator()->log() << "DipoleShowerHandler selecting splittings for the chain:\n"
<< eventRecord().currentChain() << flush;
}
list<Dipole>::iterator winnerDip = eventRecord().currentChain().dipoles().end();
Energy winnerScale = 0.0*GeV;
Energy nextLeftScale = 0.0*GeV;
Energy nextRightScale = 0.0*GeV;
for ( list<Dipole>::iterator dip = eventRecord().currentChain().dipoles().begin();
dip != eventRecord().currentChain().dipoles().end(); ++dip ) {
nextLeftScale = getWinner(dipoleWinner,*dip,make_pair(true,false),optHardPt,optCutoff);
if ( nextLeftScale > winnerScale ) {
winnerScale = nextLeftScale;
winner = dipoleWinner;
winnerDip = dip;
}
nextRightScale = getWinner(dipoleWinner,*dip,make_pair(false,true),optHardPt,optCutoff);
if ( nextRightScale > winnerScale ) {
winnerScale = nextRightScale;
winner = dipoleWinner;
winnerDip = dip;
}
if ( evolutionOrdering()->independentDipoles() ) {
Energy dipScale = max(nextLeftScale,nextRightScale);
if ( dip->leftScale() > dipScale )
dip->leftScale(dipScale);
if ( dip->rightScale() > dipScale )
dip->rightScale(dipScale);
}
}
if ( verbosity > 1 ) {
if ( winnerDip != eventRecord().currentChain().dipoles().end() )
generator()->log() << "DipoleShowerHandler selected the splitting:\n"
<< winner << " for the dipole\n"
<< (*winnerDip) << flush;
else
generator()->log() << "DipoleShowerHandler could not select a splitting above the IR cutoff\n"
<< flush;
}
// pop the chain if no dipole did radiate
if ( winnerDip == eventRecord().currentChain().dipoles().end() ) {
eventRecord().popChain();
if ( theEventReweight && eventRecord().chains().empty() )
if ( (theEventReweight->firstInteraction() && firstInteraction()) ||
(theEventReweight->secondaryInteractions() && !firstInteraction()) ) {
double w = theEventReweight->weightCascade(eventRecord().incoming(),
eventRecord().outgoing(),
eventRecord().hard(),theGlobalAlphaS);
reweight(reweight()*w);
}
continue;
}
// otherwise perform the splitting
didRadiate = true;
eventRecord().isMCatNLOSEvent(false);
eventRecord().isMCatNLOHEvent(false);
pair<list<Dipole>::iterator,list<Dipole>::iterator> children;
DipoleChain* firstChain = 0;
DipoleChain* secondChain = 0;
eventRecord().split(winnerDip,winner,children,firstChain,secondChain);
assert(firstChain && secondChain);
evolutionOrdering()->setEvolutionScale(winnerScale,winner,*firstChain,children);
if ( !secondChain->dipoles().empty() )
evolutionOrdering()->setEvolutionScale(winnerScale,winner,*secondChain,children);
if ( verbosity > 1 ) {
generator()->log() << "DipoleShowerHandler did split the last selected dipole into:\n"
<< (*children.first) << (*children.second) << flush;
}
if ( verbosity > 2 ) {
generator()->log() << "After splitting the last selected dipole, "
<< "DipoleShowerHandler encountered the following chains:\n"
<< (*firstChain) << (*secondChain) << flush;
}
if ( theEventReweight )
if ( (theEventReweight->firstInteraction() && firstInteraction()) ||
(theEventReweight->secondaryInteractions() && !firstInteraction()) ) {
double w = theEventReweight->weight(eventRecord().incoming(),
eventRecord().outgoing(),
eventRecord().hard(),theGlobalAlphaS);
reweight(reweight()*w);
}
if ( nEmissions )
if ( ++emDone == nEmissions )
return;
}
}
bool DipoleShowerHandler::realign() {
if ( !didRadiate && !intrinsicPtGenerator )
return false;
if ( eventRecord().incoming().first->coloured() ||
eventRecord().incoming().second->coloured() ) {
if ( eventRecord().incoming().first->momentum().perp2()/GeV2 < 1e-10 &&
eventRecord().incoming().second->momentum().perp2()/GeV2 < 1e-10 )
return false;
pair<Lorentz5Momentum,Lorentz5Momentum> inMomenta
(eventRecord().incoming().first->momentum(),
eventRecord().incoming().second->momentum());
SpinOneLorentzRotation transform((inMomenta.first+inMomenta.second).findBoostToCM());
Axis dir = (transform * inMomenta.first).vect().unit();
Axis rot (-dir.y(),dir.x(),0);
double theta = dir.theta();
if ( lastParticles().first->momentum().z() < ZERO )
theta = -theta;
transform.rotate(-theta,rot);
inMomenta.first = transform*inMomenta.first;
inMomenta.second = transform*inMomenta.second;
assert(inMomenta.first.z() > ZERO &&
inMomenta.second.z() < ZERO);
Energy2 sHat =
(eventRecord().incoming().first->momentum() +
eventRecord().incoming().second->momentum()).m2();
pair<Energy,Energy> masses(eventRecord().incoming().first->mass(),
eventRecord().incoming().second->mass());
pair<Energy,Energy> qs;
if ( !eventRecord().incoming().first->coloured() ) {
assert(masses.second == ZERO);
qs.first = eventRecord().incoming().first->momentum().z();
qs.second = (sHat-sqr(masses.first))/(2.*(qs.first+sqrt(sqr(masses.first)+sqr(qs.first))));
} else if ( !eventRecord().incoming().second->coloured() ) {
assert(masses.first == ZERO);
qs.second = eventRecord().incoming().second->momentum().z();
qs.first = (sHat-sqr(masses.second))/(2.*(qs.second+sqrt(sqr(masses.second)+sqr(qs.second))));
} else {
assert(masses.first == ZERO && masses.second == ZERO);
if ( realignmentScheme == 0 ) {
double yX = eventRecord().pX().rapidity();
double yInt = (transform*eventRecord().pX()).rapidity();
double dy = yX-yInt;
qs.first = (sqrt(sHat)/2.)*exp(dy);
qs.second = (sqrt(sHat)/2.)*exp(-dy);
} else if ( realignmentScheme == 1 ) {
Energy sS = sqrt((lastParticles().first->momentum() +
lastParticles().second->momentum()).m2());
qs.first = eventRecord().fractions().first * sS / 2.;
qs.second = eventRecord().fractions().second * sS / 2.;
}
}
double beta =
(qs.first-qs.second) /
( sqrt(sqr(masses.first)+sqr(qs.first)) +
sqrt(sqr(masses.second)+sqr(qs.second)) );
transform.boostZ(beta);
Lorentz5Momentum tmp;
if ( eventRecord().incoming().first->coloured() ) {
tmp = eventRecord().incoming().first->momentum();
tmp = transform * tmp;
eventRecord().incoming().first->set5Momentum(tmp);
}
if ( eventRecord().incoming().second->coloured() ) {
tmp = eventRecord().incoming().second->momentum();
tmp = transform * tmp;
eventRecord().incoming().second->set5Momentum(tmp);
}
eventRecord().transform(transform);
return true;
}
return false;
}
void DipoleShowerHandler::resetAlphaS(Ptr<AlphaSBase>::tptr as) {
for ( vector<Ptr<DipoleSplittingKernel>::ptr>::iterator k = kernels.begin();
k != kernels.end(); ++k ) {
if ( !(**k).alphaS() )
(**k).alphaS(as);
(**k).renormalizationScaleFreeze(theRenormalizationScaleFreeze);
(**k).factorizationScaleFreeze(theFactorizationScaleFreeze);
}
// clear the generators to be rebuild
// actually, there shouldn't be any generators
// when this happens.
generators().clear();
}
void DipoleShowerHandler::resetReweight(Ptr<DipoleSplittingReweight>::tptr rw) {
for ( GeneratorMap::iterator k = generators().begin();
k != generators().end(); ++k )
k->second->splittingReweight(rw);
}
void DipoleShowerHandler::getGenerators(const DipoleIndex& ind,
Ptr<DipoleSplittingReweight>::tptr rw) {
bool gotone = false;
for ( vector<Ptr<DipoleSplittingKernel>::ptr>::iterator k =
kernels.begin(); k != kernels.end(); ++k ) {
if ( (**k).canHandle(ind) ) {
if ( verbosity > 0 ) {
generator()->log() << "DipoleShowerHandler encountered the dipole configuration\n"
<< ind << " in event number "
<< eventHandler()->currentEvent()->number()
<< "\nwhich can be handled by the splitting kernel '"
<< (**k).name() << "'.\n" << flush;
}
gotone = true;
Ptr<DipoleSplittingGenerator>::ptr nGenerator =
new_ptr(DipoleSplittingGenerator());
nGenerator->doCompensate(theDoCompensate);
nGenerator->splittingKernel(*k);
if ( renormalizationScaleFactor() != 1. )
nGenerator->splittingKernel()->renormalizationScaleFactor(renormalizationScaleFactor());
if ( factorizationScaleFactor() != 1. )
nGenerator->splittingKernel()->factorizationScaleFactor(factorizationScaleFactor());
if ( !nGenerator->splittingReweight() )
nGenerator->splittingReweight(rw);
nGenerator->splittingKernel()->freezeGrid(theFreezeGrid);
nGenerator->splittingKernel()->detuning(theDetuning);
GeneratorMap::const_iterator equivalent = generators().end();
for ( GeneratorMap::const_iterator eq = generators().begin();
eq != generators().end(); ++eq ) {
if ( !eq->second->wrapping() )
if ( (**k).canHandleEquivalent(ind,*(eq->second->splittingKernel()),eq->first) ) {
equivalent = eq;
if ( verbosity > 0 ) {
generator()->log() << "The dipole configuration "
<< ind
<< " can equivalently be handled by the existing\n"
<< "generator for configuration "
<< eq->first << " using the kernel '"
<< eq->second->splittingKernel()->name()
<< "'\n" << flush;
}
break;
}
}
if ( equivalent != generators().end() ) {
nGenerator->wrap(equivalent->second);
}
DipoleSplittingInfo dummy;
dummy.index(ind);
nGenerator->prepare(dummy);
generators().insert(make_pair(ind,nGenerator));
}
}
if ( !gotone ) {
generator()->logWarning(Exception()
<< "DipoleShowerHandler could not "
<< "find a splitting kernel which is able "
<< "to handle splittings off the dipole "
<< ind << ".\n"
<< "Please check the input files."
<< Exception::warning);
}
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void DipoleShowerHandler::doinit() {
ShowerHandler::doinit();
if ( theGlobalAlphaS )
resetAlphaS(theGlobalAlphaS);
}
void DipoleShowerHandler::dofinish() {
ShowerHandler::dofinish();
}
void DipoleShowerHandler::doinitrun() {
ShowerHandler::doinitrun();
}
void DipoleShowerHandler::persistentOutput(PersistentOStream & os) const {
os << kernels << theEvolutionOrdering
<< constituentReshuffler << intrinsicPtGenerator
<< theGlobalAlphaS << chainOrderVetoScales
<< nEmissions << discardNoEmissions << firstMCatNLOEmission
<< realignmentScheme << verbosity << printEvent
<< ounit(theRenormalizationScaleFreeze,GeV)
<< ounit(theFactorizationScaleFreeze,GeV)
<< theShowerApproximation
<< theDoCompensate << theFreezeGrid << theDetuning
<< theEventReweight << theSplittingReweight << ounit(maxPt,GeV)
<< ounit(muPt,GeV);
}
void DipoleShowerHandler::persistentInput(PersistentIStream & is, int) {
is >> kernels >> theEvolutionOrdering
>> constituentReshuffler >> intrinsicPtGenerator
>> theGlobalAlphaS >> chainOrderVetoScales
>> nEmissions >> discardNoEmissions >> firstMCatNLOEmission
>> realignmentScheme >> verbosity >> printEvent
>> iunit(theRenormalizationScaleFreeze,GeV)
>> iunit(theFactorizationScaleFreeze,GeV)
>> theShowerApproximation
>> theDoCompensate >> theFreezeGrid >> theDetuning
>> theEventReweight >> theSplittingReweight >> iunit(maxPt,GeV)
>> iunit(muPt,GeV);
}
ClassDescription<DipoleShowerHandler> DipoleShowerHandler::initDipoleShowerHandler;
// Definition of the static class description member.
void DipoleShowerHandler::Init() {
static ClassDocumentation<DipoleShowerHandler> documentation
("The DipoleShowerHandler class manages the showering using "
"the dipole shower algorithm.",
"The shower evolution was performed using the algorithm described in "
"\\cite{Platzer:2009jq} and \\cite{Platzer:2011bc}.",
"%\\cite{Platzer:2009jq}\n"
"\\bibitem{Platzer:2009jq}\n"
"S.~Platzer and S.~Gieseke,\n"
"``Coherent Parton Showers with Local Recoils,''\n"
" JHEP {\\bf 1101}, 024 (2011)\n"
"arXiv:0909.5593 [hep-ph].\n"
"%%CITATION = ARXIV:0909.5593;%%\n"
"%\\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;%%");
static RefVector<DipoleShowerHandler,DipoleSplittingKernel> interfaceKernels
("Kernels",
"Set the splitting kernels to be used by the dipole shower.",
&DipoleShowerHandler::kernels, -1, false, false, true, false, false);
static Reference<DipoleShowerHandler,DipoleEvolutionOrdering> interfaceEvolutionOrdering
("EvolutionOrdering",
"Set the evolution ordering to be used.",
&DipoleShowerHandler::theEvolutionOrdering, false, false, true, false, false);
static Reference<DipoleShowerHandler,ConstituentReshuffler> interfaceConstituentReshuffler
("ConstituentReshuffler",
"The object to be used to reshuffle partons to their constitutent mass shells.",
&DipoleShowerHandler::constituentReshuffler, false, false, true, true, false);
static Reference<DipoleShowerHandler,IntrinsicPtGenerator> interfaceIntrinsicPtGenerator
("IntrinsicPtGenerator",
"Set the object in charge to generate intrinsic pt for incoming partons.",
&DipoleShowerHandler::intrinsicPtGenerator, false, false, true, true, false);
static Reference<DipoleShowerHandler,AlphaSBase> interfaceGlobalAlphaS
("GlobalAlphaS",
"Set a global strong coupling for all splitting kernels.",
&DipoleShowerHandler::theGlobalAlphaS, false, false, true, true, false);
static Switch<DipoleShowerHandler,int> interfaceRealignmentScheme
("RealignmentScheme",
"The realignment scheme to use.",
&DipoleShowerHandler::realignmentScheme, 0, false, false);
static SwitchOption interfaceRealignmentSchemePreserveRapidity
(interfaceRealignmentScheme,
"PreserveRapidity",
"Preserve the rapidity of non-coloured outgoing system.",
0);
static SwitchOption interfaceRealignmentSchemeEvolutionFractions
(interfaceRealignmentScheme,
"EvolutionFractions",
"Use momentum fractions as generated by the evolution.",
1);
static SwitchOption interfaceRealignmentSchemeCollisionFrame
(interfaceRealignmentScheme,
"CollisionFrame",
"Determine realignment from collision frame.",
2);
static Switch<DipoleShowerHandler,bool> interfaceChainOrderVetoScales
("ChainOrderVetoScales",
"[experimental] Switch on or off the chain ordering for veto scales.",
&DipoleShowerHandler::chainOrderVetoScales, true, false, false);
static SwitchOption interfaceChainOrderVetoScalesOn
(interfaceChainOrderVetoScales,
"On",
"Switch on chain ordering for veto scales.",
true);
static SwitchOption interfaceChainOrderVetoScalesOff
(interfaceChainOrderVetoScales,
"Off",
"Switch off chain ordering for veto scales.",
false);
interfaceChainOrderVetoScales.rank(-1);
static Parameter<DipoleShowerHandler,unsigned int> interfaceNEmissions
("NEmissions",
"[debug option] Limit the number of emissions to be generated. Zero does not limit the number of emissions.",
&DipoleShowerHandler::nEmissions, 0, 0, 0,
false, false, Interface::lowerlim);
interfaceNEmissions.rank(-1);
static Switch<DipoleShowerHandler,bool> interfaceDiscardNoEmissions
("DiscardNoEmissions",
"[debug option] Discard events without radiation.",
&DipoleShowerHandler::discardNoEmissions, false, false, false);
static SwitchOption interfaceDiscardNoEmissionsOn
(interfaceDiscardNoEmissions,
"On",
"Discard events without radiation.",
true);
static SwitchOption interfaceDiscardNoEmissionsOff
(interfaceDiscardNoEmissions,
"Off",
"Do not discard events without radiation.",
false);
interfaceDiscardNoEmissions.rank(-1);
static Switch<DipoleShowerHandler,bool> interfaceFirstMCatNLOEmission
("FirstMCatNLOEmission",
"[debug option] Only perform the first MC@NLO emission.",
&DipoleShowerHandler::firstMCatNLOEmission, false, false, false);
static SwitchOption interfaceFirstMCatNLOEmissionOn
(interfaceFirstMCatNLOEmission,
"On",
"",
true);
static SwitchOption interfaceFirstMCatNLOEmissionOff
(interfaceFirstMCatNLOEmission,
"Off",
"",
false);
interfaceFirstMCatNLOEmission.rank(-1);
static Parameter<DipoleShowerHandler,int> interfaceVerbosity
("Verbosity",
"[debug option] Set the level of debug information provided.",
&DipoleShowerHandler::verbosity, 0, 0, 0,
false, false, Interface::lowerlim);
interfaceVerbosity.rank(-1);
static Parameter<DipoleShowerHandler,int> interfacePrintEvent
("PrintEvent",
"[debug option] The number of events for which debugging information should be provided.",
&DipoleShowerHandler::printEvent, 0, 0, 0,
false, false, Interface::lowerlim);
interfacePrintEvent.rank(-1);
static Parameter<DipoleShowerHandler,Energy> interfaceRenormalizationScaleFreeze
("RenormalizationScaleFreeze",
"The freezing scale for the renormalization scale.",
&DipoleShowerHandler::theRenormalizationScaleFreeze, GeV, 1.0*GeV, 0.0*GeV, 0*GeV,
false, false, Interface::lowerlim);
static Parameter<DipoleShowerHandler,Energy> interfaceFactorizationScaleFreeze
("FactorizationScaleFreeze",
"The freezing scale for the factorization scale.",
&DipoleShowerHandler::theFactorizationScaleFreeze, GeV, 2.0*GeV, 0.0*GeV, 0*GeV,
false, false, Interface::lowerlim);
static Switch<DipoleShowerHandler,bool> interfaceDoCompensate
("DoCompensate",
"",
&DipoleShowerHandler::theDoCompensate, false, false, false);
static SwitchOption interfaceDoCompensateYes
(interfaceDoCompensate,
"Yes",
"",
true);
static SwitchOption interfaceDoCompensateNo
(interfaceDoCompensate,
"No",
"",
false);
static Parameter<DipoleShowerHandler,unsigned long> interfaceFreezeGrid
("FreezeGrid",
"",
&DipoleShowerHandler::theFreezeGrid, 500000, 1, 0,
false, false, Interface::lowerlim);
static Parameter<DipoleShowerHandler,double> interfaceDetuning
("Detuning",
"A value to detune the overestimate kernel.",
&DipoleShowerHandler::theDetuning, 1.0, 1.0, 0,
false, false, Interface::lowerlim);
static Reference<DipoleShowerHandler,DipoleEventReweight> interfaceEventReweight
("EventReweight",
"",
&DipoleShowerHandler::theEventReweight, false, false, true, true, false);
static Reference<DipoleShowerHandler,DipoleSplittingReweight> interfaceSplittingReweight
("SplittingReweight",
"Set the splitting reweight.",
&DipoleShowerHandler::theSplittingReweight, false, false, true, true, false);
}
diff --git a/Shower/Dipole/Kernels/IFMgx2qqxDipoleKernel.h b/Shower/Dipole/Kernels/IFMgx2qqxDipoleKernel.h
--- a/Shower/Dipole/Kernels/IFMgx2qqxDipoleKernel.h
+++ b/Shower/Dipole/Kernels/IFMgx2qqxDipoleKernel.h
@@ -1,181 +1,181 @@
// -*- C++ -*-
-#ifndef HERWIG_IFgx2qqxDipoleKernel_H
-#define HERWIG_IFgx2qqxDipoleKernel_H
+#ifndef HERWIG_IFMgx2qqxDipoleKernel_H
+#define HERWIG_IFMgx2qqxDipoleKernel_H
//
// This is the declaration of the IFgx2qqxDipoleKernel class.
//
#include "DipoleSplittingKernel.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup DipoleShower
* \author Simon Platzer, Martin Stoll
*
* \brief IFMgx2qqxDipoleKernel implements the g -> qq
* splitting off an initial-final dipole
*
*/
class IFMgx2qqxDipoleKernel: public DipoleSplittingKernel {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
IFMgx2qqxDipoleKernel();
/**
* The destructor.
*/
virtual ~IFMgx2qqxDipoleKernel();
//@}
public:
/**
* Return true, if this splitting kernel
* applies to the given dipole index.
*/
virtual bool canHandle(const DipoleIndex&) const;
/**
* Return true, if this splitting kernel is
* the same for the given index a, as the given
* splitting kernel for index b.
*/
virtual bool canHandleEquivalent(const DipoleIndex& a,
const DipoleSplittingKernel& sk,
const DipoleIndex& b) const;
/**
* Return the emitter data after splitting, given
* a dipole index.
*/
virtual tcPDPtr emitter(const DipoleIndex&) const;
/**
* Return the emission data after splitting, given
* a dipole index.
*/
virtual tcPDPtr emission(const DipoleIndex&) const;
/**
* Return the spectator data after splitting, given
* a dipole index.
*/
virtual tcPDPtr spectator(const DipoleIndex&) const;
/**
* Evaluate this splitting kernel for the given
* dipole splitting.
*/
virtual double evaluate(const DipoleSplittingInfo&) 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:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<IFMgx2qqxDipoleKernel> initIFMgx2qqxDipoleKernel;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
IFMgx2qqxDipoleKernel & operator=(const IFMgx2qqxDipoleKernel &);
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of IFMgx2qqxDipoleKernel. */
template <>
struct BaseClassTrait<Herwig::IFMgx2qqxDipoleKernel,1> {
/** Typedef of the first base class of IFMgx2qqxDipoleKernel. */
typedef Herwig::DipoleSplittingKernel NthBase;
};
/** This template specialization informs ThePEG about the name of
* the IFMgx2qqxDipoleKernel class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::IFMgx2qqxDipoleKernel>
: public ClassTraitsBase<Herwig::IFMgx2qqxDipoleKernel> {
/** Return a platform-independent class name */
static string className() { return "Herwig::IFMgx2qqxDipoleKernel"; }
/**
* The name of a file containing the dynamic library where the class
* IFMgx2qqxDipoleKernel is implemented. It may also include several, space-separated,
* libraries if the class IFMgx2qqxDipoleKernel depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwDipoleShower.so"; }
};
/** @endcond */
}
#endif /* HERWIG_IFMgx2qqxDipoleKernel_H */
diff --git a/Shower/Dipole/Kernels/IFMqx2gqxDipoleKernel.h b/Shower/Dipole/Kernels/IFMqx2gqxDipoleKernel.h
--- a/Shower/Dipole/Kernels/IFMqx2gqxDipoleKernel.h
+++ b/Shower/Dipole/Kernels/IFMqx2gqxDipoleKernel.h
@@ -1,181 +1,181 @@
// -*- C++ -*-
-#ifndef HERWIG_IFqx2gqxDipoleKernel_H
-#define HERWIG_IFqx2gqxDipoleKernel_H
+#ifndef HERWIG_IFMqx2gqxDipoleKernel_H
+#define HERWIG_IFMqx2gqxDipoleKernel_H
//
// This is the declaration of the IFqx2gqxDipoleKernel class.
//
#include "DipoleSplittingKernel.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup DipoleShower
* \author Simon Platzer, Martin Stoll
*
* \brief IFMqx2gqxDipoleKernel implements the q -> gqbar
* splitting off an initial-final dipole
*
*/
class IFMqx2gqxDipoleKernel: public DipoleSplittingKernel {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
IFMqx2gqxDipoleKernel();
/**
* The destructor.
*/
virtual ~IFMqx2gqxDipoleKernel();
//@}
public:
/**
* Return true, if this splitting kernel
* applies to the given dipole index.
*/
virtual bool canHandle(const DipoleIndex&) const;
/**
* Return true, if this splitting kernel is
* the same for the given index a, as the given
* splitting kernel for index b.
*/
virtual bool canHandleEquivalent(const DipoleIndex& a,
const DipoleSplittingKernel& sk,
const DipoleIndex& b) const;
/**
* Return the emitter data after splitting, given
* a dipole index.
*/
virtual tcPDPtr emitter(const DipoleIndex&) const;
/**
* Return the emission data after splitting, given
* a dipole index.
*/
virtual tcPDPtr emission(const DipoleIndex&) const;
/**
* Return the spectator data after splitting, given
* a dipole index.
*/
virtual tcPDPtr spectator(const DipoleIndex&) const;
/**
* Evaluate this splitting kernel for the given
* dipole splitting.
*/
virtual double evaluate(const DipoleSplittingInfo&) 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:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<IFMqx2gqxDipoleKernel> initIFMqx2gqxDipoleKernel;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
IFMqx2gqxDipoleKernel & operator=(const IFMqx2gqxDipoleKernel &);
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of IFMqx2gqxDipoleKernel. */
template <>
struct BaseClassTrait<Herwig::IFMqx2gqxDipoleKernel,1> {
/** Typedef of the first base class of IFMqx2gqxDipoleKernel. */
typedef Herwig::DipoleSplittingKernel NthBase;
};
/** This template specialization informs ThePEG about the name of
* the IFMqx2gqxDipoleKernel class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::IFMqx2gqxDipoleKernel>
: public ClassTraitsBase<Herwig::IFMqx2gqxDipoleKernel> {
/** Return a platform-independent class name */
static string className() { return "Herwig::IFMqx2gqxDipoleKernel"; }
/**
* The name of a file containing the dynamic library where the class
* IFMqx2gqxDipoleKernel is implemented. It may also include several, space-separated,
* libraries if the class IFMqx2gqxDipoleKernel depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwDipoleShower.so"; }
};
/** @endcond */
}
#endif /* HERWIG_IFMqx2gqxDipoleKernel_H */
diff --git a/Shower/Dipole/Kernels/IFMqx2qgxDipoleKernel.h b/Shower/Dipole/Kernels/IFMqx2qgxDipoleKernel.h
--- a/Shower/Dipole/Kernels/IFMqx2qgxDipoleKernel.h
+++ b/Shower/Dipole/Kernels/IFMqx2qgxDipoleKernel.h
@@ -1,181 +1,181 @@
// -*- C++ -*-
-#ifndef HERWIG_IFqx2qgxDipoleKernel_H
-#define HERWIG_IFqx2qgxDipoleKernel_H
+#ifndef HERWIG_IFMqx2qgxDipoleKernel_H
+#define HERWIG_IFMqx2qgxDipoleKernel_H
//
// This is the declaration of the IFqx2qgxDipoleKernel class.
//
#include "DipoleSplittingKernel.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup DipoleShower
* \author Simon Platzer, Martin Stoll
*
* \brief IFMqx2qgxDipoleKernel implements the q -> qg
* splitting off an initial-final dipole
*
*/
class IFMqx2qgxDipoleKernel: public DipoleSplittingKernel {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
IFMqx2qgxDipoleKernel();
/**
* The destructor.
*/
virtual ~IFMqx2qgxDipoleKernel();
//@}
public:
/**
* Return true, if this splitting kernel
* applies to the given dipole index.
*/
virtual bool canHandle(const DipoleIndex&) const;
/**
* Return true, if this splitting kernel is
* the same for the given index a, as the given
* splitting kernel for index b.
*/
virtual bool canHandleEquivalent(const DipoleIndex& a,
const DipoleSplittingKernel& sk,
const DipoleIndex& b) const;
/**
* Return the emitter data after splitting, given
* a dipole index.
*/
virtual tcPDPtr emitter(const DipoleIndex&) const;
/**
* Return the emission data after splitting, given
* a dipole index.
*/
virtual tcPDPtr emission(const DipoleIndex&) const;
/**
* Return the spectator data after splitting, given
* a dipole index.
*/
virtual tcPDPtr spectator(const DipoleIndex&) const;
/**
* Evaluate this splitting kernel for the given
* dipole splitting.
*/
virtual double evaluate(const DipoleSplittingInfo&) 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:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<IFMqx2qgxDipoleKernel> initIFMqx2qgxDipoleKernel;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
IFMqx2qgxDipoleKernel & operator=(const IFMqx2qgxDipoleKernel &);
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of IFMqx2qgxDipoleKernel. */
template <>
struct BaseClassTrait<Herwig::IFMqx2qgxDipoleKernel,1> {
/** Typedef of the first base class of IFMqx2qgxDipoleKernel. */
typedef Herwig::DipoleSplittingKernel NthBase;
};
/** This template specialization informs ThePEG about the name of
* the IFMqx2qgxDipoleKernel class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::IFMqx2qgxDipoleKernel>
: public ClassTraitsBase<Herwig::IFMqx2qgxDipoleKernel> {
/** Return a platform-independent class name */
static string className() { return "Herwig::IFMqx2qgxDipoleKernel"; }
/**
* The name of a file containing the dynamic library where the class
* IFMqx2qgxDipoleKernel is implemented. It may also include several, space-separated,
* libraries if the class IFMqx2qgxDipoleKernel depends on other classes (base classes
* excepted). In this case the listed libraries will be dynamically
* linked in the order they are specified.
*/
static string library() { return "HwDipoleShower.so"; }
};
/** @endcond */
}
#endif /* HERWIG_IFMqx2qgxDipoleKernel_H */
diff --git a/Shower/Dipole/Kernels/Makefile.am b/Shower/Dipole/Kernels/Makefile.am
--- a/Shower/Dipole/Kernels/Makefile.am
+++ b/Shower/Dipole/Kernels/Makefile.am
@@ -1,27 +1,64 @@
noinst_LTLIBRARIES = libHwDipoleShowerKernels.la
libHwDipoleShowerKernels_la_SOURCES = \
- DipoleSplittingKernel.h DipoleSplittingKernel.cc \
- FFMqx2qgxDipoleKernel.h FFMqx2qgxDipoleKernel.cc \
- FFMgx2ggxDipoleKernel.h FFMgx2ggxDipoleKernel.cc \
- FFMgx2qqxDipoleKernel.h FFMgx2qqxDipoleKernel.cc \
- FFqx2qgxDipoleKernel.h FFqx2qgxDipoleKernel.cc \
- FFgx2ggxDipoleKernel.h FFgx2ggxDipoleKernel.cc \
- FFgx2qqxDipoleKernel.h FFgx2qqxDipoleKernel.cc \
- FIqx2qgxDipoleKernel.h FIqx2qgxDipoleKernel.cc \
- FIgx2ggxDipoleKernel.h FIgx2ggxDipoleKernel.cc \
- FIgx2qqxDipoleKernel.h FIgx2qqxDipoleKernel.cc \
- IFqx2qgxDipoleKernel.h IFqx2qgxDipoleKernel.cc \
- IFqx2gqxDipoleKernel.h IFqx2gqxDipoleKernel.cc \
- IFgx2ggxDipoleKernel.h IFgx2ggxDipoleKernel.cc \
- IFgx2qqxDipoleKernel.h IFgx2qqxDipoleKernel.cc \
- IIqx2qgxDipoleKernel.h IIqx2qgxDipoleKernel.cc \
- IIqx2gqxDipoleKernel.h IIqx2gqxDipoleKernel.cc \
- IIgx2ggxDipoleKernel.h IIgx2ggxDipoleKernel.cc \
- IIgx2qqxDipoleKernel.h IIgx2qqxDipoleKernel.cc \
- FIMqx2qgxDipoleKernel.h FIMqx2qgxDipoleKernel.cc \
- FIMgx2qqxDipoleKernel.h FIMgx2qqxDipoleKernel.cc \
- IFMqx2qgxDipoleKernel.h IFMqx2qgxDipoleKernel.cc \
- IFMqx2gqxDipoleKernel.h IFMqx2gqxDipoleKernel.cc \
- IFMgx2ggxDipoleKernel.h IFMgx2ggxDipoleKernel.cc \
- IFMgx2qqxDipoleKernel.h IFMgx2qqxDipoleKernel.cc
+$(ALL_H_FILES) DipoleKernels__all.cc
+
+BUILT_SOURCES = DipoleKernels__all.cc
+DISTCLEANFILES = DipoleKernels__all.cc
+
+DipoleKernels__all.cc : $(ALL_CC_FILES)
+ $(top_srcdir)/cat_with_cpplines $^ > $@
+
+EXTRA_DIST = $(ALL_CC_FILES)
+
+ALL_H_FILES = \
+ DipoleSplittingKernel.h \
+ FFMqx2qgxDipoleKernel.h \
+ FFMgx2ggxDipoleKernel.h \
+ FFMgx2qqxDipoleKernel.h \
+ FFqx2qgxDipoleKernel.h \
+ FFgx2ggxDipoleKernel.h \
+ FFgx2qqxDipoleKernel.h \
+ FIqx2qgxDipoleKernel.h \
+ FIgx2ggxDipoleKernel.h \
+ FIgx2qqxDipoleKernel.h \
+ IFqx2qgxDipoleKernel.h \
+ IFqx2gqxDipoleKernel.h \
+ IFgx2ggxDipoleKernel.h \
+ IFgx2qqxDipoleKernel.h \
+ IIqx2qgxDipoleKernel.h \
+ IIqx2gqxDipoleKernel.h \
+ IIgx2ggxDipoleKernel.h \
+ IIgx2qqxDipoleKernel.h \
+ FIMqx2qgxDipoleKernel.h \
+ FIMgx2qqxDipoleKernel.h \
+ IFMqx2qgxDipoleKernel.h \
+ IFMqx2gqxDipoleKernel.h \
+ IFMgx2ggxDipoleKernel.h \
+ IFMgx2qqxDipoleKernel.h
+
+ALL_CC_FILES = \
+ DipoleSplittingKernel.cc \
+ FFMqx2qgxDipoleKernel.cc \
+ FFMgx2ggxDipoleKernel.cc \
+ FFMgx2qqxDipoleKernel.cc \
+ FFqx2qgxDipoleKernel.cc \
+ FFgx2ggxDipoleKernel.cc \
+ FFgx2qqxDipoleKernel.cc \
+ FIqx2qgxDipoleKernel.cc \
+ FIgx2ggxDipoleKernel.cc \
+ FIgx2qqxDipoleKernel.cc \
+ IFqx2qgxDipoleKernel.cc \
+ IFqx2gqxDipoleKernel.cc \
+ IFgx2ggxDipoleKernel.cc \
+ IFgx2qqxDipoleKernel.cc \
+ IIqx2qgxDipoleKernel.cc \
+ IIqx2gqxDipoleKernel.cc \
+ IIgx2ggxDipoleKernel.cc \
+ IIgx2qqxDipoleKernel.cc \
+ FIMqx2qgxDipoleKernel.cc \
+ FIMgx2qqxDipoleKernel.cc \
+ IFMqx2qgxDipoleKernel.cc \
+ IFMqx2gqxDipoleKernel.cc \
+ IFMgx2ggxDipoleKernel.cc \
+ IFMgx2qqxDipoleKernel.cc
diff --git a/Shower/QTilde/Base/Branching.h b/Shower/QTilde/Base/Branching.h
--- a/Shower/QTilde/Base/Branching.h
+++ b/Shower/QTilde/Base/Branching.h
@@ -1,69 +1,69 @@
// -*- C++ -*-
#ifndef HERWIG_Branching_H
#define HERWIG_Branching_H
//
// This is the declaration of the Branching struct.
//
#include "Herwig/Shower/QTilde/ShowerConfig.h"
#include "Herwig/Shower/QTilde/Base/ShowerKinematics.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
* The branching struct is used to store information on the branching.
* The kinematics variable is a pointer to the ShowerKinematics for the branching
* The sudakov variable is a pointer to the SudakovFormFactor for the branching
* The ids variable is the list of particles in the branching
*/
struct Branching {
/**
* Pointer to the ShowerKinematics object for the branching
*/
ShoKinPtr kinematics;
/**
* PDG codes of the particles in the branching
*/
IdList ids;
/**
* The SudakovFormFactor for the branching
*/
tSudakovPtr sudakov;
/**
* The type of radiation line
*/
- ShowerPartnerType::Type type;
+ ShowerPartnerType type;
/**
* Whether or not it keep from forced hard emisson
*/
bool hard;
/**
* Which of the children is same as incoming
*/
unsigned int iout;
/**
* Constructor for the struct
* @param a pointer to the ShowerKinematics object for the branching
* @param c PDG codes of the particles in the branching
* @param d The SudakovFormFactor for the branching
*/
- Branching(ShoKinPtr a, IdList c,tSudakovPtr d,ShowerPartnerType::Type t)
+ Branching(ShoKinPtr a, IdList c,tSudakovPtr d,ShowerPartnerType t)
: kinematics(a), ids(c), sudakov(d), type(t), hard(false), iout(0) {}
/**
* Default constructor
*/
Branching() : hard(false), iout(0) {}
};
}
#endif /* HERWIG_Branching_H */
diff --git a/Shower/QTilde/Base/HardBranching.h b/Shower/QTilde/Base/HardBranching.h
--- a/Shower/QTilde/Base/HardBranching.h
+++ b/Shower/QTilde/Base/HardBranching.h
@@ -1,363 +1,363 @@
// -*- C++ -*-
#ifndef HERWIG_HardBranching_H
#define HERWIG_HardBranching_H
//
// This is the declaration of the HardBranching class.
//
#include "ThePEG/Config/ThePEG.h"
#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h"
#include "Herwig/Shower/QTilde/Base/ShowerTree.h"
#include "Herwig/Shower/QTilde/Base/SudakovFormFactor.h"
#include "HardBranching.fh"
#include "HardTree.fh"
namespace Herwig {
using namespace ThePEG;
/**
* The HardBranching class is designed to contain the information needed for
* an individual branching in the POWHEG approach
*/
class HardBranching : public Base {
/**
* The HardTree is friend
*/
friend class HardTree;
public:
/**
* Enum for the status
*/
enum Status {Outgoing=0,Incoming,Decay};
public:
/**
* The default constructor
* @param particle The particle which is branching
* @param sudakov The Sudakov form factor for the branching
* @param parent The parent for the branching
* @param status Whether the particle is incoming or outgoing
*/
HardBranching(ShowerParticlePtr particle, SudakovPtr sudakov,
tHardBranchingPtr parent,Status status);
/**
* Add a child of the branching
* @param child The child of the branching
*/
void addChild(HardBranchingPtr child) {_children.push_back(child);}
/**
* Clear the children
*/
void clearChildren() { _children.clear(); }
/**
* Set the momenta of the particles
*/
void setMomenta(LorentzRotation R, double alpha, Lorentz5Momentum pt,
bool setMomentum=true);
/**
* Set and get members for the private member variables
*/
//@{
/**
* Return the branching particle.
*/
tShowerParticlePtr branchingParticle() const {return _particle;}
/**
* Set the branching particle
*/
void branchingParticle(ShowerParticlePtr in) {_particle=in;}
/**
* Get the original momentum
*/
const Lorentz5Momentum & original() const {return _original;}
/**
* Set the original momentum
*/
void original(const Lorentz5Momentum & in) {_original=in;}
/**
* Get the p reference vector
*/
const Lorentz5Momentum & pVector() const {return _p;}
/**
* Set the p reference vector
*/
void pVector(const Lorentz5Momentum & in) {_p=in;}
/**
* Get the n reference vector
*/
const Lorentz5Momentum & nVector() const {return _n;}
/**
* Set the n reference vector
*/
void nVector(const Lorentz5Momentum & in) {_n=in;}
/**
* Get the transverse momentum vector
*/
const Lorentz5Momentum & qPerp() const {return _qt;}
/**
* Set the transverse momentum vector
*/
void qPerp(const Lorentz5Momentum & in) {_qt=in;}
/**
* Get the momentum the particle should have as the start of a shower
*/
const Lorentz5Momentum & showerMomentum() const {return _shower;}
/**
* Set the momentum the particle should have as the start of a shower
*/
void showerMomentum(const Lorentz5Momentum & in ) {_shower=in;}
/**
* Get the transverse momentum
*/
Energy pT() const {return _pt;}
/**
* Set the transverse momentum
*/
void pT(Energy in) { _pt=in;}
/**
* Get the fraction of beam momentum x
*/
double x_frac() const {return _x_frac;}
/**
* Set the fraction of beam momentum x
*/
void x_frac( double x ) { _x_frac = x; }
/**
* Get whether the branching is incoming, outgoing or decay
*/
Status status() const {return _status;}
/**
* Set whether the branching is incoming, outgoing or decay
*/
void status(Status in) {_status=in;}
/**
* The parent of the branching
*/
tHardBranchingPtr parent() const {return _parent;}
/**
* Set the parent of the branching
*/
void parent(tHardBranchingPtr in) {_parent=in;}
/**
* The Sudakov form-factor
*/
SudakovPtr sudakov() const {return _sudakov;}
/**
* The Sudakov form-factor
*/
void sudakov(SudakovPtr in) {_sudakov=in;}
/**
* Get the beam particle
*/
PPtr beam() const {return _beam;}
/**
* Set the beam particle
*/
void beam(PPtr in) {_beam=in;}
/**
* The children
*/
vector<HardBranchingPtr> & children() {return _children;}
//@}
/**
* Information on the Shower variables for the branching
*/
//@{
/**
* Get the evolution scale
*/
Energy scale() const {return _scale;}
/**
* The evolution scale
*/
void scale(Energy in) {_scale=in;}
/**
* The energy fraction
*/
double z() const {return _z;}
/**
* The energy fraction
*/
void z(double in) {_z=in;}
/**
* The azimthual angle
*/
double phi() const {return _phi;}
/**
* The azimthual angle
*/
void phi(double in) {_phi=in;}
//@}
/**
* Colour partners
*/
//@{
/**
* Get the colour partner
*/
tHardBranchingPtr colourPartner() const {return _partner;}
/**
* The colour partner of the branching
*/
void colourPartner(tHardBranchingPtr in) {_partner=in;}
//@}
/**
* Type of branching
*/
- ShowerPartnerType::Type type() const {
+ ShowerPartnerType type() const {
assert(type_!=ShowerPartnerType::Undefined);
return type_;
}
/**
* Type of branching
*/
- void type(ShowerPartnerType::Type in) {
+ void type(ShowerPartnerType in) {
type_ = in;
assert(type_!=ShowerPartnerType::Undefined);
}
private:
/**
* The branching particle
*/
ShowerParticlePtr _particle;
/**
* The rescaled momentum
*/
Lorentz5Momentum _original;
/**
* The \f$p\f$ reference vector
*/
Lorentz5Momentum _p;
/**
* The \f$n\f$ reference vector
*/
Lorentz5Momentum _n;
/**
* The transverse momentum vector
*/
Lorentz5Momentum _qt;
/**
* The momentum the particle should have as the start of a shower
*/
Lorentz5Momentum _shower;
/**
* The transverse momentum
*/
Energy _pt;
/**
* The beam momentum fraction carried by an incoming parton x
*/
double _x_frac;
/**
* Whether the branching is incoming, outgoing or a decay
*/
Status _status;
/**
* Information on the Shower variables for the branching
*/
//@{
/**
* The evolution scale
*/
Energy _scale;
/**
* The energy fraction
*/
double _z;
/**
* The azimthual angle
*/
double _phi;
//@}
/**
* The parent of the branching
*/
tHardBranchingPtr _parent;
/**
* The Sudakov form-factor
*/
SudakovPtr _sudakov;
/**
* The children
*/
vector<HardBranchingPtr> _children;
/**
* The beam particle
*/
PPtr _beam;
/**
* The colour partner
*/
tHardBranchingPtr _partner;
/**
* The type of branching
*/
- ShowerPartnerType::Type type_;
+ ShowerPartnerType type_;
};
}
#endif /* HERWIG_HardBranching_H */
diff --git a/Shower/QTilde/Base/HardTree.cc b/Shower/QTilde/Base/HardTree.cc
--- a/Shower/QTilde/Base/HardTree.cc
+++ b/Shower/QTilde/Base/HardTree.cc
@@ -1,347 +1,347 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the HardTree class.
//
#include "HardTree.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "Herwig/Shower/RealEmissionProcess.h"
using namespace Herwig;
HardTree::HardTree(vector<HardBranchingPtr> branchings,
vector<HardBranchingPtr> spacelike,
- ShowerInteraction::Type type)
+ ShowerInteraction type)
: interaction_(type),
branchings_(branchings.begin(),branchings.end()),
spacelike_ (spacelike .begin(),spacelike .end()),
partnersSet_(false)
{}
bool HardTree::connect(ShowerTreePtr shower) {
particles_.clear();
// extract the progenitors from the ShowerTree
vector<ShowerProgenitorPtr> progenitors = shower->extractProgenitors();
vector<bool> connectedProgenitors(progenitors.size(),false);
// connect the trees up
for( set<HardBranchingPtr>::iterator it = branchings().begin();
it != branchings().end(); ++it) {
Energy2 dmin( 1e30*GeV2 );
tShowerParticlePtr partner;
unsigned int progenitorsIndex(999);
for( unsigned int ix = 0; ix < progenitors.size(); ++ix ) {
if( connectedProgenitors[ix] ) continue;
if( (**it).branchingParticle()->id() != progenitors[ix]->progenitor()->id() ) continue;
if( (**it).branchingParticle()->isFinalState() !=
progenitors[ix]->progenitor()->isFinalState() ) continue;
Energy2 dtest =
sqr( progenitors[ix]->progenitor()->momentum().x() - (**it).showerMomentum().x() ) +
sqr( progenitors[ix]->progenitor()->momentum().y() - (**it).showerMomentum().y() ) +
sqr( progenitors[ix]->progenitor()->momentum().z() - (**it).showerMomentum().z() ) +
sqr( progenitors[ix]->progenitor()->momentum().t() - (**it).showerMomentum().t() );
if( dtest < dmin ) {
partner = progenitors[ix]->progenitor();
progenitorsIndex = ix;
dmin = dtest;
}
}
if( !partner ) return false;
connectedProgenitors[progenitorsIndex] = true;
connect( partner, *it );
if( (**it).status() == HardBranching::Incoming ) {
double z( (**it).z() );
tHardBranchingPtr parent = (**it).parent();
while (parent) {
z *= parent->z();
parent = parent->parent();
}
partner->x(z);
}
}
if( particles().size() == progenitors.size() ) return true;
else return false;
}
ostream & Herwig::operator<<(ostream & os, const HardTree & x) {
os << "Output of HardTree " << &x << "\n";
for(set<HardBranchingPtr>::const_iterator it=x.branchings_.begin();
it!=x.branchings_.end();++it) {
os << "Hard Particle: " << *(**it).branchingParticle() << " has Sudakov "
<< (**it).sudakov() << " pT = " << (**it).pT()/GeV
<< " scale = " << (**it).scale()/GeV << "\n";
os << "Its colour lines are " << (**it).branchingParticle()->colourLine() << "\t"
<< (**it).branchingParticle()->antiColourLine() << "\n";
os << "Its basis vectors are " << (**it).pVector()/GeV
<< " " << (**it).nVector()/GeV << "\n";
os << "Its shower momentum is " << (**it).showerMomentum()/GeV << "\n";
for(unsigned int iy=0;iy<(**it).children().size();++iy) {
os << "\t Children : " << *(**it).children()[iy]->branchingParticle()
<< "\n";
os << "It's colour lines are "
<< (**it).children()[iy]->branchingParticle()->colourLine() << "\t"
<< (**it).children()[iy]->branchingParticle()->antiColourLine() << "\n";
}
}
for(set<HardBranchingPtr>::const_iterator it=x.spacelike_.begin();
it!=x.spacelike_.end();++it) {
os << "SpaceLike: " << *(**it).branchingParticle() << " has Sudakov"
<< (**it).sudakov() << " pT = " << (**it).pT()/GeV
<< " scale = " << (**it).scale()/GeV << "\n";
os << "It's colour lines are "
<< (**it).branchingParticle()->colourLine() << "\t"
<< (**it).branchingParticle()->antiColourLine() << "\n";
for(unsigned int iy=0;iy<(**it).children().size();++iy) {
os << "\t Children: " << *(**it).children()[iy]->branchingParticle()
<< "\n";
os << "It's colour lines are "
<< (**it).children()[iy]->branchingParticle()->colourLine() << "\t"
<< (**it).children()[iy]->branchingParticle()->antiColourLine() << "\n";
}
}
return os;
}
HardTree::HardTree(RealEmissionProcessPtr real)
: interaction_(real->interaction()),
partnersSet_(false) {
// check the type
unsigned int pType = real->incoming().size() == 2 ? 1 : 2;
// create the Branchings for the incoming particles
vector<HardBranchingPtr> spaceBranchings;
ShowerParticleVector incoming;
for(unsigned int ix=0;ix<real->incoming().size();++ix) {
unsigned int type = ix!=real->emitter() ? pType : 0;
ShowerParticlePtr part(new_ptr(ShowerParticle(*real->incoming()[ix],type,false)));
incoming.push_back(part);
spaceBranchings.push_back(new_ptr(HardBranching(part,SudakovPtr(),HardBranchingPtr(),
HardBranching::Incoming)));
if(real->incoming().size()==2) {
assert(real->hadrons()[ix]);
spaceBranchings.back()->beam(real->hadrons()[ix]);
}
}
// create the outgoing particles
ShowerParticleVector outgoing;
vector<HardBranchingPtr> timeBranchings;
for(unsigned int ix=0;ix<real->outgoing().size();++ix) {
unsigned int type =
int(ix)!=int(real->emitted()-real->incoming().size()) &&
int(ix)!=int(real->emitter()-real->incoming().size()) ? pType : 0;
ShowerParticlePtr part(new_ptr(ShowerParticle(*real->outgoing()[ix],type,true)));
outgoing.push_back(part);
timeBranchings.push_back(new_ptr(HardBranching(part,SudakovPtr(),HardBranchingPtr(),
HardBranching::Outgoing)));
}
// create the branching for the radiating particle
HardBranchingPtr emitterBranch;
// inital-state emitter
if(real->emitter() < real->incoming().size()) {
unsigned int iemitter = real->emitter();
unsigned int iemitted = real->emitted() -real->incoming().size();
ShowerParticlePtr parent(new_ptr(ShowerParticle(real->bornIncoming()[iemitter]->dataPtr(),false)));
Lorentz5Momentum parentMomentum =
real->incoming()[iemitter]->momentum() -
real->outgoing()[iemitted]->momentum();
parentMomentum.setMass(real->bornIncoming()[iemitter]->dataPtr()->mass());
parent->set5Momentum(parentMomentum);
emitterBranch = new_ptr(HardBranching(parent,SudakovPtr(),HardBranchingPtr(),
HardBranching::Incoming));
// QED radiation
if(real->interaction()==ShowerInteraction::QED) {
spaceBranchings[iemitter]->type(ShowerPartnerType::QED);
if(parent->id()!=ParticleID::gamma) {
if(spaceBranchings[iemitter]->branchingParticle()-> colourLine())
spaceBranchings[iemitter]->branchingParticle()-> colourLine()->addColoured(parent);
if(spaceBranchings[iemitter]->branchingParticle()->antiColourLine())
spaceBranchings[iemitter]->branchingParticle()->antiColourLine()->addAntiColoured(parent);
}
}
else {
if(real->outgoing()[iemitted]->dataPtr()->iColour()==PDT::Colour8) {
// g -> g g
if(real->incoming()[iemitter]->dataPtr()->iColour()==PDT::Colour8) {
if(real->incoming()[iemitter]->colourLine()==real->outgoing()[iemitted]->colourLine()) {
real->incoming()[iemitter]->antiColourLine()->addAntiColoured(parent);
real->outgoing()[iemitted]->antiColourLine()-> addColoured(parent);
spaceBranchings[iemitter]->type(ShowerPartnerType::QCDColourLine);
}
else if(real->incoming()[iemitter]->antiColourLine()==real->outgoing()[iemitted]->antiColourLine()) {
real->incoming()[iemitter]->colourLine()-> addColoured(parent);
real->outgoing()[iemitted]->colourLine()->addAntiColoured(parent);
spaceBranchings[iemitter]->type(ShowerPartnerType::QCDAntiColourLine);
}
else
assert(false);
}
// q -> q g
else if(real->incoming()[iemitter]->dataPtr()->iColour()==PDT::Colour3) {
timeBranchings[iemitted]->branchingParticle()->antiColourLine()->addColoured(parent);
spaceBranchings[iemitter]->type(ShowerPartnerType::QCDColourLine);
}
// qbar -> qbar g
else if(real->incoming()[iemitter]->dataPtr()->iColour()==PDT::Colour3bar) {
timeBranchings[iemitted]->branchingParticle()->colourLine()->addAntiColoured(parent);
spaceBranchings[iemitter]->type(ShowerPartnerType::QCDAntiColourLine);
}
}
else if(real->outgoing()[iemitted]->dataPtr()->iColour()==PDT::Colour3) {
if(real->incoming()[iemitter]->dataPtr()->iColour()==PDT::Colour8) {
real->incoming()[iemitter]->antiColourLine()->addAntiColoured(parent);
spaceBranchings[iemitter]->type(ShowerPartnerType::QCDAntiColourLine);
}
else if(real->incoming()[iemitter]->dataPtr()->iColour()==PDT::Colour3) {
timeBranchings [iemitted]->branchingParticle()->colourLine()->addAntiColoured(parent);
spaceBranchings[iemitter]->branchingParticle()->colourLine()-> addColoured(parent);
spaceBranchings[iemitter]->type(ShowerPartnerType::QCDColourLine);
}
else
assert(false);
}
else if(real->outgoing()[iemitted]->dataPtr()->iColour()==PDT::Colour3bar) {
if(real->incoming()[iemitter]->dataPtr()->iColour()==PDT::Colour8) {
real->incoming()[iemitter]->colourLine()->addColoured(parent);
spaceBranchings[iemitter]->type(ShowerPartnerType::QCDColourLine);
}
else if(real->incoming()[iemitter]->dataPtr()->iColour()==PDT::Colour3bar) {
timeBranchings[iemitted ]->branchingParticle()->antiColourLine()-> addColoured(parent);
spaceBranchings[iemitter]->branchingParticle()->antiColourLine()->addAntiColoured(parent);
spaceBranchings[iemitter]->type(ShowerPartnerType::QCDAntiColourLine);
}
else
assert(false);
}
else
assert(false);
}
emitterBranch ->parent(spaceBranchings[iemitter]);
timeBranchings[iemitted]->parent(spaceBranchings[iemitter]);
spaceBranchings[iemitter]->addChild(emitterBranch);
spaceBranchings[iemitter]->addChild(timeBranchings[iemitted]);
if(real->spectator()< real->incoming().size()) {
unsigned int ispect = real->spectator();
// set partners
emitterBranch ->colourPartner(spaceBranchings[ispect]);
spaceBranchings[ispect]->colourPartner(emitterBranch);
emitterBranch ->branchingParticle()->partner(spaceBranchings[ispect]->branchingParticle());
spaceBranchings[ispect]->branchingParticle()->partner(emitterBranch ->branchingParticle());
}
else {
unsigned int ispect = real->spectator()-real->incoming().size();
// set partners
emitterBranch ->colourPartner(timeBranchings[ispect]);
timeBranchings[ispect]->colourPartner(emitterBranch);
emitterBranch ->branchingParticle()->partner(timeBranchings[ispect]->branchingParticle());
timeBranchings[ispect]->branchingParticle()->partner(emitterBranch ->branchingParticle());
}
}
// final-state emitter
else {
unsigned int iemitter = real->emitter() -real->incoming().size();
unsigned int iemitted = real->emitted() -real->incoming().size();
ShowerParticlePtr parent(new_ptr(ShowerParticle(real->bornOutgoing()[iemitter]->dataPtr(),true)));
Lorentz5Momentum parentMomentum =
real->outgoing()[iemitter]->momentum() +
real->outgoing()[iemitted]->momentum();
parentMomentum.setMass(real->bornOutgoing()[iemitter]->dataPtr()->mass());
parent->set5Momentum(parentMomentum);
emitterBranch = new_ptr(HardBranching(parent,SudakovPtr(),HardBranchingPtr(),
HardBranching::Outgoing));
// QED radiation
if(real->interaction()==ShowerInteraction::QED) {
emitterBranch->type(ShowerPartnerType::QED);
if(parent->id()!=ParticleID::gamma) {
if(timeBranchings[iemitter]->branchingParticle()-> colourLine())
timeBranchings[iemitter]->branchingParticle()-> colourLine()->addColoured(parent);
if(timeBranchings[iemitter]->branchingParticle()->antiColourLine())
timeBranchings[iemitter]->branchingParticle()->antiColourLine()->addAntiColoured(parent);
}
}
else {
if(real->outgoing()[iemitted]->dataPtr()->iColour()==PDT::Colour8) {
// g -> g g
if(real->outgoing()[iemitter]->dataPtr()->iColour()==PDT::Colour8) {
if(real->outgoing()[iemitter]->colourLine()==real->outgoing()[iemitted]->antiColourLine()) {
real->outgoing()[iemitter]->antiColourLine()->addAntiColoured(parent);
real->outgoing()[iemitted]-> colourLine()-> addColoured(parent);
emitterBranch->type(ShowerPartnerType::QCDColourLine);
}
else if(real->outgoing()[iemitter]->antiColourLine()==real->outgoing()[iemitted]->colourLine()) {
real->outgoing()[iemitter]-> colourLine()-> addColoured(parent);
real->outgoing()[iemitted]->antiColourLine()->addAntiColoured(parent);
emitterBranch->type(ShowerPartnerType::QCDAntiColourLine);
}
else
assert(false);
}
// q -> q g
else if(real->outgoing()[iemitter]->dataPtr()->iColour()==PDT::Colour3) {
timeBranchings[iemitted]->branchingParticle()->colourLine()->addColoured(parent);
emitterBranch->type(ShowerPartnerType::QCDColourLine);
}
// qbar -> qbar g
else if(real->outgoing()[iemitter]->dataPtr()->iColour()==PDT::Colour3bar) {
timeBranchings[iemitted]->branchingParticle()->antiColourLine()->addAntiColoured(parent);
emitterBranch->type(ShowerPartnerType::QCDAntiColourLine);
}
}
else if(real->outgoing()[iemitter]->dataPtr()->iColour()==PDT::Colour3 &&
real->outgoing()[iemitted]->dataPtr()->iColour()==PDT::Colour3bar) {
timeBranchings[iemitter]->branchingParticle()-> colourLine()-> addColoured(parent);
timeBranchings[iemitted]->branchingParticle()->antiColourLine()->addAntiColoured(parent);
emitterBranch->type(ShowerPartnerType::QCDColourLine);
}
else if(real->outgoing()[iemitter]->dataPtr()->iColour()==PDT::Colour3bar &&
real->outgoing()[iemitted]->dataPtr()->iColour()==PDT::Colour3) {
timeBranchings[iemitter]->branchingParticle()->antiColourLine()->addAntiColoured(parent);
timeBranchings[iemitted]->branchingParticle()-> colourLine()-> addColoured(parent);
emitterBranch->type(ShowerPartnerType::QCDAntiColourLine);
}
else
assert(false);
}
emitterBranch->addChild(timeBranchings[iemitter]);
emitterBranch->addChild(timeBranchings[iemitted]);
if(real->spectator()< real->incoming().size()) {
unsigned int ispect = real->spectator();
// set partners
emitterBranch ->colourPartner(spaceBranchings[ispect]);
spaceBranchings[ispect]->colourPartner(emitterBranch);
emitterBranch ->branchingParticle()->partner(spaceBranchings[ispect]->branchingParticle());
spaceBranchings[ispect]->branchingParticle()->partner(emitterBranch ->branchingParticle());
}
else {
unsigned int ispect = real->spectator()-real->incoming().size();
// set partners
emitterBranch ->colourPartner(timeBranchings[ispect]);
timeBranchings[ispect]->colourPartner(emitterBranch);
emitterBranch ->branchingParticle()->partner(timeBranchings[ispect]->branchingParticle());
timeBranchings[ispect]->branchingParticle()->partner(emitterBranch ->branchingParticle());
}
}
assert(emitterBranch);
spacelike_=set<HardBranchingPtr>(spaceBranchings.begin(),spaceBranchings.end());
// insert the incoming branchings
for(unsigned int ix=0;ix<spaceBranchings.size();++ix) {
HardBranchingPtr inBranch;
if(real->emitter()<real->incoming().size() && real->emitter()==ix)
inBranch = emitterBranch;
else
inBranch = spaceBranchings[ix];
if(real->incoming().size()==2)
inBranch->beam(real->hadrons()[ix]);
branchings_.insert(inBranch);
}
// and the outgoing ones
for(unsigned int ix=0;ix<timeBranchings.size();++ix) {
if(real->emitter()>=real->incoming().size() &&
real->emitter()==ix+real->incoming().size())
branchings_.insert(emitterBranch);
else if(real->emitted()==ix+real->incoming().size())
continue;
else
branchings_.insert(timeBranchings[ix]);
}
}
diff --git a/Shower/QTilde/Base/HardTree.h b/Shower/QTilde/Base/HardTree.h
--- a/Shower/QTilde/Base/HardTree.h
+++ b/Shower/QTilde/Base/HardTree.h
@@ -1,143 +1,143 @@
// -*- C++ -*-
#ifndef HERWIG_HardTree_H
#define HERWIG_HardTree_H
//
// This is the declaration of the HardTree class.
//
#include "ThePEG/Config/ThePEG.h"
#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.h"
#include "Herwig/Shower/QTilde/Base/ShowerTree.h"
#include "Herwig/Shower/QTilde/Base/SudakovFormFactor.h"
#include "Herwig/Shower/RealEmissionProcess.fh"
#include "HardBranching.h"
#include "HardTree.fh"
namespace Herwig {
using namespace ThePEG;
/**
* The HardTree class is designed to contain the information required
* to implement the POWHEG approach for Monte Carlo at next-to-leading order.
*/
class HardTree : public Base {
/**
* Output operator for testing
*/
friend ostream & operator << (ostream &, const HardTree & );
public:
/**
* The default constructor.
*/
- HardTree(vector<HardBranchingPtr>, vector<HardBranchingPtr>, ShowerInteraction::Type);
+ HardTree(vector<HardBranchingPtr>, vector<HardBranchingPtr>, ShowerInteraction);
/**
* Contructor from Real emission process
*/
HardTree(RealEmissionProcessPtr real);
/**
* Match particles in the ShowerTree to branchings in the HardTree
*/
bool connect(ShowerParticlePtr particle, HardBranchingPtr branching) {
if(branchings_.find(branching)==branchings_.end()) return false;
particles_[particle]=branching;
return true;
}
/**
* Match the prticles in the ShowerTree to the branchings in the HardTree
*/
bool connect(ShowerTreePtr);
/**
* Access the map between the ShowerParticle and the HardBranching
*/
map<ShowerParticlePtr,tHardBranchingPtr> & particles()
{return particles_;}
/**
* Access the set of branchings
*/
set<HardBranchingPtr> & branchings() {return branchings_;}
/**
* Access the incoming branchings
*/
set<HardBranchingPtr> & incoming() {return spacelike_;}
/**
* Type of interaction
*/
- ShowerInteraction::Type interaction() {return interaction_;}
+ ShowerInteraction interaction() {return interaction_;}
/**
* Get the Rotation to be applied to the tree
*/
LorentzRotation showerRot() { return showerRot_; }
/**
* Set the Rotation to be applied to the tree
*/
void showerRot( LorentzRotation r ) { showerRot_ = r; }
/**
* Whether or not the evolution partners are set
*/
bool partnersSet() const {return partnersSet_;}
/**
* Whether or not the evolution partners are set
*/
void partnersSet(bool in) {partnersSet_=in;}
private:
/**
* Type of interaction
*/
- ShowerInteraction::Type interaction_;
+ ShowerInteraction interaction_;
/**
* The ShowerTree
*/
ShowerTreePtr _tree;
/**
* Map from the particles in the ShowerTree to the HardBranchings
*/
map<ShowerParticlePtr,tHardBranchingPtr> particles_;
/**
* The HardBranchings in the hard process
*/
set<HardBranchingPtr> branchings_;
/**
* The HardBranchings which initiate the space-like showers
*/
set<HardBranchingPtr> spacelike_;
/**
* Rotation to shower frame
*/
LorentzRotation showerRot_;
/**
* Whether or not partners are set
*/
bool partnersSet_;
};
/**
* Output operator for testing
*/
ostream & operator << (ostream &, const HardTree & );
}
#endif /* HERWIG_HardTree_H */
diff --git a/Shower/QTilde/Base/KinematicsReconstructor.h b/Shower/QTilde/Base/KinematicsReconstructor.h
--- a/Shower/QTilde/Base/KinematicsReconstructor.h
+++ b/Shower/QTilde/Base/KinematicsReconstructor.h
@@ -1,132 +1,132 @@
// -*- C++ -*-
//
// KinematicsReconstructor.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_KinematicsReconstructor_H
#define HERWIG_KinematicsReconstructor_H
//
// This is the declaration of the KinematicsReconstructor class.
//
#include "ThePEG/Interface/Interfaced.h"
#include "ShowerParticle.h"
#include "ShowerProgenitor.h"
#include "ShowerTree.h"
#include "HardTree.h"
#include "KinematicsReconstructor.fh"
#include <cassert>
namespace Herwig {
using namespace ThePEG;
/**\ingroup Shower
* Exception class
* used to communicate failure of kinematics
* reconstruction.
*/
struct KinematicsReconstructionVeto {};
/** \ingroup Shower
*
* This class is responsible for the kinematical reconstruction
* after each showering step, and also for the necessary Lorentz boosts
* in order to preserve energy-momentum conservation in the overall collision,
* and also the invariant mass and the rapidity of the hard subprocess system.
* In the case of multi-step showering, there will be not unnecessary
* kinematical reconstructions.
*
* Notice:
* - although we often use the term "jet" in either methods or variables names,
* or in comments, which could appear applicable only for QCD showering,
* there is indeed no "dynamics" represented in this class: only kinematics
* is involved, as the name of this class remainds. Therefore it can be used
* for any kind of showers (QCD-,QED-,EWK-,... bremsstrahlung).
*
* @see \ref KinematicsReconstructorInterfaces "The interfaces"
* defined for KinematicsReconstructor.
*/
class KinematicsReconstructor: public Interfaced {
public:
/**
* Methods to reconstruct the kinematics of a scattering or decay process
*/
//@{
/**
* Given the ShowerTree for the shower from a hard process
* the method does the reconstruction of the jets,
* including the appropriate boosts (kinematics reshufflings)
* needed to conserve the total energy-momentum of the collision
* and preserving the invariant mass and the rapidity of the
* hard subprocess system.
*/
virtual bool reconstructHardJets(ShowerTreePtr hard,
const map<tShowerProgenitorPtr,
pair<Energy,double> > & pt,
- ShowerInteraction::Type type,
+ ShowerInteraction type,
bool switchRecon) const=0;
/**
* Given the ShowerTree for a decay shower
* the method does the reconstruction of the jets,
* including the appropriate boosts (kinematics reshufflings)
* needed to conserve the total energy-momentum of the collision
* and preserving the invariant mass and the rapidity of the
* hard subprocess system.
*/
virtual bool reconstructDecayJets(ShowerTreePtr decay,
- ShowerInteraction::Type type) const=0;
+ ShowerInteraction type) const=0;
//@}
/**
* Methods to invert the reconstruction of the shower for
* a scattering or decay process and calculate
* the variables used to generate the
* shower given the particles produced.
* This is needed for the CKKW and POWHEG approaches
*/
//@{
/**
* Given the particles, with a history which we wish to interpret
* as a shower reconstruct the variables used to generate the
* shower for a decay process
*/
- virtual bool deconstructDecayJets(HardTreePtr decay,ShowerInteraction::Type) const=0;
+ virtual bool deconstructDecayJets(HardTreePtr decay,ShowerInteraction) const=0;
/**
* Given the particles, with a history which we wish to interpret
* as a shower reconstruct the variables used to generate the shower
* for a hard process
*/
- virtual bool deconstructHardJets(HardTreePtr hard,ShowerInteraction::Type) const=0;
+ virtual bool deconstructHardJets(HardTreePtr hard,ShowerInteraction) const=0;
//@}
public:
/**
* 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();
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
KinematicsReconstructor & operator=(const KinematicsReconstructor &);
};
}
#endif /* HERWIG_KinematicsReconstructor_H */
diff --git a/Shower/QTilde/Base/PartnerFinder.cc b/Shower/QTilde/Base/PartnerFinder.cc
--- a/Shower/QTilde/Base/PartnerFinder.cc
+++ b/Shower/QTilde/Base/PartnerFinder.cc
@@ -1,535 +1,536 @@
// -*- C++ -*-
//
// PartnerFinder.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 PartnerFinder class.
//
#include "PartnerFinder.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ShowerParticle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Utilities/Debug.h"
#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
DescribeAbstractClass<PartnerFinder,Interfaced>
describePartnerFinder ("Herwig::PartnerFinder","HwShower.so");
// some useful functions to avoid using #define
namespace {
// return bool if final-state particle
inline bool FS(const tShowerParticlePtr a) {
return a->isFinalState();
}
// return colour line pointer
inline Ptr<ThePEG::ColourLine>::transient_pointer
CL(const tShowerParticlePtr a, unsigned int index=0) {
return a->colourInfo()->colourLines().empty() ? ThePEG::tColinePtr() :
const_ptr_cast<ThePEG::tColinePtr>(a->colourInfo()->colourLines()[index]);
}
// return colour line size
inline unsigned int
CLSIZE(const tShowerParticlePtr a) {
return a->colourInfo()->colourLines().size();
}
inline Ptr<ThePEG::ColourLine>::transient_pointer
ACL(const tShowerParticlePtr a, unsigned int index=0) {
return a->colourInfo()->antiColourLines().empty() ? ThePEG::tColinePtr() :
const_ptr_cast<ThePEG::tColinePtr>(a->colourInfo()->antiColourLines()[index]);
}
inline unsigned int
ACLSIZE(const tShowerParticlePtr a) {
return a->colourInfo()->antiColourLines().size();
}
}
void PartnerFinder::persistentOutput(PersistentOStream & os) const {
os << partnerMethod_ << QEDPartner_ << scaleChoice_;
}
void PartnerFinder::persistentInput(PersistentIStream & is, int) {
is >> partnerMethod_ >> QEDPartner_ >> scaleChoice_;
}
void PartnerFinder::Init() {
static ClassDocumentation<PartnerFinder> documentation
("This class is responsible for finding the partners for each interaction types ",
"and within the evolution scale range specified by the ShowerVariables ",
"then to determine the initial evolution scales for each pair of partners.");
static Switch<PartnerFinder,int> interfacePartnerMethod
("PartnerMethod",
"Choice of partner finding method for gluon evolution.",
&PartnerFinder::partnerMethod_, 0, false, false);
static SwitchOption interfacePartnerMethodRandom
(interfacePartnerMethod,
"Random",
"Choose partners of a gluon randomly.",
0);
static SwitchOption interfacePartnerMethodMaximum
(interfacePartnerMethod,
"Maximum",
"Choose partner of gluon with largest angle.",
1);
static Switch<PartnerFinder,int> interfaceQEDPartner
("QEDPartner",
"Control of which particles to use as the partner for QED radiation",
&PartnerFinder::QEDPartner_, 0, false, false);
static SwitchOption interfaceQEDPartnerAll
(interfaceQEDPartner,
"All",
"Consider all possible choices which give a positive contribution"
" in the soft limit.",
0);
static SwitchOption interfaceQEDPartnerIIandFF
(interfaceQEDPartner,
"IIandFF",
"Only allow initial-initial or final-final combinations",
1);
static SwitchOption interfaceQEDPartnerIF
(interfaceQEDPartner,
"IF",
"Only allow initial-final combinations",
2);
static Switch<PartnerFinder,int> interfaceScaleChoice
("ScaleChoice",
"The choice of the evolution scales",
&PartnerFinder::scaleChoice_, 0, false, false);
static SwitchOption interfaceScaleChoicePartner
(interfaceScaleChoice,
"Partner",
"Scale of all interactions is that of the evolution partner",
0);
static SwitchOption interfaceScaleChoiceDifferent
(interfaceScaleChoice,
"Different",
"Allow each interaction to have different scales",
1);
}
void PartnerFinder::setInitialEvolutionScales(const ShowerParticleVector &particles,
const bool isDecayCase,
- ShowerInteraction::Type type,
+ ShowerInteraction type,
const bool setPartners) {
// clear the existing partners
for(ShowerParticleVector::const_iterator cit = particles.begin();
cit != particles.end(); ++cit) (*cit)->clearPartners();
// set them
if(type==ShowerInteraction::QCD) {
setInitialQCDEvolutionScales(particles,isDecayCase,setPartners);
}
else if(type==ShowerInteraction::QED) {
setInitialQEDEvolutionScales(particles,isDecayCase,setPartners);
}
else {
setInitialQCDEvolutionScales(particles,isDecayCase,setPartners);
setInitialQEDEvolutionScales(particles,isDecayCase,false);
}
// print out for debugging
if(Debug::level>=10) {
for(ShowerParticleVector::const_iterator cit = particles.begin();
cit != particles.end(); ++cit) {
generator()->log() << "Particle: " << **cit << "\n";
if(!(**cit).partner()) continue;
generator()->log() << "Primary partner: " << *(**cit).partner() << "\n";
for(vector<ShowerParticle::EvolutionPartner>::const_iterator it= (**cit).partners().begin();
it!=(**cit).partners().end();++it) {
- generator()->log() << it->type << " " << it->weight << " "
+ generator()->log() << static_cast<long>(it->type) << " "
+ << it->weight << " "
<< it->scale/GeV << " "
<< *(it->partner)
<< "\n";
}
}
generator()->log() << flush;
}
}
void PartnerFinder::setInitialQCDEvolutionScales(const ShowerParticleVector &particles,
const bool isDecayCase,
const bool setPartners) {
// set the partners and the scales
if(setPartners) {
// Loop over particles and consider only coloured particles which don't
// have already their colour partner fixed and that don't have children
// (the latter requirement is relaxed in the case isDecayCase is true).
// Build a map which has as key one of these particles (i.e. a pointer
// to a ShowerParticle object) and as a corresponding value the vector
// of all its possible *normal* candidate colour partners, defined as follows:
// --- have colour, and no children (this is not required in the case
// isDecayCase is true);
// --- if both are initial (incoming) state particles, then the (non-null) colourLine()
// of one of them must match the (non-null) antiColourLine() of the other.
// --- if one is an initial (incoming) state particle and the other is
// a final (outgoing) state particle, then both must have the
// same (non-null) colourLine() or the same (non-null) antiColourLine();
// Notice that this definition exclude the special case of baryon-violating
// processes (as in R-parity Susy), which will show up as particles
// without candidate colour partners, and that we will be treated a part later
// (this means that no modifications of the following loop is needed!)
ShowerParticleVector::const_iterator cit, cjt;
for(cit = particles.begin(); cit != particles.end(); ++cit) {
// Skip colourless particles
if(!(*cit)->data().coloured()) continue;
// find the partners
- vector< pair<ShowerPartnerType::Type, tShowerParticlePtr> > partners =
+ vector< pair<ShowerPartnerType, tShowerParticlePtr> > partners =
findQCDPartners(*cit,particles);
// must have a partner
if(partners.empty()) {
throw Exception() << "`Failed to make colour connections in "
<< "PartnerFinder::setQCDInitialEvolutionScales"
<< (**cit)
<< Exception::eventerror;
}
// Calculate the evolution scales for all possible pairs of of particles
vector<pair<Energy,Energy> > scales;
for(unsigned int ix=0;ix< partners.size();++ix) {
scales.push_back(calculateInitialEvolutionScales(ShowerPPair(*cit,partners[ix].second),
isDecayCase));
}
// In the case of more than one candidate colour partners,
// there are now two approaches to choosing the partner. The
// first method is based on two assumptions:
// 1) the choice of which is the colour partner is done
// *randomly* between the available candidates.
// 2) the choice of which is the colour partner is done
// *independently* from each particle: in other words,
// if for a particle "i" its selected colour partner is
// the particle "j", then the colour partner of "j"
// does not have to be necessarily "i".
// The second method always chooses the furthest partner
// for hard gluons and gluinos.
// store the choice
int position(-1);
// random choice
if( partnerMethod_ == 0 ) {
// random choice of partner
position = UseRandom::irnd(partners.size());
}
// take the one with largest angle
else if (partnerMethod_ == 1 ) {
if ((*cit)->perturbative() == 1 &&
(*cit)->dataPtr()->iColour()==PDT::Colour8 ) {
assert(partners.size()==2);
// Determine largest angle
double maxAngle(0.);
for(unsigned int ix=0;ix<partners.size();++ix) {
double angle = (*cit)->momentum().vect().
angle(partners[ix].second->momentum().vect());
if(angle>maxAngle) {
maxAngle = angle;
position = ix;
}
}
}
else
position = UseRandom::irnd(partners.size());
}
else
assert(false);
// set the evolution partner
(*cit)->partner(partners[position].second);
for(unsigned int ix=0;ix<partners.size();++ix) {
(**cit).addPartner(ShowerParticle::EvolutionPartner(partners[ix].second,
1.,partners[ix].first,
scales[ix].first));
}
// set scales for all interactions to that of the partner, default
Energy scale = scales[position].first;
for(unsigned int ix=0;ix<partners.size();++ix) {
if(partners[ix].first==ShowerPartnerType::QCDColourLine) {
(**cit).scales().QCD_c =
(**cit).scales().QCD_c_noAO =
(scaleChoice_==0 ? scale : scales[ix].first);
}
else if(partners[ix].first==ShowerPartnerType::QCDAntiColourLine) {
(**cit).scales().QCD_ac =
(**cit).scales().QCD_ac_noAO =
(scaleChoice_==0 ? scale : scales[ix].first);
}
else
assert(false);
}
}
}
// primary partner set, set the others and do the scale
else {
for(ShowerParticleVector::const_iterator cit = particles.begin();
cit != particles.end(); ++cit) {
// Skip colourless particles
if(!(*cit)->data().coloured()) continue;
// find the partners
- vector< pair<ShowerPartnerType::Type, tShowerParticlePtr> > partners =
+ vector< pair<ShowerPartnerType, tShowerParticlePtr> > partners =
findQCDPartners(*cit,particles);
// must have a partner
if(partners.empty()) {
throw Exception() << "`Failed to make colour connections in "
<< "PartnerFinder::setQCDInitialEvolutionScales"
<< (**cit)
<< Exception::eventerror;
}
// Calculate the evolution scales for all possible pairs of of particles
vector<pair<Energy,Energy> > scales;
int position(-1);
for(unsigned int ix=0;ix< partners.size();++ix) {
if(partners[ix].second) position = ix;
scales.push_back(calculateInitialEvolutionScales(ShowerPPair(*cit,partners[ix].second),
isDecayCase));
}
assert(position>=0);
for(unsigned int ix=0;ix<partners.size();++ix) {
(**cit).addPartner(ShowerParticle::EvolutionPartner(partners[ix].second,
1.,partners[ix].first,
scales[ix].first));
}
// set scales for all interactions to that of the partner, default
Energy scale = scales[position].first;
for(unsigned int ix=0;ix<partners.size();++ix) {
if(partners[ix].first==ShowerPartnerType::QCDColourLine) {
(**cit).scales().QCD_c =
(**cit).scales().QCD_c_noAO =
(scaleChoice_==0 ? scale : scales[ix].first);
}
else if(partners[ix].first==ShowerPartnerType::QCDAntiColourLine) {
(**cit).scales().QCD_ac =
(**cit).scales().QCD_ac_noAO =
(scaleChoice_==0 ? scale : scales[ix].first);
}
else {
assert(false);
}
}
}
}
}
void PartnerFinder::setInitialQEDEvolutionScales(const ShowerParticleVector &particles,
const bool isDecayCase,
const bool setPartners) {
// loop over all the particles
for(ShowerParticleVector::const_iterator cit = particles.begin();
cit != particles.end(); ++cit) {
// not charged or photon continue
if(!(**cit).dataPtr()->charged()) continue;
// find the potential partners
vector<pair<double,tShowerParticlePtr> > partners = findQEDPartners(*cit,particles,isDecayCase);
if(partners.empty()) {
throw Exception() << "Failed to find partner in "
<< "PartnerFinder::setQEDInitialEvolutionScales"
<< (**cit) << Exception::eventerror;
}
// calculate the probabilities
double prob(0.);
for(unsigned int ix=0;ix<partners.size();++ix) prob += partners[ix].first;
// normalise
for(unsigned int ix=0;ix<partners.size();++ix) partners[ix].first /= prob;
// set the partner if required
int position(-1);
// use QCD partner if set
if(!setPartners&&(*cit)->partner()) {
for(unsigned int ix=0;ix<partners.size();++ix) {
if((*cit)->partner()==partners[ix].second) {
position = ix;
break;
}
}
}
// set the partner
if(setPartners||!(*cit)->partner()||position<0) {
prob = UseRandom::rnd();
for(unsigned int ix=0;ix<partners.size();++ix) {
if(partners[ix].first>prob) {
position = ix;
break;
}
prob -= partners[ix].first;
}
if(position>=0&&(setPartners||!(*cit)->partner())) {
(*cit)->partner(partners[position].second);
}
}
// must have a partner
if(position<0) throw Exception() << "Failed to find partner in "
<< "PartnerFinder::setQEDInitialEvolutionScales"
<< (**cit) << Exception::eventerror;
// Calculate the evolution scales for all possible pairs of of particles
vector<pair<Energy,Energy> > scales;
for(unsigned int ix=0;ix< partners.size();++ix) {
scales.push_back(calculateInitialEvolutionScales(ShowerPPair(*cit,partners[ix].second),
isDecayCase));
}
// store all the possible partners
for(unsigned int ix=0;ix<partners.size();++ix) {
(**cit).addPartner(ShowerParticle::EvolutionPartner(partners[ix].second,
partners[ix].first,
ShowerPartnerType::QED,
scales[ix].first));
}
// set scales
(**cit).scales().QED = scales[position].first;
(**cit).scales().QED_noAO = scales[position].first;
}
}
pair<Energy,Energy> PartnerFinder::
calculateInitialEvolutionScales(const ShowerPPair &particlePair,
const bool isDecayCase) {
bool FS1=FS(particlePair.first),FS2= FS(particlePair.second);
if(FS1 && FS2)
return calculateFinalFinalScales(particlePair);
else if(FS1 && !FS2) {
ShowerPPair a(particlePair.second, particlePair.first);
pair<Energy,Energy> rval = calculateInitialFinalScales(a,isDecayCase);
return pair<Energy,Energy>(rval.second,rval.first);
}
else if(!FS1 &&FS2)
return calculateInitialFinalScales(particlePair,isDecayCase);
else
return calculateInitialInitialScales(particlePair);
}
-vector< pair<ShowerPartnerType::Type, tShowerParticlePtr> >
+vector< pair<ShowerPartnerType, tShowerParticlePtr> >
PartnerFinder::findQCDPartners(tShowerParticlePtr particle,
const ShowerParticleVector &particles) {
- vector< pair<ShowerPartnerType::Type, tShowerParticlePtr> > partners;
+ vector< pair<ShowerPartnerType, tShowerParticlePtr> > partners;
ShowerParticleVector::const_iterator cjt;
for(cjt = particles.begin(); cjt != particles.end(); ++cjt) {
if(!(*cjt)->data().coloured() || particle==*cjt) continue;
// one initial-state and one final-state particle
if(FS(particle) != FS(*cjt)) {
// loop over all the colours of both particles
for(unsigned int ix=0; ix<CLSIZE(particle); ++ix) {
for(unsigned int jx=0; jx<CLSIZE(*cjt); ++jx) {
if((CL(particle,ix) && CL(particle,ix)==CL(*cjt,jx))) {
partners.push_back(make_pair(ShowerPartnerType:: QCDColourLine,*cjt));
}
}
}
//loop over all the anti-colours of both particles
for(unsigned int ix=0; ix<ACLSIZE(particle); ++ix) {
for(unsigned int jx=0; jx<ACLSIZE(*cjt); ++jx) {
if((ACL(particle,ix) && ACL(particle,ix)==ACL(*cjt,jx))) {
partners.push_back(make_pair(ShowerPartnerType::QCDAntiColourLine,*cjt));
}
}
}
}
// two initial-state or two final-state particles
else {
//loop over the colours of the first particle and the anti-colours of the other
for(unsigned int ix=0; ix<CLSIZE(particle); ++ix){
for(unsigned int jx=0; jx<ACLSIZE(*cjt); ++jx){
if(CL(particle,ix) && CL(particle,ix)==ACL(*cjt,jx)) {
partners.push_back(make_pair(ShowerPartnerType:: QCDColourLine,*cjt));
}
}
}
//loop over the anti-colours of the first particle and the colours of the other
for(unsigned int ix=0; ix<ACLSIZE(particle); ++ix){
for(unsigned int jx=0; jx<CLSIZE(*cjt); jx++){
if(ACL(particle,ix) && ACL(particle,ix)==CL(*cjt,jx)) {
partners.push_back(make_pair(ShowerPartnerType::QCDAntiColourLine,*cjt));
}
}
}
}
}
// if we haven't found any partners look for RPV
if (partners.empty()) {
// special for RPV
tColinePtr col = CL(particle);
if(FS(particle)&&col&&col->sourceNeighbours().first) {
tColinePair cpair = col->sourceNeighbours();
for(cjt=particles.begin();cjt!=particles.end();++cjt) {
if(( FS(*cjt) && ( CL(*cjt) == cpair.first || CL(*cjt) == cpair.second))||
(!FS(*cjt) && (ACL(*cjt) == cpair.first || ACL(*cjt) == cpair.second ))) {
partners.push_back(make_pair(ShowerPartnerType:: QCDColourLine,*cjt));
}
}
}
else if(col&&col->sinkNeighbours().first) {
tColinePair cpair = col->sinkNeighbours();
for(cjt=particles.begin();cjt!=particles.end();++cjt) {
if(( FS(*cjt) && (ACL(*cjt) == cpair.first || ACL(*cjt) == cpair.second))||
(!FS(*cjt) && ( CL(*cjt) == cpair.first || CL(*cjt) == cpair.second))) {
partners.push_back(make_pair(ShowerPartnerType:: QCDColourLine,*cjt));
}
}
}
col = ACL(particle);
if(FS(particle)&&col&&col->sinkNeighbours().first) {
tColinePair cpair = col->sinkNeighbours();
for(cjt=particles.begin();cjt!=particles.end();++cjt) {
if(( FS(*cjt) && (ACL(*cjt) == cpair.first || ACL(*cjt) == cpair.second))||
(!FS(*cjt) && ( CL(*cjt) == cpair.first || CL(*cjt) == cpair.second ))) {
partners.push_back(make_pair(ShowerPartnerType::QCDAntiColourLine,*cjt));
}
}
}
else if(col&&col->sourceNeighbours().first) {
tColinePair cpair = col->sourceNeighbours();
for(cjt=particles.begin();cjt!=particles.end();++cjt) {
if(( FS(*cjt) && ( CL(*cjt) == cpair.first || CL(*cjt) == cpair.second))||
(!FS(*cjt) && (ACL(*cjt) == cpair.first ||ACL(*cjt) == cpair.second))) {
partners.push_back(make_pair(ShowerPartnerType::QCDAntiColourLine,*cjt));
}
}
}
}
// return the partners
return partners;
}
vector< pair<double, tShowerParticlePtr> >
PartnerFinder::findQEDPartners(tShowerParticlePtr particle,
const ShowerParticleVector &particles,
const bool isDecayCase) {
vector< pair<double, tShowerParticlePtr> > partners;
ShowerParticleVector::const_iterator cjt;
double pcharge = particle->id()==ParticleID::gamma ? 1 : double(particle->data().iCharge());
vector< pair<double, tShowerParticlePtr> > photons;
for(cjt = particles.begin(); cjt != particles.end(); ++cjt) {
if(particle == *cjt) continue;
if((**cjt).id()==ParticleID::gamma) photons.push_back(make_pair(1.,*cjt));
if(!(*cjt)->data().charged() ) continue;
double charge = pcharge*double((*cjt)->data().iCharge());
if( FS(particle) != FS(*cjt) ) charge *=-1.;
if( QEDPartner_ != 0 && !isDecayCase ) {
// only include II and FF as requested
if( QEDPartner_ == 1 && FS(particle) != FS(*cjt) )
continue;
// only include IF is requested
else if(QEDPartner_ == 2 && FS(particle) == FS(*cjt) )
continue;
}
if(particle->id()==ParticleID::gamma) charge = -abs(charge);
// only keep positive dipoles
if(charge<0.) partners.push_back(make_pair(-charge,*cjt));
}
if(particle->id()==ParticleID::gamma&& partners.empty()) {
return photons;
}
return partners;
}
diff --git a/Shower/QTilde/Base/PartnerFinder.h b/Shower/QTilde/Base/PartnerFinder.h
--- a/Shower/QTilde/Base/PartnerFinder.h
+++ b/Shower/QTilde/Base/PartnerFinder.h
@@ -1,208 +1,208 @@
// -*- C++ -*-
//
// PartnerFinder.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_PartnerFinder_H
#define HERWIG_PartnerFinder_H
//
// This is the declaration of the PartnerFinder class.
//
#include "Herwig/Shower/QTilde/ShowerConfig.h"
#include "ThePEG/Interface/Interfaced.h"
#include "PartnerFinder.fh"
namespace Herwig {
using namespace ThePEG;
/**
* typedef of a pair of particle for calculating the evolution scales
*/
typedef pair<tShowerParticlePtr,tShowerParticlePtr> ShowerPPair;
/** \ingroup Shower
*
* This class is responsible of two related tasks:
* - it finds the partners
* - for each pair of partners (and interaction therefore)
* it sets the initial evolution scales of both of them.
*
* In general the finding of the partners is performed by this class but
* the calculation of the initial evolution scales should be implemented
* for different shower evolution models in classes inheriting from this one.
* Notice that a given particle has, in general, a different partner
* for each different interaction; however, given a partner, its
* initial evolution scale, Q, is purely a kinematical relationship
* between the pair, without dependence on the dynamics (i.e. type of interaction).
*
* @see \ref PartnerFinderInterfaces "The interfaces"
* defined for PartnerFinder.
*/
class PartnerFinder: public Interfaced {
public:
/**
* The default constructor.
*/
PartnerFinder() : partnerMethod_(0), QEDPartner_(0), scaleChoice_(0) {}
/**
* Given in input a collection of particles (ShowerParticle objects),
* each of these methods set the initial evolution scales of those particles,
* between the ones given in input, that do not have yet their
* evolution scale set.
* The input collection of particles can be either the full collection of
* showering particles (kept in the main class ShowerHandler,
* in the case isDecayCase is false, or simply, in the case isDecayCase
* is true, the decaying particle and its decay products.
* The methods returns true, unless something wrong (inconsistencies,
* or undefined values) happens.
*
* These methods are virtual but in most cases inheriting classes should not
* need to overide them as they simply find the relevant partner and call
* one of the calculateScale members to calculate the scale.
*/
//@{
/**
* Set the initial scales
* @param particles The particles to be considered
* @param isDecayCase Whether or not this is a decay
* @param setPartners Whether to set the colour partners or just the scales
*/
virtual void setInitialEvolutionScales(const ShowerParticleVector &particles,
const bool isDecayCase,
- ShowerInteraction::Type,
+ ShowerInteraction,
const bool setPartners=true);
//@}
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:
/**
* Members to set the scales for different interactions
*/
//@{
/**
* Set initial scales for a QCD interaction
*/
virtual void setInitialQCDEvolutionScales(const ShowerParticleVector &particles,
const bool isDecayCase,
const bool setPartners=true);
/**
* Set initial scales for a QED interaction
*/
virtual void setInitialQEDEvolutionScales(const ShowerParticleVector &particles,
const bool isDecayCase,
const bool setPartners=true);
//@}
/**
* Find the QCD partners
* @param particle The particle to find the partners for
* @param particles The full set of particles to search
*/
- vector< pair<ShowerPartnerType::Type, tShowerParticlePtr> >
+ vector< pair<ShowerPartnerType, tShowerParticlePtr> >
findQCDPartners(tShowerParticlePtr particle, const ShowerParticleVector &particles);
/**
* Find the QED partners
* @param particle The particle to find the partners for
* @param particles The full set of particles to search
*/
vector< pair<double, tShowerParticlePtr> >
findQEDPartners(tShowerParticlePtr particle, const ShowerParticleVector &particles,
const bool isDecayCase);
/**
* Given a pair of particles, supposedly partners w.r.t. an interaction,
* this method returns their initial evolution scales as a pair.
* If something wrong happens, it returns the null (ZERO,ZERO) pair.
* This method is used by the above setXXXInitialEvolutionScales
* methods.
* These methods must be overiden in inheriting classes
*/
//@{
/**
* General method to calculate the initial evolution scales
*/
virtual pair<Energy,Energy> calculateInitialEvolutionScales(const ShowerPPair &,
const bool isDecayCase);
/**
* Calculate the initial evolution scales for two final-state particles
*/
virtual pair<Energy,Energy> calculateFinalFinalScales(const ShowerPPair &)=0;
/**
* Calculate the initial evolution scales for two initial-state particles
*/
virtual pair<Energy,Energy> calculateInitialInitialScales(const ShowerPPair &)=0;
/**
* Calculate the initial evolution scales for one initial
* and one final-state particles
*/
virtual pair<Energy,Energy> calculateInitialFinalScales(const ShowerPPair &,
const bool isDecayCase)=0;
//@}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
PartnerFinder & operator=(const PartnerFinder &);
private:
/**
* Method for choosing colour partner
*/
int partnerMethod_;
/**
* Choice for the QED radiation partner
*/
int QEDPartner_;
/**
* Choice of the scale
*/
int scaleChoice_;
};
}
#endif /* HERWIG_PartnerFinder_H */
diff --git a/Shower/QTilde/Base/ShowerKinematics.cc b/Shower/QTilde/Base/ShowerKinematics.cc
--- a/Shower/QTilde/Base/ShowerKinematics.cc
+++ b/Shower/QTilde/Base/ShowerKinematics.cc
@@ -1,65 +1,65 @@
// -*- C++ -*-
//
// ShowerKinematics.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 ShowerKinematics class.
//
#include "ShowerKinematics.h"
using namespace Herwig;
void ShowerKinematics::updateChildren(const tShowerParticlePtr,
const ShowerParticleVector &,
- ShowerPartnerType::Type,bool) const {
+ ShowerPartnerType,bool) const {
throw Exception() << "Base class ShowerKinematics::updateChildren called,"
<< " should have been overriden in an inheriting class"
<< Exception::runerror;
}
void ShowerKinematics::resetChildren(const tShowerParticlePtr,
const ShowerParticleVector &) const {
throw Exception() << "Base class ShowerKinematics::resetChildren called,"
<< " should have been overriden in an inheriting class"
<< Exception::runerror;
}
void ShowerKinematics::updateParent(const tShowerParticlePtr,
const ShowerParticleVector &,
- ShowerPartnerType::Type) const {
+ ShowerPartnerType) const {
throw Exception() << "Base class ShowerKinematics::updateParent called,"
<< " should have been overriden in an inheriting class"
<< Exception::runerror;
}
void ShowerKinematics::reconstructChildren(const tShowerParticlePtr,
const ShowerParticleVector &) const {
throw Exception() << "Base class ShowerKinematics::reconstructChildren called,"
<< " should have been overriden in an inheriting class"
<< Exception::runerror;
}
void ShowerKinematics::reconstructParent(const tShowerParticlePtr,
const ParticleVector &) const {
throw Exception() << "Base class ShowerKinematics::reconstructParent called,"
<< " should have been overriden in an inheriting class"
<< Exception::runerror;
}
void ShowerKinematics::reconstructLast(const tShowerParticlePtr,
Energy) const {
throw Exception() << "Base class ShowerKinematics::reconstructLast called,"
<< " should have been overriden in an inheriting class"
<< Exception::runerror;
}
void ShowerKinematics::updateLast(const tShowerParticlePtr,
Energy,Energy) const {
throw Exception() << "Base class ShowerKinematics::updatetLast called,"
<< " should have been overriden in an inheriting class"
<< Exception::runerror;
}
diff --git a/Shower/QTilde/Base/ShowerKinematics.h b/Shower/QTilde/Base/ShowerKinematics.h
--- a/Shower/QTilde/Base/ShowerKinematics.h
+++ b/Shower/QTilde/Base/ShowerKinematics.h
@@ -1,303 +1,303 @@
// -*- C++ -*-
//
// ShowerKinematics.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_ShowerKinematics_H
#define HERWIG_ShowerKinematics_H
//
// This is the declaration of the ShowerKinematics class.
//
#include "Herwig/Shower/QTilde/ShowerConfig.h"
#include "ThePEG/Config/ThePEG.h"
#include "Herwig/Shower/QTilde/Base/SudakovFormFactor.h"
#include "ShowerKinematics.fh"
namespace Herwig {
using namespace ThePEG;
/**\ingroup Shower
*
* This is the abstract base class from which all other shower
* kinematics classes derive. The main purpose of the
* shower kinematics classes is to allow the reconstruction
* of jet masses, at the end of the showering (indeed, for
* multi-scale showering, at the end of each scale-range evolution).
* This is necessary for the kinematics reshuffling
* in order to compensate the recoil of the emissions.
* The KinematicsReconstructor class is in
* charge of this job, and which is the main "user" of
* ShowerKinematics and its derived classes.
* How this is done depends on the choice of kinematics variables
* and whether the jet is time-like (forward evolved) or
* space-like (backward evolved), whereas the class ShowerKinematics
* describes only the common features which are independent by them.
*
* In general there are a number of methods specific to a shower approach
*
* @see KinematicsReconstructor
*/
class ShowerKinematics: public Base {
public:
/**
* The default constructor.
*/
ShowerKinematics() : Base(), _isTheJetStartingPoint( false ),
_scale(), _z( 0.0 ), _phi( 0.0 ), _pt(),
_sudakov() {}
/**
* The updateChildren and updateParent
* members to update the values of the \f$\alpha\f$ and
* \f$p_\perp\f$ variables during the shower evolution.
*/
//@{
/**
* Along with the showering evolution --- going forward for
* time-like (forward) evolution, and going backward for space-like
* (backward) evolution --- the kinematical variables of the
* branching products are calculated and updated from the knowledge
* of the parent kinematics.
* @param parent The parent
* @param children The children
* @param partnerType The type of evolution partner
*/
virtual void updateChildren(const tShowerParticlePtr parent,
const ShowerParticleVector & children,
- ShowerPartnerType::Type partnerType,
+ ShowerPartnerType partnerType,
bool massVeto ) const;
virtual void resetChildren( const tShowerParticlePtr parent,
const ShowerParticleVector & children) const;
/**
* Update the parent Kinematics from the knowledge of the kinematics
* of the children. This method will be used by the KinematicsReconstructor.
* @param parent The parent
* @param children The children
* @param partnerType The type of evolution partner
*/
virtual void updateParent(const tShowerParticlePtr parent,
const ShowerParticleVector & children,
- ShowerPartnerType::Type partnerType) const;
+ ShowerPartnerType partnerType) const;
/**
* Update the kinematical data of a particle when a reconstruction
* fixpoint was found. This will highly depend on the kind of
* kinematics chosen and will be defined in the inherited concrete
* classes. This method will be used by the KinematicsReconstructor.
* @param last The particle.
* @param px The \f$x\f$ component of the \f$p_T\f$.
* @param py The \f$y\f$ component of the \f$p_T\f$.
*/
virtual void updateLast(const tShowerParticlePtr last,
Energy px, Energy py) const;
//@}
/**
* The reconstructLast, reconstructChildren and reconstructParent members
* are used during the reconstruction
*/
//@{
/**
* Along with the showering evolution --- going forward for
* time-like (forward) evolution, and going backward for space-like
* (backward) evolution --- the kinematical variables of the
* branching products are calculated and updated from the knowledge
* of the parent kinematics.
* @param parent The parent
* @param children The children
*/
virtual void reconstructChildren(const tShowerParticlePtr parent,
const ShowerParticleVector & children) const;
/**
* Reconstruct the parent Kinematics from the knowledge of the kinematics
* of the children. This method will be used by the KinematicsReconstructor.
* @param parent The parent
* @param children The children
*/
virtual void reconstructParent(const tShowerParticlePtr parent,
const ParticleVector & children) const;
/**
* Update the kinematical data of a particle when a reconstruction
* fixpoint was found. This will highly depend on the kind of
* kinematics chosen and will be defined in the inherited concrete
* classes. This method will be used by the KinematicsReconstructor.
* @param last The particle.
* @param mass The mass to be used, if less than zero on-shell
*/
virtual void reconstructLast(const tShowerParticlePtr last, Energy mass=-1.*GeV) const;
//@}
public:
/**
* Set/access the flag that tells whether or not this ShowerKinematics
* object is associated to the starting particle of the jet: only in this
* case it is sensible to use the two main virtual methods below.
*/
//@{
/**
* Set the starting point flag
*/
void isTheJetStartingPoint(const bool );
/**
* Get the starting point flag
*/
bool isTheJetStartingPoint() const;
//@}
/**
* Set/Get methods for the kinematic variables
*/
//@{
/**
* Access the scale of the splitting.
*/
Energy scale() const { return _scale; }
/**
* Set the scale of the splitting.
*/
void scale(const Energy in) { _scale=in; }
/**
* Access the energy fraction, \f$z\f$.
*/
double z() const { return _z; }
/**
* Set the energy fraction, \f$z\f$.
*/
void z(const double in) { _z=in; }
/**
* Access the azimuthal angle, \f$\phi\f$.
*/
double phi() const { return _phi; }
/**
* Set the azimuthal angle, \f$\phi\f$.
*/
void phi(const double in) { _phi=in; }
/**
* Access the relative \f$p_T\f$ for the branching
*/
Energy pT() const { return _pt; }
/**
* Set the relative \f$p_T\f$ for the branching
*/
void pT(const Energy in) const { _pt=in; }
//@}
/**
* Set and get methods for the SplittingFunction object
*/
//@{
/**
* Access the SplittingFunction object responsible of the
* eventual branching of this particle.
*/
tSplittingFnPtr splittingFn() const { return _sudakov-> splittingFn(); }
//@}
/**
* Set and get methods for the SudakovFormFactor object
*/
/**
* Access the SudakovFormFactor object responsible of the
* eventual branching of this particle.
*/
tSudakovPtr SudakovFormFactor() const { return _sudakov; }
/**
* Set the SudakovFormFactor object responsible of the
* eventual branching of this particle.
*/
void SudakovFormFactor(const tSudakovPtr sud) { _sudakov=sud; }
//@}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
ShowerKinematics & operator=(const ShowerKinematics &);
private:
/**
* Is this the starting point of the jet
*/
bool _isTheJetStartingPoint;
/**
* The \f$\tilde{q}\f$ evolution variable.
*/
Energy _scale;
/**
* The energy fraction, \f$z\f$
*/
double _z;
/**
* The azimuthal angle, \f$\phi\f$.
*/
double _phi;
/**
* The relative \f$p_T\f$
*/
mutable Energy _pt;
/**
* The splitting function for the branching of the particle
*/
tSudakovPtr _sudakov;
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of ShowerKinematics. */
template <>
struct BaseClassTrait<Herwig::ShowerKinematics,1> {
/** Typedef of the first base class of ShowerKinematics. */
typedef Base NthBase;
};
/** This template specialization informs ThePEG about the name of
* the ShowerKinematics class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::ShowerKinematics>
: public ClassTraitsBase<Herwig::ShowerKinematics> {
/** Return a platform-independent class name */
static string className() { return "Herwig::ShowerKinematics"; }
};
/** @endcond */
}
#endif /* HERWIG_ShowerKinematics_H */
diff --git a/Shower/QTilde/Base/ShowerParticle.cc b/Shower/QTilde/Base/ShowerParticle.cc
--- a/Shower/QTilde/Base/ShowerParticle.cc
+++ b/Shower/QTilde/Base/ShowerParticle.cc
@@ -1,593 +1,593 @@
// -*- C++ -*-
//
// ShowerParticle.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 ShowerParticle class.
//
#include "ShowerParticle.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
#include "ThePEG/Helicity/WaveFunction/ScalarWaveFunction.h"
#include <ostream>
using namespace Herwig;
PPtr ShowerParticle::clone() const {
return new_ptr(*this);
}
PPtr ShowerParticle::fullclone() const {
return new_ptr(*this);
}
ClassDescription<ShowerParticle> ShowerParticle::initShowerParticle;
// Definition of the static class description member.
-void ShowerParticle::vetoEmission(ShowerPartnerType::Type, Energy scale) {
+void ShowerParticle::vetoEmission(ShowerPartnerType, Energy scale) {
scales_.QED = min(scale,scales_.QED );
scales_.QED_noAO = min(scale,scales_.QED_noAO );
scales_.QCD_c = min(scale,scales_.QCD_c );
scales_.QCD_c_noAO = min(scale,scales_.QCD_c_noAO );
scales_.QCD_ac = min(scale,scales_.QCD_ac );
scales_.QCD_ac_noAO = min(scale,scales_.QCD_ac_noAO);
}
void ShowerParticle::addPartner(EvolutionPartner in ) {
partners_.push_back(in);
}
namespace {
LorentzRotation boostToShower(Lorentz5Momentum & porig, tShowerBasisPtr basis) {
LorentzRotation output;
assert(basis);
if(basis->frame()==ShowerBasis::BackToBack) {
// we are doing the evolution in the back-to-back frame
// work out the boostvector
Boost boostv(-(basis->pVector()+basis->nVector()).boostVector());
// momentum of the parton
Lorentz5Momentum ptest(basis->pVector());
// construct the Lorentz boost
output = LorentzRotation(boostv);
ptest *= output;
Axis axis(ptest.vect().unit());
// now rotate so along the z axis as needed for the splitting functions
if(axis.perp2()>1e-10) {
double sinth(sqrt(1.-sqr(axis.z())));
output.rotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
}
else if(axis.z()<0.) {
output.rotate(Constants::pi,Axis(1.,0.,0.));
}
porig = output*basis->pVector();
porig.setX(ZERO);
porig.setY(ZERO);
}
else {
output = LorentzRotation(-basis->pVector().boostVector());
porig = output*basis->pVector();
porig.setX(ZERO);
porig.setY(ZERO);
porig.setZ(ZERO);
}
return output;
}
RhoDMatrix bosonMapping(ShowerParticle & particle,
const Lorentz5Momentum & porig,
VectorSpinPtr vspin,
const LorentzRotation & rot) {
// rotate the original basis
vector<LorentzPolarizationVector> sbasis;
for(unsigned int ix=0;ix<3;++ix) {
sbasis.push_back(vspin->getProductionBasisState(ix));
sbasis.back().transform(rot);
}
// splitting basis
vector<LorentzPolarizationVector> fbasis;
bool massless(particle.id()==ParticleID::g||particle.id()==ParticleID::gamma);
VectorWaveFunction wave(porig,particle.dataPtr(),outgoing);
for(unsigned int ix=0;ix<3;++ix) {
if(massless&&ix==1) {
fbasis.push_back(LorentzPolarizationVector());
}
else {
wave.reset(ix);
fbasis.push_back(wave.wave());
}
}
// work out the mapping
RhoDMatrix mapping=RhoDMatrix(PDT::Spin1,false);
for(unsigned int ix=0;ix<3;++ix) {
for(unsigned int iy=0;iy<3;++iy) {
mapping(ix,iy)= sbasis[iy].dot(fbasis[ix].conjugate());
if(particle.id()<0)
mapping(ix,iy)=conj(mapping(ix,iy));
}
}
// \todo need to fix this
mapping = RhoDMatrix(PDT::Spin1,false);
if(massless) {
mapping(0,0) = 1.;
mapping(2,2) = 1.;
}
else {
mapping(0,0) = 1.;
mapping(1,1) = 1.;
mapping(2,2) = 1.;
}
return mapping;
}
RhoDMatrix fermionMapping(ShowerParticle & particle,
const Lorentz5Momentum & porig,
FermionSpinPtr fspin,
const LorentzRotation & rot) {
// extract the original basis states
vector<LorentzSpinor<SqrtEnergy> > sbasis;
for(unsigned int ix=0;ix<2;++ix) {
sbasis.push_back(fspin->getProductionBasisState(ix));
sbasis.back().transform(rot);
}
// calculate the states in the splitting basis
vector<LorentzSpinor<SqrtEnergy> > fbasis;
SpinorWaveFunction wave(porig,particle.dataPtr(),
particle.id()>0 ? incoming : outgoing);
for(unsigned int ix=0;ix<2;++ix) {
wave.reset(ix);
fbasis.push_back(wave.dimensionedWave());
}
RhoDMatrix mapping=RhoDMatrix(PDT::Spin1Half,false);
for(unsigned int ix=0;ix<2;++ix) {
if(fbasis[0].s2()==complex<SqrtEnergy>()) {
mapping(ix,0) = sbasis[ix].s3()/fbasis[0].s3();
mapping(ix,1) = sbasis[ix].s2()/fbasis[1].s2();
}
else {
mapping(ix,0) = sbasis[ix].s2()/fbasis[0].s2();
mapping(ix,1) = sbasis[ix].s3()/fbasis[1].s3();
}
}
return mapping;
}
FermionSpinPtr createFermionSpinInfo(ShowerParticle & particle,
const Lorentz5Momentum & porig,
const LorentzRotation & rot,
Helicity::Direction dir) {
// calculate the splitting basis for the branching
// and rotate back to construct the basis states
LorentzRotation rinv = rot.inverse();
SpinorWaveFunction wave;
if(particle.id()>0)
wave=SpinorWaveFunction(porig,particle.dataPtr(),incoming);
else
wave=SpinorWaveFunction(porig,particle.dataPtr(),outgoing);
FermionSpinPtr fspin = new_ptr(FermionSpinInfo(particle.momentum(),dir==outgoing));
for(unsigned int ix=0;ix<2;++ix) {
wave.reset(ix);
LorentzSpinor<SqrtEnergy> basis = wave.dimensionedWave();
basis.transform(rinv);
fspin->setBasisState(ix,basis);
fspin->setDecayState(ix,basis);
}
particle.spinInfo(fspin);
return fspin;
}
VectorSpinPtr createVectorSpinInfo(ShowerParticle & particle,
const Lorentz5Momentum & porig,
const LorentzRotation & rot,
Helicity::Direction dir) {
// calculate the splitting basis for the branching
// and rotate back to construct the basis states
LorentzRotation rinv = rot.inverse();
bool massless(particle.id()==ParticleID::g||particle.id()==ParticleID::gamma);
VectorWaveFunction wave(porig,particle.dataPtr(),dir);
VectorSpinPtr vspin = new_ptr(VectorSpinInfo(particle.momentum(),dir==outgoing));
for(unsigned int ix=0;ix<3;++ix) {
LorentzPolarizationVector basis;
if(massless&&ix==1) {
basis = LorentzPolarizationVector();
}
else {
wave.reset(ix);
basis = wave.wave();
}
basis *= rinv;
vspin->setBasisState(ix,basis);
vspin->setDecayState(ix,basis);
}
particle.spinInfo(vspin);
vspin-> DMatrix() = RhoDMatrix(PDT::Spin1);
vspin->rhoMatrix() = RhoDMatrix(PDT::Spin1);
if(massless) {
vspin-> DMatrix()(0,0) = 0.5;
vspin->rhoMatrix()(0,0) = 0.5;
vspin-> DMatrix()(2,2) = 0.5;
vspin->rhoMatrix()(2,2) = 0.5;
}
return vspin;
}
}
RhoDMatrix ShowerParticle::extractRhoMatrix(bool forward) {
// get the spin density matrix and the mapping
RhoDMatrix mapping;
SpinPtr inspin;
bool needMapping = getMapping(inspin,mapping);
// set the decayed flag
inspin->decay();
// get the spin density matrix
RhoDMatrix rho = forward ? inspin->rhoMatrix() : inspin->DMatrix();
// map to the shower basis if needed
if(needMapping) {
RhoDMatrix rhop(rho.iSpin(),false);
for(int ixa=0;ixa<rho.iSpin();++ixa) {
for(int ixb=0;ixb<rho.iSpin();++ixb) {
for(int iya=0;iya<rho.iSpin();++iya) {
for(int iyb=0;iyb<rho.iSpin();++iyb) {
rhop(ixa,ixb) += rho(iya,iyb)*mapping(iya,ixa)*conj(mapping(iyb,ixb));
}
}
}
}
rhop.normalize();
rho = rhop;
}
return rho;
}
bool ShowerParticle::getMapping(SpinPtr & output, RhoDMatrix & mapping) {
// if the particle is not from the hard process
if(!this->perturbative()) {
// mapping is the identity
output=this->spinInfo();
mapping=RhoDMatrix(this->dataPtr()->iSpin());
if(output) {
return false;
}
else {
Lorentz5Momentum porig;
LorentzRotation rot = boostToShower(porig,showerBasis());
Helicity::Direction dir = this->isFinalState() ? outgoing : incoming;
if(this->dataPtr()->iSpin()==PDT::Spin0) {
assert(false);
}
else if(this->dataPtr()->iSpin()==PDT::Spin1Half) {
output = createFermionSpinInfo(*this,porig,rot,dir);
}
else if(this->dataPtr()->iSpin()==PDT::Spin1) {
output = createVectorSpinInfo(*this,porig,rot,dir);
}
else {
assert(false);
}
return false;
}
}
// if particle is final-state and is from the hard process
else if(this->isFinalState()) {
assert(this->perturbative()==1 || this->perturbative()==2);
// get transform to shower frame
Lorentz5Momentum porig;
LorentzRotation rot = boostToShower(porig,showerBasis());
// the rest depends on the spin of the particle
PDT::Spin spin(this->dataPtr()->iSpin());
mapping=RhoDMatrix(spin,false);
// do the spin dependent bit
if(spin==PDT::Spin0) {
ScalarSpinPtr sspin=dynamic_ptr_cast<ScalarSpinPtr>(this->spinInfo());
if(!sspin) {
ScalarWaveFunction::constructSpinInfo(this,outgoing,true);
}
output=this->spinInfo();
return false;
}
else if(spin==PDT::Spin1Half) {
FermionSpinPtr fspin=dynamic_ptr_cast<FermionSpinPtr>(this->spinInfo());
// spin info exists get information from it
if(fspin) {
output=fspin;
mapping = fermionMapping(*this,porig,fspin,rot);
return true;
}
// spin info does not exist create it
else {
output = createFermionSpinInfo(*this,porig,rot,outgoing);
return false;
}
}
else if(spin==PDT::Spin1) {
VectorSpinPtr vspin=dynamic_ptr_cast<VectorSpinPtr>(this->spinInfo());
// spin info exists get information from it
if(vspin) {
output=vspin;
mapping = bosonMapping(*this,porig,vspin,rot);
return true;
}
else {
output = createVectorSpinInfo(*this,porig,rot,outgoing);
return false;
}
}
// not scalar/fermion/vector
else
assert(false);
}
// incoming to hard process
else if(this->perturbative()==1 && !this->isFinalState()) {
// get the basis vectors
// get transform to shower frame
Lorentz5Momentum porig;
LorentzRotation rot = boostToShower(porig,showerBasis());
porig *= this->x();
// the rest depends on the spin of the particle
PDT::Spin spin(this->dataPtr()->iSpin());
mapping=RhoDMatrix(spin);
// do the spin dependent bit
if(spin==PDT::Spin0) {
cerr << "testing spin 0 not yet implemented " << endl;
assert(false);
}
// spin-1/2
else if(spin==PDT::Spin1Half) {
FermionSpinPtr fspin=dynamic_ptr_cast<FermionSpinPtr>(this->spinInfo());
// spin info exists get information from it
if(fspin) {
output=fspin;
mapping = fermionMapping(*this,porig,fspin,rot);
return true;
}
// spin info does not exist create it
else {
output = createFermionSpinInfo(*this,porig,rot,incoming);
return false;
}
}
// spin-1
else if(spin==PDT::Spin1) {
VectorSpinPtr vspin=dynamic_ptr_cast<VectorSpinPtr>(this->spinInfo());
// spinInfo exists map it
if(vspin) {
output=vspin;
mapping = bosonMapping(*this,porig,vspin,rot);
return true;
}
// create the spininfo
else {
output = createVectorSpinInfo(*this,porig,rot,incoming);
return false;
}
}
assert(false);
}
// incoming to decay
else if(this->perturbative() == 2 && !this->isFinalState()) {
// get the basis vectors
Lorentz5Momentum porig;
LorentzRotation rot=boostToShower(porig,showerBasis());
// the rest depends on the spin of the particle
PDT::Spin spin(this->dataPtr()->iSpin());
mapping=RhoDMatrix(spin);
// do the spin dependent bit
if(spin==PDT::Spin0) {
cerr << "testing spin 0 not yet implemented " << endl;
assert(false);
}
// spin-1/2
else if(spin==PDT::Spin1Half) {
// FermionSpinPtr fspin=dynamic_ptr_cast<FermionSpinPtr>(this->spinInfo());
// // spin info exists get information from it
// if(fspin) {
// output=fspin;
// mapping = fermionMapping(*this,porig,fspin,rot);
// return true;
// // spin info does not exist create it
// else {
// output = createFermionSpinInfo(*this,porig,rot,incoming);
// return false;
// }
// }
assert(false);
}
// // spin-1
// else if(spin==PDT::Spin1) {
// VectorSpinPtr vspin=dynamic_ptr_cast<VectorSpinPtr>(this->spinInfo());
// // spinInfo exists map it
// if(vspin) {
// output=vspin;
// mapping = bosonMapping(*this,porig,vspin,rot);
// return true;
// }
// // create the spininfo
// else {
// output = createVectorSpinInfo(*this,porig,rot,incoming);
// return false;
// }
// }
// assert(false);
assert(false);
}
else
assert(false);
return true;
}
void ShowerParticle::constructSpinInfo(bool timeLike) {
// now construct the required spininfo and calculate the basis states
PDT::Spin spin(dataPtr()->iSpin());
if(spin==PDT::Spin0) {
ScalarWaveFunction::constructSpinInfo(this,outgoing,timeLike);
}
// calculate the basis states and construct the SpinInfo for a spin-1/2 particle
else if(spin==PDT::Spin1Half) {
// outgoing particle
if(id()>0) {
vector<LorentzSpinorBar<SqrtEnergy> > stemp;
SpinorBarWaveFunction::calculateWaveFunctions(stemp,this,outgoing);
SpinorBarWaveFunction::constructSpinInfo(stemp,this,outgoing,timeLike);
}
// outgoing antiparticle
else {
vector<LorentzSpinor<SqrtEnergy> > stemp;
SpinorWaveFunction::calculateWaveFunctions(stemp,this,outgoing);
SpinorWaveFunction::constructSpinInfo(stemp,this,outgoing,timeLike);
}
}
// calculate the basis states and construct the SpinInfo for a spin-1 particle
else if(spin==PDT::Spin1) {
bool massless(id()==ParticleID::g||id()==ParticleID::gamma);
vector<Helicity::LorentzPolarizationVector> vtemp;
VectorWaveFunction::calculateWaveFunctions(vtemp,this,outgoing,massless);
VectorWaveFunction::constructSpinInfo(vtemp,this,outgoing,timeLike,massless);
}
else {
throw Exception() << "Spins higher than 1 are not yet implemented in "
<< "FS_QtildaShowerKinematics1to2::constructVertex() "
<< Exception::runerror;
}
}
void ShowerParticle::initializeDecay() {
Lorentz5Momentum p, n, ppartner, pcm;
assert(perturbative()!=1);
// this is for the initial decaying particle
if(perturbative()==2) {
ShowerBasisPtr newBasis;
p = momentum();
Lorentz5Momentum ppartner(partner()->momentum());
// removed to make inverse recon work properly
//if(partner->thePEGBase()) ppartner=partner->thePEGBase()->momentum();
pcm=ppartner;
Boost boost(p.findBoostToCM());
pcm.boost(boost);
n = Lorentz5Momentum( ZERO,0.5*p.mass()*pcm.vect().unit());
n.boost( -boost);
newBasis = new_ptr(ShowerBasis());
newBasis->setBasis(p,n,ShowerBasis::Rest);
showerBasis(newBasis,false);
}
else {
showerBasis(dynamic_ptr_cast<ShowerParticlePtr>(parents()[0])->showerBasis(),true);
}
}
void ShowerParticle::initializeInitialState(PPtr parent) {
// For the time being we are considering only 1->2 branching
Lorentz5Momentum p, n, pthis, pcm;
assert(perturbative()!=2);
if(perturbative()==1) {
ShowerBasisPtr newBasis;
// find the partner and its momentum
if(!partner()) return;
if(partner()->isFinalState()) {
Lorentz5Momentum pa = -momentum()+partner()->momentum();
Lorentz5Momentum pb = momentum();
Energy scale=parent->momentum().t();
Lorentz5Momentum pbasis(ZERO,parent->momentum().vect().unit()*scale);
Axis axis(pa.vect().unit());
LorentzRotation rot;
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
if(axis.perp2()>1e-20) {
rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
rot.rotateX(Constants::pi);
}
if(abs(1.-pa.e()/pa.vect().mag())>1e-6) rot.boostZ( pa.e()/pa.vect().mag());
pb *= rot;
if(pb.perp2()/GeV2>1e-20) {
Boost trans = -1./pb.e()*pb.vect();
trans.setZ(0.);
rot.boost(trans);
}
pbasis *=rot;
rot.invert();
n = rot*Lorentz5Momentum(ZERO,-pbasis.vect());
p = rot*Lorentz5Momentum(ZERO, pbasis.vect());
}
else {
pcm = parent->momentum();
p = Lorentz5Momentum(ZERO, pcm.vect());
n = Lorentz5Momentum(ZERO, -pcm.vect());
}
newBasis = new_ptr(ShowerBasis());
newBasis->setBasis(p,n,ShowerBasis::BackToBack);
showerBasis(newBasis,false);
}
else {
showerBasis(dynamic_ptr_cast<ShowerParticlePtr>(children()[0])->showerBasis(),true);
}
}
void ShowerParticle::initializeFinalState() {
// set the basis vectors
Lorentz5Momentum p,n;
if(perturbative()!=0) {
ShowerBasisPtr newBasis;
// find the partner() and its momentum
if(!partner()) return;
Lorentz5Momentum ppartner(partner()->momentum());
// momentum of the emitting particle
p = momentum();
Lorentz5Momentum pcm;
// if the partner is a final-state particle then the reference
// vector is along the partner in the rest frame of the pair
if(partner()->isFinalState()) {
Boost boost=(p + ppartner).findBoostToCM();
pcm = ppartner;
pcm.boost(boost);
n = Lorentz5Momentum(ZERO,pcm.vect());
n.boost( -boost);
}
else if(!partner()->isFinalState()) {
// if the partner is an initial-state particle then the reference
// vector is along the partner which should be massless
if(perturbative()==1) {
n = Lorentz5Momentum(ZERO,ppartner.vect());
}
// if the partner is an initial-state decaying particle then the reference
// vector is along the backwards direction in rest frame of decaying particle
else {
Boost boost=ppartner.findBoostToCM();
pcm = p;
pcm.boost(boost);
n = Lorentz5Momentum( ZERO, -pcm.vect());
n.boost( -boost);
}
}
newBasis = new_ptr(ShowerBasis());
newBasis->setBasis(p,n,ShowerBasis::BackToBack);
showerBasis(newBasis,false);
}
else if(initiatesTLS()) {
showerBasis(dynamic_ptr_cast<ShowerParticlePtr>(parents()[0]->children()[0])->showerBasis(),true);
}
else {
showerBasis(dynamic_ptr_cast<ShowerParticlePtr>(parents()[0])->showerBasis(),true);
}
}
void ShowerParticle::setShowerMomentum(bool timeLike) {
Energy m = this->mass() > ZERO ? this->mass() : this->data().mass();
// calculate the momentum of the assuming on-shell
Energy2 pt2 = sqr(this->showerParameters().pt);
double alpha = timeLike ? this->showerParameters().alpha : this->x();
double beta = 0.5*(sqr(m) + pt2 - sqr(alpha)*showerBasis()->pVector().m2())/(alpha*showerBasis()->p_dot_n());
Lorentz5Momentum porig=showerBasis()->sudakov2Momentum(alpha,beta,
this->showerParameters().ptx,
this->showerParameters().pty);
porig.setMass(m);
this->set5Momentum(porig);
}
diff --git a/Shower/QTilde/Base/ShowerParticle.h b/Shower/QTilde/Base/ShowerParticle.h
--- a/Shower/QTilde/Base/ShowerParticle.h
+++ b/Shower/QTilde/Base/ShowerParticle.h
@@ -1,530 +1,530 @@
// -*- C++ -*-
//
// ShowerParticle.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_ShowerParticle_H
#define HERWIG_ShowerParticle_H
//
// This is the declaration of the ShowerParticle class.
//
#include "ThePEG/EventRecord/Particle.h"
#include "Herwig/Shower/QTilde/SplittingFunctions/SplittingFunction.fh"
#include "Herwig/Shower/QTilde/ShowerConfig.h"
#include "ShowerBasis.h"
#include "ShowerKinematics.h"
#include "ShowerParticle.fh"
#include <iosfwd>
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
* This class represents a particle in the showering process.
* It inherits from the Particle class of ThePEG and has some
* specifics information useful only during the showering process.
*
* Notice that:
* - for forward evolution, it is clear what is meant by parent/child;
* for backward evolution, however, it depends whether we want
* to keep a physical picture or a Monte-Carlo effective one.
* In the former case, an incoming particle (emitting particle)
* splits into an emitted particle and the emitting particle after
* the emission: the latter two are then children of the
* emitting particle, the parent. In the Monte-Carlo effective
* picture, we have that the particle close to the hard subprocess,
* with higher (space-like) virtuality, splits into an emitted particle
* and the emitting particle at lower virtuality: the latter two are,
* in this case, the children of the first one, the parent. However we
* choose a more physical picture where the new emitting particle is the
* parented of the emitted final-state particle and the original emitting
* particle.
* - the pointer to a SplitFun object is set only in the case
* that the particle has undergone a shower emission. This is similar to
* the case of the decay of a normal Particle where
* the pointer to a Decayer object is set only in the case
* that the particle has undergone to a decay.
* In the case of particle connected directly to the hard subprocess,
* there is no pointer to the hard subprocess, but there is a method
* isFromHardSubprocess() which returns true only in this case.
*
* @see Particle
* @see ShowerConfig
* @see ShowerKinematics
*/
class ShowerParticle: public Particle {
public:
/**
* Struct for all the info on an evolution partner
*/
struct EvolutionPartner {
/**
* Constructor
*/
- EvolutionPartner(tShowerParticlePtr p,double w, ShowerPartnerType::Type t,
+ EvolutionPartner(tShowerParticlePtr p,double w, ShowerPartnerType t,
Energy s) : partner(p), weight(w), type(t), scale(s)
{}
/**
* The partner
*/
tShowerParticlePtr partner;
/**
* Weight
*/
double weight;
/**
* Type
*/
- ShowerPartnerType::Type type;
+ ShowerPartnerType type;
/**
* The assoicated evolution scale
*/
Energy scale;
};
/**
* Struct to store the evolution scales
*/
struct EvolutionScales {
/**
* Constructor
*/
EvolutionScales() : QED(),QCD_c(),QCD_ac(),
QED_noAO(),QCD_c_noAO(),QCD_ac_noAO(),
Max_Q2(Constants::MaxEnergy2)
{}
/**
* QED scale
*/
Energy QED;
/**
* QCD colour scale
*/
Energy QCD_c;
/**
* QCD anticolour scale
*/
Energy QCD_ac;
/**
* QED scale
*/
Energy QED_noAO;
/**
* QCD colour scale
*/
Energy QCD_c_noAO;
/**
* QCD anticolour scale
*/
Energy QCD_ac_noAO;
/**
* Maximum allowed virtuality of the particle
*/
Energy2 Max_Q2;
};
/** @name Construction and descruction functions. */
//@{
/**
* Standard Constructor. Note that the default constructor is
* private - there is no particle without a pointer to a
* ParticleData object.
* @param x the ParticleData object
* @param fs Whether or not the particle is an inital or final-state particle
* @param tls Whether or not the particle initiates a time-like shower
*/
ShowerParticle(tcEventPDPtr x, bool fs, bool tls=false)
: Particle(x), _isFinalState(fs),
_perturbative(0), _initiatesTLS(tls), _x(1.0), _showerKinematics(),
_vMass(ZERO), _thePEGBase() {}
/**
* Copy constructor from a ThePEG Particle
* @param x ThePEG particle
* @param pert Where the particle came from
* @param fs Whether or not the particle is an inital or final-state particle
* @param tls Whether or not the particle initiates a time-like shower
*/
ShowerParticle(const Particle & x, unsigned int pert, bool fs, bool tls=false)
: Particle(x), _isFinalState(fs),
_perturbative(pert), _initiatesTLS(tls), _x(1.0), _showerKinematics(),
_vMass(ZERO), _thePEGBase(&x) {}
//@}
public:
/**
* Set a preliminary momentum for the particle
*/
void setShowerMomentum(bool timelike);
/**
* Construct the spin info object for a shower particle
*/
void constructSpinInfo(bool timelike);
/**
* Perform any initial calculations needed after the branching has been selected
*/
void initializeDecay();
/**
* Perform any initial calculations needed after the branching has been selected
* @param parent The beam particle
*/
void initializeInitialState(PPtr parent);
/**
* Perform any initial calculations needed after the branching has been selected
*/
void initializeFinalState();
/**
* Access/Set various flags about the state of the particle
*/
//@{
/**
* Access the flag that tells if the particle is final state
* or initial state.
*/
bool isFinalState() const { return _isFinalState; }
/**
* Access the flag that tells if the particle is initiating a
* time like shower when it has been emitted in an initial state shower.
*/
bool initiatesTLS() const { return _initiatesTLS; }
/**
* Access the flag which tells us where the particle came from
* This is 0 for a particle produced in the shower, 1 if the particle came
* from the hard sub-process and 2 is it came from a decay.
*/
unsigned int perturbative() const { return _perturbative; }
//@}
/**
* Set/Get the momentum fraction for initial-state particles
*/
//@{
/**
* For an initial state particle get the fraction of the beam momentum
*/
void x(double x) { _x = x; }
/**
* For an initial state particle set the fraction of the beam momentum
*/
double x() const { return _x; }
//@}
/**
* Set/Get methods for the ShowerKinematics objects
*/
//@{
/**
* Access/ the ShowerKinematics object.
*/
const ShoKinPtr & showerKinematics() const { return _showerKinematics; }
/**
* Set the ShowerKinematics object.
*/
void showerKinematics(const ShoKinPtr in) { _showerKinematics = in; }
//@}
/**
* Set/Get methods for the ShowerBasis objects
*/
//@{
/**
* Access/ the ShowerBasis object.
*/
const ShowerBasisPtr & showerBasis() const { return _showerBasis; }
/**
* Set the ShowerBasis object.
*/
void showerBasis(const ShowerBasisPtr in, bool copy) {
if(!copy)
_showerBasis = in;
else {
_showerBasis = new_ptr(ShowerBasis());
_showerBasis->setBasis(in->pVector(),in->nVector(),in->frame());
}
}
//@}
/**
* Members relating to the initial evolution scale and partner for the particle
*/
//@{
/**
* Veto emission at a given scale
*/
- void vetoEmission(ShowerPartnerType::Type type, Energy scale);
+ void vetoEmission(ShowerPartnerType type, Energy scale);
/**
* Access to the evolution scales
*/
const EvolutionScales & scales() const {return scales_;}
/**
* Access to the evolution scales
*/
EvolutionScales & scales() {return scales_;}
/**
* Return the virtual mass\f$
*/
Energy virtualMass() const { return _vMass; }
/**
* Set the virtual mass
*/
void virtualMass(Energy mass) { _vMass = mass; }
/**
* Return the partner
*/
tShowerParticlePtr partner() const { return _partner; }
/**
* Set the partner
*/
void partner(const tShowerParticlePtr partner) { _partner = partner; }
/**
* Get the possible partners
*/
vector<EvolutionPartner> & partners() { return partners_; }
/**
* Add a possible partners
*/
void addPartner(EvolutionPartner in );
/**
* Clear the evolution partners
*/
void clearPartners() { partners_.clear(); }
/**
* Return the progenitor of the shower
*/
tShowerParticlePtr progenitor() const { return _progenitor; }
/**
* Set the progenitor of the shower
*/
void progenitor(const tShowerParticlePtr progenitor) { _progenitor = progenitor; }
//@}
/**
* Members to store and provide access to variables for a specific
* shower evolution scheme
*/
//@{
struct Parameters {
Parameters() : alpha(1.), beta(), ptx(), pty(), pt() {}
double alpha;
double beta;
Energy ptx;
Energy pty;
Energy pt;
};
/**
* Set the vector containing dimensionless variables
*/
Parameters & showerParameters() { return _parameters; }
//@}
/**
* If this particle came from the hard process get a pointer to ThePEG particle
* it came from
*/
const tcPPtr thePEGBase() const { return _thePEGBase; }
public:
/**
* Extract the rho matrix including mapping needed in the shower
*/
RhoDMatrix extractRhoMatrix(bool forward);
protected:
/**
* For a particle which came from the hard process get the spin density and
* the mapping required to the basis used in the Shower
* @param rho The \f$\rho\f$ matrix
* @param mapping The mapping
* @param showerkin The ShowerKinematics object
*/
bool getMapping(SpinPtr &, RhoDMatrix & map);
protected:
/**
* Standard clone function.
*/
virtual PPtr clone() const;
/**
* Standard clone function.
*/
virtual PPtr fullclone() const;
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<ShowerParticle> initShowerParticle;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
ShowerParticle & operator=(const ShowerParticle &);
private:
/**
* Whether the particle is in the final or initial state
*/
bool _isFinalState;
/**
* Whether the particle came from
*/
unsigned int _perturbative;
/**
* Does a particle produced in the backward shower initiate a time-like shower
*/
bool _initiatesTLS;
/**
* Dimensionless parameters
*/
Parameters _parameters;
/**
* The beam energy fraction for particle's in the initial state
*/
double _x;
/**
* The shower kinematics for the particle
*/
ShoKinPtr _showerKinematics;
/**
* The shower basis for the particle
*/
ShowerBasisPtr _showerBasis;
/**
* Storage of the evolution scales
*/
EvolutionScales scales_;
/**
* Virtual mass
*/
Energy _vMass;
/**
* Partners
*/
tShowerParticlePtr _partner;
/**
* Pointer to ThePEG Particle this ShowerParticle was created from
*/
const tcPPtr _thePEGBase;
/**
* Progenitor
*/
tShowerParticlePtr _progenitor;
/**
* Partners
*/
vector<EvolutionPartner> partners_;
};
inline ostream & operator<<(ostream & os, const ShowerParticle::EvolutionScales & es) {
os << "Scales: QED=" << es.QED / GeV
<< " QCD_c=" << es.QCD_c / GeV
<< " QCD_ac=" << es.QCD_ac / GeV
<< " QED_noAO=" << es.QED_noAO / GeV
<< " QCD_c_noAO=" << es.QCD_c_noAO / GeV
<< " QCD_ac_noAO=" << es.QCD_ac_noAO / GeV
<< '\n';
return os;
}
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of ShowerParticle. */
template <>
struct BaseClassTrait<Herwig::ShowerParticle,1> {
/** Typedef of the first base class of ShowerParticle. */
typedef Particle NthBase;
};
/** This template specialization informs ThePEG about the name of
* the ShowerParticle class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::ShowerParticle>
: public ClassTraitsBase<Herwig::ShowerParticle> {
/** Return a platform-independent class name */
static string className() { return "Herwig::ShowerParticle"; }
/** Create a Event object. */
static TPtr create() { return TPtr::Create(Herwig::ShowerParticle(tcEventPDPtr(),true)); }
};
/** @endcond */
}
#endif /* HERWIG_ShowerParticle_H */
diff --git a/Shower/QTilde/Base/ShowerProgenitor.h b/Shower/QTilde/Base/ShowerProgenitor.h
--- a/Shower/QTilde/Base/ShowerProgenitor.h
+++ b/Shower/QTilde/Base/ShowerProgenitor.h
@@ -1,263 +1,263 @@
// -*- C++ -*-
//
// ShowerProgenitor.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_ShowerProgenitor_H
#define HERWIG_ShowerProgenitor_H
//
// This is the declaration of the ShowerProgenitor struct.
//
#include "ThePEG/Config/ThePEG.h"
#include "Herwig/Shower/QTilde/ShowerConfig.h"
#include "Herwig/Shower/QTilde/Base/ShowerParticle.h"
#include "ShowerProgenitor.fh"
#include "ThePEG/PDF/BeamParticleData.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
* A struct to store information on the perturbative particle which
* initiates a shower
*/
class ShowerProgenitor : public Base {
public:
/**
* Enum for the reconstruction state of this progentitor
*/
enum Reconstructed { notReconstructed=0, done, dontReconstruct};
/**
* Typedef for the BeamParticleData objects
*/
typedef Ptr<BeamParticleData>::transient_const_pointer tcBeamPtr;
public:
/**
* Constructor for the class
* @param original The original particle
* @param copy The colour isolated copy
* @param particle The ShowerPArticle copy
* @param pT The \f$p_t\f$ of the hardest emission
* @param emitted Whether or not the particle has radiated
*/
ShowerProgenitor(PPtr original,PPtr copy, ShowerParticlePtr particle,
Energy pT=ZERO,bool emitted=false)
: _original(original), _copy(copy), _perturbative(true),
_particle(particle), _highestpT(pT),
_maxHardPt(ZERO), _hardScale(ZERO), _hasEmitted(emitted),
_reconstructed(notReconstructed) {
// get the BeamParticleData object
if ( original->parents().empty() ) {
_beam=dynamic_ptr_cast<tcBeamPtr>(original->dataPtr());
}
else {
_beam=dynamic_ptr_cast<tcBeamPtr>(original->parents()[0]->dataPtr());
}
}
/**
* Access to the particle
*/
ShowerParticlePtr progenitor() const { return _particle; }
/**
* Set the particle
*/
void progenitor(ShowerParticlePtr in) { _particle=in; }
/**
* Access to the original particle
*/
PPtr original() const { return _original; }
/**
* Access to the colour isolated copy
*/
PPtr copy() const { return _copy; }
/**
* Set the copy
*/
void copy(PPtr in) { _copy=in; }
/**
* Whether the particle came from the hard process or was added by
* the matrix element correction
*/
bool perturbative() const { return _perturbative; }
/**
* Whether the particle came from the hard process or was added by
* the matrix element correction
*/
void perturbative(bool in) { _perturbative=in; }
/**
* Set/Get methods for the hardest \f$p_T\f$ so far
*/
//@{
/**
* Access the \f$p_T\f$ of the hardest emission so far
*/
Energy highestpT() const { return _highestpT; }
/**
* Set the \f$p_T\f$ of the hardest emission so far
*/
void highestpT(Energy in) { _highestpT=in; }
//@}
/**
* Set/Get methods for the maximum \f$p_T\f$
*/
//@{
/**
* Access the maximum \f$p_T\f$ for radiation
*/
- Energy maximumpT(ShowerInteraction::Type type) const {
+ Energy maximumpT(ShowerInteraction type) const {
assert(type!=ShowerInteraction::Both);
- map<ShowerInteraction::Type,Energy>::const_iterator it = _maxpT.find(type);
+ map<ShowerInteraction,Energy>::const_iterator it = _maxpT.find(type);
return it !=_maxpT.end() ? it->second : Constants::MaxEnergy;
}
/**
* Set the maximum \f$p_T\f$ for radiation
*/
- void maximumpT(Energy in,ShowerInteraction::Type type) {
+ void maximumpT(Energy in,ShowerInteraction type) {
_maxpT[type]=in; }
//@}
/**
* Set/Get methods for whether the particle has radiated
*/
//@{
/**
* Access the maximum hard \f$p_T\f$, given by the hard process
*/
Energy maxHardPt() const { return _maxHardPt; }
/**
* Set the maximum hard \f$p_T\f$, given by the hard process
*/
void maxHardPt(Energy in) { _maxHardPt = in; }
/**
* Access the relevant hard scale to be used in profile scales; usually
* this is taken to be the maximum pt, except for other choices such as
* hfact.
*/
Energy hardScale() const { return _hardScale; }
/**
* Set the relevant hard scale to be used in profile scales; usually
* this is taken to be the maximum pt, except for other choices such as
* hfact.
*/
void hardScale(Energy in) { _hardScale = in; }
/**
* Has this particle radiated
*/
bool hasEmitted() const { return _hasEmitted; }
/**
* Set whether or not this particle has radiated
*/
void hasEmitted(bool in) { _hasEmitted=in; }
//@}
/**
* The id of the particle
*/
long id() const { return _particle->id(); }
/**
* The BeamParticleData object
*/
tcBeamPtr beam() { return _beam; }
/**
* Whether or not the recon has been performed
*/
Reconstructed reconstructed() const {return _reconstructed;}
/**
* Whether or not the recon has been performed
*/
void reconstructed(Reconstructed recon) {_reconstructed = recon;}
private:
/**
* Pointer to the original particle
*/
PPtr _original;
/**
* Pointer to the colour isolated copy of the original particle
*/
PPtr _copy;
/**
* Whether the particle came from the hard process or was added by
* the matrix element correction
*/
bool _perturbative;
/**
* Pointer to the ShowerParticle
*/
ShowerParticlePtr _particle;
/**
* Highest \f$p_T\f$ emitted in the shower from this particle
*/
Energy _highestpT;
/**
* Maximum allowed \f$p_T\f$ for emission from this particle
*/
- map<ShowerInteraction::Type,Energy> _maxpT;
+ map<ShowerInteraction,Energy> _maxpT;
/**
* maximum hard \f$p_T\f$ from the hard process
*/
Energy _maxHardPt;
/**
* The relevant hard scale to be used in profile scales; usually
* this is taken to be the maximum pt, except for other choices such as
* hfact.
*/
Energy _hardScale;
/**
* Has there been radiation
*/
bool _hasEmitted;
/**
* The BeamParticleData object
*/
tcBeamPtr _beam;
/**
* Whether or not the reconstruction has been performed
*/
Reconstructed _reconstructed;
};
}
#endif /* HERWIG_ShowerProgenitor_H */
diff --git a/Shower/QTilde/Base/ShowerTree.cc b/Shower/QTilde/Base/ShowerTree.cc
--- a/Shower/QTilde/Base/ShowerTree.cc
+++ b/Shower/QTilde/Base/ShowerTree.cc
@@ -1,924 +1,924 @@
// -*- C++ -*-
//
// ShowerTree.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.
//
#include "ShowerProgenitor.h"
#include "ThePEG/EventRecord/MultiColour.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ShowerTree.h"
#include "Herwig/Shower/QTilde/Base/ShowerParticle.h"
#include "Herwig/Shower/ShowerHandler.h"
#include "ThePEG/PDT/DecayMode.h"
#include "ThePEG/Handlers/EventHandler.h"
#include "ThePEG/Handlers/XComb.h"
#include "KinematicsReconstructor.h"
#include <cassert>
#include "ThePEG/Repository/CurrentGenerator.h"
#include "ThePEG/PDT/StandardMatchers.h"
using namespace Herwig;
using namespace ThePEG;
bool ShowerTree::_spaceTime = false;
Energy2 ShowerTree::_vmin2 = 0.1*GeV2;
namespace {
void findBeam(tPPtr & beam, PPtr incoming) {
while(!beam->children().empty()) {
bool found=false;
for(unsigned int ix=0;ix<beam->children().size();++ix) {
if(beam->children()[ix]==incoming) {
found = true;
break;
}
}
if(found) break;
beam = beam->children()[0];
}
}
}
ShowerTree::ShowerTree(PerturbativeProcessPtr process)
: _hardMECorrection(false),
_parent(), _hasShowered(false) {
// get the incoming and outgoing particles and make copies
vector<PPtr> original,copy;
for(unsigned int ix=0;ix<process->incoming().size();++ix) {
original.push_back(process->incoming()[ix].first);
copy .push_back(new_ptr(Particle(*original.back())));
}
for(unsigned int ix=0;ix<process->outgoing().size();++ix) {
original.push_back(process->outgoing()[ix].first);
copy .push_back(new_ptr(Particle(*original.back())));
}
// isolate the colour
colourIsolate(original,copy);
// hard process
unsigned int itype(1);
if(process->incoming().size()==2) {
_wasHard = true;
// set the beams and incoming particles
tPPair beam = CurrentGenerator::current().currentEvent()->incoming();
findBeam(beam.first ,process->incoming()[0].first);
findBeam(beam.second,process->incoming()[1].first);
_incoming = make_pair(process->incoming()[0].first,
process->incoming()[1].first);
double x1(_incoming.first ->momentum().rho()/beam.first ->momentum().rho());
double x2(_incoming.second->momentum().rho()/beam.second->momentum().rho());
// must have two incoming particles
assert(_incoming.first && _incoming.second);
// set the parent tree
_parent=ShowerTreePtr();
for(unsigned int ix=0;ix<2;++ix) {
ShowerParticlePtr temp=new_ptr(ShowerParticle(*copy[ix],itype,false));
fixColour(temp);
temp->x(ix==0 ? x1 : x2);
_incomingLines.insert(make_pair(new_ptr(ShowerProgenitor(original[ix],
copy[ix],temp)),temp));
_backward.insert(temp);
}
}
// decay process
else if(process->incoming().size()==1) {
_wasHard = false;
itype=2;
// create the parent shower particle
ShowerParticlePtr sparent(new_ptr(ShowerParticle(*copy[0],itype,false)));
fixColour(sparent);
_incomingLines.insert(make_pair(new_ptr(ShowerProgenitor(original[0],copy[0],sparent))
,sparent));
// return if not decayed
if(original.size()==1) return;
}
else
assert(false);
// create the children
assert(copy.size() == original.size());
for (unsigned int ix=process->incoming().size();ix<original.size();++ix) {
ShowerParticlePtr stemp= new_ptr(ShowerParticle(*copy[ix],itype,true));
fixColour(stemp);
_outgoingLines.insert(make_pair(new_ptr(ShowerProgenitor(original[ix],copy[ix],
stemp)),
stemp));
_forward.insert(stemp);
}
}
void ShowerTree::updateFinalStateShowerProduct(ShowerProgenitorPtr progenitor,
ShowerParticlePtr parent,
const ShowerParticleVector & children) {
assert(children.size()==2);
bool matches[2];
for(unsigned int ix=0;ix<2;++ix) {
matches[ix] = children[ix]->id()==progenitor->id();
}
ShowerParticlePtr newpart;
if(matches[0]&&matches[1]) {
if(parent->showerKinematics()->z()>0.5) newpart=children[0];
else newpart=children[1];
}
else if(matches[0]) newpart=children[0];
else if(matches[1]) newpart=children[1];
_outgoingLines[progenitor]=newpart;
}
void ShowerTree::updateInitialStateShowerProduct(ShowerProgenitorPtr progenitor,
ShowerParticlePtr newParent) {
_incomingLines[progenitor]=newParent;
}
void ShowerTree::insertHard(StepPtr pstep, bool ISR, bool) {
assert(_incomingLines.size()==2);
colourLines().clear();
map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator cit;
// construct the map of colour lines for hard process
for(cit=_incomingLines.begin();cit!=_incomingLines.end();++cit) {
if(!cit->first->perturbative()) continue;
mapColour(cit->first->original(),cit->first->copy());
}
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator cjt;
for(cjt=_outgoingLines.begin();cjt!=_outgoingLines.end();++cjt) {
if(!cjt->first->perturbative()) continue;
mapColour(cjt->first->original(),cjt->first->copy());
}
// initial-state radiation
if(ISR) {
for(cit=incomingLines().begin();cit!=incomingLines().end();++cit) {
ShowerParticlePtr init=(*cit).first->progenitor();
assert(init->thePEGBase());
PPtr original = (*cit).first->original();
if(original->parents().empty()) continue;
PPtr hadron= original->parents()[0];
assert(!original->children().empty());
PPtr copy=cit->first->copy();
ParticleVector intermediates=original->children();
for(unsigned int ix=0;ix<intermediates.size();++ix) {
init->abandonChild(intermediates[ix]);
copy->abandonChild(intermediates[ix]);
}
// if not from a matrix element correction
if(cit->first->perturbative()) {
// break mother/daugther relations
init->addChild(original);
hadron->abandonChild(original);
// if particle showers add shower
if(cit->first->hasEmitted()) {
addInitialStateShower(init,hadron,pstep,false);
}
// no showering for this particle
else {
updateColour(init,false);
hadron->addChild(init);
pstep->addIntermediate(init);
init->setLifeLength(Lorentz5Distance());
init->setVertex(LorentzPoint());
}
}
// from matrix element correction
else {
// break mother/daugther relations
hadron->abandonChild(original);
copy->addChild(original);
updateColour(copy,false);
init->addChild(copy);
pstep->addIntermediate(copy);
copy->setLifeLength(Lorentz5Distance());
copy->setVertex(LorentzPoint());
// if particle showers add shower
if(cit->first->hasEmitted()) {
addInitialStateShower(init,hadron,pstep,false);
}
// no showering for this particle
else {
updateColour(init,false);
hadron->addChild(init);
pstep->addIntermediate(init);
init->setLifeLength(Lorentz5Distance());
init->setVertex(LorentzPoint());
}
}
}
}
else {
for(cit=incomingLines().begin();cit!=incomingLines().end();++cit) {
ShowerParticlePtr init=(*cit).first->progenitor();
assert(init->thePEGBase());
PPtr original = (*cit).first->original();
if(original->parents().empty()) continue;
PPtr hadron= original->parents()[0];
assert(!original->children().empty());
PPtr copy=cit->first->copy();
ParticleVector intermediates=original->children();
for(unsigned int ix=0;ix<intermediates.size();++ix) {
init->abandonChild(intermediates[ix]);
copy->abandonChild(intermediates[ix]);
}
// break mother/daugther relations
init->addChild(original);
hadron->abandonChild(original);
// no showering for this particle
updateColour(init,false);
hadron->addChild(init);
pstep->addIntermediate(init);
init->setLifeLength(Lorentz5Distance());
init->setVertex(LorentzPoint());
original->setLifeLength(Lorentz5Distance());
original->setVertex(LorentzPoint());
}
}
// final-state radiation
for(cjt=outgoingLines().begin();cjt!=outgoingLines().end();++cjt) {
ShowerParticlePtr init=(*cjt).first->progenitor();
assert(init->thePEGBase());
// ZERO the distance of original
(*cjt).first->original()->setLifeLength(Lorentz5Distance());
(*cjt).first->original()->setVertex(LorentzPoint());
// if not from a matrix element correction
if(cjt->first->perturbative()) {
// register the shower particle as a
// copy of the one from the hard process
tParticleVector parents=init->parents();
for(unsigned int ix=0;ix<parents.size();++ix)
parents[ix]->abandonChild(init);
(*cjt).first->original()->addChild(init);
pstep->addDecayProduct(init);
}
// from a matrix element correction
else {
if(cjt->first->original()==_incoming.first||
cjt->first->original()==_incoming.second) {
updateColour((*cjt).first->copy(),false);
(*cjt).first->original()->parents()[0]->
addChild((*cjt).first->copy());
pstep->addDecayProduct((*cjt).first->copy());
(*cjt).first->copy()->addChild(init);
pstep->addDecayProduct(init);
}
else {
updateColour((*cjt).first->copy(),false);
(*cjt).first->original()->addChild((*cjt).first->copy());
pstep->addDecayProduct((*cjt).first->copy());
(*cjt).first->copy()->addChild(init);
pstep->addDecayProduct(init);
}
// ZERO the distance of copy ??? \todo change if add space-time
(*cjt).first->copy()->setLifeLength(Lorentz5Distance());
(*cjt).first->copy()->setVertex(LorentzPoint());
}
// copy so travels no distance
init->setLifeLength(Lorentz5Distance());
init->setVertex(init->parents()[0]->decayVertex());
// sort out the colour
updateColour(init,false);
// insert shower products
addFinalStateShower(init,pstep);
}
colourLines().clear();
}
void ShowerTree::addFinalStateShower(PPtr p, StepPtr s) {
// if endpoint assume doesn't travel
if(p->children().empty()) {
if(p->dataPtr()->stable()||ShowerHandler::currentHandler()->decaysInShower(p->id()))
p->setLifeLength(Lorentz5Distance());
else {
Length ctau = p->dataPtr()->generateLifeTime(p->mass(), p->dataPtr()->width());
Lorentz5Distance lifeLength(ctau,p->momentum().vect()*(ctau/p->mass()));
p->setLifeLength(lifeLength);
}
return;
}
// set the space-time distance
else {
p->setLifeLength(spaceTimeDistance(p));
}
ParticleVector::const_iterator child;
for(child=p->children().begin(); child != p->children().end(); ++child) {
updateColour(*child,false);
s->addDecayProduct(*child);
(**child).setVertex(p->decayVertex());
addFinalStateShower(*child,s);
}
}
void ShowerTree::addInitialStateShower(PPtr p, PPtr hadron,
StepPtr s, bool addchildren) {
// Each parton here should only have one parent
if(!p->parents().empty()) {
if(p->parents().size()!=1)
throw Exception() << "Particle must only have one parent in ShowerTree"
<< "::addInitialStateShower" << Exception::runerror;
// set the space-time distances
if(addchildren) {
p->setLifeLength(spaceTimeDistance(p));
p->setVertex(p->children()[0]->vertex()-p->lifeLength());
}
else {
p->setLifeLength(spaceTimeDistance(p));
p->setVertex(-p->lifeLength());
}
// recurse
addInitialStateShower(p->parents()[0],hadron,s);
}
else {
hadron->addChild(p);
s->addIntermediate(p);
p->setVertex(p->children()[0]->vertex());
p->setLifeLength(Lorentz5Distance());
}
updateColour(p,false);
// if not adding children return
if(!addchildren) return;
// add children
ParticleVector::const_iterator child;
for(child = p->children().begin(); child != p->children().end(); ++child) {
// if a final-state particle update the colour
ShowerParticlePtr schild =
dynamic_ptr_cast<ShowerParticlePtr>(*child);
(**child).setVertex(p->decayVertex());
if(schild && schild->isFinalState()) updateColour(*child,false);
// if there are grandchildren of p
if(!(*child)->children().empty()) {
// Add child as intermediate
s->addIntermediate(*child);
// If child is shower particle and final-state, add children
if(schild && schild->isFinalState()) addFinalStateShower(schild,s);
}
else
s->addDecayProduct(*child);
}
}
void ShowerTree::update(PerturbativeProcessPtr newProcess) {
// must be one incoming particle
assert(_incomingLines.size()==1);
colourLines().clear();
// copy the particles and isolate the colour
vector<PPtr> original,copy;
for(unsigned int ix=0;ix<newProcess->incoming().size();++ix) {
original.push_back(newProcess->incoming()[ix].first);
copy .push_back(new_ptr(Particle(*original.back())));
}
for(unsigned int ix=0;ix<newProcess->outgoing().size();++ix) {
original.push_back(newProcess->outgoing()[ix].first);
copy .push_back(new_ptr(Particle(*original.back())));
}
// isolate the colour
colourIsolate(original,copy);
// make the new progenitor
ShowerParticlePtr stemp=new_ptr(ShowerParticle(*copy[0],2,false));
fixColour(stemp);
ShowerProgenitorPtr newprog=new_ptr(ShowerProgenitor(original[0],copy[0],stemp));
_incomingLines.clear();
_incomingLines.insert(make_pair(newprog,stemp));
// create the children
assert(copy.size() == original.size());
for (unsigned int ix=newProcess->incoming().size();ix<original.size();++ix) {
ShowerParticlePtr stemp= new_ptr(ShowerParticle(*copy[ix],2,true));
fixColour(stemp);
_outgoingLines.insert(make_pair(new_ptr(ShowerProgenitor(original[ix],copy[ix],
stemp)),
stemp));
_forward.insert(stemp);
}
}
void ShowerTree::insertDecay(StepPtr pstep,bool ISR, bool) {
assert(_incomingLines.size()==1);
colourLines().clear();
// find final particle from previous tree
PPtr final;
if(_parent&&!_parent->_treelinks.empty())
final = _parent->_treelinks[this].second;
else
final=_incomingLines.begin()->first->original();
// construct the map of colour lines
PPtr copy=_incomingLines.begin()->first->copy();
mapColour(final,copy);
// now this is the ONE instance of the particle which should have a life length
// \todo change if space-time picture added
// set the lifelength, need this so that still in right direction after
// any ISR recoils
Length ctau = copy->lifeTime();
Lorentz5Distance lifeLength(ctau,final->momentum().vect()*(ctau/final->mass()));
final->setLifeLength(lifeLength);
// initial-state radiation
if(ISR&&!_incomingLines.begin()->first->progenitor()->children().empty()) {
ShowerParticlePtr init=_incomingLines.begin()->first->progenitor();
updateColour(init,false);
final->addChild(init);
pstep->addDecayProduct(init);
// just a copy doesn't travel
init->setLifeLength(Lorentz5Distance());
init->setVertex(final->decayVertex());
// insert shower products
addFinalStateShower(init,pstep);
// sort out colour
final=_incomingLines.begin()->second;
colourLines().clear();
mapColour(final,copy);
}
// get the decaying particles
// make the copy
tColinePair cline=make_pair(copy->colourLine(),copy->antiColourLine());
updateColour(copy,false);
// sort out sinks and sources if needed
if(cline.first) {
if(cline.first->sourceNeighbours().first) {
copy->colourLine()->setSourceNeighbours(cline.first->sourceNeighbours().first,
cline.first->sourceNeighbours().second);
}
else if (cline.first->sinkNeighbours().first) {
copy->colourLine()->setSinkNeighbours(cline.first->sinkNeighbours().first,
cline.first->sinkNeighbours().second);
}
}
if(cline.second) {
if(cline.second->sourceNeighbours().first) {
copy->antiColourLine()->setSourceNeighbours(cline.second->sourceNeighbours().first,
cline.second->sourceNeighbours().second);
}
else if (cline.second->sinkNeighbours().first) {
copy->antiColourLine()->setSinkNeighbours(cline.second->sinkNeighbours().first,
cline.second->sinkNeighbours().second);
}
}
// copy of the one from the hard process
tParticleVector dpar=copy->parents();
for(unsigned int ix=0;ix<dpar.size();++ix) dpar[ix]->abandonChild(copy);
final->addChild(copy);
pstep->addDecayProduct(copy);
// just a copy does not move
copy->setLifeLength(Lorentz5Distance());
copy->setVertex(final->decayVertex());
// final-state radiation
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator cit;
for(cit=outgoingLines().begin();cit!=outgoingLines().end();++cit) {
ShowerParticlePtr init=cit->first->progenitor();
// ZERO the distance
init->setLifeLength(Lorentz5Distance());
if(!init->thePEGBase())
throw Exception() << "Final-state particle must have a ThePEGBase"
<< " in ShowerTree::insertDecay()"
<< Exception::runerror;
// if not from matrix element correction
if(cit->first->perturbative()) {
// add the child
updateColour(cit->first->copy(),false);
PPtr orig=cit->first->original();
orig->setLifeLength(Lorentz5Distance());
orig->setVertex(copy->decayVertex());
copy->addChild(orig);
pstep->addDecayProduct(orig);
orig->addChild(cit->first->copy());
pstep->addDecayProduct(cit->first->copy());
// register the shower particle as a
// copy of the one from the hard process
tParticleVector parents=init->parents();
for(unsigned int ix=0;ix<parents.size();++ix)
{parents[ix]->abandonChild(init);}
(*cit).first->copy()->addChild(init);
pstep->addDecayProduct(init);
updateColour(init,false);
}
// from a matrix element correction
else {
if(copy->children().end()==
find(copy->children().begin(),copy->children().end(),
cit->first->original())) {
updateColour(cit->first->original(),false);
copy->addChild(cit->first->original());
pstep->addDecayProduct(cit->first->original());
}
updateColour(cit->first->copy(),false);
cit->first->original()->addChild(cit->first->copy());
pstep->addDecayProduct(cit->first->copy());
// register the shower particle as a
// copy of the one from the hard process
tParticleVector parents=init->parents();
for(unsigned int ix=0;ix<parents.size();++ix)
{parents[ix]->abandonChild(init);}
(*cit).first->copy()->addChild(init);
pstep->addDecayProduct(init);
updateColour(init,false);
}
// ZERO the distances as just copies
cit->first->copy()->setLifeLength(Lorentz5Distance());
init->setLifeLength(Lorentz5Distance());
cit->first->copy()->setVertex(copy->decayVertex());
init->setVertex(copy->decayVertex());
// insert shower products
addFinalStateShower(init,pstep);
}
colourLines().clear();
}
void ShowerTree::clear() {
// reset the has showered flag
_hasShowered=false;
// clear the colour map
colourLines().clear();
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator cit;
map<ShowerProgenitorPtr, ShowerParticlePtr>::const_iterator cjt;
// abandon the children of the outgoing particles
for(cit=_outgoingLines.begin();cit!=_outgoingLines.end();++cit) {
ShowerParticlePtr orig=cit->first->progenitor();
orig->set5Momentum(cit->first->copy()->momentum());
ParticleVector children=orig->children();
for(unsigned int ix=0;ix<children.size();++ix) orig->abandonChild(children[ix]);
_outgoingLines[cit->first]=orig;
cit->first->hasEmitted(false);
cit->first->reconstructed(ShowerProgenitor::notReconstructed);
}
// forward products
_forward.clear();
for(cit=_outgoingLines.begin();cit!=_outgoingLines.end();++cit)
_forward.insert(cit->first->progenitor());
// if a decay
if(!_wasHard) {
ShowerParticlePtr orig=_incomingLines.begin()->first->progenitor();
orig->set5Momentum(_incomingLines.begin()->first->copy()->momentum());
ParticleVector children=orig->children();
for(unsigned int ix=0;ix<children.size();++ix) orig->abandonChild(children[ix]);
_incomingLines.begin()->first->reconstructed(ShowerProgenitor::notReconstructed);
}
// if a hard process
else {
for(cjt=_incomingLines.begin();cjt!=_incomingLines.end();++cjt) {
tPPtr parent = cjt->first->original()->parents().empty() ?
tPPtr() : cjt->first->original()->parents()[0];
ShowerParticlePtr temp=
new_ptr(ShowerParticle(*cjt->first->copy(),
cjt->first->progenitor()->perturbative(),
cjt->first->progenitor()->isFinalState()));
fixColour(temp);
temp->x(cjt->first->progenitor()->x());
cjt->first->hasEmitted(false);
if(!(cjt->first->progenitor()==cjt->second)&&cjt->second&&parent)
parent->abandonChild(cjt->second);
cjt->first->progenitor(temp);
_incomingLines[cjt->first]=temp;
cjt->first->reconstructed(ShowerProgenitor::notReconstructed);
}
}
// reset the particles at the end of the shower
_backward.clear();
// if hard process backward products
if(_wasHard)
for(cjt=_incomingLines.begin();cjt!=_incomingLines.end();++cjt)
_backward.insert(cjt->first->progenitor());
clearTransforms();
}
void ShowerTree::resetShowerProducts() {
map<ShowerProgenitorPtr, ShowerParticlePtr>::const_iterator cit;
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator cjt;
_backward.clear();
_forward.clear();
for(cit=_incomingLines.begin();cit!=_incomingLines.end();++cit)
_backward.insert(cit->second);
for(cjt=_outgoingLines.begin();cjt!=_outgoingLines.end();++cjt)
_forward.insert(cjt->second);
}
void ShowerTree::updateAfterShower(ShowerDecayMap & decay) {
// update the links
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator mit;
map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::iterator tit;
for(tit=_treelinks.begin();tit!=_treelinks.end();++tit) {
if(tit->second.first) {
mit=_outgoingLines.find(tit->second.first);
if(mit!=_outgoingLines.end()) tit->second.second=mit->second;
}
}
// get the particles coming from those in the hard process
set<tShowerParticlePtr> hard;
for(mit=_outgoingLines.begin();mit!=_outgoingLines.end();++mit)
hard.insert(mit->second);
// find the shower particles which should be decayed in the
// shower but didn't come from the hard process
set<tShowerParticlePtr>::const_iterator cit;
for(cit=_forward.begin();cit!=_forward.end();++cit) {
if((ShowerHandler::currentHandler()->decaysInShower((**cit).id())&&
!(**cit).dataPtr()->stable()) &&
hard.find(*cit)==hard.end()) {
PerturbativeProcessPtr newProcess(new_ptr(PerturbativeProcess()));
newProcess->incoming().push_back(make_pair(*cit,PerturbativeProcessPtr()));
ShowerTreePtr newtree=new_ptr(ShowerTree(newProcess));
newtree->setParents();
newtree->_parent=this;
Energy width=(**cit).dataPtr()->generateWidth((**cit).mass());
decay.insert(make_pair(width,newtree));
_treelinks.insert(make_pair(newtree,
make_pair(tShowerProgenitorPtr(),*cit)));
}
}
}
void ShowerTree::addFinalStateBranching(ShowerParticlePtr parent,
const ShowerParticleVector & children) {
assert(children.size()==2);
_forward.erase(parent);
for(unsigned int ix=0; ix<children.size(); ++ix) {
_forward.insert(children[ix]);
}
}
void ShowerTree::addInitialStateBranching(ShowerParticlePtr oldParent,
ShowerParticlePtr newParent,
ShowerParticlePtr otherChild) {
_backward.erase(oldParent);
_backward.insert(newParent);
_forward.insert(otherChild);
}
void ShowerTree::setParents() {
// set the parent tree of the children
map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator tit;
for(tit=_treelinks.begin();tit!=_treelinks.end();++tit)
tit->first->_parent=this;
}
vector<ShowerProgenitorPtr> ShowerTree::extractProgenitors() {
// extract the particles from the ShowerTree
map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator mit;
vector<ShowerProgenitorPtr> ShowerHardJets;
for(mit=incomingLines().begin();mit!=incomingLines().end();++mit)
ShowerHardJets.push_back((*mit).first);
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator mjt;
for(mjt=outgoingLines().begin();mjt!=outgoingLines().end();++mjt)
ShowerHardJets.push_back((*mjt).first);
return ShowerHardJets;
}
void ShowerTree::transform(const LorentzRotation & boost, bool applyNow) {
if(applyNow) {
// now boost all the particles
map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator cit;
// incoming
for(cit=_incomingLines.begin();cit!=_incomingLines.end();++cit) {
cit->first->progenitor()->deepTransform(boost);
cit->first->copy()->deepTransform(boost);
}
// outgoing
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator cjt;
for(cjt=_outgoingLines.begin();cjt!=_outgoingLines.end();++cjt) {
cjt->first->progenitor()->deepTransform(boost);
cjt->first->copy()->deepTransform(boost);
}
}
else {
_transforms.transform(boost);
}
// child trees
for(map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator
tit=_treelinks.begin();tit!=_treelinks.end();++tit)
tit->first->transform(boost,applyNow);
}
void ShowerTree::applyTransforms() {
// now boost all the particles
map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator cit;
// incoming
for(cit=_incomingLines.begin();cit!=_incomingLines.end();++cit) {
cit->first->progenitor()->deepTransform(_transforms);
cit->first->copy()->deepTransform(_transforms);
}
// outgoing
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator cjt;
for(cjt=_outgoingLines.begin();cjt!=_outgoingLines.end();++cjt) {
cjt->first->progenitor()->deepTransform(_transforms);
cjt->first->copy()->deepTransform(_transforms);
}
// child trees
for(map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator
tit=_treelinks.begin();tit!=_treelinks.end();++tit)
tit->first->applyTransforms();
_transforms = LorentzRotation();
}
void ShowerTree::clearTransforms() {
_transforms = LorentzRotation();
// // child trees
// for(map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator
// tit=_treelinks.begin();tit!=_treelinks.end();++tit)
// tit->first->clearTransforms();
}
void ShowerTree::fixColour(tShowerParticlePtr part) {
if(!part->colourInfo()->colourLines().empty()) {
if(part->colourInfo()->colourLines().size()==1) {
ColinePtr line=part->colourLine();
if(line) {
line->removeColoured(part);
line->addColoured(part);
}
}
else {
Ptr<MultiColour>::pointer colour =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>(part->colourInfo());
vector<tcColinePtr> lines = colour->colourLines();
for(unsigned int ix=0;ix<lines.size();++ix) {
ColinePtr line = const_ptr_cast<ColinePtr>(lines[ix]);
if(line) {
line->removeColoured(part);
line->addColoured(part);
}
}
}
}
if(!part->colourInfo()->antiColourLines().empty()) {
if(part->colourInfo()->antiColourLines().size()==1) {
ColinePtr line=part->antiColourLine();
if(line) {
line->removeAntiColoured(part);
line->addAntiColoured(part);
}
}
else {
Ptr<MultiColour>::pointer colour =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>(part->colourInfo());
vector<tcColinePtr> lines = colour->antiColourLines();
for(unsigned int ix=0;ix<lines.size();++ix) {
ColinePtr line = const_ptr_cast<ColinePtr>(lines[ix]);
if(line) {
line->removeAntiColoured(part);
line->addAntiColoured(part);
}
}
}
}
}
vector<ShowerParticlePtr> ShowerTree::extractProgenitorParticles() {
vector<ShowerParticlePtr> particles;
// incoming particles
for(map<ShowerProgenitorPtr, ShowerParticlePtr>::const_iterator
cit=incomingLines().begin(); cit!=incomingLines().end();++cit)
particles.push_back(cit->first->progenitor());
// outgoing particles
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
cjt=outgoingLines().begin(); cjt!=outgoingLines().end();++cjt)
particles.push_back(cjt->first->progenitor());
return particles;
}
Lorentz5Distance ShowerTree::spaceTimeDistance(tPPtr particle) {
if(!_spaceTime) return Lorentz5Distance();
Energy2 q2 = particle->mass() > ZERO ? sqr(particle->mass()) : -sqr(particle->mass());
const tcPDPtr data = particle->dataPtr();
// calculate width imposing min value
Energy conMass = max(data->constituentMass(),200*MeV);
Energy width = max(data->generateWidth(particle->mass()),_vmin2/conMass);
// offshellness
Energy2 offShell = q2-sqr(data->constituentMass());
if(abs(offShell)<1e-10*GeV2) offShell = ZERO;
InvEnergy2 fact = UseRandom::rndExp(1./sqrt((sqr(offShell)+sqr(q2*width/conMass))));
Lorentz5Distance output = (hbarc*fact)*particle->momentum();
return output;
}
void ShowerTree::constructTrees(ShowerTreePtr & hardTree,
ShowerDecayMap & decayTrees,
PerturbativeProcessPtr hard,
DecayProcessMap decay) {
map<PerturbativeProcessPtr,ShowerTreePtr> treeMap;
// convert the hard process
if(hardTree) {
hardTree->update(hard);
}
else {
hardTree = new_ptr(ShowerTree(hard));
}
treeMap.insert(make_pair(hard,hardTree));
for(DecayProcessMap::const_iterator it=decay.begin();it!=decay.end();++it) {
ShowerTreePtr newTree = new_ptr(ShowerTree(it->second));
treeMap.insert(make_pair(it->second,newTree));
decayTrees.insert(make_pair(it->first,newTree));
}
// set up the links between the trees
for(map<PerturbativeProcessPtr,ShowerTreePtr>::const_iterator it=treeMap.begin();
it!=treeMap.end();++it) {
// links to daughter trees
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator mit;
for(mit=it->second->_outgoingLines.begin();
mit!=it->second->_outgoingLines.end();++mit) {
unsigned int iloc=0;
for(;iloc<it->first->outgoing().size();++iloc) {
if(it->first->outgoing()[iloc].first==mit->first->original())
break;
}
if(it->first->outgoing()[iloc].second)
it->second->_treelinks.insert(make_pair(treeMap[it->first->outgoing()[iloc].second],
make_pair(mit->first,mit->first->progenitor())));
}
// links to parent trees
if(it->first->incoming()[0].second) {
it->second->_parent = treeMap[it->first->incoming()[0].second];
}
}
}
namespace {
Lorentz5Momentum sumMomenta(tPPtr particle) {
if(particle->children().empty())
return particle->momentum();
Lorentz5Momentum output;
for(unsigned int ix=0;ix<particle->children().size();++ix) {
output += sumMomenta(particle->children()[ix]);
}
return output;
}
}
void ShowerTree::checkMomenta() {
vector<Lorentz5Momentum> pin;
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator it=_incomingLines.begin();
it!=_incomingLines.end();++it) {
if(isDecay()) {
tPPtr parent = it->first->progenitor();
pin.push_back(parent->momentum());
while(!parent->children().empty()) {
pin.back() -= sumMomenta(parent->children()[1]);
parent = parent->children()[0];
}
}
else {
tPPtr parent = it->second;
pin.push_back(parent->momentum());
while(!parent->children().empty()&&parent->children().size()==2) {
pin.back() -= sumMomenta(parent->children()[1]);
parent = parent->children()[0];
if(parent==it->first->progenitor()) break;
}
}
}
vector<Lorentz5Momentum> pout;
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator it= _outgoingLines.begin();
it!=_outgoingLines.end();++it) {
pout.push_back(sumMomenta(it->first->progenitor()));
}
Lorentz5Momentum psum;
for(unsigned int ix=0;ix< pin.size();++ix) {
CurrentGenerator::log() << "pin " << ix << pin[ix]/GeV << "\n";
psum +=pin[ix];
}
CurrentGenerator::log() << "In total " << psum/GeV << " " << psum.m()/GeV << "\n";
Lorentz5Momentum psum2;
for(unsigned int ix=0;ix< pout.size();++ix) {
CurrentGenerator::log() << "pout " << ix << pout[ix]/GeV << "\n";
psum2 +=pout[ix];
}
CurrentGenerator::log() << "Out total " << psum2/GeV << " " << psum2.m()/GeV << "\n";
CurrentGenerator::log() << "Total " << (psum-psum2)/GeV << "\n";
}
RealEmissionProcessPtr ShowerTree::perturbativeProcess() {
RealEmissionProcessPtr output(new_ptr(RealEmissionProcess()));
// add the incoming particles
unsigned int ix=0;
pair<double,double> x;
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator it=_incomingLines.begin();
it!=_incomingLines.end();++it) {
output->bornIncoming().push_back(it->first->progenitor());
if(!it->first->original()->parents().empty())
output->hadrons().push_back(it->first->original()->parents()[0]);
else
output->hadrons().push_back(it->first->progenitor());
if(ix==0) x.first = it->second->x();
else x.second = it->second->x();
++ix;
}
output->x(x);
// add the outgoing particles
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator it= _outgoingLines.begin();
it!=_outgoingLines.end();++it) {
output->bornOutgoing().push_back(it->first->progenitor());
}
return output;
}
-void ShowerTree::setVetoes(const map<ShowerInteraction::Type,Energy> & pTs,
+void ShowerTree::setVetoes(const map<ShowerInteraction,Energy> & pTs,
unsigned int type) {
if(type==1||type==3) {
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator it=_incomingLines.begin();
it!=_incomingLines.end();++it) {
- for(map<ShowerInteraction::Type,Energy>::const_iterator jt=pTs.begin();jt!=pTs.end();++jt)
+ for(map<ShowerInteraction,Energy>::const_iterator jt=pTs.begin();jt!=pTs.end();++jt)
it->first->maximumpT(jt->second,jt->first);
}
}
if(type==2||type==3) {
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator it= _outgoingLines.begin();
it!=_outgoingLines.end();++it) {
- for(map<ShowerInteraction::Type,Energy>::const_iterator jt=pTs.begin();jt!=pTs.end();++jt)
+ for(map<ShowerInteraction,Energy>::const_iterator jt=pTs.begin();jt!=pTs.end();++jt)
it->first->maximumpT(jt->second,jt->first);
}
}
}
diff --git a/Shower/QTilde/Base/ShowerTree.h b/Shower/QTilde/Base/ShowerTree.h
--- a/Shower/QTilde/Base/ShowerTree.h
+++ b/Shower/QTilde/Base/ShowerTree.h
@@ -1,414 +1,414 @@
// -*- C++ -*-
//
// ShowerTree.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_ShowerTree_H
#define HERWIG_ShowerTree_H
#include "ThePEG/Config/ThePEG.h"
#include "Herwig/Shower/ShowerHandler.fh"
#include "Herwig/Shower/PerturbativeProcess.h"
#include "Herwig/Shower/RealEmissionProcess.h"
#include "Herwig/Shower/ShowerEventRecord.h"
#include "Herwig/Shower/QTilde/ShowerConfig.h"
#include "Herwig/Shower/QTilde/Base/ShowerParticle.h"
#include "ShowerProgenitor.h"
#include "ThePEG/EventRecord/Step.h"
#include <cassert>
#include "ShowerTree.fh"
namespace Herwig {
/**
* Typedef for map of ShowerTrees for decays
*/
typedef multimap<Energy,ShowerTreePtr,std::greater<Energy> > ShowerDecayMap;
using namespace ThePEG;
/** \ingroup Shower
*
* The ShowerTree class stores the basic information needed for
* each hard interaction, either a scattering process or decay, which
* needs to be showered.
*
*/
class ShowerTree : public ShowerEventRecord {
friend class ShowerHandler;
public:
/**
* Constructor from a perturbative process
* @param process The perturbative process
*/
ShowerTree(PerturbativeProcessPtr process);
/**
* Calculate the space-time displacement
* @param particle The particle for which to calculate the displacement
*/
static Lorentz5Distance spaceTimeDistance(tPPtr particle);
/**
* Construct the trees from the hard process
* @param hardTree The output ShowerTree for the hard process
* @param decayTrees The output ShowerTrees for any decays.
* @param hard The output ShowerTree for the hard process
* @param decay The output ShowerTrees for any decays.
*/
static void constructTrees(ShowerTreePtr & hardTree,
ShowerDecayMap & decayTrees,
PerturbativeProcessPtr hard,
DecayProcessMap decay);
public:
/**
* Insert the tree into the event record
* @param pstep The step into which the particles should be inserted
* @param ISR Whether or not ISR is switched on
* @param FSR Whether or not FSR is switched on
*/
void fillEventRecord(StepPtr pstep,bool ISR,bool FSR) {
if(_wasHard)
insertHard (pstep,ISR,FSR);
else
insertDecay(pstep,ISR,FSR);
}
/**
* Set the parent tree to this tree for trees which come from this one.
* This needs to be run after the constructor.
*/
void setParents();
/**
* Access methods for the type of interaction
*/
//@{
/**
* Whether or not this is a scattering process
*/
bool isHard() const { return _wasHard; }
/**
* Whether or not this is a decay.
*/
bool isDecay() const { return !_wasHard; }
//@}
/**
* Flags relating to the application of the hard matrix element correction
*/
//@{
/**
* Was the hard matrix element correction applied
*/
bool hardMatrixElementCorrection() const { return _hardMECorrection; }
/**
* Set whether or not the hard matrix element correction was applied
*/
void hardMatrixElementCorrection(bool in) { _hardMECorrection=in; }
//@}
/**
* Get the incoming shower particles
*/
map<ShowerProgenitorPtr,ShowerParticlePtr> & incomingLines() {
return _incomingLines;
}
/**
* Get the outgoing shower particles
*/
map<ShowerProgenitorPtr,tShowerParticlePtr> & outgoingLines() {
return _outgoingLines;
}
/**
* Update the shower product for a final-state particle
*/
void updateFinalStateShowerProduct(ShowerProgenitorPtr progenitor,
ShowerParticlePtr parent,
const ShowerParticleVector & children);
/**
* Update the shower product for an initial-state particle
*/
void updateInitialStateShowerProduct(ShowerProgenitorPtr progenitor,
ShowerParticlePtr newParent);
/**
* Get the current final shower product for a final-state particle
*/
tShowerParticlePtr getFinalStateShowerProduct(ShowerProgenitorPtr progenitor) {
return _outgoingLines.find(progenitor)==_outgoingLines.end()
? tShowerParticlePtr() : _outgoingLines[progenitor];
}
/**
* Add a final-state branching. This method removes the parent of the branching
* from the list of particles at the end of the shower and inserts the children
* @param parent The parent for the branching
* @param children The outgoing particles in the branching
*/
void addFinalStateBranching(ShowerParticlePtr parent,
const ShowerParticleVector & children);
/**
* Add an initial-state branching. This method removes the oldParent of the
* branching and inserts the result of the backward evolution and the
* outgoing particle into the relevant lists.
* @param oldParent The particle being backward evolved
* @param newParent The initial-state particle resulting from the backward evolution
* @param otherChild The final-state particle produced in the evolution.
*/
void addInitialStateBranching(ShowerParticlePtr oldParent,
ShowerParticlePtr newParent,
ShowerParticlePtr otherChild);
// /**
// * Member called at the end of the shower of a tree to perform a number of
// * updates.
// * @param decay The map of widths and ShowerTrees for the decays so that
// * any unstable decay products can be added.
// */
void updateAfterShower(ShowerDecayMap & decay);
/**
* Access and set the flag for whether this tree has been showered
*/
//@{
/**
* Access the flag
*/
bool hasShowered() const { return _hasShowered; }
/**
* Set the flag
*/
void hasShowered(bool in) { _hasShowered=in; }
//@}
/**
* Access the parent tree
*/
ShowerTreePtr parent() const { return _parent; }
/**
* Clear all the shower products so that the event can be reshowered
* if the first attempt fail
*/
void clear();
/**
* Reset the particles resulting from the shower to those which started
* the shower
*/
void resetShowerProducts();
/**
* Set maximum Emission scales
*/
- void setVetoes(const map<ShowerInteraction::Type,Energy> & pTs,
+ void setVetoes(const map<ShowerInteraction,Energy> & pTs,
unsigned int type);
/**
* Extract the progenitors for the reconstruction
*/
vector<ShowerProgenitorPtr> extractProgenitors();
/**
* Access to the outgoing particles
*/
const set<tShowerParticlePtr> & forwardParticles() const { return _forward; }
/**
* Map of particles in this Tree which are the initial particles in other
* trees
*/
const map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> > &
treelinks() const {return _treelinks;}
/**
* Update the link between shower particle and tree
*/
void updateLink(tShowerTreePtr tree,
pair<tShowerProgenitorPtr,tShowerParticlePtr> in) {
_treelinks[tree] = in;
}
/**
* Transform the tree
*/
void transform(const LorentzRotation & rot, bool applyNow);
/**
* Apply any postphoned transformations
*/
void applyTransforms();
/**
* Clear any postphoned transformations
*/
void clearTransforms();
/**
* Transform which needs to be applied
*/
const LorentzRotation & transform() {return _transforms;}
/**
* Get all the progenitors
*/
vector<ShowerParticlePtr> extractProgenitorParticles();
/**
* Check the momentum conservation in the tree
*/
void checkMomenta();
/**
* Update tree after the parent has been decayed.
*/
void update(PerturbativeProcessPtr newProcess);
/**
* The perturbative process
*/
RealEmissionProcessPtr perturbativeProcess();
protected:
/**
* Functions to add the shower to the event record.
*/
//@{
/**
* Insert a hard process
* @param pstep The step into which the particles should be inserted
* @param ISR Whether or not ISR is switched on
* @param FSR Whether or not FSR is switched on
*/
void insertHard(StepPtr pstep,bool ISR,bool FSR);
/**
* Insert a decay process
* @param pstep The step into which the particles should be inserted
* @param ISR Whether or not ISR is switched on
* @param FSR Whether or not FSR is switched on
*/
void insertDecay(StepPtr pstep,bool ISR,bool FSR);
/**
* Recursively add the final-state shower from the particle to the event record.
* @param particle The final-state particle
* @param step The step
*/
void addFinalStateShower(PPtr particle, StepPtr step);
/**
* Add the initial-state shwoer from the particle to the step
* @param particle The final-state particle
* @param hadron The incoming hadron
* @param step The step
* @param addchildren Add the children of the particle
*/
void addInitialStateShower(PPtr particle, PPtr hadron,
StepPtr step, bool addchildren=true);
//@}
/**
* After the creatation of a ShowerParticle make sure it is properly attached
* to its ColourLine
* @param part The particle
*/
void fixColour(tShowerParticlePtr part);
private:
/**
* Incoming partons for the hard process
*/
PPair _incoming;
/**
* The incoming ShowerParticles connected to the interaction
* as the index of a map with the particle the shower backward evolves
* them to as the value
*/
map<ShowerProgenitorPtr,ShowerParticlePtr> _incomingLines;
/**
* The outgoing ShowerParticles connected to the interaction
* as the index of a map with the particle the shower
* evolves them to as the value
*/
map<ShowerProgenitorPtr,tShowerParticlePtr> _outgoingLines;
/**
* The outgoing ShowerParticles at the end of the final-state shower
*/
set<tShowerParticlePtr> _forward;
/**
* The incoming ShowerParticles at the end of the initial-state shower
*/
set<tShowerParticlePtr> _backward;
/**
* Was the hard matrix element correction applied
*/
bool _hardMECorrection;
/**
* Was this a scattering process or a decay
*/
bool _wasHard;
/**
* Map of particles in this Tree which are the initial particles in other
* trees
*/
map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> > _treelinks;
/**
* The parent tree
*/
tShowerTreePtr _parent;
/**
* Has this tree showered
*/
bool _hasShowered;
/**
* The transforms which still need to be applied
*/
LorentzRotation _transforms;
private:
/**
* Whether or not to include space-time distances
*/
static bool _spaceTime;
/**
* Minimum virtuality for the space-time model
*/
static Energy2 _vmin2;
};
}
#endif
diff --git a/Shower/QTilde/Base/SudakovFormFactor.h b/Shower/QTilde/Base/SudakovFormFactor.h
--- a/Shower/QTilde/Base/SudakovFormFactor.h
+++ b/Shower/QTilde/Base/SudakovFormFactor.h
@@ -1,723 +1,723 @@
// -*- C++ -*-
//
// SudakovFormFactor.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_SudakovFormFactor_H
#define HERWIG_SudakovFormFactor_H
//
// This is the declaration of the SudakovFormFactor class.
//
#include "ThePEG/Interface/Interfaced.h"
#include "Herwig/Shower/QTilde/SplittingFunctions/SplittingFunction.h"
#include "Herwig/Shower/QTilde/Couplings/ShowerAlpha.h"
#include "Herwig/Shower/QTilde/SplittingFunctions/SplittingGenerator.fh"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/PDF/BeamParticleData.h"
#include "ThePEG/EventRecord/RhoDMatrix.h"
#include "ThePEG/EventRecord/SpinInfo.h"
#include "ShowerKinematics.fh"
#include "SudakovFormFactor.fh"
namespace Herwig {
using namespace ThePEG;
/**
* A typedef for the BeamParticleData
*/
typedef Ptr<BeamParticleData>::transient_const_pointer tcBeamPtr;
/** \ingroup Shower
*
* This is the definition of the Sudakov form factor class. In general this
* is the base class for the implementation of Sudakov form factors in Herwig.
* The methods generateNextTimeBranching(), generateNextDecayBranching() and
* generateNextSpaceBranching need to be implemented in classes inheriting from this
* one.
*
* In addition a number of methods are implemented to assist with the calculation
* of the form factor using the veto algorithm in classes inheriting from this one.
*
* In general the Sudakov form-factor, for final-state radiation, is given
* by
* \f[\Delta_{ba}(\tilde{q}_{i+1},\tilde{q}_i)=
* \exp\left\{
* -\int^{\tilde{q}^2_i}_{\tilde{q}^2_{i+1}}
* \frac{{\rm d}\tilde{q}^2}{\tilde{q}^2}
* \int\frac{\alpha_S(z,\tilde{q})}{2\pi}
* P_{ba}(z,\tilde{q})\Theta(p_T)
* \right\}.
* \f]
* We can solve this to obtain the next value of the scale \f$\tilde{q}_{i+1}\f$
* given the previous value \f$\tilde{q}_i\f$
* in the following way. First we obtain a simplified form of the integrand
* which is greater than or equal to the true integrand for all values of
* \f$\tilde{q}\f$.
*
* In practice it is easiest to obtain this over estimate in pieces. The ShowerAlpha
* object contains an over estimate for \f$\alpha_S\f$, the splitting function
* contains both an over estimate of the spltting function and its integral
* which is needed to compute the over estimate of the \f$\tilde{q}\f$ integrand,
* together with an over estimate of the limit of the \f$z\f$ integral.
*
* This gives an overestimate of the integrand
* \f[g(\tilde{q}^2) = \frac{c}{\tilde{q}^2}, \f]
* where because the over estimates are chosen to be independent of \f$\tilde{q}\f$ the
* parameter
* \f[c = \frac{\alpha_{\rm over}}{2\pi}\int^{z_1}_{z_0}P_{\rm over}(z),\f]
* is a constant independent of \f$\tilde{q}\f$.
*
* The guesst() member can then be used to generate generate the value of
* \f$\tilde{q}^2\f$ according to this result. This is done by solving the Sudakov
* form factor, with the over estimates, is equal to a random number
* \f$r\f$ in the interval \f$[0,1]\f$. This gives
* \f[\tilde{q}^2_{i+1}=G^{-1}\left[G(\tilde{q}^2_i)+\ln r\right],\f]
* where \f$G(\tilde{q}^2)=c\ln(\tilde{q}^2)\f$ is the infinite integral
* of \f$g(\tilde{q}^2)\f$ and \f$G^{-1}(x)=\exp\left(\frac{x}c\right)\f$
* is its inverse.
* It this case we therefore obtain
* \f[\tilde{q}^2_{i+1}=\tilde{q}^2_ir^{\frac1c}.\f]
* The value of \f$z\f$ can then be calculated in a similar way
* \f[z = I^{-1}\left[I(z_0)+r\left(I(z_1)-I(z_0)\right)\right],\f]
* using the guessz() member,
* where \f$I=\int P(z){\rm d}z\f$ and \f$I^{-1}\f$ is its inverse.
*
* The veto algorithm then uses rejection using the ratio of the
* true value to the overestimated one to obtain the original distribution.
* This is accomplished using the
* - alphaSVeto() member for the \f$\alpha_S\f$ veto
* - SplittingFnVeto() member for the veto on the value of the splitting function.
* in general there must also be a chech that the emission is in the allowed
* phase space but this is left to the inheriting classes as it will depend
* on the ordering variable.
*
* The Sudakov form factor for the initial-scale shower is different because
* it must include the PDF which guides the backward evolution.
* It is given by
* \f[\Delta_{ba}(\tilde{q}_{i+1},\tilde{q}_i)=
* \exp\left\{
* -\int^{\tilde{q}^2_i}_{\tilde{q}^2_{i+1}}
* \frac{{\rm d}\tilde{q}^2}{\tilde{q}^2}
* \int\frac{\alpha_S(z,\tilde{q})}{2\pi}
* P_{ba}(z,\tilde{q})\frac{x'f_a(\frac{x}z,\tilde{q}^2)}{xf_b(x,\tilde{q^2})}
* \right\},
* \f]
* where \f$x\f$ is the fraction of the beam momentum the parton \f$b\f$ had before
* the backward evolution.
* This can be solve in the same way as for the final-state branching but the constant
* becomes
* \f[c = \frac{\alpha_{\rm over}}{2\pi}\int^{z_1}_{z_0}P_{\rm over}(z)PDF_{\rm max},\f]
* where
* \f[PDF_{\rm max}=\max\frac{x'f_a(\frac{x}z,\tilde{q}^2)}{xf_b(x,\tilde{q^2})},\f]
* which can be set using an interface.
* In addition the PDFVeto() member then is needed to implement the relevant veto.
*
* @see SplittingGenerator
* @see SplittingFunction
* @see ShowerAlpha
* @see \ref SudakovFormFactorInterfaces "The interfaces"
* defined for SudakovFormFactor.
*/
class SudakovFormFactor: public Interfaced {
/**
* The SplittingGenerator is a friend to insert the particles in the
* branchings at initialisation
*/
friend class SplittingGenerator;
public:
/**
* The default constructor.
*/
SudakovFormFactor() : pdfmax_(35.0), pdffactor_(0),
cutOffOption_(0), a_(0.3), b_(2.3), c_(0.3*GeV),
kinCutoffScale_( 2.3*GeV ), vgcut_(0.85*GeV),
vqcut_(0.85*GeV), pTmin_(1.*GeV), pT2min_(ZERO),
z_( 0.0 ),phi_(0.0), pT_(),
theFactorizationScaleFactor(1.0),
theRenormalizationScaleFactor(1.0) {}
/**
* Members to generate the scale of the next branching
*/
//@{
/**
* Return the scale of the next time-like branching. If there is no
* branching then it returns ZERO.
* @param startingScale starting scale for the evolution
* @param ids The PDG codes of the particles in the splitting
* @param enhance The radiation enhancement factor
* defined.
*/
virtual ShoKinPtr generateNextTimeBranching(const Energy startingScale,
const IdList &ids,
const RhoDMatrix & rho,
double enhance, double detuning,
Energy2 maxQ2)=0;
/**
* Return the scale of the next space-like decay branching. If there is no
* branching then it returns ZERO.
* @param startingScale starting scale for the evolution
* @param stoppingScale stopping scale for the evolution
* @param minmass The minimum mass allowed for the spake-like particle.
* @param ids The PDG codes of the particles in the splitting
* defined.
* @param enhance The radiation enhancement factor
*/
virtual ShoKinPtr generateNextDecayBranching(const Energy startingScale,
const Energy stoppingScale,
const Energy minmass,
const IdList &ids,
const RhoDMatrix & rho,
double enhance,
double detuning)=0;
/**
* Return the scale of the next space-like branching. If there is no
* branching then it returns ZERO.
* @param startingScale starting scale for the evolution
* @param ids The PDG codes of the particles in the splitting
* @param x The fraction of the beam momentum
* defined.
* @param beam The beam particle
* @param enhance The radiation enhancement factor
*/
virtual ShoKinPtr generateNextSpaceBranching(const Energy startingScale,
const IdList &ids,double x,
const RhoDMatrix & rho,
double enhance,
tcBeamPtr beam,
double detuning)=0;
//@}
/**
* Generate the azimuthal angle of the branching for forward evolution
* @param particle The branching particle
* @param ids The PDG codes of the particles in the branchings
* @param The Shower kinematics
*/
virtual double generatePhiForward(ShowerParticle & particle,const IdList & ids,
ShoKinPtr kinematics,
const RhoDMatrix & rho)=0;
/**
* Generate the azimuthal angle of the branching for backward evolution
* @param particle The branching particle
* @param ids The PDG codes of the particles in the branchings
* @param The Shower kinematics
*/
virtual double generatePhiBackward(ShowerParticle & particle,const IdList & ids,
ShoKinPtr kinematics,
const RhoDMatrix & rho)=0;
/**
* Generate the azimuthal angle of the branching for ISR in decays
* @param particle The branching particle
* @param ids The PDG codes of the particles in the branchings
* @param The Shower kinematics
*/
virtual double generatePhiDecay(ShowerParticle & particle,const IdList & ids,
ShoKinPtr kinematics,
const RhoDMatrix & rho)=0;
/**
* Methods to provide public access to the private member variables
*/
//@{
/**
* Return the pointer to the SplittingFunction object.
*/
tSplittingFnPtr splittingFn() const { return splittingFn_; }
/**
* Return the pointer to the ShowerAlpha object.
*/
tShowerAlphaPtr alpha() const { return alpha_; }
/**
* The type of interaction
*/
- inline ShowerInteraction::Type interactionType() const
+ inline ShowerInteraction interactionType() const
{return splittingFn_->interactionType();}
//@}
public:
/**
* Methods to access the kinematic variables for the branching
*/
//@{
/**
* The energy fraction
*/
double z() const { return z_; }
/**
* The azimuthal angle
*/
double phi() const { return phi_; }
/**
* The transverse momentum
*/
Energy pT() const { return pT_; }
//@}
/**
* Access the maximum weight for the PDF veto
*/
double pdfMax() const { return pdfmax_;}
/**
* Method to return the evolution scale given the
* transverse momentum, \f$p_T\f$ and \f$z\f$.
*/
virtual Energy calculateScale(double z, Energy pt, IdList ids,unsigned int iopt)=0;
/**
* Method to create the ShowerKinematics object for a final-state branching
*/
virtual ShoKinPtr createFinalStateBranching(Energy scale,double z,
double phi, Energy pt)=0;
/**
* Method to create the ShowerKinematics object for an initial-state branching
*/
virtual ShoKinPtr createInitialStateBranching(Energy scale,double z,
double phi, Energy pt)=0;
/**
* Method to create the ShowerKinematics object for a decay branching
*/
virtual ShoKinPtr createDecayBranching(Energy scale,double z,
double phi, Energy pt)=0;
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:
/**
* Methods to implement the veto algorithm to generate the scale of
* the next branching
*/
//@{
/**
* Value of the energy fraction for the veto algorithm
* @param iopt The option for calculating z
* @param ids The PDG codes of the particles in the splitting
* - 0 is final-state
* - 1 is initial-state for the hard process
* - 2 is initial-state for particle decays
*/
double guessz (unsigned int iopt, const IdList &ids) const;
/**
* Value of the scale for the veto algorithm
* @param t1 The starting valoe of the scale
* @param iopt The option for calculating t
* @param ids The PDG codes of the particles in the splitting
* - 0 is final-state
* - 1 is initial-state for the hard process
* - 2 is initial-state for particle decays
* @param enhance The radiation enhancement factor
* @param identical Whether or not the outgoing particles are identical
*/
Energy2 guesst (Energy2 t1,unsigned int iopt, const IdList &ids,
double enhance, bool identical, double detune) const;
/**
* Veto on the PDF for the initial-state shower
* @param t The scale
* @param x The fraction of the beam momentum
* @param parton0 Pointer to the particleData for the
* new parent (this is the particle we evolved back to)
* @param parton1 Pointer to the particleData for the
* original particle
* @param beam The BeamParticleData object
*/
bool PDFVeto(const Energy2 t, const double x,
const tcPDPtr parton0, const tcPDPtr parton1,
tcBeamPtr beam) const;
/**
* The PDF veto ratio
*/
double PDFVetoRatio(const Energy2 t, const double x,
const tcPDPtr parton0, const tcPDPtr parton1,
tcBeamPtr beam,double factor) const;
/**
* The veto on the splitting function.
* @param t The scale
* @param ids The PDG codes of the particles in the splitting
* @param mass Whether or not to use the massive splitting functions
* @return true if vetoed
*/
bool SplittingFnVeto(const Energy2 t,
const IdList &ids,
const bool mass,
const RhoDMatrix & rho,
double detune) const {
return UseRandom::rnd()>SplittingFnVetoRatio(t,ids,mass,rho,detune);
}
/**
* The Splitting function veto ratio
*/
double SplittingFnVetoRatio(const Energy2 t,
const IdList &ids,
const bool mass,
const RhoDMatrix & rho,
double detune) const {
return splittingFn_->ratioP(z_, t, ids,mass,rho)/detune;
}
/**
* The veto on the coupling constant
* @param pt2 The value of ther transverse momentum squared, \f$p_T^2\f$.
* @return true if vetoed
*/
bool alphaSVeto(Energy2 pt2) const;
/**
* The alpha S veto ratio
*/
double alphaSVetoRatio(Energy2 pt2,double factor) const;
//@}
/**
* Methods to set the kinematic variables for the branching
*/
//@{
/**
* The energy fraction
*/
void z(double in) { z_=in; }
/**
* The azimuthal angle
*/
void phi(double in) { phi_=in; }
/**
* The transverse momentum
*/
void pT(Energy in) { pT_=in; }
//@}
/**
* Set/Get the limits on the energy fraction for the splitting
*/
//@{
/**
* Get the limits
*/
pair<double,double> zLimits() const { return zlimits_;}
/**
* Set the limits
*/
void zLimits(pair<double,double> in) { zlimits_=in; }
//@}
/**
* Set the particles in the splittings
*/
void addSplitting(const IdList &);
/**
* Delete the particles in the splittings
*/
void removeSplitting(const IdList &);
/**
* Access the potential branchings
*/
const vector<IdList> & particles() const { return particles_; }
public:
/**
* @name Methods for the cut-off
*/
//@{
/**
* The option being used
*/
unsigned int cutOffOption() const { return cutOffOption_; }
/**
* The kinematic scale
*/
Energy kinScale() const {return kinCutoffScale_;}
/**
* The virtuality cut-off on the gluon \f$Q_g=\frac{\delta-am_q}{b}\f$
* @param scale The scale \f$\delta\f$
* @param mq The quark mass \f$m_q\f$.
*/
Energy kinematicCutOff(Energy scale, Energy mq) const
{return max((scale -a_*mq)/b_,c_);}
/**
* The virtualilty cut-off for gluons
*/
Energy vgCut() const { return vgcut_; }
/**
* The virtuality cut-off for everything else
*/
Energy vqCut() const { return vqcut_; }
/**
* The minimum \f$p_T\f$ for the branching
*/
Energy pTmin() const { return pTmin_; }
/**
* The square of the minimum \f$p_T\f$
*/
Energy2 pT2min() const { return pT2min_; }
/**
* Calculate the virtual masses for a branchings
*/
const vector<Energy> & virtualMasses(const IdList & ids);
//@}
/**
* Set the PDF
*/
void setPDF(tcPDFPtr pdf, Energy scale) {
pdf_ = pdf;
freeze_ = scale;
}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
SudakovFormFactor & operator=(const SudakovFormFactor &);
private:
/**
* Pointer to the splitting function for this Sudakov form factor
*/
SplittingFnPtr splittingFn_;
/**
* Pointer to the coupling for this Sudakov form factor
*/
ShowerAlphaPtr alpha_;
/**
* Maximum value of the PDF weight
*/
double pdfmax_;
/**
* List of the particles this Sudakov is used for to aid in setting up
* interpolation tables if needed
*/
vector<IdList> particles_;
/**
* Option for the inclusion of a factor \f$1/(1-z)\f$ in the PDF estimate
*/
unsigned pdffactor_;
private:
/**
* Option for the type of cut-off to be applied
*/
unsigned int cutOffOption_;
/**
* Parameters for the default Herwig cut-off option, i.e. the parameters for
* the \f$Q_g=\max(\frac{\delta-am_q}{b},c)\f$ kinematic cut-off
*/
//@{
/**
* The \f$a\f$ parameter
*/
double a_;
/**
* The \f$b\f$ parameter
*/
double b_;
/**
* The \f$c\f$ parameter
*/
Energy c_;
/**
* Kinematic cutoff used in the parton shower phase space.
*/
Energy kinCutoffScale_;
//@}
/**
* Parameters for the FORTRAN-like cut-off
*/
//@{
/**
* The virtualilty cut-off for gluons
*/
Energy vgcut_;
/**
* The virtuality cut-off for everything else
*/
Energy vqcut_;
//@}
/**
* Parameters for the \f$p_T\f$ cut-off
*/
//@{
/**
* The minimum \f$p_T\f$ for the branching
*/
Energy pTmin_;
/**
* The square of the minimum \f$p_T\f$
*/
Energy2 pT2min_;
//@}
private:
/**
* Member variables to keep the shower kinematics information
* generated by a call to generateNextTimeBranching or generateNextSpaceBranching
*/
//@{
/**
* The energy fraction
*/
double z_;
/**
* The azimuthal angle
*/
double phi_;
/**
* The transverse momentum
*/
Energy pT_;
//@}
/**
* The limits of \f$z\f$ in the splitting
*/
pair<double,double> zlimits_;
/**
* Stuff for the PDFs
*/
//@{
/**
* PDf
*/
tcPDFPtr pdf_;
/**
* Freezing scale
*/
Energy freeze_;
//@}
public:
/**
* Get the factorization scale factor
*/
double factorizationScaleFactor() const { return theFactorizationScaleFactor; }
/**
* Set the factorization scale factor
*/
void factorizationScaleFactor(double f) { theFactorizationScaleFactor = f; }
/**
* Get the renormalization scale factor
*/
double renormalizationScaleFactor() const { return theRenormalizationScaleFactor; }
/**
* Set the renormalization scale factor
*/
void renormalizationScaleFactor(double f) { theRenormalizationScaleFactor = f; }
private:
/**
* The factorization scale factor.
*/
double theFactorizationScaleFactor;
/**
* The renormalization scale factor.
*/
double theRenormalizationScaleFactor;
};
}
#endif /* HERWIG_SudakovFormFactor_H */
diff --git a/Shower/QTilde/Default/Decay_QTildeShowerKinematics1to2.cc b/Shower/QTilde/Default/Decay_QTildeShowerKinematics1to2.cc
--- a/Shower/QTilde/Default/Decay_QTildeShowerKinematics1to2.cc
+++ b/Shower/QTilde/Default/Decay_QTildeShowerKinematics1to2.cc
@@ -1,113 +1,113 @@
// -*- C++ -*-
//
// Decay_QTildeShowerKinematics1to2.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 Decay_QTildeShowerKinematics1to2 class.
//
#include "Decay_QTildeShowerKinematics1to2.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "Herwig/Shower/QTilde/SplittingFunctions/SplittingFunction.h"
#include "Herwig/Shower/QTilde/Base/ShowerParticle.h"
#include <cassert>
#include "Herwig/Shower/ShowerHandler.h"
#include "Herwig/Shower/QTilde/Base/ShowerVertex.h"
using namespace Herwig;
void Decay_QTildeShowerKinematics1to2::
updateChildren(const tShowerParticlePtr parent,
const ShowerParticleVector & children,
- ShowerPartnerType::Type partnerType,
+ ShowerPartnerType partnerType,
bool massVeto) const {
assert(children.size() == 2);
// calculate the scales
splittingFn()->evaluateDecayScales(partnerType,scale(),z(),parent,
children[0],children[1]);
// set the maximum virtual masses
IdList ids(3);
ids[0] = parent->dataPtr();
ids[1] = children[0]->dataPtr();
ids[2] = children[1]->dataPtr();
const vector<Energy> & virtualMasses = SudakovFormFactor()->virtualMasses(ids);
Energy2 q2 = sqr(virtualMasses[0])-(1.-z())*sqr(scale());
children[0]->virtualMass(sqrt(q2));
if(massVeto) {
children[1]->scales().Max_Q2 = (1.-z())/z()*(z()*sqr(virtualMasses[0])-q2);
}
// determine alphas of children according to interpretation of z
const ShowerParticle::Parameters & params = parent->showerParameters();
ShowerParticle::Parameters & child0 = children[0]->showerParameters();
ShowerParticle::Parameters & child1 = children[1]->showerParameters();
child0.alpha = z() * params.alpha;
child1.alpha = (1.-z()) * params.alpha;
child0.ptx = pT() * cos(phi()) + z()* params.ptx;
child0.pty = pT() * sin(phi()) + z()* params.pty;
child0.pt = sqrt( sqr(child0.ptx) + sqr(child0.pty) );
child1.ptx = -pT() * cos(phi()) + (1.-z()) * params.ptx;
child1.pty = -pT() * sin(phi()) + (1.-z()) * params.pty;
child1.pt = sqrt( sqr(child1.ptx) + sqr(child1.pty) );
// set up the colour connections
splittingFn()->colourConnection(parent,children[0],children[1],partnerType,false);
// make the products children of the parent
parent->addChild(children[0]);
parent->addChild(children[1]);
// set the momenta of the children
for(ShowerParticleVector::const_iterator pit=children.begin();
pit!=children.end();++pit) {
(**pit).showerBasis(parent->showerBasis(),true);
(**pit).setShowerMomentum(true);
}
}
void Decay_QTildeShowerKinematics1to2::
reconstructParent( const tShowerParticlePtr, const ParticleVector &) const {
throw Exception() << "Decay_QTildeShowerKinematics1to2::reconstructParent not implemented"
<< Exception::abortnow;
}
void Decay_QTildeShowerKinematics1to2::
reconstructLast(const tShowerParticlePtr last, Energy mass) const {
// set beta component and consequently all missing data from that,
// using the nominal (i.e. PDT) mass.
Energy theMass = mass > ZERO ? mass : last->data().constituentMass();
last->showerParameters().beta=
(sqr(theMass) + sqr(last->showerParameters().pt)
- sqr( last->showerParameters().alpha )*last->showerBasis()->pVector().m2())
/ ( 2.*last->showerParameters().alpha*last->showerBasis()->p_dot_n() );
// set that new momentum
last->set5Momentum( last->showerBasis()->sudakov2Momentum( last->showerParameters().alpha,
last->showerParameters().beta,
last->showerParameters().ptx,
last->showerParameters().pty) );
}
void Decay_QTildeShowerKinematics1to2::updateParent(const tShowerParticlePtr parent,
const ShowerParticleVector & children,
- ShowerPartnerType::Type) const {
+ ShowerPartnerType) const {
IdList ids(3);
ids[0] = parent->dataPtr();
ids[1] = children[0]->dataPtr();
ids[2] = children[1]->dataPtr();
const vector<Energy> & virtualMasses = SudakovFormFactor()->virtualMasses(ids);
children[0]->virtualMass(sqrt(sqr(virtualMasses[0])-(1.-z())*sqr(scale())));
if(children[1]->children().empty()) children[1]->virtualMass(virtualMasses[2]);
// compute the new pT of the branching
Energy2 pt2=(1.-z())*(z()*sqr(virtualMasses[0])-sqr(children[0]->virtualMass()))
-z()*sqr(children[1]->virtualMass());
if(pt2>ZERO) {
pT(sqrt(pt2));
}
else {
parent->virtualMass(ZERO);
}
}
diff --git a/Shower/QTilde/Default/Decay_QTildeShowerKinematics1to2.h b/Shower/QTilde/Default/Decay_QTildeShowerKinematics1to2.h
--- a/Shower/QTilde/Default/Decay_QTildeShowerKinematics1to2.h
+++ b/Shower/QTilde/Default/Decay_QTildeShowerKinematics1to2.h
@@ -1,101 +1,101 @@
// -*- C++ -*-
//
// Decay_QTildeShowerKinematics1to2.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_Decay_QTildeShowerKinematics1to2_H
#define HERWIG_Decay_QTildeShowerKinematics1to2_H
//
// This is the declaration of the Decay_QTildeShowerKinematics1to2 class.
//
#include "Herwig/Shower/QTilde/Base/ShowerKinematics.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
*
* This (concrete) class provides the specific decay shower
* kinematics information.
*
* @see ShowerKinematics
* @see IS_QTildeShowerKinematics1to2
* @see FS_QTildeShowerKinematics1to2
* @see KinematicsReconstructor
*
*/
class Decay_QTildeShowerKinematics1to2: public ShowerKinematics {
public:
/**
* The updateChildren, updateParent and updateLast
* members to update the values of the \f$\alpha\f$ and
* \f$p_\perp\f$ variables during the shower evolution.
*/
//@{
/**
* Along with the showering evolution --- going forward for
* time-like (forward) evolution, and going backward for space-like
* (backward) evolution --- the kinematical variables of the
* branching products are calculated and updated from the knowledge
* of the parent kinematics. This method is used by the
* ForwardShowerEvolver.
* @param parent The branching particle
* @param children The particles produced in the branching
* @param partnerType The type of evolution partner
*/
virtual void updateChildren( const tShowerParticlePtr parent,
const ShowerParticleVector & children,
- ShowerPartnerType::Type partnerType,
+ ShowerPartnerType partnerType,
bool massVeto) const;
/**
* Update the parent Kinematics from the knowledge of the kinematics
* of the children. This method will be used by the
* KinematicsReconstructor.
*/
virtual void reconstructParent( const tShowerParticlePtr parent,
const ParticleVector & children ) const;
/**
* Update the kinematical data of a particle when a reconstruction
* fixpoint was found. This will highly depend on the kind of
* kinematics chosen and will be defined in the inherited concrete
* classes. This method will be used by the KinematicsReconstructor.
* @param last The particle to update
* @param mass The mass to be used, if less than zero on-shell
*/
virtual void reconstructLast(const tShowerParticlePtr last, Energy mass=-1.*GeV) const;
/**
* Update the parent Kinematics from the knowledge of the kinematics
* of the children. This method will be used by the KinematicsReconstructor.
* @param parent The parent
* @param children The children
* @param partnerType The type of evolution partner
*/
virtual void updateParent(const tShowerParticlePtr parent,
const ShowerParticleVector & children,
- ShowerPartnerType::Type partnerType) const;
+ ShowerPartnerType partnerType) const;
//@}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
Decay_QTildeShowerKinematics1to2 & operator=(const Decay_QTildeShowerKinematics1to2 &);
};
}
#endif /* HERWIG_Decay_QTildeShowerKinematics1to2_H */
diff --git a/Shower/QTilde/Default/FS_QTildeShowerKinematics1to2.cc b/Shower/QTilde/Default/FS_QTildeShowerKinematics1to2.cc
--- a/Shower/QTilde/Default/FS_QTildeShowerKinematics1to2.cc
+++ b/Shower/QTilde/Default/FS_QTildeShowerKinematics1to2.cc
@@ -1,199 +1,199 @@
// -*- C++ -*-
//
// FS_QTildeShowerKinematics1to2.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 FS_QTildeShowerKinematics1to2 class.
//
#include "FS_QTildeShowerKinematics1to2.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "Herwig/Shower/QTilde/SplittingFunctions/SplittingFunction.h"
#include "Herwig/Shower/QTilde/Base/ShowerParticle.h"
#include "ThePEG/Utilities/Debug.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"
#include "Herwig/Shower/QTilde/Base/ShowerVertex.h"
using namespace Herwig;
void FS_QTildeShowerKinematics1to2::
updateParameters(tShowerParticlePtr theParent,
tShowerParticlePtr theChild0,
tShowerParticlePtr theChild1,
bool setAlpha) const {
const ShowerParticle::Parameters & parent = theParent->showerParameters();
ShowerParticle::Parameters & child0 = theChild0->showerParameters();
ShowerParticle::Parameters & child1 = theChild1->showerParameters();
// determine alphas of children according to interpretation of z
if ( setAlpha ) {
child0.alpha = z() * parent.alpha;
child1.alpha = (1.-z()) * parent.alpha;
}
// set the values
double cphi = cos(phi());
double sphi = sin(phi());
child0.ptx = pT() * cphi + z() * parent.ptx;
child0.pty = pT() * sphi + z() * parent.pty;
child0.pt = sqrt( sqr(child0.ptx) + sqr(child0.pty) );
child1.ptx = -pT() * cphi + (1.-z())* parent.ptx;
child1.pty = -pT() * sphi + (1.-z())* parent.pty;
child1.pt = sqrt( sqr(child1.ptx) + sqr(child1.pty) );
}
void FS_QTildeShowerKinematics1to2::
updateChildren(const tShowerParticlePtr parent,
const ShowerParticleVector & children,
- ShowerPartnerType::Type partnerType,
+ ShowerPartnerType partnerType,
bool massVeto) const {
assert(children.size()==2);
// calculate the scales
splittingFn()->evaluateFinalStateScales(partnerType,scale(),z(),parent,
children[0],children[1]);
// set the maximum virtual masses
if(massVeto) {
Energy2 q2 = z()*(1.-z())*sqr(scale());
IdList ids(3);
ids[0] = parent->dataPtr();
ids[1] = children[0]->dataPtr();
ids[2] = children[1]->dataPtr();
const vector<Energy> & virtualMasses = SudakovFormFactor()->virtualMasses(ids);
if(ids[0]->id()!=ParticleID::g && ids[0]->id()!=ParticleID::gamma ) {
q2 += sqr(virtualMasses[0]);
}
// limits on further evolution
children[0]->scales().Max_Q2 = z() *(q2-sqr(virtualMasses[2])/(1.-z()));
children[1]->scales().Max_Q2 = (1.-z())*(q2-sqr(virtualMasses[1])/ z() );
}
// update the parameters
updateParameters(parent, children[0], children[1], true);
// set up the colour connections
splittingFn()->colourConnection(parent,children[0],children[1],partnerType,false);
// make the products children of the parent
parent->addChild(children[0]);
parent->addChild(children[1]);
// set the momenta of the children
for(ShowerParticleVector::const_iterator pit=children.begin();
pit!=children.end();++pit) {
(**pit).showerBasis(parent->showerBasis(),true);
(**pit).setShowerMomentum(true);
}
// sort out the helicity stuff
if(! dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->correlations()) return;
SpinPtr pspin(parent->spinInfo());
if(!pspin || !dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->spinCorrelations() ) return;
Energy2 t = sqr(scale())*z()*(1.-z());
IdList ids;
ids.push_back(parent->dataPtr());
ids.push_back(children[0]->dataPtr());
ids.push_back(children[1]->dataPtr());
// create the vertex
SVertexPtr vertex(new_ptr(ShowerVertex()));
// set the matrix element
vertex->ME(splittingFn()->matrixElement(z(),t,ids,phi(),true));
// set the incoming particle for the vertex
parent->spinInfo()->decayVertex(vertex);
for(ShowerParticleVector::const_iterator pit=children.begin();
pit!=children.end();++pit) {
// construct the spin info for the children
(**pit).constructSpinInfo(true);
// connect the spinInfo object to the vertex
(*pit)->spinInfo()->productionVertex(vertex);
}
}
void FS_QTildeShowerKinematics1to2::
reconstructParent(const tShowerParticlePtr parent,
const ParticleVector & children ) const {
assert(children.size() == 2);
ShowerParticlePtr c1 = dynamic_ptr_cast<ShowerParticlePtr>(children[0]);
ShowerParticlePtr c2 = dynamic_ptr_cast<ShowerParticlePtr>(children[1]);
parent->showerParameters().beta=
c1->showerParameters().beta + c2->showerParameters().beta;
Lorentz5Momentum pnew = c1->momentum() + c2->momentum();
Energy2 m2 = sqr(pT())/z()/(1.-z()) + sqr(c1->mass())/z()
+ sqr(c2->mass())/(1.-z());
pnew.setMass(sqrt(m2));
parent->set5Momentum( pnew );
}
void FS_QTildeShowerKinematics1to2::reconstructLast(const tShowerParticlePtr last,
Energy mass) const {
// set beta component and consequently all missing data from that,
// using the nominal (i.e. PDT) mass.
Energy theMass = mass > ZERO ? mass : last->data().constituentMass();
Lorentz5Momentum pVector = last->showerBasis()->pVector();
ShowerParticle::Parameters & lastParam = last->showerParameters();
Energy2 denom = 2. * lastParam.alpha * last->showerBasis()->p_dot_n();
if(abs(denom)/(sqr(pVector.e())+pVector.rho2())<1e-10) {
throw KinematicsReconstructionVeto();
}
lastParam.beta = ( sqr(theMass) + sqr(lastParam.pt)
- sqr(lastParam.alpha) * pVector.m2() )
/ denom;
// set that new momentum
Lorentz5Momentum newMomentum = last->showerBasis()->
sudakov2Momentum( lastParam.alpha, lastParam.beta,
lastParam.ptx , lastParam.pty);
newMomentum.setMass(theMass);
newMomentum.rescaleEnergy();
if(last->data().stable()) {
last->set5Momentum( newMomentum );
}
else {
last->boost(last->momentum().findBoostToCM());
last->boost(newMomentum.boostVector());
}
}
void FS_QTildeShowerKinematics1to2::updateParent(const tShowerParticlePtr parent,
const ShowerParticleVector & children,
- ShowerPartnerType::Type) const {
+ ShowerPartnerType) const {
IdList ids(3);
ids[0] = parent->dataPtr();
ids[1] = children[0]->dataPtr();
ids[2] = children[1]->dataPtr();
const vector<Energy> & virtualMasses = SudakovFormFactor()->virtualMasses(ids);
if(children[0]->children().empty()) children[0]->virtualMass(virtualMasses[1]);
if(children[1]->children().empty()) children[1]->virtualMass(virtualMasses[2]);
// compute the new pT of the branching
Energy2 pt2=sqr(z()*(1.-z()))*sqr(scale())
- sqr(children[0]->virtualMass())*(1.-z())
- sqr(children[1]->virtualMass())* z() ;
if(ids[0]->id()!=ParticleID::g) pt2 += z()*(1.-z())*sqr(virtualMasses[0]);
if(pt2>ZERO) {
Energy2 q2 =
sqr(children[0]->virtualMass())/z() +
sqr(children[1]->virtualMass())/(1.-z()) +
pt2/z()/(1.-z());
parent->virtualMass(sqrt(q2));
pT(sqrt(pt2));
}
else {
parent->virtualMass(ZERO);
}
}
void FS_QTildeShowerKinematics1to2::
resetChildren(const tShowerParticlePtr parent,
const ShowerParticleVector & children) const {
updateParameters(parent, children[0], children[1], false);
for(unsigned int ix=0;ix<children.size();++ix) {
if(children[ix]->children().empty()) continue;
ShowerParticleVector newChildren;
for(unsigned int iy=0;iy<children[ix]->children().size();++iy)
newChildren.push_back(dynamic_ptr_cast<ShowerParticlePtr>
(children[ix]->children()[iy]));
children[ix]->showerKinematics()->resetChildren(children[ix],newChildren);
}
}
diff --git a/Shower/QTilde/Default/FS_QTildeShowerKinematics1to2.h b/Shower/QTilde/Default/FS_QTildeShowerKinematics1to2.h
--- a/Shower/QTilde/Default/FS_QTildeShowerKinematics1to2.h
+++ b/Shower/QTilde/Default/FS_QTildeShowerKinematics1to2.h
@@ -1,117 +1,117 @@
// -*- C++ -*-
//
// FS_QTildeShowerKinematics1to2.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_FS_QTildeShowerKinematics1to2_H
#define HERWIG_FS_QTildeShowerKinematics1to2_H
//
// This is the declaration of the FS_QTildeShowerKinematics1to2 class.
//
#include "Herwig/Shower/QTilde/Base/ShowerKinematics.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
*
* This (concrete) class provides the specific Final State shower
* kinematics information.
*
* @see ShowerKinematics
* @see IS_QTildeShowerKinematics1to2
* @see Decay_QTildeShowerKinematics1to2
* @see KinematicsReconstructor
*/
class FS_QTildeShowerKinematics1to2: public ShowerKinematics {
public:
/**
* Default constructor
*/
inline FS_QTildeShowerKinematics1to2() {}
/**
* The updateChildren, updateParent and updateLast
* members to update the values of the \f$\alpha\f$ and
* \f$p_\perp\f$ variables during the shower evolution.
*/
//@{
/**
* Along with the showering evolution --- going forward for
* time-like (forward) evolution, and going backward for space-like
* (backward) evolution --- the kinematical variables of the
* branching products are calculated and updated from the knowledge
* of the parent kinematics. This method is used by the
* ForwardShowerEvolver.
* @param parent The branching particle
* @param children The particles produced in the branching
* @param partnerType The type of evolution partner
*/
private:
void updateParameters(tShowerParticlePtr theParent,
tShowerParticlePtr theChild0,
tShowerParticlePtr theChild1,
bool setAlpha) const;
public:
virtual void updateChildren( const tShowerParticlePtr parent,
const ShowerParticleVector & children,
- ShowerPartnerType::Type partnerType,
+ ShowerPartnerType partnerType,
bool massVeto ) const;
virtual void resetChildren( const tShowerParticlePtr parent,
const ShowerParticleVector & children) const;
/**
* Update the parent Kinematics from the knowledge of the kinematics
* of the children. This method will be used by the KinematicsReconstructor.
* @param parent The parent
* @param children The children
* @param partnerType The type of evolution partner
*/
virtual void updateParent(const tShowerParticlePtr parent,
const ShowerParticleVector & children,
- ShowerPartnerType::Type partnerType) const;
+ ShowerPartnerType partnerType) const;
/**
* Update the parent Kinematics from the knowledge of the kinematics
* of the children. This method will be used by the
* KinematicsReconstructor.
*/
virtual void reconstructParent( const tShowerParticlePtr parent,
const ParticleVector & children ) const;
/**
* Update the kinematical data of a particle when a reconstruction
* fixpoint was found. This will highly depend on the kind of
* kinematics chosen and will be defined in the inherited concrete
* classes. This method will be used by the KinematicsReconstructor.
* @param last The particle to update
* @param mass The mass to be used, if less than zero on-shell
*/
virtual void reconstructLast(const tShowerParticlePtr last, Energy mass=-1.*GeV) const;
//@}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
FS_QTildeShowerKinematics1to2 & operator=(const FS_QTildeShowerKinematics1to2 &);
};
}
#endif /* HERWIG_FS_QTildeShowerKinematics1to2_H */
diff --git a/Shower/QTilde/Default/IS_QTildeShowerKinematics1to2.cc b/Shower/QTilde/Default/IS_QTildeShowerKinematics1to2.cc
--- a/Shower/QTilde/Default/IS_QTildeShowerKinematics1to2.cc
+++ b/Shower/QTilde/Default/IS_QTildeShowerKinematics1to2.cc
@@ -1,150 +1,150 @@
// -*- C++ -*-
//
// IS_QTildeShowerKinematics1to2.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 IS_QTildeShowerKinematics1to2 class.
//
#include "IS_QTildeShowerKinematics1to2.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "Herwig/Shower/QTilde/Base/ShowerParticle.h"
#include "ThePEG/Utilities/Debug.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"
#include "Herwig/Shower/QTilde/Base/ShowerVertex.h"
#include <cassert>
using namespace Herwig;
void IS_QTildeShowerKinematics1to2::
updateChildren( const tShowerParticlePtr theParent,
const ShowerParticleVector & children,
- ShowerPartnerType::Type,
+ ShowerPartnerType,
bool massVeto) const {
const ShowerParticle::Parameters & parent = theParent->showerParameters();
ShowerParticle::Parameters & child0 = children[0]->showerParameters();
ShowerParticle::Parameters & child1 = children[1]->showerParameters();
double cphi = cos(phi());
double sphi = sin(phi());
child1.alpha = (1.-z()) * parent.alpha;
child1.ptx = (1.-z()) * parent.ptx - cphi * pT();
child1.pty = (1.-z()) * parent.pty - sphi * pT();
child1.pt = sqrt( sqr(child1.ptx) + sqr(child1.pty) );
// space-like child
child0.alpha = parent.alpha - child1.alpha;
child0.beta = parent.beta - child1.beta;
child0.ptx = parent.ptx - child1.ptx;
child0.pty = parent.pty - child1.pty;
if(massVeto) {
Energy2 q2 = (1.-z())*sqr(scale());
children[1]->scales().Max_Q2 = (1.-z())*q2/z();
}
}
void IS_QTildeShowerKinematics1to2::
updateParent(const tShowerParticlePtr parent,
const ShowerParticleVector & children,
- ShowerPartnerType::Type partnerType) const {
+ ShowerPartnerType partnerType) const {
// calculate the scales
splittingFn()->evaluateInitialStateScales(partnerType,scale(),z(),parent,
children[0],children[1]);
// set proper colour connections
splittingFn()->colourConnection(parent,children[0],children[1],
partnerType,true);
// set proper parent/child relationships
parent->addChild(children[0]);
parent->addChild(children[1]);
parent->x(children[0]->x()/z());
// sort out the helicity stuff
// construct the spin info for parent and timelike child
// temporary assignment of shower parameters to calculate correlations
parent->showerParameters().alpha = parent->x();
children[1]->showerParameters().alpha = (1.-z()) * parent->x();
children[1]->showerParameters().ptx = - cos(phi()) * pT();
children[1]->showerParameters().pty = - sin(phi()) * pT();
children[1]->showerParameters().pt = pT();
parent ->showerBasis(children[0]->showerBasis(),true);
children[1]->showerBasis(children[0]->showerBasis(),true);
parent ->setShowerMomentum(false);
children[1]->setShowerMomentum(true);
if(! dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->correlations()) return;
SpinPtr pspin(children[0]->spinInfo());
if(!pspin || !dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->spinCorrelations() ) return;
// compute the matrix element for spin correlations
IdList ids;
ids.push_back(parent->dataPtr());
ids.push_back(children[0]->dataPtr());
ids.push_back(children[1]->dataPtr());
Energy2 t = (1.-z())*sqr(scale())/z();
// create the vertex
SVertexPtr vertex(new_ptr(ShowerVertex()));
// set the matrix element
vertex->ME(splittingFn()->matrixElement(z(),t,ids,phi(),false));
// set the incoming particle for the vertex
// (in reality the first child as going backwards)
pspin->decayVertex(vertex);
// construct the spin infos
parent ->constructSpinInfo(false);
children[1]->constructSpinInfo(true);
// connect the spinInfo objects to the vertex
parent ->spinInfo()->productionVertex(vertex);
children[1]->spinInfo()->productionVertex(vertex);
}
void IS_QTildeShowerKinematics1to2::
reconstructParent(const tShowerParticlePtr parent,
const ParticleVector & children ) const {
PPtr c1 = children[0];
ShowerParticlePtr c2 = dynamic_ptr_cast<ShowerParticlePtr>(children[1]);
ShowerParticle::Parameters & c2param = c2->showerParameters();
// get shower variables from 1st child in order to keep notation
// parent->(c1, c2) clean even though the splitting was initiated
// from c1. The name updateParent is still referring to the
// timelike branching though.
// on-shell child
c2param.beta = 0.5*( sqr(c2->data().constituentMass()) + sqr(c2param.pt) )
/ ( c2param.alpha * parent->showerBasis()->p_dot_n() );
Lorentz5Momentum pnew = parent->showerBasis()->
sudakov2Momentum(c2param.alpha, c2param.beta,
c2param.ptx , c2param.pty);
pnew.setMass(c2->data().constituentMass());
pnew.rescaleEnergy();
c2->set5Momentum( pnew );
// spacelike child
Lorentz5Momentum pc1(parent->momentum() - c2->momentum());
pc1.rescaleMass();
c1->set5Momentum(pc1);
}
void IS_QTildeShowerKinematics1to2::
updateLast( const tShowerParticlePtr theLast,Energy px,Energy py) const {
if(theLast->isFinalState()) return;
ShowerParticle::Parameters & last = theLast->showerParameters();
Lorentz5Momentum pVector = theLast->showerBasis()->pVector();
Energy2 pt2 = sqr(px) + sqr(py);
last.alpha = theLast->x();
last.beta = 0.5 * pt2 / last.alpha / theLast->showerBasis()->p_dot_n();
last.ptx = ZERO;
last.pty = ZERO;
last.pt = ZERO;
// momentum
Lorentz5Momentum ntemp = Lorentz5Momentum(ZERO,-pVector.vect());
double beta = 0.5 * pt2 / last.alpha / ( pVector * ntemp);
Lorentz5Momentum plast =
Lorentz5Momentum( (pVector.z()>ZERO ? px : -px), py, ZERO, ZERO)
+ theLast->x() * pVector + beta * ntemp;
plast.rescaleMass();
theLast->set5Momentum(plast);
}
diff --git a/Shower/QTilde/Default/IS_QTildeShowerKinematics1to2.h b/Shower/QTilde/Default/IS_QTildeShowerKinematics1to2.h
--- a/Shower/QTilde/Default/IS_QTildeShowerKinematics1to2.h
+++ b/Shower/QTilde/Default/IS_QTildeShowerKinematics1to2.h
@@ -1,112 +1,112 @@
// -*- C++ -*-
//
// IS_QTildeShowerKinematics1to2.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_IS_QTildeShowerKinematics1to2_H
#define HERWIG_IS_QTildeShowerKinematics1to2_H
//
// This is the declaration of the IS_QTildeShowerKinematics1to2 class.
//
#include "Herwig/Shower/QTilde/Base/ShowerKinematics.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
*
* This (concrete) class provides the specific Intial State shower
* kinematics information.
*
* @see ShowerKinematics
* @see FS_QTildeShowerKinematics1to2
* @see Decay_QTildeShowerKinematics1to2
* @see KinematicsReconstructor
*/
class IS_QTildeShowerKinematics1to2: public ShowerKinematics {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* Construct in terms of the basis states
*/
inline IS_QTildeShowerKinematics1to2() {}
//@}
public:
/**
* The updateChildren, updateParent and updateLast
* members to update the values of the \f$\alpha\f$ and
* \f$p_\perp\f$ variables during the shower evolution.
*/
//@{
/**
* Along with the showering evolution --- going forward for
* time-like (forward) evolution, and going backward for space-like
* (backward) evolution --- the kinematical variables of the
* branching products are calculated and updated from the knowledge
* of the parent kinematics. This method is used by the
* ForwardShowerEvolver.
* @param parent The branching particle
* @param children The particles produced in the branching
* @param partnerType The type of evolution partner
*/
virtual void updateChildren( const tShowerParticlePtr parent,
const ShowerParticleVector & children,
- ShowerPartnerType::Type partnerType,
+ ShowerPartnerType partnerType,
bool massVeto) const;
/**
* Update the parent Kinematics from the knowledge of the kinematics
* of the children. This method will be used by the
* KinematicsReconstructor.
* @param parent The branching particle
* @param children The particles produced in the branching
* @param partnerType The type of evolution partner
*/
virtual void updateParent( const tShowerParticlePtr parent,
const ShowerParticleVector & children,
- ShowerPartnerType::Type partnerType) const;
+ ShowerPartnerType partnerType) const;
/**
* Update the parent Kinematics from the knowledge of the kinematics
* of the children. This method will be used by the
* KinematicsReconstructor.
*/
virtual void reconstructParent( const tShowerParticlePtr parent,
const ParticleVector & children ) const;
/**
* Update the kinematical data of a particle when a reconstruction
* fixpoint was found. This will highly depend on the kind of
* kinematics chosen and will be defined in the inherited concrete
* classes. This method will be used by the KinematicsReconstructor.
* @param theLast The particle.
* @param px The \f$x\f$ component of the \f$p_T\f$.
* @param py The \f$y\f$ component of the \f$p_T\f$.
*/
virtual void updateLast(const tShowerParticlePtr theLast,
Energy px, Energy py) const;
//@}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
IS_QTildeShowerKinematics1to2 & operator=(const IS_QTildeShowerKinematics1to2 &);
};
}
#endif /* HERWIG_IS_QTildeShowerKinematics1to2_H */
diff --git a/Shower/QTilde/Default/QTildeReconstructor.cc b/Shower/QTilde/Default/QTildeReconstructor.cc
--- a/Shower/QTilde/Default/QTildeReconstructor.cc
+++ b/Shower/QTilde/Default/QTildeReconstructor.cc
@@ -1,2923 +1,2923 @@
// -*- C++ -*-
//
// QTildeReconstructor.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 QTildeReconstructor class.
//
#include "QTildeReconstructor.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/EventRecord/Event.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/RefVector.h"
#include "Herwig/Shower/QTilde/Base/PartnerFinder.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig/Shower/QTilde/SplittingFunctions/SplittingFunction.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/EventRecord/ColourLine.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "Herwig/Shower/QTilde/QTildeShowerHandler.h"
#include <cassert>
using namespace Herwig;
DescribeClass<QTildeReconstructor,KinematicsReconstructor>
describeQTildeReconstructor("Herwig::QTildeReconstructor", "HwShower.so");
namespace {
/**
* Struct to order the jets in off-shellness
*/
struct JetOrdering {
bool operator() (const JetKinStruct & j1, const JetKinStruct & j2) {
Energy diff1 = j1.q.m()-j1.p.m();
Energy diff2 = j2.q.m()-j2.p.m();
if(diff1!=diff2) {
return diff1>diff2;
}
else if( j1.q.e() != j2.q.e() )
return j1.q.e()>j2.q.e();
else
return j1.parent->uniqueId>j2.parent->uniqueId;
}
};
}
void QTildeReconstructor::persistentOutput(PersistentOStream & os) const {
os << _reconopt << _initialBoost << ounit(_minQ,GeV) << _noRescale
<< _noRescaleVector << _finalStateReconOption
<< _initialStateReconOption;
}
void QTildeReconstructor::persistentInput(PersistentIStream & is, int) {
is >> _reconopt >> _initialBoost >> iunit(_minQ,GeV) >> _noRescale
>> _noRescaleVector >> _finalStateReconOption
>> _initialStateReconOption;
}
void QTildeReconstructor::Init() {
static ClassDocumentation<QTildeReconstructor> documentation
( "This class is responsible for the kinematics reconstruction of the showering,",
" including the kinematics reshuffling necessary to compensate for the recoil"
"of the emissions." );
static Switch<QTildeReconstructor,unsigned int> interfaceReconstructionOption
("ReconstructionOption",
"Option for the kinematics reconstruction",
&QTildeReconstructor::_reconopt, 0, false, false);
static SwitchOption interfaceReconstructionOptionGeneral
(interfaceReconstructionOption,
"General",
"Use the general solution which ignores the colour structure for all processes",
0);
static SwitchOption interfaceReconstructionOptionColour
(interfaceReconstructionOption,
"Colour",
"Use the colour structure of the process to determine the reconstruction procedure.",
1);
static SwitchOption interfaceReconstructionOptionColour2
(interfaceReconstructionOption,
"Colour2",
"Make the most use possible of the colour structure of the process to determine the reconstruction procedure. "
"Start with FF, then IF then II colour connections",
2);
static SwitchOption interfaceReconstructionOptionColour3
(interfaceReconstructionOption,
"Colour3",
"Make the most use possible of the colour structure of the process to determine the reconstruction procedure. "
"Do the colour connections in order of the pT's emitted in the shower starting with the hardest."
" The colour partner is fully reconstructed at the same time.",
3);
static SwitchOption interfaceReconstructionOptionColour4
(interfaceReconstructionOption,
"Colour4",
"Make the most use possible of the colour structure of the process to determine the reconstruction procedure. "
"Do the colour connections in order of the pT's emitted in the shower starting with the hardest, while leaving"
" the colour partner on mass-shell",
4);
static Parameter<QTildeReconstructor,Energy> interfaceMinimumQ2
("MinimumQ2",
"The minimum Q2 for the reconstruction of initial-final systems",
&QTildeReconstructor::_minQ, GeV, 0.001*GeV, 1e-6*GeV, 10.0*GeV,
false, false, Interface::limited);
static RefVector<QTildeReconstructor,ParticleData> interfaceNoRescale
("NoRescale",
"Particles which shouldn't be rescaled to be on shell by the shower",
&QTildeReconstructor::_noRescaleVector, -1, false, false, true, false, false);
static Switch<QTildeReconstructor,unsigned int> interfaceInitialInitialBoostOption
("InitialInitialBoostOption",
"Option for how the boost from the system before ISR to that after ISR is applied.",
&QTildeReconstructor::_initialBoost, 0, false, false);
static SwitchOption interfaceInitialInitialBoostOptionOneBoost
(interfaceInitialInitialBoostOption,
"OneBoost",
"Apply one boost from old CMS to new CMS",
0);
static SwitchOption interfaceInitialInitialBoostOptionLongTransBoost
(interfaceInitialInitialBoostOption,
"LongTransBoost",
"First apply a longitudinal and then a transverse boost",
1);
static Switch<QTildeReconstructor,unsigned int> interfaceFinalStateReconOption
("FinalStateReconOption",
"Option for how to reconstruct the momenta of the final-state system",
&QTildeReconstructor::_finalStateReconOption, 0, false, false);
static SwitchOption interfaceFinalStateReconOptionDefault
(interfaceFinalStateReconOption,
"Default",
"All the momenta are rescaled in the rest frame",
0);
static SwitchOption interfaceFinalStateReconOptionMostOffShell
(interfaceFinalStateReconOption,
"MostOffShell",
"All particles put on the new-mass shell and then the most off-shell and"
" recoiling system are rescaled to ensure 4-momentum is conserved.",
1);
static SwitchOption interfaceFinalStateReconOptionRecursive
(interfaceFinalStateReconOption,
"Recursive",
"Recursively put on shell by putting the most off-shell particle which"
" hasn't been rescaled on-shell by rescaling the particles and the recoiling system. ",
2);
static SwitchOption interfaceFinalStateReconOptionRestMostOffShell
(interfaceFinalStateReconOption,
"RestMostOffShell",
"The most off-shell is put on shell by rescaling it and the recoiling system,"
" the recoiling system is then put on-shell in its rest frame.",
3);
static SwitchOption interfaceFinalStateReconOptionRestRecursive
(interfaceFinalStateReconOption,
"RestRecursive",
"As 3 but recursive treated the currently most-off shell,"
" only makes a difference if more than 3 partons.",
4);
static Switch<QTildeReconstructor,unsigned int> interfaceInitialStateReconOption
("InitialStateReconOption",
"Option for the reconstruction of initial state radiation",
&QTildeReconstructor::_initialStateReconOption, 0, false, false);
static SwitchOption interfaceInitialStateReconOptionRapidity
(interfaceInitialStateReconOption,
"Rapidity",
"Preserve shat and rapidity",
0);
static SwitchOption interfaceInitialStateReconOptionLongitudinal
(interfaceInitialStateReconOption,
"Longitudinal",
"Preserve longitudinal momentum",
1);
static SwitchOption interfaceInitialStateReconOptionSofterFraction
(interfaceInitialStateReconOption,
"SofterFraction",
"Preserve the momentum fraction of the parton which has emitted softer.",
2);
}
void QTildeReconstructor::doinit() {
KinematicsReconstructor::doinit();
_noRescale = set<cPDPtr>(_noRescaleVector.begin(),_noRescaleVector.end());
}
bool QTildeReconstructor::
reconstructTimeLikeJet(const tShowerParticlePtr particleJetParent) const {
assert(particleJetParent);
bool emitted=true;
// if this is not a fixed point in the reconstruction
if( !particleJetParent->children().empty() ) {
// if not a reconstruction fixpoint, dig deeper for all children:
for ( ParticleVector::const_iterator cit =
particleJetParent->children().begin();
cit != particleJetParent->children().end(); ++cit )
reconstructTimeLikeJet(dynamic_ptr_cast<ShowerParticlePtr>(*cit));
}
// it is a reconstruction fixpoint, ie kinematical data has to be available
else {
// check if the parent was part of the shower
ShowerParticlePtr jetGrandParent;
if(!particleJetParent->parents().empty())
jetGrandParent= dynamic_ptr_cast<ShowerParticlePtr>
(particleJetParent->parents()[0]);
// update if so
if (jetGrandParent) {
if (jetGrandParent->showerKinematics()) {
if(particleJetParent->id()==_progenitor->id()&&
!_progenitor->data().stable()) {
jetGrandParent->showerKinematics()->reconstructLast(particleJetParent,
_progenitor->mass());
}
else {
jetGrandParent->showerKinematics()->reconstructLast(particleJetParent);
}
}
}
// otherwise
else {
Energy dm = particleJetParent->data().constituentMass();
if (abs(dm-particleJetParent->momentum().m())>0.001*MeV
&&particleJetParent->dataPtr()->stable()
&&particleJetParent->id()!=ParticleID::gamma
&&_noRescale.find(particleJetParent->dataPtr())==_noRescale.end()) {
Lorentz5Momentum dum = particleJetParent->momentum();
dum.setMass(dm);
dum.rescaleEnergy();
particleJetParent->set5Momentum(dum);
}
else {
emitted=false;
}
}
}
// recursion has reached an endpoint once, ie we can reconstruct the
// kinematics from the children.
if( !particleJetParent->children().empty() )
particleJetParent->showerKinematics()
->reconstructParent( particleJetParent, particleJetParent->children() );
return emitted;
}
bool QTildeReconstructor::
reconstructHardJets(ShowerTreePtr hard,
const map<tShowerProgenitorPtr,
pair<Energy,double> > & intrinsic,
- ShowerInteraction::Type type,
+ ShowerInteraction type,
bool switchRecon) const {
_currentTree = hard;
_intrinsic=intrinsic;
// extract the particles from the ShowerTree
vector<ShowerProgenitorPtr> ShowerHardJets=hard->extractProgenitors();
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
_boosts[ShowerHardJets[ix]->progenitor()] = vector<LorentzRotation>();
}
for(map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator
tit = _currentTree->treelinks().begin();
tit != _currentTree->treelinks().end();++tit) {
_treeBoosts[tit->first] = vector<LorentzRotation>();
}
try {
// old recon method, using new member functions
if(_reconopt == 0 || switchRecon ) {
reconstructGeneralSystem(ShowerHardJets);
}
// reconstruction based on coloured systems
else if( _reconopt == 1) {
reconstructColourSinglets(ShowerHardJets,type);
}
// reconstruction of FF, then IF, then II
else if( _reconopt == 2) {
reconstructFinalFirst(ShowerHardJets);
}
// reconstruction based on coloured systems
else if( _reconopt == 3 || _reconopt == 4) {
reconstructColourPartner(ShowerHardJets);
}
else
assert(false);
}
catch(KinematicsReconstructionVeto) {
_progenitor=tShowerParticlePtr();
_intrinsic.clear();
for(map<tPPtr,vector<LorentzRotation> >::const_iterator bit=_boosts.begin();bit!=_boosts.end();++bit) {
for(vector<LorentzRotation>::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) {
LorentzRotation rot = rit->inverse();
bit->first->transform(rot);
}
}
_boosts.clear();
for(map<tShowerTreePtr,vector<LorentzRotation> >::const_iterator bit=_treeBoosts.begin();bit!=_treeBoosts.end();++bit) {
for(vector<LorentzRotation>::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) {
LorentzRotation rot = rit->inverse();
bit->first->transform(rot,false);
}
}
_currentTree = tShowerTreePtr();
_treeBoosts.clear();
return false;
}
catch (Exception & ex) {
_progenitor=tShowerParticlePtr();
_intrinsic.clear();
_currentTree = tShowerTreePtr();
_boosts.clear();
_treeBoosts.clear();
throw ex;
}
_progenitor=tShowerParticlePtr();
_intrinsic.clear();
// ensure x<1
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit=hard->incomingLines().begin();cit!=hard->incomingLines().end();++cit) {
tPPtr parent = cit->first->progenitor();
while (!parent->parents().empty()) {
parent = parent->parents()[0];
}
tPPtr hadron;
if ( cit->first->original()->parents().empty() ) {
hadron = cit->first->original();
}
else {
hadron = cit->first->original()->parents()[0];
}
if( ! (hadron->id() == parent->id() && hadron->children().size() <= 1)
&& parent->momentum().rho() > hadron->momentum().rho()) {
_progenitor=tShowerParticlePtr();
_intrinsic.clear();
for(map<tPPtr,vector<LorentzRotation> >::const_iterator bit=_boosts.begin();bit!=_boosts.end();++bit) {
for(vector<LorentzRotation>::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) {
LorentzRotation rot = rit->inverse();
bit->first->transform(rot);
}
}
_boosts.clear();
for(map<tShowerTreePtr,vector<LorentzRotation> >::const_iterator bit=_treeBoosts.begin();bit!=_treeBoosts.end();++bit) {
for(vector<LorentzRotation>::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) {
LorentzRotation rot = rit->inverse();
bit->first->transform(rot,false);
}
}
_currentTree = tShowerTreePtr();
_treeBoosts.clear();
return false;
}
}
_boosts.clear();
_treeBoosts.clear();
_currentTree = tShowerTreePtr();
return true;
}
double
QTildeReconstructor::solveKfactor(const Energy & root_s,
const JetKinVect & jets) const {
Energy2 s = sqr(root_s);
// must be at least two jets
if ( jets.size() < 2) throw KinematicsReconstructionVeto();
// sum of jet masses must be less than roots
if(momConsEq( 0.0, root_s, jets )>ZERO) throw KinematicsReconstructionVeto();
// if two jets simple solution
if ( jets.size() == 2 ) {
static const Energy2 eps = 1.0e-4 * MeV2;
if ( sqr(jets[0].p.x()+jets[1].p.x()) < eps &&
sqr(jets[0].p.y()+jets[1].p.y()) < eps &&
sqr(jets[0].p.z()+jets[1].p.z()) < eps ) {
Energy test = (jets[0].p+jets[1].p).vect().mag();
if(test > 1.0e-4 * MeV) throw KinematicsReconstructionVeto();
if ( jets[0].p.vect().mag2() < eps ) throw KinematicsReconstructionVeto();
Energy2 m1sq(jets[0].q.m2()),m2sq(jets[1].q.m2());
return sqrt( ( sqr(s - m1sq - m2sq) - 4.*m1sq*m2sq )
/(4.*s*jets[0].p.vect().mag2()) );
}
else throw KinematicsReconstructionVeto();
}
// i.e. jets.size() > 2, numerically
// check convergence, if it's a problem maybe use Newton iteration?
else {
double k1 = 0.,k2 = 1.,k = 0.;
if ( momConsEq( k1, root_s, jets ) < ZERO ) {
while ( momConsEq( k2, root_s, jets ) < ZERO ) {
k1 = k2;
k2 *= 2;
}
while ( fabs( (k1 - k2)/(k1 + k2) ) > 1.e-10 ) {
if( momConsEq( k2, root_s, jets ) == ZERO ) {
return k2;
} else {
k = (k1+k2)/2.;
if ( momConsEq( k, root_s, jets ) > ZERO ) {
k2 = k;
} else {
k1 = k;
}
}
}
return k1;
} else throw KinematicsReconstructionVeto();
}
throw KinematicsReconstructionVeto();
}
bool QTildeReconstructor::
reconstructSpaceLikeJet( const tShowerParticlePtr p) const {
bool emitted = true;
tShowerParticlePtr child;
tShowerParticlePtr parent;
if(!p->parents().empty())
parent = dynamic_ptr_cast<ShowerParticlePtr>(p->parents()[0]);
if(parent) {
emitted=true;
reconstructSpaceLikeJet(parent);
}
// if branching reconstruct time-like child
if(p->children().size()==2)
child = dynamic_ptr_cast<ShowerParticlePtr>(p->children()[1]);
if(p->perturbative()==0 && child) {
dynamic_ptr_cast<ShowerParticlePtr>(p->children()[0])->
showerKinematics()->reconstructParent(p,p->children());
if(!child->children().empty()) {
_progenitor=child;
reconstructTimeLikeJet(child);
// calculate the momentum of the particle
Lorentz5Momentum pnew=p->momentum()-child->momentum();
pnew.rescaleMass();
p->children()[0]->set5Momentum(pnew);
}
}
return emitted;
}
Boost QTildeReconstructor::
solveBoostBeta( const double k, const Lorentz5Momentum & newq,
const Lorentz5Momentum & oldp ) {
// try something different, purely numerical first:
// a) boost to rest frame of newq, b) boost with kp/E
Energy q = newq.vect().mag();
Energy2 qs = sqr(q);
Energy2 Q2 = newq.m2();
Energy kp = k*(oldp.vect().mag());
Energy2 kps = sqr(kp);
// usually we take the minus sign, since this boost will be smaller.
// we only require |k \vec p| = |\vec q'| which leaves the sign of
// the boost open but the 'minus' solution gives a smaller boost
// parameter, i.e. the result should be closest to the previous
// result. this is to be changed if we would get many momentum
// conservation violations at the end of the shower from a hard
// process.
double betam = (q*sqrt(qs + Q2) - kp*sqrt(kps + Q2))/(kps + qs + Q2);
// move directly to 'return'
Boost beta = -betam*(k/kp)*oldp.vect();
// note that (k/kp)*oldp.vect() = oldp.vect()/oldp.vect().mag() but cheaper.
// leave this out if it's running properly!
if ( betam >= 0 ) return beta;
else return Boost(0., 0., 0.);
}
bool QTildeReconstructor::
reconstructDecayJets(ShowerTreePtr decay,
- ShowerInteraction::Type) const {
+ ShowerInteraction) const {
_currentTree = decay;
// extract the particles from the ShowerTree
vector<ShowerProgenitorPtr> ShowerHardJets=decay->extractProgenitors();
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
_boosts[ShowerHardJets[ix]->progenitor()] = vector<LorentzRotation>();
}
for(map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator
tit = _currentTree->treelinks().begin();
tit != _currentTree->treelinks().end();++tit) {
_treeBoosts[tit->first] = vector<LorentzRotation>();
}
try {
bool radiated[2]={false,false};
// find the decaying particle and check if particles radiated
ShowerProgenitorPtr initial;
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
// only consider initial-state jets
if(ShowerHardJets[ix]->progenitor()->isFinalState()) {
radiated[1] |=ShowerHardJets[ix]->hasEmitted();
}
else {
initial=ShowerHardJets[ix];
radiated[0]|=ShowerHardJets[ix]->hasEmitted();
}
}
// find boost to the rest frame if needed
Boost boosttorest=-initial->progenitor()->momentum().boostVector();
double gammarest =
initial->progenitor()->momentum().e()/
initial->progenitor()->momentum().mass();
// check if need to boost to rest frame
bool gottaBoost = (boosttorest.mag() > 1e-12);
// if initial state radiation reconstruct the jet and set up the basis vectors
Lorentz5Momentum pjet;
Lorentz5Momentum nvect;
// find the partner
ShowerParticlePtr partner = initial->progenitor()->partner();
Lorentz5Momentum ppartner[2];
if(partner) ppartner[0]=partner->momentum();
// get the n reference vector
if(partner) {
if(initial->progenitor()->showerKinematics()) {
nvect = initial->progenitor()->showerBasis()->getBasis()[1];
}
else {
Lorentz5Momentum ppartner=initial->progenitor()->partner()->momentum();
if(gottaBoost) ppartner.boost(boosttorest,gammarest);
nvect = Lorentz5Momentum( ZERO,0.5*initial->progenitor()->mass()*
ppartner.vect().unit());
nvect.boost(-boosttorest,gammarest);
}
}
// if ISR
if(radiated[0]) {
// reconstruct the decay jet
reconstructDecayJet(initial->progenitor());
// momentum of decaying particle after ISR
pjet=initial->progenitor()->momentum()
-decay->incomingLines().begin()->second->momentum();
pjet.rescaleMass();
}
// boost initial state jet and basis vector if needed
if(gottaBoost) {
pjet.boost(boosttorest,gammarest);
nvect.boost(boosttorest,gammarest);
ppartner[0].boost(boosttorest,gammarest);
}
// loop over the final-state particles and do the reconstruction
JetKinVect possiblepartners;
JetKinVect jetKinematics;
bool atLeastOnce = radiated[0];
LorentzRotation restboost(boosttorest,gammarest);
Energy inmass(ZERO);
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
// only consider final-state jets
if(!ShowerHardJets[ix]->progenitor()->isFinalState()) {
inmass=ShowerHardJets[ix]->progenitor()->mass();
continue;
}
// do the reconstruction
JetKinStruct tempJetKin;
tempJetKin.parent = ShowerHardJets[ix]->progenitor();
if(ShowerHardJets.size()==2) {
Lorentz5Momentum dum=ShowerHardJets[ix]->progenitor()->momentum();
dum.setMass(inmass);
dum.rescaleRho();
tempJetKin.parent->set5Momentum(dum);
}
tempJetKin.p = ShowerHardJets[ix]->progenitor()->momentum();
if(gottaBoost) tempJetKin.p.boost(boosttorest,gammarest);
_progenitor=tempJetKin.parent;
if(ShowerHardJets[ix]->reconstructed()==ShowerProgenitor::notReconstructed) {
atLeastOnce |= reconstructTimeLikeJet(tempJetKin.parent);
ShowerHardJets[ix]->reconstructed(ShowerProgenitor::done);
}
if(gottaBoost) deepTransform(tempJetKin.parent,restboost);
tempJetKin.q = ShowerHardJets[ix]->progenitor()->momentum();
jetKinematics.push_back(tempJetKin);
}
if(partner) ppartner[1]=partner->momentum();
// calculate the rescaling parameters
double k1,k2;
Lorentz5Momentum qt;
if(!solveDecayKFactor(initial->progenitor()->mass(),nvect,pjet,
jetKinematics,partner,ppartner,k1,k2,qt)) {
for(map<tPPtr,vector<LorentzRotation> >::const_iterator bit=_boosts.begin();bit!=_boosts.end();++bit) {
for(vector<LorentzRotation>::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) {
LorentzRotation rot = rit->inverse();
bit->first->transform(rot);
}
}
_boosts.clear();
for(map<tShowerTreePtr,vector<LorentzRotation> >::const_iterator bit=_treeBoosts.begin();bit!=_treeBoosts.end();++bit) {
for(vector<LorentzRotation>::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) {
LorentzRotation rot = rit->inverse();
bit->first->transform(rot,false);
}
}
_treeBoosts.clear();
_currentTree = tShowerTreePtr();
return false;
}
// apply boosts and rescalings to final-state jets
for(JetKinVect::iterator it = jetKinematics.begin();
it != jetKinematics.end(); ++it) {
LorentzRotation Trafo = LorentzRotation();
if(it->parent!=partner) {
// boost for rescaling
if(atLeastOnce) {
map<tShowerTreePtr,pair<tShowerProgenitorPtr,
tShowerParticlePtr> >::const_iterator tit;
for(tit = _currentTree->treelinks().begin();
tit != _currentTree->treelinks().end();++tit) {
if(tit->second.first && tit->second.second==it->parent)
break;
}
if(it->parent->children().empty()&&!it->parent->spinInfo() &&
tit==_currentTree->treelinks().end()) {
Lorentz5Momentum pnew(k2*it->p.vect(),
sqrt(sqr(k2*it->p.vect().mag())+it->q.mass2()),
it->q.mass());
it->parent->set5Momentum(pnew);
}
else {
// rescaling boost can't ever work in this case
if(k2<0. && it->q.mass()==ZERO)
throw KinematicsReconstructionVeto();
Trafo = solveBoost(k2, it->q, it->p);
}
}
if(gottaBoost) Trafo.boost(-boosttorest,gammarest);
if(atLeastOnce || gottaBoost) deepTransform(it->parent,Trafo);
}
else {
Lorentz5Momentum pnew=ppartner[0];
pnew *=k1;
pnew-=qt;
pnew.setMass(ppartner[1].mass());
pnew.rescaleEnergy();
LorentzRotation Trafo=solveBoost(1.,ppartner[1],pnew);
if(gottaBoost) Trafo.boost(-boosttorest,gammarest);
deepTransform(partner,Trafo);
}
}
}
catch(KinematicsReconstructionVeto) {
for(map<tPPtr,vector<LorentzRotation> >::const_iterator bit=_boosts.begin();bit!=_boosts.end();++bit) {
for(vector<LorentzRotation>::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) {
LorentzRotation rot = rit->inverse();
bit->first->transform(rot);
}
}
_boosts.clear();
for(map<tShowerTreePtr,vector<LorentzRotation> >::const_iterator bit=_treeBoosts.begin();bit!=_treeBoosts.end();++bit) {
for(vector<LorentzRotation>::const_reverse_iterator rit=bit->second.rbegin();rit!=bit->second.rend();++rit) {
LorentzRotation rot = rit->inverse();
bit->first->transform(rot,false);
}
}
_treeBoosts.clear();
_currentTree = tShowerTreePtr();
return false;
}
catch (Exception & ex) {
_currentTree = tShowerTreePtr();
_boosts.clear();
_treeBoosts.clear();
throw ex;
}
_boosts.clear();
_treeBoosts.clear();
_currentTree = tShowerTreePtr();
return true;
}
bool QTildeReconstructor::
reconstructDecayJet( const tShowerParticlePtr p) const {
if(p->children().empty()) return false;
tShowerParticlePtr child;
// if branching reconstruct time-like child
child = dynamic_ptr_cast<ShowerParticlePtr>(p->children()[1]);
if(child) {
_progenitor=child;
reconstructTimeLikeJet(child);
// calculate the momentum of the particle
Lorentz5Momentum pnew=p->momentum()-child->momentum();
pnew.rescaleMass();
p->children()[0]->set5Momentum(pnew);
child=dynamic_ptr_cast<ShowerParticlePtr>(p->children()[0]);
reconstructDecayJet(child);
return true;
}
return false;
}
bool QTildeReconstructor::
solveDecayKFactor(Energy mb,
const Lorentz5Momentum & n,
const Lorentz5Momentum & pjet,
const JetKinVect & jetKinematics,
ShowerParticlePtr partner,
Lorentz5Momentum ppartner[2],
double & k1, double & k2,
Lorentz5Momentum & qt) const {
Energy2 pjn = partner ? pjet.vect()*n.vect() : ZERO;
Energy2 pcn = partner ? ppartner[0].vect()*n.vect() : 1.*MeV2;
Energy2 nmag = n.vect().mag2();
Lorentz5Momentum pn = partner ? (pjn/nmag)*n : Lorentz5Momentum();
qt=pjet-pn; qt.setE(ZERO);
Energy2 pt2=qt.vect().mag2();
Energy Ejet = pjet.e();
// magnitudes of the momenta for fast access
vector<Energy2> pmag;
Energy total(Ejet);
for(unsigned int ix=0;ix<jetKinematics.size();++ix) {
pmag.push_back(jetKinematics[ix].p.vect().mag2());
total+=jetKinematics[ix].q.mass();
}
// return if no possible solution
if(total>mb) return false;
Energy2 pcmag=ppartner[0].vect().mag2();
// used newton-raphson to get the rescaling
static const Energy eps=1e-8*GeV;
long double d1(1.),d2(1.);
Energy roots, ea, ec, ds;
unsigned int ix=0;
do {
++ix;
d2 = d1 + pjn/pcn;
roots = Ejet;
ds = ZERO;
for(unsigned int iy=0;iy<jetKinematics.size();++iy) {
if(jetKinematics[iy].parent==partner) continue;
ea = sqrt(sqr(d2)*pmag[iy]+jetKinematics[iy].q.mass2());
roots += ea;
ds += d2/ea*pmag[iy];
}
if(partner) {
ec = sqrt(sqr(d1)*pcmag + pt2 + ppartner[1].mass2());
roots += ec;
ds += d1/ec*pcmag;
}
d1 += (mb-roots)/ds;
d2 = d1 + pjn/pcn;
}
while(abs(mb-roots)>eps && ix<100);
k1=d1;
k2=d2;
// return true if N-R succeed, otherwise false
return ix<100;
}
bool QTildeReconstructor::
-deconstructDecayJets(HardTreePtr decay,ShowerInteraction::Type) const {
+deconstructDecayJets(HardTreePtr decay,ShowerInteraction) const {
// extract the momenta of the particles
vector<Lorentz5Momentum> pin;
vector<Lorentz5Momentum> pout;
// on-shell masses of the decay products
vector<Energy> mon;
Energy mbar(-GeV);
// the hard branchings of the particles
set<HardBranchingPtr>::iterator cit;
set<HardBranchingPtr> branchings=decay->branchings();
// properties of the incoming particle
bool ISR = false;
HardBranchingPtr initial;
Lorentz5Momentum qisr;
// find the incoming particle, both before and after
// any ISR
for(cit=branchings.begin();cit!=branchings.end();++cit){
if((*cit)->status()==HardBranching::Incoming||
(*cit)->status()==HardBranching::Decay) {
// search back up isr if needed
HardBranchingPtr branch = *cit;
while(branch->parent()) branch=branch->parent();
initial=branch;
// momentum or original parent
pin.push_back(branch->branchingParticle()->momentum());
// ISR?
ISR = !branch->branchingParticle()->children().empty();
// ISR momentum
qisr = pin.back()-(**cit).branchingParticle()->momentum();
qisr.rescaleMass();
}
}
assert(pin.size()==1);
// compute boost to rest frame
Boost boostv=-pin[0].boostVector();
// partner for ISR
ShowerParticlePtr partner;
Lorentz5Momentum ppartner;
if(initial->branchingParticle()->partner()) {
partner=initial->branchingParticle()->partner();
ppartner=partner->momentum();
}
// momentum of the decay products
for(cit=branchings.begin();cit!=branchings.end();++cit) {
if((*cit)->status()!=HardBranching::Outgoing) continue;
// find the mass of the particle
// including special treatment for off-shell resonances
// to preserve off-shell mass
Energy mass;
if(!(**cit).branchingParticle()->dataPtr()->stable()) {
HardBranchingPtr branch=*cit;
while(!branch->children().empty()) {
for(unsigned int ix=0;ix<branch->children().size();++ix) {
if(branch->children()[ix]->branchingParticle()->id()==
(**cit).branchingParticle()->id()) {
branch = branch->children()[ix];
continue;
}
}
};
mass = branch->branchingParticle()->mass();
}
else {
mass = (**cit).branchingParticle()->dataPtr()->mass();
}
// if not evolution partner of decaying particle
if((*cit)->branchingParticle()!=partner) {
pout.push_back((*cit)->branchingParticle()->momentum());
mon.push_back(mass);
}
// evolution partner of decaying particle
else {
mbar = mass;
}
}
// boost all the momenta to the rest frame of the decaying particle
for(unsigned int ix=0;ix<pout.size();++ix) pout[ix].boost(boostv);
if(initial->branchingParticle()->partner()) {
ppartner.boost(boostv);
qisr.boost(boostv);
}
// compute the rescaling factors
double k1,k2;
if(!ISR) {
if(partner) {
pout.push_back(ppartner);
mon.push_back(mbar);
}
k1=k2=inverseRescalingFactor(pout,mon,pin[0].mass());
if(partner) {
pout.pop_back();
mon.pop_back();
}
}
else {
if(!inverseDecayRescalingFactor(pout,mon,pin[0].mass(),
ppartner,mbar,k1,k2)) return false;
}
// now calculate the p reference vectors
unsigned int ifinal=0;
for(cit=branchings.begin();cit!=branchings.end();++cit) {
if((**cit).status()!=HardBranching::Outgoing) continue;
// for partners other than colour partner of decaying particle
if((*cit)->branchingParticle()!=partner) {
Lorentz5Momentum pvect = (*cit)->branchingParticle()->momentum();
pvect.boost(boostv);
pvect /= k1;
pvect.setMass(mon[ifinal]);
++ifinal;
pvect.rescaleEnergy();
pvect.boost(-boostv);
(*cit)->pVector(pvect);
(*cit)->showerMomentum(pvect);
}
// for colour partner of decaying particle
else {
Lorentz5Momentum pvect = (*cit)->branchingParticle()->momentum();
pvect.boost(boostv);
Lorentz5Momentum qtotal;
for(unsigned int ix=0;ix<pout.size();++ix) qtotal+=pout[ix];
Lorentz5Momentum qperp =
qisr-(qisr.vect()*qtotal.vect())/(qtotal.vect().mag2())*qtotal;
pvect +=qperp;
pvect /=k2;
pvect.setMass(mbar);
pvect.rescaleEnergy();
pvect.boost(-boostv);
(*cit)->pVector(pvect);
(*cit)->showerMomentum(pvect);
}
}
// For initial-state if needed
if(initial) {
tShowerParticlePtr newPartner=initial->branchingParticle()->partner();
if(newPartner) {
tHardBranchingPtr branch;
for( set<HardBranchingPtr>::iterator clt = branchings.begin();
clt != branchings.end(); ++clt ) {
if((**clt).branchingParticle()==newPartner) {
initial->colourPartner(*clt);
branch=*clt;
break;
}
}
Lorentz5Momentum pvect = initial->branchingParticle()->momentum();
initial->pVector(pvect);
Lorentz5Momentum ptemp = branch->pVector();
ptemp.boost(boostv);
Lorentz5Momentum nvect = Lorentz5Momentum( ZERO,
0.5*initial->branchingParticle()->mass()*
ptemp.vect().unit());
nvect.boost(-boostv);
initial->nVector(nvect);
}
}
// calculate the reference vectors, then for outgoing particles
for(cit=branchings.begin();cit!=branchings.end();++cit){
if((**cit).status()!=HardBranching::Outgoing) continue;
// find the partner branchings
tShowerParticlePtr newPartner=(*cit)->branchingParticle()->partner();
if(!newPartner) continue;
tHardBranchingPtr branch;
for( set<HardBranchingPtr>::iterator clt = branchings.begin();
clt != branchings.end(); ++clt ) {
if(cit==clt) continue;
if((**clt).branchingParticle()==newPartner) {
(**cit).colourPartner(*clt);
branch=*clt;
break;
}
}
if((**decay->incoming().begin()).branchingParticle()==newPartner) {
(**cit).colourPartner(*decay->incoming().begin());
branch = *decay->incoming().begin();
}
// final-state colour partner
if(branch->status()==HardBranching::Outgoing) {
Boost boost=((*cit)->pVector()+branch->pVector()).findBoostToCM();
Lorentz5Momentum pcm = branch->pVector();
pcm.boost(boost);
Lorentz5Momentum nvect = Lorentz5Momentum(ZERO,pcm.vect());
nvect.boost( -boost);
(*cit)->nVector(nvect);
}
// initial-state colour partner
else {
Boost boost=branch->pVector().findBoostToCM();
Lorentz5Momentum pcm = (*cit)->pVector();
pcm.boost(boost);
Lorentz5Momentum nvect = Lorentz5Momentum( ZERO, -pcm.vect());
nvect.boost( -boost);
(*cit)->nVector(nvect);
}
}
// now compute the new momenta
// and calculate the shower variables
for(cit=branchings.begin();cit!=branchings.end();++cit) {
if((**cit).status()!=HardBranching::Outgoing) continue;
LorentzRotation B=LorentzRotation(-boostv);
LorentzRotation A=LorentzRotation(boostv),R;
if((*cit)->branchingParticle()==partner) {
Lorentz5Momentum qnew;
Energy2 dot=(*cit)->pVector()*(*cit)->nVector();
double beta = 0.5*((*cit)->branchingParticle()->momentum().m2()
-sqr((*cit)->pVector().mass()))/dot;
qnew=(*cit)->pVector()+beta*(*cit)->nVector();
qnew.rescaleMass();
// compute the boost
R=B*solveBoost(A*qnew,A*(*cit)->branchingParticle()->momentum())*A;
}
else {
Lorentz5Momentum qnew;
if((*cit)->branchingParticle()->partner()) {
Energy2 dot=(*cit)->pVector()*(*cit)->nVector();
double beta = 0.5*((*cit)->branchingParticle()->momentum().m2()
-sqr((*cit)->pVector().mass()))/dot;
qnew=(*cit)->pVector()+beta*(*cit)->nVector();
qnew.rescaleMass();
}
else {
qnew = (*cit)->pVector();
}
// compute the boost
R=B*solveBoost(A*qnew,A*(*cit)->branchingParticle()->momentum())*A;
}
// reconstruct the momenta
(*cit)->setMomenta(R,1.0,Lorentz5Momentum());
}
if(initial) {
initial->setMomenta(LorentzRotation(),1.0,Lorentz5Momentum());
}
return true;
}
double QTildeReconstructor::
inverseRescalingFactor(vector<Lorentz5Momentum> pout,
vector<Energy> mon, Energy roots) const {
double lambda=1.;
if(pout.size()==2) {
double mu_q1(pout[0].m()/roots), mu_q2(pout[1].m()/roots);
double mu_p1(mon[0]/roots) , mu_p2(mon[1]/roots);
lambda =
((1.+mu_q1+mu_q2)*(1.-mu_q1-mu_q2)*(mu_q1-1.-mu_q2)*(mu_q2-1.-mu_q1))/
((1.+mu_p1+mu_p2)*(1.-mu_p1-mu_p2)*(mu_p1-1.-mu_p2)*(mu_p2-1.-mu_p1));
if(lambda<0.)
throw Exception() << "Rescaling factor is imaginary in QTildeReconstructor::"
<< "inverseRescalingFactor lambda^2= " << lambda
<< Exception::eventerror;
lambda = sqrt(lambda);
}
else {
unsigned int ntry=0;
// compute magnitudes once for speed
vector<Energy2> pmag;
for(unsigned int ix=0;ix<pout.size();++ix) {
pmag.push_back(pout[ix].vect().mag2());
}
// Newton-Raphson for the rescaling
vector<Energy> root(pout.size());
do {
// compute new energies
Energy sum(ZERO);
for(unsigned int ix=0;ix<pout.size();++ix) {
root[ix] = sqrt(pmag[ix]/sqr(lambda)+sqr(mon[ix]));
sum+=root[ix];
}
// if accuracy reached exit
if(abs(sum/roots-1.)<1e-10) break;
// use Newton-Raphson to compute new guess for lambda
Energy numer(ZERO),denom(ZERO);
for(unsigned int ix=0;ix<pout.size();++ix) {
numer +=root[ix];
denom +=pmag[ix]/root[ix];
}
numer-=roots;
double fact = 1.+sqr(lambda)*numer/denom;
if(fact<0.) fact=0.5;
lambda *=fact;
++ntry;
}
while(ntry<100);
}
- if(isnan(lambda))
+ if(std::isnan(lambda))
throw Exception() << "Rescaling factor is nan in QTildeReconstructor::"
<< "inverseRescalingFactor "
<< Exception::eventerror;
return lambda;
}
bool QTildeReconstructor::
deconstructGeneralSystem(HardTreePtr tree,
- ShowerInteraction::Type type) const {
+ ShowerInteraction type) const {
// extract incoming and outgoing particles
ColourSingletShower in,out;
for(set<HardBranchingPtr>::const_iterator it=tree->branchings().begin();
it!=tree->branchings().end();++it) {
if((**it).status()==HardBranching::Incoming) in .jets.push_back(*it);
else out.jets.push_back(*it);
}
LorentzRotation toRest,fromRest;
bool applyBoost(false);
// do the initial-state reconstruction
deconstructInitialInitialSystem(applyBoost,toRest,fromRest,
tree,in.jets,type);
// do the final-state reconstruction
deconstructFinalStateSystem(toRest,fromRest,tree,
out.jets,type);
// only at this point that we can be sure all the reference vectors
// are correct
for(set<HardBranchingPtr>::const_iterator it=tree->branchings().begin();
it!=tree->branchings().end();++it) {
if((**it).status()==HardBranching::Incoming) continue;
if((**it).branchingParticle()->coloured())
(**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false);
}
for(set<HardBranchingPtr>::const_iterator it=tree->incoming().begin();
it!=tree->incoming().end();++it) {
(**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false);
}
return true;
}
bool QTildeReconstructor::deconstructHardJets(HardTreePtr tree,
- ShowerInteraction::Type type) const {
+ ShowerInteraction type) const {
// inverse of old recon method
if(_reconopt == 0) {
return deconstructGeneralSystem(tree,type);
}
else if(_reconopt == 1) {
return deconstructColourSinglets(tree,type);
}
else if(_reconopt == 2) {
throw Exception() << "Inverse reconstruction is not currently supported for ReconstructionOption Colour2 "
<< "in QTildeReconstructor::deconstructHardJets(). Please use one of the other options\n"
<< Exception::runerror;
}
else if(_reconopt == 3 || _reconopt == 4 ) {
return deconstructColourPartner(tree,type);
}
else
assert(false);
}
bool QTildeReconstructor::
deconstructColourSinglets(HardTreePtr tree,
- ShowerInteraction::Type type) const {
+ ShowerInteraction type) const {
// identify the colour singlet systems
unsigned int nnun(0),nnii(0),nnif(0),nnf(0),nni(0);
vector<ColourSingletShower>
systems(identifySystems(tree->branchings(),nnun,nnii,nnif,nnf,nni));
// now decide what to do
LorentzRotation toRest,fromRest;
bool applyBoost(false);
bool general(false);
// initial-initial connection and final-state colour singlet systems
// Drell-Yan type
if(nnun==0&&nnii==1&&nnif==0&&nnf>0&&nni==0) {
// reconstruct initial-initial system
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type==II)
deconstructInitialInitialSystem(applyBoost,toRest,fromRest,tree,
systems[ix].jets,type);
}
if(type!=ShowerInteraction::QCD) {
combineFinalState(systems);
general=false;
}
}
// DIS and VBF type
else if(nnun==0&&nnii==0&&((nnif==1&&nnf>0&&nni==1)||
(nnif==2&& nni==0))) {
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type==IF)
deconstructInitialFinalSystem(tree,systems[ix].jets,type);
}
}
// e+e- type
else if(nnun==0&&nnii==0&&nnif==0&&nnf>0&&nni==2) {
// only FS needed
// but need to boost to rest frame if QED ISR
Lorentz5Momentum ptotal;
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type==I)
ptotal += systems[ix].jets[0]->branchingParticle()->momentum();
}
toRest = LorentzRotation(ptotal.findBoostToCM());
fromRest = toRest;
fromRest.invert();
if(type!=ShowerInteraction::QCD) {
combineFinalState(systems);
general=false;
}
}
// general type
else {
general = true;
}
// final-state systems except for general recon
if(!general) {
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type==F)
deconstructFinalStateSystem(toRest,fromRest,tree,
systems[ix].jets,type);
}
// only at this point that we can be sure all the reference vectors
// are correct
for(set<HardBranchingPtr>::const_iterator it=tree->branchings().begin();
it!=tree->branchings().end();++it) {
if((**it).status()==HardBranching::Incoming) continue;
if((**it).branchingParticle()->coloured())
(**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false);
}
for(set<HardBranchingPtr>::const_iterator it=tree->incoming().begin();
it!=tree->incoming().end();++it) {
(**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false);
}
return true;
}
else {
return deconstructGeneralSystem(tree,type);
}
return true;
}
bool QTildeReconstructor::
deconstructColourPartner(HardTreePtr tree,
- ShowerInteraction::Type type) const {
+ ShowerInteraction type) const {
Lorentz5Momentum ptotal;
HardBranchingPtr emitter;
ColourSingletShower incomingShower,outgoingShower;
for(set<HardBranchingPtr>::const_iterator it=tree->branchings().begin();
it!=tree->branchings().end();++it) {
if((**it).status()==HardBranching::Incoming) {
incomingShower.jets.push_back(*it);
ptotal += (*it)->branchingParticle()->momentum();
// check for emitting particle
if((**it).parent() ) {
if(!emitter)
emitter = *it;
else
throw Exception() << "Only one emitting particle allowed in "
<< "QTildeReconstructor::deconstructColourPartner()"
<< Exception::runerror;
}
}
else if ((**it).status()==HardBranching::Outgoing) {
outgoingShower.jets.push_back(*it);
// check for emitting particle
if(!(**it).children().empty() ) {
if(!emitter)
emitter = *it;
else
throw Exception() << "Only one emitting particle allowed in "
<< "QTildeReconstructor::deconstructColourPartner()"
<< Exception::runerror;
}
}
}
assert(emitter);
assert(emitter->colourPartner());
ColourSingletShower system;
system.jets.push_back(emitter);
system.jets.push_back(emitter->colourPartner());
LorentzRotation toRest,fromRest;
bool applyBoost(false);
// identify the colour singlet system
if(emitter->status() == HardBranching::Outgoing &&
emitter->colourPartner()->status() == HardBranching::Outgoing ) {
system.type=F;
// need to boost to rest frame if QED ISR
if( !incomingShower.jets[0]->branchingParticle()->coloured() &&
!incomingShower.jets[1]->branchingParticle()->coloured() ) {
Boost boost = ptotal.findBoostToCM();
toRest = LorentzRotation( boost);
fromRest = LorentzRotation(-boost);
}
else
findInitialBoost(ptotal,ptotal,toRest,fromRest);
deconstructFinalStateSystem(toRest,fromRest,tree,
system.jets,type);
}
else if (emitter->status() == HardBranching::Incoming &&
emitter->colourPartner()->status() == HardBranching::Incoming) {
system.type=II;
deconstructInitialInitialSystem(applyBoost,toRest,fromRest,tree,system.jets,type);
// make sure the recoil gets applied
deconstructFinalStateSystem(toRest,fromRest,tree,
outgoingShower.jets,type);
}
else if ((emitter->status() == HardBranching::Outgoing &&
emitter->colourPartner()->status() == HardBranching::Incoming ) ||
(emitter->status() == HardBranching::Incoming &&
emitter->colourPartner()->status() == HardBranching::Outgoing)) {
system.type=IF;
// enusre incoming first
if(system.jets[0]->status() == HardBranching::Outgoing)
swap(system.jets[0],system.jets[1]);
deconstructInitialFinalSystem(tree,system.jets,type);
}
else {
throw Exception() << "Unknown type of system in "
<< "QTildeReconstructor::deconstructColourPartner()"
<< Exception::runerror;
}
// only at this point that we can be sure all the reference vectors
// are correct
for(set<HardBranchingPtr>::const_iterator it=tree->branchings().begin();
it!=tree->branchings().end();++it) {
if((**it).status()==HardBranching::Incoming) continue;
if((**it).branchingParticle()->coloured())
(**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false);
}
for(set<HardBranchingPtr>::const_iterator it=tree->incoming().begin();
it!=tree->incoming().end();++it) {
(**it).setMomenta(LorentzRotation(),1.,Lorentz5Momentum(),false);
}
for(set<HardBranchingPtr>::const_iterator it=tree->branchings().begin();
it!=tree->branchings().end();++it) {
if((**it).status()!=HardBranching::Incoming) continue;
if(*it==system.jets[0] || *it==system.jets[1]) continue;
if((**it).branchingParticle()->momentum().z()>ZERO) {
(**it).z((**it).branchingParticle()->momentum().plus()/(**it).beam()->momentum().plus());
}
else {
(**it).z((**it).branchingParticle()->momentum().minus()/(**it).beam()->momentum().minus());
}
}
return true;
}
void QTildeReconstructor::
reconstructInitialFinalSystem(vector<ShowerProgenitorPtr> jets) const {
Lorentz5Momentum pin[2],pout[2],pbeam;
for(unsigned int ix=0;ix<jets.size();++ix) {
// final-state parton
if(jets[ix]->progenitor()->isFinalState()) {
pout[0] +=jets[ix]->progenitor()->momentum();
_progenitor = jets[ix]->progenitor();
if(jets[ix]->reconstructed()==ShowerProgenitor::notReconstructed) {
reconstructTimeLikeJet(jets[ix]->progenitor());
jets[ix]->reconstructed(ShowerProgenitor::done);
}
}
// initial-state parton
else {
pin[0] +=jets[ix]->progenitor()->momentum();
if(jets[ix]->progenitor()->showerKinematics()) {
pbeam = jets[ix]->progenitor()->showerBasis()->getBasis()[0];
}
else {
if ( jets[ix]->original()->parents().empty() ) {
pbeam = jets[ix]->progenitor()->momentum();
}
else {
pbeam = jets[ix]->original()->parents()[0]->momentum();
}
}
if(jets[ix]->reconstructed()==ShowerProgenitor::notReconstructed) {
reconstructSpaceLikeJet(jets[ix]->progenitor());
jets[ix]->reconstructed(ShowerProgenitor::done);
}
assert(!jets[ix]->original()->parents().empty());
}
}
// add intrinsic pt if needed
addIntrinsicPt(jets);
// momenta after showering
for(unsigned int ix=0;ix<jets.size();++ix) {
if(jets[ix]->progenitor()->isFinalState())
pout[1] += jets[ix]->progenitor()->momentum();
else
pin[1] += jets[ix]->progenitor()->momentum();
}
// work out the boost to the Breit frame
Lorentz5Momentum pa = pout[0]-pin[0];
Axis axis(pa.vect().unit());
LorentzRotation rot;
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
if ( sinth > 1.e-9 )
rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
rot.rotateX(Constants::pi);
rot.boostZ( pa.e()/pa.vect().mag());
Lorentz5Momentum ptemp=rot*pbeam;
Boost trans = -1./ptemp.e()*ptemp.vect();
trans.setZ(0.);
if ( trans.mag2() - 1. >= 0. ) throw KinematicsReconstructionVeto();
rot.boost(trans);
pa *=rot;
// project and calculate rescaling
// reference vectors
Lorentz5Momentum n1(ZERO,ZERO,-pa.z(),-pa.z());
Lorentz5Momentum n2(ZERO,ZERO, pa.z(),-pa.z());
Energy2 n1n2 = n1*n2;
// decompose the momenta
Lorentz5Momentum qbp=rot*pin[1],qcp=rot*pout[1];
qbp.rescaleMass();
qcp.rescaleMass();
double a[2],b[2];
a[0] = n2*qbp/n1n2;
b[0] = n1*qbp/n1n2;
Lorentz5Momentum qperp = qbp-a[0]*n1-b[0]*n2;
b[1] = 0.5;
a[1] = 0.5*(qcp.m2()-qperp.m2())/n1n2/b[1];
double kb;
if(a[0]!=0.) {
double A(0.5*a[0]),B(b[0]*a[0]-a[1]*b[1]-0.25),C(-0.5*b[0]);
if(sqr(B)-4.*A*C<0.) throw KinematicsReconstructionVeto();
kb = 0.5*(-B+sqrt(sqr(B)-4.*A*C))/A;
}
else {
kb = 0.5*b[0]/(b[0]*a[0]-a[1]*b[1]-0.25);
}
// changed to improve stability
if(kb==0.) throw KinematicsReconstructionVeto();
if ( a[1]>b[1] && abs(a[1]) < 1e-12 )
throw KinematicsReconstructionVeto();
if ( a[1]<=b[1] && abs(0.5+b[0]/kb) < 1e-12 )
throw KinematicsReconstructionVeto();
double kc = (a[1]>b[1]) ? (a[0]*kb-0.5)/a[1] : b[1]/(0.5+b[0]/kb);
if(kc==0.) throw KinematicsReconstructionVeto();
Lorentz5Momentum pnew[2] = { a[0]*kb*n1+b[0]/kb*n2+qperp,
a[1]*kc*n1+b[1]/kc*n2+qperp};
LorentzRotation rotinv=rot.inverse();
for(unsigned int ix=0;ix<jets.size();++ix) {
if(jets[ix]->progenitor()->isFinalState()) {
deepTransform(jets[ix]->progenitor(),rot);
deepTransform(jets[ix]->progenitor(),solveBoost(pnew[1],qcp));
Energy delta = jets[ix]->progenitor()->momentum().m()-jets[ix]->progenitor()->momentum().mass();
if ( abs(delta) > MeV ) throw KinematicsReconstructionVeto();
deepTransform(jets[ix]->progenitor(),rotinv);
}
else {
tPPtr parent;
boostChain(jets[ix]->progenitor(),rot,parent);
boostChain(jets[ix]->progenitor(),solveBoostZ(pnew[0],qbp),parent);
// check the first boost worked, and if not apply small correction to
// fix energy/momentum conservation
// this is a kludge but it reduces momentum non-conservation dramatically
Lorentz5Momentum pdiff = pnew[0]-jets[ix]->progenitor()->momentum();
Energy2 delta = sqr(pdiff.x())+sqr(pdiff.y())+sqr(pdiff.z())+sqr(pdiff.t());
unsigned int ntry=0;
while(delta>1e-6*GeV2 && ntry<5 ) {
ntry +=1;
boostChain(jets[ix]->progenitor(),solveBoostZ(pnew[0],jets[ix]->progenitor()->momentum()),parent);
pdiff = pnew[0]-jets[ix]->progenitor()->momentum();
delta = sqr(pdiff.x())+sqr(pdiff.y())+sqr(pdiff.z())+sqr(pdiff.t());
}
// apply test in breit-frame
Lorentz5Momentum ptest1 = parent->momentum();
Lorentz5Momentum ptest2 = rot*pbeam;
if(ptest1.z()/ptest2.z()<0. || ptest1.z()/ptest2.z()>1.)
throw KinematicsReconstructionVeto();
boostChain(jets[ix]->progenitor(),rotinv,parent);
}
}
}
bool QTildeReconstructor::addIntrinsicPt(vector<ShowerProgenitorPtr> jets) const {
bool added=false;
// add the intrinsic pt if needed
for(unsigned int ix=0;ix<jets.size();++ix) {
// only for initial-state particles which haven't radiated
if(jets[ix]->progenitor()->isFinalState()||
jets[ix]->hasEmitted()||
jets[ix]->reconstructed()==ShowerProgenitor::dontReconstruct) continue;
if(_intrinsic.find(jets[ix])==_intrinsic.end()) continue;
pair<Energy,double> pt=_intrinsic[jets[ix]];
Energy etemp = jets[ix]->original()->parents()[0]->momentum().z();
Lorentz5Momentum
p_basis(ZERO, ZERO, etemp, abs(etemp)),
n_basis(ZERO, ZERO,-etemp, abs(etemp));
double alpha = jets[ix]->progenitor()->x();
double beta = 0.5*(sqr(jets[ix]->progenitor()->data().mass())+
sqr(pt.first))/alpha/(p_basis*n_basis);
Lorentz5Momentum pnew=alpha*p_basis+beta*n_basis;
pnew.setX(pt.first*cos(pt.second));
pnew.setY(pt.first*sin(pt.second));
pnew.rescaleMass();
jets[ix]->progenitor()->set5Momentum(pnew);
added = true;
}
return added;
}
LorentzRotation QTildeReconstructor::
solveBoost(const double k, const Lorentz5Momentum & newq,
const Lorentz5Momentum & oldp ) const {
Energy q = newq.vect().mag();
Energy2 qs = sqr(q);
Energy2 Q2 = newq.mass2();
Energy kp = k*(oldp.vect().mag());
Energy2 kps = sqr(kp);
double betam = (q*newq.e() - kp*sqrt(kps + Q2))/(kps + qs + Q2);
if ( abs(betam) - 1. >= 0. ) throw KinematicsReconstructionVeto();
Boost beta = -betam*(k/kp)*oldp.vect();
double gamma = 0.;
if(Q2/sqr(oldp.e())>1e-4) {
if(betam<0.5) {
gamma = 1./sqrt(1.-sqr(betam));
}
else {
gamma = ( kps+ qs + Q2)/
sqrt(2.*kps*qs + kps*Q2 + qs*Q2 + sqr(Q2) + 2.*q*newq.e()*kp*sqrt(kps + Q2));
}
}
else {
if(k>0) {
gamma = 4.*kps*qs/sqr(kps +qs) + 2.*sqr(kps-qs)*Q2/pow<3,1>(kps +qs)
- 0.25*( sqr(kps) + 14.*kps*qs + sqr(qs))*sqr(kps-qs)/(pow<4,1>(kps +qs)*kps*qs)*sqr(Q2);
}
else {
gamma = 0.25*sqr(Q2)/(kps*qs)*(1. - 0.5*(kps+qs)/(kps*qs)*Q2);
}
if(gamma<=0.) throw KinematicsReconstructionVeto();
gamma = 1./sqrt(gamma);
}
// note that (k/kp)*oldp.vect() = oldp.vect()/oldp.vect().mag() but cheaper.
ThreeVector<Energy2> ax = newq.vect().cross( oldp.vect() );
double delta = newq.vect().angle( oldp.vect() );
LorentzRotation R;
using Constants::pi;
Energy2 scale1 = sqr(newq.x())+ sqr(newq.y())+sqr(newq.z());
Energy2 scale2 = sqr(oldp.x())+ sqr(oldp.y())+sqr(oldp.z());
if ( ax.mag2()/scale1/scale2 > 1e-28 ) {
R.rotate( delta, unitVector(ax) ).boost( beta , gamma );
}
else if(abs(delta-pi)/pi < 0.001) {
double phi=2.*pi*UseRandom::rnd();
Axis axis(cos(phi),sin(phi),0.);
axis.rotateUz(newq.vect().unit());
R.rotate(delta,axis).boost( beta , gamma );
}
else {
R.boost( beta , gamma );
}
return R;
}
LorentzRotation QTildeReconstructor::solveBoost(const Lorentz5Momentum & q,
const Lorentz5Momentum & p ) const {
Energy modp = p.vect().mag();
Energy modq = q.vect().mag();
double betam = (p.e()*modp-q.e()*modq)/(sqr(modq)+sqr(modp)+p.mass2());
if ( abs(betam)-1. >= 0. ) throw KinematicsReconstructionVeto();
Boost beta = -betam*q.vect().unit();
ThreeVector<Energy2> ax = p.vect().cross( q.vect() );
double delta = p.vect().angle( q.vect() );
LorentzRotation R;
using Constants::pi;
if ( beta.mag2() - 1. >= 0. ) throw KinematicsReconstructionVeto();
if ( ax.mag2()/GeV2/MeV2 > 1e-16 ) {
R.rotate( delta, unitVector(ax) ).boost( beta );
}
else {
R.boost( beta );
}
return R;
}
LorentzRotation QTildeReconstructor::solveBoostZ(const Lorentz5Momentum & q,
const Lorentz5Momentum & p ) const {
static const double eps = 1e-6;
LorentzRotation R;
double beta;
Energy2 mt2 = p.mass()<ZERO ? -sqr(p.mass())+sqr(p.x())+sqr(p.y()) : sqr(p.mass())+sqr(p.x())+sqr(p.y()) ;
double ratio = mt2/(sqr(p.t())+sqr(q.t()));
if(abs(ratio)>eps) {
double erat = (q.t()+q.z())/(p.t()+p.z());
Energy2 den = mt2*(erat+1./erat);
Energy2 num = (q.z()-p.z())*(q.t()+p.t()) + (p.z()+q.z())*(p.t()-q.t());
beta = num/den;
if ( abs(beta) - 1. >= 0. ) throw KinematicsReconstructionVeto();
R.boostZ(beta);
}
else {
double er = sqr(p.t()/q.t());
double x = ratio+0.125*(er+10.+1./er)*sqr(ratio);
beta = -(p.t()-q.t())*(p.t()+q.t())/(sqr(p.t())+sqr(q.t()))*(1.+x);
double gamma = (4.*sqr(p.t()*q.t()) +sqr(p.t()-q.t())*sqr(p.t()+q.t())*
(-2.*x+sqr(x)))/sqr(sqr(p.t())+sqr(q.t()));
if ( abs(beta) - 1. >= 0. ) throw KinematicsReconstructionVeto();
gamma = 1./sqrt(gamma);
R.boost(0.,0.,beta,gamma);
}
Lorentz5Momentum ptest = R*p;
if(ptest.z()/q.z() < 0. || ptest.t()/q.t() < 0. ) {
throw KinematicsReconstructionVeto();
}
return R;
}
void QTildeReconstructor::
reconstructFinalStateSystem(bool applyBoost,
const LorentzRotation & toRest,
const LorentzRotation & fromRest,
vector<ShowerProgenitorPtr> jets) const {
LorentzRotation trans = applyBoost? toRest : LorentzRotation();
// special for case of individual particle
if(jets.size()==1) {
deepTransform(jets[0]->progenitor(),trans);
deepTransform(jets[0]->progenitor(),fromRest);
return;
}
bool radiated(false);
// find the hard process centre-of-mass energy
Lorentz5Momentum pcm;
// check if radiated and calculate total momentum
for(unsigned int ix=0;ix<jets.size();++ix) {
radiated |=jets[ix]->hasEmitted();
pcm += jets[ix]->progenitor()->momentum();
}
if(applyBoost) pcm *= trans;
// check if in CMF frame
Boost beta_cm = pcm.findBoostToCM();
bool gottaBoost(false);
if(beta_cm.mag() > 1e-12) {
gottaBoost = true;
trans.boost(beta_cm);
}
// collection of pointers to initial hard particle and jet momenta
// for final boosts
JetKinVect jetKinematics;
vector<ShowerProgenitorPtr>::const_iterator cit;
for(cit = jets.begin(); cit != jets.end(); cit++) {
JetKinStruct tempJetKin;
tempJetKin.parent = (*cit)->progenitor();
if(applyBoost || gottaBoost) {
deepTransform(tempJetKin.parent,trans);
}
tempJetKin.p = (*cit)->progenitor()->momentum();
_progenitor=tempJetKin.parent;
if((**cit).reconstructed()==ShowerProgenitor::notReconstructed) {
radiated |= reconstructTimeLikeJet((*cit)->progenitor());
(**cit).reconstructed(ShowerProgenitor::done);
}
else {
radiated |= !(*cit)->progenitor()->children().empty();
}
tempJetKin.q = (*cit)->progenitor()->momentum();
jetKinematics.push_back(tempJetKin);
}
// default option rescale everything with the same factor
if( _finalStateReconOption == 0 || jetKinematics.size() <= 2 ) {
// find the rescaling factor
double k = 0.0;
if(radiated) {
k = solveKfactor(pcm.m(), jetKinematics);
// perform the rescaling and boosts
for(JetKinVect::iterator it = jetKinematics.begin();
it != jetKinematics.end(); ++it) {
LorentzRotation Trafo = solveBoost(k, it->q, it->p);
deepTransform(it->parent,Trafo);
}
}
}
// different treatment of most off-shell
else if ( _finalStateReconOption <= 4 ) {
// sort the jets by virtuality
std::sort(jetKinematics.begin(),jetKinematics.end(),JetOrdering());
// Bryan's procedures from FORTRAN
if( _finalStateReconOption <=2 ) {
// loop over the off-shell partons, _finalStateReconOption==1 only first ==2 all
JetKinVect::const_iterator jend = _finalStateReconOption==1 ? jetKinematics.begin()+1 : jetKinematics.end();
for(JetKinVect::const_iterator jit=jetKinematics.begin(); jit!=jend;++jit) {
// calculate the 4-momentum of the recoiling system
Lorentz5Momentum psum;
bool done = true;
for(JetKinVect::const_iterator it=jetKinematics.begin();it!=jetKinematics.end();++it) {
if(it==jit) {
done = false;
continue;
}
// first option put on-shell and sum 4-momenta
if( _finalStateReconOption == 1 ) {
LorentzRotation Trafo = solveBoost(1., it->q, it->p);
deepTransform(it->parent,Trafo);
psum += it->parent->momentum();
}
// second option, sum momenta
else {
// already rescaled
if(done) psum += it->parent->momentum();
// still needs to be rescaled
else psum += it->p;
}
}
// set the mass
psum.rescaleMass();
// calculate the 3-momentum rescaling factor
Energy2 s(pcm.m2());
Energy2 m1sq(jit->q.m2()),m2sq(psum.m2());
Energy4 num = sqr(s - m1sq - m2sq) - 4.*m1sq*m2sq;
if(num<ZERO) throw KinematicsReconstructionVeto();
double k = sqrt( num / (4.*s*jit->p.vect().mag2()) );
// boost the off-shell parton
LorentzRotation B1 = solveBoost(k, jit->q, jit->p);
deepTransform(jit->parent,B1);
// boost everything else to rescale
LorentzRotation B2 = solveBoost(k, psum, psum);
for(JetKinVect::iterator it=jetKinematics.begin();it!=jetKinematics.end();++it) {
if(it==jit) continue;
deepTransform(it->parent,B2);
it->p *= B2;
it->q *= B2;
}
}
}
// Peter's C++ procedures
else {
reconstructFinalFinalOffShell(jetKinematics,pcm.m2(), _finalStateReconOption == 4);
}
}
else
assert(false);
// apply the final boosts
if(gottaBoost || applyBoost) {
LorentzRotation finalBoosts;
if(gottaBoost) finalBoosts.boost(-beta_cm);
if(applyBoost) finalBoosts.transform(fromRest);
for(JetKinVect::iterator it = jetKinematics.begin();
it != jetKinematics.end(); ++it) {
deepTransform(it->parent,finalBoosts);
}
}
}
void QTildeReconstructor::
reconstructInitialInitialSystem(bool & applyBoost,
LorentzRotation & toRest,
LorentzRotation & fromRest,
vector<ShowerProgenitorPtr> jets) const {
bool radiated = false;
Lorentz5Momentum pcm;
// check whether particles radiated and calculate total momentum
for( unsigned int ix = 0; ix < jets.size(); ++ix ) {
radiated |= jets[ix]->hasEmitted();
pcm += jets[ix]->progenitor()->momentum();
if(jets[ix]->original()->parents().empty()) return;
}
pcm.rescaleMass();
// check if intrinsic pt to be added
radiated |= !_intrinsic.empty();
// if no radiation return
if(!radiated) {
for(unsigned int ix=0;ix<jets.size();++ix) {
if(jets[ix]->reconstructed()==ShowerProgenitor::notReconstructed)
jets[ix]->reconstructed(ShowerProgenitor::done);
}
return;
}
// initial state shuffling
applyBoost=false;
vector<Lorentz5Momentum> p, pq, p_in;
vector<Energy> pts;
for(unsigned int ix=0;ix<jets.size();++ix) {
// add momentum to vector
p_in.push_back(jets[ix]->progenitor()->momentum());
// reconstruct the jet
if(jets[ix]->reconstructed()==ShowerProgenitor::notReconstructed) {
radiated |= reconstructSpaceLikeJet(jets[ix]->progenitor());
jets[ix]->reconstructed(ShowerProgenitor::done);
}
assert(!jets[ix]->original()->parents().empty());
Energy etemp = jets[ix]->original()->parents()[0]->momentum().z();
Lorentz5Momentum ptemp = Lorentz5Momentum(ZERO, ZERO, etemp, abs(etemp));
pq.push_back(ptemp);
pts.push_back(jets[ix]->highestpT());
}
// add the intrinsic pt if needed
radiated |=addIntrinsicPt(jets);
for(unsigned int ix=0;ix<jets.size();++ix) {
p.push_back(jets[ix]->progenitor()->momentum());
}
double x1 = p_in[0].z()/pq[0].z();
double x2 = p_in[1].z()/pq[1].z();
vector<double> beta=initialStateRescaling(x1,x2,p_in[0]+p_in[1],p,pq,pts);
// if not need don't apply boosts
if(!(radiated && p.size() == 2 && pq.size() == 2)) return;
applyBoost=true;
// apply the boosts
Lorentz5Momentum newcmf;
for(unsigned int ix=0;ix<jets.size();++ix) {
tPPtr toBoost = jets[ix]->progenitor();
Boost betaboost(0, 0, beta[ix]);
tPPtr parent;
boostChain(toBoost, LorentzRotation(0.,0.,beta[ix]),parent);
if(parent->momentum().e()/pq[ix].e()>1.||
parent->momentum().z()/pq[ix].z()>1.) throw KinematicsReconstructionVeto();
newcmf+=toBoost->momentum();
}
if(newcmf.m()<ZERO||newcmf.e()<ZERO) throw KinematicsReconstructionVeto();
findInitialBoost(pcm,newcmf,toRest,fromRest);
}
void QTildeReconstructor::
deconstructInitialInitialSystem(bool & applyBoost,
LorentzRotation & toRest,
LorentzRotation & fromRest,
HardTreePtr tree,
vector<HardBranchingPtr> jets,
- ShowerInteraction::Type) const {
+ ShowerInteraction) const {
assert(jets.size()==2);
// put beam with +z first
if(jets[0]->beam()->momentum().z()<ZERO) swap(jets[0],jets[1]);
// get the momenta of the particles
vector<Lorentz5Momentum> pin,pq;
for(unsigned int ix=0;ix<jets.size();++ix) {
pin.push_back(jets[ix]->branchingParticle()->momentum());
Energy etemp = jets[ix]->beam()->momentum().z();
pq.push_back(Lorentz5Momentum(ZERO, ZERO,etemp, abs(etemp)));
}
// calculate the rescaling
double x[2];
Lorentz5Momentum pcm=pin[0]+pin[1];
assert(pcm.mass2()>ZERO);
pcm.rescaleMass();
vector<double> boost = inverseInitialStateRescaling(x[0],x[1],pcm,pin,pq);
set<HardBranchingPtr>::const_iterator cjt=tree->incoming().begin();
HardBranchingPtr incoming[2];
incoming[0] = *cjt;
++cjt;
incoming[1] = *cjt;
if((*tree->incoming().begin())->beam()->momentum().z()/pq[0].z()<0.)
swap(incoming[0],incoming[1]);
// apply the boost the the particles
unsigned int iswap[2]={1,0};
for(unsigned int ix=0;ix<2;++ix) {
LorentzRotation R(0.,0.,-boost[ix]);
incoming[ix]->pVector(pq[ix]);
incoming[ix]->nVector(pq[iswap[ix]]);
incoming[ix]->setMomenta(R,1.,Lorentz5Momentum());
jets[ix]->showerMomentum(x[ix]*jets[ix]->pVector());
}
// and calculate the boosts
applyBoost=true;
// do one boost
if(_initialBoost==0) {
toRest = LorentzRotation(-pcm.boostVector());
}
else if(_initialBoost==1) {
// first the transverse boost
Energy pT = sqrt(sqr(pcm.x())+sqr(pcm.y()));
double beta = -pT/pcm.t();
toRest=LorentzRotation(Boost(beta*pcm.x()/pT,beta*pcm.y()/pT,0.));
// the longitudinal
beta = pcm.z()/sqrt(pcm.m2()+sqr(pcm.z()));
toRest.boost(Boost(0.,0.,-beta));
}
else
assert(false);
fromRest = LorentzRotation((jets[0]->showerMomentum()+
jets[1]->showerMomentum()).boostVector());
}
void QTildeReconstructor::
deconstructFinalStateSystem(const LorentzRotation & toRest,
const LorentzRotation & fromRest,
HardTreePtr tree, vector<HardBranchingPtr> jets,
- ShowerInteraction::Type type) const {
+ ShowerInteraction type) const {
LorentzRotation trans = toRest;
if(jets.size()==1) {
Lorentz5Momentum pnew = toRest*(jets[0]->branchingParticle()->momentum());
pnew *= fromRest;
jets[0]-> original(pnew);
jets[0]->showerMomentum(pnew);
// find the colour partners
ShowerParticleVector particles;
vector<Lorentz5Momentum> ptemp;
set<HardBranchingPtr>::const_iterator cjt;
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
ptemp.push_back((**cjt).branchingParticle()->momentum());
(**cjt).branchingParticle()->set5Momentum((**cjt).showerMomentum());
particles.push_back((**cjt).branchingParticle());
}
dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->showerModel()->partnerFinder()
->setInitialEvolutionScales(particles,false,type,false);
// calculate the reference vectors
unsigned int iloc(0);
set<HardBranchingPtr>::iterator clt;
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
// reset the momentum
(**cjt).branchingParticle()->set5Momentum(ptemp[iloc]);
++iloc;
// sort out the partners
tShowerParticlePtr partner =
(*cjt)->branchingParticle()->partner();
if(!partner) continue;
for(clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) {
if((**clt).branchingParticle()==partner) {
(**cjt).colourPartner(*clt);
break;
}
}
tHardBranchingPtr branch;
for(clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) {
if(clt==cjt) continue;
if((*clt)->branchingParticle()==partner) {
branch=*clt;
break;
}
}
}
return;
}
vector<HardBranchingPtr>::iterator cit;
vector<Lorentz5Momentum> pout;
vector<Energy> mon;
Lorentz5Momentum pin;
for(cit=jets.begin();cit!=jets.end();++cit) {
pout.push_back((*cit)->branchingParticle()->momentum());
mon.push_back(findMass(*cit));
pin+=pout.back();
}
// boost all the momenta to the rest frame of the decaying particle
pin.rescaleMass();
pin *=trans;
Boost beta_cm = pin.findBoostToCM();
bool gottaBoost(false);
if(beta_cm.mag() > 1e-12) {
gottaBoost = true;
trans.boost(beta_cm);
pin.boost(beta_cm);
}
for(unsigned int ix=0;ix<pout.size();++ix) {
pout[ix].transform(trans);
}
// rescaling factor
double lambda=inverseRescalingFactor(pout,mon,pin.mass());
if (lambda< 1.e-10) throw KinematicsReconstructionVeto();
// now calculate the p reference vectors
for(unsigned int ix=0;ix<jets.size();++ix) {
Lorentz5Momentum pvect = jets[ix]->branchingParticle()->momentum();
pvect.transform(trans);
pvect /= lambda;
pvect.setMass(mon[ix]);
pvect.rescaleEnergy();
if(gottaBoost) pvect.boost(-beta_cm);
pvect.transform(fromRest);
jets[ix]->pVector(pvect);
jets[ix]->showerMomentum(pvect);
}
// find the colour partners
ShowerParticleVector particles;
vector<Lorentz5Momentum> ptemp;
set<HardBranchingPtr>::const_iterator cjt;
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
ptemp.push_back((**cjt).branchingParticle()->momentum());
(**cjt).branchingParticle()->set5Momentum((**cjt).showerMomentum());
particles.push_back((**cjt).branchingParticle());
}
dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->showerModel()->partnerFinder()
->setInitialEvolutionScales(particles,false,type,false);
// calculate the reference vectors
unsigned int iloc(0);
set<HardBranchingPtr>::iterator clt;
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
// reset the momentum
(**cjt).branchingParticle()->set5Momentum(ptemp[iloc]);
++iloc;
}
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
// sort out the partners
tShowerParticlePtr partner =
(*cjt)->branchingParticle()->partner();
if(!partner) continue;
for(clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) {
if((**clt).branchingParticle()==partner) {
(**cjt).colourPartner(*clt);
break;
}
}
tHardBranchingPtr branch;
for(clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) {
if(clt==cjt) continue;
if((*clt)->branchingParticle()==partner) {
branch=*clt;
break;
}
}
// compute the reference vectors
// both incoming, should all ready be done
if((**cjt).status()==HardBranching::Incoming &&
(**clt).status()==HardBranching::Incoming) {
continue;
}
// both outgoing
else if((**cjt).status()!=HardBranching::Incoming&&
branch->status()==HardBranching::Outgoing) {
Boost boost=((*cjt)->pVector()+branch->pVector()).findBoostToCM();
Lorentz5Momentum pcm = branch->pVector();
pcm.boost(boost);
Lorentz5Momentum nvect = Lorentz5Momentum(ZERO,pcm.vect());
nvect.boost( -boost);
(**cjt).nVector(nvect);
}
else if((**cjt).status()==HardBranching::Incoming) {
Lorentz5Momentum pa = -(**cjt).showerMomentum()+branch->showerMomentum();
Lorentz5Momentum pb = (**cjt).showerMomentum();
Axis axis(pa.vect().unit());
LorentzRotation rot;
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
rot.rotateX(Constants::pi);
rot.boostZ( pa.e()/pa.vect().mag());
pb*=rot;
Boost trans = -1./pb.e()*pb.vect();
trans.setZ(0.);
rot.boost(trans);
Energy scale=(**cjt).beam()->momentum().e();
Lorentz5Momentum pbasis(ZERO,(**cjt).beam()->momentum().vect().unit()*scale);
Lorentz5Momentum pcm = rot*pbasis;
rot.invert();
(**cjt).nVector(rot*Lorentz5Momentum(ZERO,-pcm.vect()));
tHardBranchingPtr branch2 = *cjt;;
while (branch2->parent()) {
branch2=branch2->parent();
branch2->nVector(rot*Lorentz5Momentum(ZERO,-pcm.vect()));
}
}
else if(branch->status()==HardBranching::Incoming) {
(**cjt).nVector(Lorentz5Momentum(ZERO,branch->showerMomentum().vect()));
}
}
// now compute the new momenta
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
if(!(*cjt)->branchingParticle()->isFinalState()) continue;
Lorentz5Momentum qnew;
if((*cjt)->branchingParticle()->partner()) {
Energy2 dot=(*cjt)->pVector()*(*cjt)->nVector();
double beta = 0.5*((*cjt)->branchingParticle()->momentum().m2()
-sqr((*cjt)->pVector().mass()))/dot;
qnew=(*cjt)->pVector()+beta*(*cjt)->nVector();
qnew.rescaleMass();
}
else {
qnew = (*cjt)->pVector();
}
// qnew is the unshuffled momentum in the rest frame of the p basis vectors,
// for the simple case Z->q qbar g this was checked against analytic formulae.
// compute the boost
LorentzRotation R=solveBoost(qnew,
toRest*(*cjt)->branchingParticle()->momentum())*toRest;
(*cjt)->setMomenta(R,1.0,Lorentz5Momentum());
}
}
Energy QTildeReconstructor::momConsEq(double k,
const Energy & root_s,
const JetKinVect & jets) const {
static const Energy2 eps=1e-8*GeV2;
Energy dum = ZERO;
for(JetKinVect::const_iterator it = jets.begin(); it != jets.end(); ++it) {
Energy2 dum2 = (it->q).m2() + sqr(k)*(it->p).vect().mag2();
if(dum2 < ZERO) {
if(dum2 < -eps) throw KinematicsReconstructionVeto();
dum2 = ZERO;
}
dum += sqrt(dum2);
}
return dum - root_s;
}
void QTildeReconstructor::boostChain(tPPtr p, const LorentzRotation &bv,
tPPtr & parent) const {
if(!p->parents().empty()) boostChain(p->parents()[0], bv,parent);
else parent=p;
p->transform(bv);
if(p->children().size()==2) {
if(dynamic_ptr_cast<ShowerParticlePtr>(p->children()[1]))
deepTransform(p->children()[1],bv);
}
}
namespace {
bool sortJets(ShowerProgenitorPtr j1, ShowerProgenitorPtr j2) {
return j1->highestpT()>j2->highestpT();
}
}
void QTildeReconstructor::
reconstructGeneralSystem(vector<ShowerProgenitorPtr> & ShowerHardJets) const {
// find initial- and final-state systems
ColourSingletSystem in,out;
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
if(ShowerHardJets[ix]->progenitor()->isFinalState())
out.jets.push_back(ShowerHardJets[ix]);
else
in.jets.push_back(ShowerHardJets[ix]);
}
// reconstruct initial-initial system
LorentzRotation toRest,fromRest;
bool applyBoost(false);
// reconstruct initial-initial system
reconstructInitialInitialSystem(applyBoost,toRest,fromRest,in.jets);
// reconstruct the final-state systems
reconstructFinalStateSystem(applyBoost,toRest,fromRest,out.jets);
}
void QTildeReconstructor::
reconstructFinalFirst(vector<ShowerProgenitorPtr> & ShowerHardJets) const {
static const Energy2 minQ2 = 1e-4*GeV2;
map<ShowerProgenitorPtr,bool> used;
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
used[ShowerHardJets[ix]] = false;
} // first to the final-state reconstruction of any systems which need it
set<ShowerProgenitorPtr> outgoing;
// first find any particles with final state partners
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
if(ShowerHardJets[ix]->progenitor()->isFinalState()&&
ShowerHardJets[ix]->progenitor()->partner()&&
ShowerHardJets[ix]->progenitor()->partner()->isFinalState()) outgoing.insert(ShowerHardJets[ix]);
}
// then find the colour partners
if(!outgoing.empty()) {
set<ShowerProgenitorPtr> partners;
for(set<ShowerProgenitorPtr>::const_iterator it=outgoing.begin();it!=outgoing.end();++it) {
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
if((**it).progenitor()->partner()==ShowerHardJets[ix]->progenitor()) {
partners.insert(ShowerHardJets[ix]);
break;
}
}
}
outgoing.insert(partners.begin(),partners.end());
}
// do the final-state reconstruction if needed
if(!outgoing.empty()) {
assert(outgoing.size()!=1);
LorentzRotation toRest,fromRest;
vector<ShowerProgenitorPtr> outgoingJets(outgoing.begin(),outgoing.end());
reconstructFinalStateSystem(false,toRest,fromRest,outgoingJets);
}
// Now do any initial-final systems which are needed
vector<ColourSingletSystem> IFSystems;
// find the systems N.B. can have duplicates
// find initial-state with FS partners or FS with IS partners
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
if(!ShowerHardJets[ix]->progenitor()->isFinalState()&&
ShowerHardJets[ix]->progenitor()->partner()&&
ShowerHardJets[ix]->progenitor()->partner()->isFinalState()) {
IFSystems.push_back(ColourSingletSystem(IF,ShowerHardJets[ix]));
}
else if(ShowerHardJets[ix]->progenitor()->isFinalState()&&
ShowerHardJets[ix]->progenitor()->partner()&&
!ShowerHardJets[ix]->progenitor()->partner()->isFinalState()) {
IFSystems.push_back(ColourSingletSystem(IF,ShowerHardJets[ix]));
}
}
// then add the partners
for(unsigned int is=0;is<IFSystems.size();++is) {
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
if(IFSystems[is].jets[0]->progenitor()->partner()==ShowerHardJets[ix]->progenitor()) {
IFSystems[is].jets.push_back(ShowerHardJets[ix]);
}
}
// ensure incoming first
if(IFSystems[is].jets[0]->progenitor()->isFinalState())
swap(IFSystems[is].jets[0],IFSystems[is].jets[1]);
}
if(!IFSystems.empty()) {
unsigned int istart = UseRandom::irnd(IFSystems.size());
unsigned int istop=IFSystems.size();
for(unsigned int is=istart;is<=istop;++is) {
if(is==IFSystems.size()) {
if(istart!=0) {
istop = istart-1;
is=0;
}
else break;
}
// skip duplicates
if(used[IFSystems[is].jets[0]] &&
used[IFSystems[is].jets[1]] ) continue;
if(IFSystems[is].jets[0]->original()&&IFSystems[is].jets[0]->original()->parents().empty()) continue;
Lorentz5Momentum psum;
for(unsigned int ix=0;ix<IFSystems[is].jets.size();++ix) {
if(IFSystems[is].jets[ix]->progenitor()->isFinalState())
psum += IFSystems[is].jets[ix]->progenitor()->momentum();
else
psum -= IFSystems[is].jets[ix]->progenitor()->momentum();
}
if(-psum.m2()>minQ2) {
reconstructInitialFinalSystem(IFSystems[is].jets);
for(unsigned int ix=0;ix<IFSystems[is].jets.size();++ix) {
used[IFSystems[is].jets[ix]] = true;
}
}
}
}
// now we finally need to handle the initial state system
ColourSingletSystem in,out;
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
if(ShowerHardJets[ix]->progenitor()->isFinalState())
out.jets.push_back(ShowerHardJets[ix]);
else
in.jets.push_back(ShowerHardJets[ix]);
}
// reconstruct initial-initial system
bool doRecon = false;
for(unsigned int ix=0;ix<in.jets.size();++ix) {
if(!used[in.jets[ix]]) {
doRecon = true;
break;
}
}
LorentzRotation toRest,fromRest;
bool applyBoost(false);
if(doRecon) {
reconstructInitialInitialSystem(applyBoost,toRest,fromRest,in.jets);
}
// reconstruct the final-state systems
if(!doRecon) {
for(unsigned int ix=0;ix<out.jets.size();++ix) {
if(!used[out.jets[ix]]) {
doRecon = true;
break;
}
}
}
if(doRecon) {
reconstructFinalStateSystem(applyBoost,toRest,fromRest,out.jets);
}
}
void QTildeReconstructor::
reconstructColourPartner(vector<ShowerProgenitorPtr> & ShowerHardJets) const {
static const Energy2 minQ2 = 1e-4*GeV2;
// sort the vector by hardness of emission
std::sort(ShowerHardJets.begin(),ShowerHardJets.end(),sortJets);
// map between particles and progenitors for easy lookup
map<ShowerParticlePtr,ShowerProgenitorPtr> progenitorMap;
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
progenitorMap[ShowerHardJets[ix]->progenitor()] = ShowerHardJets[ix];
}
// check that the IF systems can be reconstructed
bool canReconstruct = true;
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
tShowerParticlePtr progenitor = ShowerHardJets[ix]->progenitor();
tShowerParticlePtr partner = progenitor->partner();
if(!partner) continue;
else if((progenitor->isFinalState() &&
!partner->isFinalState()) ||
(!progenitor->isFinalState() &&
partner->isFinalState()) ) {
vector<ShowerProgenitorPtr> jets(2);
jets[0] = ShowerHardJets[ix];
jets[1] = progenitorMap[partner];
Lorentz5Momentum psum;
for(unsigned int iy=0;iy<jets.size();++iy) {
if(jets[iy]->progenitor()->isFinalState())
psum += jets[iy]->progenitor()->momentum();
else
psum -= jets[iy]->progenitor()->momentum();
}
if(-psum.m2()<minQ2) {
canReconstruct = false;
break;
}
}
}
if(!canReconstruct) {
reconstructGeneralSystem(ShowerHardJets);
return;
}
map<ShowerProgenitorPtr,bool> used;
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
used[ShowerHardJets[ix]] = false;
}
for(unsigned int ix=0;ix<ShowerHardJets.size();++ix) {
// skip jets which have already been handled
if(ShowerHardJets[ix]->reconstructed()==ShowerProgenitor::done) continue;
// already reconstructed
if(used[ShowerHardJets[ix]]) continue;
// no partner continue
tShowerParticlePtr progenitor = ShowerHardJets[ix]->progenitor();
tShowerParticlePtr partner = progenitor->partner();
if(!partner) {
// check if there's a daughter tree which also needs boosting
Lorentz5Momentum porig = progenitor->momentum();
map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator tit;
for(tit = _currentTree->treelinks().begin();
tit != _currentTree->treelinks().end();++tit) {
// if there is, boost it
if(tit->second.first && tit->second.second==progenitor) {
Lorentz5Momentum pnew = tit->first->incomingLines().begin()
->first->progenitor()->momentum();
pnew *= tit->first->transform();
Lorentz5Momentum pdiff = porig-pnew;
Energy2 test = sqr(pdiff.x()) + sqr(pdiff.y()) +
sqr(pdiff.z()) + sqr(pdiff.t());
LorentzRotation rot;
if(test>1e-6*GeV2) rot = solveBoost(porig,pnew);
tit->first->transform(rot,false);
_treeBoosts[tit->first].push_back(rot);
}
}
ShowerHardJets[ix]->reconstructed(ShowerProgenitor::done);
continue;
}
// do the reconstruction
// final-final
if(progenitor->isFinalState() &&
partner->isFinalState() ) {
LorentzRotation toRest,fromRest;
vector<ShowerProgenitorPtr> jets(2);
jets[0] = ShowerHardJets[ix];
jets[1] = progenitorMap[partner];
if(_reconopt==4 && jets[1]->reconstructed()==ShowerProgenitor::notReconstructed)
jets[1]->reconstructed(ShowerProgenitor::dontReconstruct);
reconstructFinalStateSystem(false,toRest,fromRest,jets);
if(_reconopt==4 && jets[1]->reconstructed()==ShowerProgenitor::dontReconstruct)
jets[1]->reconstructed(ShowerProgenitor::notReconstructed);
used[jets[0]] = true;
if(_reconopt==3) used[jets[1]] = true;
}
// initial-final
else if((progenitor->isFinalState() &&
!partner->isFinalState()) ||
(!progenitor->isFinalState() &&
partner->isFinalState()) ) {
vector<ShowerProgenitorPtr> jets(2);
jets[0] = ShowerHardJets[ix];
jets[1] = progenitorMap[partner];
if(jets[0]->progenitor()->isFinalState()) swap(jets[0],jets[1]);
if(jets[0]->original()&&jets[0]->original()->parents().empty()) continue;
Lorentz5Momentum psum;
for(unsigned int iy=0;iy<jets.size();++iy) {
if(jets[iy]->progenitor()->isFinalState())
psum += jets[iy]->progenitor()->momentum();
else
psum -= jets[iy]->progenitor()->momentum();
}
if(_reconopt==4 && progenitorMap[partner]->reconstructed()==ShowerProgenitor::notReconstructed)
progenitorMap[partner]->reconstructed(ShowerProgenitor::dontReconstruct);
reconstructInitialFinalSystem(jets);
if(_reconopt==4 && progenitorMap[partner]->reconstructed()==ShowerProgenitor::dontReconstruct)
progenitorMap[partner]->reconstructed(ShowerProgenitor::notReconstructed);
used[ShowerHardJets[ix]] = true;
if(_reconopt==3) used[progenitorMap[partner]] = true;
}
// initial-initial
else if(!progenitor->isFinalState() &&
!partner->isFinalState() ) {
ColourSingletSystem in,out;
in.jets.push_back(ShowerHardJets[ix]);
in.jets.push_back(progenitorMap[partner]);
for(unsigned int iy=0;iy<ShowerHardJets.size();++iy) {
if(ShowerHardJets[iy]->progenitor()->isFinalState())
out.jets.push_back(ShowerHardJets[iy]);
}
LorentzRotation toRest,fromRest;
bool applyBoost(false);
if(_reconopt==4 && in.jets[1]->reconstructed()==ShowerProgenitor::notReconstructed)
in.jets[1]->reconstructed(ShowerProgenitor::dontReconstruct);
reconstructInitialInitialSystem(applyBoost,toRest,fromRest,in.jets);
if(_reconopt==4 && in.jets[1]->reconstructed()==ShowerProgenitor::dontReconstruct)
in.jets[1]->reconstructed(ShowerProgenitor::notReconstructed);
used[in.jets[0]] = true;
if(_reconopt==3) used[in.jets[1]] = true;
for(unsigned int iy=0;iy<out.jets.size();++iy) {
if(out.jets[iy]->reconstructed()==ShowerProgenitor::notReconstructed)
out.jets[iy]->reconstructed(ShowerProgenitor::dontReconstruct);
}
// reconstruct the final-state systems
LorentzRotation finalBoosts;
finalBoosts.transform( toRest);
finalBoosts.transform(fromRest);
for(unsigned int iy=0;iy<out.jets.size();++iy) {
deepTransform(out.jets[iy]->progenitor(),finalBoosts);
}
for(unsigned int iy=0;iy<out.jets.size();++iy) {
if(out.jets[iy]->reconstructed()==ShowerProgenitor::dontReconstruct)
out.jets[iy]->reconstructed(ShowerProgenitor::notReconstructed);
}
}
}
}
bool QTildeReconstructor::
inverseDecayRescalingFactor(vector<Lorentz5Momentum> pout,
vector<Energy> mon,Energy roots,
Lorentz5Momentum ppartner, Energy mbar,
double & k1, double & k2) const {
ThreeVector<Energy> qtotal;
vector<Energy2> pmag;
for(unsigned int ix=0;ix<pout.size();++ix) {
pmag.push_back(pout[ix].vect().mag2());
qtotal+=pout[ix].vect();
}
Energy2 dot1 = qtotal*ppartner.vect();
Energy2 qmag2=qtotal.mag2();
double a = -dot1/qmag2;
static const Energy eps=1e-10*GeV;
unsigned int itry(0);
Energy numer(ZERO),denom(ZERO);
k1=1.;
do {
++itry;
numer=denom=0.*GeV;
double k12=sqr(k1);
for(unsigned int ix=0;ix<pout.size();++ix) {
Energy en = sqrt(pmag[ix]/k12+sqr(mon[ix]));
numer += en;
denom += pmag[ix]/en;
}
Energy en = sqrt(qmag2/k12+sqr(mbar));
numer += en-roots;
denom += qmag2/en;
k1 += numer/denom*k12*k1;
if(abs(k1)>1e10) return false;
}
while (abs(numer)>eps&&itry<100);
k1 = abs(k1);
k2 = a*k1;
return itry<100;
}
void QTildeReconstructor::
deconstructInitialFinalSystem(HardTreePtr tree,vector<HardBranchingPtr> jets,
- ShowerInteraction::Type type) const {
+ ShowerInteraction type) const {
HardBranchingPtr incoming;
Lorentz5Momentum pin[2],pout[2],pbeam;
HardBranchingPtr initial;
Energy mc(ZERO);
for(unsigned int ix=0;ix<jets.size();++ix) {
// final-state parton
if(jets[ix]->status()==HardBranching::Outgoing) {
pout[0] += jets[ix]->branchingParticle()->momentum();
mc = jets[ix]->branchingParticle()->thePEGBase() ?
jets[ix]->branchingParticle()->thePEGBase()->mass() :
jets[ix]->branchingParticle()->dataPtr()->mass();
}
// initial-state parton
else {
pin[0] += jets[ix]->branchingParticle()->momentum();
initial = jets[ix];
pbeam = jets[ix]->beam()->momentum();
Energy scale=pbeam.t();
pbeam = Lorentz5Momentum(ZERO,pbeam.vect().unit()*scale);
incoming = jets[ix];
while(incoming->parent()) incoming = incoming->parent();
}
}
if(jets.size()>2) {
pout[0].rescaleMass();
mc = pout[0].mass();
}
// work out the boost to the Breit frame
Lorentz5Momentum pa = pout[0]-pin[0];
Axis axis(pa.vect().unit());
LorentzRotation rot;
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
if(axis.perp2()>0.) {
rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
rot.rotateX(Constants::pi);
rot.boostZ( pa.e()/pa.vect().mag());
}
// transverse part
Lorentz5Momentum paxis=rot*pbeam;
Boost trans = -1./paxis.e()*paxis.vect();
trans.setZ(0.);
rot.boost(trans);
pa *= rot;
// reference vectors
Lorentz5Momentum n1(ZERO,ZERO,-pa.z(),-pa.z());
Lorentz5Momentum n2(ZERO,ZERO, pa.z(),-pa.z());
Energy2 n1n2 = n1*n2;
// decompose the momenta
Lorentz5Momentum qbp=rot*pin[0],qcp= rot*pout[0];
double a[2],b[2];
a[0] = n2*qbp/n1n2;
b[0] = n1*qbp/n1n2;
a[1] = n2*qcp/n1n2;
b[1] = n1*qcp/n1n2;
Lorentz5Momentum qperp = qbp-a[0]*n1-b[0]*n2;
// before reshuffling
Energy Q = abs(pa.z());
double c = sqr(mc/Q);
Lorentz5Momentum pb(ZERO,ZERO,0.5*Q*(1.+c),0.5*Q*(1.+c));
Lorentz5Momentum pc(ZERO,ZERO,0.5*Q*(c-1.),0.5*Q*(1.+c));
double anew[2],bnew[2];
anew[0] = pb*n2/n1n2;
bnew[0] = 0.5*(qbp.m2()-qperp.m2())/n1n2/anew[0];
bnew[1] = pc*n1/n1n2;
anew[1] = 0.5*qcp.m2()/bnew[1]/n1n2;
Lorentz5Momentum qnewb = (anew[0]*n1+bnew[0]*n2+qperp);
Lorentz5Momentum qnewc = (anew[1]*n1+bnew[1]*n2);
// initial-state boost
LorentzRotation rotinv=rot.inverse();
LorentzRotation transb=rotinv*solveBoostZ(qnewb,qbp)*rot;
// final-state boost
LorentzRotation transc=rotinv*solveBoost(qnewc,qcp)*rot;
// this will need changing for more than one outgoing particle
// set the pvectors
for(unsigned int ix=0;ix<jets.size();++ix) {
if(jets[ix]->status()==HardBranching::Incoming) {
jets[ix]->pVector(pbeam);
jets[ix]->showerMomentum(rotinv*pb);
incoming->pVector(jets[ix]->pVector());
}
else {
jets[ix]->pVector(rotinv*pc);
jets[ix]->showerMomentum(jets[ix]->pVector());
}
}
// find the colour partners
ShowerParticleVector particles;
vector<Lorentz5Momentum> ptemp;
set<HardBranchingPtr>::const_iterator cjt;
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
ptemp.push_back((**cjt).branchingParticle()->momentum());
(**cjt).branchingParticle()->set5Momentum((**cjt).showerMomentum());
particles.push_back((**cjt).branchingParticle());
}
dynamic_ptr_cast<tcQTildeShowerHandlerPtr>(ShowerHandler::currentHandler())->showerModel()->partnerFinder()
->setInitialEvolutionScales(particles,false,type,false);
unsigned int iloc(0);
for(cjt=tree->branchings().begin();cjt!=tree->branchings().end();++cjt) {
// reset the momentum
(**cjt).branchingParticle()->set5Momentum(ptemp[iloc]);
++iloc;
}
for(vector<HardBranchingPtr>::const_iterator cjt=jets.begin();
cjt!=jets.end();++cjt) {
// sort out the partners
tShowerParticlePtr partner =
(*cjt)->branchingParticle()->partner();
if(!partner) continue;
tHardBranchingPtr branch;
for(set<HardBranchingPtr>::const_iterator
clt=tree->branchings().begin();clt!=tree->branchings().end();++clt) {
if((**clt).branchingParticle()==partner) {
(**cjt).colourPartner(*clt);
branch=*clt;
break;
}
}
// compute the reference vectors
// both incoming, should all ready be done
if((**cjt).status()==HardBranching::Incoming &&
branch->status()==HardBranching::Incoming) {
Energy etemp = (*cjt)->beam()->momentum().z();
Lorentz5Momentum nvect(ZERO, ZERO,-etemp, abs(etemp));
tHardBranchingPtr branch2 = *cjt;
(**cjt).nVector(nvect);
while (branch2->parent()) {
branch2=branch2->parent();
branch2->nVector(nvect);
}
}
// both outgoing
else if((**cjt).status()==HardBranching::Outgoing&&
branch->status()==HardBranching::Outgoing) {
Boost boost=((*cjt)->pVector()+branch->pVector()).findBoostToCM();
Lorentz5Momentum pcm = branch->pVector();
pcm.boost(boost);
Lorentz5Momentum nvect = Lorentz5Momentum(ZERO,pcm.vect());
nvect.boost( -boost);
(**cjt).nVector(nvect);
}
else if((**cjt).status()==HardBranching::Incoming) {
Lorentz5Momentum pa = -(**cjt).showerMomentum()+branch->showerMomentum();
Lorentz5Momentum pb = (**cjt).showerMomentum();
Axis axis(pa.vect().unit());
LorentzRotation rot;
double sinth(sqrt(sqr(axis.x())+sqr(axis.y())));
if(axis.perp2()>1e-20) {
rot.setRotate(-acos(axis.z()),Axis(-axis.y()/sinth,axis.x()/sinth,0.));
rot.rotateX(Constants::pi);
}
if(abs(1.-pa.e()/pa.vect().mag())>1e-6) rot.boostZ( pa.e()/pa.vect().mag());
pb*=rot;
Boost trans = -1./pb.e()*pb.vect();
trans.setZ(0.);
rot.boost(trans);
Energy scale=(**cjt).beam()->momentum().t();
Lorentz5Momentum pbasis(ZERO,(**cjt).beam()->momentum().vect().unit()*scale);
Lorentz5Momentum pcm = rot*pbasis;
rot.invert();
Lorentz5Momentum nvect = rot*Lorentz5Momentum(ZERO,-pcm.vect());
(**cjt).nVector(nvect);
tHardBranchingPtr branch2 = *cjt;
while (branch2->parent()) {
branch2=branch2->parent();
branch2->nVector(nvect);
}
}
else if(branch->status()==HardBranching::Incoming) {
Lorentz5Momentum nvect=Lorentz5Momentum(ZERO,branch->showerMomentum().vect());
(**cjt).nVector(nvect);
}
}
// now compute the new momenta
for(vector<HardBranchingPtr>::const_iterator cjt=jets.begin();
cjt!=jets.end();++cjt) {
if((**cjt).status()==HardBranching::Outgoing) {
(**cjt).setMomenta(transc,1.,Lorentz5Momentum());
}
}
incoming->setMomenta(transb,1.,Lorentz5Momentum());
}
void QTildeReconstructor::deepTransform(PPtr particle,
const LorentzRotation & r,
bool match,
PPtr original) const {
if(_boosts.find(particle)!=_boosts.end()) {
_boosts[particle].push_back(r);
}
Lorentz5Momentum porig = particle->momentum();
if(!original) original = particle;
for ( int i = 0, N = particle->children().size(); i < N; ++i ) {
deepTransform(particle->children()[i],r,
particle->children()[i]->id()==original->id()&&match,original);
}
particle->transform(r);
// transform the p and n vectors
ShowerParticlePtr sparticle = dynamic_ptr_cast<ShowerParticlePtr>(particle);
if(sparticle && sparticle->showerBasis()) {
sparticle->showerBasis()->transform(r);
}
if ( particle->next() ) deepTransform(particle->next(),r,match,original);
if(!match) return;
if(!particle->children().empty()) return;
// force the mass shell
if(particle->dataPtr()->stable()) {
Lorentz5Momentum ptemp = particle->momentum();
ptemp.rescaleEnergy();
particle->set5Momentum(ptemp);
}
// check if there's a daughter tree which also needs boosting
map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator tit;
for(tit = _currentTree->treelinks().begin();
tit != _currentTree->treelinks().end();++tit) {
// if there is, boost it
if(tit->second.first && tit->second.second==original) {
Lorentz5Momentum pnew = tit->first->incomingLines().begin()
->first->progenitor()->momentum();
pnew *= tit->first->transform();
Lorentz5Momentum pdiff = porig-pnew;
Energy2 test = sqr(pdiff.x()) + sqr(pdiff.y()) +
sqr(pdiff.z()) + sqr(pdiff.t());
LorentzRotation rot;
if(test>1e-6*GeV2) rot = solveBoost(porig,pnew);
tit->first->transform(r*rot,false);
_treeBoosts[tit->first].push_back(r*rot);
}
}
}
void QTildeReconstructor::reconstructFinalFinalOffShell(JetKinVect orderedJets,
Energy2 s,
bool recursive) const {
JetKinVect::iterator jit;
jit = orderedJets.begin(); ++jit;
// 4-momentum of recoiling system
Lorentz5Momentum psum;
for( ; jit!=orderedJets.end(); ++jit) psum += jit->p;
psum.rescaleMass();
// calculate the 3-momentum rescaling factor
Energy2 m1sq(orderedJets.begin()->q.m2()),m2sq(psum.m2());
Energy4 num = sqr(s - m1sq - m2sq) - 4.*m1sq*m2sq;
if(num<ZERO) throw KinematicsReconstructionVeto();
double k = sqrt( num / (4.*s*orderedJets.begin()->p.vect().mag2()) );
// boost the most off-shell
LorentzRotation B1 = solveBoost(k, orderedJets.begin()->q, orderedJets.begin()->p);
deepTransform(orderedJets.begin()->parent,B1);
// boost everything else
// first to rescale
LorentzRotation B2 = solveBoost(k, psum, psum);
// and then to rest frame of new system
Lorentz5Momentum pnew = B2*psum;
pnew.rescaleMass();
B2.transform(pnew.findBoostToCM());
// apply transform (calling routine ensures at least 3 elements)
jit = orderedJets.begin(); ++jit;
for(;jit!=orderedJets.end();++jit) {
deepTransform(jit->parent,B2);
jit->p *= B2;
jit->q *= B2;
}
JetKinVect newJets(orderedJets.begin()+1,orderedJets.end());
// final reconstruction
if(newJets.size()==2 || !recursive ) {
// rescaling factor
double k = solveKfactor(psum.m(), newJets);
// rescale jets in the new CMF
for(JetKinVect::iterator it = newJets.begin(); it != newJets.end(); ++it) {
LorentzRotation Trafo = solveBoost(k, it->q, it->p);
deepTransform(it->parent,Trafo);
}
}
// recursive
else {
std::sort(newJets.begin(),newJets.end(),JetOrdering());
reconstructFinalFinalOffShell(newJets,psum.m2(),recursive);
}
// finally boost back from new CMF
LorentzRotation back(-pnew.findBoostToCM());
for(JetKinVect::iterator it = newJets.begin(); it != newJets.end(); ++it) {
deepTransform(it->parent,back);
}
}
Energy QTildeReconstructor::findMass(HardBranchingPtr branch) const {
// KH - 230909 - If the particle has no children then it will
// not have showered and so it should be "on-shell" so we can
// get it's mass from it's momentum. This means that the
// inverseRescalingFactor doesn't give any nans or do things
// it shouldn't if it gets e.g. two Z bosons generated with
// off-shell masses. This is for sure not the best solution.
// PR 1/1/10 modification to previous soln
// PR 28/8/14 change to procedure and factorize into a function
if(branch->children().empty()) {
return branch->branchingParticle()->mass();
}
else if(!branch->children().empty() &&
!branch->branchingParticle()->dataPtr()->stable() ) {
for(unsigned int ix=0;ix<branch->children().size();++ix) {
if(branch->branchingParticle()->id()==
branch->children()[ix]->branchingParticle()->id())
return findMass(branch->children()[ix]);
}
}
return branch->branchingParticle()->dataPtr()->mass();
}
vector<double>
QTildeReconstructor::inverseInitialStateRescaling(double & x1, double & x2,
const Lorentz5Momentum & pold,
const vector<Lorentz5Momentum> & p,
const vector<Lorentz5Momentum> & pq) const {
// hadronic CMS
Energy2 s = (pq[0] +pq[1] ).m2();
// partonic CMS
Energy MDY = pold.m();
// find alpha, beta and pt
Energy2 p12=pq[0]*pq[1];
double a[2],b[2];
Lorentz5Momentum pt[2];
for(unsigned int ix=0;ix<2;++ix) {
a[ix] = p[ix]*pq[1]/p12;
b [ix] = p[ix]*pq[0]/p12;
pt[ix] = p[ix]-a[ix]*pq[0]-b[ix]*pq[1];
}
// compute kappa
// we always want to preserve the mass of the system
double k1(1.),k2(1.);
if(_initialStateReconOption==0) {
double rap=pold.rapidity();
x2 = MDY/sqrt(s*exp(2.*rap));
x1 = sqr(MDY)/s/x2;
k1=a[0]/x1;
k2=b[1]/x2;
}
// longitudinal momentum
else if(_initialStateReconOption==1) {
double A = 1.;
double C = -sqr(MDY)/s;
double B = 2.*pold.z()/sqrt(s);
if(abs(B)>1e-10) {
double discrim = 1.-4.*A*C/sqr(B);
if(discrim < 0.) throw KinematicsReconstructionVeto();
x1 = B>0. ? 0.5*B/A*(1.+sqrt(discrim)) : 0.5*B/A*(1.-sqrt(discrim));
}
else {
x1 = -C/A;
if( x1 <= 0.) throw KinematicsReconstructionVeto();
x1 = sqrt(x1);
}
x2 = sqr(MDY)/s/x1;
k1=a[0]/x1;
k2=b[1]/x2;
}
// preserve mass and don't scale the softer system
// to reproduce the dipole kinematics
else if(_initialStateReconOption==2) {
// in this case kp = k1 or k2 depending on who's the harder guy
k1 = a[0]*b[1]*s/sqr(MDY);
if ( pt[0].perp2() < pt[1].perp2() ) swap(k1,k2);
x1 = a[0]/k1;
x2 = b[1]/k2;
}
else
assert(false);
// decompose the momenta
double anew[2] = {a[0]/k1,a[1]*k2};
double bnew[2] = {b[0]*k1,b[1]/k2};
vector<double> boost(2);
for(unsigned int ix=0;ix<2;++ix) {
boost[ix] = getBeta(a [ix]+b [ix], a[ix] -b [ix],
anew[ix]+bnew[ix], anew[ix]-bnew[ix]);
}
return boost;
}
vector<double>
QTildeReconstructor::initialStateRescaling(double x1, double x2,
const Lorentz5Momentum & pold,
const vector<Lorentz5Momentum> & p,
const vector<Lorentz5Momentum> & pq,
const vector<Energy>& highestpts) const {
Energy2 S = (pq[0]+pq[1]).m2();
// find alphas and betas in terms of desired basis
Energy2 p12 = pq[0]*pq[1];
double a[2] = {p[0]*pq[1]/p12,p[1]*pq[1]/p12};
double b[2] = {p[0]*pq[0]/p12,p[1]*pq[0]/p12};
Lorentz5Momentum p1p = p[0] - a[0]*pq[0] - b[0]*pq[1];
Lorentz5Momentum p2p = p[1] - a[1]*pq[0] - b[1]*pq[1];
// compute kappa
// we always want to preserve the mass of the system
Energy MDY = pold.m();
Energy2 A = a[0]*b[1]*S;
Energy2 B = Energy2(sqr(MDY)) - (a[0]*b[0]+a[1]*b[1])*S - (p1p+p2p).m2();
Energy2 C = a[1]*b[0]*S;
double rad = 1.-4.*A*C/sqr(B);
if(rad < 0.) throw KinematicsReconstructionVeto();
double kp = B/(2.*A)*(1.+sqrt(rad));
// now compute k1
// conserve rapidity
double k1(0.);
double k2(0.);
if(_initialStateReconOption==0) {
rad = kp*(b[0]+kp*b[1])/(kp*a[0]+a[1]);
rad *= pq[0].z()<ZERO ? exp(-2.*pold.rapidity()) : exp(2.*pold.rapidity());
if(rad <= 0.) throw KinematicsReconstructionVeto();
k1 = sqrt(rad);
k2 = kp/k1;
}
// conserve longitudinal momentum
else if(_initialStateReconOption==1) {
double a2 = (a[0]+a[1]/kp);
double b2 = -x2+x1;
double c2 = -(b[1]*kp+b[0]);
if(abs(b2)>1e-10) {
double discrim = 1.-4.*a2*c2/sqr(b2);
if(discrim < 0.) throw KinematicsReconstructionVeto();
k1 = b2>0. ? 0.5*b2/a2*(1.+sqrt(discrim)) : 0.5*b2/a2*(1.-sqrt(discrim));
}
else {
k1 = -c2/a2;
if( k1 <= 0.) throw KinematicsReconstructionVeto();
k1 = sqrt(k1);
}
k2 = kp/k1;
}
// preserve mass and don't scale the softer system
// to reproduce the dipole kinematics
else if(_initialStateReconOption==2) {
// in this case kp = k1 or k2 depending on who's the harder guy
k1 = kp; k2 = 1.;
if ( highestpts[0] < highestpts[1] )
swap(k1,k2);
}
else
assert(false);
// calculate the boosts
vector<double> beta(2);
beta[0] = getBeta((a[0]+b[0]), (a[0]-b[0]), (k1*a[0]+b[0]/k1), (k1*a[0]-b[0]/k1));
beta[1] = getBeta((a[1]+b[1]), (a[1]-b[1]), (a[1]/k2+k2*b[1]), (a[1]/k2-k2*b[1]));
if (pq[0].z() > ZERO) {
beta[0] = -beta[0];
beta[1] = -beta[1];
}
return beta;
}
void QTildeReconstructor::
reconstructColourSinglets(vector<ShowerProgenitorPtr> & ShowerHardJets,
- ShowerInteraction::Type type) const {
+ ShowerInteraction type) const {
// identify and catagorize the colour singlet systems
unsigned int nnun(0),nnii(0),nnif(0),nnf(0),nni(0);
vector<ColourSingletSystem>
systems(identifySystems(set<ShowerProgenitorPtr>(ShowerHardJets.begin(),ShowerHardJets.end()),
nnun,nnii,nnif,nnf,nni));
// now decide what to do
// initial-initial connection and final-state colour singlet systems
LorentzRotation toRest,fromRest;
bool applyBoost(false),general(false);
// Drell-Yan type
if(nnun==0&&nnii==1&&nnif==0&&nnf>0&&nni==0) {
// reconstruct initial-initial system
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type==II)
reconstructInitialInitialSystem(applyBoost,toRest,fromRest,
systems[ix].jets);
}
if(type!=ShowerInteraction::QCD) {
combineFinalState(systems);
general=false;
}
}
// DIS and VBF type
else if(nnun==0&&nnii==0&&((nnif==1&&nnf>0&&nni==1)||
(nnif==2&& nni==0))) {
// check these systems can be reconstructed
for(unsigned int ix=0;ix<systems.size();++ix) {
// compute q^2
if(systems[ix].type!=IF) continue;
Lorentz5Momentum q;
for(unsigned int iy=0;iy<systems[ix].jets.size();++iy) {
if(systems[ix].jets[iy]->progenitor()->isFinalState())
q += systems[ix].jets[iy]->progenitor()->momentum();
else
q -= systems[ix].jets[iy]->progenitor()->momentum();
}
q.rescaleMass();
// check above cut
if(abs(q.m())>=_minQ) continue;
if(nnif==1&&nni==1) {
throw KinematicsReconstructionVeto();
}
else {
general = true;
break;
}
}
if(!general) {
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type==IF)
reconstructInitialFinalSystem(systems[ix].jets);
}
}
}
// e+e- type
else if(nnun==0&&nnii==0&&nnif==0&&nnf>0&&nni==2) {
general = type!=ShowerInteraction::QCD;
}
// general type
else {
general = true;
}
// final-state systems except for general recon
if(!general) {
for(unsigned int ix=0;ix<systems.size();++ix) {
if(systems[ix].type==F)
reconstructFinalStateSystem(applyBoost,toRest,fromRest,
systems[ix].jets);
}
}
else {
reconstructGeneralSystem(ShowerHardJets);
}
}
void QTildeReconstructor::findInitialBoost(const Lorentz5Momentum & pold,
const Lorentz5Momentum & pnew,
LorentzRotation & toRest,
LorentzRotation & fromRest) const {
// do one boost
if(_initialBoost==0) {
toRest = LorentzRotation(pold.findBoostToCM());
fromRest = LorentzRotation(pnew.boostVector());
}
else if(_initialBoost==1) {
// boost to rest frame
// first transverse
toRest = Boost(-pold.x()/pold.t(),-pold.y()/pold.t(),0.);
// then longitudinal
double beta = pold.z()/sqrt(pold.m2()+sqr(pold.z()));
toRest.boost((Boost(0.,0.,-beta)));
// boost from rest frame
// first apply longitudinal boost
beta = pnew.z()/sqrt(pnew.m2()+sqr(pnew.z()));
fromRest=LorentzRotation(Boost(0.,0.,beta));
// then transverse one
fromRest.boost(Boost(pnew.x()/pnew.t(),
pnew.y()/pnew.t(),0.));
}
else
assert(false);
}
diff --git a/Shower/QTilde/Default/QTildeReconstructor.h b/Shower/QTilde/Default/QTildeReconstructor.h
--- a/Shower/QTilde/Default/QTildeReconstructor.h
+++ b/Shower/QTilde/Default/QTildeReconstructor.h
@@ -1,642 +1,642 @@
// -*- C++ -*-
//
// QTildeReconstructor.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_QTildeReconstructor_H
#define HERWIG_QTildeReconstructor_H
//
// This is the declaration of the QTildeReconstructor class.
//
#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
* A simple struct to store the information we need on the
* showering
*/
struct JetKinStruct {
/**
* Parent particle of the jet
*/
tShowerParticlePtr parent;
/**
* Momentum of the particle before reconstruction
*/
Lorentz5Momentum p;
/**
* Momentum of the particle after reconstruction
*/
Lorentz5Momentum q;
};
/**
* typedef for a vector of JetKinStruct
*/
typedef vector<JetKinStruct> JetKinVect;
/**
* Enum to identify types of colour singlet systems
*/
enum SystemType { UNDEFINED=-1, II, IF, F ,I };
/**
* Struct to store colour singlets
*/
template<typename Value> struct ColourSinglet {
typedef vector<ColourSinglet<Value> > VecType;
ColourSinglet() : type(UNDEFINED) {}
ColourSinglet(SystemType intype,Value inpart)
: type(intype),jets(1,inpart) {}
/**
* The type of system
*/
SystemType type;
/**
* The jets in the system
*/
vector<Value> jets;
};
/**
* Struct to store a colour singlet system of particles
*/
typedef ColourSinglet<ShowerProgenitorPtr> ColourSingletSystem;
/**
* Struct to store a colour singlet shower
*/
typedef ColourSinglet<HardBranchingPtr> ColourSingletShower;
/** \ingroup Shower
*
* This class is responsible for the kinematical reconstruction
* after each showering step, and also for the necessary Lorentz boosts
* in order to preserve energy-momentum conservation in the overall collision,
* and also the invariant mass and the rapidity of the hard subprocess system.
* In the case of multi-step showering, there will be not unnecessary
* kinematical reconstructions.
*
* There is also the option of taking a set of momenta for the particles
* and inverting the reconstruction to give the evolution variables for the
* shower.
*
* Notice:
* - although we often use the term "jet" in either methods or variables names,
* or in comments, which could appear applicable only for QCD showering,
* there is indeed no "dynamics" represented in this class: only kinematics
* is involved, as the name of this class remainds. Therefore it can be used
* for any kind of showers (QCD-,QED-,EWK-,... bremsstrahlung).
*
* @see ShowerParticle
* @see ShowerKinematics
* @see \ref QTildeReconstructorInterfaces "The interfaces"
* defined for QTildeReconstructor.
*/
class QTildeReconstructor: public KinematicsReconstructor {
public:
/**
* Default constructor
*/
QTildeReconstructor() : _reconopt(0), _initialBoost(0),
_finalStateReconOption(0),
_initialStateReconOption(0), _minQ(MeV) {};
/**
* Methods to reconstruct the kinematics of a scattering or decay process
*/
//@{
/**
* Given in input a vector of the particles which initiated the showers
* the method does the reconstruction of such jets,
* including the appropriate boosts (kinematics reshufflings)
* needed to conserve the total energy-momentum of the collision
* and preserving the invariant mass and the rapidity of the
* hard subprocess system.
*/
virtual bool reconstructHardJets(ShowerTreePtr hard,
const map<tShowerProgenitorPtr,
pair<Energy,double> > & pt,
- ShowerInteraction::Type type,
+ ShowerInteraction type,
bool switchRecon) const;
/**
* Given in input a vector of the particles which initiated the showers
* the method does the reconstruction of such jets,
* including the appropriate boosts (kinematics reshufflings)
* needed to conserve the total energy-momentum of the collision
* and preserving the invariant mass and the rapidity of the
* hard subprocess system.
*/
virtual bool reconstructDecayJets(ShowerTreePtr decay,
- ShowerInteraction::Type type) const;
+ ShowerInteraction type) const;
//@}
/**
* Methods to invert the reconstruction of the shower for
* a scattering or decay process and calculate
* the variables used to generate the
* shower given the particles produced.
* This is needed for the CKKW and POWHEG approaches
*/
//@{
/**
* Given the particles, with a history which we wish to interpret
* as a shower reconstruct the variables used to generate the
* shower
*/
- virtual bool deconstructDecayJets(HardTreePtr,ShowerInteraction::Type) const;
+ virtual bool deconstructDecayJets(HardTreePtr,ShowerInteraction) const;
/**
* Given the particles, with a history which we wish to interpret
* as a shower reconstruct the variables used to generate the shower
* for a hard process
*/
- virtual bool deconstructHardJets(HardTreePtr,ShowerInteraction::Type) const;
+ virtual bool deconstructHardJets(HardTreePtr,ShowerInteraction) 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:
/**
* Methods to reconstruct the kinematics of individual jets
*/
//@{
/**
* Given the particle (ShowerParticle object) that
* originates a forward (time-like) jet, this method reconstructs the kinematics
* of the jet. That is, by starting from the final grand-children (which
* originates directly or indirectly from particleJetParent,
* and which don't have children), and moving "backwards" (in a physical
* time picture), towards the particleJetParent, the
* ShowerKinematics objects associated with the various particles,
* which have been created during the showering, are now completed.
* In particular, at the end, we get the mass of the jet, which is the
* main information we want.
* This methods returns false if there was no radiation or rescaling required
*/
virtual bool reconstructTimeLikeJet(const tShowerParticlePtr particleJetParent) const;
/**
* Exactly similar to the previous one, but for a space-like jet.
* Also in this case we start from the final grand-children (which
* are childless) of the particle which originates the jet, but in
* this case we proceed "forward" (in the physical time picture)
* towards the particleJetParent.
* This methods returns false if there was no radiation or rescaling required
*/
bool reconstructSpaceLikeJet(const tShowerParticlePtr particleJetParent) const;
/**
* Exactly similar to the previous one, but for a decay jet
* This methods returns false if there was no radiation or rescaling required
*/
bool reconstructDecayJet(const tShowerParticlePtr particleJetParent) const;
//@}
/**
* Methods to perform the reconstruction of various types of colour
* singlet systems
*/
//@{
/**
* Perform the reconstruction of a system with one incoming and at least one
* outgoing particle
*/
void reconstructInitialFinalSystem(vector<ShowerProgenitorPtr>) const;
/**
* Perform the reconstruction of a system with only final-state
* particles
*/
void reconstructFinalStateSystem(bool applyBoost,
const LorentzRotation & toRest,
const LorentzRotation & fromRest,
vector<ShowerProgenitorPtr>) const;
/**
* Reconstruction of a general coloured system
*/
void reconstructGeneralSystem(vector<ShowerProgenitorPtr> & ShowerHardJets) const;
/**
* Reconstruction of a general coloured system doing
* final-final, then initial-final and then initial-initial
*/
void reconstructFinalFirst(vector<ShowerProgenitorPtr> & ShowerHardJets) const;
/**
* Reconstruction of a general coloured system doing
* colour parners
*/
void reconstructColourPartner(vector<ShowerProgenitorPtr> & ShowerHardJets) const;
/**
* Reconstruction based on colour singlet systems
*/
void reconstructColourSinglets(vector<ShowerProgenitorPtr> & ShowerHardJets,
- ShowerInteraction::Type type) const;
+ ShowerInteraction type) const;
/**
* Perform the reconstruction of a system with only final-state
* particles
*/
void reconstructInitialInitialSystem(bool & applyBoost,
LorentzRotation & toRest,
LorentzRotation & fromRest,
vector<ShowerProgenitorPtr>) const;
//@}
/**
* Methods to perform the inverse reconstruction of various types of
* colour singlet systems
*/
//@{
/**
* Perform the inverse reconstruction of a system with only final-state
* particles
*/
void deconstructFinalStateSystem(const LorentzRotation & toRest,
const LorentzRotation & fromRest,
HardTreePtr,
vector<HardBranchingPtr>,
- ShowerInteraction::Type) const;
+ ShowerInteraction) const;
/**
* Perform the inverse reconstruction of a system with only initial-state
* particles
*/
void deconstructInitialInitialSystem(bool & applyBoost,
LorentzRotation & toRest,
LorentzRotation & fromRest,
HardTreePtr,
vector<HardBranchingPtr>,
- ShowerInteraction::Type ) const;
+ ShowerInteraction ) const;
/**
* Perform the inverse reconstruction of a system with only initial-state
* particles
*/
void deconstructInitialFinalSystem(HardTreePtr,
vector<HardBranchingPtr>,
- ShowerInteraction::Type ) const;
+ ShowerInteraction ) const;
bool deconstructGeneralSystem(HardTreePtr,
- ShowerInteraction::Type) const;
+ ShowerInteraction) const;
bool deconstructColourSinglets(HardTreePtr,
- ShowerInteraction::Type) const;
+ ShowerInteraction) const;
bool deconstructColourPartner(HardTreePtr,
- ShowerInteraction::Type) const;
+ ShowerInteraction) const;
//@}
/**
* Recursively treat the most off-shell paricle seperately
* for final-final reconstruction
*/
void reconstructFinalFinalOffShell(JetKinVect orderedJets, Energy2 s,
bool recursive) const;
/**
* Various methods for the Lorentz transforms needed to do the
* rescalings
*/
//@{
/**
* Compute the boost to get from the the old momentum to the new
*/
LorentzRotation solveBoost(const double k,
const Lorentz5Momentum & newq,
const Lorentz5Momentum & oldp) const;
/**
* Compute the boost to get from the the old momentum to the new
*/
LorentzRotation solveBoost(const Lorentz5Momentum & newq,
const Lorentz5Momentum & oldq) const;
/**
* Compute the boost to get from the the old momentum to the new
*/
LorentzRotation solveBoostZ(const Lorentz5Momentum & newq,
const Lorentz5Momentum & oldq) const;
/**
* Recursively boost the initial-state shower
* @param p The particle
* @param bv The boost
* @param parent The parent of the chain
*/
void boostChain(tPPtr p, const LorentzRotation & bv, tPPtr & parent) const;
/**
* Given a 5-momentum and a scale factor, the method returns the
* Lorentz boost that transforms the 3-vector vec{momentum} --->
* k*vec{momentum}. The method returns the null boost in the case no
* solution exists. This will only work in the case where the
* outgoing jet-momenta are parallel to the momenta of the particles
* leaving the hard subprocess.
*/
Boost solveBoostBeta( const double k, const Lorentz5Momentum & newq,
const Lorentz5Momentum & oldp);
/**
* Compute boost parameter along z axis to get (Ep, any perp, qp)
* from (E, same perp, q).
*/
double getBeta(const double E, const double q,
const double Ep, const double qp) const
{return (q*E-qp*Ep)/(sqr(qp)+sqr(E));}
//@}
/**
* Methods to calculate the various scaling factors
*/
//@{
/**
* Given a vector of 5-momenta of jets, where the 3-momenta are the initial
* ones before showering and the masses are reconstructed after the showering,
* this method returns the overall scaling factor for the 3-momenta of the
* vector of particles, vec{P}_i -> k * vec{P}_i, such to preserve energy-
* momentum conservation, i.e. after the rescaling the center of mass 5-momentum
* is equal to the one specified in input, cmMomentum.
* The method returns 0 if such factor cannot be found.
* @param root_s Centre-of-mass energy
* @param jets The jets
*/
double solveKfactor( const Energy & root_s, const JetKinVect & jets ) const;
/**
* Calculate the rescaling factors for the jets in a particle decay where
* there was initial-state radiation
* @param mb The mass of the decaying particle
* @param n The reference vector for the initial state radiation
* @param pjet The momentum of the initial-state jet
* @param jetKinematics The JetKinStruct objects for the jets
* @param partner The colour partner
* @param ppartner The momentum of the colour partner of the decaying particle
* before and after radiation
* @param k1 The rescaling parameter for the partner
* @param k2 The rescaling parameter for the outgoing singlet
* @param qt The transverse momentum vector
*/
bool solveDecayKFactor(Energy mb,
const Lorentz5Momentum & n,
const Lorentz5Momentum & pjet,
const JetKinVect & jetKinematics,
ShowerParticlePtr partner,
Lorentz5Momentum ppartner[2],
double & k1,
double & k2,
Lorentz5Momentum & qt) const;
/**
* Compute the momentum rescaling factor needed to invert the shower
* @param pout The momenta of the outgoing particles
* @param mon The on-shell masses
* @param roots The mass of the decaying particle
*/
double inverseRescalingFactor(vector<Lorentz5Momentum> pout,
vector<Energy> mon,Energy roots) const;
/**
* Compute the momentum rescaling factor needed to invert the shower
* @param pout The momenta of the outgoing particles
* @param mon The on-shell masses
* @param roots The mass of the decaying particle
* @param ppartner The momentum of the colour partner
* @param mbar The mass of the decaying particle
* @param k1 The first scaling factor
* @param k2 The second scaling factor
*/
bool inverseDecayRescalingFactor(vector<Lorentz5Momentum> pout,
vector<Energy> mon,Energy roots,
Lorentz5Momentum ppartner, Energy mbar,
double & k1, double & k2) const;
/**
* Check the rescaling conserves momentum
* @param k The rescaling
* @param root_s The centre-of-mass energy
* @param jets The jets
*/
Energy momConsEq(double k, const Energy & root_s,
const JetKinVect & jets) const;
void findInitialBoost(const Lorentz5Momentum & pold, const Lorentz5Momentum & pnew,
LorentzRotation & toRest, LorentzRotation & fromRest) const;
//@}
/**
* Find the colour partners of a particle to identify the colour singlet
* systems for the reconstruction.
*/
template<typename Value> void findPartners(Value branch,set<Value> & done,
const set<Value> & branchings,
vector<Value> & jets) const;
/**
* Add the intrinsic \f$p_T\f$ to the system if needed
*/
bool addIntrinsicPt(vector<ShowerProgenitorPtr>) const;
/**
* Apply a transform to the particle and any child, including child ShowerTree
* objects
* @param particle The particle
* @param r The Lorentz transformation
* @param match Whether or not to look at children etc
* @param original The original particle
*/
void deepTransform(PPtr particle,const LorentzRotation & r,
bool match=true,PPtr original=PPtr()) const;
/**
* Find the mass of a particle in the hard branching
*/
Energy findMass(HardBranchingPtr) const;
/**
* Calculate the initial-state rescaling factors
*/
vector<double> initialStateRescaling(double x1, double x2,
const Lorentz5Momentum & pold,
const vector<Lorentz5Momentum> & p,
const vector<Lorentz5Momentum> & pq,
const vector<Energy>& highespts) const;
/**
* Calculate the inverse of the initial-state rescaling factor
*/
vector<double> inverseInitialStateRescaling(double & x1, double & x2,
const Lorentz5Momentum & pold,
const vector<Lorentz5Momentum> & p,
const vector<Lorentz5Momentum> & pq) const;
/**
* Find the colour singlet systems
*/
template<typename Value >
typename ColourSinglet<Value>::VecType identifySystems(set<Value> jets,
unsigned int & nnun,unsigned int & nnii,
unsigned int & nnif,unsigned int & nnf,
unsigned int & nni) const;
/**
* Combine final-state colour systems
*/
template<typename Value>
void combineFinalState(vector<ColourSinglet<Value> > & systems) const;
protected:
/** @name Clone Methods. */
//@{
/**
* Make a simple clone of this object.
* @return a pointer to the new object.
*/
virtual IBPtr clone() const {return new_ptr(*this);}
/** 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 {return new_ptr(*this);}
//@}
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();
//@}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
QTildeReconstructor & operator=(const QTildeReconstructor &);
private:
/**
* Option for handling the reconstruction
*/
unsigned int _reconopt;
/**
* Option for the boost for initial-initial reconstruction
*/
unsigned int _initialBoost;
/**
* Option for the reconstruction of final state systems
*/
unsigned int _finalStateReconOption;
/**
* Option for the initial state reconstruction
*/
unsigned int _initialStateReconOption;
/**
* Minimum invariant mass for initial-final dipoles to allow the
* reconstruction
*/
Energy _minQ;
/**
* The progenitor of the jet currently being reconstructed
*/
mutable tShowerParticlePtr _progenitor;
/**
* Storage of the intrinsic \f$p_T\f$
*/
mutable map<tShowerProgenitorPtr,pair<Energy,double> > _intrinsic;
/**
* Current ShowerTree
*/
mutable tShowerTreePtr _currentTree;
/**
* Particles which shouldn't have their masses rescaled as
* vector for the interface
*/
PDVector _noRescaleVector;
/**
* Particles which shouldn't have their masses rescaled as
* set for quick access
*/
set<cPDPtr> _noRescale;
/**
* Storage of the boosts applied to enable resetting after failure
*/
mutable map<tPPtr,vector<LorentzRotation> > _boosts;
/**
* Storage of the boosts applied to enable resetting after failure
*/
mutable map<tShowerTreePtr,vector<LorentzRotation> > _treeBoosts;
};
}
#include "QTildeReconstructor.tcc"
#endif /* HERWIG_QTildeReconstructor_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::Type inter) {
+ 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/Matching/CKKWTree.cc b/Shower/QTilde/Matching/CKKWTree.cc
--- a/Shower/QTilde/Matching/CKKWTree.cc
+++ b/Shower/QTilde/Matching/CKKWTree.cc
@@ -1,350 +1,350 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the CKKWTree class.
//
#include "CKKWTree.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "Herwig/Utilities/Maths.h"
using namespace Herwig;
CKKWTree::CKKWTree(vector<HardBranchingPtr> branchings,
vector<HardBranchingPtr> spacelike,
- ShowerInteraction::Type type) : HardTree(branchings,spacelike,type),
+ ShowerInteraction type) : HardTree(branchings,spacelike,type),
lowestpTMomentum_(ZERO),
totalpT_(ZERO), ordered_(false)
{}
bool CKKWTree::checkXOrdering() {
double x_frac;
for( set< HardBranchingPtr >::const_iterator cit = incoming().begin();
cit != incoming().end(); ++cit ) {
//find the pdf for this line
HardBranchingPtr currentParticle = *cit;
if( currentParticle->status() == HardBranching::Outgoing ||
!currentParticle->branchingParticle()->coloured() ) continue;
Lorentz5Momentum beamMom = currentParticle->beam()->momentum();
Lorentz5Momentum otherBeam = beamMom;
otherBeam.setZ( -otherBeam.z() );
// x_frac = currentParticle->branchingParticle()->momentum()
// * otherBeam / ( beamMom*otherBeam );
x_frac = currentParticle->x_frac();
//trace from incoming to hard process checking x_{i+1} < x_{i}
while( !currentParticle->children().empty() ){
currentParticle = currentParticle->children()[0];
double last_xfrac = x_frac;
//is this the correct momentum
x_frac = currentParticle->x_frac();
// x_frac = currentParticle->branchingParticle()->momentum()
// * otherBeam / ( beamMom*otherBeam );
if( x_frac > last_xfrac ) {
return false;
}
// if( currentParticle->branchingParticle()->momentum().t() < ZERO )
// return false;
}
}
return true;
}
//calculates the highest merging scale in the jet measure
//does this based on the hardtree momenta rather than the shower variables
//cutting events based on this is equivalent to the mad graph cuts
Energy CKKWTree::lowestPtMomentum( int jetMeasureMode, int cutOption ){
Energy lowestpTMomentum_ = 9999999. * GeV;
//vector of timelike initiators
vector< HardBranchingPtr > FSsHat_hower_initiators;
//add FS shower initiators from FS progenitors
for( set<HardBranchingPtr>::const_iterator it = branchings().begin();
it != branchings().end(); ++it) {
if( ! (*it)->branchingParticle()->coloured() || (*it)->status() == HardBranching::Incoming ) continue;
FSsHat_hower_initiators.push_back( *it );
}
//add FS shower initiators from IS branchings
//trace back all incoming lines
for( set< HardBranchingPtr >::const_iterator cit = incoming().begin();
cit != incoming().end(); ++cit ) {
if( ! (*cit)->branchingParticle()->coloured() ) continue;
HardBranchingPtr currentParticle = *cit;
while( !currentParticle->children().empty() ){
//get scale for hardbranching - order of partons here IS first??
//is this correct for ISFS branching should be between widtilde{ij} and j creating i
//I think it was wrong before so have changed it -depended only on the second FS parton though!!
Energy kt_measure = hadronJetMeasure( currentParticle->branchingParticle()->momentum(),
currentParticle->children()[1]->branchingParticle()->momentum(),
false );
//if cutOption == 2 then only set this if the only partons
//involved are endpoints (no parent for IS and no children for FS)
if( !( cutOption == 2 && !externalBranching( currentParticle, currentParticle->children()[1] ) )
&& kt_measure < lowestpTMomentum_ )
lowestpTMomentum_ = kt_measure;
FSsHat_hower_initiators.push_back( currentParticle->children()[1] );
currentParticle = currentParticle->children()[0];
}
}
//loop over the time like initiators
for( vector< HardBranchingPtr >::const_iterator cit = FSsHat_hower_initiators.begin();
cit != FSsHat_hower_initiators.end(); ++cit ){
getLowestJetMeasure( *cit, jetMeasureMode, cutOption );
}
return lowestpTMomentum_;
}
void CKKWTree::getLowestJetMeasure( HardBranchingPtr branch, int jetMeasureMode, int cutOption ){
//if branching has children then find the jet measure from them
if( ! branch->children().empty() ){
Energy kt_measure = ZERO;
if( jetMeasureMode == 0 || jetMeasureMode == 0 ){
kt_measure = getJetMeasure( branch->children()[0]->branchingParticle()->momentum(),
branch->children()[1]->branchingParticle()->momentum(),
jetMeasureMode );
}
else if( jetMeasureMode == 3 ) {
kt_measure = hadronJetMeasure( branch->children()[0]->branchingParticle()->momentum(),
branch->children()[1]->branchingParticle()->momentum(),
true );
}
if( !( cutOption == 2 && !externalBranching( branch->children()[0], branch->children()[1] ) )
&& kt_measure < lowestpTMomentum_ ) lowestpTMomentum_ = kt_measure;
//do the same for children
getLowestJetMeasure( branch->children()[0], jetMeasureMode, cutOption );
getLowestJetMeasure( branch->children()[1], jetMeasureMode, cutOption );
}
}
Energy CKKWTree::hadronJetMeasure( const Lorentz5Momentum & p1,
const Lorentz5Momentum & p2,
bool final ) {
Energy kt_measure(ZERO);
//FSFS case
if( final ) {
double deltay = p1.rapidity() - p2.rapidity();
double deltaphi = Herwig::Math::angleMinusPiToPi(p1.phi() - p2.phi());
double deltaR = sqr( deltay ) + sqr( deltaphi );
kt_measure = sqrt( min( p1.perp2(), p2.perp2() ) * deltaR );
}
//in the case of ISFS the merge scale is given by the pt
//of the FS parton w.r.t incoming hadron (assumed second argument)
else {
kt_measure = p2.perp();
}
return kt_measure;
}
Energy CKKWTree::getJetMeasure( const Lorentz5Momentum & p1,
const Lorentz5Momentum & p2,
int jetMeasureMode ) {
Energy kt_measure(ZERO);
double costheta = p1.vect().cosTheta( p2.vect() );
switch( jetMeasureMode ){
case 0:
kt_measure = sqrt( 2. * sqr( max(p1.e(), p2.e() ) ) * ( 1. - costheta ) );
break;
case 2:
kt_measure = sqrt( 2. * sqr( p1.e() * p2.e() / ( p1.e() + p2.e() ) )
* ( 1. - costheta ) );
break;
default:
assert(false);
}
return kt_measure;
}
bool CKKWTree::externalBranching( HardBranchingPtr a, HardBranchingPtr b ){
if( a->status() == HardBranching::Incoming && a->parent() ) return false;
if( a->status() == HardBranching::Outgoing && !a->children().empty() ) return false;
if( b->status() == HardBranching::Incoming && b->parent() ) return false;
if( b->status() == HardBranching::Outgoing && !b->children().empty() ) return false;
return true;
}
bool CKKWTree::checkHardOrdering( ) {
//this function also caculates sum of pts of all branchings
totalpT_ = 0. * GeV;
hardLineScales_.clear();
//create timelike proto lines from the outgoing and hardbranchings (the ones in hard process)
vector< pair< HardBranchingPtr, vector< pair< Energy, double > > > > proto_lines;
for( set<HardBranchingPtr>::const_iterator it = this->branchings().begin();
it != this->branchings().end(); ++it) {
if( ! (*it)->branchingParticle()->coloured() ) continue;
if( (*it)->status()!=HardBranching::Incoming && ! (*it)->children().empty() ) {
vector< pair< Energy, double > > new_hard_line1;
new_hard_line1.push_back( make_pair( (*it)->scale(), (*it)->children()[0]->z() ) );
vector< pair< Energy, double > > new_hard_line2;
new_hard_line2.push_back( make_pair( (*it)->scale(), (*it)->children()[1]->z() ) );
proto_lines.push_back( make_pair( (*it)->children()[0], new_hard_line1 ) );
proto_lines.push_back( make_pair( (*it)->children()[1], new_hard_line2 ) );
//pts of children are equal so just add once
Energy branchingPt = (*it)->children()[0]->pT();
//included factor to favour ISFS branchings between partons in same z direction
//hard coded factor here should make a parameter
if( (*it)->status() == HardBranching::Incoming &&
( ( (*it)->branchingParticle()->momentum().z() > ZERO )
== ( (*it)->children()[1]->branchingParticle()->momentum().z() > ZERO ) ) )
branchingPt *= 0.9;
totalpT_ += branchingPt;
}
else if( (*it)->parent() ) {
//trace all spacelike branchings back following parents
HardBranchingPtr spacelike = *it;
vector< pair< Energy, double > > space_like_line;
while( spacelike->parent() ) {
Energy branchingPt = spacelike->pT();
assert( spacelike->parent()->children().size() == 2 );
HardBranchingPtr emitted = spacelike->parent()->children()[0] == spacelike ?
spacelike->parent()->children()[1] : spacelike->parent()->children()[0];
// included factor to favour ISFS branchings between partons in same z direction
//hard coded factor here should make a parameter
if( ( emitted ->branchingParticle()->momentum().z() > ZERO ) ==
( spacelike->parent()->branchingParticle()->momentum().z() > ZERO ) )
branchingPt *= 0.9;
totalpT_ += branchingPt;
//create a protoline from the time like child of parent
vector< pair< Energy, double > > time_like_line = space_like_line;
//timelike child is always first child
time_like_line.push_back( make_pair( spacelike->parent()->scale(),
spacelike->parent()->children()[1]->z() ) );
proto_lines.push_back( make_pair( spacelike->parent()->children()[1], time_like_line ) );
//add the parent to the space_like_line
space_like_line.push_back( make_pair( spacelike->parent()->scale(), 1. ) );
spacelike = spacelike->parent();
}
hardLineScales_.push_back( space_like_line );
}
}
//recursively fill all timelike lines from proto_lines
for( unsigned int ix = 0; ix < proto_lines.size(); ix++ ) {
fillHardScales( proto_lines[ix].first, proto_lines[ix].second );
hardLineScales_.push_back( proto_lines[ix].second );
}
//go down each line (outwards from hard sub process) checking angular ordering condition
for( unsigned int ix = 0; ix < hardLineScales_.size(); ix++ ){
for( unsigned int jx = 0; jx < hardLineScales_[ix].size(); jx++ ){
if( jx == 0 )
continue;
//angular ordering condition: z_1*q_1 > q2
//this should also work for spacelike lines since for those z was set to 1
if( hardLineScales_[ix][jx].first > hardLineScales_[ix][jx - 1].first * hardLineScales_[ix][ jx - 1 ].second )
return false;
}
}
return true;
}
void CKKWTree::fillHardScales( HardBranchingPtr branch, vector< pair< Energy, double > > & currentLine ){
if( branch->children().empty() ) return;
else{
//child[0] continues currentline child[1] creates a new line
//copy contents of old line into newline
vector< pair< Energy, double > > newHardLine = currentLine;
currentLine.push_back( make_pair( branch->scale(),
branch->children()[0]->z() ) );
fillHardScales( branch->children()[0], currentLine );
newHardLine.push_back( make_pair( branch->scale(),
branch->children()[1]->z() ) );
fillHardScales( branch->children()[1], newHardLine );
hardLineScales_.push_back( newHardLine );
}
}
void CKKWTree::findNodes() {
//clear all containers to be filled
nodes_.clear();
lowestpT_ = HardBranchingPtr();
// find all branchings that initiate a timelike shower
// also add nodes from the spacelike line
for( set<HardBranchingPtr>::const_iterator it = this->branchings().begin();
it != this->branchings().end(); ++it) {
if( ! (*it)->branchingParticle()->coloured() ) continue;
if( (*it)->status() ==HardBranching::Outgoing ){
//remove any parent ptr that might be set
(*it)->parent( HardBranchingPtr() );
fillNodes( *it );
continue;
}
HardBranchingPtr spacelike = *it;
while( spacelike->parent() ) {
assert( spacelike == spacelike->parent()->children()[0] );
spacelike = spacelike->parent();
if( ! lowestpT_ || lowestpT_->children()[0]->pT()
> spacelike->children()[0]->pT() )
lowestpT_ = spacelike;
//nb for bkwd branchings the child contains the splitting variables
nodes_.insert( make_pair( spacelike->children()[0], spacelike->children()[0]->scale() ) );
fillNodes( spacelike->children()[0] );
}
}
ordered_ = checkHardOrdering() && checkXOrdering();
}
bool CKKWTree::fillNodes( HardBranchingPtr branch ){
if( ! branch->children().empty() ) {
if( ! lowestpT_ || lowestpT_->children()[0]->pT() > branch->children()[0]->pT() )
lowestpT_ = branch;
nodes_.insert( make_pair( branch, branch->scale() ) );
fillNodes( branch->children()[0] );
fillNodes( branch->children()[1] );
}
return true;
}
Energy CKKWTree::lowestPt( int jetMeasureMode, Energy2 s ){
// perform various checks
assert( lowestpT_ && lowestpT_->children().size() == 2 &&
lowestpT_->children()[0] );
Energy ktsHat_oftest = lowestpT_->children()[0]->pT();
if( jetMeasureMode == 0 || jetMeasureMode == 2 ){
Energy pt = ktsHat_oftest;
double z = lowestpT_->children()[0]->z();
Energy2 m0 = sqr( lowestpT_->branchingParticle()->nominalMass() );
Energy2 m1 = sqr( lowestpT_->children()[0]->branchingParticle()->nominalMass() );
Energy2 m2 = sqr( lowestpT_->children()[1]->branchingParticle()->nominalMass() );
double lambda = sqrt( 1. - 4.*m0/s );
double beta1 = 2.*( m1 - sqr(z)*m0 + sqr(pt) )
/ z / lambda / ( lambda + 1. ) / s;
double beta2 = 2.*( m2 - sqr( 1. - z )*m0 + sqr(pt) )
/ ( 1. - z ) / lambda / ( lambda + 1. ) / s;
Energy E1 = sqrt(s)/2.*( z + lambda*beta1 );
Energy E2 = sqrt(s)/2.*( (1.-z) + lambda*beta2 );
Energy Z1 = sqrt(s)/2.*lambda*( z - beta1 );
Energy Z2 = sqrt(s)/2.*lambda*( (1.-z) - beta2 );
double costheta = ( Z1*Z2 - sqr(pt) )
/ sqrt( sqr(Z1)+sqr(pt) ) / sqrt( sqr(Z2)+sqr(pt) );
Energy2 kt_measure(ZERO);
if( jetMeasureMode == 0 )
kt_measure = 2.*min( sqr(E1), sqr(E2) )*( 1. - costheta );
else if( jetMeasureMode == 2 )
kt_measure = 2.*sqr(E1)*sqr(E2)/sqr(E1+E2)*( 1. - costheta );
else
assert(false);
ktsHat_oftest = sqrt( kt_measure );
}
else if( jetMeasureMode == 3 && lowestpT_->status() != HardBranching::Incoming ){
Energy2 m1 = sqr( lowestpT_->children()[0]->branchingParticle()->nominalMass() );
Energy2 m2 = sqr( lowestpT_->children()[1]->branchingParticle()->nominalMass() );
Energy pt = ktsHat_oftest;
double z = lowestpT_->z();
double beta1 = 2.*( m1 + sqr(pt) ) / z / s;
double beta2 = 2.*( m2 + sqr(pt) ) / ( 1. - z ) / s;
//delta phi is always pi for first emission (qt_i = +-pt)
double deltaR = sqr( log( z / beta1 ) - log( (1-z) / beta2 ) ) / 4.
+ sqr( Constants::pi );
ktsHat_oftest = pt*sqrt( deltaR );
}
return ktsHat_oftest;
}
diff --git a/Shower/QTilde/Matching/CKKWTree.h b/Shower/QTilde/Matching/CKKWTree.h
--- a/Shower/QTilde/Matching/CKKWTree.h
+++ b/Shower/QTilde/Matching/CKKWTree.h
@@ -1,149 +1,149 @@
// -*- C++ -*-
#ifndef HERWIG_CKKWTree_H
#define HERWIG_CKKWTree_H
//
// This is the declaration of the CKKWTree class.
//
#include "Herwig/Shower/QTilde/Base/HardTree.h"
#include "CKKWTree.fh"
namespace Herwig {
using namespace ThePEG;
/**
* Here is the documentation of the CKKWTree class.
*/
class CKKWTree: public HardTree {
public:
/**
* The default constructor.
*/
- CKKWTree(vector<HardBranchingPtr>, vector<HardBranchingPtr>, ShowerInteraction::Type);
+ CKKWTree(vector<HardBranchingPtr>, vector<HardBranchingPtr>, ShowerInteraction);
public:
/**
* Returns true if all spacelike lines are ordered in x
*/
bool checkXOrdering();
/**
* Get lowest Pt in which ever jet definition from the hardtree momentum
*/
Energy lowestPtMomentum( int jetMeasureMode, int cutOption );
/**
* Returns true if all lines in tree are ordered in /tilde(q)
*/
bool checkHardOrdering();
/**
* Returns sum of pts of all branchings in tree
*/
Energy totalPt() { return totalpT_; }
/**
* Calls recursive function to fill externals and nodes
* then finds the internal lines from the nodes
*/
void findNodes();
/**
* Access the nodal branchings
*/
map< HardBranchingPtr, Energy > & getNodes() { return nodes_; }
/**
* Get LowestPt in which ever jet definition from the shower variables
*/
Energy lowestPt( int jetMeasureMode, Energy2 s );
/**
* Is the tree ordered?
*/
bool ordered() const {return ordered_;}
protected:
/**
* Recursive function to find the lowest jet measure in a hardtree from clustered momenta
**/
void getLowestJetMeasure( HardBranchingPtr branch, int jetMeasureMode, int cutOption );
/**
* Function for finding the hadronic jet measure of two partons
**/
Energy hadronJetMeasure( const Lorentz5Momentum & p1,
const Lorentz5Momentum & p2,
bool final );
/**
* Function for finding the Durham or LUCLUS jet measures of two partons
**/
Energy getJetMeasure( const Lorentz5Momentum & p1,
const Lorentz5Momentum & p2,
int jetMeasureMode );
/**
* Function to determine whether a branching consists of external partons
**/
bool externalBranching( HardBranchingPtr a, HardBranchingPtr b );
/**
* Function to recursively find the hard line scales
**/
void fillHardScales( HardBranchingPtr branch, vector< pair< Energy, double > > & currentLine );
/**
* Recursive function to fill externals, nodes and intermediates from the time-like showers
*/
bool fillNodes( HardBranchingPtr );
/**
* Recursive function to fix the parent assignments
*/
bool fixParents( HardBranchingPtr );
private:
/**
* Map containing all nodes with the ingoing partons and their scale
* (this is the the intermediates and their ending node).
*/
map< HardBranchingPtr, Energy > nodes_;
/**
* Scales and z along each hard line to check ordering
*/
vector< vector< pair< Energy, double > > > hardLineScales_;
/**
* The lowest pt of the branchings in the hardtree in whatever
* jet measure according to the hardtree momenta (not the shower variables)
*/
Energy lowestpTMomentum_;
/**
* The sum of the pts of all branchings
*/
Energy totalpT_;
/**
* The hardBranching of softest branching
* This is found by looking at tree end points in fillNodes
*/
HardBranchingPtr lowestpT_;
/**
* Is the tree ordered
*/
bool ordered_;
};
}
#endif /* HERWIG_CKKWTree_H */
diff --git a/Shower/QTilde/Matching/ProtoBranching.h b/Shower/QTilde/Matching/ProtoBranching.h
--- a/Shower/QTilde/Matching/ProtoBranching.h
+++ b/Shower/QTilde/Matching/ProtoBranching.h
@@ -1,202 +1,202 @@
// -*- C++ -*-
#ifndef HERWIG_ProtoBranching_H
#define HERWIG_ProtoBranching_H
//
// This is the declaration of the ProtoBranching class.
//
namespace Herwig {
using namespace ThePEG;
/**
* Declare the pointers
*/
class ProtoBranching;
ThePEG_DECLARE_POINTERS(Herwig::ProtoBranching,ProtoBranchingPtr);
/**
* Class to store a prototype branching
*/
class ProtoBranching : public Base {
public:
/**
* Default constructor
*/
ProtoBranching() {}
/**
* Constructor
*/
ProtoBranching(tcPDPtr part, HardBranching::Status status,
const Lorentz5Momentum & momentum,
tSudakovPtr sudakov)
: part_(part), status_(status), momentum_(momentum),
sudakov_(sudakov), type_(ShowerPartnerType::Undefined)
{}
/**
* Id of the brnaching particle
*/
long id() { return part_->id();}
/**
* The ParticleData
*/
tcPDPtr particle() {return part_;}
/**
* Status of the branching
*/
HardBranching::Status status() {return status_;}
/**
* Set the parent
*/
tProtoBranchingPtr parent() {return parent_;}
/**
* Get the parent
*/
void parent(tProtoBranchingPtr in) {parent_=in;}
/**
* Children
*/
vector<tProtoBranchingPtr> children() {return children_;}
/**
* Add a child
*/
void addChild(tProtoBranchingPtr in ) {children_.push_back(in);}
/**
* Back children
*/
vector<tProtoBranchingPtr> backChildren() {return backChildren_;}
/**
* Add a child
*/
void addBackChild(tProtoBranchingPtr in ) {backChildren_.push_back(in);}
/**
* momentum
*/
const Lorentz5Momentum & momentum() {return momentum_;}
/**
* Get the Sudakov
*/
tSudakovPtr sudakov() {return sudakov_;}
/**
* Set the Sudakov
*/
void sudakov(tSudakovPtr in) { sudakov_=in; }
/**
* Type of branching
*/
- ShowerPartnerType::Type type() const {
+ ShowerPartnerType type() const {
return type_;
}
/**
* Type of branching
*/
- void type(ShowerPartnerType::Type in) {
+ void type(ShowerPartnerType in) {
type_ = in;
assert(type_!=ShowerPartnerType::Undefined);
}
/**
* Colour line
*/
tColinePtr colourLine() const {
return colourLine_;
}
/**
* Anticolour line
*/
tColinePtr antiColourLine() const {
return antiColourLine_;
}
/**
* Colour line
*/
void colourLine(tColinePtr in) {
colourLine_ = in;
}
/**
* Anticolour line
*/
void antiColourLine(tColinePtr in) {
antiColourLine_ = in;
}
private:
/**
* PDG code
*/
tcPDPtr part_;
/**
* status
*/
HardBranching::Status status_;
/**
* Momentum
*/
Lorentz5Momentum momentum_;
/**
* Sudakov
*/
tSudakovPtr sudakov_;
/**
* children
*/
vector<tProtoBranchingPtr> children_;
/**
* back children
*/
vector<tProtoBranchingPtr> backChildren_;
/**
* parent
*/
tProtoBranchingPtr parent_;
/**
* The type of branching
*/
- ShowerPartnerType::Type type_;
+ ShowerPartnerType type_;
/**
* Colour lines
*/
//@{
/**
* Colour line
*/
tColinePtr colourLine_;
/**
* Anticolour line
*/
tColinePtr antiColourLine_;
//@}
};
}
#endif /* HERWIG_ProtoBranching_H */
diff --git a/Shower/QTilde/QTildeShowerHandler.cc b/Shower/QTilde/QTildeShowerHandler.cc
--- a/Shower/QTilde/QTildeShowerHandler.cc
+++ b/Shower/QTilde/QTildeShowerHandler.cc
@@ -1,3723 +1,3723 @@
// -*- C++ -*-
//
// This is the implementation of the non-inlined, non-templated member
// functions of the QTildeShowerHandler class.
//
#include "QTildeShowerHandler.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Parameter.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 "ThePEG/Utilities/EnumIO.h"
#include "Herwig/Shower/QTilde/Base/ShowerParticle.h"
#include "Herwig/PDF/MPIPDF.h"
#include "Herwig/PDF/MinBiasPDF.h"
#include "Herwig/Shower/QTilde/Base/ShowerTree.h"
#include "Herwig/Shower/QTilde/Base/KinematicsReconstructor.h"
#include "Herwig/Shower/QTilde/Base/PartnerFinder.h"
#include "Herwig/PDF/HwRemDecayer.h"
#include "Herwig/Shower/QTilde/Base/ShowerVertex.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "Herwig/MatrixElement/Matchbox/Base/SubtractedME.h"
#include "Herwig/MatrixElement/Matchbox/MatchboxFactory.h"
#include "ThePEG/PDF/PartonExtractor.h"
#include "Herwig/Shower/RealEmissionProcess.h"
using namespace Herwig;
namespace {
/**
* A struct to order the particles in the same way as in the DecayMode's
*/
struct ParticleOrdering {
/**
* Operator for the ordering
* @param p1 The first ParticleData object
* @param p2 The second ParticleData object
*/
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() );
}
};
typedef multiset<tcPDPtr,ParticleOrdering> OrderedParticles;
/**
* Cached lookup of decay modes.
* Generator::findDecayMode() is not efficient.
*/
tDMPtr findDecayMode(const string & tag) {
static map<string,DMPtr> cache;
map<string,DMPtr>::const_iterator pos = cache.find(tag);
if ( pos != cache.end() )
return pos->second;
tDMPtr dm = CurrentGenerator::current().findDecayMode(tag);
cache[tag] = dm;
return dm;
}
}
bool QTildeShowerHandler::_hardEmissionWarn = true;
bool QTildeShowerHandler::_missingTruncWarn = true;
QTildeShowerHandler::QTildeShowerHandler() :
_maxtry(100), _meCorrMode(1), _reconOpt(0),
_hardVetoReadOption(false),
_iptrms(ZERO), _beta(0.), _gamma(ZERO), _iptmax(),
_limitEmissions(0), _initialenhance(1.), _finalenhance(1.),
_nReWeight(100), _reWeight(false),
interaction_(ShowerInteraction::Both),
_trunc_Mode(true), _hardEmission(1),
_spinOpt(1), _softOpt(2), _hardPOWHEG(false), muPt(ZERO),
_maxTryFSR(100000), _maxFailFSR(100), _fracFSR(0.001),
_nFSR(0), _nFailedFSR(0)
{}
QTildeShowerHandler::~QTildeShowerHandler() {}
IBPtr QTildeShowerHandler::clone() const {
return new_ptr(*this);
}
IBPtr QTildeShowerHandler::fullclone() const {
return new_ptr(*this);
}
void QTildeShowerHandler::persistentOutput(PersistentOStream & os) const {
os << _model << _splittingGenerator << _maxtry
<< _meCorrMode << _hardVetoReadOption
<< _limitEmissions << _spinOpt << _softOpt << _hardPOWHEG
<< ounit(_iptrms,GeV) << _beta << ounit(_gamma,GeV) << ounit(_iptmax,GeV)
<< _vetoes << _fullShowerVetoes << _nReWeight << _reWeight
<< _trunc_Mode << _hardEmission << _reconOpt
<< ounit(muPt,GeV)
<< oenum(interaction_) << _maxTryFSR << _maxFailFSR << _fracFSR;
}
void QTildeShowerHandler::persistentInput(PersistentIStream & is, int) {
is >> _model >> _splittingGenerator >> _maxtry
>> _meCorrMode >> _hardVetoReadOption
>> _limitEmissions >> _spinOpt >> _softOpt >> _hardPOWHEG
>> iunit(_iptrms,GeV) >> _beta >> iunit(_gamma,GeV) >> iunit(_iptmax,GeV)
>> _vetoes >> _fullShowerVetoes >> _nReWeight >> _reWeight
>> _trunc_Mode >> _hardEmission >> _reconOpt
>> iunit(muPt,GeV)
>> ienum(interaction_) >> _maxTryFSR >> _maxFailFSR >> _fracFSR;
}
// The following static variable is needed for the type
// description system in ThePEG.
DescribeClass<QTildeShowerHandler,ShowerHandler>
describeHerwigQTildeShowerHandler("Herwig::QTildeShowerHandler", "HwShower.so");
void QTildeShowerHandler::Init() {
static ClassDocumentation<QTildeShowerHandler> documentation
("TheQTildeShowerHandler class is the main class"
" for the angular-ordered parton shower",
"The Shower evolution was performed using an algorithm described in "
"\\cite{Marchesini:1983bm,Marchesini:1987cf,Gieseke:2003rz,Bahr:2008pv}.",
"%\\cite{Marchesini:1983bm}\n"
"\\bibitem{Marchesini:1983bm}\n"
" G.~Marchesini and B.~R.~Webber,\n"
" ``Simulation Of QCD Jets Including Soft Gluon Interference,''\n"
" Nucl.\\ Phys.\\ B {\\bf 238}, 1 (1984).\n"
" %%CITATION = NUPHA,B238,1;%%\n"
"%\\cite{Marchesini:1987cf}\n"
"\\bibitem{Marchesini:1987cf}\n"
" G.~Marchesini and B.~R.~Webber,\n"
" ``Monte Carlo Simulation of General Hard Processes with Coherent QCD\n"
" Radiation,''\n"
" Nucl.\\ Phys.\\ B {\\bf 310}, 461 (1988).\n"
" %%CITATION = NUPHA,B310,461;%%\n"
"%\\cite{Gieseke:2003rz}\n"
"\\bibitem{Gieseke:2003rz}\n"
" S.~Gieseke, P.~Stephens and B.~Webber,\n"
" ``New formalism for QCD parton showers,''\n"
" JHEP {\\bf 0312}, 045 (2003)\n"
" [arXiv:hep-ph/0310083].\n"
" %%CITATION = JHEPA,0312,045;%%\n"
);
static Reference<QTildeShowerHandler,SplittingGenerator>
interfaceSplitGen("SplittingGenerator",
"A reference to the SplittingGenerator object",
&Herwig::QTildeShowerHandler::_splittingGenerator,
false, false, true, false);
static Reference<QTildeShowerHandler,ShowerModel> interfaceShowerModel
("ShowerModel",
"The pointer to the object which defines the shower evolution model.",
&QTildeShowerHandler::_model, false, false, true, false, false);
static Parameter<QTildeShowerHandler,unsigned int> interfaceMaxTry
("MaxTry",
"The maximum number of attempts to generate the shower from a"
" particular ShowerTree",
&QTildeShowerHandler::_maxtry, 100, 1, 100000,
false, false, Interface::limited);
static Parameter<QTildeShowerHandler,unsigned int> interfaceNReWeight
("NReWeight",
"The number of attempts for the shower when reweighting",
&QTildeShowerHandler::_nReWeight, 100, 10, 10000,
false, false, Interface::limited);
static Switch<QTildeShowerHandler, unsigned int> ifaceMECorrMode
("MECorrMode",
"Choice of the ME Correction Mode",
&QTildeShowerHandler::_meCorrMode, 1, false, false);
static SwitchOption on
(ifaceMECorrMode,"HardPlusSoft","hard+soft on", 1);
static SwitchOption hard
(ifaceMECorrMode,"Hard","only hard on", 2);
static SwitchOption soft
(ifaceMECorrMode,"Soft","only soft on", 3);
static Switch<QTildeShowerHandler, bool> ifaceHardVetoReadOption
("HardVetoReadOption",
"Apply read-in scale veto to all collisions or just the primary one?",
&QTildeShowerHandler::_hardVetoReadOption, false, false, false);
static SwitchOption AllCollisions
(ifaceHardVetoReadOption,
"AllCollisions",
"Read-in pT veto applied to primary and secondary collisions.",
false);
static SwitchOption PrimaryCollision
(ifaceHardVetoReadOption,
"PrimaryCollision",
"Read-in pT veto applied to primary but not secondary collisions.",
true);
static Parameter<QTildeShowerHandler, Energy> ifaceiptrms
("IntrinsicPtGaussian",
"RMS of intrinsic pT of Gaussian distribution:\n"
"2*(1-Beta)*exp(-sqr(intrinsicpT/RMS))/sqr(RMS)",
&QTildeShowerHandler::_iptrms, GeV, ZERO, ZERO, 1000000.0*GeV,
false, false, Interface::limited);
static Parameter<QTildeShowerHandler, double> ifacebeta
("IntrinsicPtBeta",
"Proportion of inverse quadratic distribution in generating intrinsic pT.\n"
"(1-Beta) is the proportion of Gaussian distribution",
&QTildeShowerHandler::_beta, 0, 0, 1,
false, false, Interface::limited);
static Parameter<QTildeShowerHandler, Energy> ifacegamma
("IntrinsicPtGamma",
"Parameter for inverse quadratic:\n"
"2*Beta*Gamma/(sqr(Gamma)+sqr(intrinsicpT))",
&QTildeShowerHandler::_gamma,GeV, ZERO, ZERO, 100000.0*GeV,
false, false, Interface::limited);
static Parameter<QTildeShowerHandler, Energy> ifaceiptmax
("IntrinsicPtIptmax",
"Upper bound on intrinsic pT for inverse quadratic",
&QTildeShowerHandler::_iptmax,GeV, ZERO, ZERO, 100000.0*GeV,
false, false, Interface::limited);
static RefVector<QTildeShowerHandler,ShowerVeto> ifaceVetoes
("Vetoes",
"The vetoes to be checked during showering",
&QTildeShowerHandler::_vetoes, -1,
false,false,true,true,false);
static RefVector<QTildeShowerHandler,FullShowerVeto> interfaceFullShowerVetoes
("FullShowerVetoes",
"The vetos to be appliede on the full final state of the shower",
&QTildeShowerHandler::_fullShowerVetoes, -1, false, false, true, false, false);
static Switch<QTildeShowerHandler,unsigned int> interfaceLimitEmissions
("LimitEmissions",
"Limit the number and type of emissions for testing",
&QTildeShowerHandler::_limitEmissions, 0, false, false);
static SwitchOption interfaceLimitEmissionsNoLimit
(interfaceLimitEmissions,
"NoLimit",
"Allow an arbitrary number of emissions",
0);
static SwitchOption interfaceLimitEmissionsOneInitialStateEmission
(interfaceLimitEmissions,
"OneInitialStateEmission",
"Allow one emission in the initial state and none in the final state",
1);
static SwitchOption interfaceLimitEmissionsOneFinalStateEmission
(interfaceLimitEmissions,
"OneFinalStateEmission",
"Allow one emission in the final state and none in the initial state",
2);
static SwitchOption interfaceLimitEmissionsHardOnly
(interfaceLimitEmissions,
"HardOnly",
"Only allow radiation from the hard ME correction",
3);
static SwitchOption interfaceLimitEmissionsOneEmission
(interfaceLimitEmissions,
"OneEmission",
"Allow one emission in either the final state or initial state, but not both",
4);
static Switch<QTildeShowerHandler,bool> interfaceTruncMode
("TruncatedShower", "Include the truncated shower?",
&QTildeShowerHandler::_trunc_Mode, 1, false, false);
static SwitchOption interfaceTruncMode0
(interfaceTruncMode,"No","Truncated Shower is OFF", 0);
static SwitchOption interfaceTruncMode1
(interfaceTruncMode,"Yes","Truncated Shower is ON", 1);
static Switch<QTildeShowerHandler,int> interfaceHardEmission
("HardEmission",
"Whether to use ME corrections or POWHEG for the hardest emission",
&QTildeShowerHandler::_hardEmission, 0, false, false);
static SwitchOption interfaceHardEmissionNone
(interfaceHardEmission,
"None",
"No Corrections",
0);
static SwitchOption interfaceHardEmissionMECorrection
(interfaceHardEmission,
"MECorrection",
"Old fashioned ME correction",
1);
static SwitchOption interfaceHardEmissionPOWHEG
(interfaceHardEmission,
"POWHEG",
"Powheg style hard emission",
2);
- static Switch<QTildeShowerHandler,ShowerInteraction::Type> interfaceInteractions
+ static Switch<QTildeShowerHandler,ShowerInteraction> interfaceInteractions
("Interactions",
"The interactions to be used in the shower",
&QTildeShowerHandler::interaction_, ShowerInteraction::Both, false, false);
static SwitchOption interfaceInteractionsQCD
(interfaceInteractions,
"QCD",
"Only QCD radiation",
ShowerInteraction::QCD);
static SwitchOption interfaceInteractionsQED
(interfaceInteractions,
"QED",
"Only QEd radiation",
ShowerInteraction::QED);
static SwitchOption interfaceInteractionsQCDandQED
(interfaceInteractions,
"QCDandQED",
"Both QED and QCD radiation",
ShowerInteraction::Both);
static Switch<QTildeShowerHandler,unsigned int> interfaceReconstructionOption
("ReconstructionOption",
"Treatment of the reconstruction of the transverse momentum of "
"a branching from the evolution scale.",
&QTildeShowerHandler::_reconOpt, 0, false, false);
static SwitchOption interfaceReconstructionOptionCutOff
(interfaceReconstructionOption,
"CutOff",
"Use the cut-off masses in the calculation",
0);
static SwitchOption interfaceReconstructionOptionOffShell
(interfaceReconstructionOption,
"OffShell",
"Use the off-shell masses in the calculation veto the emission of the parent,"
" no veto in generation of emissions from children",
1);
static SwitchOption interfaceReconstructionOptionOffShell2
(interfaceReconstructionOption,
"OffShell2",
"Use the off-shell masses in the calculation veto the emissions from the children."
" no veto in generation of emissions from children",
2);
static SwitchOption interfaceReconstructionOptionOffShell3
(interfaceReconstructionOption,
"OffShell3",
"Use the off-shell masses in the calculation veto the emissions from the children."
" veto in generation of emissions from children using cut-off for second parton",
3);
static SwitchOption interfaceReconstructionOptionOffShell4
(interfaceReconstructionOption,
"OffShell4",
"Ass OffShell3 but with a restriction on the mass of final-state"
" jets produced via backward evolution.",
4);
static Switch<QTildeShowerHandler,unsigned int> interfaceSpinCorrelations
("SpinCorrelations",
"Treatment of spin correlations in the parton shower",
&QTildeShowerHandler::_spinOpt, 1, false, false);
static SwitchOption interfaceSpinCorrelationsOff
(interfaceSpinCorrelations,
"No",
"No spin correlations",
0);
static SwitchOption interfaceSpinCorrelationsSpin
(interfaceSpinCorrelations,
"Yes",
"Include the azimuthal spin correlations only",
1);
static Switch<QTildeShowerHandler,unsigned int> interfaceSoftCorrelations
("SoftCorrelations",
"Option for the treatment of soft correlations in the parton shower",
&QTildeShowerHandler::_softOpt, 2, false, false);
static SwitchOption interfaceSoftCorrelationsNone
(interfaceSoftCorrelations,
"No",
"No soft correlations",
0);
static SwitchOption interfaceSoftCorrelationsFull
(interfaceSoftCorrelations,
"Full",
"Use the full eikonal",
1);
static SwitchOption interfaceSoftCorrelationsSingular
(interfaceSoftCorrelations,
"Singular",
"Use original Webber-Marchisini form",
2);
static Switch<QTildeShowerHandler,bool> interfaceHardPOWHEG
("HardPOWHEG",
"Treatment of powheg emissions which are too hard to have a shower interpretation",
&QTildeShowerHandler::_hardPOWHEG, false, false, false);
static SwitchOption interfaceHardPOWHEGAsShower
(interfaceHardPOWHEG,
"AsShower",
"Still interpret as shower emissions",
false);
static SwitchOption interfaceHardPOWHEGRealEmission
(interfaceHardPOWHEG,
"RealEmission",
"Generate shower from the real emmission configuration",
true);
static Parameter<QTildeShowerHandler,unsigned int> interfaceMaxTryFSR
("MaxTryFSR",
"The maximum number of attempted FSR emissions in"
" the generation of the FSR",
&QTildeShowerHandler::_maxTryFSR, 100000, 10, 100000000,
false, false, Interface::limited);
static Parameter<QTildeShowerHandler,unsigned int> interfaceMaxFailFSR
("MaxFailFSR",
"Maximum number of failures generating the FSR",
&QTildeShowerHandler::_maxFailFSR, 100, 1, 100000000,
false, false, Interface::limited);
static Parameter<QTildeShowerHandler,double> interfaceFSRFailureFraction
("FSRFailureFraction",
"Maximum fraction of events allowed to fail due to too many FSR emissions",
&QTildeShowerHandler::_fracFSR, 0.001, 1e-10, 1,
false, false, Interface::limited);
}
tPPair QTildeShowerHandler::cascade(tSubProPtr sub,
XCPtr xcomb) {
// use me for reference in tex file etc
useMe();
prepareCascade(sub);
// set things up in the base class
resetWeights();
hard_=ShowerTreePtr();
decay_.clear();
done_.clear();
// check if anything needs doing
if ( !doFSR() && ! doISR() )
return sub->incoming();
// start of the try block for the whole showering process
unsigned int countFailures=0;
while (countFailures<maxtry()) {
try {
decay_.clear();
done_.clear();
PerturbativeProcessPtr hard;
DecayProcessMap decay;
splitHardProcess(firstInteraction() ? tagged() :
tPVector(currentSubProcess()->outgoing().begin(),
currentSubProcess()->outgoing().end()),
hard,decay);
ShowerTree::constructTrees(hard_,decay_,hard,decay);
// if no hard process
if(!hard_) throw Exception() << "Shower starting with a decay"
<< "is not implemented"
<< Exception::runerror;
// perform the shower for the hard process
showerHardProcess(hard_,xcomb);
done_.push_back(hard_);
hard_->updateAfterShower(decay_);
// if no decaying particles to shower break out of the loop
if(decay_.empty()) break;
// shower the decay products
while(!decay_.empty()) {
// find particle whose production process has been showered
ShowerDecayMap::iterator dit = decay_.begin();
while(!dit->second->parent()->hasShowered() && dit!=decay_.end()) ++dit;
assert(dit!=decay_.end());
// get the particle
ShowerTreePtr decayingTree = dit->second;
// remove it from the multimap
decay_.erase(dit);
// make sure the particle has been decayed
QTildeShowerHandler::decay(decayingTree,decay_);
// now shower the decay
showerDecay(decayingTree);
done_.push_back(decayingTree);
decayingTree->updateAfterShower(decay_);
}
// suceeded break out of the loop
break;
}
catch (KinematicsReconstructionVeto) {
resetWeights();
++countFailures;
}
}
// if loop exited because of too many tries, throw event away
if (countFailures >= maxtry()) {
resetWeights();
hard_=ShowerTreePtr();
decay_.clear();
done_.clear();
throw Exception() << "Too many tries for main while loop "
<< "in ShowerHandler::cascade()."
<< Exception::eventerror;
}
//enter the particles in the event record
fillEventRecord();
// clear storage
hard_=ShowerTreePtr();
decay_.clear();
done_.clear();
// non hadronic case return
if (!isResolvedHadron(incomingBeams().first ) &&
!isResolvedHadron(incomingBeams().second) )
return incomingBeams();
// remake the remnants (needs to be after the colours are sorted
// out in the insertion into the event record)
if ( firstInteraction() ) return remakeRemnant(sub->incoming());
//Return the new pair of incoming partons. remakeRemnant is not
//necessary here, because the secondary interactions are not yet
//connected to the remnants.
return make_pair(findFirstParton(sub->incoming().first ),
findFirstParton(sub->incoming().second));
}
void QTildeShowerHandler::fillEventRecord() {
// create a new step
StepPtr pstep = newStep();
assert(!done_.empty());
assert(done_[0]->isHard());
// insert the steps
for(unsigned int ix=0;ix<done_.size();++ix) {
done_[ix]->fillEventRecord(pstep,doISR(),doFSR());
}
}
HardTreePtr QTildeShowerHandler::generateCKKW(ShowerTreePtr ) const {
return HardTreePtr();
}
void QTildeShowerHandler::doinit() {
ShowerHandler::doinit();
// interactions may have been changed through a setup file so we
// clear it up here
// calculate max no of FSR vetos
_maxFailFSR = max(int(_maxFailFSR), int(_fracFSR*double(generator()->N())));
// check on the reweighting
for(unsigned int ix=0;ix<_fullShowerVetoes.size();++ix) {
if(_fullShowerVetoes[ix]->behaviour()==1) {
_reWeight = true;
break;
}
}
if(_reWeight && maximumTries()<_nReWeight) {
throw Exception() << "Reweight being performed in the shower but the number of attempts for the"
<< "shower is less than that for the reweighting.\n"
<< "Maximum number of attempt for the shower "
<< fullName() << ":MaxTry is " << maximumTries() << "\nand for reweighting is "
<< fullName() << ":NReWeight is " << _nReWeight << "\n"
<< "we recommend the number of attempts is 10 times the number for reweighting\n"
<< Exception::runerror;
}
}
void QTildeShowerHandler::generateIntrinsicpT(vector<ShowerProgenitorPtr> particlesToShower) {
_intrinsic.clear();
if ( !ipTon() || !doISR() ) return;
// don't do anything for the moment for secondary scatters
if( !firstInteraction() ) return;
// generate intrinsic pT
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
// only consider initial-state particles
if(particlesToShower[ix]->progenitor()->isFinalState()) continue;
if(!particlesToShower[ix]->progenitor()->dataPtr()->coloured()) continue;
Energy ipt;
if(UseRandom::rnd() > _beta) {
ipt=_iptrms*sqrt(-log(UseRandom::rnd()));
}
else {
ipt=_gamma*sqrt(pow(1.+sqr(_iptmax/_gamma), UseRandom::rnd())-1.);
}
pair<Energy,double> pt = make_pair(ipt,UseRandom::rnd(Constants::twopi));
_intrinsic[particlesToShower[ix]] = pt;
}
}
void QTildeShowerHandler::setupMaximumScales(const vector<ShowerProgenitorPtr> & p,
XCPtr xcomb) {
// let POWHEG events radiate freely
if(_hardEmission==2&&hardTree()) {
vector<ShowerProgenitorPtr>::const_iterator ckt = p.begin();
for (; ckt != p.end(); ckt++) (*ckt)->maxHardPt(Constants::MaxEnergy);
return;
}
// return if no vetos
if (!restrictPhasespace()) return;
// find out if hard partonic subprocess.
bool isPartonic(false);
map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit = _currenttree->incomingLines().begin();
Lorentz5Momentum pcm;
for(; cit!=currentTree()->incomingLines().end(); ++cit) {
pcm += cit->first->progenitor()->momentum();
isPartonic |= cit->first->progenitor()->coloured();
}
// find minimum pt from hard process, the maximum pt from all outgoing
// coloured lines (this is simpler and more general than
// 2stu/(s^2+t^2+u^2)). Maximum scale for scattering processes will
// be transverse mass.
Energy ptmax = generator()->maximumCMEnergy();
// general case calculate the scale
if ( !hardScaleIsMuF() || (hardVetoReadOption()&&!firstInteraction()) ) {
// scattering process
if(currentTree()->isHard()) {
assert(xcomb);
// coloured incoming particles
if (isPartonic) {
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
cjt = currentTree()->outgoingLines().begin();
for(; cjt!=currentTree()->outgoingLines().end(); ++cjt) {
if (cjt->first->progenitor()->coloured())
ptmax = min(ptmax,cjt->first->progenitor()->momentum().mt());
}
}
if (ptmax == generator()->maximumCMEnergy() ) ptmax = pcm.m();
if(hardScaleIsMuF()&&hardVetoReadOption()&&
!firstInteraction()) {
ptmax=min(ptmax,sqrt(xcomb->lastShowerScale()));
}
}
// decay, incoming() is the decaying particle.
else {
ptmax = currentTree()->incomingLines().begin()->first
->progenitor()->momentum().mass();
}
}
// hepeup.SCALUP is written into the lastXComb by the
// LesHouchesReader itself - use this by user's choice.
// Can be more general than this.
else {
if(currentTree()->isHard()) {
assert(xcomb);
ptmax = sqrt( xcomb->lastShowerScale() );
}
else {
ptmax = currentTree()->incomingLines().begin()->first
->progenitor()->momentum().mass();
}
}
ptmax *= hardScaleFactor();
// set maxHardPt for all progenitors. For partonic processes this
// is now the max pt in the FS, for non-partonic processes or
// processes with no coloured FS the invariant mass of the IS
vector<ShowerProgenitorPtr>::const_iterator ckt = p.begin();
for (; ckt != p.end(); ckt++) (*ckt)->maxHardPt(ptmax);
}
void QTildeShowerHandler::setupHardScales(const vector<ShowerProgenitorPtr> & p,
XCPtr xcomb) {
if ( hardScaleIsMuF() &&
(!hardVetoReadOption() || firstInteraction()) ) {
Energy hardScale = ZERO;
if(currentTree()->isHard()) {
assert(xcomb);
hardScale = sqrt( xcomb->lastShowerScale() );
}
else {
hardScale = currentTree()->incomingLines().begin()->first
->progenitor()->momentum().mass();
}
hardScale *= hardScaleFactor();
vector<ShowerProgenitorPtr>::const_iterator ckt = p.begin();
for (; ckt != p.end(); ckt++) (*ckt)->hardScale(hardScale);
muPt = hardScale;
}
}
void QTildeShowerHandler::showerHardProcess(ShowerTreePtr hard, XCPtr xcomb) {
_hardme = HwMEBasePtr();
// extract the matrix element
tStdXCombPtr lastXC = dynamic_ptr_cast<tStdXCombPtr>(xcomb);
if(lastXC) {
_hardme = dynamic_ptr_cast<HwMEBasePtr>(lastXC->matrixElement());
}
_decayme = HwDecayerBasePtr();
// set the current tree
currentTree(hard);
hardTree(HardTreePtr());
// work out the type of event
currentTree()->xcombPtr(dynamic_ptr_cast<StdXCombPtr>(xcomb));
currentTree()->identifyEventType();
checkFlags();
// generate the showering
doShowering(true,xcomb);
}
RealEmissionProcessPtr QTildeShowerHandler::hardMatrixElementCorrection(bool hard) {
// set the initial enhancement factors for the soft correction
_initialenhance = 1.;
_finalenhance = 1.;
// see if we can get the correction from the matrix element
// or decayer
RealEmissionProcessPtr real;
if(hard) {
if(_hardme&&_hardme->hasMECorrection()) {
_hardme->initializeMECorrection(_currenttree->perturbativeProcess(),
_initialenhance,_finalenhance);
if(hardMEC())
real =
_hardme->applyHardMatrixElementCorrection(_currenttree->perturbativeProcess());
}
}
else {
if(_decayme&&_decayme->hasMECorrection()) {
_decayme->initializeMECorrection(_currenttree->perturbativeProcess(),
_initialenhance,_finalenhance);
if(hardMEC())
real = _decayme->applyHardMatrixElementCorrection(_currenttree->perturbativeProcess());
}
}
return real;
}
ShowerParticleVector QTildeShowerHandler::createTimeLikeChildren(tShowerParticlePtr, IdList ids) {
// Create the ShowerParticle objects for the two children of
// the emitting particle; set the parent/child relationship
// if same as definition create particles, otherwise create cc
ShowerParticleVector children;
for(unsigned int ix=0;ix<2;++ix) {
children.push_back(new_ptr(ShowerParticle(ids[ix+1],true)));
if(children[ix]->id()==_progenitor->id()&&!ids[ix+1]->stable())
children[ix]->set5Momentum(Lorentz5Momentum(_progenitor->progenitor()->mass()));
else
children[ix]->set5Momentum(Lorentz5Momentum(ids[ix+1]->mass()));
}
return children;
}
bool QTildeShowerHandler::timeLikeShower(tShowerParticlePtr particle,
- ShowerInteraction::Type type,
+ ShowerInteraction type,
Branching fb, bool first) {
// don't do anything if not needed
if(_limitEmissions == 1 || hardOnly() ||
( _limitEmissions == 2 && _nfs != 0) ||
( _limitEmissions == 4 && _nfs + _nis != 0) ) {
if(particle->spinInfo()) particle->spinInfo()->develop();
return false;
}
// too many tries
if(_nFSR>=_maxTryFSR) {
++_nFailedFSR;
// too many failed events
if(_nFailedFSR>=_maxFailFSR)
throw Exception() << "Too many events have failed due to too many shower emissions, in\n"
<< "QTildeShowerHandler::timeLikeShower(). Terminating run\n"
<< Exception::runerror;
throw Exception() << "Too many attempted emissions in QTildeShowerHandler::timeLikeShower()\n"
<< Exception::eventerror;
}
// generate the emission
ShowerParticleVector children;
int ntry=0;
// generate the emission
if(!fb.kinematics)
fb = selectTimeLikeBranching(particle,type,HardBranchingPtr());
// no emission, return
if(!fb.kinematics) {
if(particle->spinInfo()) particle->spinInfo()->develop();
return false;
}
Branching fc[2];
bool setupChildren = true;
while (ntry<50) {
fc[0] = Branching();
fc[1] = Branching();
++ntry;
assert(fb.kinematics);
// has emitted
// Assign the shower kinematics to the emitting particle.
if(setupChildren) {
++_nFSR;
particle->showerKinematics(fb.kinematics);
// check highest pT
if(fb.kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(fb.kinematics->pT());
// create the children
children = createTimeLikeChildren(particle,fb.ids);
// update the children
particle->showerKinematics()->
updateChildren(particle, children,fb.type,_reconOpt>=3);
// update number of emissions
++_nfs;
if(_limitEmissions!=0) {
if(children[0]->spinInfo()) children[0]->spinInfo()->develop();
if(children[1]->spinInfo()) children[1]->spinInfo()->develop();
if(particle->spinInfo()) particle->spinInfo()->develop();
return true;
}
setupChildren = false;
}
// select branchings for children
fc[0] = selectTimeLikeBranching(children[0],type,HardBranchingPtr());
fc[1] = selectTimeLikeBranching(children[1],type,HardBranchingPtr());
// old default
if(_reconOpt==0) {
// shower the first particle
if(fc[0].kinematics) timeLikeShower(children[0],type,fc[0],false);
if(children[0]->spinInfo()) children[0]->spinInfo()->develop();
// shower the second particle
if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],false);
if(children[1]->spinInfo()) children[1]->spinInfo()->develop();
break;
}
// Herwig default
else if(_reconOpt==1) {
// shower the first particle
if(fc[0].kinematics) timeLikeShower(children[0],type,fc[0],false);
if(children[0]->spinInfo()) children[0]->spinInfo()->develop();
// shower the second particle
if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],false);
if(children[1]->spinInfo()) children[1]->spinInfo()->develop();
// branching has happened
particle->showerKinematics()->updateParent(particle, children,fb.type);
// clean up the vetoed emission
if(particle->virtualMass()==ZERO) {
particle->showerKinematics(ShoKinPtr());
for(unsigned int ix=0;ix<children.size();++ix)
particle->abandonChild(children[ix]);
children.clear();
if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr());
particle->vetoEmission(fb.type,fb.kinematics->scale());
// generate the new emission
fb = selectTimeLikeBranching(particle,type,HardBranchingPtr());
// no emission, return
if(!fb.kinematics) {
if(particle->spinInfo()) particle->spinInfo()->develop();
return false;
}
setupChildren = true;
continue;
}
else
break;
}
// veto children
else if(_reconOpt>=2) {
// cut-off masses for the branching
const vector<Energy> & virtualMasses = fb.sudakov->virtualMasses(fb.ids);
// compute the masses of the children
Energy masses[3];
for(unsigned int ix=0;ix<2;++ix) {
if(fc[ix].kinematics) {
const vector<Energy> & vm = fc[ix].sudakov->virtualMasses(fc[ix].ids);
Energy2 q2 =
fc[ix].kinematics->z()*(1.-fc[ix].kinematics->z())*sqr(fc[ix].kinematics->scale());
if(fc[ix].ids[0]->id()!=ParticleID::g) q2 += sqr(vm[0]);
masses[ix+1] = sqrt(q2);
}
else {
masses[ix+1] = virtualMasses[ix+1];
}
}
masses[0] = fb.ids[0]->id()!=ParticleID::g ? virtualMasses[0] : ZERO;
double z = fb.kinematics->z();
Energy2 pt2 = z*(1.-z)*(z*(1.-z)*sqr(fb.kinematics->scale()) + sqr(masses[0]))
- sqr(masses[1])*(1.-z) - sqr(masses[2])*z;
if(pt2>=ZERO) {
break;
}
else {
// reset the scales for the children
for(unsigned int ix=0;ix<2;++ix) {
if(fc[ix].kinematics)
children[ix]->vetoEmission(fc[ix].type,fc[ix].kinematics->scale());
else
children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,ZERO);
children[ix]->virtualMass(ZERO);
}
}
}
};
if(_reconOpt>=2) {
// shower the first particle
if(fc[0].kinematics) timeLikeShower(children[0],type,fc[0],false);
if(children[0]->spinInfo()) children[0]->spinInfo()->develop();
// shower the second particle
if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],false);
if(children[1]->spinInfo()) children[1]->spinInfo()->develop();
// branching has happened
particle->showerKinematics()->updateParent(particle, children,fb.type);
}
if(first&&!children.empty())
particle->showerKinematics()->resetChildren(particle,children);
if(particle->spinInfo()) particle->spinInfo()->develop();
return true;
}
bool
QTildeShowerHandler::spaceLikeShower(tShowerParticlePtr particle, PPtr beam,
- ShowerInteraction::Type type) {
+ ShowerInteraction type) {
//using the pdf's associated with the ShowerHandler assures, that
//modified pdf's are used for the secondary interactions via
//CascadeHandler::resetPDFs(...)
tcPDFPtr pdf;
if(firstPDF().particle() == _beam)
pdf = firstPDF().pdf();
if(secondPDF().particle() == _beam)
pdf = secondPDF().pdf();
Energy freeze = pdfFreezingScale();
// don't do anything if not needed
if(_limitEmissions == 2 || hardOnly() ||
( _limitEmissions == 1 && _nis != 0 ) ||
( _limitEmissions == 4 && _nis + _nfs != 0 ) ) {
if(particle->spinInfo()) particle->spinInfo()->develop();
return false;
}
Branching bb;
// generate branching
while (true) {
bb=_splittingGenerator->chooseBackwardBranching(*particle,beam,
_initialenhance,
_beam,type,
pdf,freeze);
// return if no emission
if(!bb.kinematics) {
if(particle->spinInfo()) particle->spinInfo()->develop();
return false;
}
// if not vetoed break
if(!spaceLikeVetoed(bb,particle)) break;
// otherwise reset scale and continue
particle->vetoEmission(bb.type,bb.kinematics->scale());
if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr());
}
// assign the splitting function and shower kinematics
particle->showerKinematics(bb.kinematics);
if(bb.kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(bb.kinematics->pT());
// For the time being we are considering only 1->2 branching
// particles as in Sudakov form factor
tcPDPtr part[2]={bb.ids[0],bb.ids[2]};
// Now create the actual particles, make the otherChild a final state
// particle, while the newParent is not
ShowerParticlePtr newParent = new_ptr(ShowerParticle(part[0],false));
ShowerParticlePtr otherChild = new_ptr(ShowerParticle(part[1],true,true));
ShowerParticleVector theChildren;
theChildren.push_back(particle);
theChildren.push_back(otherChild);
//this updates the evolution scale
particle->showerKinematics()->
updateParent(newParent, theChildren,bb.type);
// update the history if needed
_currenttree->updateInitialStateShowerProduct(_progenitor,newParent);
_currenttree->addInitialStateBranching(particle,newParent,otherChild);
// for the reconstruction of kinematics, parent/child
// relationships are according to the branching process:
// now continue the shower
++_nis;
bool emitted = _limitEmissions==0 ?
spaceLikeShower(newParent,beam,type) : false;
if(newParent->spinInfo()) newParent->spinInfo()->develop();
// now reconstruct the momentum
if(!emitted) {
if(_intrinsic.find(_progenitor)==_intrinsic.end()) {
bb.kinematics->updateLast(newParent,ZERO,ZERO);
}
else {
pair<Energy,double> kt=_intrinsic[_progenitor];
bb.kinematics->updateLast(newParent,
kt.first*cos(kt.second),
kt.first*sin(kt.second));
}
}
particle->showerKinematics()->
updateChildren(newParent, theChildren,bb.type,_reconOpt>=4);
if(_limitEmissions!=0) {
if(particle->spinInfo()) particle->spinInfo()->develop();
return true;
}
// perform the shower of the final-state particle
timeLikeShower(otherChild,type,Branching(),true);
updateHistory(otherChild);
if(theChildren[1]->spinInfo()) theChildren[1]->spinInfo()->develop();
// return the emitted
if(particle->spinInfo()) particle->spinInfo()->develop();
return true;
}
void QTildeShowerHandler::showerDecay(ShowerTreePtr decay) {
// work out the type of event
currentTree()->xcombPtr(StdXCombPtr());
currentTree()->identifyEventType();
_decayme = HwDecayerBasePtr();
_hardme = HwMEBasePtr();
// find the decayer
// try the normal way if possible
tDMPtr dm = decay->incomingLines().begin()->first->original() ->decayMode();
if(!dm) dm = decay->incomingLines().begin()->first->copy() ->decayMode();
if(!dm) dm = decay->incomingLines().begin()->first->progenitor()->decayMode();
// otherwise make a string and look it up
if(!dm) {
string tag = decay->incomingLines().begin()->first->original()->dataPtr()->name()
+ "->";
OrderedParticles outgoing;
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
it=decay->outgoingLines().begin();it!=decay->outgoingLines().end();++it) {
if(abs(decay->incomingLines().begin()->first->original()->id()) == ParticleID::t &&
abs(it->first->original()->id())==ParticleID::Wplus &&
decay->treelinks().size() == 1) {
ShowerTreePtr Wtree = decay->treelinks().begin()->first;
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
it2=Wtree->outgoingLines().begin();it2!=Wtree->outgoingLines().end();++it2) {
outgoing.insert(it2->first->original()->dataPtr());
}
}
else {
outgoing.insert(it->first->original()->dataPtr());
}
}
for(OrderedParticles::const_iterator it=outgoing.begin(); it!=outgoing.end();++it) {
if(it!=outgoing.begin()) tag += ",";
tag +=(**it).name();
}
tag += ";";
dm = findDecayMode(tag);
}
if(dm) _decayme = dynamic_ptr_cast<HwDecayerBasePtr>(dm->decayer());
// set the ShowerTree to be showered
currentTree(decay);
decay->applyTransforms();
hardTree(HardTreePtr());
// generate the showering
doShowering(false,XCPtr());
// if no vetos
// force calculation of spin correlations
SpinPtr spInfo = decay->incomingLines().begin()->first->progenitor()->spinInfo();
if(spInfo) {
if(!spInfo->developed()) spInfo->needsUpdate();
spInfo->develop();
}
}
bool QTildeShowerHandler::spaceLikeDecayShower(tShowerParticlePtr particle,
const ShowerParticle::EvolutionScales & maxScales,
- Energy minmass,ShowerInteraction::Type type,
+ Energy minmass,ShowerInteraction type,
Branching fb) {
// too many tries
if(_nFSR>=_maxTryFSR) {
++_nFailedFSR;
// too many failed events
if(_nFailedFSR>=_maxFailFSR)
throw Exception() << "Too many events have failed due to too many shower emissions, in\n"
<< "QTildeShowerHandler::timeLikeShower(). Terminating run\n"
<< Exception::runerror;
throw Exception() << "Too many attempted emissions in QTildeShowerHandler::timeLikeShower()\n"
<< Exception::eventerror;
}
// generate the emission
ShowerParticleVector children;
int ntry=0;
// generate the emission
if(!fb.kinematics)
fb = selectSpaceLikeDecayBranching(particle,maxScales,minmass,type,
HardBranchingPtr());
// no emission, return
if(!fb.kinematics) return false;
Branching fc[2];
bool setupChildren = true;
while (ntry<50) {
if(particle->virtualMass()==ZERO)
particle->virtualMass(_progenitor->progenitor()->mass());
fc[0] = Branching();
fc[1] = Branching();
++ntry;
assert(fb.kinematics);
// has emitted
// Assign the shower kinematics to the emitting particle.
if(setupChildren) {
++_nFSR;
// Assign the shower kinematics to the emitting particle.
particle->showerKinematics(fb.kinematics);
if(fb.kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(fb.kinematics->pT());
// create the ShowerParticle objects for the two children
children = createTimeLikeChildren(particle,fb.ids);
// updateChildren the children
particle->showerKinematics()->
updateChildren(particle, children, fb.type,_reconOpt>=3);
setupChildren = false;
}
// select branchings for children
fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass,
type,HardBranchingPtr());
fc[1] = selectTimeLikeBranching (children[1],type,HardBranchingPtr());
// old default
if(_reconOpt==0) {
// shower the first particle
_currenttree->updateInitialStateShowerProduct(_progenitor,children[0]);
_currenttree->addInitialStateBranching(particle,children[0],children[1]);
if(fc[0].kinematics) spaceLikeDecayShower(children[0],maxScales,minmass,type,Branching());
// shower the second particle
if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],true);
updateHistory(children[1]);
// branching has happened
break;
}
// Herwig default
else if(_reconOpt==1) {
// shower the first particle
_currenttree->updateInitialStateShowerProduct(_progenitor,children[0]);
_currenttree->addInitialStateBranching(particle,children[0],children[1]);
if(fc[0].kinematics) spaceLikeDecayShower(children[0],maxScales,minmass,type,Branching());
// shower the second particle
if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],true);
updateHistory(children[1]);
// branching has happened
particle->showerKinematics()->updateParent(particle, children,fb.type);
// clean up the vetoed emission
if(particle->virtualMass()==ZERO) {
particle->showerKinematics(ShoKinPtr());
for(unsigned int ix=0;ix<children.size();++ix)
particle->abandonChild(children[ix]);
children.clear();
particle->vetoEmission(fb.type,fb.kinematics->scale());
// generate the new emission
fb = selectSpaceLikeDecayBranching(particle,maxScales,minmass,type,
HardBranchingPtr());
// no emission, return
if(!fb.kinematics) {
return false;
}
setupChildren = true;
continue;
}
else
break;
}
else if(_reconOpt>=2) {
// cut-off masses for the branching
const vector<Energy> & virtualMasses = fb.sudakov->virtualMasses(fb.ids);
// compute the masses of the children
Energy masses[3];
// space-like children
masses[1] = children[0]->virtualMass();
// time-like child
if(fc[1].kinematics) {
const vector<Energy> & vm = fc[1].sudakov->virtualMasses(fc[1].ids);
Energy2 q2 =
fc[1].kinematics->z()*(1.-fc[1].kinematics->z())*sqr(fc[1].kinematics->scale());
if(fc[1].ids[0]->id()!=ParticleID::g) q2 += sqr(vm[0]);
masses[2] = sqrt(q2);
}
else {
masses[2] = virtualMasses[2];
}
masses[0]=particle->virtualMass();
double z = fb.kinematics->z();
Energy2 pt2 = (1.-z)*(z*sqr(masses[0])-sqr(masses[1])-z/(1.-z)*sqr(masses[2]));
if(pt2>=ZERO) {
break;
}
else {
// reset the scales for the children
for(unsigned int ix=0;ix<2;++ix) {
if(fc[ix].kinematics)
children[ix]->vetoEmission(fc[ix].type,fc[ix].kinematics->scale());
else {
if(ix==0)
children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,Constants::MaxEnergy);
else
children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,ZERO);
}
}
children[0]->virtualMass(_progenitor->progenitor()->mass());
children[1]->virtualMass(ZERO);
}
}
};
if(_reconOpt>=2) {
// In the case of splittings which involves coloured particles,
// set properly the colour flow of the branching.
// update the history if needed
_currenttree->updateInitialStateShowerProduct(_progenitor,children[0]);
_currenttree->addInitialStateBranching(particle,children[0],children[1]);
// shower the first particle
if(fc[0].kinematics) spaceLikeDecayShower(children[0],maxScales,minmass,type,Branching());
// shower the second particle
if(fc[1].kinematics) timeLikeShower(children[1],type,fc[1],true);
updateHistory(children[1]);
// branching has happened
particle->showerKinematics()->updateParent(particle, children,fb.type);
}
// branching has happened
return true;
}
vector<ShowerProgenitorPtr> QTildeShowerHandler::setupShower(bool hard) {
RealEmissionProcessPtr real;
// generate hard me if needed
if(_hardEmission==1) {
real = hardMatrixElementCorrection(hard);
if(real&&!real->outgoing().empty()) setupMECorrection(real);
}
// generate POWHEG hard emission if needed
else if(_hardEmission==2)
hardestEmission(hard);
// set the initial colour partners
setEvolutionPartners(hard,interaction_,false);
// get the particles to be showered
vector<ShowerProgenitorPtr> particlesToShower =
currentTree()->extractProgenitors();
// return the answer
return particlesToShower;
}
-void QTildeShowerHandler::setEvolutionPartners(bool hard,ShowerInteraction::Type type,
+void QTildeShowerHandler::setEvolutionPartners(bool hard,ShowerInteraction type,
bool clear) {
// match the particles in the ShowerTree and hardTree
if(hardTree() && !hardTree()->connect(currentTree()))
throw Exception() << "Can't match trees in "
<< "QTildeShowerHandler::setEvolutionPartners()"
<< Exception::eventerror;
// extract the progenitors
vector<ShowerParticlePtr> particles =
currentTree()->extractProgenitorParticles();
// clear the partners if needed
if(clear) {
for(unsigned int ix=0;ix<particles.size();++ix) {
particles[ix]->partner(ShowerParticlePtr());
particles[ix]->clearPartners();
}
}
// sort out the colour partners
if(hardTree()) {
// find the partner
for(unsigned int ix=0;ix<particles.size();++ix) {
tShowerParticlePtr partner = hardTree()->particles()[particles[ix]]->branchingParticle()->partner();
if(!partner) continue;
for(map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
it=hardTree()->particles().begin();
it!=hardTree()->particles().end();++it) {
if(it->second->branchingParticle()==partner) {
particles[ix]->partner(it->first);
break;
}
}
if(!particles[ix]->partner())
throw Exception() << "Can't match partners in "
<< "QTildeShowerHandler::setEvolutionPartners()"
<< Exception::eventerror;
}
}
// Set the initial evolution scales
showerModel()->partnerFinder()->
setInitialEvolutionScales(particles,!hard,interaction_,!_hardtree);
if(hardTree() && _hardPOWHEG) {
bool tooHard=false;
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
eit=hardTree()->particles().end();
for(unsigned int ix=0;ix<particles.size();++ix) {
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
mit = hardTree()->particles().find(particles[ix]);
Energy hardScale(ZERO);
- ShowerPartnerType::Type type(ShowerPartnerType::Undefined);
+ ShowerPartnerType type(ShowerPartnerType::Undefined);
// final-state
if(particles[ix]->isFinalState()) {
if(mit!= eit && !mit->second->children().empty()) {
hardScale = mit->second->scale();
type = mit->second->type();
}
}
// initial-state
else {
if(mit!= eit && mit->second->parent()) {
hardScale = mit->second->parent()->scale();
type = mit->second->parent()->type();
}
}
if(type!=ShowerPartnerType::Undefined) {
if(type==ShowerPartnerType::QED) {
tooHard |= particles[ix]->scales().QED_noAO<hardScale;
}
else if(type==ShowerPartnerType::QCDColourLine) {
tooHard |= particles[ix]->scales().QCD_c_noAO<hardScale;
}
else if(type==ShowerPartnerType::QCDAntiColourLine) {
tooHard |= particles[ix]->scales().QCD_ac_noAO<hardScale;
}
}
}
if(tooHard) convertHardTree(hard,type);
}
}
void QTildeShowerHandler::updateHistory(tShowerParticlePtr particle) {
if(!particle->children().empty()) {
ShowerParticleVector theChildren;
for(unsigned int ix=0;ix<particle->children().size();++ix) {
ShowerParticlePtr part = dynamic_ptr_cast<ShowerParticlePtr>
(particle->children()[ix]);
theChildren.push_back(part);
}
// update the history if needed
if(particle==_currenttree->getFinalStateShowerProduct(_progenitor))
_currenttree->updateFinalStateShowerProduct(_progenitor,
particle,theChildren);
_currenttree->addFinalStateBranching(particle,theChildren);
for(unsigned int ix=0;ix<theChildren.size();++ix)
updateHistory(theChildren[ix]);
}
}
-bool QTildeShowerHandler::startTimeLikeShower(ShowerInteraction::Type type) {
+bool QTildeShowerHandler::startTimeLikeShower(ShowerInteraction type) {
_nFSR = 0;
// initialize basis vectors etc
+ if(!progenitor()->progenitor()->partner()) return false;
progenitor()->progenitor()->initializeFinalState();
- if(!progenitor()->progenitor()->partner()) return false;
if(hardTree()) {
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
eit=hardTree()->particles().end(),
mit = hardTree()->particles().find(progenitor()->progenitor());
if( mit != eit && !mit->second->children().empty() ) {
bool output=truncatedTimeLikeShower(progenitor()->progenitor(),
mit->second ,type,Branching(),true);
if(output) updateHistory(progenitor()->progenitor());
return output;
}
}
// do the shower
bool output = hardOnly() ? false :
timeLikeShower(progenitor()->progenitor() ,type,Branching(),true) ;
if(output) updateHistory(progenitor()->progenitor());
return output;
}
-bool QTildeShowerHandler::startSpaceLikeShower(PPtr parent, ShowerInteraction::Type type) {
+bool QTildeShowerHandler::startSpaceLikeShower(PPtr parent, ShowerInteraction type) {
// initialise the basis vectors
+ if(!progenitor()->progenitor()->partner()) return false;
progenitor()->progenitor()->initializeInitialState(parent);
- if(!progenitor()->progenitor()->partner()) return false;
if(hardTree()) {
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
eit =hardTree()->particles().end(),
mit = hardTree()->particles().find(progenitor()->progenitor());
if( mit != eit && mit->second->parent() ) {
return truncatedSpaceLikeShower( progenitor()->progenitor(),
parent, mit->second->parent(), type );
}
}
// perform the shower
return hardOnly() ? false :
spaceLikeShower(progenitor()->progenitor(),parent,type);
}
bool QTildeShowerHandler::
startSpaceLikeDecayShower(const ShowerParticle::EvolutionScales & maxScales,
- Energy minimumMass,ShowerInteraction::Type type) {
+ Energy minimumMass,ShowerInteraction type) {
_nFSR = 0;
// set up the particle basis vectors
+ if(!progenitor()->progenitor()->partner()) return false;
progenitor()->progenitor()->initializeDecay();
- if(!progenitor()->progenitor()->partner()) return false;
if(hardTree()) {
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
eit =hardTree()->particles().end(),
mit = hardTree()->particles().find(progenitor()->progenitor());
if( mit != eit && mit->second->parent() ) {
HardBranchingPtr branch=mit->second;
while(branch->parent()) branch=branch->parent();
return truncatedSpaceLikeDecayShower(progenitor()->progenitor(),maxScales,
minimumMass, branch ,type, Branching());
}
}
// perform the shower
return hardOnly() ? false :
spaceLikeDecayShower(progenitor()->progenitor(),maxScales,minimumMass,type,Branching());
}
bool QTildeShowerHandler::timeLikeVetoed(const Branching & fb,
ShowerParticlePtr particle) {
// work out type of interaction
- ShowerInteraction::Type type = convertInteraction(fb.type);
+ ShowerInteraction type = convertInteraction(fb.type);
// check whether emission was harder than largest pt of hard subprocess
if ( restrictPhasespace() && fb.kinematics->pT() > _progenitor->maxHardPt() )
return true;
// soft matrix element correction veto
if( softMEC()) {
if(_hardme && _hardme->hasMECorrection()) {
if(_hardme->softMatrixElementVeto(_progenitor,particle,fb))
return true;
}
else if(_decayme && _decayme->hasMECorrection()) {
if(_decayme->softMatrixElementVeto(_progenitor,particle,fb))
return true;
}
}
// veto on maximum pt
if(fb.kinematics->pT()>_progenitor->maximumpT(type)) return true;
// general vetos
if (fb.kinematics && !_vetoes.empty()) {
bool vetoed=false;
for (vector<ShowerVetoPtr>::iterator v = _vetoes.begin();
v != _vetoes.end(); ++v) {
bool test = (**v).vetoTimeLike(_progenitor,particle,fb);
switch((**v).vetoType()) {
case ShowerVeto::Emission:
vetoed |= test;
break;
case ShowerVeto::Shower:
if(test) throw VetoShower();
break;
case ShowerVeto::Event:
if(test) throw Veto();
break;
}
}
if(vetoed) return true;
}
if ( firstInteraction() &&
profileScales() ) {
double weight =
profileScales()->
hardScaleProfile(_progenitor->hardScale(),fb.kinematics->pT());
if ( UseRandom::rnd() > weight )
return true;
}
return false;
}
bool QTildeShowerHandler::spaceLikeVetoed(const Branching & bb,
ShowerParticlePtr particle) {
// work out type of interaction
- ShowerInteraction::Type type = convertInteraction(bb.type);
+ ShowerInteraction type = convertInteraction(bb.type);
// check whether emission was harder than largest pt of hard subprocess
if (restrictPhasespace() && bb.kinematics->pT() > _progenitor->maxHardPt())
return true;
// apply the soft correction
if( softMEC() && _hardme && _hardme->hasMECorrection() ) {
if(_hardme->softMatrixElementVeto(_progenitor,particle,bb))
return true;
}
// the more general vetos
// check vs max pt for the shower
if(bb.kinematics->pT()>_progenitor->maximumpT(type)) return true;
if (!_vetoes.empty()) {
bool vetoed=false;
for (vector<ShowerVetoPtr>::iterator v = _vetoes.begin();
v != _vetoes.end(); ++v) {
bool test = (**v).vetoSpaceLike(_progenitor,particle,bb);
switch ((**v).vetoType()) {
case ShowerVeto::Emission:
vetoed |= test;
break;
case ShowerVeto::Shower:
if(test) throw VetoShower();
break;
case ShowerVeto::Event:
if(test) throw Veto();
break;
}
}
if (vetoed) return true;
}
if ( firstInteraction() &&
profileScales() ) {
double weight =
profileScales()->
hardScaleProfile(_progenitor->hardScale(),bb.kinematics->pT());
if ( UseRandom::rnd() > weight )
return true;
}
return false;
}
bool QTildeShowerHandler::spaceLikeDecayVetoed( const Branching & fb,
ShowerParticlePtr particle) {
// work out type of interaction
- ShowerInteraction::Type type = convertInteraction(fb.type);
+ ShowerInteraction type = convertInteraction(fb.type);
// apply the soft correction
if( softMEC() && _decayme && _decayme->hasMECorrection() ) {
if(_decayme->softMatrixElementVeto(_progenitor,particle,fb))
return true;
}
// veto on hardest pt in the shower
if(fb.kinematics->pT()> _progenitor->maximumpT(type)) return true;
// general vetos
if (!_vetoes.empty()) {
bool vetoed=false;
for (vector<ShowerVetoPtr>::iterator v = _vetoes.begin();
v != _vetoes.end(); ++v) {
bool test = (**v).vetoSpaceLike(_progenitor,particle,fb);
switch((**v).vetoType()) {
case ShowerVeto::Emission:
vetoed |= test;
break;
case ShowerVeto::Shower:
if(test) throw VetoShower();
break;
case ShowerVeto::Event:
if(test) throw Veto();
break;
}
if (vetoed) return true;
}
}
return false;
}
void QTildeShowerHandler::hardestEmission(bool hard) {
HardTreePtr ISRTree;
// internal POWHEG in production or decay
if( (( _hardme && _hardme->hasPOWHEGCorrection()!=0 ) ||
( _decayme && _decayme->hasPOWHEGCorrection()!=0 ) ) ) {
RealEmissionProcessPtr real;
unsigned int type(0);
// production
if(_hardme) {
assert(hard);
real = _hardme->generateHardest( currentTree()->perturbativeProcess(),
interaction_);
type = _hardme->hasPOWHEGCorrection();
}
// decay
else {
assert(!hard);
real = _decayme->generateHardest( currentTree()->perturbativeProcess() );
type = _decayme->hasPOWHEGCorrection();
}
if(real) {
// set up ther hard tree
if(!real->outgoing().empty()) _hardtree = new_ptr(HardTree(real));
// set up the vetos
currentTree()->setVetoes(real->pT(),type);
}
// store initial state POWHEG radiation
if(_hardtree && _hardme && _hardme->hasPOWHEGCorrection()==1)
ISRTree = _hardtree;
}
else if (hard) {
// Get minimum pT cutoff used in shower approximation
Energy maxpt = 1.*GeV;
if ( currentTree()->showerApproximation() ) {
int colouredIn = 0;
int colouredOut = 0;
for( map< ShowerProgenitorPtr, tShowerParticlePtr >::iterator it
= currentTree()->outgoingLines().begin();
it != currentTree()->outgoingLines().end(); ++it ) {
if( it->second->coloured() ) ++colouredOut;
}
for( map< ShowerProgenitorPtr, ShowerParticlePtr >::iterator it
= currentTree()->incomingLines().begin();
it != currentTree()->incomingLines().end(); ++it ) {
if( it->second->coloured() ) ++colouredIn;
}
if ( currentTree()->showerApproximation()->ffPtCut() == currentTree()->showerApproximation()->fiPtCut() &&
currentTree()->showerApproximation()->ffPtCut() == currentTree()->showerApproximation()->iiPtCut() )
maxpt = currentTree()->showerApproximation()->ffPtCut();
else if ( colouredIn == 2 && colouredOut == 0 )
maxpt = currentTree()->showerApproximation()->iiPtCut();
else if ( colouredIn == 0 && colouredOut > 1 )
maxpt = currentTree()->showerApproximation()->ffPtCut();
else if ( colouredIn == 2 && colouredOut == 1 )
maxpt = min(currentTree()->showerApproximation()->iiPtCut(), currentTree()->showerApproximation()->fiPtCut());
else if ( colouredIn == 1 && colouredOut > 1 )
maxpt = min(currentTree()->showerApproximation()->ffPtCut(), currentTree()->showerApproximation()->fiPtCut());
else
maxpt = min(min(currentTree()->showerApproximation()->iiPtCut(), currentTree()->showerApproximation()->fiPtCut()),
currentTree()->showerApproximation()->ffPtCut());
}
// Generate hardtree from born and real emission subprocesses
_hardtree = generateCKKW(currentTree());
// Find transverse momentum of hardest emission
if (_hardtree){
for(set<HardBranchingPtr>::iterator it=_hardtree->branchings().begin();
it!=_hardtree->branchings().end();++it) {
if ((*it)->parent() && (*it)->status()==HardBranching::Incoming)
maxpt=(*it)->branchingParticle()->momentum().perp();
if ((*it)->children().size()==2 && (*it)->status()==HardBranching::Outgoing){
if ((*it)->branchingParticle()->id()!=21 &&
abs((*it)->branchingParticle()->id())>5 ){
if ((*it)->children()[0]->branchingParticle()->id()==21 ||
abs((*it)->children()[0]->branchingParticle()->id())<6)
maxpt=(*it)->children()[0]->branchingParticle()->momentum().perp();
else if ((*it)->children()[1]->branchingParticle()->id()==21 ||
abs((*it)->children()[1]->branchingParticle()->id())<6)
maxpt=(*it)->children()[1]->branchingParticle()->momentum().perp();
}
else {
if ( abs((*it)->branchingParticle()->id())<6){
if (abs((*it)->children()[0]->branchingParticle()->id())<6)
maxpt = (*it)->children()[1]->branchingParticle()->momentum().perp();
else
maxpt = (*it)->children()[0]->branchingParticle()->momentum().perp();
}
else maxpt = (*it)->children()[1]->branchingParticle()->momentum().perp();
}
}
}
}
// Hardest (pt) emission should be the first powheg emission.
maxpt=min(sqrt(lastXCombPtr()->lastShowerScale()),maxpt);
// set maximum pT for subsequent emissions from S events
if ( currentTree()->isPowhegSEvent() ) {
for( map< ShowerProgenitorPtr, tShowerParticlePtr >::iterator it
= currentTree()->outgoingLines().begin();
it != currentTree()->outgoingLines().end(); ++it ) {
if( ! it->second->coloured() ) continue;
it->first->maximumpT(maxpt, ShowerInteraction::QCD );
}
for( map< ShowerProgenitorPtr, ShowerParticlePtr >::iterator it
= currentTree()->incomingLines().begin();
it != currentTree()->incomingLines().end(); ++it ) {
if( ! it->second->coloured() ) continue;
it->first->maximumpT(maxpt, ShowerInteraction::QCD );
}
}
}
else
_hardtree = generateCKKW(currentTree());
// if hard me doesn't have a FSR powheg
// correction use decay powheg correction
if (_hardme && _hardme->hasPOWHEGCorrection()<2) {
addFSRUsingDecayPOWHEG(ISRTree);
}
// connect the trees
if(_hardtree) {
connectTrees(currentTree(),_hardtree,hard);
}
}
void QTildeShowerHandler::addFSRUsingDecayPOWHEG(HardTreePtr ISRTree) {
// check for intermediate colour singlet resonance
const ParticleVector inter = _hardme->subProcess()->intermediates();
if (inter.size()!=1 || inter[0]->momentum().m2()/GeV2 < 0 ||
inter[0]->dataPtr()->iColour()!=PDT::Colour0) {
return;
}
// ignore cases where outgoing particles are not coloured
map<ShowerProgenitorPtr, tShowerParticlePtr > out = currentTree()->outgoingLines();
if (out.size() != 2 ||
out. begin()->second->dataPtr()->iColour()==PDT::Colour0 ||
out.rbegin()->second->dataPtr()->iColour()==PDT::Colour0) {
return;
}
// look up decay mode
tDMPtr dm;
string tag;
string inParticle = inter[0]->dataPtr()->name() + "->";
vector<string> outParticles;
outParticles.push_back(out.begin ()->first->progenitor()->dataPtr()->name());
outParticles.push_back(out.rbegin()->first->progenitor()->dataPtr()->name());
for (int it=0; it<2; ++it){
tag = inParticle + outParticles[it] + "," + outParticles[(it+1)%2] + ";";
dm = generator()->findDecayMode(tag);
if(dm) break;
}
// get the decayer
HwDecayerBasePtr decayer;
if(dm) decayer = dynamic_ptr_cast<HwDecayerBasePtr>(dm->decayer());
// check if decayer has a FSR POWHEG correction
if (!decayer || decayer->hasPOWHEGCorrection()<2) {
return;
}
// generate the hardest emission
// create RealEmissionProcess
PPtr in = new_ptr(*inter[0]);
RealEmissionProcessPtr newProcess(new_ptr(RealEmissionProcess()));
newProcess->bornIncoming().push_back(in);
newProcess->bornOutgoing().push_back(out.begin ()->first->progenitor());
newProcess->bornOutgoing().push_back(out.rbegin()->first->progenitor());
// generate the FSR
newProcess = decayer->generateHardest(newProcess);
HardTreePtr FSRTree;
if(newProcess) {
// set up ther hard tree
if(!newProcess->outgoing().empty()) FSRTree = new_ptr(HardTree(newProcess));
// set up the vetos
currentTree()->setVetoes(newProcess->pT(),2);
}
if(!FSRTree) return;
// if there is no ISRTree make _hardtree from FSRTree
if (!ISRTree){
vector<HardBranchingPtr> inBranch,hardBranch;
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit =currentTree()->incomingLines().begin();
cit!=currentTree()->incomingLines().end();++cit ) {
inBranch.push_back(new_ptr(HardBranching(cit->second,SudakovPtr(),
HardBranchingPtr(),
HardBranching::Incoming)));
inBranch.back()->beam(cit->first->original()->parents()[0]);
hardBranch.push_back(inBranch.back());
}
if(inBranch[0]->branchingParticle()->dataPtr()->coloured()) {
inBranch[0]->colourPartner(inBranch[1]);
inBranch[1]->colourPartner(inBranch[0]);
}
for(set<HardBranchingPtr>::iterator it=FSRTree->branchings().begin();
it!=FSRTree->branchings().end();++it) {
if((**it).branchingParticle()->id()!=in->id())
hardBranch.push_back(*it);
}
hardBranch[2]->colourPartner(hardBranch[3]);
hardBranch[3]->colourPartner(hardBranch[2]);
HardTreePtr newTree = new_ptr(HardTree(hardBranch,inBranch,
ShowerInteraction::QCD));
_hardtree = newTree;
}
// Otherwise modify the ISRTree to include the emission in FSRTree
else {
vector<tShowerParticlePtr> FSROut, ISROut;
set<HardBranchingPtr>::iterator itFSR, itISR;
// get outgoing particles
for(itFSR =FSRTree->branchings().begin();
itFSR!=FSRTree->branchings().end();++itFSR){
if ((**itFSR).status()==HardBranching::Outgoing)
FSROut.push_back((*itFSR)->branchingParticle());
}
for(itISR =ISRTree->branchings().begin();
itISR!=ISRTree->branchings().end();++itISR){
if ((**itISR).status()==HardBranching::Outgoing)
ISROut.push_back((*itISR)->branchingParticle());
}
// find COM frame formed by outgoing particles
LorentzRotation eventFrameFSR, eventFrameISR;
eventFrameFSR = ((FSROut[0]->momentum()+FSROut[1]->momentum()).findBoostToCM());
eventFrameISR = ((ISROut[0]->momentum()+ISROut[1]->momentum()).findBoostToCM());
// find rotation between ISR and FSR frames
int j=0;
if (ISROut[0]->id()!=FSROut[0]->id()) j=1;
eventFrameISR.rotateZ( (eventFrameFSR*FSROut[0]->momentum()).phi()-
(eventFrameISR*ISROut[j]->momentum()).phi() );
eventFrameISR.rotateY( (eventFrameFSR*FSROut[0]->momentum()).theta()-
(eventFrameISR*ISROut[j]->momentum()).theta() );
eventFrameISR.invert();
for (itFSR=FSRTree->branchings().begin();
itFSR!=FSRTree->branchings().end();++itFSR){
if ((**itFSR).branchingParticle()->id()==in->id()) continue;
for (itISR =ISRTree->branchings().begin();
itISR!=ISRTree->branchings().end();++itISR){
if ((**itISR).status()==HardBranching::Incoming) continue;
if ((**itFSR).branchingParticle()->id()==
(**itISR).branchingParticle()->id()){
// rotate FSRTree particle to ISRTree event frame
(**itISR).branchingParticle()->setMomentum(eventFrameISR*
eventFrameFSR*
(**itFSR).branchingParticle()->momentum());
(**itISR).branchingParticle()->rescaleMass();
// add the children of the FSRTree particles to the ISRTree
if(!(**itFSR).children().empty()){
(**itISR).addChild((**itFSR).children()[0]);
(**itISR).addChild((**itFSR).children()[1]);
// rotate momenta to ISRTree event frame
(**itISR).children()[0]->branchingParticle()->setMomentum(eventFrameISR*
eventFrameFSR*
(**itFSR).children()[0]->branchingParticle()->momentum());
(**itISR).children()[1]->branchingParticle()->setMomentum(eventFrameISR*
eventFrameFSR*
(**itFSR).children()[1]->branchingParticle()->momentum());
}
}
}
}
_hardtree = ISRTree;
}
}
bool QTildeShowerHandler::truncatedTimeLikeShower(tShowerParticlePtr particle,
HardBranchingPtr branch,
- ShowerInteraction::Type type,
+ ShowerInteraction type,
Branching fb, bool first) {
// select a branching if we don't have one
if(!fb.kinematics)
fb = selectTimeLikeBranching(particle,type,branch);
// must be an emission, the forced one it not a truncated one
assert(fb.kinematics);
ShowerParticleVector children;
int ntry=0;
Branching fc[2];
bool setupChildren = true;
while (ntry<50) {
if(!fc[0].hard) fc[0] = Branching();
if(!fc[1].hard) fc[1] = Branching();
++ntry;
// Assign the shower kinematics to the emitting particle.
if(setupChildren) {
++_nFSR;
// Assign the shower kinematics to the emitting particle.
particle->showerKinematics(fb.kinematics);
if(fb.kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(fb.kinematics->pT());
// create the children
children = createTimeLikeChildren(particle,fb.ids);
// update the children
particle->showerKinematics()->
updateChildren(particle, children,fb.type,_reconOpt>=3);
setupChildren = false;
}
// select branchings for children
if(!fc[0].kinematics) {
// select branching for first particle
if(!fb.hard && fb.iout ==1 )
fc[0] = selectTimeLikeBranching(children[0],type,branch);
else if(fb.hard && !branch->children()[0]->children().empty() )
fc[0] = selectTimeLikeBranching(children[0],type,branch->children()[0]);
else
fc[0] = selectTimeLikeBranching(children[0],type,HardBranchingPtr());
}
// select branching for the second particle
if(!fc[1].kinematics) {
// select branching for first particle
if(!fb.hard && fb.iout ==2 )
fc[1] = selectTimeLikeBranching(children[1],type,branch);
else if(fb.hard && !branch->children()[1]->children().empty() )
fc[1] = selectTimeLikeBranching(children[1],type,branch->children()[1]);
else
fc[1] = selectTimeLikeBranching(children[1],type,HardBranchingPtr());
}
// old default
if(_reconOpt==0 || (_reconOpt==1 && fb.hard) ) {
// shower the first particle
if(fc[0].kinematics) {
// the parent has truncated emission and following line
if(!fb.hard && fb.iout == 1)
truncatedTimeLikeShower(children[0],branch,type,fc[0],false);
// hard emission and subsquent hard emissions
else if(fb.hard && !branch->children()[0]->children().empty() )
truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false);
// normal shower
else
timeLikeShower(children[0],type,fc[0],false);
}
if(children[0]->spinInfo()) children[0]->spinInfo()->develop();
// shower the second particle
if(fc[1].kinematics) {
// the parent has truncated emission and following line
if(!fb.hard && fb.iout == 2)
truncatedTimeLikeShower(children[1],branch,type,fc[1],false);
// hard emission and subsquent hard emissions
else if(fb.hard && !branch->children()[1]->children().empty() )
truncatedTimeLikeShower(children[1],branch->children()[1],type,fc[1],false);
else
timeLikeShower(children[1],type,fc[1],false);
}
if(children[1]->spinInfo()) children[1]->spinInfo()->develop();
// branching has happened
particle->showerKinematics()->updateParent(particle, children,fb.type);
break;
}
// H7 default
else if(_reconOpt==1) {
// shower the first particle
if(fc[0].kinematics) {
// the parent has truncated emission and following line
if(!fb.hard && fb.iout == 1)
truncatedTimeLikeShower(children[0],branch,type,fc[0],false);
else
timeLikeShower(children[0],type,fc[0],false);
}
if(children[0]->spinInfo()) children[0]->spinInfo()->develop();
// shower the second particle
if(fc[1].kinematics) {
// the parent has truncated emission and following line
if(!fb.hard && fb.iout == 2)
truncatedTimeLikeShower(children[1],branch,type,fc[1],false);
else
timeLikeShower(children[1],type,fc[1],false);
}
if(children[1]->spinInfo()) children[1]->spinInfo()->develop();
// branching has happened
particle->showerKinematics()->updateParent(particle, children,fb.type);
// clean up the vetoed emission
if(particle->virtualMass()==ZERO) {
particle->showerKinematics(ShoKinPtr());
for(unsigned int ix=0;ix<children.size();++ix)
particle->abandonChild(children[ix]);
children.clear();
if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr());
particle->vetoEmission(fb.type,fb.kinematics->scale());
// generate the new emission
fb = selectTimeLikeBranching(particle,type,branch);
// must be at least hard emission
assert(fb.kinematics);
setupChildren = true;
continue;
}
else
break;
}
else if(_reconOpt>=2) {
// cut-off masses for the branching
const vector<Energy> & virtualMasses = fb.sudakov->virtualMasses(fb.ids);
// compute the masses of the children
Energy masses[3];
for(unsigned int ix=0;ix<2;++ix) {
if(fc[ix].kinematics) {
const vector<Energy> & vm = fc[ix].sudakov->virtualMasses(fc[ix].ids);
Energy2 q2 =
fc[ix].kinematics->z()*(1.-fc[ix].kinematics->z())*sqr(fc[ix].kinematics->scale());
if(fc[ix].ids[0]->id()!=ParticleID::g) q2 += sqr(vm[0]);
masses[ix+1] = sqrt(q2);
}
else {
masses[ix+1] = virtualMasses[ix+1];
}
}
masses[0] = fb.ids[0]->id()!=ParticleID::g ? virtualMasses[0] : ZERO;
double z = fb.kinematics->z();
Energy2 pt2 = z*(1.-z)*(z*(1.-z)*sqr(fb.kinematics->scale()) + sqr(masses[0]))
- sqr(masses[1])*(1.-z) - sqr(masses[2])*z;
if(pt2>=ZERO) {
break;
}
// if only the hard emission have to accept it
else if ((fc[0].hard && !fc[1].kinematics) ||
(fc[1].hard && !fc[0].kinematics) ) {
break;
}
else {
// reset the scales for the children
for(unsigned int ix=0;ix<2;++ix) {
if(fc[ix].hard) continue;
if(fc[ix].kinematics && ! fc[ix].hard )
children[ix]->vetoEmission(fc[ix].type,fc[ix].kinematics->scale());
else
children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,ZERO);
children[ix]->virtualMass(ZERO);
}
}
}
};
if(_reconOpt>=2) {
// shower the first particle
if(fc[0].kinematics) {
// the parent has truncated emission and following line
if(!fb.hard && fb.iout == 1)
truncatedTimeLikeShower(children[0],branch,type,fc[0],false);
// hard emission and subsquent hard emissions
else if(fb.hard && !branch->children()[0]->children().empty() )
truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false);
// normal shower
else
timeLikeShower(children[0],type,fc[0],false);
}
if(children[0]->spinInfo()) children[0]->spinInfo()->develop();
// shower the second particle
if(fc[1].kinematics) {
// the parent has truncated emission and following line
if(!fb.hard && fb.iout == 2)
truncatedTimeLikeShower(children[1],branch,type,fc[1],false);
// hard emission and subsquent hard emissions
else if(fb.hard && !branch->children()[1]->children().empty() )
truncatedTimeLikeShower(children[1],branch->children()[1],type,fc[1],false);
else
timeLikeShower(children[1],type,fc[1],false);
}
if(children[1]->spinInfo()) children[1]->spinInfo()->develop();
// branching has happened
particle->showerKinematics()->updateParent(particle, children,fb.type);
}
if(first&&!children.empty())
particle->showerKinematics()->resetChildren(particle,children);
if(particle->spinInfo()) particle->spinInfo()->develop();
return true;
}
bool QTildeShowerHandler::truncatedSpaceLikeShower(tShowerParticlePtr particle, PPtr beam,
HardBranchingPtr branch,
- ShowerInteraction::Type type) {
+ ShowerInteraction type) {
tcPDFPtr pdf;
if(firstPDF().particle() == beamParticle())
pdf = firstPDF().pdf();
if(secondPDF().particle() == beamParticle())
pdf = secondPDF().pdf();
Energy freeze = pdfFreezingScale();
Branching bb;
// parameters of the force branching
double z(0.);
HardBranchingPtr timelike;
for( unsigned int ix = 0; ix < branch->children().size(); ++ix ) {
if( branch->children()[ix]->status() ==HardBranching::Outgoing) {
timelike = branch->children()[ix];
}
if( branch->children()[ix]->status() ==HardBranching::Incoming )
z = branch->children()[ix]->z();
}
// generate truncated branching
tcPDPtr part[2];
if(z>=0.&&z<=1.) {
while (true) {
if( !isTruncatedShowerON() || hardOnly() ) break;
bb = splittingGenerator()->chooseBackwardBranching( *particle,
beam, 1., beamParticle(),
type , pdf,freeze);
if( !bb.kinematics || bb.kinematics->scale() < branch->scale() ) {
bb = Branching();
break;
}
// particles as in Sudakov form factor
part[0] = bb.ids[0];
part[1] = bb.ids[2];
double zsplit = bb.kinematics->z();
// apply the vetos for the truncated shower
// if doesn't carry most of momentum
- ShowerInteraction::Type type2 = convertInteraction(bb.type);
+ ShowerInteraction type2 = convertInteraction(bb.type);
if(type2==branch->sudakov()->interactionType() &&
zsplit < 0.5) {
particle->vetoEmission(bb.type,bb.kinematics->scale());
continue;
}
// others
if( part[0]->id() != particle->id() || // if particle changes type
bb.kinematics->pT() > progenitor()->maximumpT(type2) || // pt veto
bb.kinematics->scale() < branch->scale()) { // angular ordering veto
particle->vetoEmission(bb.type,bb.kinematics->scale());
continue;
}
// and those from the base class
if(spaceLikeVetoed(bb,particle)) {
particle->vetoEmission(bb.type,bb.kinematics->scale());
continue;
}
break;
}
}
if( !bb.kinematics ) {
//do the hard emission
ShoKinPtr kinematics =
branch->sudakov()->createInitialStateBranching( branch->scale(), z, branch->phi(),
branch->children()[0]->pT() );
// assign the splitting function and shower kinematics
particle->showerKinematics( kinematics );
if(kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(kinematics->pT());
// For the time being we are considering only 1->2 branching
// Now create the actual particles, make the otherChild a final state
// particle, while the newParent is not
ShowerParticlePtr newParent =
new_ptr( ShowerParticle( branch->branchingParticle()->dataPtr(), false ) );
ShowerParticlePtr otherChild =
new_ptr( ShowerParticle( timelike->branchingParticle()->dataPtr(),
true, true ) );
ShowerParticleVector theChildren;
theChildren.push_back( particle );
theChildren.push_back( otherChild );
particle->showerKinematics()->
updateParent( newParent, theChildren, branch->type());
// update the history if needed
currentTree()->updateInitialStateShowerProduct( progenitor(), newParent );
currentTree()->addInitialStateBranching( particle, newParent, otherChild );
// for the reconstruction of kinematics, parent/child
// relationships are according to the branching process:
// now continue the shower
bool emitted=false;
if(!hardOnly()) {
if( branch->parent() ) {
emitted = truncatedSpaceLikeShower( newParent, beam, branch->parent() , type);
}
else {
emitted = spaceLikeShower( newParent, beam , type);
}
}
if( !emitted ) {
if( intrinsicpT().find( progenitor() ) == intrinsicpT().end() ) {
kinematics->updateLast( newParent, ZERO, ZERO );
}
else {
pair<Energy,double> kt = intrinsicpT()[progenitor()];
kinematics->updateLast( newParent,
kt.first*cos( kt.second ),
kt.first*sin( kt.second ) );
}
}
particle->showerKinematics()->
updateChildren( newParent, theChildren,bb.type,false);
if(hardOnly()) return true;
// perform the shower of the final-state particle
if( timelike->children().empty() ) {
timeLikeShower( otherChild , type,Branching(),true);
}
else {
truncatedTimeLikeShower( otherChild, timelike , type,Branching(), true);
}
updateHistory(otherChild);
// return the emitted
return true;
}
// assign the splitting function and shower kinematics
particle->showerKinematics( bb.kinematics );
if(bb.kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(bb.kinematics->pT());
// For the time being we are considering only 1->2 branching
// Now create the actual particles, make the otherChild a final state
// particle, while the newParent is not
ShowerParticlePtr newParent = new_ptr( ShowerParticle( part[0], false ) );
ShowerParticlePtr otherChild = new_ptr( ShowerParticle( part[1], true, true ) );
ShowerParticleVector theChildren;
theChildren.push_back( particle );
theChildren.push_back( otherChild );
particle->showerKinematics()->
updateParent( newParent, theChildren, bb.type);
// update the history if needed
currentTree()->updateInitialStateShowerProduct( progenitor(), newParent );
currentTree()->addInitialStateBranching( particle, newParent, otherChild );
// for the reconstruction of kinematics, parent/child
// relationships are according to the branching process:
// now continue the shower
bool emitted = truncatedSpaceLikeShower( newParent, beam, branch,type);
// now reconstruct the momentum
if( !emitted ) {
if( intrinsicpT().find( progenitor() ) == intrinsicpT().end() ) {
bb.kinematics->updateLast( newParent, ZERO, ZERO );
}
else {
pair<Energy,double> kt = intrinsicpT()[ progenitor() ];
bb.kinematics->updateLast( newParent,
kt.first*cos( kt.second ),
kt.first*sin( kt.second ) );
}
}
particle->showerKinematics()->
updateChildren( newParent, theChildren, bb.type,false);
// perform the shower of the final-state particle
timeLikeShower( otherChild , type,Branching(),true);
updateHistory(otherChild);
// return the emitted
return true;
}
bool QTildeShowerHandler::
truncatedSpaceLikeDecayShower(tShowerParticlePtr particle,
const ShowerParticle::EvolutionScales & maxScales,
Energy minmass, HardBranchingPtr branch,
- ShowerInteraction::Type type, Branching fb) {
+ ShowerInteraction type, Branching fb) {
// select a branching if we don't have one
if(!fb.kinematics)
fb = selectSpaceLikeDecayBranching(particle,maxScales,minmass,type,branch);
// must be an emission, the forced one it not a truncated one
assert(fb.kinematics);
ShowerParticleVector children;
int ntry=0;
Branching fc[2];
bool setupChildren = true;
while (ntry<50) {
if(!fc[0].hard) fc[0] = Branching();
if(!fc[1].hard) fc[1] = Branching();
++ntry;
if(setupChildren) {
++_nFSR;
// Assign the shower kinematics to the emitting particle.
particle->showerKinematics(fb.kinematics);
if(fb.kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(fb.kinematics->pT());
// create the ShowerParticle objects for the two children
children = createTimeLikeChildren(particle,fb.ids);
// updateChildren the children
particle->showerKinematics()->
updateChildren(particle, children, fb.type,_reconOpt>=3);
setupChildren = false;
}
// select branchings for children
if(!fc[0].kinematics) {
if(children[0]->id()==particle->id()) {
// select branching for first particle
if(!fb.hard)
fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass,type,branch);
else if(fb.hard && ! branch->children()[0]->children().empty() )
fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass,type,
branch->children()[0]);
else
fc[0] = selectSpaceLikeDecayBranching(children[0],maxScales,minmass,type,
HardBranchingPtr());
}
else {
// select branching for first particle
if(fb.hard && !branch->children()[0]->children().empty() )
fc[0] = selectTimeLikeBranching(children[0],type,branch->children()[0]);
else
fc[0] = selectTimeLikeBranching(children[0],type,HardBranchingPtr());
}
}
// select branching for the second particle
if(!fc[1].kinematics) {
if(children[1]->id()==particle->id()) {
// select branching for first particle
if(!fb.hard)
fc[1] = selectSpaceLikeDecayBranching(children[1],maxScales,minmass,type,branch);
else if(fb.hard && ! branch->children()[1]->children().empty() )
fc[1] = selectSpaceLikeDecayBranching(children[1],maxScales,minmass,type,
branch->children()[1]);
else
fc[1] = selectSpaceLikeDecayBranching(children[1],maxScales,minmass,type,
HardBranchingPtr());
}
else {
if(fb.hard && !branch->children()[1]->children().empty() )
fc[1] = selectTimeLikeBranching(children[1],type,branch->children()[1]);
else
fc[1] = selectTimeLikeBranching(children[1],type,HardBranchingPtr());
}
}
// old default
if(_reconOpt==0 || (_reconOpt==1 && fb.hard) ) {
// update the history if needed
currentTree()->updateInitialStateShowerProduct(progenitor(),children[0]);
currentTree()->addInitialStateBranching(particle,children[0],children[1]);
// shower the first particle
if(fc[0].kinematics) {
if(children[0]->id()==particle->id()) {
if(!fb.hard)
truncatedSpaceLikeDecayShower( children[0],maxScales,minmass,
branch,type,fc[0]);
else if(fb.hard && ! branch->children()[0]->children().empty() )
truncatedSpaceLikeDecayShower( children[0],maxScales,minmass,
branch->children()[0],type,fc[0]);
else
spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[0]);
}
else {
if(fb.hard && !branch->children()[0]->children().empty() )
truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false);
// normal shower
else
timeLikeShower(children[0],type,fc[0],false);
}
}
// shower the second particle
if(fc[1].kinematics) {
if(children[0]->id()==particle->id()) {
if(!fb.hard)
truncatedSpaceLikeDecayShower( children[0],maxScales,minmass,
branch,type,fc[1]);
else if(fb.hard && ! branch->children()[0]->children().empty() )
truncatedSpaceLikeDecayShower( children[0],maxScales,minmass,
branch->children()[0],type,fc[1]);
else
spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[1]);
}
else {
if(fb.hard && !branch->children()[0]->children().empty() )
truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[1],false);
// normal shower
else
timeLikeShower(children[0],type,fc[1],false);
}
}
updateHistory(children[1]);
// branching has happened
break;
}
// H7 default
else if(_reconOpt==1) {
// update the history if needed
currentTree()->updateInitialStateShowerProduct(progenitor(),children[0]);
currentTree()->addInitialStateBranching(particle,children[0],children[1]);
// shower the first particle
if(fc[0].kinematics) {
if(children[0]->id()==particle->id()) {
if(!fb.hard)
truncatedSpaceLikeDecayShower( children[0],maxScales,minmass,
branch,type,fc[0]);
else if(fb.hard && ! branch->children()[0]->children().empty() )
truncatedSpaceLikeDecayShower( children[0],maxScales,minmass,
branch->children()[0],type,fc[0]);
else
spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[0]);
}
else {
if(fb.hard && !branch->children()[0]->children().empty() )
truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false);
// normal shower
else
timeLikeShower(children[0],type,fc[0],false);
}
}
// shower the second particle
if(fc[1].kinematics) {
if(children[0]->id()==particle->id()) {
if(!fb.hard)
truncatedSpaceLikeDecayShower( children[0],maxScales,minmass,
branch,type,fc[1]);
else if(fb.hard && ! branch->children()[0]->children().empty() )
truncatedSpaceLikeDecayShower( children[0],maxScales,minmass,
branch->children()[0],type,fc[1]);
else
spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[1]);
}
else {
if(fb.hard && !branch->children()[0]->children().empty() )
truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[1],false);
// normal shower
else
timeLikeShower(children[0],type,fc[1],false);
}
}
// clean up the vetoed emission
if(particle->virtualMass()==ZERO) {
particle->showerKinematics(ShoKinPtr());
for(unsigned int ix=0;ix<children.size();++ix)
particle->abandonChild(children[ix]);
children.clear();
particle->vetoEmission(fb.type,fb.kinematics->scale());
// generate the new emission
fb = selectSpaceLikeDecayBranching(particle,maxScales,minmass,type,branch);
// must be at least hard emission
assert(fb.kinematics);
setupChildren = true;
continue;
}
else {
updateHistory(children[1]);
break;
}
}
else if(_reconOpt>=2) {
// cut-off masses for the branching
const vector<Energy> & virtualMasses = fb.sudakov->virtualMasses(fb.ids);
// compute the masses of the children
Energy masses[3];
// space-like children
masses[1] = children[0]->virtualMass();
// time-like child
if(fc[1].kinematics) {
const vector<Energy> & vm = fc[1].sudakov->virtualMasses(fc[1].ids);
Energy2 q2 =
fc[1].kinematics->z()*(1.-fc[1].kinematics->z())*sqr(fc[1].kinematics->scale());
if(fc[1].ids[0]->id()!=ParticleID::g) q2 += sqr(vm[0]);
masses[2] = sqrt(q2);
}
else {
masses[2] = virtualMasses[2];
}
masses[0]=particle->virtualMass();
double z = fb.kinematics->z();
Energy2 pt2 = (1.-z)*(z*sqr(masses[0])-sqr(masses[1])-z/(1.-z)*sqr(masses[2]));
if(pt2>=ZERO) {
break;
}
else {
// reset the scales for the children
for(unsigned int ix=0;ix<2;++ix) {
if(fc[ix].kinematics)
children[ix]->vetoEmission(fc[ix].type,fc[ix].kinematics->scale());
else {
if(ix==0)
children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,Constants::MaxEnergy);
else
children[ix]->vetoEmission(ShowerPartnerType::QCDColourLine,ZERO);
}
}
children[0]->virtualMass(_progenitor->progenitor()->mass());
children[1]->virtualMass(ZERO);
}
}
};
if(_reconOpt>=2) {
// update the history if needed
currentTree()->updateInitialStateShowerProduct(progenitor(),children[0]);
currentTree()->addInitialStateBranching(particle,children[0],children[1]);
// shower the first particle
if(fc[0].kinematics) {
if(children[0]->id()==particle->id()) {
if(!fb.hard)
truncatedSpaceLikeDecayShower( children[0],maxScales,minmass,
branch,type,fc[0]);
else if(fb.hard && ! branch->children()[0]->children().empty() )
truncatedSpaceLikeDecayShower( children[0],maxScales,minmass,
branch->children()[0],type,fc[0]);
else
spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[0]);
}
else {
if(fb.hard && !branch->children()[0]->children().empty() )
truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[0],false);
// normal shower
else
timeLikeShower(children[0],type,fc[0],false);
}
}
// shower the second particle
if(fc[1].kinematics) {
if(children[0]->id()==particle->id()) {
if(!fb.hard)
truncatedSpaceLikeDecayShower( children[0],maxScales,minmass,
branch,type,fc[1]);
else if(fb.hard && ! branch->children()[0]->children().empty() )
truncatedSpaceLikeDecayShower( children[0],maxScales,minmass,
branch->children()[0],type,fc[1]);
else
spaceLikeDecayShower( children[0],maxScales,minmass,type,fc[1]);
}
else {
if(fb.hard && !branch->children()[0]->children().empty() )
truncatedTimeLikeShower(children[0],branch->children()[0],type,fc[1],false);
// normal shower
else
timeLikeShower(children[0],type,fc[1],false);
}
}
updateHistory(children[1]);
}
return true;
}
void QTildeShowerHandler::connectTrees(ShowerTreePtr showerTree,
HardTreePtr hardTree, bool hard ) {
ShowerParticleVector particles;
// find the Sudakovs
for(set<HardBranchingPtr>::iterator cit=hardTree->branchings().begin();
cit!=hardTree->branchings().end();++cit) {
// Sudakovs for ISR
if((**cit).parent()&&(**cit).status()==HardBranching::Incoming) {
++_nis;
vector<long> br(3);
br[0] = (**cit).parent()->branchingParticle()->id();
br[1] = (**cit). branchingParticle()->id();
br[2] = (**cit).parent()->children()[0]==*cit ?
(**cit).parent()->children()[1]->branchingParticle()->id() :
(**cit).parent()->children()[0]->branchingParticle()->id();
BranchingList branchings = splittingGenerator()->initialStateBranchings();
if(br[1]<0&&br[0]==br[1]) {
br[0] = abs(br[0]);
br[1] = abs(br[1]);
}
else if(br[1]<0) {
br[1] = -br[1];
br[2] = -br[2];
}
long index = abs(br[1]);
SudakovPtr sudakov;
for(BranchingList::const_iterator cjt = branchings.lower_bound(index);
cjt != branchings.upper_bound(index); ++cjt ) {
IdList ids = cjt->second.particles;
if(ids[0]->id()==br[0]&&ids[1]->id()==br[1]&&ids[2]->id()==br[2]) {
sudakov=cjt->second.sudakov;
break;
}
}
if(!sudakov) throw Exception() << "Can't find Sudakov for the hard emission in "
<< "QTildeShowerHandler::connectTrees() for ISR"
<< Exception::runerror;
(**cit).parent()->sudakov(sudakov);
}
// Sudakovs for FSR
else if(!(**cit).children().empty()) {
++_nfs;
vector<long> br(3);
br[0] = (**cit) .branchingParticle()->id();
br[1] = (**cit).children()[0]->branchingParticle()->id();
br[2] = (**cit).children()[1]->branchingParticle()->id();
BranchingList branchings = splittingGenerator()->finalStateBranchings();
if(br[0]<0) {
br[0] = abs(br[0]);
br[1] = abs(br[1]);
br[2] = abs(br[2]);
}
long index = br[0];
SudakovPtr sudakov;
for(BranchingList::const_iterator cjt = branchings.lower_bound(index);
cjt != branchings.upper_bound(index); ++cjt ) {
IdList ids = cjt->second.particles;
if(ids[0]->id()==br[0]&&ids[1]->id()==br[1]&&ids[2]->id()==br[2]) {
sudakov=cjt->second.sudakov;
break;
}
}
if(!sudakov) {
throw Exception() << "Can't find Sudakov for the hard emission in "
<< "QTildeShowerHandler::connectTrees()"
<< Exception::runerror;
}
(**cit).sudakov(sudakov);
}
}
// calculate the evolution scale
for(set<HardBranchingPtr>::iterator cit=hardTree->branchings().begin();
cit!=hardTree->branchings().end();++cit) {
particles.push_back((*cit)->branchingParticle());
}
showerModel()->partnerFinder()->
setInitialEvolutionScales(particles,!hard,interaction_,true);
hardTree->partnersSet(true);
// inverse reconstruction
if(hard) {
showerModel()->kinematicsReconstructor()->
deconstructHardJets(hardTree,interaction_);
}
else
showerModel()->kinematicsReconstructor()->
deconstructDecayJets(hardTree,interaction_);
// now reset the momenta of the showering particles
vector<ShowerProgenitorPtr> particlesToShower=showerTree->extractProgenitors();
// match them
map<ShowerProgenitorPtr,HardBranchingPtr> partners;
for(set<HardBranchingPtr>::const_iterator bit=hardTree->branchings().begin();
bit!=hardTree->branchings().end();++bit) {
Energy2 dmin( 1e30*GeV2 );
ShowerProgenitorPtr partner;
for(vector<ShowerProgenitorPtr>::const_iterator pit=particlesToShower.begin();
pit!=particlesToShower.end();++pit) {
if(partners.find(*pit)!=partners.end()) continue;
if( (**bit).branchingParticle()->id() != (**pit).progenitor()->id() ) continue;
if( (**bit).branchingParticle()->isFinalState() !=
(**pit).progenitor()->isFinalState() ) continue;
if( (**pit).progenitor()->isFinalState() ) {
Energy2 dtest =
sqr( (**pit).progenitor()->momentum().x() - (**bit).showerMomentum().x() ) +
sqr( (**pit).progenitor()->momentum().y() - (**bit).showerMomentum().y() ) +
sqr( (**pit).progenitor()->momentum().z() - (**bit).showerMomentum().z() ) +
sqr( (**pit).progenitor()->momentum().t() - (**bit).showerMomentum().t() );
// add mass difference for identical particles (e.g. Z0 Z0 production)
dtest += 1e10*sqr((**pit).progenitor()->momentum().m()-(**bit).showerMomentum().m());
if( dtest < dmin ) {
partner = *pit;
dmin = dtest;
}
}
else {
// ensure directions are right
if((**pit).progenitor()->momentum().z()/(**bit).showerMomentum().z()>ZERO) {
partner = *pit;
break;
}
}
}
if(!partner) throw Exception() << "Failed to match shower and hard trees in QTildeShowerHandler::hardestEmission"
<< Exception::eventerror;
partners[partner] = *bit;
}
for(vector<ShowerProgenitorPtr>::const_iterator pit=particlesToShower.begin();
pit!=particlesToShower.end();++pit) {
HardBranchingPtr partner = partners[*pit];
if((**pit).progenitor()->dataPtr()->stable()) {
(**pit).progenitor()->set5Momentum(partner->showerMomentum());
(**pit).copy()->set5Momentum(partner->showerMomentum());
}
else {
Lorentz5Momentum oldMomentum = (**pit).progenitor()->momentum();
Lorentz5Momentum newMomentum = partner->showerMomentum();
LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass());
(**pit).progenitor()->transform(boost);
(**pit).copy() ->transform(boost);
boost = LorentzRotation(-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass());
(**pit).progenitor()->transform(boost);
(**pit).copy() ->transform(boost);
}
}
// correction boosts for daughter trees
for(map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator
tit = showerTree->treelinks().begin();
tit != showerTree->treelinks().end();++tit) {
ShowerTreePtr decayTree = tit->first;
map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit = decayTree->incomingLines().begin();
// reset the momentum of the decay particle
Lorentz5Momentum oldMomentum = cit->first->progenitor()->momentum();
Lorentz5Momentum newMomentum = tit->second.second->momentum();
LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass());
decayTree->transform(boost,true);
boost = LorentzRotation(-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass());
decayTree->transform(boost,true);
}
}
void QTildeShowerHandler::doShowering(bool hard,XCPtr xcomb) {
// zero number of emissions
_nis = _nfs = 0;
// if MC@NLO H event and limited emissions
// indicate both final and initial state emission
if ( currentTree()->isMCatNLOHEvent() && _limitEmissions != 0 ) {
_nis = _nfs = 1;
}
// extract particles to shower
vector<ShowerProgenitorPtr> particlesToShower(setupShower(hard));
// check if we should shower
bool colCharge = false;
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
if(particlesToShower[ix]->progenitor()->dataPtr()->coloured() ||
particlesToShower[ix]->progenitor()->dataPtr()->charged()) {
colCharge = true;
break;
}
}
if(!colCharge) {
_currenttree->hasShowered(true);
return;
}
// setup the maximum scales for the shower
if (restrictPhasespace()) setupMaximumScales(particlesToShower,xcomb);
// set the hard scales for the profiles
setupHardScales(particlesToShower,xcomb);
// specific stuff for hard processes and decays
Energy minmass(ZERO), mIn(ZERO);
// hard process generate the intrinsic p_T once and for all
if(hard) {
generateIntrinsicpT(particlesToShower);
}
// decay compute the minimum mass of the final-state
else {
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
if(particlesToShower[ix]->progenitor()->isFinalState()) {
if(particlesToShower[ix]->progenitor()->dataPtr()->stable())
minmass += particlesToShower[ix]->progenitor()->dataPtr()->constituentMass();
else
minmass += particlesToShower[ix]->progenitor()->mass();
}
else {
mIn = particlesToShower[ix]->progenitor()->mass();
}
}
// throw exception if decay can't happen
if ( minmass > mIn ) {
throw Exception() << "QTildeShowerHandler.cc: Mass of decaying particle is "
<< "below constituent masses of decay products."
<< Exception::eventerror;
}
}
// setup for reweighted
bool reWeighting = _reWeight && hard && ShowerHandler::currentHandler()->firstInteraction();
double eventWeight=0.;
unsigned int nTryReWeight(0);
// create random particle vector (only need to do once)
vector<ShowerProgenitorPtr> tmp;
unsigned int nColouredIncoming = 0;
while(particlesToShower.size()>0){
unsigned int xx=UseRandom::irnd(particlesToShower.size());
tmp.push_back(particlesToShower[xx]);
particlesToShower.erase(particlesToShower.begin()+xx);
}
particlesToShower=tmp;
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
if(!particlesToShower[ix]->progenitor()->isFinalState() &&
particlesToShower[ix]->progenitor()->coloured()) ++nColouredIncoming;
}
bool switchRecon = hard && nColouredIncoming !=1;
// main shower loop
unsigned int ntry(0);
bool reconstructed = false;
do {
// clear results of last attempt if needed
if(ntry!=0) {
currentTree()->clear();
setEvolutionPartners(hard,interaction_,true);
_nis = _nfs = 0;
// if MC@NLO H event and limited emissions
// indicate both final and initial state emission
if ( currentTree()->isMCatNLOHEvent() && _limitEmissions != 0 ) {
_nis = _nfs = 1;
}
for(unsigned int ix=0; ix<particlesToShower.size();++ix) {
SpinPtr spin = particlesToShower[ix]->progenitor()->spinInfo();
if(spin && spin->decayVertex() &&
dynamic_ptr_cast<tcSVertexPtr>(spin->decayVertex())) {
spin->decayVertex(VertexPtr());
}
}
}
// loop over particles
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
// extract the progenitor
progenitor(particlesToShower[ix]);
// final-state radiation
if(progenitor()->progenitor()->isFinalState()) {
if(!doFSR()) continue;
// perform shower
progenitor()->hasEmitted(startTimeLikeShower(interaction_));
}
// initial-state radiation
else {
if(!doISR()) continue;
// hard process
if(hard) {
// get the PDF
setBeamParticle(_progenitor->beam());
assert(beamParticle());
// perform the shower
// set the beam particle
tPPtr beamparticle=progenitor()->original();
if(!beamparticle->parents().empty())
beamparticle=beamparticle->parents()[0];
// generate the shower
progenitor()->hasEmitted(startSpaceLikeShower(beamparticle,
interaction_));
}
// decay
else {
// skip colour and electrically neutral particles
if(!progenitor()->progenitor()->dataPtr()->coloured() &&
!progenitor()->progenitor()->dataPtr()->charged()) {
progenitor()->hasEmitted(false);
continue;
}
// perform shower
// set the scales correctly. The current scale is the maximum scale for
// emission not the starting scale
ShowerParticle::EvolutionScales maxScales(progenitor()->progenitor()->scales());
progenitor()->progenitor()->scales() = ShowerParticle::EvolutionScales();
if(progenitor()->progenitor()->dataPtr()->charged()) {
progenitor()->progenitor()->scales().QED = progenitor()->progenitor()->mass();
progenitor()->progenitor()->scales().QED_noAO = progenitor()->progenitor()->mass();
}
if(progenitor()->progenitor()->hasColour()) {
progenitor()->progenitor()->scales().QCD_c = progenitor()->progenitor()->mass();
progenitor()->progenitor()->scales().QCD_c_noAO = progenitor()->progenitor()->mass();
}
if(progenitor()->progenitor()->hasAntiColour()) {
progenitor()->progenitor()->scales().QCD_ac = progenitor()->progenitor()->mass();
progenitor()->progenitor()->scales().QCD_ac_noAO = progenitor()->progenitor()->mass();
}
// perform the shower
progenitor()->hasEmitted(startSpaceLikeDecayShower(maxScales,minmass,
interaction_));
}
}
}
// do the kinematic reconstruction, checking if it worked
reconstructed = hard ?
showerModel()->kinematicsReconstructor()->
reconstructHardJets (currentTree(),intrinsicpT(),interaction_,
switchRecon && ntry>maximumTries()/2) :
showerModel()->kinematicsReconstructor()->
reconstructDecayJets(currentTree(),interaction_);
if(!reconstructed) continue;
// apply vetos on the full shower
for(vector<FullShowerVetoPtr>::const_iterator it=_fullShowerVetoes.begin();
it!=_fullShowerVetoes.end();++it) {
int veto = (**it).applyVeto(currentTree());
if(veto<0) continue;
// veto the shower
if(veto==0) {
reconstructed = false;
break;
}
// veto the shower and reweight
else if(veto==1) {
reconstructed = false;
break;
}
// veto the event
else if(veto==2) {
throw Veto();
}
}
if(reWeighting) {
if(reconstructed) eventWeight += 1.;
reconstructed=false;
++nTryReWeight;
if(nTryReWeight==_nReWeight) {
reWeighting = false;
if(eventWeight==0.) throw Veto();
}
}
}
while(!reconstructed&&maximumTries()>++ntry);
// check if failed to generate the shower
if(ntry==maximumTries()) {
if(hard)
throw ShowerHandler::ShowerTriesVeto(ntry);
else
throw Exception() << "Failed to generate the shower after "
<< ntry << " attempts in QTildeShowerHandler::showerDecay()"
<< Exception::eventerror;
}
// handle the weights and apply any reweighting required
if(nTryReWeight>0) {
tStdEHPtr seh = dynamic_ptr_cast<tStdEHPtr>(generator()->currentEventHandler());
static bool first = true;
if(seh) {
seh->reweight(eventWeight/double(nTryReWeight));
}
else if(first) {
generator()->log() << "Reweighting the shower only works with internal Herwig7 processes"
<< "Presumably you are showering Les Houches Events. These will not be"
<< "reweighted\n";
first = false;
}
}
// tree has now showered
_currenttree->hasShowered(true);
hardTree(HardTreePtr());
}
-void QTildeShowerHandler:: convertHardTree(bool hard,ShowerInteraction::Type type) {
+void QTildeShowerHandler:: convertHardTree(bool hard,ShowerInteraction type) {
map<ColinePtr,ColinePtr> cmap;
// incoming particles
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit=currentTree()->incomingLines().begin();cit!=currentTree()->incomingLines().end();++cit) {
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
mit = hardTree()->particles().find(cit->first->progenitor());
// put the colour lines in the map
ShowerParticlePtr oldParticle = cit->first->progenitor();
ShowerParticlePtr newParticle = mit->second->branchingParticle();
ColinePtr cLine = oldParticle-> colourLine();
ColinePtr aLine = oldParticle->antiColourLine();
if(newParticle->colourLine() &&
cmap.find(newParticle-> colourLine())==cmap.end())
cmap[newParticle-> colourLine()] = cLine;
if(newParticle->antiColourLine() &&
cmap.find(newParticle->antiColourLine())==cmap.end())
cmap[newParticle->antiColourLine()] = aLine;
// check whether or not particle emits
bool emission = mit->second->parent();
if(emission) {
if(newParticle->colourLine()) {
ColinePtr ctemp = newParticle-> colourLine();
ctemp->removeColoured(newParticle);
}
if(newParticle->antiColourLine()) {
ColinePtr ctemp = newParticle->antiColourLine();
ctemp->removeAntiColoured(newParticle);
}
newParticle = mit->second->parent()->branchingParticle();
}
// get the new colour lines
ColinePtr newCLine,newALine;
// sort out colour lines
if(newParticle->colourLine()) {
ColinePtr ctemp = newParticle-> colourLine();
ctemp->removeColoured(newParticle);
if(cmap.find(ctemp)!=cmap.end()) {
newCLine = cmap[ctemp];
}
else {
newCLine = new_ptr(ColourLine());
cmap[ctemp] = newCLine;
}
}
// and anticolour lines
if(newParticle->antiColourLine()) {
ColinePtr ctemp = newParticle->antiColourLine();
ctemp->removeAntiColoured(newParticle);
if(cmap.find(ctemp)!=cmap.end()) {
newALine = cmap[ctemp];
}
else {
newALine = new_ptr(ColourLine());
cmap[ctemp] = newALine;
}
}
// remove colour lines from old particle
if(aLine) {
aLine->removeAntiColoured(cit->first->copy());
aLine->removeAntiColoured(cit->first->progenitor());
}
if(cLine) {
cLine->removeColoured(cit->first->copy());
cLine->removeColoured(cit->first->progenitor());
}
// add particle to colour lines
if(newCLine) newCLine->addColoured (newParticle);
if(newALine) newALine->addAntiColoured(newParticle);
// insert new particles
cit->first->copy(newParticle);
ShowerParticlePtr sp(new_ptr(ShowerParticle(*newParticle,1,false)));
cit->first->progenitor(sp);
currentTree()->incomingLines()[cit->first]=sp;
cit->first->perturbative(!emission);
// and the emitted particle if needed
if(emission) {
ShowerParticlePtr newOut = mit->second->parent()->children()[1]->branchingParticle();
if(newOut->colourLine()) {
ColinePtr ctemp = newOut-> colourLine();
ctemp->removeColoured(newOut);
assert(cmap.find(ctemp)!=cmap.end());
cmap[ctemp]->addColoured (newOut);
}
if(newOut->antiColourLine()) {
ColinePtr ctemp = newOut->antiColourLine();
ctemp->removeAntiColoured(newOut);
assert(cmap.find(ctemp)!=cmap.end());
cmap[ctemp]->addAntiColoured(newOut);
}
ShowerParticlePtr sout=new_ptr(ShowerParticle(*newOut,1,true));
ShowerProgenitorPtr out=new_ptr(ShowerProgenitor(cit->first->original(),newOut,sout));
out->perturbative(false);
currentTree()->outgoingLines().insert(make_pair(out,sout));
}
if(hard) {
// sort out the value of x
if(mit->second->beam()->momentum().z()>ZERO) {
sp->x(newParticle->momentum(). plus()/mit->second->beam()->momentum(). plus());
}
else {
sp->x(newParticle->momentum().minus()/mit->second->beam()->momentum().minus());
}
}
}
// outgoing particles
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
cit=currentTree()->outgoingLines().begin();cit!=currentTree()->outgoingLines().end();++cit) {
map<tShowerTreePtr,pair<tShowerProgenitorPtr,
tShowerParticlePtr> >::const_iterator tit;
for(tit = currentTree()->treelinks().begin();
tit != currentTree()->treelinks().end();++tit) {
if(tit->second.first && tit->second.second==cit->first->progenitor())
break;
}
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
mit = hardTree()->particles().find(cit->first->progenitor());
if(mit==hardTree()->particles().end()) continue;
// put the colour lines in the map
ShowerParticlePtr oldParticle = cit->first->progenitor();
ShowerParticlePtr newParticle = mit->second->branchingParticle();
ShowerParticlePtr newOut;
ColinePtr cLine = oldParticle-> colourLine();
ColinePtr aLine = oldParticle->antiColourLine();
if(newParticle->colourLine() &&
cmap.find(newParticle-> colourLine())==cmap.end())
cmap[newParticle-> colourLine()] = cLine;
if(newParticle->antiColourLine() &&
cmap.find(newParticle->antiColourLine())==cmap.end())
cmap[newParticle->antiColourLine()] = aLine;
// check whether or not particle emits
bool emission = !mit->second->children().empty();
if(emission) {
if(newParticle->colourLine()) {
ColinePtr ctemp = newParticle-> colourLine();
ctemp->removeColoured(newParticle);
}
if(newParticle->antiColourLine()) {
ColinePtr ctemp = newParticle->antiColourLine();
ctemp->removeAntiColoured(newParticle);
}
newParticle = mit->second->children()[0]->branchingParticle();
newOut = mit->second->children()[1]->branchingParticle();
if(newParticle->id()!=oldParticle->id()&&newParticle->id()==newOut->id())
swap(newParticle,newOut);
}
// get the new colour lines
ColinePtr newCLine,newALine;
// sort out colour lines
if(newParticle->colourLine()) {
ColinePtr ctemp = newParticle-> colourLine();
ctemp->removeColoured(newParticle);
if(cmap.find(ctemp)!=cmap.end()) {
newCLine = cmap[ctemp];
}
else {
newCLine = new_ptr(ColourLine());
cmap[ctemp] = newCLine;
}
}
// and anticolour lines
if(newParticle->antiColourLine()) {
ColinePtr ctemp = newParticle->antiColourLine();
ctemp->removeAntiColoured(newParticle);
if(cmap.find(ctemp)!=cmap.end()) {
newALine = cmap[ctemp];
}
else {
newALine = new_ptr(ColourLine());
cmap[ctemp] = newALine;
}
}
// remove colour lines from old particle
if(aLine) {
aLine->removeAntiColoured(cit->first->copy());
aLine->removeAntiColoured(cit->first->progenitor());
}
if(cLine) {
cLine->removeColoured(cit->first->copy());
cLine->removeColoured(cit->first->progenitor());
}
// special for unstable particles
if(newParticle->id()==oldParticle->id() &&
(tit!=currentTree()->treelinks().end()||!oldParticle->dataPtr()->stable())) {
Lorentz5Momentum oldMomentum = oldParticle->momentum();
Lorentz5Momentum newMomentum = newParticle->momentum();
LorentzRotation boost( oldMomentum.findBoostToCM(),oldMomentum.e()/oldMomentum.mass());
if(tit!=currentTree()->treelinks().end()) tit->first->transform(boost,false);
oldParticle->transform(boost);
boost = LorentzRotation(-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass());
oldParticle->transform(boost);
if(tit!=currentTree()->treelinks().end()) tit->first->transform(boost,false);
newParticle=oldParticle;
}
// add particle to colour lines
if(newCLine) newCLine->addColoured (newParticle);
if(newALine) newALine->addAntiColoured(newParticle);
// insert new particles
cit->first->copy(newParticle);
ShowerParticlePtr sp(new_ptr(ShowerParticle(*newParticle,1,true)));
cit->first->progenitor(sp);
currentTree()->outgoingLines()[cit->first]=sp;
cit->first->perturbative(!emission);
// and the emitted particle if needed
if(emission) {
if(newOut->colourLine()) {
ColinePtr ctemp = newOut-> colourLine();
ctemp->removeColoured(newOut);
assert(cmap.find(ctemp)!=cmap.end());
cmap[ctemp]->addColoured (newOut);
}
if(newOut->antiColourLine()) {
ColinePtr ctemp = newOut->antiColourLine();
ctemp->removeAntiColoured(newOut);
assert(cmap.find(ctemp)!=cmap.end());
cmap[ctemp]->addAntiColoured(newOut);
}
ShowerParticlePtr sout=new_ptr(ShowerParticle(*newOut,1,true));
ShowerProgenitorPtr out=new_ptr(ShowerProgenitor(cit->first->original(),newOut,sout));
out->perturbative(false);
currentTree()->outgoingLines().insert(make_pair(out,sout));
}
// update any decay products
if(tit!=currentTree()->treelinks().end())
currentTree()->updateLink(tit->first,make_pair(cit->first,sp));
}
// reset the tree
currentTree()->resetShowerProducts();
// reextract the particles and set the colour partners
vector<ShowerParticlePtr> particles =
currentTree()->extractProgenitorParticles();
// clear the partners
for(unsigned int ix=0;ix<particles.size();++ix) {
particles[ix]->partner(ShowerParticlePtr());
particles[ix]->clearPartners();
}
// clear the tree
hardTree(HardTreePtr());
// Set the initial evolution scales
showerModel()->partnerFinder()->
setInitialEvolutionScales(particles,!hard,type,!_hardtree);
}
Branching QTildeShowerHandler::selectTimeLikeBranching(tShowerParticlePtr particle,
- ShowerInteraction::Type type,
+ ShowerInteraction type,
HardBranchingPtr branch) {
Branching fb;
unsigned int iout=0;
while (true) {
// break if doing truncated shower and no truncated shower needed
if(branch && (!isTruncatedShowerON()||hardOnly())) break;
fb=_splittingGenerator->chooseForwardBranching(*particle,_finalenhance,type);
// no emission break
if(!fb.kinematics) break;
// special for truncated shower
if(branch) {
// check haven't evolved too far
if(fb.kinematics->scale() < branch->scale()) {
fb=Branching();
break;
}
// find the truncated line
iout=0;
if(fb.ids[1]->id()!=fb.ids[2]->id()) {
if(fb.ids[1]->id()==particle->id()) iout=1;
else if (fb.ids[2]->id()==particle->id()) iout=2;
}
else if(fb.ids[1]->id()==particle->id()) {
if(fb.kinematics->z()>0.5) iout=1;
else iout=2;
}
// apply the vetos for the truncated shower
// no flavour changing branchings
if(iout==0) {
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
double zsplit = iout==1 ? fb.kinematics->z() : 1-fb.kinematics->z();
// only if same interaction for forced branching
- ShowerInteraction::Type type2 = convertInteraction(fb.type);
+ ShowerInteraction type2 = convertInteraction(fb.type);
// and evolution
if(type2==branch->sudakov()->interactionType()) {
if(zsplit < 0.5 || // hardest line veto
fb.kinematics->scale()*zsplit < branch->scale() ) { // angular ordering veto
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
}
// pt veto
if(fb.kinematics->pT() > progenitor()->maximumpT(type2)) {
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
}
// standard vetos for all emissions
if(timeLikeVetoed(fb,particle)) {
particle->vetoEmission(fb.type,fb.kinematics->scale());
if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr());
continue;
}
// special for already decayed particles
// don't allow flavour changing branchings
bool vetoDecay = false;
for(map<tShowerTreePtr,pair<tShowerProgenitorPtr,
tShowerParticlePtr> >::const_iterator tit = currentTree()->treelinks().begin();
tit != currentTree()->treelinks().end();++tit) {
if(tit->second.first == progenitor()) {
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
it = currentTree()->outgoingLines().find(progenitor());
if(it!=currentTree()->outgoingLines().end() && particle == it->second &&
fb.ids[0]!=fb.ids[1] && fb.ids[1]!=fb.ids[2]) {
vetoDecay = true;
break;
}
}
}
if(vetoDecay) {
particle->vetoEmission(fb.type,fb.kinematics->scale());
if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr());
continue;
}
break;
}
// normal case
if(!branch) {
if(fb.kinematics) fb.hard = false;
return fb;
}
// truncated emission
if(fb.kinematics) {
fb.hard = false;
fb.iout = iout;
return fb;
}
// otherwise need to return the hard emission
// construct the kinematics for the hard emission
ShoKinPtr showerKin=
branch->sudakov()->createFinalStateBranching(branch->scale(),
branch->children()[0]->z(),
branch->phi(),
branch->children()[0]->pT());
IdList idlist(3);
idlist[0] = particle->dataPtr();
idlist[1] = branch->children()[0]->branchingParticle()->dataPtr();
idlist[2] = branch->children()[1]->branchingParticle()->dataPtr();
fb = Branching( showerKin, idlist, branch->sudakov(),branch->type() );
fb.hard = true;
fb.iout=0;
// return it
return fb;
}
Branching QTildeShowerHandler::selectSpaceLikeDecayBranching(tShowerParticlePtr particle,
const ShowerParticle::EvolutionScales & maxScales,
- Energy minmass,ShowerInteraction::Type type,
+ Energy minmass,ShowerInteraction type,
HardBranchingPtr branch) {
Branching fb;
unsigned int iout=0;
while (true) {
// break if doing truncated shower and no truncated shower needed
if(branch && (!isTruncatedShowerON()||hardOnly())) break;
// select branching
fb=_splittingGenerator->chooseDecayBranching(*particle,maxScales,minmass,
_initialenhance,type);
// return if no radiation
if(!fb.kinematics) break;
// special for truncated shower
if(branch) {
// check haven't evolved too far
if(fb.kinematics->scale() < branch->scale()) {
fb=Branching();
break;
}
// find the truncated line
iout=0;
if(fb.ids[1]->id()!=fb.ids[2]->id()) {
if(fb.ids[1]->id()==particle->id()) iout=1;
else if (fb.ids[2]->id()==particle->id()) iout=2;
}
else if(fb.ids[1]->id()==particle->id()) {
if(fb.kinematics->z()>0.5) iout=1;
else iout=2;
}
// apply the vetos for the truncated shower
// no flavour changing branchings
if(iout==0) {
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
- ShowerInteraction::Type type2 = convertInteraction(fb.type);
+ ShowerInteraction type2 = convertInteraction(fb.type);
double zsplit = iout==1 ? fb.kinematics->z() : 1-fb.kinematics->z();
if(type2==branch->sudakov()->interactionType()) {
if(zsplit < 0.5 || // hardest line veto
fb.kinematics->scale()*zsplit < branch->scale() ) { // angular ordering veto
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
}
// pt veto
if(fb.kinematics->pT() > progenitor()->maximumpT(type2)) {
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
}
// if not vetoed break
if(spaceLikeDecayVetoed(fb,particle)) {
// otherwise reset scale and continue
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
break;
}
// normal case
if(!branch) {
if(fb.kinematics) fb.hard = false;
return fb;
}
// truncated emission
if(fb.kinematics) {
fb.hard = false;
fb.iout = iout;
return fb;
}
// otherwise need to return the hard emission
// construct the kinematics for the hard emission
ShoKinPtr showerKin=
branch->sudakov()->createDecayBranching(branch->scale(),
branch->children()[0]->z(),
branch->phi(),
branch->children()[0]->pT());
IdList idlist(3);
idlist[0] = particle->dataPtr();
idlist[1] = branch->children()[0]->branchingParticle()->dataPtr();
idlist[2] = branch->children()[1]->branchingParticle()->dataPtr();
// create the branching
fb = Branching( showerKin, idlist, branch->sudakov(),ShowerPartnerType::QCDColourLine );
fb.hard=true;
fb.iout=0;
// return it
return fb;
}
void QTildeShowerHandler::checkFlags() {
string error = "Inconsistent hard emission set-up in QTildeShowerHandler::showerHardProcess(). ";
if ( ( currentTree()->isMCatNLOSEvent() || currentTree()->isMCatNLOHEvent() ) ) {
if (_hardEmission ==2 )
throw Exception() << error
<< "Cannot generate POWHEG matching with MC@NLO shower "
<< "approximation. Add 'set QTildeShowerHandler:HardEmission 0' to input file."
<< Exception::runerror;
if ( canHandleMatchboxTrunc() )
throw Exception() << error
<< "Cannot use truncated qtilde shower with MC@NLO shower "
<< "approximation. Set LHCGenerator:EventHandler"
<< ":CascadeHandler to '/Herwig/Shower/ShowerHandler' or "
<< "'/Herwig/Shower/Dipole/DipoleShowerHandler'."
<< Exception::runerror;
}
else if ( ((currentTree()->isPowhegSEvent() || currentTree()->isPowhegHEvent()) ) &&
_hardEmission != 2){
if ( canHandleMatchboxTrunc())
throw Exception() << error
<< "Unmatched events requested for POWHEG shower "
<< "approximation. Set QTildeShowerHandler:HardEmission to "
<< "'POWHEG'."
<< Exception::runerror;
else if (_hardEmissionWarn) {
_hardEmissionWarn = false;
_hardEmission=2;
throw Exception() << error
<< "Unmatched events requested for POWHEG shower "
<< "approximation. Changing QTildeShowerHandler:HardEmission from "
<< _hardEmission << " to 2"
<< Exception::warning;
}
}
if ( currentTree()->isPowhegSEvent() || currentTree()->isPowhegHEvent()) {
if (currentTree()->showerApproximation()->needsTruncatedShower() &&
!canHandleMatchboxTrunc() )
throw Exception() << error
<< "Current shower handler cannot generate truncated shower. "
<< "Set Generator:EventHandler:CascadeHandler to "
<< "'/Herwig/Shower/PowhegShowerHandler'."
<< Exception::runerror;
}
else if ( currentTree()->truncatedShower() && _missingTruncWarn) {
_missingTruncWarn=false;
throw Exception() << "Warning: POWHEG shower approximation used without "
<< "truncated shower. Set Generator:EventHandler:"
<< "CascadeHandler to '/Herwig/Shower/PowhegShowerHandler' and "
<< "'MEMatching:TruncatedShower Yes'."
<< Exception::warning;
}
// else if ( !dipme && _hardEmissionMode > 1 &&
// firstInteraction())
// throw Exception() << error
// << "POWHEG matching requested for LO events. Include "
// << "'set Factory:ShowerApproximation MEMatching' in input file."
// << Exception::runerror;
}
tPPair QTildeShowerHandler::remakeRemnant(tPPair oldp){
// get the parton extractor
PartonExtractor & pex = *lastExtractor();
// get the new partons
tPPair newp = make_pair(findFirstParton(oldp.first ),
findFirstParton(oldp.second));
// if the same do nothing
if(newp == oldp) return oldp;
// Creates the new remnants and returns the new PartonBinInstances
// ATTENTION Broken here for very strange configuration
PBIPair newbins = pex.newRemnants(oldp, newp, newStep());
newStep()->addIntermediate(newp.first);
newStep()->addIntermediate(newp.second);
// return the new partons
return newp;
}
PPtr QTildeShowerHandler::findFirstParton(tPPtr seed) const{
if(seed->parents().empty()) return seed;
tPPtr parent = seed->parents()[0];
//if no parent there this is a loose end which will
//be connected to the remnant soon.
if(!parent || parent == incomingBeams().first ||
parent == incomingBeams().second ) return seed;
else return findFirstParton(parent);
}
void QTildeShowerHandler::decay(ShowerTreePtr tree, ShowerDecayMap & decay) {
// must be one incoming particle
assert(tree->incomingLines().size()==1);
// apply any transforms
tree->applyTransforms();
// if already decayed return
if(!tree->outgoingLines().empty()) return;
// now we need to replace the particle with a new copy after the shower
// find particle after the shower
map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator
tit = tree->parent()->treelinks().find(tree);
assert(tit!=tree->parent()->treelinks().end());
ShowerParticlePtr newparent=tit->second.second;
PerturbativeProcessPtr newProcess = new_ptr(PerturbativeProcess());
newProcess->incoming().push_back(make_pair(newparent,PerturbativeProcessPtr()));
DecayProcessMap decayMap;
ShowerHandler::decay(newProcess,decayMap);
ShowerTree::constructTrees(tree,decay,newProcess,decayMap);
}
namespace {
ShowerProgenitorPtr
findFinalStateLine(ShowerTreePtr tree, long id, Lorentz5Momentum momentum) {
map<ShowerProgenitorPtr,tShowerParticlePtr>::iterator partner;
Energy2 dmin(1e30*GeV2);
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::iterator
cit =tree->outgoingLines().begin(); cit!=tree->outgoingLines().end(); ++cit) {
if(cit->second->id()!=id) continue;
Energy2 test =
sqr(cit->second->momentum().x()-momentum.x())+
sqr(cit->second->momentum().y()-momentum.y())+
sqr(cit->second->momentum().z()-momentum.z())+
sqr(cit->second->momentum().t()-momentum.t());
if(test<dmin) {
dmin = test;
partner = cit;
}
}
return partner->first;
}
ShowerProgenitorPtr
findInitialStateLine(ShowerTreePtr tree, long id, Lorentz5Momentum momentum) {
map<ShowerProgenitorPtr,ShowerParticlePtr>::iterator partner;
Energy2 dmin(1e30*GeV2);
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::iterator
cit =tree->incomingLines().begin(); cit!=tree->incomingLines().end(); ++cit) {
if(cit->second->id()!=id) continue;
Energy2 test =
sqr(cit->second->momentum().x()-momentum.x())+
sqr(cit->second->momentum().y()-momentum.y())+
sqr(cit->second->momentum().z()-momentum.z())+
sqr(cit->second->momentum().t()-momentum.t());
if(test<dmin) {
dmin = test;
partner = cit;
}
}
return partner->first;
}
void fixSpectatorColours(PPtr newSpect,ShowerProgenitorPtr oldSpect,
ColinePair & cline,ColinePair & aline, bool reconnect) {
cline.first = oldSpect->progenitor()->colourLine();
cline.second = newSpect->colourLine();
aline.first = oldSpect->progenitor()->antiColourLine();
aline.second = newSpect->antiColourLine();
if(!reconnect) return;
if(cline.first) {
cline.first ->removeColoured(oldSpect->copy());
cline.first ->removeColoured(oldSpect->progenitor());
cline.second->removeColoured(newSpect);
cline.first ->addColoured(newSpect);
}
if(aline.first) {
aline.first ->removeAntiColoured(oldSpect->copy());
aline.first ->removeAntiColoured(oldSpect->progenitor());
aline.second->removeAntiColoured(newSpect);
aline.first ->addAntiColoured(newSpect);
}
}
void fixInitialStateEmitter(ShowerTreePtr tree, PPtr newEmit,PPtr emitted, ShowerProgenitorPtr emitter,
ColinePair cline,ColinePair aline,double x) {
// sort out the colours
if(emitted->dataPtr()->iColour()==PDT::Colour8) {
// emitter
if(cline.first && cline.first == emitter->progenitor()->antiColourLine() &&
cline.second !=newEmit->antiColourLine()) {
// sort out not radiating line
ColinePtr col = emitter->progenitor()->colourLine();
if(col) {
col->removeColoured(emitter->copy());
col->removeColoured(emitter->progenitor());
newEmit->colourLine()->removeColoured(newEmit);
col->addColoured(newEmit);
}
}
else if(aline.first && aline.first == emitter->progenitor()->colourLine() &&
aline.second !=newEmit->colourLine()) {
// sort out not radiating line
ColinePtr anti = emitter->progenitor()->antiColourLine();
if(anti) {
anti->removeAntiColoured(emitter->copy());
anti->removeAntiColoured(emitter->progenitor());
newEmit->colourLine()->removeAntiColoured(newEmit);
anti->addAntiColoured(newEmit);
}
}
else
assert(false);
// emitted
if(cline.first && cline.second==emitted->colourLine()) {
cline.second->removeColoured(emitted);
cline.first->addColoured(emitted);
}
else if(aline.first && aline.second==emitted->antiColourLine()) {
aline.second->removeAntiColoured(emitted);
aline.first->addAntiColoured(emitted);
}
else
assert(false);
}
else {
if(emitter->progenitor()->antiColourLine() ) {
ColinePtr col = emitter->progenitor()->antiColourLine();
col->removeAntiColoured(emitter->copy());
col->removeAntiColoured(emitter->progenitor());
if(newEmit->antiColourLine()) {
newEmit->antiColourLine()->removeAntiColoured(newEmit);
col->addAntiColoured(newEmit);
}
else if (emitted->colourLine()) {
emitted->colourLine()->removeColoured(emitted);
col->addColoured(emitted);
}
else
assert(false);
}
if(emitter->progenitor()->colourLine() ) {
ColinePtr col = emitter->progenitor()->colourLine();
col->removeColoured(emitter->copy());
col->removeColoured(emitter->progenitor());
if(newEmit->colourLine()) {
newEmit->colourLine()->removeColoured(newEmit);
col->addColoured(newEmit);
}
else if (emitted->antiColourLine()) {
emitted->antiColourLine()->removeAntiColoured(emitted);
col->addAntiColoured(emitted);
}
else
assert(false);
}
}
// update the emitter
emitter->copy(newEmit);
ShowerParticlePtr sp = new_ptr(ShowerParticle(*newEmit,1,false));
sp->x(x);
emitter->progenitor(sp);
tree->incomingLines()[emitter]=sp;
emitter->perturbative(false);
// add emitted
sp=new_ptr(ShowerParticle(*emitted,1,true));
ShowerProgenitorPtr gluon=new_ptr(ShowerProgenitor(emitter->original(),emitted,sp));
gluon->perturbative(false);
tree->outgoingLines().insert(make_pair(gluon,sp));
}
void fixFinalStateEmitter(ShowerTreePtr tree, PPtr newEmit,PPtr emitted, ShowerProgenitorPtr emitter,
ColinePair cline,ColinePair aline) {
map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator tit;
// special case if decayed
for(tit = tree->treelinks().begin(); tit != tree->treelinks().end();++tit) {
if(tit->second.first && tit->second.second==emitter->progenitor())
break;
}
// sort out the colour lines
if(cline.first && cline.first == emitter->progenitor()->antiColourLine() &&
cline.second !=newEmit->antiColourLine()) {
// sort out not radiating line
ColinePtr col = emitter->progenitor()->colourLine();
if(col) {
col->removeColoured(emitter->copy());
col->removeColoured(emitter->progenitor());
newEmit->colourLine()->removeColoured(newEmit);
col->addColoured(newEmit);
}
}
else if(aline.first && aline.first == emitter->progenitor()->colourLine() &&
aline.second !=newEmit->colourLine()) {
// sort out not radiating line
ColinePtr anti = emitter->progenitor()->antiColourLine();
if(anti) {
anti->removeAntiColoured(emitter->copy());
anti->removeAntiColoured(emitter->progenitor());
newEmit->colourLine()->removeAntiColoured(newEmit);
anti->addAntiColoured(newEmit);
}
}
else
assert(false);
// update the emitter
emitter->copy(newEmit);
ShowerParticlePtr sp = new_ptr(ShowerParticle(*newEmit,1,true));
emitter->progenitor(sp);
tree->outgoingLines()[emitter]=sp;
emitter->perturbative(false);
// update for decaying particles
if(tit!=tree->treelinks().end())
tree->updateLink(tit->first,make_pair(emitter,sp));
// add the emitted particle
// sort out the colour
if(cline.first && cline.second==emitted->antiColourLine()) {
cline.second->removeAntiColoured(emitted);
cline.first->addAntiColoured(emitted);
}
else if(aline.first && aline.second==emitted->colourLine()) {
aline.second->removeColoured(emitted);
aline.first->addColoured(emitted);
}
else
assert(false);
sp=new_ptr(ShowerParticle(*emitted,1,true));
ShowerProgenitorPtr gluon=new_ptr(ShowerProgenitor(emitter->original(),
emitted,sp));
gluon->perturbative(false);
tree->outgoingLines().insert(make_pair(gluon,sp));
}
}
void QTildeShowerHandler::setupMECorrection(RealEmissionProcessPtr real) {
assert(real);
currentTree()->hardMatrixElementCorrection(true);
// II emission
if(real->emitter() < real->incoming().size() &&
real->spectator() < real->incoming().size()) {
// recoiling system
for( map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
cjt= currentTree()->outgoingLines().begin();
cjt != currentTree()->outgoingLines().end();++cjt ) {
cjt->first->progenitor()->transform(real->transformation());
cjt->first->copy()->transform(real->transformation());
}
// the the radiating system
ShowerProgenitorPtr emitter,spectator;
unsigned int iemit = real->emitter();
unsigned int ispect = real->spectator();
int ig = int(real->emitted())-int(real->incoming().size());
emitter = findInitialStateLine(currentTree(),
real->bornIncoming()[iemit]->id(),
real->bornIncoming()[iemit]->momentum());
spectator = findInitialStateLine(currentTree(),
real->bornIncoming()[ispect]->id(),
real->bornIncoming()[ispect]->momentum());
// sort out the colours
ColinePair cline,aline;
fixSpectatorColours(real->incoming()[ispect],spectator,cline,aline,true);
// update the spectator
spectator->copy(real->incoming()[ispect]);
ShowerParticlePtr sp(new_ptr(ShowerParticle(*real->incoming()[ispect],1,false)));
sp->x(ispect ==0 ? real->x().first :real->x().second);
spectator->progenitor(sp);
currentTree()->incomingLines()[spectator]=sp;
spectator->perturbative(true);
// now for the emitter
fixInitialStateEmitter(currentTree(),real->incoming()[iemit],real->outgoing()[ig],
emitter,cline,aline,iemit ==0 ? real->x().first :real->x().second);
}
// FF emission
else if(real->emitter() >= real->incoming().size() &&
real->spectator() >= real->incoming().size()) {
assert(real->outgoing()[real->emitted()-real->incoming().size()]->id()==ParticleID::g);
// find the emitter and spectator in the shower tree
ShowerProgenitorPtr emitter,spectator;
int iemit = int(real->emitter())-int(real->incoming().size());
emitter = findFinalStateLine(currentTree(),
real->bornOutgoing()[iemit]->id(),
real->bornOutgoing()[iemit]->momentum());
int ispect = int(real->spectator())-int(real->incoming().size());
spectator = findFinalStateLine(currentTree(),
real->bornOutgoing()[ispect]->id(),
real->bornOutgoing()[ispect]->momentum());
map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator tit;
// first the spectator
// special case if decayed
for(tit = currentTree()->treelinks().begin(); tit != currentTree()->treelinks().end();++tit) {
if(tit->second.first && tit->second.second==spectator->progenitor())
break;
}
// sort out the colours
ColinePair cline,aline;
fixSpectatorColours(real->outgoing()[ispect],spectator,cline,aline,true);
// update the spectator
spectator->copy(real->outgoing()[ispect]);
ShowerParticlePtr sp(new_ptr(ShowerParticle(*real->outgoing()[ispect],1,true)));
spectator->progenitor(sp);
currentTree()->outgoingLines()[spectator]=sp;
spectator->perturbative(true);
// update for decaying particles
if(tit!=currentTree()->treelinks().end())
currentTree()->updateLink(tit->first,make_pair(spectator,sp));
// now the emitting particle
int ig = int(real->emitted())-int(real->incoming().size());
fixFinalStateEmitter(currentTree(),real->outgoing()[iemit],
real->outgoing()[ig],
emitter,cline,aline);
}
// IF emission
else {
// scattering process
if(real->incoming().size()==2) {
ShowerProgenitorPtr emitter,spectator;
unsigned int iemit = real->emitter();
unsigned int ispect = real->spectator();
int ig = int(real->emitted())-int(real->incoming().size());
ColinePair cline,aline;
// incoming spectator
if(ispect<2) {
spectator = findInitialStateLine(currentTree(),
real->bornIncoming()[ispect]->id(),
real->bornIncoming()[ispect]->momentum());
fixSpectatorColours(real->incoming()[ispect],spectator,cline,aline,true);
// update the spectator
spectator->copy(real->incoming()[ispect]);
ShowerParticlePtr sp(new_ptr(ShowerParticle(*real->incoming()[ispect],1,false)));
sp->x(ispect ==0 ? real->x().first :real->x().second);
spectator->progenitor(sp);
currentTree()->incomingLines()[spectator]=sp;
spectator->perturbative(true);
}
// outgoing spectator
else {
spectator = findFinalStateLine(currentTree(),
real->bornOutgoing()[ispect-real->incoming().size()]->id(),
real->bornOutgoing()[ispect-real->incoming().size()]->momentum());
// special case if decayed
map<tShowerTreePtr,pair<tShowerProgenitorPtr,tShowerParticlePtr> >::const_iterator tit;
for(tit = currentTree()->treelinks().begin(); tit != currentTree()->treelinks().end();++tit) {
if(tit->second.first && tit->second.second==spectator->progenitor())
break;
}
fixSpectatorColours(real->outgoing()[ispect-real->incoming().size()],spectator,cline,aline,true);
// update the spectator
spectator->copy(real->outgoing()[ispect-real->incoming().size()]);
ShowerParticlePtr sp(new_ptr(ShowerParticle(*real->outgoing()[ispect-real->incoming().size()],1,true)));
spectator->progenitor(sp);
currentTree()->outgoingLines()[spectator]=sp;
spectator->perturbative(true);
// update for decaying particles
if(tit!=currentTree()->treelinks().end())
currentTree()->updateLink(tit->first,make_pair(spectator,sp));
}
// incoming emitter
if(iemit<2) {
emitter = findInitialStateLine(currentTree(),
real->bornIncoming()[iemit]->id(),
real->bornIncoming()[iemit]->momentum());
fixInitialStateEmitter(currentTree(),real->incoming()[iemit],real->outgoing()[ig],
emitter,aline,cline,iemit ==0 ? real->x().first :real->x().second);
}
// outgoing emitter
else {
emitter = findFinalStateLine(currentTree(),
real->bornOutgoing()[iemit-real->incoming().size()]->id(),
real->bornOutgoing()[iemit-real->incoming().size()]->momentum());
fixFinalStateEmitter(currentTree(),real->outgoing()[iemit-real->incoming().size()],
real->outgoing()[ig],emitter,aline,cline);
}
}
// decay process
else {
assert(real->spectator()==0);
unsigned int iemit = real->emitter()-real->incoming().size();
int ig = int(real->emitted())-int(real->incoming().size());
ColinePair cline,aline;
// incoming spectator
ShowerProgenitorPtr spectator = findInitialStateLine(currentTree(),
real->bornIncoming()[0]->id(),
real->bornIncoming()[0]->momentum());
fixSpectatorColours(real->incoming()[0],spectator,cline,aline,false);
// find the emitter
ShowerProgenitorPtr emitter =
findFinalStateLine(currentTree(),
real->bornOutgoing()[iemit]->id(),
real->bornOutgoing()[iemit]->momentum());
// recoiling system
for( map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
cjt= currentTree()->outgoingLines().begin();
cjt != currentTree()->outgoingLines().end();++cjt ) {
if(cjt->first==emitter) continue;
cjt->first->progenitor()->transform(real->transformation());
cjt->first->copy()->transform(real->transformation());
}
// sort out the emitter
fixFinalStateEmitter(currentTree(),real->outgoing()[iemit],
real->outgoing()[ig],emitter,aline,cline);
}
}
// clean up the shower tree
_currenttree->resetShowerProducts();
}
diff --git a/Shower/QTilde/QTildeShowerHandler.h b/Shower/QTilde/QTildeShowerHandler.h
--- a/Shower/QTilde/QTildeShowerHandler.h
+++ b/Shower/QTilde/QTildeShowerHandler.h
@@ -1,846 +1,852 @@
// -*- C++ -*-
#ifndef Herwig_QTildeShowerHandler_H
#define Herwig_QTildeShowerHandler_H
//
// This is the declaration of the QTildeShowerHandler class.
//
#include "QTildeShowerHandler.fh"
#include "Herwig/Shower/ShowerHandler.h"
#include "Herwig/Shower/QTilde/Base/ShowerModel.h"
#include "Herwig/Shower/QTilde/SplittingFunctions/SplittingGenerator.h"
#include "Herwig/Shower/QTilde/Base/ShowerTree.h"
#include "Herwig/Shower/QTilde/Base/ShowerProgenitor.fh"
#include "Herwig/Shower/QTilde/Base/HardTree.h"
#include "Herwig/Shower/QTilde/Base/Branching.h"
#include "Herwig/Shower/QTilde/Base/ShowerVeto.h"
#include "Herwig/Shower/QTilde/Base/FullShowerVeto.h"
#include "Herwig/MatrixElement/HwMEBase.h"
#include "Herwig/Decay/HwDecayerBase.h"
#include "Herwig/MatrixElement/Matchbox/Matching/ShowerApproximation.h"
#include "Herwig/Shower/RealEmissionProcess.h"
#include "Herwig/Utilities/Statistic.h"
namespace Herwig {
using namespace ThePEG;
/**
* The QTildeShowerHandler class.
*
* @see \ref QTildeShowerHandlerInterfaces "The interfaces"
* defined for QTildeShowerHandler.
*/
class QTildeShowerHandler: public ShowerHandler {
public:
/**
* Pointer to an XComb object
*/
typedef Ptr<XComb>::pointer XCPtr;
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
QTildeShowerHandler();
/**
* The destructor.
*/
virtual ~QTildeShowerHandler();
//@}
public:
/**
* At the end of the Showering, transform ShowerParticle objects
* into ThePEG particles and fill the event record with them.
* Notice that the parent/child relationships and the
* transformation from ShowerColourLine objects into ThePEG
* ColourLine ones must be properly handled.
*/
void fillEventRecord();
/**
* Return the relevant hard scale to be used in the profile scales
*/
virtual Energy hardScale() const {
return muPt;
}
/**
+ * Hook to allow vetoing of event after showering hard sub-process
+ * as in e.g. MLM merging.
+ */
+ virtual bool showerHardProcessVeto() { return false; }
+
+ /**
* Generate hard emissions for CKKW etc
*/
virtual HardTreePtr generateCKKW(ShowerTreePtr tree) const;
/**
* Members to perform the shower
*/
//@{
/**
* Perform the shower of the hard process
*/
virtual void showerHardProcess(ShowerTreePtr,XCPtr);
/**
* Perform the shower of a decay
*/
virtual void showerDecay(ShowerTreePtr);
//@}
/**
* Access to the flags and shower variables
*/
//@{
/**
* Get the ShowerModel
*/
ShowerModelPtr showerModel() const {return _model;}
/**
* Get the SplittingGenerator
*/
tSplittingGeneratorPtr splittingGenerator() const { return _splittingGenerator; }
/**
* Mode for hard emissions
*/
int hardEmission() const {return _hardEmission;}
//@}
/**
* Connect the Hard and Shower trees
*/
virtual void connectTrees(ShowerTreePtr showerTree, HardTreePtr hardTree, bool hard );
/**
* Access to switches for spin correlations
*/
//@{
/**
* Spin Correlations
*/
unsigned int spinCorrelations() const {
return _spinOpt;
}
/**
* Soft correlations
*/
unsigned int softCorrelations() const {
return _softOpt;
}
/**
* Any correlations
*/
bool correlations() const {
return _spinOpt!=0||_softOpt!=0;
}
//@}
protected:
/**
* Perform the shower
*/
void doShowering(bool hard,XCPtr);
/**
* Generate the hard matrix element correction
*/
virtual RealEmissionProcessPtr hardMatrixElementCorrection(bool);
/**
* Generate the hardest emission
*/
virtual void hardestEmission(bool hard);
/**
* Set up for applying a matrix element correction
*/
void setupMECorrection(RealEmissionProcessPtr real);
/**
* Extract the particles to be showered, set the evolution scales
* and apply the hard matrix element correction
* @param hard Whether this is a hard process or decay
* @return The particles to be showered
*/
virtual vector<ShowerProgenitorPtr> setupShower(bool hard);
/**
* set the colour partners
*/
- virtual void setEvolutionPartners(bool hard,ShowerInteraction::Type,
+ virtual void setEvolutionPartners(bool hard,ShowerInteraction,
bool clear);
/**
* Methods to perform the evolution of an individual particle, including
* recursive calling on the products
*/
//@{
/**
* It does the forward evolution of the time-like input particle
* (and recursively for all its radiation products).
* accepting only emissions which conforms to the showerVariables
* and soft matrix element correction.
* If at least one emission has occurred then the method returns true.
* @param particle The particle to be showered
*/
- virtual bool timeLikeShower(tShowerParticlePtr particle, ShowerInteraction::Type,
+ virtual bool timeLikeShower(tShowerParticlePtr particle, ShowerInteraction,
Branching fb, bool first);
/**
* It does the backward evolution of the space-like input particle
* (and recursively for all its time-like radiation products).
* accepting only emissions which conforms to the showerVariables.
* If at least one emission has occurred then the method returns true
* @param particle The particle to be showered
* @param beam The beam particle
*/
virtual bool spaceLikeShower(tShowerParticlePtr particle,PPtr beam,
- ShowerInteraction::Type);
+ ShowerInteraction);
/**
* If does the forward evolution of the input on-shell particle
* involved in a decay
* (and recursively for all its time-like radiation products).
* accepting only emissions which conforms to the showerVariables.
* @param particle The particle to be showered
* @param maxscale The maximum scale for the shower.
* @param minimumMass The minimum mass of the final-state system
*/
virtual bool
spaceLikeDecayShower(tShowerParticlePtr particle,
const ShowerParticle::EvolutionScales & maxScales,
- Energy minimumMass,ShowerInteraction::Type,
+ Energy minimumMass,ShowerInteraction,
Branching fb);
/**
* Truncated shower from a time-like particle
*/
virtual bool truncatedTimeLikeShower(tShowerParticlePtr particle,
HardBranchingPtr branch,
- ShowerInteraction::Type type,
+ ShowerInteraction type,
Branching fb, bool first);
/**
* Truncated shower from a space-like particle
*/
virtual bool truncatedSpaceLikeShower(tShowerParticlePtr particle,PPtr beam,
HardBranchingPtr branch,
- ShowerInteraction::Type type);
+ ShowerInteraction type);
/**
* Truncated shower from a time-like particle
*/
virtual bool truncatedSpaceLikeDecayShower(tShowerParticlePtr particle,
const ShowerParticle::EvolutionScales & maxScales,
Energy minimumMass, HardBranchingPtr branch,
- ShowerInteraction::Type type, Branching fb);
+ ShowerInteraction type, Branching fb);
//@}
/**
* Switches for matrix element corrections
*/
//@{
/**
* Any ME correction?
*/
bool MECOn() const {
return _hardEmission == 1;
}
/**
* Any hard ME correction?
*/
bool hardMEC() const {
return _hardEmission == 1 && (_meCorrMode == 1 || _meCorrMode == 2);
}
/**
* Any soft ME correction?
*/
bool softMEC() const {
return _hardEmission == 1 && (_meCorrMode == 1 || _meCorrMode > 2);
}
//@}
/**
* Is the truncated shower on?
*/
bool isTruncatedShowerON() const {return _trunc_Mode;}
/**
* Switch for intrinsic pT
*/
//@{
/**
* Any intrinsic pT?
*/
bool ipTon() const {
return _iptrms != ZERO || ( _beta == 1.0 && _gamma != ZERO && _iptmax !=ZERO );
}
//@}
/**@name Additional shower vetoes */
//@{
/**
* Insert a veto.
*/
void addVeto (ShowerVetoPtr v) { _vetoes.push_back(v); }
/**
* Remove a veto.
*/
void removeVeto (ShowerVetoPtr v) {
vector<ShowerVetoPtr>::iterator vit = find(_vetoes.begin(),_vetoes.end(),v);
if (vit != _vetoes.end())
_vetoes.erase(vit);
}
//@}
/**
* Switches for vetoing hard emissions
*/
//@{
/**
* Returns true if the hard veto read-in is to be applied to only
* the primary collision and false otherwise.
*/
bool hardVetoReadOption() const {return _hardVetoReadOption;}
//@}
/**
* Enhancement factors for radiation needed to generate the soft matrix
* element correction.
*/
//@{
/**
* Access the enhancement factor for initial-state radiation
*/
double initialStateRadiationEnhancementFactor() const { return _initialenhance; }
/**
* Access the enhancement factor for final-state radiation
*/
double finalStateRadiationEnhancementFactor() const { return _finalenhance; }
/**
* Set the enhancement factor for initial-state radiation
*/
void initialStateRadiationEnhancementFactor(double in) { _initialenhance=in; }
/**
* Set the enhancement factor for final-state radiation
*/
void finalStateRadiationEnhancementFactor(double in) { _finalenhance=in; }
//@}
/**
* Access to set/get the HardTree currently beinging showered
*/
//@{
/**
* The HardTree currently being showered
*/
tHardTreePtr hardTree() {return _hardtree;}
/**
* The HardTree currently being showered
*/
void hardTree(tHardTreePtr in) {_hardtree = in;}
//@}
/**
* Access/set the beam particle for the current initial-state shower
*/
//@{
/**
* Get the beam particle data
*/
Ptr<BeamParticleData>::const_pointer beamParticle() const { return _beam; }
/**
* Set the beam particle data
*/
void setBeamParticle(Ptr<BeamParticleData>::const_pointer in) { _beam=in; }
//@}
/**
* Set/Get the current tree being evolverd for inheriting classes
*/
//@{
/**
* Get the tree
*/
tShowerTreePtr currentTree() { return _currenttree; }
/**
* Set the tree
*/
void currentTree(tShowerTreePtr tree) { _currenttree=tree; }
//@}
/**
* Access the maximum number of attempts to generate the shower
*/
unsigned int maximumTries() const { return _maxtry; }
/**
* Set/Get the ShowerProgenitor for the current shower
*/
//@{
/**
* Access the progenitor
*/
ShowerProgenitorPtr progenitor() { return _progenitor; }
/**
* Set the progenitor
*/
void progenitor(ShowerProgenitorPtr in) { _progenitor=in; }
//@}
/**
* Calculate the intrinsic \f$p_T\f$.
*/
virtual void generateIntrinsicpT(vector<ShowerProgenitorPtr>);
/**
* Access to the intrinsic \f$p_T\f$ for inheriting classes
*/
map<tShowerProgenitorPtr,pair<Energy,double> > & intrinsicpT() { return _intrinsic; }
/**
* find the maximally allowed pt acc to the hard process.
*/
void setupMaximumScales(const vector<ShowerProgenitorPtr> &,XCPtr);
/**
* find the relevant hard scales for profile scales.
*/
void setupHardScales(const vector<ShowerProgenitorPtr> &,XCPtr);
/**
* Convert the HardTree into an extra shower emission
*/
- void convertHardTree(bool hard,ShowerInteraction::Type type);
+ void convertHardTree(bool hard,ShowerInteraction type);
protected:
/**
* Find the parton extracted from the incoming particle after ISR
*/
PPtr findFirstParton(tPPtr seed) const;
/**
* Fix Remnant connections after ISR
*/
tPPair remakeRemnant(tPPair oldp);
protected:
/**
* Start the shower of a timelike particle
*/
- virtual bool startTimeLikeShower(ShowerInteraction::Type);
+ virtual bool startTimeLikeShower(ShowerInteraction);
/**
* Update of the time-like stuff
*/
void updateHistory(tShowerParticlePtr particle);
/**
* Start the shower of a spacelike particle
*/
- virtual bool startSpaceLikeShower(PPtr,ShowerInteraction::Type);
+ virtual bool startSpaceLikeShower(PPtr,ShowerInteraction);
/**
* Start the shower of a spacelike particle
*/
virtual bool
startSpaceLikeDecayShower(const ShowerParticle::EvolutionScales & maxScales,
- Energy minimumMass,ShowerInteraction::Type);
+ Energy minimumMass,ShowerInteraction);
/**
* Select the branching for the next time-like emission
*/
Branching selectTimeLikeBranching(tShowerParticlePtr particle,
- ShowerInteraction::Type type,
+ ShowerInteraction type,
HardBranchingPtr branch);
/**
* Select the branching for the next space-like emission in a decay
*/
Branching selectSpaceLikeDecayBranching(tShowerParticlePtr particle,
const ShowerParticle::EvolutionScales & maxScales,
- Energy minmass,ShowerInteraction::Type type,
+ Energy minmass,ShowerInteraction type,
HardBranchingPtr branch);
/**
* Create the timelike child of a branching
*/
ShowerParticleVector createTimeLikeChildren(tShowerParticlePtr particle,
IdList ids);
/**
* Vetos for the timelike shower
*/
virtual bool timeLikeVetoed(const Branching &,ShowerParticlePtr);
/**
* Vetos for the spacelike shower
*/
virtual bool spaceLikeVetoed(const Branching &,ShowerParticlePtr);
/**
* Vetos for the spacelike shower
*/
virtual bool spaceLikeDecayVetoed(const Branching &,ShowerParticlePtr);
/**
* Only generate the hard emission, for testing only.
*/
bool hardOnly() const {return _limitEmissions==3;}
/**
* Check the flags
*/
void checkFlags();
/**
*
*/
void addFSRUsingDecayPOWHEG(HardTreePtr ISRTree);
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:
/**
* The main method which manages the showering of a subprocess.
*/
virtual tPPair cascade(tSubProPtr sub, XCPtr xcomb);
/**
* Decay a ShowerTree
*/
void decay(ShowerTreePtr tree, ShowerDecayMap & decay);
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();
//@}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
QTildeShowerHandler & operator=(const QTildeShowerHandler &);
private:
/**
* Stuff from the ShowerHandler
*/
//@{
/**
* The ShowerTree for the hard process
*/
ShowerTreePtr hard_;
/**
* The ShowerTree for the decays
*/
ShowerDecayMap decay_;
/**
* The ShowerTrees for which the initial shower
*/
vector<ShowerTreePtr> done_;
//@}
private :
/**
* Pointer to the model for the shower evolution model
*/
ShowerModelPtr _model;
/**
* Pointer to the splitting generator
*/
SplittingGeneratorPtr _splittingGenerator;
/**
* Maximum number of tries to generate the shower of a particular tree
*/
unsigned int _maxtry;
/**
* Matrix element correction switch
*/
unsigned int _meCorrMode;
/**
* Control of the reconstruction option
*/
unsigned int _reconOpt;
/**
* If hard veto pT scale is being read-in this determines
* whether the read-in value is applied to primary and
* secondary (MPI) scatters or just the primary one, with
* the usual computation of the veto being performed for
* the secondary (MPI) scatters.
*/
bool _hardVetoReadOption;
/**
* rms intrinsic pT of Gaussian distribution
*/
Energy _iptrms;
/**
* Proportion of inverse quadratic intrinsic pT distribution
*/
double _beta;
/**
* Parameter for inverse quadratic: 2*Beta*Gamma/(sqr(Gamma)+sqr(intrinsicpT))
*/
Energy _gamma;
/**
* Upper bound on intrinsic pT for inverse quadratic
*/
Energy _iptmax;
/**
* Limit the number of emissions for testing
*/
unsigned int _limitEmissions;
/**
* The progenitor of the current shower
*/
ShowerProgenitorPtr _progenitor;
/**
* Matrix element
*/
HwMEBasePtr _hardme;
/**
* Decayer
*/
HwDecayerBasePtr _decayme;
/**
* The ShowerTree currently being showered
*/
ShowerTreePtr _currenttree;
/**
* The HardTree currently being showered
*/
HardTreePtr _hardtree;
/**
* Radiation enhancement factors for use with the veto algorithm
* if needed by the soft matrix element correction
*/
//@{
/**
* Enhancement factor for initial-state radiation
*/
double _initialenhance;
/**
* Enhancement factor for final-state radiation
*/
double _finalenhance;
//@}
/**
* The beam particle data for the current initial-state shower
*/
Ptr<BeamParticleData>::const_pointer _beam;
/**
* Storage of the intrinsic \f$p_t\f$ of the particles
*/
map<tShowerProgenitorPtr,pair<Energy,double> > _intrinsic;
/**
* Vetoes
*/
vector<ShowerVetoPtr> _vetoes;
/**
* Full Shower Vetoes
*/
vector<FullShowerVetoPtr> _fullShowerVetoes;
/**
* Number of iterations for reweighting
*/
unsigned int _nReWeight;
/**
* Whether or not we are reweighting
*/
bool _reWeight;
/**
* number of IS emissions
*/
unsigned int _nis;
/**
* Number of FS emissions
*/
unsigned int _nfs;
/**
* The option for wqhich interactions to use
*/
- ShowerInteraction::Type interaction_;
+ ShowerInteraction interaction_;
/**
* Truncated shower switch
*/
bool _trunc_Mode;
/**
* Count of the number of truncated emissions
*/
unsigned int _truncEmissions;
/**
* Mode for the hard emissions
*/
int _hardEmission;
/**
* Option to include spin correlations
*/
unsigned int _spinOpt;
/**
* Option for the kernal for soft correlations
*/
unsigned int _softOpt;
/**
* Option for hard radiation in POWHEG events
*/
bool _hardPOWHEG;
/**
* True if no warnings about incorrect hard emission
* mode setting have been issued yet
*/
static bool _hardEmissionWarn;
/**
* True if no warnings about missing truncated shower
* have been issued yet
*/
static bool _missingTruncWarn;
/**
* The relevant hard scale to be used in the profile scales
*/
Energy muPt;
/**
* Maximum number of emission attempts for FSR
*/
unsigned int _maxTryFSR;
/**
* Maximum number of failures for FSR generation
*/
unsigned int _maxFailFSR;
/**
* Failure fraction for FSR generation
*/
double _fracFSR;
/**
* Counter for number of FSR emissions
*/
unsigned int _nFSR;
/**
* Counter for the number of failed events due to FSR emissions
*/
unsigned int _nFailedFSR;
};
}
#endif /* Herwig_QTildeShowerHandler_H */
diff --git a/Shower/QTilde/ShowerConfig.h b/Shower/QTilde/ShowerConfig.h
--- a/Shower/QTilde/ShowerConfig.h
+++ b/Shower/QTilde/ShowerConfig.h
@@ -1,141 +1,141 @@
// -*- C++ -*-
//
// ShowerConfig.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_ShowerConfig_H
#define HERWIG_ShowerConfig_H
//
// This is the declaration of the ShowerConfig class.
#include "ThePEG/Config/ThePEG.h"
#include "ThePEG/PDT/ParticleData.h"
#include "Herwig/Shower/QTilde/Base/ShowerParticle.fh"
#include "Herwig/Shower/QTilde/Base/SudakovFormFactor.fh"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ShowerInteraction.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
*
* Handy header file to be included in all Shower classes.
* It contains only some useful typedefs.
*/
/**
* Pointer to a ColourLine
*/
typedef Ptr<ThePEG::ColourLine>::pointer ColinePtr;
/**
* Transient Pointer to a ColourLine
*/
typedef Ptr<ThePEG::ColourLine>::transient_pointer tColinePtr;
/**
* A pair of ColourLine pointers
*/
typedef pair<ColinePtr,ColinePtr> ColinePair;
/**
* A pair of transient ColourLine pointers
*/
typedef pair<tColinePtr,tColinePtr> tColinePair;
/**
* A Vector of ShowerParticle pointers
*/
typedef vector<ShowerParticlePtr> ShowerParticleVector;
/**
* A Vector of transient ShowerParticle pointers
*/
typedef vector<tShowerParticlePtr> tShowerParticleVector;
/**
* Definition of the IdList for branchings
*/
typedef vector<tcPDPtr> IdList;
- inline ShowerInteraction::Type convertInteraction(ShowerPartnerType::Type partner) {
- if(partner==ShowerPartnerType::QCDColourLine ||
- partner==ShowerPartnerType::QCDAntiColourLine)
+ inline ShowerInteraction convertInteraction(ShowerPartnerType partner) {
+ if (partner==ShowerPartnerType::QCDColourLine ||
+ partner==ShowerPartnerType::QCDAntiColourLine)
return ShowerInteraction::QCD;
- else if(ShowerPartnerType::QED)
+ else if (partner==ShowerPartnerType::QED)
return ShowerInteraction::QED;
else
return ShowerInteraction::UNDEFINED;
}
/**
* typedef to pair the SudakovFormFactor and the particles in a branching
*/
struct BranchingElement {
/**
* Constructor
*/
BranchingElement();
/**
* Constructor
*/
BranchingElement(SudakovPtr sud, IdList part);
/**
* Destructor
*/
~BranchingElement();
/**
* Access to the Sudakov
*/
SudakovPtr sudakov;
/**
* Access to the particles
*/
IdList particles;
/**
* Access to the charge conjugate particles
*/
IdList conjugateParticles;
};
/**
* typedef to pair the PDG code of the particle and the BranchingElement
*/
typedef multimap<long,BranchingElement> BranchingList;
/**
* typedef to create a structure which can be inserted into a BranchingList
*/
typedef pair<long, BranchingElement> BranchingInsert;
}
namespace ThePEG {
/**
* Output operator to allow the structure
*/
PersistentOStream & operator << (PersistentOStream & os,
const Herwig::BranchingElement & x);
/**
* Input operator to allow the structure
*/
PersistentIStream & operator >> (PersistentIStream & is,
Herwig::BranchingElement & x);
}
#endif // HERWIG_ShowerConfig_H
diff --git a/Shower/QTilde/ShowerInteraction.h b/Shower/QTilde/ShowerInteraction.h
--- a/Shower/QTilde/ShowerInteraction.h
+++ b/Shower/QTilde/ShowerInteraction.h
@@ -1,36 +1,41 @@
// -*- C++ -*-
//
// ShowerInteraction.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_ShowerInteraction_H
#define HERWIG_ShowerInteraction_H
namespace Herwig {
/** \ingroup Shower
*
* Handy header file to be included in all Shower classes.
* It contains only some useful enums.
*/
- namespace ShowerInteraction {
+/**
+ * Enum for the type of interaction
+ */
+enum class ShowerInteraction {
+ UNDEFINED=-1,
+ QCD,
+ QED,
+ Both
+};
- /**
- * Enum for the type of interaction
- */
- enum Type { UNDEFINED=-1, QCD, QED, Both };
- }
-
- namespace ShowerPartnerType {
- /**
- * Enum for the type of shower partner
- */
- enum Type {Undefined,QCDColourLine,QCDAntiColourLine,QED};
- }
+/**
+ * Enum for the type of shower partner
+ */
+enum class ShowerPartnerType {
+ Undefined,
+ QCDColourLine,
+ QCDAntiColourLine,
+ QED
+};
}
#endif // HERWIG_ShowerInteraction_H
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,873 +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::Type>
+ 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 {
- using namespace ShowerInteraction;
os << oenum(_interactionType) << _interactionOrder
<< oenum(_colourStructure) << _colourFactor
- << angularOrdered_;
+ << angularOrdered_ << scaleChoice_;
}
void SplittingFunction::persistentInput(PersistentIStream & is, int) {
- using namespace ShowerInteraction;
is >> ienum(_interactionType) >> _interactionOrder
>> ienum(_colourStructure) >> _colourFactor
- >> angularOrdered_;
+ >> angularOrdered_ >> scaleChoice_;
}
void SplittingFunction::colourConnection(tShowerParticlePtr parent,
tShowerParticlePtr first,
tShowerParticlePtr second,
- ShowerPartnerType::Type partnerType,
+ 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::Type partnerType,
+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::Type partnerType,
+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::Type partnerType,
+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::Type interactionType() const {return _interactionType;}
+ 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::Type partnerType,
+ 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 type,
+ 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 type,
+ void evaluateInitialStateScales(ShowerPartnerType type,
Energy scale, double z,
tShowerParticlePtr parent,
tShowerParticlePtr first,
tShowerParticlePtr second);
/**
* Sort out scales for decay emission
*/
- void evaluateDecayScales(ShowerPartnerType::Type type,
+ 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::Type _interactionType;
+ 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/QTilde/SplittingFunctions/SplittingGenerator.cc b/Shower/QTilde/SplittingFunctions/SplittingGenerator.cc
--- a/Shower/QTilde/SplittingFunctions/SplittingGenerator.cc
+++ b/Shower/QTilde/SplittingFunctions/SplittingGenerator.cc
@@ -1,606 +1,606 @@
// -*- C++ -*-
//
// SplittingGenerator.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 SplittingGenerator class.
//
#include "SplittingGenerator.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Command.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Utilities/StringUtils.h"
#include "ThePEG/Repository/Repository.h"
#include "Herwig/Shower/QTilde/Base/ShowerParticle.h"
#include "Herwig/Shower/ShowerHandler.h"
#include "ThePEG/Utilities/Rebinder.h"
#include <cassert>
#include "ThePEG/Utilities/DescribeClass.h"
using namespace Herwig;
namespace {
-bool checkInteraction(ShowerInteraction::Type allowed,
- ShowerInteraction::Type splitting) {
+bool checkInteraction(ShowerInteraction allowed,
+ ShowerInteraction splitting) {
if(allowed==ShowerInteraction::Both)
return true;
else if(allowed == splitting)
return true;
else
return false;
}
}
DescribeClass<SplittingGenerator,Interfaced>
describeSplittingGenerator ("Herwig::SplittingGenerator","");
IBPtr SplittingGenerator::clone() const {
return new_ptr(*this);
}
IBPtr SplittingGenerator::fullclone() const {
return new_ptr(*this);
}
void SplittingGenerator::persistentOutput(PersistentOStream & os) const {
os << _bbranchings << _fbranchings << _deTuning;
}
void SplittingGenerator::persistentInput(PersistentIStream & is, int) {
is >> _bbranchings >> _fbranchings >> _deTuning;
}
void SplittingGenerator::Init() {
static ClassDocumentation<SplittingGenerator> documentation
("There class is responsible for initializing the Sudakov form factors ",
"and generating splittings.");
static Command<SplittingGenerator> interfaceAddSplitting
("AddFinalSplitting",
"Adds another splitting to the list of splittings considered "
"in the shower. Command is a->b,c; Sudakov",
&SplittingGenerator::addFinalSplitting);
static Command<SplittingGenerator> interfaceAddInitialSplitting
("AddInitialSplitting",
"Adds another splitting to the list of initial splittings to consider "
"in the shower. Command is a->b,c; Sudakov. Here the particle a is the "
"particle that is PRODUCED by the splitting. b is the initial state "
"particle that is splitting in the shower.",
&SplittingGenerator::addInitialSplitting);
static Command<SplittingGenerator> interfaceDeleteSplitting
("DeleteFinalSplitting",
"Deletes a splitting from the list of splittings considered "
"in the shower. Command is a->b,c; Sudakov",
&SplittingGenerator::deleteFinalSplitting);
static Command<SplittingGenerator> interfaceDeleteInitialSplitting
("DeleteInitialSplitting",
"Deletes a splitting from the list of initial splittings to consider "
"in the shower. Command is a->b,c; Sudakov. Here the particle a is the "
"particle that is PRODUCED by the splitting. b is the initial state "
"particle that is splitting in the shower.",
&SplittingGenerator::deleteInitialSplitting);
static Parameter<SplittingGenerator,double> interfaceDetuning
("Detuning",
"The Detuning parameter to make the veto algorithm less efficient to improve the weight variations",
&SplittingGenerator::_deTuning, 1.0, 1.0, 10.0,
false, false, Interface::limited);
}
string SplittingGenerator::addSplitting(string arg, bool final) {
string partons = StringUtils::car(arg);
string sudakov = StringUtils::cdr(arg);
vector<tPDPtr> products;
string::size_type next = partons.find("->");
if(next == string::npos)
return "Error: Invalid string for splitting " + arg;
if(partons.find(';') == string::npos)
return "Error: Invalid string for splitting " + arg;
tPDPtr parent = Repository::findParticle(partons.substr(0,next));
partons = partons.substr(next+2);
do {
next = min(partons.find(','), partons.find(';'));
tPDPtr pdp = Repository::findParticle(partons.substr(0,next));
partons = partons.substr(next+1);
if(pdp) products.push_back(pdp);
else return "Error: Could not create splitting from " + arg;
} while(partons[0] != ';' && partons.size());
SudakovPtr s;
s = dynamic_ptr_cast<SudakovPtr>(Repository::TraceObject(sudakov));
if(!s) return "Error: Could not load Sudakov " + sudakov + '\n';
IdList ids;
ids.push_back(parent);
for(vector<tPDPtr>::iterator it = products.begin(); it!=products.end(); ++it)
ids.push_back(*it);
// check splitting can handle this
if(!s->splittingFn()->accept(ids))
return "Error: Sudakov " + sudakov + " SplittingFunction can't handle particles\n";
// add to map
addToMap(ids,s,final);
return "";
}
string SplittingGenerator::deleteSplitting(string arg, bool final) {
string partons = StringUtils::car(arg);
string sudakov = StringUtils::cdr(arg);
vector<tPDPtr> products;
string::size_type next = partons.find("->");
if(next == string::npos)
return "Error: Invalid string for splitting " + arg;
if(partons.find(';') == string::npos)
return "Error: Invalid string for splitting " + arg;
tPDPtr parent = Repository::findParticle(partons.substr(0,next));
partons = partons.substr(next+2);
do {
next = min(partons.find(','), partons.find(';'));
tPDPtr pdp = Repository::findParticle(partons.substr(0,next));
partons = partons.substr(next+1);
if(pdp) products.push_back(pdp);
else return "Error: Could not create splitting from " + arg;
} while(partons[0] != ';' && partons.size());
SudakovPtr s;
s = dynamic_ptr_cast<SudakovPtr>(Repository::TraceObject(sudakov));
if(!s) return "Error: Could not load Sudakov " + sudakov + '\n';
IdList ids;
ids.push_back(parent);
for(vector<tPDPtr>::iterator it = products.begin(); it!=products.end(); ++it)
ids.push_back(*it);
// check splitting can handle this
if(!s->splittingFn()->accept(ids))
return "Error: Sudakov " + sudakov + " Splitting Function can't handle particles\n";
// delete from map
deleteFromMap(ids,s,final);
return "";
}
void SplittingGenerator::addToMap(const IdList &ids, const SudakovPtr &s, bool final) {
if(!final) {
_bbranchings.insert(BranchingInsert(abs(ids[1]->id()),BranchingElement(s,ids)));
s->addSplitting(ids);
}
else {
_fbranchings.insert(BranchingInsert(abs(ids[0]->id()),BranchingElement(s,ids)));
s->addSplitting(ids);
}
}
void SplittingGenerator::deleteFromMap(const IdList &ids,
const SudakovPtr &s, bool final) {
if(!final) {
pair<BranchingList::iterator,BranchingList::iterator>
range = _bbranchings.equal_range(abs(ids[1]->id()));
for(BranchingList::iterator it=range.first;
it!=range.second&&it!=_bbranchings.end();++it) {
if(it->second.sudakov==s&&it->second.particles==ids) {
BranchingList::iterator it2=it;
--it;
_bbranchings.erase(it2);
}
}
s->removeSplitting(ids);
}
else {
pair<BranchingList::iterator,BranchingList::iterator>
range = _fbranchings.equal_range(abs(ids[0]->id()));
for(BranchingList::iterator it=range.first;
it!=range.second&&it!=_fbranchings.end();++it) {
if(it->second.sudakov==s&&it->second.particles==ids) {
BranchingList::iterator it2 = it;
--it;
_fbranchings.erase(it2);
}
}
s->removeSplitting(ids);
}
}
Branching SplittingGenerator::chooseForwardBranching(ShowerParticle &particle,
double enhance,
- ShowerInteraction::Type type) const {
+ ShowerInteraction type) const {
RhoDMatrix rho;
bool rhoCalc(false);
Energy newQ = ZERO;
ShoKinPtr kinematics = ShoKinPtr();
- ShowerPartnerType::Type partnerType(ShowerPartnerType::Undefined);
+ ShowerPartnerType partnerType(ShowerPartnerType::Undefined);
SudakovPtr sudakov = SudakovPtr();
IdList ids;
// First, find the eventual branching, corresponding to the highest scale.
long index = abs(particle.data().id());
// if no branchings return empty branching struct
if( _fbranchings.find(index) == _fbranchings.end() )
return Branching(ShoKinPtr(), IdList(),SudakovPtr(),ShowerPartnerType::Undefined);
// otherwise select branching
for(BranchingList::const_iterator cit = _fbranchings.lower_bound(index);
cit != _fbranchings.upper_bound(index); ++cit) {
// check either right interaction or doing both
if(!checkInteraction(type,cit->second.sudakov->interactionType())) continue;
if(!rhoCalc) {
rho = particle.extractRhoMatrix(true);
rhoCalc = true;
}
// whether or not this interaction should be angular ordered
bool angularOrdered = cit->second.sudakov->splittingFn()->angularOrdered();
ShoKinPtr newKin;
- ShowerPartnerType::Type type;
+ ShowerPartnerType type;
IdList particles = particle.id()!=cit->first ? cit->second.conjugateParticles : cit->second.particles;
// work out which starting scale we need
if(cit->second.sudakov->interactionType()==ShowerInteraction::QED) {
type = ShowerPartnerType::QED;
Energy startingScale = angularOrdered ? particle.scales().QED : particle.scales().QED_noAO;
newKin = cit->second.sudakov->
generateNextTimeBranching(startingScale,particles,rho,enhance,
_deTuning,
particle.scales().Max_Q2);
}
else if(cit->second.sudakov->interactionType()==ShowerInteraction::QCD) {
// special for octets
if(particle.dataPtr()->iColour()==PDT::Colour8) {
// octet -> octet octet
if(cit->second.sudakov->splittingFn()->colourStructure()==OctetOctetOctet) {
type = ShowerPartnerType::QCDColourLine;
Energy startingScale = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO;
newKin= cit->second.sudakov->
generateNextTimeBranching(startingScale,particles,rho,0.5*enhance,
_deTuning,
particle.scales().Max_Q2);
startingScale = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO;
ShoKinPtr newKin2 = cit->second.sudakov->
generateNextTimeBranching(startingScale,particles,rho,0.5*enhance,
_deTuning,
particle.scales().Max_Q2);
// pick the one with the highest scale
if( ( newKin && newKin2 && newKin2->scale() > newKin->scale()) ||
(!newKin && newKin2) ) {
newKin = newKin2;
type = ShowerPartnerType::QCDAntiColourLine;
}
}
// other g -> q qbar
else {
Energy startingScale = angularOrdered ?
max(particle.scales().QCD_c , particle.scales().QCD_ac ) :
max(particle.scales().QCD_c_noAO, particle.scales().QCD_ac_noAO);
newKin= cit->second.sudakov->
generateNextTimeBranching(startingScale,particles,rho,enhance,
_deTuning,
particle.scales().Max_Q2);
type = UseRandom::rndbool() ?
ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDAntiColourLine;
}
}
// everything else q-> qg etc
else {
Energy startingScale;
if(particle.hasColour()) {
type = ShowerPartnerType::QCDColourLine;
startingScale = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO;
}
else {
type = ShowerPartnerType::QCDAntiColourLine;
startingScale = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO;
}
newKin= cit->second.sudakov->
generateNextTimeBranching(startingScale,particles,rho,enhance,
_deTuning,
particle.scales().Max_Q2);
}
}
// shouldn't be anything else
else
assert(false);
// if no kinematics contine
if(!newKin) continue;
// select highest scale
if( newKin->scale() > newQ ) {
kinematics = newKin;
newQ = newKin->scale();
ids = particles;
sudakov = cit->second.sudakov;
partnerType = type;
}
}
// return empty branching if nothing happened
if(!kinematics) return Branching(ShoKinPtr(), IdList(),SudakovPtr(),
ShowerPartnerType::Undefined);
// if not hard generate phi
kinematics->phi(sudakov->generatePhiForward(particle,ids,kinematics,rho));
// and return it
return Branching(kinematics, ids,sudakov,partnerType);
}
Branching SplittingGenerator::
chooseDecayBranching(ShowerParticle &particle,
const ShowerParticle::EvolutionScales & stoppingScales,
Energy minmass, double enhance,
- ShowerInteraction::Type interaction) const {
+ ShowerInteraction interaction) const {
RhoDMatrix rho(particle.dataPtr()->iSpin());
Energy newQ = Constants::MaxEnergy;
ShoKinPtr kinematics;
SudakovPtr sudakov;
- ShowerPartnerType::Type partnerType(ShowerPartnerType::Undefined);
+ ShowerPartnerType partnerType(ShowerPartnerType::Undefined);
IdList ids;
// First, find the eventual branching, corresponding to the lowest scale.
long index = abs(particle.data().id());
// if no branchings return empty branching struct
if(_fbranchings.find(index) == _fbranchings.end())
return Branching(ShoKinPtr(), IdList(),SudakovPtr(),ShowerPartnerType::Undefined);
// otherwise select branching
for(BranchingList::const_iterator cit = _fbranchings.lower_bound(index);
cit != _fbranchings.upper_bound(index); ++cit) {
// check interaction doesn't change flavour
if(cit->second.particles[1]->id()!=index&&cit->second.particles[2]->id()!=index) continue;
// check either right interaction or doing both
if(!checkInteraction(interaction,cit->second.sudakov->interactionType())) continue;
// whether or not this interaction should be angular ordered
bool angularOrdered = cit->second.sudakov->splittingFn()->angularOrdered();
ShoKinPtr newKin;
IdList particles = particle.id()!=cit->first ? cit->second.conjugateParticles : cit->second.particles;
- ShowerPartnerType::Type type;
+ ShowerPartnerType type;
// work out which starting scale we need
if(cit->second.sudakov->interactionType()==ShowerInteraction::QED) {
type = ShowerPartnerType::QED;
Energy stoppingScale = angularOrdered ? stoppingScales.QED : stoppingScales.QED_noAO;
Energy startingScale = angularOrdered ? particle.scales().QED : particle.scales().QED_noAO;
if(startingScale < stoppingScale ) {
newKin = cit->second.sudakov->
generateNextDecayBranching(startingScale,stoppingScale,minmass,particles,rho,enhance,_deTuning);
}
}
else if(cit->second.sudakov->interactionType()==ShowerInteraction::QCD) {
// special for octets
if(particle.dataPtr()->iColour()==PDT::Colour8) {
// octet -> octet octet
if(cit->second.sudakov->splittingFn()->colourStructure()==OctetOctetOctet) {
Energy stoppingColour = angularOrdered ? stoppingScales.QCD_c : stoppingScales.QCD_c_noAO;
Energy stoppingAnti = angularOrdered ? stoppingScales.QCD_ac : stoppingScales.QCD_ac_noAO;
Energy startingColour = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO;
Energy startingAnti = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO;
type = ShowerPartnerType::QCDColourLine;
if(startingColour<stoppingColour) {
newKin= cit->second.sudakov->
generateNextDecayBranching(startingColour,stoppingColour,minmass,
particles,rho,0.5*enhance,_deTuning);
}
ShoKinPtr newKin2;
if(startingAnti<stoppingAnti) {
newKin2 = cit->second.sudakov->
generateNextDecayBranching(startingAnti,stoppingAnti,minmass,particles,rho,0.5*enhance,_deTuning);
}
// pick the one with the lowest scale
if( (newKin&&newKin2&&newKin2->scale()<newKin->scale()) ||
(!newKin&&newKin2) ) {
newKin = newKin2;
type = ShowerPartnerType::QCDAntiColourLine;
}
}
// other
else {
assert(false);
}
}
// everything else
else {
Energy startingScale,stoppingScale;
if(particle.hasColour()) {
type = ShowerPartnerType::QCDColourLine;
stoppingScale = angularOrdered ? stoppingScales.QCD_c : stoppingScales.QCD_c_noAO;
startingScale = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO;
}
else {
type = ShowerPartnerType::QCDAntiColourLine;
stoppingScale = angularOrdered ? stoppingScales.QCD_ac : stoppingScales.QCD_ac_noAO;
startingScale = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO;
}
if(startingScale < stoppingScale ) {
newKin = cit->second.sudakov->
generateNextDecayBranching(startingScale,stoppingScale,minmass,particles,rho,enhance,_deTuning);
}
}
}
// shouldn't be anything else
else
assert(false);
if(!newKin) continue;
// select highest scale
if(newKin->scale() < newQ ) {
newQ = newKin->scale();
ids = particles;
kinematics=newKin;
sudakov=cit->second.sudakov;
partnerType = type;
}
}
// return empty branching if nothing happened
if(!kinematics) return Branching(ShoKinPtr(), IdList(),SudakovPtr(),
ShowerPartnerType::Undefined);
// and generate phi
kinematics->phi(sudakov->generatePhiDecay(particle,ids,kinematics,rho));
// and return it
return Branching(kinematics, ids,sudakov,partnerType);
}
Branching SplittingGenerator::
chooseBackwardBranching(ShowerParticle &particle,PPtr ,
double enhance,
Ptr<BeamParticleData>::transient_const_pointer beam,
- ShowerInteraction::Type type,
+ ShowerInteraction type,
tcPDFPtr pdf, Energy freeze) const {
RhoDMatrix rho;
bool rhoCalc(false);
Energy newQ=ZERO;
ShoKinPtr kinematics=ShoKinPtr();
- ShowerPartnerType::Type partnerType(ShowerPartnerType::Undefined);
+ ShowerPartnerType partnerType(ShowerPartnerType::Undefined);
SudakovPtr sudakov;
IdList ids;
// First, find the eventual branching, corresponding to the highest scale.
long index = abs(particle.id());
// if no possible branching return
if(_bbranchings.find(index) == _bbranchings.end())
return Branching(ShoKinPtr(), IdList(),SudakovPtr(),ShowerPartnerType::Undefined);
// otherwise select branching
for(BranchingList::const_iterator cit = _bbranchings.lower_bound(index);
cit != _bbranchings.upper_bound(index); ++cit ) {
// check either right interaction or doing both
if(!checkInteraction(type,cit->second.sudakov->interactionType())) continue;
// setup the PDF
cit->second.sudakov->setPDF(pdf,freeze);
//calc rho as needed
if(!rhoCalc) {
rho = particle.extractRhoMatrix(false);
rhoCalc = true;
}
// whether or not this interaction should be angular ordered
bool angularOrdered = cit->second.sudakov->splittingFn()->angularOrdered();
ShoKinPtr newKin;
IdList particles = particle.id()!=cit->first ? cit->second.conjugateParticles : cit->second.particles;
- ShowerPartnerType::Type type;
+ ShowerPartnerType type;
if(cit->second.sudakov->interactionType()==ShowerInteraction::QED) {
type = ShowerPartnerType::QED;
Energy startingScale = angularOrdered ? particle.scales().QED : particle.scales().QED_noAO;
newKin=cit->second.sudakov->
generateNextSpaceBranching(startingScale,particles,particle.x(),rho,enhance,beam,_deTuning);
}
else if(cit->second.sudakov->interactionType()==ShowerInteraction::QCD) {
// special for octets
if(particle.dataPtr()->iColour()==PDT::Colour8) {
// octet -> octet octet
if(cit->second.sudakov->splittingFn()->colourStructure()==OctetOctetOctet) {
type = ShowerPartnerType::QCDColourLine;
Energy startingScale = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO;
newKin = cit->second.sudakov->
generateNextSpaceBranching(startingScale,particles, particle.x(),rho,0.5*enhance,beam,_deTuning);
startingScale = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO;
ShoKinPtr newKin2 = cit->second.sudakov->
generateNextSpaceBranching(startingScale,particles, particle.x(),rho,0.5*enhance,beam,_deTuning);
// pick the one with the highest scale
if( (newKin&&newKin2&&newKin2->scale()>newKin->scale()) ||
(!newKin&&newKin2) ) {
newKin = newKin2;
type = ShowerPartnerType::QCDAntiColourLine;
}
}
else {
Energy startingScale = angularOrdered ?
max(particle.scales().QCD_c , particle.scales().QCD_ac ) :
max(particle.scales().QCD_c_noAO, particle.scales().QCD_ac_noAO);
type = UseRandom::rndbool() ?
ShowerPartnerType::QCDColourLine : ShowerPartnerType::QCDAntiColourLine;
newKin=cit->second.sudakov->
generateNextSpaceBranching(startingScale,particles, particle.x(),rho,enhance,beam,_deTuning);
}
}
// everything else
else {
Energy startingScale;
if(particle.hasColour()) {
type = ShowerPartnerType::QCDColourLine;
startingScale = angularOrdered ? particle.scales().QCD_c : particle.scales().QCD_c_noAO;
}
else {
type = ShowerPartnerType::QCDAntiColourLine;
startingScale = angularOrdered ? particle.scales().QCD_ac : particle.scales().QCD_ac_noAO;
}
newKin=cit->second.sudakov->
generateNextSpaceBranching(startingScale,particles, particle.x(),rho,enhance,beam,_deTuning);
}
}
// shouldn't be anything else
else
assert(false);
// if no kinematics contine
if(!newKin) continue;
// select highest scale
if(newKin->scale() > newQ) {
newQ = newKin->scale();
kinematics=newKin;
ids = particles;
sudakov=cit->second.sudakov;
partnerType = type;
}
}
// return empty branching if nothing happened
if(!kinematics) return Branching(ShoKinPtr(), IdList(),SudakovPtr(),
ShowerPartnerType::Undefined);
// initialize the ShowerKinematics
// and generate phi
kinematics->phi(sudakov->generatePhiBackward(particle,ids,kinematics,rho));
// return the answer
return Branching(kinematics, ids,sudakov,partnerType);
}
void SplittingGenerator::rebind(const TranslationMap & trans) {
BranchingList::iterator cit;
for(cit=_fbranchings.begin();cit!=_fbranchings.end();++cit) {
(cit->second).sudakov=trans.translate((cit->second).sudakov);
for(unsigned int ix=0;ix<(cit->second).particles.size();++ix) {
(cit->second).particles[ix]=trans.translate((cit->second).particles[ix]);
}
for(unsigned int ix=0;ix<(cit->second).conjugateParticles.size();++ix) {
(cit->second).conjugateParticles[ix]=trans.translate((cit->second).conjugateParticles[ix]);
}
}
for(cit=_bbranchings.begin();cit!=_bbranchings.end();++cit) {
(cit->second).sudakov=trans.translate((cit->second).sudakov);
for(unsigned int ix=0;ix<(cit->second).particles.size();++ix) {
(cit->second).particles[ix]=trans.translate((cit->second).particles[ix]);
}
for(unsigned int ix=0;ix<(cit->second).conjugateParticles.size();++ix) {
(cit->second).conjugateParticles[ix]=trans.translate((cit->second).conjugateParticles[ix]);
}
}
Interfaced::rebind(trans);
}
IVector SplittingGenerator::getReferences() {
IVector ret = Interfaced::getReferences();
BranchingList::iterator cit;
for(cit=_fbranchings.begin();cit!=_fbranchings.end();++cit) {
ret.push_back((cit->second).sudakov);
for(unsigned int ix=0;ix<(cit->second).particles.size();++ix)
ret.push_back(const_ptr_cast<tPDPtr>((cit->second).particles[ix]));
for(unsigned int ix=0;ix<(cit->second).conjugateParticles.size();++ix)
ret.push_back(const_ptr_cast<tPDPtr>((cit->second).conjugateParticles[ix]));
}
for(cit=_bbranchings.begin();cit!=_bbranchings.end();++cit) {
ret.push_back((cit->second).sudakov);
for(unsigned int ix=0;ix<(cit->second).particles.size();++ix)
ret.push_back(const_ptr_cast<tPDPtr>((cit->second).particles[ix]));
for(unsigned int ix=0;ix<(cit->second).conjugateParticles.size();++ix)
ret.push_back(const_ptr_cast<tPDPtr>((cit->second).conjugateParticles[ix]));
}
return ret;
}
void SplittingGenerator::factorizationScaleFactor(double f) {
BranchingList::iterator cit;
for(cit=_fbranchings.begin();cit!=_fbranchings.end();++cit)
{(cit->second).sudakov->factorizationScaleFactor(f);}
for(cit=_bbranchings.begin();cit!=_bbranchings.end();++cit)
{(cit->second).sudakov->factorizationScaleFactor(f);}
}
void SplittingGenerator::renormalizationScaleFactor(double f) {
BranchingList::iterator cit;
for(cit=_fbranchings.begin();cit!=_fbranchings.end();++cit)
{(cit->second).sudakov->renormalizationScaleFactor(f);}
for(cit=_bbranchings.begin();cit!=_bbranchings.end();++cit)
{(cit->second).sudakov->renormalizationScaleFactor(f);}
}
diff --git a/Shower/QTilde/SplittingFunctions/SplittingGenerator.h b/Shower/QTilde/SplittingFunctions/SplittingGenerator.h
--- a/Shower/QTilde/SplittingFunctions/SplittingGenerator.h
+++ b/Shower/QTilde/SplittingFunctions/SplittingGenerator.h
@@ -1,330 +1,330 @@
// -*- C++ -*-
//
// SplittingGenerator.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_SplittingGenerator_H
#define HERWIG_SplittingGenerator_H
//
// This is the declaration of the SplittingGenerator class.
//
#include "ThePEG/Interface/Interfaced.h"
#include "Herwig/Shower/QTilde/Base/Branching.h"
#include "Herwig/Shower/QTilde/Base/SudakovFormFactor.h"
#include "SplittingGenerator.fh"
#include "Herwig/Shower/QTilde/Base/ShowerParticle.h"
#include "Herwig/Shower/QTilde/Base/ShowerKinematics.h"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
*
* This class is responsible for creating, at the beginning of the Run,
* all the SplittingFunction objects and the corresponding
* SudakovFormFactor objects, and then of the generation of splittings
* (radiation emissions) during the event.
* Many switches are defined in this class which allowed the user to turn on/off:
* - each type of interaction (QCD, QED, EWK,...);
* - initial- and final-state radiation for all type of interactions;
* - initial- and final-state radiation for each type of interaction;
* - each type of splitting (\f$u\to ug\f$, \f$d\to dg\f$, \f$\ldots\f$,
* \f$g\to gg\f$, \f$g\to u\bar{u}\f$, \f$\ldots\f$).
*
* These switches are useful mainly for debugging, but eventually can
* also be used for a "quick and dirty" estimation of systematic errors.
*
* In the future it should be possible to implement in this class
*
* - the \f$1\to2\f$ azimuthal correlations for soft emission due to QCD coherence
* using the ShowerParticle object provided in the input.
* - Similarly having the \f$\rho-D\f$ matrix and the SplittingFunction pointer
* it should be possible to implement the spin correlations.
*
* @see SudakovFormFactor
* @see SplitFun
*
* @see \ref SplittingGeneratorInterfaces "The interfaces"
* defined for SplittingGenerator.
*/
class SplittingGenerator: public Interfaced {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
SplittingGenerator() : _deTuning(1.) {}
//@}
public:
/**
* Methods to select the next branching and reconstruct the kinematics
*/
//@{
/**
* Choose a new forward branching for a time-like particle
* The method returns:
* - a pointer to a ShowerKinematics object, which
* contains the information about the new scale and all other
* kinematics variables that need to be generated simultaneously;
* - a pointer to the SudakovFormFactor object associated
* with the chosen emission.
* - The PDG codes of the particles in the branching,
* as a Branching struct.
*
* In the case no branching has been generated, both the returned
* pointers are null ( ShoKinPtr() , tSudakovFFPtr() ).
*
* @param particle The particle to be evolved
* @param enhance The factor by which to ehnace the emission of radiation
* @param type The type of interaction to generate
* @return The Branching struct for the branching
*/
Branching chooseForwardBranching(ShowerParticle & particle,
double enhance,
- ShowerInteraction::Type type) const;
+ ShowerInteraction type) const;
/**
* Select the next branching of a particles for the initial-state shower
* in the particle's decay.
* @param particle The particle being showerwed
* @param maxscale The maximum scale
* @param minmass Minimum mass of the particle after the branching
* @param enhance The factor by which to ehnace the emission of radiation
* @param type The type of interaction to generate
* @return The Branching struct for the branching
*/
Branching chooseDecayBranching(ShowerParticle & particle,
const ShowerParticle::EvolutionScales & maxScales,
Energy minmass,double enhance,
- ShowerInteraction::Type type) const;
+ ShowerInteraction type) const;
/**
* Choose a new backward branching for a space-like particle.
* The method returns:
* - a pointer to a ShowerKinematics object, which
* contains the information about the new scale and all other
* kinematics variables that need to be generated simultaneously;
* - a pointer to the SudakovFormFactor object associated
* with the chosen emission.
* - The PDG codes of the particles in the branching,
* as a Branching struct.
*
* In the case no branching has been generated, both the returned
* pointers are null ( ShoKinPtr() , tSudakovFFPtr() ).
*
* @param particle The particle to be evolved
* @param enhance The factor by which to ehnace the emission of radiation
* @param beamparticle The beam particle
* @param beam The BeamParticleData object
* @param type The type of interaction to generate
* @return The Branching struct for the branching
*/
Branching
chooseBackwardBranching(ShowerParticle & particle,
PPtr beamparticle,
double enhance,
Ptr<BeamParticleData>::transient_const_pointer beam,
- ShowerInteraction::Type type,
+ ShowerInteraction type,
tcPDFPtr , Energy ) const;
//@}
public:
/**
* Methods to parse the information from the input files to create the
* branchings
*/
//@{
/**
* Add a final-state splitting
*/
string addFinalSplitting(string arg) { return addSplitting(arg,true); }
/**
* Add an initial-state splitting
*/
string addInitialSplitting(string arg) { return addSplitting(arg,false); }
/**
* Add a final-state splitting
*/
string deleteFinalSplitting(string arg) { return deleteSplitting(arg,true); }
/**
* Add an initial-state splitting
*/
string deleteInitialSplitting(string arg) { return deleteSplitting(arg,false); }
//@}
/**
* Access to the splittings
*/
//@{
/**
* Access the final-state branchings
*/
const BranchingList & finalStateBranchings() const { return _fbranchings; }
/**
* Access the initial-state branchings
*/
const BranchingList & initialStateBranchings() const { return _bbranchings; }
//@}
/**
* Set the factorization scale factor
*/
void factorizationScaleFactor(double f);
/**
* Set the renormalization scale factor
*/
void renormalizationScaleFactor(double f);
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;
//@}
protected:
/** @name Standard Interfaced functions. */
//@{
/**
* Rebind pointer to other Interfaced objects. Called in the setup phase
* after all objects used in an EventGenerator has been cloned so that
* the pointers will refer to the cloned objects afterwards.
* @param trans a TranslationMap relating the original objects to
* their respective clones.
* @throws RebindException if no cloned object was found for a given
* pointer.
*/
virtual void rebind(const TranslationMap & trans)
;
/**
* Return a vector of all pointers to Interfaced objects used in this
* object.
* @return a vector of pointers.
*/
virtual IVector getReferences();
//@}
private:
/**
* Add a branching to the map
* @param ids PDG coeds of the particles in the branching
* @param sudakov The SudakovFormFactor for the branching
* @param final Whether this is an initial- or final-state branching
*/
void addToMap(const IdList & ids, const SudakovPtr & sudakov, bool final);
/**
* Remove a branching to the map
* @param ids PDG coeds of the particles in the branching
* @param sudakov The SudakovFormFactor for the branching
* @param final Whether this is an initial- or final-state branching
*/
void deleteFromMap(const IdList & ids, const SudakovPtr & sudakov, bool final);
/**
* Obtain the reference vectors for a final-state particle
* @param particle The particle
* @param p The p reference vector
* @param n The n reference vector
*/
void finalStateBasisVectors(ShowerParticle particle, Lorentz5Momentum & p,
Lorentz5Momentum & n) const;
/**
* Add a splitting
* @param in string to be parsed
* @param final Whether this is an initial- or final-state branching
*/
string addSplitting(string in ,bool final);
/**
* Delete a splitting
* @param in string to be parsed
* @param final Whether this is an initial- or final-state branching
*/
string deleteSplitting(string in ,bool final);
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
SplittingGenerator & operator=(const SplittingGenerator &);
private:
/**
* List of the branchings and the appropriate Sudakovs for forward branchings
*/
BranchingList _fbranchings;
/**
* Lists of the branchings and the appropriate Sudakovs for backward branchings.
*/
BranchingList _bbranchings;
/**
* The detuning parameter
*/
double _deTuning;
};
}
#endif /* HERWIG_SplittingGenerator_H */
diff --git a/Shower/RealEmissionProcess.h b/Shower/RealEmissionProcess.h
--- a/Shower/RealEmissionProcess.h
+++ b/Shower/RealEmissionProcess.h
@@ -1,245 +1,245 @@
// -*- C++ -*-
//
// RealEmissionProcess.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_RealEmissionProcess_H
#define HERWIG_RealEmissionProcess_H
#include "ThePEG/Config/ThePEG.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/EventRecord/SubProcess.h"
#include "ThePEG/Handlers/XComb.h"
#include "ThePEG/Config/Pointers.h"
#include "RealEmissionProcess.fh"
#include "Herwig/Shower/QTilde/ShowerInteraction.h"
namespace Herwig {
using namespace ThePEG;
/**
* Simple struct for hard processes and decays
*/
class RealEmissionProcess : public Base {
friend ostream & operator<<(ostream & os, const RealEmissionProcess & proc);
public:
/**
* The incoming particles
*/
ParticleVector & incoming() {
return incoming_;
}
/**
* The outgoing particles
*/
ParticleVector & outgoing() {
return outgoing_;
}
public:
/**
* The incoming particles
*/
ParticleVector & bornIncoming() {
return bornIncoming_;
}
/**
* The outgoing particles
*/
ParticleVector & bornOutgoing() {
return bornOutgoing_;
}
/**
* The hadrons
*/
ParticleVector & hadrons() {
return hadrons_;
}
public:
/**
* The emitter
*/
unsigned int emitter () const {return emitter_;}
/**
* The spectator
*/
unsigned int spectator() const {return spectator_;}
/**
* The emitted
*/
unsigned int emitted () const {return emitted_;}
/**
* The emitter
*/
void emitter (unsigned int in) {emitter_=in;}
/**
* The spectator
*/
void spectator(unsigned int in) {spectator_=in;}
/**
* The emitted
*/
void emitted (unsigned int in) {emitted_=in;}
public:
/**
* Lorentz Rotation to final-state for II dipoles
*/
LorentzRotation transformation() const { return trans_;}
/**
* Lorentz Rotation to final-state for II dipoles
*/
void transformation(LorentzRotation in) {trans_=in;}
public:
/**
* Get the x values
*/
pair<double,double> x() const {return x_;}
/**
* Set the x values
*/
void x(pair<double,double> in) {x_=in;}
public:
/**
* Type of interaction
*/
- ShowerInteraction::Type interaction() {return interaction_;}
+ ShowerInteraction interaction() {return interaction_;}
/**
* Type of interaction
*/
- void interaction(ShowerInteraction::Type in) {interaction_ = in;}
+ void interaction(ShowerInteraction in) {interaction_ = in;}
/**
* Emission scales
*/
- map<ShowerInteraction::Type,Energy> & pT() {return pT_;}
+ map<ShowerInteraction,Energy> & pT() {return pT_;}
private:
/**
* The emitter
*/
unsigned int emitter_;
/**
* The spectator
*/
unsigned int spectator_;
/**
* The emitter
*/
unsigned int emitted_;
private:
/**
* The incoming particles
*/
ParticleVector incoming_;
/*
* The outgoing particles
*/
ParticleVector outgoing_;
private:
/**
* The hadrons
*/
ParticleVector hadrons_;
private:
/**
* Incoming for the Born process
*/
ParticleVector bornIncoming_;
/**
* Outgoing for the Born process
*/
ParticleVector bornOutgoing_;
private:
/**
* Lorentz transformation for spectators in II
*/
LorentzRotation trans_;
/**
* x values
*/
pair<double,double> x_;
private:
/**
* Type of interaction
*/
- ShowerInteraction::Type interaction_;
+ ShowerInteraction interaction_;
/**
* Emission scales
*/
- map<ShowerInteraction::Type,Energy> pT_;
+ map<ShowerInteraction,Energy> pT_;
};
/**
* Output to a stream
*/
inline ostream & operator<<(ostream & os, const RealEmissionProcess & proc) {
os << "REAL EMISSION "
<< proc.emitter_ << " "
<< proc.spectator_ << " "
<< proc.emitted_ << "\n";
os << "BORN\n";
for(unsigned int ix=0;ix<proc.bornIncoming_.size();++ix)
os << proc.bornIncoming_[ix]->colourLine() << " "
<< proc.bornIncoming_[ix]->antiColourLine() << " "
<< *proc.bornIncoming_[ix] << "\n";
for(unsigned int ix=0;ix<proc.bornOutgoing_.size();++ix)
os << proc.bornOutgoing_[ix]->colourLine() << " "
<< proc.bornOutgoing_[ix]->antiColourLine() << " "
<< *proc.bornOutgoing_[ix] << "\n";
os << "REAL\n";
for(unsigned int ix=0;ix<proc.incoming_.size();++ix)
os << proc.incoming_[ix]->colourLine() << " "
<< proc.incoming_[ix]->antiColourLine() << " "
<< *proc.incoming_[ix] << "\n";
for(unsigned int ix=0;ix<proc.outgoing_.size();++ix)
os << proc.outgoing_[ix]->colourLine() << " "
<< proc.outgoing_[ix]->antiColourLine() << " "
<< *proc.outgoing_[ix] << "\n";
return os;
}
}
#endif
diff --git a/Tests/BuildbotTest/Top-DipoleLO.in b/Tests/BuildbotTest/Top-DipoleLO.in
new file mode 100644
--- /dev/null
+++ b/Tests/BuildbotTest/Top-DipoleLO.in
@@ -0,0 +1,158 @@
+# -*- ThePEG-repository -*-
+
+##################################################
+## Herwig/Matchbox example input file
+##################################################
+
+##################################################
+## Collider type
+##################################################
+
+read Matchbox/PPCollider.in
+
+##################################################
+## Beam energy sqrt(s)
+##################################################
+
+cd /Herwig/EventHandlers
+set EventHandler:LuminosityFunction:Energy 7000*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 2
+set Factory:OrderInAlphaEW 0
+
+## Select the process
+## You may use identifiers such as p, pbar, j, l, mu+, h0 etc.
+do Factory:Process p p -> t tbar
+
+## Special settings required for on-shell production of unstable particles
+## enable for on-shell top production
+read Matchbox/OnShellTopProduction.in
+#read Matchbox/PQCDLevel.in
+## enable for on-shell W, Z or h production
+# read Matchbox/OnShellWProduction.in
+# read Matchbox/OnShellZProduction.in
+# read Matchbox/OnShellHProduction.in
+# Special settings for the VBF approximation
+# read Matchbox/VBFDiagramsOnly.in
+
+##################################################
+## Matrix element library selection
+##################################################
+
+## Select a generic tree/loop combination or a
+## specialized NLO package
+
+# read Matchbox/MadGraph-GoSam.in
+read Matchbox/MadGraph-MadGraph.in
+# read Matchbox/MadGraph-NJet.in
+# read Matchbox/MadGraph-OpenLoops.in
+# read Matchbox/HJets.in
+# read Matchbox/VBFNLO.in
+
+## Uncomment this to use ggh effective couplings
+## currently only supported by MadGraph-GoSam
+
+# read Matchbox/HiggsEffective.in
+
+##################################################
+## Cut selection
+## See the documentation for more options
+##################################################
+
+set /Herwig/Cuts/ChargedLeptonPairMassCut:MinMass 60*GeV
+set /Herwig/Cuts/ChargedLeptonPairMassCut:MaxMass 120*GeV
+
+## cuts on additional jets
+
+# read Matchbox/DefaultPPJets.in
+
+# insert JetCuts:JetRegions 0 FirstJet
+# insert JetCuts:JetRegions 1 SecondJet
+# insert JetCuts:JetRegions 2 ThirdJet
+# insert JetCuts:JetRegions 3 FourthJet
+
+##################################################
+## Scale choice
+## See the documentation for more options
+##################################################
+
+cd /Herwig/MatrixElements/Matchbox
+set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/TopPairMassScale
+
+##################################################
+## Matching and shower selection
+## Please also see flavour scheme settings
+## towards the end of the input file.
+##################################################
+
+#read Matchbox/MCatNLO-DefaultShower.in
+# read Matchbox/Powheg-DefaultShower.in
+## use for strict LO/NLO comparisons
+# read Matchbox/MCatLO-DefaultShower.in
+## use for improved LO showering
+# read Matchbox/LO-DefaultShower.in
+
+# read Matchbox/MCatNLO-DipoleShower.in
+# read Matchbox/Powheg-DipoleShower.in
+## use for strict LO/NLO comparisons
+# read Matchbox/MCatLO-DipoleShower.in
+## use for improved LO showering
+read Matchbox/LO-DipoleShower.in
+
+# read Matchbox/NLO-NoShower.in
+# read Matchbox/LO-NoShower.in
+
+##################################################
+## Scale uncertainties
+##################################################
+
+# read Matchbox/MuDown.in
+# read Matchbox/MuUp.in
+
+##################################################
+## Shower scale uncertainties
+##################################################
+
+# read Matchbox/MuQDown.in
+# read Matchbox/MuQUp.in
+
+##################################################
+## PDF choice
+##################################################
+
+read Matchbox/FiveFlavourScheme.in
+## required for dipole shower and fixed order in five flavour scheme
+# read Matchbox/FiveFlavourNoBMassScheme.in
+read Matchbox/MMHT2014.in
+
+##################################################
+## Analyses
+##################################################
+
+cd /Herwig/Analysis
+insert Rivet:Analyses 0 MC_TTBAR
+insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 Rivet
+# insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 HepMC
+
+##################################################
+## Save the generator
+##################################################
+
+do /Herwig/MatrixElements/Matchbox/Factory:ProductionMode
+
+cd /Herwig/Generators
+saverun Top-DipoleLO EventGenerator
diff --git a/Tests/BuildbotTest/VBF-DipoleLO-almostUnweighted.in b/Tests/BuildbotTest/VBF-DipoleLO-almostUnweighted.in
new file mode 100644
--- /dev/null
+++ b/Tests/BuildbotTest/VBF-DipoleLO-almostUnweighted.in
@@ -0,0 +1,162 @@
+# -*- ThePEG-repository -*-
+
+##################################################
+## Herwig/Matchbox example input file
+##################################################
+
+##################################################
+## Collider type
+##################################################
+
+read Matchbox/PPCollider.in
+
+##################################################
+## Beam energy sqrt(s)
+##################################################
+
+cd /Herwig/EventHandlers
+set EventHandler:LuminosityFunction:Energy 7000*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 0
+set Factory:OrderInAlphaEW 3
+
+## Select the process
+## You may use identifiers such as p, pbar, j, l, mu+, h0 etc.
+do Factory:Process p p -> W+ j j
+
+## Special settings required for on-shell production of unstable particles
+## enable for on-shell top production
+#read Matchbox/OnShellTopProduction.in
+#read Matchbox/PQCDLevel.in
+## enable for on-shell W, Z or h production
+ read Matchbox/OnShellWProduction.in
+# read Matchbox/OnShellZProduction.in
+# read Matchbox/OnShellHProduction.in
+# Special settings for the VBF approximation
+# read Matchbox/VBFDiagramsOnly.in
+
+##################################################
+## Matrix element library selection
+##################################################
+
+## Select a generic tree/loop combination or a
+## specialized NLO package
+
+# read Matchbox/MadGraph-GoSam.in
+read Matchbox/MadGraph-MadGraph.in
+# read Matchbox/MadGraph-NJet.in
+# read Matchbox/MadGraph-OpenLoops.in
+# read Matchbox/HJets.in
+# read Matchbox/VBFNLO.in
+
+## Uncomment this to use ggh effective couplings
+## currently only supported by MadGraph-GoSam
+
+# read Matchbox/HiggsEffective.in
+
+##################################################
+## Cut selection
+## See the documentation for more options
+##################################################
+
+set /Herwig/Cuts/ChargedLeptonPairMassCut:MinMass 60*GeV
+set /Herwig/Cuts/ChargedLeptonPairMassCut:MaxMass 120*GeV
+
+## cuts on additional jets
+
+ read Matchbox/DefaultPPJets.in
+
+ insert JetCuts:JetRegions 0 FirstJet
+ insert JetCuts:JetRegions 1 SecondJet
+# insert JetCuts:JetRegions 2 ThirdJet
+# insert JetCuts:JetRegions 3 FourthJet
+
+##################################################
+## Scale choice
+## See the documentation for more options
+##################################################
+
+cd /Herwig/MatrixElements/Matchbox
+set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale
+
+##################################################
+## Matching and shower selection
+## Please also see flavour scheme settings
+## towards the end of the input file.
+##################################################
+
+#read Matchbox/MCatNLO-DefaultShower.in
+# read Matchbox/Powheg-DefaultShower.in
+## use for strict LO/NLO comparisons
+# read Matchbox/MCatLO-DefaultShower.in
+## use for improved LO showering
+# read Matchbox/LO-DefaultShower.in
+
+# read Matchbox/MCatNLO-DipoleShower.in
+# read Matchbox/Powheg-DipoleShower.in
+## use for strict LO/NLO comparisons
+# read Matchbox/MCatLO-DipoleShower.in
+## use for improved LO showering
+read Matchbox/LO-DipoleShower.in
+
+# read Matchbox/NLO-NoShower.in
+# read Matchbox/LO-NoShower.in
+
+##################################################
+## Scale uncertainties
+##################################################
+
+# read Matchbox/MuDown.in
+# read Matchbox/MuUp.in
+
+##################################################
+## Shower scale uncertainties
+##################################################
+
+# read Matchbox/MuQDown.in
+# read Matchbox/MuQUp.in
+
+##################################################
+## PDF choice
+##################################################
+
+read Matchbox/FiveFlavourScheme.in
+## required for dipole shower and fixed order in five flavour scheme
+# read Matchbox/FiveFlavourNoBMassScheme.in
+read Matchbox/MMHT2014.in
+
+##################################################
+## Analyses
+##################################################
+
+cd /Herwig/Analysis
+insert Rivet:Analyses 0 MC_WINC
+insert Rivet:Analyses 0 MC_WJETS
+ insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 Rivet
+# insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 HepMC
+
+##################################################
+## Save the generator
+##################################################
+
+set /Herwig/Samplers/Sampler:AlmostUnweighted On
+
+
+do /Herwig/MatrixElements/Matchbox/Factory:ProductionMode
+
+cd /Herwig/Generators
+saverun VBF-DipoleLO-almostUnweighted EventGenerator
diff --git a/Tests/BuildbotTest/VBF-DipoleLO.in b/Tests/BuildbotTest/VBF-DipoleLO.in
new file mode 100644
--- /dev/null
+++ b/Tests/BuildbotTest/VBF-DipoleLO.in
@@ -0,0 +1,159 @@
+# -*- ThePEG-repository -*-
+
+##################################################
+## Herwig/Matchbox example input file
+##################################################
+
+##################################################
+## Collider type
+##################################################
+
+read Matchbox/PPCollider.in
+
+##################################################
+## Beam energy sqrt(s)
+##################################################
+
+cd /Herwig/EventHandlers
+set EventHandler:LuminosityFunction:Energy 7000*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 0
+set Factory:OrderInAlphaEW 3
+
+## Select the process
+## You may use identifiers such as p, pbar, j, l, mu+, h0 etc.
+do Factory:Process p p -> W+ j j
+
+## Special settings required for on-shell production of unstable particles
+## enable for on-shell top production
+#read Matchbox/OnShellTopProduction.in
+#read Matchbox/PQCDLevel.in
+## enable for on-shell W, Z or h production
+ read Matchbox/OnShellWProduction.in
+# read Matchbox/OnShellZProduction.in
+# read Matchbox/OnShellHProduction.in
+# Special settings for the VBF approximation
+# read Matchbox/VBFDiagramsOnly.in
+
+##################################################
+## Matrix element library selection
+##################################################
+
+## Select a generic tree/loop combination or a
+## specialized NLO package
+
+# read Matchbox/MadGraph-GoSam.in
+read Matchbox/MadGraph-MadGraph.in
+# read Matchbox/MadGraph-NJet.in
+# read Matchbox/MadGraph-OpenLoops.in
+# read Matchbox/HJets.in
+# read Matchbox/VBFNLO.in
+
+## Uncomment this to use ggh effective couplings
+## currently only supported by MadGraph-GoSam
+
+# read Matchbox/HiggsEffective.in
+
+##################################################
+## Cut selection
+## See the documentation for more options
+##################################################
+
+set /Herwig/Cuts/ChargedLeptonPairMassCut:MinMass 60*GeV
+set /Herwig/Cuts/ChargedLeptonPairMassCut:MaxMass 120*GeV
+
+## cuts on additional jets
+
+ read Matchbox/DefaultPPJets.in
+
+ insert JetCuts:JetRegions 0 FirstJet
+ insert JetCuts:JetRegions 1 SecondJet
+# insert JetCuts:JetRegions 2 ThirdJet
+# insert JetCuts:JetRegions 3 FourthJet
+
+##################################################
+## Scale choice
+## See the documentation for more options
+##################################################
+
+cd /Herwig/MatrixElements/Matchbox
+set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale
+
+##################################################
+## Matching and shower selection
+## Please also see flavour scheme settings
+## towards the end of the input file.
+##################################################
+
+#read Matchbox/MCatNLO-DefaultShower.in
+# read Matchbox/Powheg-DefaultShower.in
+## use for strict LO/NLO comparisons
+# read Matchbox/MCatLO-DefaultShower.in
+## use for improved LO showering
+# read Matchbox/LO-DefaultShower.in
+
+# read Matchbox/MCatNLO-DipoleShower.in
+# read Matchbox/Powheg-DipoleShower.in
+## use for strict LO/NLO comparisons
+# read Matchbox/MCatLO-DipoleShower.in
+## use for improved LO showering
+read Matchbox/LO-DipoleShower.in
+
+# read Matchbox/NLO-NoShower.in
+# read Matchbox/LO-NoShower.in
+
+##################################################
+## Scale uncertainties
+##################################################
+
+# read Matchbox/MuDown.in
+# read Matchbox/MuUp.in
+
+##################################################
+## Shower scale uncertainties
+##################################################
+
+# read Matchbox/MuQDown.in
+# read Matchbox/MuQUp.in
+
+##################################################
+## PDF choice
+##################################################
+
+read Matchbox/FiveFlavourScheme.in
+## required for dipole shower and fixed order in five flavour scheme
+# read Matchbox/FiveFlavourNoBMassScheme.in
+read Matchbox/MMHT2014.in
+
+##################################################
+## Analyses
+##################################################
+
+cd /Herwig/Analysis
+insert Rivet:Analyses 0 MC_WINC
+insert Rivet:Analyses 0 MC_WJETS
+ insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 Rivet
+# insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 HepMC
+
+##################################################
+## Save the generator
+##################################################
+
+do /Herwig/MatrixElements/Matchbox/Factory:ProductionMode
+
+cd /Herwig/Generators
+saverun VBF-DipoleLO EventGenerator
diff --git a/Tests/BuildbotTest/Zjj-DipoleLO.in b/Tests/BuildbotTest/Zjj-DipoleLO.in
new file mode 100644
--- /dev/null
+++ b/Tests/BuildbotTest/Zjj-DipoleLO.in
@@ -0,0 +1,159 @@
+# -*- ThePEG-repository -*-
+
+##################################################
+## Herwig/Matchbox example input file
+##################################################
+
+##################################################
+## Collider type
+##################################################
+
+read Matchbox/PPCollider.in
+
+##################################################
+## Beam energy sqrt(s)
+##################################################
+
+cd /Herwig/EventHandlers
+set EventHandler:LuminosityFunction:Energy 7000*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 2
+set Factory:OrderInAlphaEW 1
+
+## Select the process
+## You may use identifiers such as p, pbar, j, l, mu+, h0 etc.
+do Factory:Process p p -> Z0 j j
+
+## Special settings required for on-shell production of unstable particles
+## enable for on-shell top production
+#read Matchbox/OnShellTopProduction.in
+#read Matchbox/PQCDLevel.in
+## enable for on-shell W, Z or h production
+# read Matchbox/OnShellWProduction.in
+ read Matchbox/OnShellZProduction.in
+# read Matchbox/OnShellHProduction.in
+# Special settings for the VBF approximation
+# read Matchbox/VBFDiagramsOnly.in
+
+##################################################
+## Matrix element library selection
+##################################################
+
+## Select a generic tree/loop combination or a
+## specialized NLO package
+
+# read Matchbox/MadGraph-GoSam.in
+read Matchbox/MadGraph-MadGraph.in
+# read Matchbox/MadGraph-NJet.in
+# read Matchbox/MadGraph-OpenLoops.in
+# read Matchbox/HJets.in
+# read Matchbox/VBFNLO.in
+
+## Uncomment this to use ggh effective couplings
+## currently only supported by MadGraph-GoSam
+
+# read Matchbox/HiggsEffective.in
+
+##################################################
+## Cut selection
+## See the documentation for more options
+##################################################
+
+set /Herwig/Cuts/ChargedLeptonPairMassCut:MinMass 60*GeV
+set /Herwig/Cuts/ChargedLeptonPairMassCut:MaxMass 120*GeV
+
+## cuts on additional jets
+
+ read Matchbox/DefaultPPJets.in
+
+ insert JetCuts:JetRegions 0 FirstJet
+ insert JetCuts:JetRegions 1 SecondJet
+# insert JetCuts:JetRegions 2 ThirdJet
+# insert JetCuts:JetRegions 3 FourthJet
+
+##################################################
+## Scale choice
+## See the documentation for more options
+##################################################
+
+cd /Herwig/MatrixElements/Matchbox
+set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale
+
+##################################################
+## Matching and shower selection
+## Please also see flavour scheme settings
+## towards the end of the input file.
+##################################################
+
+#read Matchbox/MCatNLO-DefaultShower.in
+# read Matchbox/Powheg-DefaultShower.in
+## use for strict LO/NLO comparisons
+# read Matchbox/MCatLO-DefaultShower.in
+## use for improved LO showering
+# read Matchbox/LO-DefaultShower.in
+
+# read Matchbox/MCatNLO-DipoleShower.in
+# read Matchbox/Powheg-DipoleShower.in
+## use for strict LO/NLO comparisons
+# read Matchbox/MCatLO-DipoleShower.in
+## use for improved LO showering
+read Matchbox/LO-DipoleShower.in
+
+# read Matchbox/NLO-NoShower.in
+# read Matchbox/LO-NoShower.in
+
+##################################################
+## Scale uncertainties
+##################################################
+
+# read Matchbox/MuDown.in
+# read Matchbox/MuUp.in
+
+##################################################
+## Shower scale uncertainties
+##################################################
+
+# read Matchbox/MuQDown.in
+# read Matchbox/MuQUp.in
+
+##################################################
+## PDF choice
+##################################################
+
+read Matchbox/FiveFlavourScheme.in
+## required for dipole shower and fixed order in five flavour scheme
+# read Matchbox/FiveFlavourNoBMassScheme.in
+read Matchbox/MMHT2014.in
+
+##################################################
+## Analyses
+##################################################
+
+cd /Herwig/Analysis
+insert Rivet:Analyses 0 MC_ZINC
+insert Rivet:Analyses 0 MC_ZJETS
+ insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 Rivet
+# insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 HepMC
+
+##################################################
+## Save the generator
+##################################################
+
+do /Herwig/MatrixElements/Matchbox/Factory:ProductionMode
+
+cd /Herwig/Generators
+saverun Zjj-DipoleLO EventGenerator
diff --git a/Tests/ExternNLO/Buildin.in b/Tests/ExternNLO/Buildin.in
new file mode 100644
--- /dev/null
+++ b/Tests/ExternNLO/Buildin.in
@@ -0,0 +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+ e- j
+
+
+#read Matchbox/MadGraph-MadGraph.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/FiveFlavourNoBMassScheme.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 Buildin EventGenerator
diff --git a/Tests/ExternNLO/GoSam.in b/Tests/ExternNLO/GoSam.in
new file mode 100644
--- /dev/null
+++ b/Tests/ExternNLO/GoSam.in
@@ -0,0 +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+ 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/MadGraph.in b/Tests/ExternNLO/MadGraph.in
new file mode 100644
--- /dev/null
+++ b/Tests/ExternNLO/MadGraph.in
@@ -0,0 +1,64 @@
+# -*- 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+ e- j
+
+read Matchbox/MadGraph-MadGraph.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/FiveFlavourNoBMassScheme.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 MadGraph EventGenerator
diff --git a/Tests/ExternNLO/NJet.in b/Tests/ExternNLO/NJet.in
new file mode 100644
--- /dev/null
+++ b/Tests/ExternNLO/NJet.in
@@ -0,0 +1,64 @@
+# -*- 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+ e- j
+
+read Matchbox/NJet-NJet.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/FiveFlavourNoBMassScheme.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 NJet EventGenerator
diff --git a/Tests/ExternNLO/OpenLoops.in b/Tests/ExternNLO/OpenLoops.in
new file mode 100644
--- /dev/null
+++ b/Tests/ExternNLO/OpenLoops.in
@@ -0,0 +1,67 @@
+# -*- 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+ e- j
+
+read Matchbox/OpenLoops-OpenLoops.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/FiveFlavourNoBMassScheme.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 OpenLoops 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/Tests/LHE/LHE-WZ-Dipole.in b/Tests/LHE/LHE-WZ-Dipole.in
new file mode 100644
--- /dev/null
+++ b/Tests/LHE/LHE-WZ-Dipole.in
@@ -0,0 +1,67 @@
+#
+mkdir LesHouches
+cd LesHouches
+library LesHouches.so
+cd /Herwig/EventHandlers
+
+
+create ThePEG::LesHouchesFileReader Reader2 LesHouches.so
+set Reader2:FileName PPEE.lhe
+set Reader2:BeamA 2212
+set Reader2:BeamB -2212
+set Reader2:EBeamA 3500.0
+set Reader2:EBeamB 3500.0
+set Reader2:PDFA /Herwig/Partons/ShowerLOPDF
+set Reader2:PDFB /Herwig/Partons/ShowerLOPDF
+create ThePEG::Cuts QCDCuts
+set QCDCuts:ScaleMin 1.0*GeV
+set QCDCuts:X1Min 0.00001
+set QCDCuts:X2Min 0.00001
+set QCDCuts:MHatMin 20.*GeV
+set QCDCuts:X1Max 0.9
+set QCDCuts:X2Max 0.9
+create ThePEG::LesHouchesEventHandler LesHouchesHandler
+insert LesHouchesHandler:LesHouchesReaders[0] Reader2
+set LesHouchesHandler:PartonExtractor /Herwig/Partons/QCDExtractor
+set LesHouchesHandler:StatLevel 2
+set LesHouchesHandler:CascadeHandler /Herwig/DipoleShower/DipoleShowerHandler
+insert LesHouchesHandler:PreCascadeHandlers[0] /Herwig/Decays/DecayHandler
+set LesHouchesHandler:HadronizationHandler /Herwig/Hadronization/ClusterHadHandler
+set LesHouchesHandler:DecayHandler /Herwig/Decays/DecayHandler
+set LesHouchesHandler:WeightOption NegUnitWeight
+
+cd /Herwig/Cuts
+set JetKtCut:MinKT 0.0*GeV
+
+cd /Herwig/Generators
+create ThePEG::EventGenerator MGGenerator
+set MGGenerator:RandomNumberGenerator /Herwig/Random
+set MGGenerator:StandardModelParameters /Herwig/Model
+set MGGenerator:EventHandler /Herwig/EventHandlers/LesHouchesHandler
+
+cd /Herwig/Generators
+set MGGenerator:EventHandler:Cuts /Herwig/Cuts/QCDCuts
+
+
+cd /Herwig/Analysis
+create ThePEG::RivetAnalysis RivetAnalysis RivetAnalysis.so
+
+# General analysis
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 MC_ZINC
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 MC_ZJETS
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 MC_WINC
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 MC_WJETS
+
+
+insert /Herwig/Generators/MGGenerator:AnalysisHandlers 0 RivetAnalysis
+
+cd /Herwig/Generators/
+set MGGenerator:NumberOfEvents 1000000
+set MGGenerator:RandomNumberGenerator:Seed 31122001
+set MGGenerator:PrintEvent 10
+set MGGenerator:MaxErrors 100000000
+#set MGGenerator:EventHandler:CascadeHandler:MPIHandler NULL
+#
+saverun LHE MGGenerator
+
+
diff --git a/Tests/LHE/LHE-WZ.in b/Tests/LHE/LHE-WZ.in
new file mode 100644
--- /dev/null
+++ b/Tests/LHE/LHE-WZ.in
@@ -0,0 +1,66 @@
+#
+mkdir LesHouches
+cd LesHouches
+library LesHouches.so
+cd /Herwig/EventHandlers
+
+
+create ThePEG::LesHouchesFileReader Reader2 LesHouches.so
+set Reader2:FileName PPEE.lhe
+set Reader2:BeamA 2212
+set Reader2:BeamB -2212
+set Reader2:EBeamA 3500.0
+set Reader2:EBeamB 3500.0
+set Reader2:PDFA /Herwig/Partons/ShowerLOPDF
+set Reader2:PDFB /Herwig/Partons/ShowerLOPDF
+create ThePEG::Cuts QCDCuts
+set QCDCuts:ScaleMin 1.0*GeV
+set QCDCuts:X1Min 0.00001
+set QCDCuts:X2Min 0.00001
+set QCDCuts:MHatMin 20.*GeV
+set QCDCuts:X1Max 0.9
+set QCDCuts:X2Max 0.9
+create ThePEG::LesHouchesEventHandler LesHouchesHandler
+insert LesHouchesHandler:LesHouchesReaders[0] Reader2
+set LesHouchesHandler:PartonExtractor /Herwig/Partons/QCDExtractor
+set LesHouchesHandler:StatLevel 2
+set LesHouchesHandler:CascadeHandler /Herwig/Shower/ShowerHandler
+set LesHouchesHandler:HadronizationHandler /Herwig/Hadronization/ClusterHadHandler
+set LesHouchesHandler:DecayHandler /Herwig/Decays/DecayHandler
+set LesHouchesHandler:WeightOption NegUnitWeight
+
+cd /Herwig/Cuts
+set JetKtCut:MinKT 0.0*GeV
+
+cd /Herwig/Generators
+create ThePEG::EventGenerator MGGenerator
+set MGGenerator:RandomNumberGenerator /Herwig/Random
+set MGGenerator:StandardModelParameters /Herwig/Model
+set MGGenerator:EventHandler /Herwig/EventHandlers/LesHouchesHandler
+
+cd /Herwig/Generators
+set MGGenerator:EventHandler:Cuts /Herwig/Cuts/QCDCuts
+
+
+cd /Herwig/Analysis
+create ThePEG::RivetAnalysis RivetAnalysis RivetAnalysis.so
+
+# General analysis
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 MC_ZINC
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 MC_ZJETS
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 MC_WINC
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 MC_WJETS
+
+
+insert /Herwig/Generators/MGGenerator:AnalysisHandlers 0 RivetAnalysis
+
+cd /Herwig/Generators/
+set MGGenerator:NumberOfEvents 1000000
+set MGGenerator:RandomNumberGenerator:Seed 31122001
+set MGGenerator:PrintEvent 10
+set MGGenerator:MaxErrors 100000000
+#set MGGenerator:EventHandler:CascadeHandler:MPIHandler NULL
+#
+saverun LHE MGGenerator
+
+
diff --git a/Tests/LHE/LHE.in b/Tests/LHE/LHE.in
new file mode 100644
--- /dev/null
+++ b/Tests/LHE/LHE.in
@@ -0,0 +1,88 @@
+#
+mkdir LesHouches
+cd LesHouches
+library LesHouches.so
+cd /Herwig/EventHandlers
+
+
+create ThePEG::LesHouchesFileReader Reader2 LesHouches.so
+set Reader2:FileName PPEE.lhe
+set Reader2:BeamA 2212
+set Reader2:BeamB -2212
+set Reader2:EBeamA 3500.0
+set Reader2:EBeamB 3500.0
+set Reader2:PDFA /Herwig/Partons/ShowerLOPDF
+set Reader2:PDFB /Herwig/Partons/ShowerLOPDF
+create ThePEG::Cuts QCDCuts
+set QCDCuts:ScaleMin 1.0*GeV
+set QCDCuts:X1Min 0.00001
+set QCDCuts:X2Min 0.00001
+set QCDCuts:MHatMin 20.*GeV
+set QCDCuts:X1Max 0.9
+set QCDCuts:X2Max 0.9
+create ThePEG::LesHouchesEventHandler LesHouchesHandler
+insert LesHouchesHandler:LesHouchesReaders[0] Reader2
+set LesHouchesHandler:PartonExtractor /Herwig/Partons/QCDExtractor
+set LesHouchesHandler:StatLevel 2
+set LesHouchesHandler:CascadeHandler /Herwig/Shower/ShowerHandler
+set LesHouchesHandler:HadronizationHandler /Herwig/Hadronization/ClusterHadHandler
+set LesHouchesHandler:DecayHandler /Herwig/Decays/DecayHandler
+set LesHouchesHandler:WeightOption NegUnitWeight
+
+cd /Herwig/Cuts
+set JetKtCut:MinKT 0.0*GeV
+
+cd /Herwig/Generators
+create ThePEG::EventGenerator MGGenerator
+set MGGenerator:RandomNumberGenerator /Herwig/Random
+set MGGenerator:StandardModelParameters /Herwig/Model
+set MGGenerator:EventHandler /Herwig/EventHandlers/LesHouchesHandler
+
+cd /Herwig/Generators
+set MGGenerator:EventHandler:Cuts /Herwig/Cuts/QCDCuts
+
+
+cd /Herwig/Analysis
+create ThePEG::RivetAnalysis RivetAnalysis RivetAnalysis.so
+
+# General analysis
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 MC_ZINC
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 MC_ZJETS
+# # ATLAS pT
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_S9131140
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1300647
+# # ATLAS Z+jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I945498
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2013_I1230812
+# # ATLAS phi*
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1204784
+# # CMS Z + b-hadron
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1256943
+# CMS Z pt and y
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I941555
+# # ATLAS Z + bjets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1306294
+# ATLAS Z
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I928289_Z
+# CMS Z AFB
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1122847
+# CMS Z+jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2015_I1310737
+# ATLAS event shapes in Z events
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1424838
+# ATLAS forwrd backward
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1351916_EL
+
+
+insert /Herwig/Generators/MGGenerator:AnalysisHandlers 0 RivetAnalysis
+
+cd /Herwig/Generators/
+set MGGenerator:NumberOfEvents 1000000
+set MGGenerator:RandomNumberGenerator:Seed 31122001
+set MGGenerator:PrintEvent 10
+set MGGenerator:MaxErrors 100000000
+#set MGGenerator:EventHandler:CascadeHandler:MPIHandler NULL
+#
+saverun LHE MGGenerator
+
+
diff --git a/Tests/LHE/ppWZ_LO_mg5.dat b/Tests/LHE/ppWZ_LO_mg5.dat
new file mode 100644
--- /dev/null
+++ b/Tests/LHE/ppWZ_LO_mg5.dat
@@ -0,0 +1,44 @@
+#************************************************************
+#* MadGraph5_aMC@NLO *
+#* *
+#* * * *
+#* * * * * *
+#* * * * * 5 * * * * *
+#* * * * * *
+#* * * *
+#* *
+#* *
+#* VERSION 2.4.3 2016-08-01 *
+#* BZR *
+#* *
+#* The MadGraph5_aMC@NLO Development Team - Find us at *
+#* https://server06.fynu.ucl.ac.be/projects/madgraph *
+#* *
+#************************************************************
+#* *
+#* Command File for MadGraph5_aMC@NLO *
+#* *
+#* run as ./bin/mg5_aMC filename *
+#* *
+#************************************************************
+set group_subprocesses Auto
+set ignore_six_quark_processes False
+set loop_optimized_output True
+set loop_color_flows False
+set gauge unitary
+set complex_mass_scheme False
+set max_npoint_for_channel 0
+import model sm
+define p = g u c d s u~ c~ d~ s~
+define j = g u c d s u~ c~ d~ s~
+define l+ = e+ mu+
+define l- = e- mu-
+define vl = ve vm vt
+define vl~ = ve~ vm~ vt~
+generate p p > W+ Z
+output PROC
+launch PROC
+set ebeam1 3500
+set ebeam2 3500
+set nevents 100000
+
diff --git a/Tests/LHE/ppee_LO_mg5.dat b/Tests/LHE/ppee_LO_mg5.dat
new file mode 100644
--- /dev/null
+++ b/Tests/LHE/ppee_LO_mg5.dat
@@ -0,0 +1,48 @@
+#************************************************************
+#* MadGraph5_aMC@NLO *
+#* *
+#* * * *
+#* * * * * *
+#* * * * * 5 * * * * *
+#* * * * * *
+#* * * *
+#* *
+#* *
+#* VERSION 2.4.3 2016-08-01 *
+#* BZR *
+#* *
+#* The MadGraph5_aMC@NLO Development Team - Find us at *
+#* https://server06.fynu.ucl.ac.be/projects/madgraph *
+#* *
+#************************************************************
+#* *
+#* Command File for MadGraph5_aMC@NLO *
+#* *
+#* run as ./bin/mg5_aMC filename *
+#* *
+#************************************************************
+set group_subprocesses Auto
+set ignore_six_quark_processes False
+set loop_optimized_output True
+set loop_color_flows False
+set gauge unitary
+set complex_mass_scheme False
+set max_npoint_for_channel 0
+import model sm
+define p = g u c d s u~ c~ d~ s~
+define j = g u c d s u~ c~ d~ s~
+define l+ = e+ mu+
+define l- = e- mu-
+define vl = ve vm vt
+define vl~ = ve~ vm~ vt~
+generate p p > e+ e-
+output PROC
+launch PROC
+set ebeam1 3500
+set ebeam2 3500
+set nevents 100000
+set ptl 0.0
+set etal 4.5
+set mmll 66.0
+set mmllmax 120.0
+
diff --git a/Tests/Makefile.am b/Tests/Makefile.am
--- a/Tests/Makefile.am
+++ b/Tests/Makefile.am
@@ -1,365 +1,369 @@
AUTOMAKE_OPTIONS = -Wno-portability
AM_LDFLAGS += -module -avoid-version -rpath /dummy/path/not/used
EXTRA_DIST = Inputs python Rivet
dist-hook:
rm -rf $(distdir)/Inputs/.svn
rm -rf $(distdir)/python/.svn
rm -rf $(distdir)/Rivet/.svn
EXTRA_LTLIBRARIES = LeptonTest.la GammaTest.la HadronTest.la DISTest.la
if WANT_LIBFASTJET
EXTRA_LTLIBRARIES += HadronJetTest.la LeptonJetTest.la
HadronJetTest_la_SOURCES = \
Hadron/VHTest.h Hadron/VHTest.cc\
Hadron/VTest.h Hadron/VTest.cc\
Hadron/HTest.h Hadron/HTest.cc
HadronJetTest_la_CPPFLAGS = $(AM_CPPFLAGS) $(FASTJETINCLUDE) \
-I$(FASTJETPATH)
HadronJetTest_la_LIBADD = $(FASTJETLIBS)
LeptonJetTest_la_SOURCES = \
Lepton/TopDecay.h Lepton/TopDecay.cc
LeptonJetTest_la_CPPFLAGS = $(AM_CPPFLAGS) $(FASTJETINCLUDE) \
-I$(FASTJETPATH)
LeptonJetTest_la_LIBADD = $(FASTJETLIBS)
endif
LeptonTest_la_SOURCES = \
Lepton/VVTest.h Lepton/VVTest.cc \
Lepton/VBFTest.h Lepton/VBFTest.cc \
Lepton/VHTest.h Lepton/VHTest.cc \
Lepton/FermionTest.h Lepton/FermionTest.cc
GammaTest_la_SOURCES = \
Gamma/GammaMETest.h Gamma/GammaMETest.cc \
Gamma/GammaPMETest.h Gamma/GammaPMETest.cc
DISTest_la_SOURCES = \
DIS/DISTest.h DIS/DISTest.cc
HadronTest_la_SOURCES = \
Hadron/HadronVVTest.h Hadron/HadronVVTest.cc\
Hadron/HadronVBFTest.h Hadron/HadronVBFTest.cc\
Hadron/WHTest.h Hadron/WHTest.cc\
Hadron/ZHTest.h Hadron/ZHTest.cc\
Hadron/VGammaTest.h Hadron/VGammaTest.cc\
Hadron/ZJetTest.h Hadron/ZJetTest.cc\
Hadron/WJetTest.h Hadron/WJetTest.cc\
Hadron/QQHTest.h Hadron/QQHTest.cc
REPO = $(top_builddir)/src/HerwigDefaults.rpo
HERWIG = $(top_builddir)/src/Herwig
HWREAD = $(HERWIG) read --repo $(REPO) -L $(builddir)/.libs -i $(top_builddir)/src
HWRUN = $(HERWIG) run
tests : tests-LEP tests-DIS tests-LHC tests-Gamma
if WANT_LIBFASTJET
tests-LEP : test-LEP-VV test-LEP-VH test-LEP-VBF test-LEP-BB test-LEP-Quarks test-LEP-Leptons \
test-LEP-default test-LEP-Powheg test-LEP-TopDecay
else
tests-LEP : test-LEP-VV test-LEP-VH test-LEP-VBF test-LEP-BB test-LEP-Quarks test-LEP-Leptons
endif
tests-DIS : test-DIS-Charged test-DIS-Neutral
if WANT_LIBFASTJET
tests-LHC : test-LHC-WW test-LHC-WZ test-LHC-ZZ test-LHC-ZGamma test-LHC-WGamma \
test-LHC-ZH test-LHC-WH test-LHC-ZJet test-LHC-WJet test-LHC-Z test-LHC-W test-LHC-ZZVBF test-LHC-VBF \
test-LHC-WWVBF test-LHC-bbH test-LHC-ttH test-LHC-GammaGamma test-LHC-GammaJet test-LHC-Higgs \
test-LHC-HiggsJet test-LHC-QCDFast test-LHC-QCD test-LHC-Top test-LHC-Bottom \
test-LHC-WHJet test-LHC-ZHJet test-LHC-HJet test-LHC-ZShower test-LHC-WShower\
test-LHC-WHJet-Powheg test-LHC-ZHJet-Powheg test-LHC-HJet-Powheg \
test-LHC-ZShower-Powheg test-LHC-WShower-Powheg
else
tests-LHC : test-LHC-WW test-LHC-WZ test-LHC-ZZ test-LHC-ZGamma test-LHC-WGamma \
test-LHC-ZH test-LHC-WH test-LHC-ZJet test-LHC-WJet test-LHC-Z test-LHC-W test-LHC-ZZVBF test-LHC-VBF \
test-LHC-WWVBF test-LHC-bbH test-LHC-ttH test-LHC-GammaGamma test-LHC-GammaJet test-LHC-Higgs \
test-LHC-HiggsJet test-LHC-QCDFast test-LHC-QCD test-LHC-Top
endif
tests-Gamma : test-Gamma-FF test-Gamma-WW test-Gamma-P
if WANT_LIBFASTJET
test-LEP-% : Inputs/LEP-%.in LeptonTest.la LeptonJetTest.la
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
else
test-LEP-% : Inputs/LEP-%.in LeptonTest.la
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
endif
Rivet-LHC-Matchbox-% : Rivet/LHC-Matchbox-%.in
if [ ! -d Rivet-$(notdir $(subst .in,,$<)) ]; then mkdir Rivet-$(notdir $(subst .in,,$<)); fi;
cd Rivet-$(notdir $(subst .in,,$<)); echo `pwd`; \
../$(HERWIG) read --repo ../$(REPO) -L ../$(top_builddir)/lib -i ../$(top_builddir)/src ../$<; \
../$(HERWIG) run $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}; \
mv $(notdir $(subst .in,.yoda,$<)) ..; \
cd ..
Rivet-TVT-Matchbox-% : Rivet/TVT-Matchbox-%.in
if [ ! -d Rivet-$(notdir $(subst .in,,$<)) ]; then mkdir Rivet-$(notdir $(subst .in,,$<)); fi;
cd Rivet-$(notdir $(subst .in,,$<)); echo `pwd`; \
../$(HERWIG) read --repo ../$(REPO) -L ../$(top_builddir)/lib -i ../$(top_builddir)/src ../$<; \
../$(HERWIG) run $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}; \
mv $(notdir $(subst .in,.yoda,$<)) ..; \
cd ..
Rivet-TVT-Dipole-% : Rivet/TVT-Dipole-%.in
if [ ! -d Rivet-$(notdir $(subst .in,,$<)) ]; then mkdir Rivet-$(notdir $(subst .in,,$<)); fi;
cd Rivet-$(notdir $(subst .in,,$<)); echo `pwd`; \
../$(HERWIG) read --repo ../$(REPO) -L ../$(top_builddir)/lib -i ../$(top_builddir)/src ../$<; \
../$(HERWIG) run $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}; \
mv $(notdir $(subst .in,.yoda,$<)) ..; \
cd ..
Rivet-LHC-Dipole-% : Rivet/LHC-Dipole-%.in
if [ ! -d Rivet-$(notdir $(subst .in,,$<)) ]; then mkdir Rivet-$(notdir $(subst .in,,$<)); fi;
cd Rivet-$(notdir $(subst .in,,$<)); echo `pwd`; \
../$(HERWIG) read --repo ../$(REPO) -L ../$(top_builddir)/lib -i ../$(top_builddir)/src ../$<; \
../$(HERWIG) run $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}; \
mv $(notdir $(subst .in,.yoda,$<)) ..; \
cd ..
Rivet/LEP-%.in :
python/make_input_files.py $(notdir $(subst .in,,$@))
Rivet/DIS-%.in :
python/make_input_files.py $(notdir $(subst .in,,$@))
Rivet/BFactory-%.in:
python/make_input_files.py $(notdir $(subst .in,,$@))
Rivet/TVT-%.in:
python/make_input_files.py $(notdir $(subst .in,,$@))
Rivet/LHC-%.in:
python/make_input_files.py $(notdir $(subst .in,,$@))
Rivet/Star-%.in:
python/make_input_files.py $(notdir $(subst .in,,$@))
Rivet/SppS-%.in:
python/make_input_files.py $(notdir $(subst .in,,$@))
Rivet/ISR-%.in:
python/make_input_files.py $(notdir $(subst .in,,$@))
Rivet-LEP-Matchbox-% : Rivet/LEP-Matchbox-%.in
if [ ! -d Rivet-$(notdir $(subst .in,,$<)) ]; then mkdir Rivet-$(notdir $(subst .in,,$<)); fi;
cd Rivet-$(notdir $(subst .in,,$<)); echo `pwd`; \
../$(HERWIG) read --repo ../$(REPO) -L ../$(top_builddir)/lib -i ../$(top_builddir)/src ../$<; \
../$(HERWIG) run $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}; \
mv $(notdir $(subst .in,.yoda,$<)) ..; \
cd ..
Rivet-LEP-Dipole-% : Rivet/LEP-Dipole-%.in
if [ ! -d Rivet-$(notdir $(subst .in,,$<)) ]; then mkdir Rivet-$(notdir $(subst .in,,$<)); fi;
cd Rivet-$(notdir $(subst .in,,$<)); echo `pwd`; \
../$(HERWIG) read --repo ../$(REPO) -L ../$(top_builddir)/lib -i ../$(top_builddir)/src ../$<; \
../$(HERWIG) run $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}; \
mv $(notdir $(subst .in,.yoda,$<)) ..; \
cd ..
Rivet-BFactory-Matchbox-% : Rivet/BFactory-Matchbox-%.in
if [ ! -d Rivet-$(notdir $(subst .in,,$<)) ]; then mkdir Rivet-$(notdir $(subst .in,,$<)); fi;
cd Rivet-$(notdir $(subst .in,,$<)); echo `pwd`; \
../$(HERWIG) read --repo ../$(REPO) -L ../$(top_builddir)/lib -i ../$(top_builddir)/src ../$<; \
../$(HERWIG) run $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}; \
mv $(notdir $(subst .in,.yoda,$<)) ..; \
cd ..
Rivet-LEP-% : Rivet/LEP-%.in
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
Rivet-BFactory-% : Rivet/BFactory-%.in
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
Rivet-TVT-% : Rivet/TVT-%.in
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
Rivet-DIS-% : Rivet/DIS-%.in
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
Rivet-LHC-% : Rivet/LHC-%.in
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
Rivet-Star-% : Rivet/Star-%.in
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
Rivet-SppS-% : Rivet/SppS-%.in
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
Rivet-ISR-% : Rivet/ISR-%.in
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
-Rivet-inputfiles: $(shell echo Rivet/LEP{,-Powheg,-Matchbox,-Dipole,-Matchbox-Powheg}-{10,22,35,44,91,130,133,136,161,172,177,183,189,192,196,197,200,202,206,91-nopi}.in) \
+Rivet-inputfiles: $(shell echo Rivet/LEP{,-Powheg,-Matchbox,-Dipole,-Matchbox-Powheg}-{10,12.8,22,26.8,35,44,48.0,91,93.0,130,133,136,161,172,177,183,189,192,196,197,200,202,206,91-nopi}.in) \
$(shell echo Rivet/LEP{,-Powheg,-Matchbox-Powheg}-14.in) \
+ $(shell echo Rivet/LEP-{10.5,11.96,12.8,13.96,16.86,21.84,26.8,28.48,35.44,48.0,97.0}-gg.in) \
$(shell echo Rivet/BFactory{,-Powheg,-Matchbox,-Dipole,-Matchbox-Powheg}-{10.52,10.52-sym,10.54,10.45}.in) \
$(shell echo Rivet/BFactory-{Upsilon,Upsilon2,Upsilon4,Tau,10.58-res}.in) \
$(shell echo Rivet/DIS{,-NoME,-Powheg,-Matchbox,-Dipole,-Matchbox-Powheg}-{e--LowQ2,e+-LowQ2,e+-HighQ2}.in) \
$(shell echo Rivet/TVT{,-Powheg,-Matchbox,-Dipole,-Matchbox-Powheg}-{Run-I-Z,Run-I-W,Run-I-WZ,Run-II-Z-e,Run-II-Z-{,LowMass-,HighMass-}mu,Run-II-W}.in) \
$(shell echo Rivet/TVT-Run-II-{DiPhoton-GammaGamma,DiPhoton-GammaJet,PromptPhoton}.in) \
$(shell echo Rivet/TVT-Powheg-Run-II-{DiPhoton-GammaGamma,DiPhoton-GammaJet}.in) \
$(shell echo Rivet/TVT{,-Dipole,-Matchbox,-Matchbox-Powheg}-{Run-II-Jets-{0..11},Run-I-Jets-{1..8}}.in ) \
$(shell echo Rivet/TVT{,-Dipole,-Matchbox,-Matchbox-Powheg}-{630-Jets-{1..3},300-Jets-1,900-Jets-1}.in ) \
$(shell echo Rivet/TVT-{Run-I,Run-II,300,630,900}-UE.in) \
- $(shell echo Rivet/LHC{,-Dipole,-Matchbox,-Matchbox-Powheg}-7-Jets-{0..15}.in ) \
+ $(shell echo Rivet/LHC{,-Dipole,-Matchbox,-Matchbox-Powheg}-7-DiJets-{1..7}-{A,B,C}.in ) \
+ $(shell echo Rivet/LHC{,-Dipole,-Matchbox,-Matchbox-Powheg}-{7,8}-Jets-{0..10}.in ) \
$(shell echo Rivet/LHC-{900,2360,2760,7,8,13}-UE.in ) \
- $(shell echo Rivet/LHC-{900,7}-UE-Long.in ) \
+ $(shell echo Rivet/LHC-{900,7}-UE-{Short,Long}.in ) \
$(shell echo Rivet/LHC{,-Dipole,-Matchbox,-Matchbox-Powheg}-7-Charm-{1..5}.in) \
$(shell echo Rivet/LHC{,-Dipole,-Matchbox,-Matchbox-Powheg}-7-Bottom-{0..8}.in) \
$(shell echo Rivet/LHC{,-Matchbox,-Matchbox-Powheg}-7-Top-{L,SL,All}.in) \
$(shell echo Rivet/LHC{,-Matchbox,-Matchbox-Powheg}-8-Top-All.in) \
$(shell echo Rivet/Star-{UE,Jets-{1..4}}.in ) \
$(shell echo Rivet/SppS-{200,500,900,546}-UE.in ) \
$(shell echo Rivet/LHC{,-Matchbox,-Matchbox-Powheg,-Powheg,-Dipole}-{W-{e,mu},13-Z-{e,mu},8-Z-Mass{1..4}-{e,mu},Z-{e,mu,mu-SOPHTY},Z-LowMass-{e,mu},Z-MedMass-e,WZ,WW-{emu,ll},ZZ-{ll,lv},W-Z-{e,mu}}.in) \
$(shell echo Rivet/LHC-7-{W,Z}Gamma-{e,mu}.in) \
$(shell echo Rivet/LHC{,-Matchbox,-Matchbox-Powheg,-Dipole}-{7-W-Jet-{1..3}-e,7-Z-Jet-{0..3}-e,7-Z-Jet-0-mu}.in) \
$(shell echo Rivet/LHC{-Matchbox,-Matchbox-Powheg,-Dipole}-{Z-b,Z-bb,W-b,8-Z-jj}.in) \
$(shell echo Rivet/LHC-{7,8}-PromptPhoton-{1..4}.in) Rivet/LHC-GammaGamma-7.in \
$(shell echo Rivet/LHC{,-Powheg}-7-{DiPhoton-GammaGamma,DiPhoton-GammaJet}.in) \
$(shell echo Rivet/LHC{,-Powheg,-Matchbox,-Matchbox-Powheg,-Dipole}-{ggH,VBF,WH,ZH}.in) \
$(shell echo Rivet/LHC{,-Powheg,-Matchbox,-Matchbox-Powheg,-Dipole}-8-{ggH,VBF,WH,ZH}{,-GammaGamma}.in) \
$(shell echo Rivet/LHC{,-Matchbox,-Matchbox-Powheg,-Dipole}-ggHJet.in)
# $(shell echo Rivet/ISR-{30,44,53,62}-UE.in ) $(shell echo Rivet/SppS-{53,63}-UE.in )
-Rivet-LEP: $(shell echo Rivet-LEP{,-Powheg,-Matchbox,-Dipole}-{10,14,22,35,44,91,130,133,136,161,172,177,183,189,192,196,197,200,202,206,91-nopi})
+Rivet-LEP: $(shell echo Rivet-LEP{,-Powheg,-Matchbox,-Dipole}-{10,12.8,22,26.8,35,44,48.0,91,93.0,130,133,136,161,172,177,183,189,192,196,197,200,202,206,91-nopi}) \
+ $(shell echo Rivet-LEP-{10.5,11.96,12.8,13.96,16.86,21.84,26.8,28.48,35.44,48.0,97.0}-gg)
rm -rf Rivet-LEP
python/merge-LEP LEP
python/merge-LEP LEP-Powheg
python/merge-LEP LEP-Matchbox
python/merge-LEP LEP-Dipole
rivet-mkhtml -o Rivet-LEP LEP.yoda:Hw++ LEP-Powheg.yoda:Hw++-Powheg LEP-Matchbox.yoda:Hw++-Matchbox LEP-Dipole.yoda:Hw++-Dipole
Rivet-BFactory: $(shell echo Rivet-BFactory{,-Powheg,-Matchbox,-Dipole}-{10.52,10.52-sym,10.54,10.45}) \
$(shell echo Rivet-BFactory-{Upsilon,Upsilon2,Upsilon4,Tau,10.58-res,10.58})
rm -rf Rivet-BFactory
python/merge-BFactory BFactory
python/merge-BFactory BFactory-Powheg
python/merge-BFactory BFactory-Matchbox
python/merge-BFactory BFactory-Dipole
rivet-mkhtml -o Rivet-BFactory BFactory.yoda:Hw++ BFactory-Powheg.yoda:Hw++-Powheg BFactory-Matchbox.yoda:Hw++-Matchbox BFactory-Dipole.yoda:Hw++-Dipole
Rivet-DIS: $(shell echo Rivet-DIS{,-NoME,-Powheg,-Matchbox,-Dipole}-{e--LowQ2,e+-LowQ2,e+-HighQ2})
rm -rf Rivet-DIS
python/merge-DIS DIS
python/merge-DIS DIS-Powheg
python/merge-DIS DIS-NoME
python/merge-DIS DIS-Matchbox
python/merge-DIS DIS-Dipole
rivet-mkhtml -o Rivet-DIS DIS.yoda:Hw++ DIS-Powheg.yoda:Hw++-Powheg DIS-NoME.yoda:Hw++-NoME DIS-Matchbox.yoda:Hw++-Matchbox DIS-Dipole.yoda:Hw++-Dipole
Rivet-TVT-WZ: $(shell echo Rivet-TVT{,-Powheg,-Matchbox,-Dipole}-{Run-I-Z,Run-I-W,Run-I-WZ,Run-II-Z-{e,{,LowMass-,HighMass-}mu},Run-II-W})
rm -rf Rivet-TVT-WZ
python/merge-TVT-EW TVT-Run-II-W.yoda TVT-Run-II-Z-{e,{,LowMass-,HighMass-}mu}.yoda\
TVT-Run-I-{W,Z,WZ}.yoda -o TVT-WZ.yoda
python/merge-TVT-EW TVT-Powheg-Run-II-W.yoda TVT-Powheg-Run-II-Z-{e,{,LowMass-,HighMass-}mu}.yoda\
TVT-Powheg-Run-I-{W,Z,WZ}.yoda -o TVT-Powheg-WZ.yoda
python/merge-TVT-EW TVT-Matchbox-Run-II-W.yoda TVT-Matchbox-Run-II-Z-{e,{,LowMass-,HighMass-}mu}.yoda\
TVT-Matchbox-Run-I-{W,Z,WZ}.yoda -o TVT-Matchbox-WZ.yoda
python/merge-TVT-EW TVT-Dipole-Run-II-W.yoda TVT-Dipole-Run-II-Z-{e,{,LowMass-,HighMass-}mu}.yoda\
TVT-Dipole-Run-I-{W,Z,WZ}.yoda -o TVT-Dipole-WZ.yoda
rivet-mkhtml -o Rivet-TVT-WZ TVT-WZ.yoda:Hw++ TVT-Powheg-WZ.yoda:Hw++-Powheg TVT-Matchbox-WZ.yoda:Hw++-Matchbox TVT-Dipole-WZ.yoda:Hw++-Dipole
Rivet-TVT-Photon: $(shell echo Rivet-TVT-Run-II-{DiPhoton-GammaGamma,DiPhoton-GammaJet,PromptPhoton}) \
$(shell echo Rivet-TVT-Powheg-Run-II-{DiPhoton-GammaGamma,DiPhoton-GammaJet})
rm -rf Rivet-TVT-Photon
python/merge-TVT-Photon TVT -o TVT-Photon.yoda
python/merge-TVT-Photon TVT-Powheg -o TVT-Powheg-Photon.yoda
rivet-mkhtml -o Rivet-TVT-Photon TVT-Photon.yoda:Hw TVT-Powheg-Photon.yoda:Hw-Powheg
Rivet-TVT-Jets: $(shell echo Rivet-TVT-{Run-II-Jets-{0..11},Run-I-Jets-{1..8}} ) \
$(shell echo Rivet-TVT-{630-Jets-{1..3},300-Jets-1,900-Jets-1} ) \
$(shell echo Rivet-TVT-{Run-I,Run-II,300,630,900}-UE)
python/merge-TVT-Energy TVT
rivet-merge-CDF_2012_NOTE10874 TVT-300-Energy.yoda TVT-900-Energy.yoda TVT-1960-Energy.yoda
flat2yoda RatioPlots.dat -o TVT-RatioPlots.yoda
rm -rf Rivet-TVT-Jets
python/merge-TVT-Jets TVT
rivet-mkhtml -o Rivet-TVT-Jets TVT-Jets.yoda:Hw++
-Rivet-LHC-Jets: $(shell echo Rivet-LHC-7-Jets-{0..15} ) \
+Rivet-LHC-Jets: $(shell echo Rivet-LHC-7-DiJets-{1..7}-{A,B,C} ) \
+ $(shell echo Rivet-LHC-{7,8}-Jets-{0..10} ) \
$(shell echo Rivet-LHC-{900,2360,2760,7,8,13}-UE ) \
- $(shell echo Rivet-LHC-{900,7}-UE-Long ) \
+ $(shell echo Rivet-LHC-{900,7}-UE-{Short,Long} ) \
$(shell echo Rivet-LHC-7-Charm-{1..5}) \
$(shell echo Rivet-LHC-7-Bottom-{0..8}) \
$(shell echo Rivet-LHC-7-Top-{L,SL,All})\
$(shell echo Rivet-LHC-8-Top-All)
rm -rf Rivet-LHC-Jets
python/merge-LHC-Jets LHC
rivet-mkhtml -o Rivet-LHC-Jets LHC-Jets.yoda:Hw++
Rivet-Star: $(shell echo Rivet-Star-{UE,Jets-{1..4}} )
rm -rf Rivet-Star
python/merge-Star Star
rivet-mkhtml -o Rivet-Star Star.yoda
Rivet-SppS: $(shell echo Rivet-ISR-{30,44,53,62}-UE ) \
$(shell echo Rivet-SppS-{53,63,200,500,900,546}-UE )
rm -rf Rivet-SppS
python/merge-SppS SppS
rivet-mkhtml -o Rivet-SppS SppS.yoda
Rivet-LHC-EW: $(shell echo Rivet-LHC{,-Matchbox,-Powheg,-Dipole}-{13-Z-{e,mu},8-Z-Mass{1..4}-{e,mu},W-{e,mu},Z-{e,mu,mu-SOPHTY},Z-LowMass-{e,mu},Z-MedMass-e,WZ,WW-{emu,ll},ZZ-{ll,lv},W-Z-{e,mu}}) \
$(shell echo Rivet-LHC{,-Matchbox,-Dipole}-{7-W-Jet-{1..3}-e,7-Z-Jet-{0..3}-e,7-Z-Jet-0-mu}) \
$(shell echo Rivet-LHC{-Matchbox,-Dipole}-{Z-b,Z-bb,W-b,8-Z-jj}) \
$(shell echo Rivet-LHC-7-{W,Z}Gamma-{e,mu}) \
rm -rf Rivet-LHC-EW;
- python/merge-LHC-EW LHC-{13-Z-{e,mu},8-Z-Mass{1..4}-{e,mu},W-{e,mu},Z-{e,mu},Z-LowMass-{e,mu},Z-MedMass-e,W-Z-{e,mu},WW-{emu,ll},WZ,ZZ-{ll,lv}}.yoda LHC-7-{W,Z}-Jet-{1,2,3}-e.yoda LHC-7-{W,Z}Gamma-{e,mu}.yoda -o LHC-EW.yoda;
- python/merge-LHC-EW LHC-Matchbox-{13-Z-{e,mu},8-Z-Mass{1..4}-{e,mu},W-{e,mu},Z-{e,mu},Z-LowMass-{e,mu},Z-MedMass-e,W-Z-{e,mu},WW-{emu,ll},WZ,ZZ-{ll,lv}}.yoda LHC-Matchbox-7-{W,Z}-Jet-{1,2,3}-e.yoda -o LHC-Matchbox-EW.yoda;
- python/merge-LHC-EW LHC-Dipole-{13-Z-{e,mu},8-Z-Mass{1..4}-{e,mu},W-{e,mu},Z-{e,mu},Z-LowMass-{e,mu},Z-MedMass-e,W-Z-{e,mu},WW-{emu,ll},WZ,ZZ-{ll,lv}}.yoda LHC-Dipole-7-{W,Z}-Jet-{1,2,3}-e.yoda -o LHC-Dipole-EW.yoda;
+ python/merge-LHC-EW LHC-{13-Z-{e,mu},8-Z-Mass{1..4}-{e,mu},W-{e,mu},Z-{e,mu,mu-Short},Z-LowMass-{e,mu},Z-MedMass-e,W-Z-{e,mu},WW-{emu,ll},WZ,ZZ-{ll,lv}}.yoda LHC-7-{W,Z}-Jet-{1,2,3}-e.yoda LHC-7-{W,Z}Gamma-{e,mu}.yoda -o LHC-EW.yoda;
+ python/merge-LHC-EW LHC-Matchbox-{13-Z-{e,mu},8-Z-Mass{1..4}-{e,mu},W-{e,mu},Z-{e,mu,mu-Short},Z-LowMass-{e,mu},Z-MedMass-e,W-Z-{e,mu},WW-{emu,ll},WZ,ZZ-{ll,lv}}.yoda LHC-Matchbox-7-{W,Z}-Jet-{1,2,3}-e.yoda -o LHC-Matchbox-EW.yoda;
+ python/merge-LHC-EW LHC-Dipole-{13-Z-{e,mu},8-Z-Mass{1..4}-{e,mu},W-{e,mu},Z-{e,mu,mu-Short},Z-LowMass-{e,mu},Z-MedMass-e,W-Z-{e,mu},WW-{emu,ll},WZ,ZZ-{ll,lv}}.yoda LHC-Dipole-7-{W,Z}-Jet-{1,2,3}-e.yoda -o LHC-Dipole-EW.yoda;
python/merge-LHC-EW LHC-Powheg-{W-{e,mu},Z-{e,mu},Z-LowMass-{e,mu},Z-MedMass-e,W-Z-{e,mu},WW-{emu,ll},WZ,ZZ-{ll,lv}}.yoda -o LHC-Powheg-EW.yoda;
rivet-mkhtml -o Rivet-LHC-EW LHC-EW.yoda:Hw++ LHC-Powheg-EW.yoda:Hw++-Powheg LHC-Matchbox-EW.yoda:Hw++-Matchbox LHC-Matchbox-Z-b.yoda:Hw++-Matchbox-Zb \
LHC-Matchbox-Z-bb.yoda:Hw++-Matchbox-Zbb LHC-Matchbox-W-b.yoda:Hw++-Matchbox-W-bb LHC-Dipole-EW.yoda:Hw++-Dipole \
LHC-Dipole-Z-b.yoda:Hw++-Dipole-Zb LHC-Dipole-Z-bb.yoda:Hw++-Dipole-Zbb LHC-Dipole-W-b.yoda:Hw++-Dipole-W-bb \
LHC-Z-mu-SOPHTY.yoda:Hw++ LHC-Powheg-Z-mu-SOPHTY.yoda:Hw++-Powheg LHC-Matchbox-Z-mu-SOPHTY.yoda:Hw++-Matchbox
Rivet-LHC-Photon: $(shell echo Rivet-LHC-{7,8}-PromptPhoton-{1..4}) Rivet-LHC-GammaGamma-7 \
$(shell echo Rivet-LHC{,-Powheg}-7-{DiPhoton-GammaGamma,DiPhoton-GammaJet})
rm -rf Rivet-LHC-Photon
python/merge-LHC-Photon LHC -o LHC-Photon.yoda
python/merge-LHC-Photon LHC-Powheg -o LHC-Powheg-Photon.yoda
rivet-mkhtml -o Rivet-LHC-Photon LHC-Photon.yoda:Hw LHC-Powheg-Photon.yoda:Hw-Powheg
Rivet-LHC-Higgs: $(shell echo Rivet-LHC{,-Powheg}-{ggH,VBF,WH,ZH})\
$(shell echo Rivet-LHC{,-Powheg}-8-{ggH,VBF,WH,ZH}{,-GammaGamma}) Rivet-LHC-ggHJet
rm -rf Rivet-LHC-Higgs
rivet-mkhtml -o Rivet-LHC-Higgs LHC-Powheg-ggH.yoda:gg-Powheg LHC-ggH.yoda:gg LHC-ggHJet.yoda:HJet \
LHC-Powheg-VBF.yoda:VBF-Powheg LHC-VBF.yoda:VBF LHC-WH.yoda:WH LHC-ZH.yoda:ZH \
LHC-Powheg-WH.yoda:WH-Powheg LHC-Powheg-ZH.yoda:ZH-Powheg
tests-Rivet : Rivet-LEP Rivet-BFactory Rivet-DIS Rivet-TVT-WZ Rivet-TVT-Photon Rivet-TVT-Jets Rivet-LHC-Jets Rivet-Star Rivet-SppS Rivet-LHC-EW Rivet-LHC-Photon
test-Gamma-% : Inputs/Gamma-%.in GammaTest.la
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
test-DIS-% : Inputs/DIS-%.in DISTest.la
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
if WANT_LIBFASTJET
test-LHC-% : Inputs/LHC-%.in HadronTest.la GammaTest.la HadronJetTest.la
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
else
test-LHC-% : Inputs/LHC-%.in HadronTest.la GammaTest.la
$(HWREAD) $<
$(HWRUN) $(notdir $(subst .in,.run,$<)) -N $${NUMEVENTS:-10000}
endif
clean-local:
rm -f *.out *.log *.tex *.top *.run *.dump *.mult *.Bmult *.yoda
diff --git a/Tests/Rivet/LEP/LEP-10.in b/Tests/Rivet/LEP/LEP-10.5-gg.in
copy from Tests/Rivet/LEP/LEP-10.in
copy to Tests/Rivet/LEP/LEP-10.5-gg.in
--- a/Tests/Rivet/LEP/LEP-10.in
+++ b/Tests/Rivet/LEP/LEP-10.5-gg.in
@@ -1,11 +1,10 @@
##################################################
# LEP physics parameters (override defaults)
##################################################
-set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 10.
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 10.5
set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 9.99
##################################################
# select the analyses
##################################################
# PDG hadron multiplicities and ratios
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 PDG_HADRON_MULTIPLICITIES
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 PDG_HADRON_MULTIPLICITIES_RATIOS
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_2003_I631361_hemispheres
diff --git a/Tests/Rivet/LEP/LEP-10.in b/Tests/Rivet/LEP/LEP-10.in
--- a/Tests/Rivet/LEP/LEP-10.in
+++ b/Tests/Rivet/LEP/LEP-10.in
@@ -1,11 +1,11 @@
##################################################
# LEP physics parameters (override defaults)
##################################################
set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 10.
-set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 9.99
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 9.
##################################################
# select the analyses
##################################################
# PDG hadron multiplicities and ratios
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 PDG_HADRON_MULTIPLICITIES
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 PDG_HADRON_MULTIPLICITIES_RATIOS
diff --git a/Tests/Rivet/LEP/LEP-11.96-gg.in b/Tests/Rivet/LEP/LEP-11.96-gg.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LEP/LEP-11.96-gg.in
@@ -0,0 +1,10 @@
+##################################################
+# LEP physics parameters (override defaults)
+##################################################
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 11.96
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 9.99
+##################################################
+# select the analyses
+##################################################
+# PDG hadron multiplicities and ratios
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_2003_I631361_hemispheres
diff --git a/Tests/Rivet/LEP/LEP-12.8-gg.in b/Tests/Rivet/LEP/LEP-12.8-gg.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LEP/LEP-12.8-gg.in
@@ -0,0 +1,10 @@
+##################################################
+# LEP physics parameters (override defaults)
+##################################################
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 12.8
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 9.99
+##################################################
+# select the analyses
+##################################################
+# PDG hadron multiplicities and ratios
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_2004_I648738
diff --git a/Tests/Rivet/LEP/LEP-12.8.in b/Tests/Rivet/LEP/LEP-12.8.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LEP/LEP-12.8.in
@@ -0,0 +1,10 @@
+##################################################
+# LEP physics parameters (override defaults)
+##################################################
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 12.8
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 9.99
+##################################################
+# select the analyses
+##################################################
+# PDG hadron multiplicities and ratios
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_2004_I648738
diff --git a/Tests/Rivet/LEP/LEP-13.96-gg.in b/Tests/Rivet/LEP/LEP-13.96-gg.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LEP/LEP-13.96-gg.in
@@ -0,0 +1,10 @@
+##################################################
+# LEP physics parameters (override defaults)
+##################################################
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 13.96
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 9.99
+##################################################
+# select the analyses
+##################################################
+# PDG hadron multiplicities and ratios
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_2003_I631361_hemispheres
diff --git a/Tests/Rivet/LEP/LEP-16.86-gg.in b/Tests/Rivet/LEP/LEP-16.86-gg.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LEP/LEP-16.86-gg.in
@@ -0,0 +1,10 @@
+##################################################
+# LEP physics parameters (override defaults)
+##################################################
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 16.86
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 9.99
+##################################################
+# select the analyses
+##################################################
+# PDG hadron multiplicities and ratios
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_2003_I631361_hemispheres
diff --git a/Tests/Rivet/LEP/LEP-197.in b/Tests/Rivet/LEP/LEP-197.in
--- a/Tests/Rivet/LEP/LEP-197.in
+++ b/Tests/Rivet/LEP/LEP-197.in
@@ -1,9 +1,11 @@
##################################################
# LEP physics parameters (override defaults)
##################################################
set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 197.
##################################################
# select the analyses
##################################################
# OPAL event shapes and multiplicities at different energies
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_2004_S6132243
+# OPAL from gluon paper
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_2004_I648738
diff --git a/Tests/Rivet/LEP/LEP-21.84-gg.in b/Tests/Rivet/LEP/LEP-21.84-gg.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LEP/LEP-21.84-gg.in
@@ -0,0 +1,10 @@
+##################################################
+# LEP physics parameters (override defaults)
+##################################################
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 21.84
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 9.99
+##################################################
+# select the analyses
+##################################################
+# PDG hadron multiplicities and ratios
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_2003_I631361_hemispheres
diff --git a/Tests/Rivet/LEP/LEP-26.8-gg.in b/Tests/Rivet/LEP/LEP-26.8-gg.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LEP/LEP-26.8-gg.in
@@ -0,0 +1,10 @@
+##################################################
+# LEP physics parameters (override defaults)
+##################################################
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 26.8
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 9.99
+##################################################
+# select the analyses
+##################################################
+# PDG hadron multiplicities and ratios
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_2004_I648738
diff --git a/Tests/Rivet/LEP/LEP-26.8.in b/Tests/Rivet/LEP/LEP-26.8.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LEP/LEP-26.8.in
@@ -0,0 +1,10 @@
+##################################################
+# LEP physics parameters (override defaults)
+##################################################
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 26.8
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 9.99
+##################################################
+# select the analyses
+##################################################
+# PDG hadron multiplicities and ratios
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_2004_I648738
diff --git a/Tests/Rivet/LEP/LEP-28.48-gg.in b/Tests/Rivet/LEP/LEP-28.48-gg.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LEP/LEP-28.48-gg.in
@@ -0,0 +1,10 @@
+##################################################
+# LEP physics parameters (override defaults)
+##################################################
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 28.48
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 9.99
+##################################################
+# select the analyses
+##################################################
+# PDG hadron multiplicities and ratios
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_2003_I631361_hemispheres
diff --git a/Tests/Rivet/LEP/LEP-35.44-gg.in b/Tests/Rivet/LEP/LEP-35.44-gg.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LEP/LEP-35.44-gg.in
@@ -0,0 +1,10 @@
+##################################################
+# LEP physics parameters (override defaults)
+##################################################
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 35.44
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 9.99
+##################################################
+# select the analyses
+##################################################
+# PDG hadron multiplicities and ratios
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_2003_I631361_hemispheres
diff --git a/Tests/Rivet/LEP/LEP-48.0-gg.in b/Tests/Rivet/LEP/LEP-48.0-gg.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LEP/LEP-48.0-gg.in
@@ -0,0 +1,10 @@
+##################################################
+# LEP physics parameters (override defaults)
+##################################################
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 48.0
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 9.99
+##################################################
+# select the analyses
+##################################################
+# PDG hadron multiplicities and ratios
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_2004_I648738
diff --git a/Tests/Rivet/LEP/LEP-48.0.in b/Tests/Rivet/LEP/LEP-48.0.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LEP/LEP-48.0.in
@@ -0,0 +1,10 @@
+##################################################
+# LEP physics parameters (override defaults)
+##################################################
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 48.0
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 9.99
+##################################################
+# select the analyses
+##################################################
+# PDG hadron multiplicities and ratios
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_2004_I648738
diff --git a/Tests/Rivet/LEP/LEP-91.in b/Tests/Rivet/LEP/LEP-91.in
--- a/Tests/Rivet/LEP/LEP-91.in
+++ b/Tests/Rivet/LEP/LEP-91.in
@@ -1,68 +1,70 @@
##################################################
# LEP physics parameters (override defaults)
##################################################
set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 91.2
##################################################
# select the analyses
##################################################
# Validated
##################################################
# ALEPH charged particle multiplicity
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALEPH_1991_S2435284
# ALEPH main LEP I QCD summary paper
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALEPH_1996_S3486095
# ALEPH D*
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALEPH_1999_S4193598
# OPAL charged hadron analysis
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_1994_S2927284
# OPAL Delta++ analysis
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_1995_S3198391
# OPAL J/Psi analysis analysis
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_1996_S3257789
# ALEPH eta/omega analysis
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALEPH_2002_S4823664
# OPAL K*0 analysis
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_1997_S3608263
# OPAL flavour specific charged multiplicities etc
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_1998_S3780481
# OPAL f_0,f_2 and phi production
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_1998_S3702294
# OPAL gamma,pi0,eta,eta',rho+/-,a0+/-
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_1998_S3749908
# OPAL K0
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_2000_S4418603
# SLD flavour specific charged multiplicities etc
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 SLD_1996_S3398250
# SLD flavour specific charged multiplicities etc
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 SLD_1999_S3743934
# SLD flavour specific charged multiplicities etc
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 SLD_2004_S5693039
# OPAL event shapes and multiplicities at different energies
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_2004_S6132243
# ALEPH jet and event shapes at many energies
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALEPH_2004_S5765862
# OPAL/JADE jet rates at many energies
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 JADE_OPAL_2000_S4300807
# DELPHI strange baryon production
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 DELPHI_1995_S3137023
# DELPHI f_0, rho_0 and f_2 production
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 DELPHI_1999_S3960137
# OPAL strange baryon production
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_1997_S3396100
# DELPHI tuning paper
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 DELPHI_1996_S3430090
# DELPHI b quark
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 DELPHI_2002_069_CONF_603
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 DELPHI_2011_I890503
# ALEPH b quark
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALEPH_2001_S4656318
# SLD b quark
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 SLD_2002_S4869273
# PDG hadron multiplicities and ratios
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 PDG_HADRON_MULTIPLICITIES
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 PDG_HADRON_MULTIPLICITIES_RATIOS
+# OPAL from gluon paper
+# insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_2004_I648738
##################################################
# unvalidated
##################################################
# OPAL 4 jet angles
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_2001_S4553896
diff --git a/Tests/Rivet/LEP/LEP-93.0.in b/Tests/Rivet/LEP/LEP-93.0.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LEP/LEP-93.0.in
@@ -0,0 +1,10 @@
+##################################################
+# LEP physics parameters (override defaults)
+##################################################
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 93.0
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 9.99
+##################################################
+# select the analyses
+##################################################
+# PDG hadron multiplicities and ratios
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_2004_I648738
diff --git a/Tests/Rivet/LEP/LEP-97.0-gg.in b/Tests/Rivet/LEP/LEP-97.0-gg.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LEP/LEP-97.0-gg.in
@@ -0,0 +1,10 @@
+##################################################
+# LEP physics parameters (override defaults)
+##################################################
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 97.0
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 9.99
+##################################################
+# select the analyses
+##################################################
+# PDG hadron multiplicities and ratios
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 OPAL_2004_I648738
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-1-A.in b/Tests/Rivet/LHC/LHC-7-DiJets-1-A.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-1-A.in
@@ -0,0 +1,9 @@
+##################################################
+# select the analyses
+##################################################
+# ATLAS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8817804
+# CMS High mass jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1268975
+# CMS Jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1208923
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-1-B.in b/Tests/Rivet/LHC/LHC-7-DiJets-1-B.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-1-B.in
@@ -0,0 +1,7 @@
+##################################################
+# select the analyses
+##################################################
+# CMS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8968497
+# CMS dijet
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1090423
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-1-C.in b/Tests/Rivet/LHC/LHC-7-DiJets-1-C.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-1-C.in
@@ -0,0 +1,5 @@
+##################################################
+# select the analyses
+##################################################
+# ATLAS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1082936
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-2-A.in b/Tests/Rivet/LHC/LHC-7-DiJets-2-A.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-2-A.in
@@ -0,0 +1,9 @@
+##################################################
+# select the analyses
+##################################################
+# ATLAS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8817804
+# CMS High mass jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1268975
+# CMS Jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1208923
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-2-B.in b/Tests/Rivet/LHC/LHC-7-DiJets-2-B.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-2-B.in
@@ -0,0 +1,7 @@
+##################################################
+# select the analyses
+##################################################
+# CMS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8968497
+# CMS dijet
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1090423
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-2-C.in b/Tests/Rivet/LHC/LHC-7-DiJets-2-C.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-2-C.in
@@ -0,0 +1,5 @@
+##################################################
+# select the analyses
+##################################################
+# ATLAS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1082936
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-3-A.in b/Tests/Rivet/LHC/LHC-7-DiJets-3-A.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-3-A.in
@@ -0,0 +1,9 @@
+##################################################
+# select the analyses
+##################################################
+# ATLAS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8817804
+# CMS High mass jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1268975
+# CMS Jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1208923
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-3-B.in b/Tests/Rivet/LHC/LHC-7-DiJets-3-B.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-3-B.in
@@ -0,0 +1,7 @@
+##################################################
+# select the analyses
+##################################################
+# CMS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8968497
+# CMS dijet
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1090423
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-3-C.in b/Tests/Rivet/LHC/LHC-7-DiJets-3-C.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-3-C.in
@@ -0,0 +1,5 @@
+##################################################
+# select the analyses
+##################################################
+# ATLAS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1082936
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-4-A.in b/Tests/Rivet/LHC/LHC-7-DiJets-4-A.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-4-A.in
@@ -0,0 +1,9 @@
+##################################################
+# select the analyses
+##################################################
+# ATLAS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8817804
+# CMS High mass jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1268975
+# CMS Jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1208923
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-4-B.in b/Tests/Rivet/LHC/LHC-7-DiJets-4-B.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-4-B.in
@@ -0,0 +1,7 @@
+##################################################
+# select the analyses
+##################################################
+# CMS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8968497
+# CMS dijet
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1090423
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-4-C.in b/Tests/Rivet/LHC/LHC-7-DiJets-4-C.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-4-C.in
@@ -0,0 +1,5 @@
+##################################################
+# select the analyses
+##################################################
+# ATLAS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1082936
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-5-A.in b/Tests/Rivet/LHC/LHC-7-DiJets-5-A.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-5-A.in
@@ -0,0 +1,9 @@
+##################################################
+# select the analyses
+##################################################
+# ATLAS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8817804
+# CMS High mass jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1268975
+# CMS Jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1208923
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-5-B.in b/Tests/Rivet/LHC/LHC-7-DiJets-5-B.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-5-B.in
@@ -0,0 +1,7 @@
+##################################################
+# select the analyses
+##################################################
+# CMS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8968497
+# CMS dijet
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1090423
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-5-C.in b/Tests/Rivet/LHC/LHC-7-DiJets-5-C.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-5-C.in
@@ -0,0 +1,5 @@
+##################################################
+# select the analyses
+##################################################
+# ATLAS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1082936
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-6-A.in b/Tests/Rivet/LHC/LHC-7-DiJets-6-A.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-6-A.in
@@ -0,0 +1,9 @@
+##################################################
+# select the analyses
+##################################################
+# ATLAS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8817804
+# CMS High mass jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1268975
+# CMS Jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1208923
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-6-B.in b/Tests/Rivet/LHC/LHC-7-DiJets-6-B.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-6-B.in
@@ -0,0 +1,7 @@
+##################################################
+# select the analyses
+##################################################
+# CMS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8968497
+# CMS dijet
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1090423
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-6-C.in b/Tests/Rivet/LHC/LHC-7-DiJets-6-C.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-6-C.in
@@ -0,0 +1,5 @@
+##################################################
+# select the analyses
+##################################################
+# ATLAS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1082936
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-7-A.in b/Tests/Rivet/LHC/LHC-7-DiJets-7-A.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-7-A.in
@@ -0,0 +1,9 @@
+##################################################
+# select the analyses
+##################################################
+# ATLAS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8817804
+# CMS High mass jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1268975
+# CMS Jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1208923
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-7-B.in b/Tests/Rivet/LHC/LHC-7-DiJets-7-B.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-7-B.in
@@ -0,0 +1,7 @@
+##################################################
+# select the analyses
+##################################################
+# CMS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8968497
+# CMS dijet
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1090423
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-7-C.in b/Tests/Rivet/LHC/LHC-7-DiJets-7-C.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-7-C.in
@@ -0,0 +1,5 @@
+##################################################
+# select the analyses
+##################################################
+# ATLAS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1082936
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-8-A.in b/Tests/Rivet/LHC/LHC-7-DiJets-8-A.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-8-A.in
@@ -0,0 +1,9 @@
+##################################################
+# select the analyses
+##################################################
+# ATLAS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8817804
+# CMS High mass jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1268975
+# CMS Jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1208923
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-8-B.in b/Tests/Rivet/LHC/LHC-7-DiJets-8-B.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-8-B.in
@@ -0,0 +1,7 @@
+##################################################
+# select the analyses
+##################################################
+# CMS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8968497
+# CMS dijet
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1090423
diff --git a/Tests/Rivet/LHC/LHC-7-DiJets-8-C.in b/Tests/Rivet/LHC/LHC-7-DiJets-8-C.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-DiJets-8-C.in
@@ -0,0 +1,5 @@
+##################################################
+# select the analyses
+##################################################
+# ATLAS jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1082936
diff --git a/Tests/Rivet/LHC/LHC-7-Jets-1.in b/Tests/Rivet/LHC/LHC-7-Jets-1.in
--- a/Tests/Rivet/LHC/LHC-7-Jets-1.in
+++ b/Tests/Rivet/LHC/LHC-7-Jets-1.in
@@ -1,32 +1,32 @@
##################################################
# select the analyses
##################################################
# ATLAS jet shapes
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_S8924791
# ATLAS jets
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8817804
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1082936
# ATLAS dijet with veto
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_S9126244
# CMS jet cross section
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S9086218
# CMS 3/2 jet cross section ratio
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S9088458
# ATLAS track jet
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I919017
# CMS UE
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S9120041
# CMS central and forward jets
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1087342
# strange particles in underlying event
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_PAS_QCD_11_010
# ATLAS charged particle in min bias
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1125575
# CMS 4-jet
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1273574
# ATLAS leading jet UE
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1298811
# ATLAS jet shapes
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1082009
# CMS Jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1208923
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1208923
\ No newline at end of file
diff --git a/Tests/Rivet/LHC/LHC-7-Jets-10.in b/Tests/Rivet/LHC/LHC-7-Jets-10.in
--- a/Tests/Rivet/LHC/LHC-7-Jets-10.in
+++ b/Tests/Rivet/LHC/LHC-7-Jets-10.in
@@ -1,16 +1,36 @@
##################################################
# select the analyses
##################################################
+# ATLAS di-jet decorrelation
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_S8971293
# ATLAS jets
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8817804
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1082936
-# CMS jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8968497
+# ATLAS dijet with veto
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_S9126244
+# CMS jet cross section
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S9086218
+# CMS 3/2 jet cross section ratio
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S9088458
+# ATLAS track jet
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I919017
# CMS central and forward jets
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1087342
-# CMS dijet
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1090423
-# CMS High mass jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1268975
+# ATLAS subjets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1094564
+# CMS jet structure
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1224539_DIJET
+# CMS 4-jet
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1273574
+# ATLAS leading jet UE
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1298811
+# ATLAS jet veto
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1307243
+# ATLAS inclusive jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1325553
+# CMS jet ratios
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2014_I1298810
+# flavour composition of jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1188891
# CMS Jets
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1208923
diff --git a/Tests/Rivet/LHC/LHC-7-Jets-11.in b/Tests/Rivet/LHC/LHC-7-Jets-11.in
deleted file mode 100644
--- a/Tests/Rivet/LHC/LHC-7-Jets-11.in
+++ /dev/null
@@ -1,16 +0,0 @@
-##################################################
-# select the analyses
-##################################################
-# ATLAS jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8817804
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1082936
-# CMS jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8968497
-# CMS central and forward jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1087342
-# CMS dijet
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1090423
-# CMS High mass jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1268975
-# CMS Jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1208923
diff --git a/Tests/Rivet/LHC/LHC-7-Jets-12.in b/Tests/Rivet/LHC/LHC-7-Jets-12.in
deleted file mode 100644
--- a/Tests/Rivet/LHC/LHC-7-Jets-12.in
+++ /dev/null
@@ -1,16 +0,0 @@
-##################################################
-# select the analyses
-##################################################
-# ATLAS jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8817804
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1082936
-# CMS jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8968497
-# CMS central and forward jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1087342
-# CMS dijet
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1090423
-# CMS High mass jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1268975
-# CMS Jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1208923
diff --git a/Tests/Rivet/LHC/LHC-7-Jets-13.in b/Tests/Rivet/LHC/LHC-7-Jets-13.in
deleted file mode 100644
--- a/Tests/Rivet/LHC/LHC-7-Jets-13.in
+++ /dev/null
@@ -1,16 +0,0 @@
-##################################################
-# select the analyses
-##################################################
-# ATLAS jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8817804
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1082936
-# CMS jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8968497
-# CMS central and forward jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1087342
-# CMS dijet
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1090423
-# CMS High mass jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1268975
-# CMS Jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1208923
diff --git a/Tests/Rivet/LHC/LHC-7-Jets-14.in b/Tests/Rivet/LHC/LHC-7-Jets-14.in
deleted file mode 100644
--- a/Tests/Rivet/LHC/LHC-7-Jets-14.in
+++ /dev/null
@@ -1,16 +0,0 @@
-##################################################
-# select the analyses
-##################################################
-# ATLAS jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8817804
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1082936
-# CMS jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8968497
-# CMS central and forward jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1087342
-# CMS dijet
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1090423
-# CMS High mass jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1268975
-# CMS Jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1208923
diff --git a/Tests/Rivet/LHC/LHC-7-Jets-15.in b/Tests/Rivet/LHC/LHC-7-Jets-15.in
deleted file mode 100644
--- a/Tests/Rivet/LHC/LHC-7-Jets-15.in
+++ /dev/null
@@ -1,16 +0,0 @@
-##################################################
-# select the analyses
-##################################################
-# ATLAS jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8817804
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1082936
-# CMS jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8968497
-# CMS central and forward jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1087342
-# CMS dijet
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1090423
-# CMS High mass jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1268975
-# CMS Jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1208923
diff --git a/Tests/Rivet/LHC/LHC-7-Jets-3.in b/Tests/Rivet/LHC/LHC-7-Jets-3.in
--- a/Tests/Rivet/LHC/LHC-7-Jets-3.in
+++ b/Tests/Rivet/LHC/LHC-7-Jets-3.in
@@ -1,44 +1,46 @@
##################################################
# select the analyses
##################################################
# ATLAS jet shapes
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_S8924791
# ATLAS jets
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8817804
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1082936
# CMS event shapes
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8957746
# ATLAS dijet with veto
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_S9126244
# CMS dijet decorrelation
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8950903
# CMS jet cross section
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S9086218
# CMS 3/2 jet cross section ratio
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S9088458
# ATLAS track jet
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I919017
# CMS UE
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S9120041
# CMS central and forward jets
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1087342
# strange particles in underlying event
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_PAS_QCD_11_010
# ATLAS charged particle in min bias
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1125575
# CMS 4-jet
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1273574
# ATLAS leading jet UE
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1298811
# ATLAS jet veto
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1307243
# ATLAS inclusive jets
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1325553
# CMS jet ratios
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2014_I1298810
# flavour composition of jets
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1188891
# ATLAS jet shapes
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1082009
# CMS Jets
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1208923
+# atlas double parton
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1479760
diff --git a/Tests/Rivet/LHC/LHC-7-Jets-9.in b/Tests/Rivet/LHC/LHC-7-Jets-9.in
--- a/Tests/Rivet/LHC/LHC-7-Jets-9.in
+++ b/Tests/Rivet/LHC/LHC-7-Jets-9.in
@@ -1,16 +1,36 @@
##################################################
# select the analyses
##################################################
+# ATLAS di-jet decorrelation
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_S8971293
# ATLAS jets
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8817804
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1082936
-# CMS jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8968497
+# ATLAS dijet with veto
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_S9126244
+# CMS jet cross section
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S9086218
+# CMS 3/2 jet cross section ratio
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S9088458
+# ATLAS track jet
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I919017
# CMS central and forward jets
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1087342
-# CMS dijet
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1090423
-# CMS High mass jets
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1268975
+# ATLAS subjets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1094564
+# CMS jet structure
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1224539_DIJET
+# CMS 4-jet
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1273574
+# ATLAS leading jet UE
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1298811
+# ATLAS jet veto
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1307243
+# ATLAS inclusive jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1325553
+# CMS jet ratios
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2014_I1298810
+# flavour composition of jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1188891
# CMS Jets
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1208923
diff --git a/Tests/Rivet/LHC/LHC-7-UE-Short.in b/Tests/Rivet/LHC/LHC-7-UE-Short.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-7-UE-Short.in
@@ -0,0 +1,5 @@
+##################################################
+# select the analyses
+##################################################
+# CMS charged particle rapidity
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_QCD_10_024
\ No newline at end of file
diff --git a/Tests/Rivet/LHC/LHC-7-UE.in b/Tests/Rivet/LHC/LHC-7-UE.in
--- a/Tests/Rivet/LHC/LHC-7-UE.in
+++ b/Tests/Rivet/LHC/LHC-7-UE.in
@@ -1,83 +1,81 @@
##################################################
# select the analyses
##################################################
# ATLAS jet shapes
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_S8924791
# ATLAS jets
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8817804
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1082936
# ATLAS UE
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_S8994773
# ATLAS UE
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8894728
# ATLAS fragmentation function
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_CONF_2010_049
# ATLAS UE
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8918562
# ALICE charged particles
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2010_S8625980
# CMS particle spectra
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8978280
# CMS charged particle multiplicity
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8884919
# CMS charged particle pT and rapidity
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2010_S8656010
# CMS UE
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S9120041
# ATLAS track jet
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I919017
# LHCB phi production
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 LHCB_2011_I919315
# ATLAS phi production
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1282441
# LHCB promt hadron productiom
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 LHCB_2012_I1119400
# ATLAS rap gap
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1084540
# CMS forward energy flow
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S9215166
-# CMS charged particle rapidity
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_QCD_10_024
# LHC K0s/Lambda
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 LHCB_2011_I917009
# TOTEM at large rapidity
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 TOTEM_2012_I1115294
# ATLAS Azimuthal ordering of charged hadrons
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1091481
# ALICE single/double diffractive and inelastic sigma
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2012_I1181770
# ATLAS inelastic cross section
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I894867
# CMS inelastic cross section
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1193338
# total transverse energy
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1183818
# underlying event forward rapidities
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1218372
# strange particles in underlying event
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_PAS_QCD_11_010
# CMS central and forward jets
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1087342
# CMS dijet
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1184941
# ATLAS charged particle in min bias
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1125575
# ATLAS two particle correlation
#insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1094061
# ATLAS correlations
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1093734
# LHCB energy flow
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 LHCB_2013_I1208105
# ATLAS charged particle event shapes
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1124167
# CMS Jet/UE properties
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1261026
# ATLAS leading jet UE
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1298811
# LHCB charged particles in min bias
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 LHCB_2014_I1281685
# ALICE identified particle spectra
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2015_I1357424
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2014_I1300380
# LHCB min bias
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 LHCB_2015_I1333223
diff --git a/Tests/Rivet/LHC/LHC-8-Jets-0.in b/Tests/Rivet/LHC/LHC-8-Jets-0.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-8-Jets-0.in
@@ -0,0 +1,2 @@
+# ATLAS tracks in jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1419070
\ No newline at end of file
diff --git a/Tests/Rivet/LHC/LHC-8-Jets-1.in b/Tests/Rivet/LHC/LHC-8-Jets-1.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-8-Jets-1.in
@@ -0,0 +1,2 @@
+# ATLAS tracks in jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1419070
\ No newline at end of file
diff --git a/Tests/Rivet/LHC/LHC-8-Jets-10.in b/Tests/Rivet/LHC/LHC-8-Jets-10.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-8-Jets-10.in
@@ -0,0 +1,4 @@
+# ATLAS tracks in jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1419070
+# ATLAS multijet
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1394679
\ No newline at end of file
diff --git a/Tests/Rivet/LHC/LHC-8-Jets-2.in b/Tests/Rivet/LHC/LHC-8-Jets-2.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-8-Jets-2.in
@@ -0,0 +1,2 @@
+# ATLAS tracks in jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1419070
\ No newline at end of file
diff --git a/Tests/Rivet/LHC/LHC-8-Jets-3.in b/Tests/Rivet/LHC/LHC-8-Jets-3.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-8-Jets-3.in
@@ -0,0 +1,4 @@
+# ATLAS tracks in jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1419070
+# ATLAS multijet
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1394679
\ No newline at end of file
diff --git a/Tests/Rivet/LHC/LHC-8-Jets-4.in b/Tests/Rivet/LHC/LHC-8-Jets-4.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-8-Jets-4.in
@@ -0,0 +1,4 @@
+# ATLAS tracks in jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1419070
+# ATLAS multijet
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1394679
\ No newline at end of file
diff --git a/Tests/Rivet/LHC/LHC-8-Jets-5.in b/Tests/Rivet/LHC/LHC-8-Jets-5.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-8-Jets-5.in
@@ -0,0 +1,4 @@
+# ATLAS tracks in jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1419070
+# ATLAS multijet
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1394679
\ No newline at end of file
diff --git a/Tests/Rivet/LHC/LHC-8-Jets-6.in b/Tests/Rivet/LHC/LHC-8-Jets-6.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-8-Jets-6.in
@@ -0,0 +1,4 @@
+# ATLAS tracks in jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1419070
+# ATLAS multijet
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1394679
\ No newline at end of file
diff --git a/Tests/Rivet/LHC/LHC-8-Jets-7.in b/Tests/Rivet/LHC/LHC-8-Jets-7.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-8-Jets-7.in
@@ -0,0 +1,4 @@
+# ATLAS tracks in jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1419070
+# ATLAS multijet
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1394679
\ No newline at end of file
diff --git a/Tests/Rivet/LHC/LHC-8-Jets-8.in b/Tests/Rivet/LHC/LHC-8-Jets-8.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-8-Jets-8.in
@@ -0,0 +1,4 @@
+# ATLAS tracks in jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1419070
+# ATLAS multijet
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1394679
\ No newline at end of file
diff --git a/Tests/Rivet/LHC/LHC-8-Jets-9.in b/Tests/Rivet/LHC/LHC-8-Jets-9.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-8-Jets-9.in
@@ -0,0 +1,4 @@
+# ATLAS tracks in jets
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1419070
+# ATLAS multijet
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1394679
\ No newline at end of file
diff --git a/Tests/Rivet/LHC/LHC-900-UE-Short.in b/Tests/Rivet/LHC/LHC-900-UE-Short.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-900-UE-Short.in
@@ -0,0 +1,5 @@
+##################################################
+# select the analyses
+##################################################
+# CMS charged particle rapidity
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_QCD_10_024
\ No newline at end of file
diff --git a/Tests/Rivet/LHC/LHC-900-UE.in b/Tests/Rivet/LHC/LHC-900-UE.in
--- a/Tests/Rivet/LHC/LHC-900-UE.in
+++ b/Tests/Rivet/LHC/LHC-900-UE.in
@@ -1,51 +1,49 @@
##################################################
# select the analyses
##################################################
# ATLAS UE
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_S8994773
# ATLAS UE
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8918562
# ATLAS UE
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8894728
# ATLAS charged particles
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2010_S8591806
# ALICE charged particles
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2010_S8706239
# ALICE charged particles
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2010_S8625980
# ALICE charged particles
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2010_S8624100
# ALICE particle spectra
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2011_S8945144
# ALICE strange particle production
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2011_S8909580
# CMS particle spectra
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8978280
# CMS charged particle multiplicity
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S8884919
# CMS charged particle pT and rapidity
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2010_S8547297
# CMS UE
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S9120041
# LHCB k_s0
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 LHCB_2010_S8758301
# LHCB promt hadron production
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 LHCB_2012_I1119400
# CMS forward energy flow
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2011_S9215166
-# CMS charged particle rapidity
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_QCD_10_024
# LHC K0s/Lambda
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 LHCB_2011_I917009
# ATLAS Azimuthal ordering of charged hadrons
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1091481
# ALICE single/double diffractive and inelastic sigma
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ALICE_2012_I1181770
# ATLAS inelastic cross section
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I894867
# underlying event forward rapidities
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1218372
# ATLAS two particle correlation
#insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1094061
# ATLAS correlations
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1093734
diff --git a/Tests/Rivet/LHC/LHC-Z-mu-Short.in b/Tests/Rivet/LHC/LHC-Z-mu-Short.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/LHC/LHC-Z-mu-Short.in
@@ -0,0 +1,5 @@
+##################################################
+# select the analyses
+##################################################
+# CMS underlying event in Z events
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1107658
diff --git a/Tests/Rivet/LHC/LHC-Z-mu.in b/Tests/Rivet/LHC/LHC-Z-mu.in
--- a/Tests/Rivet/LHC/LHC-Z-mu.in
+++ b/Tests/Rivet/LHC/LHC-Z-mu.in
@@ -1,33 +1,31 @@
##################################################
# select the analyses
##################################################
# ATLAS Z pt
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_S9131140
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1300647
# ATLAS Z+jets
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I945498
-# CMS underlying event in Z events
-insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I1107658
# ATLAS phi*
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2012_I1204784
# Z and real photon + jet
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1258128
# CMS Z + b-hadron
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1256943
# CMS Z pt and y
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2012_I941555
# ATLAS MPI in Z events
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2014_I1315949
# ATLAS Z
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2011_I928289_Z
# CMS Z AFB
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2013_I1122847
# CMS Z+jets
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2015_I1310737
# ATLAS event shapes in Z events
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2016_I1424838
# CMS photon radiation in Z decays
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CMS_2015_I1346843
# ATLAS forwrd backward
insert /Herwig/Analysis/RivetAnalysis:Analyses 0 ATLAS_2015_I1351916_MU
diff --git a/Tests/Rivet/Templates/Hadron-Gamma.in b/Tests/Rivet/Templates/Hadron-Gamma.in
--- a/Tests/Rivet/Templates/Hadron-Gamma.in
+++ b/Tests/Rivet/Templates/Hadron-Gamma.in
@@ -1,57 +1,57 @@
# -*- ThePEG-repository -*-
##################################################
# Technical parameters for this run
##################################################
cd /Herwig/Generators
set LHCGenerator:NumberOfEvents 10000000
set LHCGenerator:RandomNumberGenerator:Seed 31122001
set LHCGenerator:PrintEvent 10
set LHCGenerator:MaxErrors 1000000
set LHCGenerator:EventHandler:StatLevel Full
set LHCGenerator:EventHandler:Sampler:Ntry 10000
set /Herwig/Partons/QCDExtractor:FlatSHatY 0
-
+set /Herwig/Decays/DecayHandler:MaxLifeTime 10*mm
##################################################
# Change the proton PDFs to those for photon radiation
##################################################
set /Herwig/Particles/p+:PDF /Herwig/Partons/BudnevPDF
set /Herwig/Particles/pbar-:PDF /Herwig/Partons/BudnevPDF
set /Herwig/Partons/QCDExtractor:FirstPDF /Herwig/Partons/BudnevPDF
set /Herwig/Partons/QCDExtractor:SecondPDF /Herwig/Partons/BudnevPDF
set /Herwig/Shower/ShowerHandler:PDFA NULL
set /Herwig/Shower/ShowerHandler:PDFB NULL
# No MPI
set LHCGenerator:EventHandler:CascadeHandler:MPIHandler NULL
##################################################
# Create the Herwig analysis
##################################################
create ThePEG::RivetAnalysis /Herwig/Analysis/RivetAnalysis RivetAnalysis.so
insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/RivetAnalysis
set /Herwig/Analysis/RivetAnalysis:Debug No
##################################################
# Cuts
##################################################
cd /Herwig/Cuts
set QCDCuts:ScaleMin 0.0*GeV
set QCDCuts:X1Min 0
set QCDCuts:X2Min 0
set QCDCuts:X1Max 1.
set QCDCuts:X2Max 1.
set QCDCuts:MHatMin 1.*GeV
erase QCDCuts:MultiCuts 0
set LeptonKtCut:MinKT 3*GeV
mv /Herwig/Generators/LHCGenerator /Herwig/Generators/EventGenerator
cd /Herwig/MatrixElements
${process}
cd /Herwig/Generators
read ${parameterFile}
##################################################
# Save run for later usage with 'Herwig run'
##################################################
cd /Herwig/Generators
saverun ${runname} EventGenerator
diff --git a/Tests/Rivet/Templates/Hadron-Matchbox.in b/Tests/Rivet/Templates/Hadron-Matchbox.in
--- a/Tests/Rivet/Templates/Hadron-Matchbox.in
+++ b/Tests/Rivet/Templates/Hadron-Matchbox.in
@@ -1,42 +1,42 @@
##################################################
## Collider type
##################################################
read Matchbox/PPCollider.in
##################################################
## Matrix element library selection
##################################################
${nlo}
##################################################
## Matching and shower selection
## Please also see flavour scheme settings
## towards the end of the input file.
##################################################
${shower}
##################################################
## PDF choice
##################################################
${bscheme}
read Matchbox/MMHT2014.in
##################################################
# Create the Herwig analysis
##################################################
create ThePEG::RivetAnalysis /Herwig/Analysis/RivetAnalysis RivetAnalysis.so
insert /Herwig/Generators/EventGenerator:AnalysisHandlers 0 /Herwig/Analysis/RivetAnalysis
set /Herwig/Analysis/RivetAnalysis:Debug No
-
+set /Herwig/Decays/DecayHandler:MaxLifeTime 10*mm
##################################################
## Save the generator
##################################################
do /Herwig/MatrixElements/Matchbox/Factory:ProductionMode
## Select the process
cd /Herwig/MatrixElements/Matchbox
${process}
read ${parameterFile}
cd /Herwig/Generators
set EventGenerator:MaxErrors 1000000
saverun ${runname} EventGenerator
diff --git a/Tests/Rivet/Templates/Hadron-Powheg.in b/Tests/Rivet/Templates/Hadron-Powheg.in
--- a/Tests/Rivet/Templates/Hadron-Powheg.in
+++ b/Tests/Rivet/Templates/Hadron-Powheg.in
@@ -1,49 +1,50 @@
##################################################
# Technical parameters for this run
##################################################
cd /Herwig/Generators
set LHCGenerator:NumberOfEvents 10000000
set LHCGenerator:RandomNumberGenerator:Seed 31122001
set LHCGenerator:PrintEvent 10
set LHCGenerator:MaxErrors 1000000
+set /Herwig/Decays/DecayHandler:MaxLifeTime 10*mm
##################################################
# Need to use an NLO PDF
##################################################
set /Herwig/Particles/p+:PDF /Herwig/Partons/HardNLOPDF
set /Herwig/Particles/pbar-:PDF /Herwig/Partons/HardNLOPDF
set /Herwig/Shower/ShowerHandler:PDFA /Herwig/Partons/ShowerLOPDF
set /Herwig/Shower/ShowerHandler:PDFB /Herwig/Partons/ShowerLOPDF
set /Herwig/Partons/MPIExtractor:FirstPDF /Herwig/Partons/MPIPDF
set /Herwig/Partons/MPIExtractor:SecondPDF /Herwig/Partons/MPIPDF
set /Herwig/Partons/QCDExtractor:FirstPDF /Herwig/Partons/HardNLOPDF
set /Herwig/Partons/QCDExtractor:SecondPDF /Herwig/Partons/HardNLOPDF
##################################################
# Setup the POWHEG shower
##################################################
cd /Herwig/Shower
set ShowerHandler:IntrinsicPtGaussian 1.9*GeV
set ShowerHandler:HardEmission POWHEG
read Matchbox/Powheg-Default-ShowerAlphaSTune.in
##################################################
# Create the Herwig analysis
##################################################
cd /Herwig/Generators
create ThePEG::RivetAnalysis /Herwig/Analysis/RivetAnalysis RivetAnalysis.so
insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/RivetAnalysis
mv /Herwig/Generators/LHCGenerator /Herwig/Generators/EventGenerator
cd /Herwig/MatrixElements
${process}
cd /Herwig/Generators
read ${parameterFile}
##################################################
# Save run for later usage with 'Herwig run'
##################################################
cd /Herwig/Generators
saverun ${runname} EventGenerator
diff --git a/Tests/Rivet/Templates/Hadron.in b/Tests/Rivet/Templates/Hadron.in
--- a/Tests/Rivet/Templates/Hadron.in
+++ b/Tests/Rivet/Templates/Hadron.in
@@ -1,28 +1,29 @@
##################################################
# Technical parameters for this run
##################################################
cd /Herwig/Generators
set LHCGenerator:NumberOfEvents 10000000
set LHCGenerator:RandomNumberGenerator:Seed 31122001
set LHCGenerator:PrintEvent 10
set LHCGenerator:MaxErrors 1000000
set LHCGenerator:EventHandler:StatLevel Full
+set /Herwig/Decays/DecayHandler:MaxLifeTime 10*mm
##################################################
# Create the Herwig analysis
##################################################
create ThePEG::RivetAnalysis /Herwig/Analysis/RivetAnalysis RivetAnalysis.so
insert LHCGenerator:AnalysisHandlers 0 /Herwig/Analysis/RivetAnalysis
set /Herwig/Analysis/RivetAnalysis:Debug No
mv /Herwig/Generators/LHCGenerator /Herwig/Generators/EventGenerator
cd /Herwig/MatrixElements
${process}
cd /Herwig/Generators
read ${parameterFile}
##################################################
# Save run for later usage with 'Herwig run'
##################################################
cd /Herwig/Generators
saverun ${runname} EventGenerator
diff --git a/Tests/Rivet/Templates/LEP.in b/Tests/Rivet/Templates/LEP.in
--- a/Tests/Rivet/Templates/LEP.in
+++ b/Tests/Rivet/Templates/LEP.in
@@ -1,42 +1,41 @@
##################################################
# base parameters for LEP analyses
##################################################
##################################################
# Technical parameters for this run
##################################################
cd /Herwig/Generators
set LEPGenerator:NumberOfEvents 100000000
set LEPGenerator:RandomNumberGenerator:Seed 31122001
set LEPGenerator:PrintEvent 10
set LEPGenerator:MaxErrors 1000000
# no MPI
set LEPGenerator:EventHandler:CascadeHandler:MPIHandler NULL
##################################################
# Switch off ISR
##################################################
set /Herwig/Particles/e-:PDF /Herwig/Partons/NoPDF
set /Herwig/Particles/e+:PDF /Herwig/Partons/NoPDF
##################################################
# Create the Herwig analysis
##################################################
create ThePEG::RivetAnalysis /Herwig/Analysis/RivetAnalysis RivetAnalysis.so
insert LEPGenerator:AnalysisHandlers 0 /Herwig/Analysis/RivetAnalysis
##################################################
# Use the q qbar matrix element
##################################################
# default e+e- > q qbar (5 flavours d,u,s,c,b)
-insert /Herwig/MatrixElements/SimpleEE:MatrixElements 0 /Herwig/MatrixElements/MEee2gZ2qq
${process}
set /Herwig/Shower/PartnerFinder:QEDPartner IIandFF
mv /Herwig/Generators/LEPGenerator /Herwig/Generators/EventGenerator
read ${parameterFile}
##################################################
# Save run for later usage with 'Herwig run'
##################################################
cd /Herwig/Generators
saverun ${runname} EventGenerator
diff --git a/Tests/python/make_input_files.py b/Tests/python/make_input_files.py
--- a/Tests/python/make_input_files.py
+++ b/Tests/python/make_input_files.py
@@ -1,1508 +1,1516 @@
#! /usr/bin/env python
import logging,sys,os
from string import strip, Template
import sys
if sys.version_info[:3] < (2,4,0):
print "rivet scripts require Python version >= 2.4.0... exiting"
sys.exit(1)
if __name__ == "__main__":
import logging
from optparse import OptionParser, OptionGroup
parser = OptionParser(usage="%prog name [...]")
(opts, args) = parser.parse_args()
## Check args
if len(args) != 1:
logging.error("Must specify at least input file")
sys.exit(1)
name=args[0]
collider=""
# select the template to load
# collider
parameters = {}
if(name.find("BFactory")==0) :
collider="BFactory"
elif(name.find("LEP")==0) :
collider="LEP"
elif(name.find("DIS")==0) :
collider="DIS"
elif(name.find("TVT")==0) :
collider="TVT"
elif(name.find("LHC-GammaGamma")==0) :
collider="LHC-GammaGamma"
elif(name.find("LHC")==0) :
collider="LHC"
elif(name.find("ISR")==0) :
collider="ISR"
elif(name.find("SppS")==0) :
collider="SppS"
elif(name.find("Star")==0) :
collider="Star"
simulation=""
istart = 1
print name
if(name.find("Matchbox-Powheg")>0) :
istart = 3
simulation="Matchbox"
parameters["shower"] = "read Matchbox/Powheg-DefaultShower.in\n"
elif(name.find("Matchbox")>0) :
istart = 2
simulation="Matchbox"
parameters["shower"] = "read Matchbox/MCatNLO-DefaultShower.in\n"
elif(name.find("Dipole")>0) :
istart = 2
simulation="Matchbox"
parameters["shower"] = "read Matchbox/MCatNLO-DipoleShower.in\n"
elif(name.find("Powheg")>0) :
istart = 2
simulation="Powheg"
if(simulation=="Matchbox") :
parameters["bscheme"] = "read Matchbox/FiveFlavourScheme.in\n"
if(parameters["shower"].find("Dipole")>=0) :
parameters["bscheme"] += "read Matchbox/FiveFlavourNoBMassScheme.in\n"
if(collider.find("DIS")<0) :
parameters["nlo"] = "read Matchbox/MadGraph-OpenLoops.in\n"
if(collider=="") :
logging.error("Can\'t find collider")
sys.exit(1)
# find the template
if(simulation=="") :
if(collider.find("LHC-GammaGamma") >=0) :
istart += 1
templateName="Hadron-Gamma.in"
elif(collider.find("TVT")>=0 or collider.find("LHC") >=0 or
collider.find("ISR")>=0 or collider.find("SppS")>=0 or
collider.find("Star")>=0) :
templateName="Hadron.in"
elif(collider.find("BFactory")<0) :
templateName= "%s.in" % (collider)
else :
templateName= "LEP.in"
else :
if(collider.find("TVT")>=0 or collider.find("LHC") >=0 or
collider.find("ISR")>=0 or collider.find("SppS")>=0 or
collider.find("Star")>=0) :
templateName= "Hadron-%s.in" % (simulation)
elif(collider.find("BFactory")<0) :
templateName= "%s-%s.in" % (collider,simulation)
else :
templateName= "LEP-%s.in" % (simulation)
with open(os.path.join("Rivet/Templates",templateName), 'r') as f:
templateText = f.read()
template = Template( templateText )
# work out the name of the parameter file
nameSplit=name.split("-")
parameterName=nameSplit[istart]
for i in range(istart+1,len(nameSplit)) :
parameterName += "-%s" % nameSplit[i]
# work out the process and parameters
process=""
# Bfactory
if(collider=="BFactory") :
if(simulation=="") :
if(parameterName=="10.58-res") :
- process += "\ncreate Herwig::MEee2VectorMeson /Herwig/MatrixElements/MEUpsilon HwMELepton.so\nset /Herwig/MatrixElements/MEUpsilon:VectorMeson /Herwig/Particles/Upsilon(4S)\nset /Herwig/MatrixElements/MEUpsilon:Coupling 0.0004151809\nset /Herwig/MatrixElements/SimpleEE:MatrixElements 0 /Herwig/MatrixElements/MEUpsilon"
+ process += "\ncreate Herwig::MEee2VectorMeson /Herwig/MatrixElements/MEUpsilon HwMELepton.so\nset /Herwig/MatrixElements/MEUpsilon:VectorMeson /Herwig/Particles/Upsilon(4S)\nset /Herwig/MatrixElements/MEUpsilon:Coupling 0.0004151809\ninsert /Herwig/MatrixElements/SimpleEE:MatrixElements 0 /Herwig/MatrixElements/MEUpsilon"
elif(parameterName=="10.58") :
process += "\ncreate Herwig::MEee2VectorMeson /Herwig/MatrixElements/MEUpsilon HwMELepton.so\nset /Herwig/MatrixElements/MEUpsilon:VectorMeson /Herwig/Particles/Upsilon(4S)\nset /Herwig/MatrixElements/MEUpsilon:Coupling 0.0004151809\ninsert /Herwig/MatrixElements/SimpleEE:MatrixElements 0 /Herwig/MatrixElements/MEUpsilon\n"
process += "set /Herwig/MatrixElements/MEee2gZ2qq:MaximumFlavour 4\n"
else :
- process += "set /Herwig/MatrixElements/MEee2gZ2qq:MaximumFlavour 4\n"
+ process+="insert /Herwig/MatrixElements/SimpleEE:MatrixElements 0 /Herwig/MatrixElements/MEee2gZ2qq\n"
+ process+= "set /Herwig/MatrixElements/MEee2gZ2qq:MaximumFlavour 4\n"
elif(simulation=="Powheg") :
process = "set /Herwig/MatrixElements/PowhegMEee2gZ2qq:MaximumFlavour 4\n"
elif(simulation=="Matchbox" ) :
process = "do Factory:Process e- e+ -> u ubar\ndo Factory:Process e- e+ -> d dbar\ndo Factory:Process e- e+ -> c cbar\ndo Factory:Process e- e+ -> s sbar\n"
# DIS
elif(collider=="DIS") :
if(simulation=="") :
if(parameterName.find("NoME")>=0) :
process = "set /Herwig/Shower/ShowerHandler:HardEmission None"
parameterName=parameterName.replace("NoME-","")
else :
process = ""
elif(simulation=="Powheg") :
process = ""
elif(simulation=="Matchbox" ) :
if(parameterName.find("e-")>=0) :
process="do Factory:Process e- p -> e- j"
else :
process="do Factory:Process e+ p -> e+ j"
# LEP
elif(collider=="LEP") :
if(simulation=="") :
- process=""
- if(parameterName=="10") :
- process="set /Herwig/MatrixElements/MEee2gZ2qq:MaximumFlavour 4"
+ if(parameterName.find("gg")>=0) :
+ process ="create Herwig::MEee2Higgs2SM /Herwig/MatrixElements/MEee2Higgs2SM\n"
+ process+="insert /Herwig/MatrixElements/SimpleEE:MatrixElements[0] /Herwig/MatrixElements/MEee2Higgs2SM\n"
+ process+="set /Herwig/MatrixElements/MEee2Higgs2SM:Allowed Gluon\n"
+
+ else :
+ process="insert /Herwig/MatrixElements/SimpleEE:MatrixElements 0 /Herwig/MatrixElements/MEee2gZ2qq\n"
+ if(parameterName=="10") :
+ process+="set /Herwig/MatrixElements/MEee2gZ2qq:MaximumFlavour 4"
elif(simulation=="Powheg") :
process=""
if(parameterName=="10") :
process="set /Herwig/MatrixElements/PowhegMEee2gZ2qq:MaximumFlavour 4"
elif(simulation=="Matchbox" ) :
if(parameterName=="10") :
process="do Factory:Process e- e+ -> u ubar\ndo Factory:Process e- e+ -> d dbar\ndo Factory:Process e- e+ -> c cbar\ndo Factory:Process e- e+ -> s sbar"
else :
process="do Factory:Process e- e+ -> j j"
# TVT
elif(collider=="TVT") :
process="set /Herwig/Generators/EventGenerator:EventHandler:BeamB /Herwig/Particles/pbar-\n"
if(parameterName.find("Run-II")>=0) :
process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 1960.0\n"
elif(parameterName.find("Run-I")>=0) :
process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 1800.0\n"
elif(parameterName.find("900")>=0) :
process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 900.0\n"
elif(parameterName.find("630")>=0) :
process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 630.0\n"
elif(parameterName.find("300")>=0) :
process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 300.0\n"
if(simulation=="") :
if(parameterName.find("PromptPhoton")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEGammaJet\n"
process+="set /Herwig/Cuts/PhotonKtCut:MinKT 15.\n"
elif(parameterName.find("DiPhoton-GammaGamma")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEGammaGamma\n"
process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n"
parameterName=parameterName.replace("-GammaGamma","")
elif(parameterName.find("DiPhoton-GammaJet")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEGammaJet\n"
process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n"
parameterName=parameterName.replace("-GammaJet","")
elif(parameterName.find("UE")>=0) :
process += "insert SimpleQCD:MatrixElements[0] MEMinBias\n"
process += "set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n"
process += "set /Herwig/Generators/EventGenerator:EventHandler:Cuts /Herwig/Cuts/MinBiasCuts\n"
process += "create Herwig::MPIXSecReweighter /Herwig/Generators/MPIXSecReweighter\n"
process += "insert /Herwig/Generators/EventGenerator:EventHandler:PostSubProcessHandlers 0 /Herwig/Generators/MPIXSecReweighter\n"
process += "set /Herwig/Decays/DecayHandler:LifeTimeOption 0\n"
process += "set /Herwig/Decays/DecayHandler:MaxLifeTime 10*mm\n"
elif(parameterName.find("Jets")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEQCD2to2\n"
process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n"
if(parameterName.find("Run-II-Jets-10")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 30.\n"
process+="set /Herwig/Cuts/QCDCuts:MHatMin 500.*GeV\n"
elif(parameterName.find("Run-II-Jets-11")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 30.\n"
process+="set /Herwig/Cuts/QCDCuts:MHatMin 900.*GeV\n"
elif(parameterName.find("Run-I-Jets-1")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n"
elif(parameterName.find("Run-I-Jets-2")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 40.\n"
elif(parameterName.find("Run-I-Jets-3")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 65.\n"
elif(parameterName.find("Run-I-Jets-4")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 90.\n"
elif(parameterName.find("Run-I-Jets-5")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 160.\n"
elif(parameterName.find("Run-I-Jets-6")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 30.\n"
process+="set /Herwig/Cuts/QCDCuts:MHatMin 100.*GeV\n"
elif(parameterName.find("Run-I-Jets-7")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 30.\n"
process+="set /Herwig/Cuts/QCDCuts:MHatMin 400.*GeV\n"
elif(parameterName.find("Run-I-Jets-8")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 30.\n"
process+="set /Herwig/Cuts/QCDCuts:MHatMin 700.*GeV\n"
elif(parameterName.find("Run-II-Jets-0")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 15.\n"
elif(parameterName.find("Run-II-Jets-1")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 25.\n"
elif(parameterName.find("Run-II-Jets-2")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 40.\n"
elif(parameterName.find("Run-II-Jets-3")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 60.\n"
elif(parameterName.find("Run-II-Jets-4")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 85.\n"
elif(parameterName.find("Run-II-Jets-5")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 110.\n"
elif(parameterName.find("Run-II-Jets-6")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 160.\n"
elif(parameterName.find("Run-II-Jets-7")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 250.\n"
elif(parameterName.find("Run-II-Jets-8")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 30.\n"
process+="set /Herwig/Cuts/QCDCuts:MHatMin 100.*GeV\n"
elif(parameterName.find("Run-II-Jets-9")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 30.\n"
process+="set /Herwig/Cuts/QCDCuts:MHatMin 300.*GeV\n"
elif(parameterName.find("900-Jets-1")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 10.\n"
elif(parameterName.find("300-Jets-1")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 6.\n"
elif(parameterName.find("630-Jets-1")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n"
elif(parameterName.find("630-Jets-2")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 40.\n"
elif(parameterName.find("630-Jets-3")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 75.\n"
elif(parameterName.find("900-Jets-1")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 10.\n"
elif(parameterName.find("Run-I-WZ")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEqq2W2ff\nset MEqq2W2ff:Process Electron\ninsert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Electron\n"
elif(parameterName.find("Run-I-W")>=0 or parameterName.find("Run-II-W")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEqq2W2ff\nset MEqq2W2ff:Process Electron\n"
elif(parameterName.find("Run-I-Z")>=0 or parameterName.find("Run-II-Z-e")>=0) :
process +="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Electron\n"
elif(parameterName.find("Run-II-Z-LowMass-mu")>=0) :
process +="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 25*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 70*GeV\n"
elif(parameterName.find("Run-II-Z-HighMass-mu")>=0) :
process +="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 150*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 600*GeV\n"
elif(parameterName.find("Run-II-Z-mu")>=0) :
process +="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n"
elif(simulation=="Powheg") :
if(parameterName.find("Run-I-WZ")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2W2ff\nset PowhegMEqq2W2ff:Process Electron\ninsert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Electron\n"
elif(parameterName.find("Run-I-W")>=0 or parameterName.find("Run-II-W")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2W2ff\nset PowhegMEqq2W2ff:Process Electron\n"
elif(parameterName.find("Run-I-Z")>=0 or parameterName.find("Run-II-Z-e")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Electron\n"
elif(parameterName.find("Run-II-Z-LowMass-mu")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Muon\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 25*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 70*GeV\n"
elif(parameterName.find("Run-II-Z-HighMass-mu")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Muon\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 150*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 600*GeV\n"
elif(parameterName.find("Run-II-Z-mu")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Muon\n"
elif(parameterName.find("DiPhoton-GammaGamma")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEGammaGammaPowheg\n"
process+="set MEGammaGammaPowheg:Process GammaGamma\n"
process+="insert SimpleQCD:MatrixElements[0] MEGammaGamma\n"
process+="set MEGammaGamma:Process gg\n"
process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n"
process+="set /Herwig/Cuts/JetKtCut:MinKT 5.\n"
parameterName=parameterName.replace("-GammaGamma","")
elif(parameterName.find("DiPhoton-GammaJet")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEGammaGammaPowheg\n"
process+="set MEGammaGammaPowheg:Process VJet\n"
process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n"
process+="set /Herwig/Cuts/JetKtCut:MinKT 5.\n"
parameterName=parameterName.replace("-GammaJet","")
elif(simulation=="Matchbox" ) :
if(parameterName.find("Jets")>=0) :
process+="set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 0\n"
process+="do Factory:Process p p j j\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/MaxJetPtScale\n"
process+="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n"
process+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n"
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n"
process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n"
if(parameterName.find("Run-II-Jets-10")>=0) :
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n"
process+="set /Herwig/Cuts/FirstJet:PtMin 30.*GeV\n"
process+="set /Herwig/Cuts/SecondJet:PtMin 25.*GeV\n"
process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n"
process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n"
process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n"
process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n"
process+="set /Herwig/Cuts/JetPairMass:MassMin 500.*GeV\n"
elif(parameterName.find("Run-II-Jets-11")>=0) :
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n"
process+="set /Herwig/Cuts/FirstJet:PtMin 30.*GeV\n"
process+="set /Herwig/Cuts/SecondJet:PtMin 25.*GeV\n"
process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n"
process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n"
process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n"
process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n"
process+="set /Herwig/Cuts/JetPairMass:MassMin 900.*GeV\n"
elif(parameterName.find("Run-II-Jets-12")>=0) :
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n"
process+="set /Herwig/Cuts/FirstJet:PtMin 30.*GeV\n"
process+="set /Herwig/Cuts/SecondJet:PtMin 25.*GeV\n"
process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n"
process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n"
process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n"
process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n"
process+="set /Herwig/Cuts/JetPairMass:MassMin 300.*GeV\n"
elif(parameterName.find("Run-I-Jets-1")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 20.\n"
elif(parameterName.find("Run-I-Jets-2")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 40.\n"
elif(parameterName.find("Run-I-Jets-3")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 65.\n"
elif(parameterName.find("Run-I-Jets-4")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 90.\n"
elif(parameterName.find("Run-I-Jets-5")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 160.\n"
elif(parameterName.find("Run-I-Jets-6")>=0) :
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n"
process+="set /Herwig/Cuts/FirstJet:PtMin 30.*GeV\n"
process+="set /Herwig/Cuts/SecondJet:PtMin 25.*GeV\n"
process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n"
process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n"
process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n"
process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n"
process+="set /Herwig/Cuts/JetPairMass:MassMin 100.*GeV\n"
elif(parameterName.find("Run-I-Jets-7")>=0) :
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n"
process+="set /Herwig/Cuts/FirstJet:PtMin 30.*GeV\n"
process+="set /Herwig/Cuts/SecondJet:PtMin 25.*GeV\n"
process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n"
process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n"
process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n"
process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n"
process+="set /Herwig/Cuts/JetPairMass:MassMin 400.*GeV\n"
elif(parameterName.find("Run-I-Jets-8")>=0) :
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n"
process+="set /Herwig/Cuts/FirstJet:PtMin 30.*GeV\n"
process+="set /Herwig/Cuts/SecondJet:PtMin 25.*GeV\n"
process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n"
process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n"
process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n"
process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n"
process+="set /Herwig/Cuts/JetPairMass:MassMin 700.*GeV\n"
elif(parameterName.find("Run-II-Jets-0")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 15.\n"
elif(parameterName.find("Run-II-Jets-1")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 25.\n"
elif(parameterName.find("Run-II-Jets-2")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 40.\n"
elif(parameterName.find("Run-II-Jets-3")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 60.\n"
elif(parameterName.find("Run-II-Jets-4")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 85.\n"
elif(parameterName.find("Run-II-Jets-5")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 110.\n"
elif(parameterName.find("Run-II-Jets-6")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 160.\n"
elif(parameterName.find("Run-II-Jets-7")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 250.\n"
elif(parameterName.find("Run-II-Jets-8")>=0) :
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n"
process+="set /Herwig/Cuts/FirstJet:PtMin 30.*GeV\n"
process+="set /Herwig/Cuts/SecondJet:PtMin 25.*GeV\n"
process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n"
process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n"
process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n"
process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n"
process+="set /Herwig/Cuts/JetPairMass:MassMin 100.*GeV\n"
elif(parameterName.find("Run-II-Jets-9")>=0) :
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n"
process+="set /Herwig/Cuts/FirstJet:PtMin 30.*GeV\n"
process+="set /Herwig/Cuts/SecondJet:PtMin 25.*GeV\n"
process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n"
process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n"
process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n"
process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n"
process+="set /Herwig/Cuts/JetPairMass:MassMin 300.*GeV\n"
elif(parameterName.find("900-Jets-1")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 10.\n"
elif(parameterName.find("300-Jets-1")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 6.\n"
elif(parameterName.find("630-Jets-1")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 20.\n"
elif(parameterName.find("630-Jets-2")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 40.\n"
elif(parameterName.find("630-Jets-3")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 75.\n"
elif(parameterName.find("900-Jets-1")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 10.\n"
elif(parameterName.find("Run-I-WZ")>=0) :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p pbar e+ e-\ndo Factory:Process p pbar e+ nu\ndo Factory:Process p pbar e- nu\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
elif(parameterName.find("Run-I-W")>=0 or parameterName.find("Run-II-W")>=0) :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p pbar e+ nu\ndo Factory:Process p pbar e- nu\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
elif(parameterName.find("Run-I-Z")>=0 or parameterName.find("Run-II-Z-e")>=0) :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p pbar e+ e-\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
elif(parameterName.find("Run-II-Z-LowMass-mu")>=0) :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p pbar mu+ mu-\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 25*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 70*GeV\n"
elif(parameterName.find("Run-II-Z-HighMass-mu")>=0) :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p pbar mu+ mu-\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 150.*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 600*GeV\n"
elif(parameterName.find("Run-II-Z-mu")>=0) :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p pbar mu+ mu-\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
# Star
elif(collider=="Star" ) :
process = "set /Herwig/Decays/DecayHandler:LifeTimeOption 0\n"
process+= "set /Herwig/Decays/DecayHandler:MaxLifeTime 10*mm\n"
process+= "set /Herwig/Generators/EventGenerator:EventHandler:BeamB /Herwig/Particles/p+\n"
process+= "set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 200.0\n"
process+= "set /Herwig/Cuts/QCDCuts:X2Min 0.01\n"
if(simulation=="") :
if(parameterName.find("UE")>=0) :
process += "insert SimpleQCD:MatrixElements[0] MEMinBias\n"
process += "set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n"
process += "set /Herwig/Generators/EventGenerator:EventHandler:Cuts /Herwig/Cuts/MinBiasCuts\n"
process += "create Herwig::MPIXSecReweighter /Herwig/Generators/MPIXSecReweighter\n"
process += "insert /Herwig/Generators/EventGenerator:EventHandler:PostSubProcessHandlers 0 /Herwig/Generators/MPIXSecReweighter\n"
else :
process+="insert SimpleQCD:MatrixElements[0] MEQCD2to2\n"
process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n"
if(parameterName.find("Jets-1")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 2.\n"
elif(parameterName.find("Jets-2")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 5.\n"
elif(parameterName.find("Jets-3")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n"
elif(parameterName.find("Jets-4")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 25.\n"
else :
logging.error("Star not supported for %s " % simulation)
sys.exit(1)
# ISR and SppS
elif(collider=="ISR" or collider =="SppS" ) :
process="set /Herwig/Decays/DecayHandler:LifeTimeOption 0\n"
process+="set /Herwig/Decays/DecayHandler:MaxLifeTime 10*mm\n"
if(collider=="SppS") :
process ="set /Herwig/Generators/EventGenerator:EventHandler:BeamB /Herwig/Particles/pbar-\n"
if(parameterName.find("30")>=0) :
process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 30.4\n"
elif(parameterName.find("44")>=0) :
process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 44.4\n"
elif(parameterName.find("53")>=0) :
process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 53.0\n"
elif(parameterName.find("62")>=0) :
process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 62.2\n"
elif(parameterName.find("63")>=0) :
process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 63.0\n"
elif(parameterName.find("200")>=0) :
process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 200.0\n"
elif(parameterName.find("500")>=0) :
process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 500.0\n"
elif(parameterName.find("546")>=0) :
process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 546.0\n"
elif(parameterName.find("900")>=0) :
process+="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 900.0\n"
if(simulation=="") :
process += "insert SimpleQCD:MatrixElements[0] MEMinBias\n"
process += "set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n"
process += "set /Herwig/Generators/EventGenerator:EventHandler:Cuts /Herwig/Cuts/MinBiasCuts\n"
process += "create Herwig::MPIXSecReweighter /Herwig/Generators/MPIXSecReweighter\n"
process += "insert /Herwig/Generators/EventGenerator:EventHandler:PostSubProcessHandlers 0 /Herwig/Generators/MPIXSecReweighter\n"
else :
logging.error(" SppS and ISR not supported for %s " % simulation)
sys.exit(1)
# LHC
elif(collider=="LHC") :
if(parameterName.find("7-")==0) :
process="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 7000.0\n"
elif(parameterName.find("8-")==0) :
process="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 8000.0\n"
elif(parameterName.find("13-")==0) :
process="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 13000.0\n"
elif(parameterName.find("900")==0) :
process="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 900.0\n"
elif(parameterName.find("2360")==0) :
process="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 2360.0\n"
elif(parameterName.find("2760")==0) :
process="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 2760.0\n"
else :
process="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 7000.0\n"
if(simulation=="") :
if(parameterName.find("8-VBF")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEPP2HiggsVBF\n"
elif(parameterName.find("VBF")>=0) :
process+="do /Herwig/Particles/h0:SelectDecayModes h0->tau-,tau+;\n"
process+="set /Herwig/Particles/tau-:Stable Stable\n"
process+="insert SimpleQCD:MatrixElements[0] MEPP2HiggsVBF\n"
elif(parameterName.find("ggHJet")>=0) :
process+="do /Herwig/Particles/h0:SelectDecayModes h0->tau-,tau+;\n"
process+="set /Herwig/Particles/tau-:Stable Stable\n"
process+="insert SimpleQCD:MatrixElements[0] MEHiggsJet\n"
elif(parameterName.find("8-ggH")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEHiggs\n"
process+="insert SimpleQCD:MatrixElements[0] MEHiggsJet\n"
process+="set MEHiggsJet:Process qqbar\n"
process+="set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV\n"
elif(parameterName.find("ggH")>=0) :
process+="do /Herwig/Particles/h0:SelectDecayModes h0->tau-,tau+;\n"
process+="set /Herwig/Particles/tau-:Stable Stable\n"
process+="insert SimpleQCD:MatrixElements[0] MEHiggs\n"
process+="insert SimpleQCD:MatrixElements[0] MEHiggsJet\n"
process+="set MEHiggsJet:Process qqbar\n"
process+="set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV\n"
elif(parameterName.find("PromptPhoton")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEGammaJet\n"
if(parameterName.find("PromptPhoton-1")>=0) :
process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n"
elif(parameterName.find("PromptPhoton-2")>=0) :
process+="set /Herwig/Cuts/PhotonKtCut:MinKT 25.\n"
elif(parameterName.find("PromptPhoton-3")>=0) :
process+="set /Herwig/Cuts/PhotonKtCut:MinKT 80.\n"
elif(parameterName.find("PromptPhoton-4")>=0) :
process+="set /Herwig/Cuts/PhotonKtCut:MinKT 150.\n"
elif(parameterName.find("DiPhoton-GammaGamma")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEGammaGamma\n"
process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n"
parameterName=parameterName.replace("-GammaGamma","")
elif(parameterName.find("DiPhoton-GammaJet")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEGammaJet\n"
process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n"
parameterName=parameterName.replace("-GammaJet","")
elif(parameterName.find("8-WH")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEPP2WH\n"
process+="set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV\n"
elif(parameterName.find("8-ZH")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEPP2ZH\n"
process+="set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV\n"
elif(parameterName.find("WH")>=0) :
process+="do /Herwig/Particles/h0:SelectDecayModes h0->b,bbar;\n"
process+="do /Herwig/Particles/W+:SelectDecayModes W+->nu_e,e+; W+->nu_mu,mu+;\n"
process+="insert SimpleQCD:MatrixElements[0] MEPP2WH\n"
process+="set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV\n"
elif(parameterName.find("ZH")>=0) :
process+="do /Herwig/Particles/h0:SelectDecayModes h0->b,bbar;\n"
process+="do /Herwig/Particles/Z0:SelectDecayModes Z0->e-,e+; Z0->mu-,mu+;\n"
process+="insert SimpleQCD:MatrixElements[0] MEPP2ZH\n"
process+="set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV\n"
elif(parameterName.find("UE")>=0) :
process += "insert SimpleQCD:MatrixElements[0] MEMinBias\n"
process += "set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n"
process += "set /Herwig/Generators/EventGenerator:EventHandler:Cuts /Herwig/Cuts/MinBiasCuts\n"
process += "create Herwig::MPIXSecReweighter /Herwig/Generators/MPIXSecReweighter\n"
process += "insert /Herwig/Generators/EventGenerator:EventHandler:PostSubProcessHandlers 0 /Herwig/Generators/MPIXSecReweighter\n"
if(parameterName.find("Long")>=0) :
process += "set /Herwig/Decays/DecayHandler:MaxLifeTime 100*mm\n"
- elif(parameterName.find("7-Jets")>=0) :
+ elif(parameterName.find("7-DiJets")>=0 or parameterName.find("8-DiJets")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEQCD2to2\n"
process+="set MEQCD2to2:MaximumFlavour 5\n"
process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n"
- if(parameterName.find("7-Jets-0")>=0) :
+ if(parameterName.find("-A")>=0) :
+ process+="set /Herwig/Cuts/JetKtCut:MinKT 45.\n"
+ process+="set /Herwig/Cuts/JetKtCut:MinEta -3.\n"
+ process+="set /Herwig/Cuts/JetKtCut:MaxEta 3.\n"
+ elif(parameterName.find("-B")>=0) :
+ process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n"
+ process+="set /Herwig/Cuts/JetKtCut:MinEta -2.7\n"
+ process+="set /Herwig/Cuts/JetKtCut:MaxEta 2.7\n"
+ elif(parameterName.find("-C")>=0) :
+ process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n"
+ process+="set /Herwig/Cuts/JetKtCut:MinEta -4.8\n"
+ process+="set /Herwig/Cuts/JetKtCut:MaxEta 4.8\n"
+ if(parameterName.find("DiJets-1")>=0) :
+ process+="set /Herwig/Cuts/QCDCuts:MHatMin 90.*GeV\n"
+ elif(parameterName.find("DiJets-2")>=0) :
+ process+="set /Herwig/Cuts/QCDCuts:MHatMin 200.*GeV\n"
+ elif(parameterName.find("DiJets-3")>=0) :
+ process+="set /Herwig/Cuts/QCDCuts:MHatMin 450.*GeV\n"
+ elif(parameterName.find("DiJets-4")>=0) :
+ process+="set /Herwig/Cuts/QCDCuts:MHatMin 750.*GeV\n"
+ elif(parameterName.find("DiJets-5")>=0) :
+ process+="set /Herwig/Cuts/QCDCuts:MHatMin 950.*GeV\n"
+ elif(parameterName.find("DiJets-6")>=0) :
+ process+="set /Herwig/Cuts/QCDCuts:MHatMin 1550.*GeV\n"
+ elif(parameterName.find("DiJets-7")>=0) :
+ process+="set /Herwig/Cuts/QCDCuts:MHatMin 2150.*GeV\n"
+ elif(parameterName.find("DiJets-8")>=0) :
+ process+="set /Herwig/Cuts/QCDCuts:MHatMin 2750.*GeV\n"
+ elif(parameterName.find("7-Jets")>=0 or parameterName.find("8-Jets")>=0) :
+ process+="insert SimpleQCD:MatrixElements[0] MEQCD2to2\n"
+ process+="set MEQCD2to2:MaximumFlavour 5\n"
+ process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n"
+ if(parameterName.find("Jets-10")>=0) :
+ process+="set /Herwig/Cuts/JetKtCut:MinKT 1800.\n"
+ elif(parameterName.find("Jets-0")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 5.\n"
- elif(parameterName.find("7-Jets-10")>=0) :
+ elif(parameterName.find("Jets-1")>=0) :
+ process+="set /Herwig/Cuts/JetKtCut:MinKT 10.\n"
+ elif(parameterName.find("Jets-2")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n"
- process+="set /Herwig/Cuts/QCDCuts:MHatMin 200.*GeV\n"
- elif(parameterName.find("7-Jets-11")>=0) :
- process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n"
- process+="set /Herwig/Cuts/QCDCuts:MHatMin 600.*GeV\n"
- elif(parameterName.find("7-Jets-12")>=0) :
- process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n"
- process+="set /Herwig/Cuts/QCDCuts:MHatMin 1000.*GeV\n"
- elif(parameterName.find("7-Jets-13")>=0) :
- process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n"
- process+="set /Herwig/Cuts/QCDCuts:MHatMin 1600.*GeV\n"
- elif(parameterName.find("7-Jets-14")>=0) :
- process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n"
- process+="set /Herwig/Cuts/QCDCuts:MHatMin 2200.*GeV\n"
- elif(parameterName.find("7-Jets-15")>=0) :
- process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n"
- process+="set /Herwig/Cuts/QCDCuts:MHatMin 2800.*GeV\n"
- elif(parameterName.find("7-Jets-1")>=0) :
- process+="set /Herwig/Cuts/JetKtCut:MinKT 10.\n"
- elif(parameterName.find("7-Jets-2")>=0) :
- process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n"
- elif(parameterName.find("7-Jets-3")>=0) :
+ elif(parameterName.find("Jets-3")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 40.\n"
- elif(parameterName.find("7-Jets-4")>=0) :
+ elif(parameterName.find("Jets-4")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 70.\n"
- elif(parameterName.find("7-Jets-5")>=0) :
+ elif(parameterName.find("Jets-5")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 150.\n"
- elif(parameterName.find("7-Jets-6")>=0) :
+ elif(parameterName.find("Jets-6")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 200.\n"
- elif(parameterName.find("7-Jets-7")>=0) :
+ elif(parameterName.find("Jets-7")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 300.\n"
- elif(parameterName.find("7-Jets-8")>=0) :
+ elif(parameterName.find("Jets-8")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 500.\n"
- elif(parameterName.find("7-Jets-9")>=0) :
- process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n"
- process+="set /Herwig/Cuts/QCDCuts:MHatMin 90.*GeV\n"
+ elif(parameterName.find("Jets-9")>=0) :
+ process+="set /Herwig/Cuts/JetKtCut:MinKT 800.\n"
elif(parameterName.find("7-Charm")>=0 or \
parameterName.find("7-Bottom")>=0) :
if(parameterName.find("7-Bottom")>=0) :
process+="cp MEHeavyQuark MEBottom\n"
process+="set MEBottom:QuarkType Bottom\n"
process+="insert SimpleQCD:MatrixElements[0] MEBottom\n"
else :
process+="cp MEHeavyQuark MECharm\n"
process+="set MECharm:QuarkType Charm\n"
process+="insert SimpleQCD:MatrixElements[0] MECharm\n"
process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n"
if(parameterName.find("-0")>=0) :
if(parameterName.find("7-Bottom")>=0) :
process+="set MEBottom:Process Pair\n"
process+="set /Herwig/Cuts/JetKtCut:MinKT 0.\n"
elif(parameterName.find("-1")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 5.\n"
elif(parameterName.find("-2")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 20.\n"
elif(parameterName.find("-3")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 50.\n"
elif(parameterName.find("-4")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 80.\n"
elif(parameterName.find("-5")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 110.\n"
elif(parameterName.find("-6")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 30.\n"
process+="set /Herwig/Cuts/QCDCuts:MHatMin 90.*GeV\n"
elif(parameterName.find("-7")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 30.\n"
process+="set /Herwig/Cuts/QCDCuts:MHatMin 340.*GeV\n"
elif(parameterName.find("-8")>=0) :
process+="set /Herwig/Cuts/JetKtCut:MinKT 30.\n"
process+="set /Herwig/Cuts/QCDCuts:MHatMin 500.*GeV\n"
elif(parameterName.find("Top-L")>=0) :
process+="set MEHeavyQuark:QuarkType Top\n"
process+="insert SimpleQCD:MatrixElements[0] MEHeavyQuark\n"
process+="do /Herwig/Particles/t:SelectDecayModes t->nu_e,e+,b; t->nu_mu,mu+,b;\n"
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
elif(parameterName.find("Top-SL")>=0) :
process+="set MEHeavyQuark:QuarkType Top\n"
process+="insert SimpleQCD:MatrixElements[0] MEHeavyQuark\n"
process+="set /Herwig/Particles/t:Synchronized Not_synchronized\n"
process+="set /Herwig/Particles/tbar:Synchronized Not_synchronized\n"
process+="do /Herwig/Particles/t:SelectDecayModes t->nu_e,e+,b; t->nu_mu,mu+,b;\n"
process+="do /Herwig/Particles/tbar:SelectDecayModes tbar->b,bbar,cbar; tbar->bbar,cbar,d; tbar->bbar,cbar,s; tbar->bbar,s,ubar; tbar->bbar,ubar,d;\n"
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
elif(parameterName.find("Top-All")>=0) :
process+="set MEHeavyQuark:QuarkType Top\n"
process+="insert SimpleQCD:MatrixElements[0] MEHeavyQuark\n"
elif(parameterName.find("WZ")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEPP2VV\nset MEPP2VV:Process WZ\n"
process+="do /Herwig/Particles/W+:SelectDecayModes /Herwig/Particles/W+/W+->nu_e,e+; /Herwig/Particles/W+/W+->nu_mu,mu+;\n"
process+="do /Herwig/Particles/W-:SelectDecayModes /Herwig/Particles/W-/W-->nu_ebar,e-; /Herwig/Particles/W-/W-->nu_mubar,mu-;\n"
process+="do /Herwig/Particles/Z0:SelectDecayModes /Herwig/Particles/Z0/Z0->e-,e+; /Herwig/Particles/Z0/Z0->mu-,mu+;\n"
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
elif(parameterName.find("WW-emu")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEPP2VV\nset MEPP2VV:Process WW\n"
process+="set /Herwig/Particles/W+:Synchronized 0\n"
process+="set /Herwig/Particles/W-:Synchronized 0\n"
process+="do /Herwig/Particles/W+:SelectDecayModes /Herwig/Particles/W+/W+->nu_e,e+;\n"
process+="do /Herwig/Particles/W-:SelectDecayModes /Herwig/Particles/W-/W-->nu_mubar,mu-;\n"
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
elif(parameterName.find("WW-ll")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEPP2VV\nset MEPP2VV:Process WW\n"
process+="do /Herwig/Particles/W+:SelectDecayModes /Herwig/Particles/W+/W+->nu_e,e+; /Herwig/Particles/W+/W+->nu_mu,mu+; /Herwig/Particles/W+/W+->nu_tau,tau+;\n"
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
elif(parameterName.find("ZZ-ll")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEPP2VV\nset MEPP2VV:Process ZZ\n"
process+="do /Herwig/Particles/Z0:SelectDecayModes /Herwig/Particles/Z0/Z0->e-,e+; /Herwig/Particles/Z0/Z0->mu-,mu+; /Herwig/Particles/Z0/Z0->tau-,tau+;\n"
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
elif(parameterName.find("ZZ-lv")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEPP2VV\nset MEPP2VV:Process ZZ\n"
process+="do /Herwig/Particles/Z0:SelectDecayModes /Herwig/Particles/Z0/Z0->e-,e+; /Herwig/Particles/Z0/Z0->mu-,mu+; /Herwig/Particles/Z0/Z0->tau-,tau+; /Herwig/Particles/Z0/Z0->nu_e,nu_ebar; /Herwig/Particles/Z0/Z0->nu_mu,nu_mubar; /Herwig/Particles/Z0/Z0->nu_tau,nu_taubar;\n"
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
elif(parameterName.find("W-Z-e")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Electron\n"
process+="insert SimpleQCD:MatrixElements[0] MEqq2W2ff\nset MEqq2W2ff:Process Electron\n"
elif(parameterName.find("W-Z-mu")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n"
process+="insert SimpleQCD:MatrixElements[0] MEqq2W2ff\nset MEqq2W2ff:Process Muon\n"
elif(parameterName.find("W-e")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEqq2W2ff\nset MEqq2W2ff:Process Electron\n"
elif(parameterName.find("W-mu")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEqq2W2ff\nset MEqq2W2ff:Process Muon\n"
elif(parameterName.find("Z-e")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Electron\n"
elif(parameterName.find("Z-mu")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n"
elif(parameterName.find("Z-LowMass-e")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Electron\n"
process+="set /Herwig/Cuts/QCDCuts:MHatMin 20.*GeV\nset /Herwig/Cuts/MassCut:MinM 20.*GeV\nset /Herwig/Cuts/MassCut:MaxM 70.*GeV\n"
elif(parameterName.find("Z-MedMass-e")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Electron\n"
process+="set /Herwig/Cuts/QCDCuts:MHatMin 40.*GeV\nset /Herwig/Cuts/MassCut:MinM 40.*GeV\nset /Herwig/Cuts/MassCut:MaxM 130.*GeV\n"
elif(parameterName.find("Z-LowMass-mu")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n"
process+="set /Herwig/Cuts/QCDCuts:MHatMin 10.*GeV\nset /Herwig/Cuts/MassCut:MinM 10.*GeV\nset /Herwig/Cuts/MassCut:MaxM 70.*GeV\n"
elif(parameterName.find("Z-Mass1")>=0) :
process+="set /Herwig/Cuts/QCDCuts:MHatMin 10.*GeV\n"
process+="set /Herwig/Cuts/MassCut:MinM 10.*GeV\n"
process+="set /Herwig/Cuts/MassCut:MaxM 35.*GeV\n"
if(parameterName.find("-e")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Electron\n"
else :
process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n"
elif(parameterName.find("Z-Mass2")>=0) :
process+="set /Herwig/Cuts/QCDCuts:MHatMin 25.*GeV\n"
process+="set /Herwig/Cuts/MassCut:MinM 25.*GeV\n"
process+="set /Herwig/Cuts/MassCut:MaxM 70.*GeV\n"
if(parameterName.find("-e")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Electron\n"
else :
process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n"
elif(parameterName.find("Z-Mass3")>=0) :
process+="set /Herwig/Cuts/QCDCuts:MHatMin 60.*GeV\n"
process+="set /Herwig/Cuts/MassCut:MinM 60.*GeV\n"
process+="set /Herwig/Cuts/MassCut:MaxM 120.*GeV\n"
if(parameterName.find("-e")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Electron\n"
else :
process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n"
elif(parameterName.find("Z-Mass4")>=0) :
process+="set /Herwig/Cuts/QCDCuts:MHatMin 110.*GeV\n"
process+="set /Herwig/Cuts/MassCut:MinM 110.*GeV\n"
process+="set /Herwig/Cuts/MassCut:MaxM 8000.*GeV\n"
if(parameterName.find("-e")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Electron\n"
else :
process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n"
elif(parameterName.find("W-Jet")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEWJet\nset MEWJet:WDecay Electron\n"
if(parameterName.find("W-Jet-1-e")>=0) :
process+="set /Herwig/Cuts/WBosonKtCut:MinKT 100.0*GeV\n"
parameterName=parameterName.replace("W-Jet-1-e","W-Jet-e")
elif(parameterName.find("W-Jet-2-e")>=0) :
process+="set /Herwig/Cuts/WBosonKtCut:MinKT 190.0*GeV\n"
parameterName=parameterName.replace("W-Jet-2-e","W-Jet-e")
elif(parameterName.find("W-Jet-3-e")>=0) :
process+="set /Herwig/Cuts/WBosonKtCut:MinKT 270.0*GeV\n"
parameterName=parameterName.replace("W-Jet-3-e","W-Jet-e")
elif(parameterName.find("Z-Jet")>=0) :
if(parameterName.find("-e")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEZJet\nset MEZJet:ZDecay Electron\n"
if(parameterName.find("Z-Jet-0-e")>=0) :
process+="set /Herwig/Cuts/ZBosonKtCut:MinKT 35.0*GeV\n"
parameterName=parameterName.replace("Z-Jet-0-e","Z-Jet-e")
elif(parameterName.find("Z-Jet-1-e")>=0) :
process+="set /Herwig/Cuts/ZBosonKtCut:MinKT 100.0*GeV\n"
parameterName=parameterName.replace("Z-Jet-1-e","Z-Jet-e")
elif(parameterName.find("Z-Jet-2-e")>=0) :
process+="set /Herwig/Cuts/ZBosonKtCut:MinKT 190.0*GeV\n"
parameterName=parameterName.replace("Z-Jet-2-e","Z-Jet-e")
elif(parameterName.find("Z-Jet-3-e")>=0) :
process+="set /Herwig/Cuts/ZBosonKtCut:MinKT 270.0*GeV\n"
parameterName=parameterName.replace("Z-Jet-3-e","Z-Jet-e")
else :
process+="insert SimpleQCD:MatrixElements[0] MEZJet\nset MEZJet:ZDecay Muon\n"
process+="set /Herwig/Cuts/ZBosonKtCut:MinKT 35.0*GeV\n"
parameterName=parameterName.replace("Z-Jet-0-mu","Z-Jet-mu")
elif(parameterName.find("WGamma")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEPP2VGamma\nset MEPP2VGamma:Process 1\nset MEPP2VGamma:MassOption 1\n"
process+="set /Herwig/Cuts/PhotonKtCut:MinKT 10.\n"
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
if(parameterName.find("-e")>=0) :
process+="do /Herwig/Particles/W+:SelectDecayModes W+->nu_e,e+;\n"
else :
process+="do /Herwig/Particles/W+:SelectDecayModes W+->nu_mu,mu+;\n"
elif(parameterName.find("ZGamma")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEPP2VGamma\nset MEPP2VGamma:Process 2\n"
process+="set /Herwig/Cuts/PhotonKtCut:MinKT 10.\n"
if(parameterName.find("-e")>=0) :
process+="do /Herwig/Particles/Z0:SelectDecayModes Z0->e-,e+;\n"
else :
process+="do /Herwig/Particles/Z0:SelectDecayModes Z0->mu-,mu+;\n"
else :
logging.error(" Process %s not supported for internal matrix elements" % name)
sys.exit(1)
elif(simulation=="Powheg") :
if(parameterName.find("8-VBF")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2HiggsVBF\n"
elif(parameterName.find("VBF")>=0) :
process+="do /Herwig/Particles/h0:SelectDecayModes h0->tau-,tau+;\n"
process+="set /Herwig/Particles/tau-:Stable Stable\n"
process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2HiggsVBF\n"
elif(parameterName.find("ggHJet")>=0) :
logging.error(" Process %s not supported for POWHEG matrix elements" % name)
sys.exit(1)
elif(parameterName.find("8-ggH")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEHiggs\n"
elif(parameterName.find("ggH")>=0) :
process+="do /Herwig/Particles/h0:SelectDecayModes h0->tau-,tau+;\n"
process+="set /Herwig/Particles/tau-:Stable Stable\n"
process+="insert SimpleQCD:MatrixElements[0] PowhegMEHiggs\n"
elif(parameterName.find("8-WH")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2WH\n"
process+="set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV\n"
elif(parameterName.find("8-ZH")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2ZH\n"
process+="set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV\n"
elif(parameterName.find("WH")>=0) :
process+="do /Herwig/Particles/h0:SelectDecayModes h0->b,bbar;\n"
process+="do /Herwig/Particles/W+:SelectDecayModes W+->nu_e,e+; W+->nu_mu,mu+;\n"
process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2WH\n"
process+="set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV\n"
elif(parameterName.find("ZH")>=0) :
process+="do /Herwig/Particles/h0:SelectDecayModes h0->b,bbar;\n"
process+="do /Herwig/Particles/Z0:SelectDecayModes Z0->e-,e+; Z0->mu-,mu+;\n"
process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2ZH\n"
process+="set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV\n"
elif(parameterName.find("UE")>=0) :
logging.error(" Process %s not supported for powheg matrix elements" % name)
sys.exit(1)
elif(parameterName.find("WZ")>=0) :
process+="create Herwig::HwDecayHandler /Herwig/NewPhysics/DecayHandler\n"
process+="set /Herwig/NewPhysics/DecayHandler:NewStep No\n"
process+="set /Herwig/Shower/ShowerHandler:SplitHardProcess No\n";
process+="set /Herwig/Decays/ZDecayer:PhotonGenerator NULL\n";
process+="set /Herwig/Decays/ZPowhegDecayer:PhotonGenerator NULL\n";
process+="set /Herwig/Decays/WDecayer:PhotonGenerator NULL\n";
process+="set /Herwig/Decays/WPowhegDecayer:PhotonGenerator NULL\n";
process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 0 /Herwig/Particles/tau-\n"
process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 1 /Herwig/Particles/tau+\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PreCascadeHandlers 0 /Herwig/NewPhysics/DecayHandler\n"
process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2VV\nset PowhegMEPP2VV:Process WZ\n"
process+="do /Herwig/Particles/W+:SelectDecayModes /Herwig/Particles/W+/W+->nu_e,e+; /Herwig/Particles/W+/W+->nu_mu,mu+;\n"
process+="do /Herwig/Particles/W-:SelectDecayModes /Herwig/Particles/W-/W-->nu_ebar,e-; /Herwig/Particles/W-/W-->nu_mubar,mu-;\n"
process+="do /Herwig/Particles/Z0:SelectDecayModes /Herwig/Particles/Z0/Z0->e-,e+; /Herwig/Particles/Z0/Z0->mu-,mu+;\n"
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
elif(parameterName.find("WW-emu")>=0) :
process+="create Herwig::HwDecayHandler /Herwig/NewPhysics/DecayHandler\n"
process+="set /Herwig/NewPhysics/DecayHandler:NewStep No\n"
process+="set /Herwig/Shower/ShowerHandler:SplitHardProcess No\n";
process+="set /Herwig/Decays/ZDecayer:PhotonGenerator NULL\n";
process+="set /Herwig/Decays/ZPowhegDecayer:PhotonGenerator NULL\n";
process+="set /Herwig/Decays/WDecayer:PhotonGenerator NULL\n";
process+="set /Herwig/Decays/WPowhegDecayer:PhotonGenerator NULL\n";
process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 0 /Herwig/Particles/tau-\n"
process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 1 /Herwig/Particles/tau+\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PreCascadeHandlers 0 /Herwig/NewPhysics/DecayHandler\n"
process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2VV\nset PowhegMEPP2VV:Process WW\n"
process+="set /Herwig/Particles/W+:Synchronized 0\n"
process+="set /Herwig/Particles/W-:Synchronized 0\n"
process+="do /Herwig/Particles/W+:SelectDecayModes /Herwig/Particles/W+/W+->nu_e,e+;\n"
process+="do /Herwig/Particles/W-:SelectDecayModes /Herwig/Particles/W-/W-->nu_mubar,mu-;\n"
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
elif(parameterName.find("WW-ll")>=0) :
process+="create Herwig::HwDecayHandler /Herwig/NewPhysics/DecayHandler\n"
process+="set /Herwig/NewPhysics/DecayHandler:NewStep No\n"
process+="set /Herwig/Shower/ShowerHandler:SplitHardProcess No\n";
process+="set /Herwig/Decays/ZDecayer:PhotonGenerator NULL\n";
process+="set /Herwig/Decays/ZPowhegDecayer:PhotonGenerator NULL\n";
process+="set /Herwig/Decays/WDecayer:PhotonGenerator NULL\n";
process+="set /Herwig/Decays/WPowhegDecayer:PhotonGenerator NULL\n";
process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 0 /Herwig/Particles/tau-\n"
process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 1 /Herwig/Particles/tau+\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PreCascadeHandlers 0 /Herwig/NewPhysics/DecayHandler\n"
process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2VV\nset PowhegMEPP2VV:Process WW\n"
process+="do /Herwig/Particles/W+:SelectDecayModes /Herwig/Particles/W+/W+->nu_e,e+; /Herwig/Particles/W+/W+->nu_mu,mu+; /Herwig/Particles/W+/W+->nu_tau,tau+;\n"
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
elif(parameterName.find("ZZ-ll")>=0) :
process+="create Herwig::HwDecayHandler /Herwig/NewPhysics/DecayHandler\n"
process+="set /Herwig/NewPhysics/DecayHandler:NewStep No\n"
process+="set /Herwig/Shower/ShowerHandler:SplitHardProcess No\n";
process+="set /Herwig/Decays/ZDecayer:PhotonGenerator NULL\n";
process+="set /Herwig/Decays/ZPowhegDecayer:PhotonGenerator NULL\n";
process+="set /Herwig/Decays/WDecayer:PhotonGenerator NULL\n";
process+="set /Herwig/Decays/WPowhegDecayer:PhotonGenerator NULL\n";
process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 0 /Herwig/Particles/tau-\n"
process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 1 /Herwig/Particles/tau+\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PreCascadeHandlers 0 /Herwig/NewPhysics/DecayHandler\n"
process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2VV\nset PowhegMEPP2VV:Process ZZ\n"
process+="do /Herwig/Particles/Z0:SelectDecayModes /Herwig/Particles/Z0/Z0->e-,e+; /Herwig/Particles/Z0/Z0->mu-,mu+; /Herwig/Particles/Z0/Z0->tau-,tau+;\n"
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
elif(parameterName.find("ZZ-lv")>=0) :
process+="create Herwig::HwDecayHandler /Herwig/NewPhysics/DecayHandler\n"
process+="set /Herwig/NewPhysics/DecayHandler:NewStep No\n"
process+="set /Herwig/Shower/ShowerHandler:SplitHardProcess No\n";
process+="set /Herwig/Decays/ZDecayer:PhotonGenerator NULL\n";
process+="set /Herwig/Decays/ZPowhegDecayer:PhotonGenerator NULL\n";
process+="set /Herwig/Decays/WDecayer:PhotonGenerator NULL\n";
process+="set /Herwig/Decays/WPowhegDecayer:PhotonGenerator NULL\n";
process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 0 /Herwig/Particles/tau-\n"
process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 1 /Herwig/Particles/tau+\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PreCascadeHandlers 0 /Herwig/NewPhysics/DecayHandler\n"
process+="insert SimpleQCD:MatrixElements[0] PowhegMEPP2VV\nset PowhegMEPP2VV:Process ZZ\n"
process+="do /Herwig/Particles/Z0:SelectDecayModes /Herwig/Particles/Z0/Z0->e-,e+; /Herwig/Particles/Z0/Z0->mu-,mu+; /Herwig/Particles/Z0/Z0->tau-,tau+; /Herwig/Particles/Z0/Z0->nu_e,nu_ebar; /Herwig/Particles/Z0/Z0->nu_mu,nu_mubar; /Herwig/Particles/Z0/Z0->nu_tau,nu_taubar;\n"
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
elif(parameterName.find("W-Z-e")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Electron\n"
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2W2ff\nset PowhegMEqq2W2ff:Process Electron\n"
elif(parameterName.find("W-Z-mu")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEqq2gZ2ff\nset MEqq2gZ2ff:Process Muon\n"
process+="insert SimpleQCD:MatrixElements[0] MEqq2W2ff\nset MEqq2W2ff:Process Muon\n"
elif(parameterName.find("W-e")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2W2ff\nset PowhegMEqq2W2ff:Process Electron\n"
elif(parameterName.find("W-mu")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2W2ff\nset PowhegMEqq2W2ff:Process Muon\n"
elif(parameterName.find("Z-e")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Electron\n"
elif(parameterName.find("Z-mu")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Muon\n"
elif(parameterName.find("Z-LowMass-e")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Electron\n"
process+="set /Herwig/Cuts/QCDCuts:MHatMin 20.*GeV\nset /Herwig/Cuts/MassCut:MinM 20.*GeV\nset /Herwig/Cuts/MassCut:MaxM 70.*GeV\n"
elif(parameterName.find("Z-MedMass-e")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Electron\n"
process+="set /Herwig/Cuts/QCDCuts:MHatMin 40.*GeV\nset /Herwig/Cuts/MassCut:MinM 40.*GeV\nset /Herwig/Cuts/MassCut:MaxM 130.*GeV\n"
elif(parameterName.find("Z-LowMass-mu")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Muon\n"
process+="set /Herwig/Cuts/QCDCuts:MHatMin 10.*GeV\nset /Herwig/Cuts/MassCut:MinM 10.*GeV\nset /Herwig/Cuts/MassCut:MaxM 70.*GeV\n"
elif(parameterName.find("Z-Mass1")>=0) :
process+="set /Herwig/Cuts/QCDCuts:MHatMin 10.*GeV\n"
process+="set /Herwig/Cuts/MassCut:MinM 10.*GeV\n"
process+="set /Herwig/Cuts/MassCut:MaxM 35.*GeV\n"
if(parameterName.find("-e")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Electron\n"
else :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Muon\n"
elif(parameterName.find("Z-Mass2")>=0) :
process+="set /Herwig/Cuts/QCDCuts:MHatMin 25.*GeV\n"
process+="set /Herwig/Cuts/MassCut:MinM 25.*GeV\n"
process+="set /Herwig/Cuts/MassCut:MaxM 70.*GeV\n"
if(parameterName.find("-e")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Electron\n"
else :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Muon\n"
elif(parameterName.find("Z-Mass3")>=0) :
process+="set /Herwig/Cuts/QCDCuts:MHatMin 60.*GeV\n"
process+="set /Herwig/Cuts/MassCut:MinM 60.*GeV\n"
process+="set /Herwig/Cuts/MassCut:MaxM 120.*GeV\n"
if(parameterName.find("-e")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Electron\n"
else :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Muon\n"
elif(parameterName.find("Z-Mass4")>=0) :
process+="set /Herwig/Cuts/QCDCuts:MHatMin 110.*GeV\n"
process+="set /Herwig/Cuts/MassCut:MinM 110.*GeV\n"
process+="set /Herwig/Cuts/MassCut:MaxM 8000.*GeV\n"
if(parameterName.find("-e")>=0) :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Electron\n"
else :
process+="insert SimpleQCD:MatrixElements[0] PowhegMEqq2gZ2ff\nset PowhegMEqq2gZ2ff:Process Muon\n"
elif(parameterName.find("DiPhoton-GammaGamma")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEGammaGammaPowheg\n"
process+="set MEGammaGammaPowheg:Process GammaGamma\n"
process+="insert SimpleQCD:MatrixElements[0] MEGammaGamma\n"
process+="set MEGammaGamma:Process gg\n"
process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n"
process+="set /Herwig/Cuts/JetKtCut:MinKT 5.\n"
parameterName=parameterName.replace("-GammaGamma","")
elif(parameterName.find("DiPhoton-GammaJet")>=0) :
process+="insert SimpleQCD:MatrixElements[0] MEGammaGammaPowheg\n"
process+="set MEGammaGammaPowheg:Process VJet\n"
process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n"
process+="set /Herwig/Cuts/JetKtCut:MinKT 5.\n"
parameterName=parameterName.replace("-GammaJet","")
else :
logging.error(" Process %s not supported for internal POWHEG matrix elements" % name)
sys.exit(1)
elif(simulation=="Matchbox" ) :
if(parameterName.find("8-VBF")>=0) :
parameters["nlo"] = "read Matchbox/VBFNLO.in\n"
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 3\n"
process+="insert Factory:DiagramGenerator:RestrictLines 0 /Herwig/Particles/Z0\n"
process+="insert Factory:DiagramGenerator:RestrictLines 0 /Herwig/Particles/W+\n"
process+="insert Factory:DiagramGenerator:RestrictLines 0 /Herwig/Particles/W-\n"
process+="insert Factory:DiagramGenerator:RestrictLines 0 /Herwig/Particles/gamma\n"
process+="do Factory:DiagramGenerator:TimeLikeRange 0 0\n"
process+="do Factory:Process p p h0 j j\n"
process+="set /Herwig/Particles/h0:HardProcessWidth 0.\n"
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n"
process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n"
if(parameterName.find("GammaGamma")>=0) :
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
elif(parameterName.find("VBF")>=0) :
process+="do /Herwig/Particles/h0:SelectDecayModes h0->tau-,tau+;\n"
process+="set /Herwig/Particles/tau-:Stable Stable\n"
parameters["nlo"] = "read Matchbox/VBFNLO.in\n"
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 3\n"
process+="insert Factory:DiagramGenerator:RestrictLines 0 /Herwig/Particles/Z0\n"
process+="insert Factory:DiagramGenerator:RestrictLines 0 /Herwig/Particles/W+\n"
process+="insert Factory:DiagramGenerator:RestrictLines 0 /Herwig/Particles/W-\n"
process+="insert Factory:DiagramGenerator:RestrictLines 0 /Herwig/Particles/gamma\n"
process+="do Factory:DiagramGenerator:TimeLikeRange 0 0\n"
process+="do Factory:Process p p h0 j j\n"
process+="set /Herwig/Particles/h0:HardProcessWidth 0.\n"
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n"
process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n"
elif(parameterName.find("ggHJet")>=0) :
parameters["nlo"] = "read Matchbox/MadGraph-GoSam.in\nread Matchbox/HiggsEffective.in\n"
process+="do /Herwig/Particles/h0:SelectDecayModes h0->tau-,tau+;\n"
process+="set /Herwig/Particles/tau-:Stable Stable\n"
process+="set Factory:OrderInAlphaS 3\nset Factory:OrderInAlphaEW 1\n"
process+="set /Herwig/Particles/h0:HardProcessWidth 0.\n"
process+="do Factory:Process p p h0 j\n"
process+="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n"
process+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n"
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n"
process+="set /Herwig/Cuts/FirstJet:PtMin 20.\n"
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n"
process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n"
elif(parameterName.find("8-ggH")>=0) :
parameters["nlo"] = "read Matchbox/MadGraph-GoSam.in\nread Matchbox/HiggsEffective.in\n"
process+="set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 1\n"
process+="set /Herwig/Particles/h0:HardProcessWidth 0.\n"
process+="do Factory:Process p p h0\n"
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n"
process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n"
if(parameterName.find("GammaGamma")>=0) :
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
elif(parameterName.find("ggH")>=0) :
parameters["nlo"] = "read Matchbox/MadGraph-GoSam.in\nread Matchbox/HiggsEffective.in\n"
process+="do /Herwig/Particles/h0:SelectDecayModes h0->tau-,tau+;\n"
process+="set /Herwig/Particles/tau-:Stable Stable\n"
process+="set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 1\n"
process+="set /Herwig/Particles/h0:HardProcessWidth 0.\n"
process+="do Factory:Process p p h0\n"
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n"
process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n"
elif(parameterName.find("8-WH")>=0) :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\n"
process+="set /Herwig/Particles/h0:HardProcessWidth 0.\n"
process+="do Factory:Process p p W+ h0\n"
process+="do Factory:Process p p W- h0\n"
process+="set /Herwig/Particles/W+:HardProcessWidth 0.\n"
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n"
process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n"
if(parameterName.find("GammaGamma")>=0) :
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
elif(parameterName.find("8-ZH")>=0) :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\n"
process+="set /Herwig/Particles/h0:HardProcessWidth 0.\n"
process+="set /Herwig/Particles/Z0:HardProcessWidth 0.\n"
process+="do Factory:Process p p Z0 h0\n"
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n"
process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n"
if(parameterName.find("GammaGamma")>=0) :
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
elif(parameterName.find("WH")>=0) :
process+="do /Herwig/Particles/h0:SelectDecayModes h0->b,bbar;\n"
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 3\n"
process+="set /Herwig/Particles/h0:HardProcessWidth 0.\n"
process+="do Factory:Process p p e+ nu h0\n"
process+="do Factory:Process p p e- nu h0\n"
process+="do Factory:Process p p mu+ nu h0\n"
process+="do Factory:Process p p mu- nu h0\n"
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
elif(parameterName.find("ZH")>=0) :
process+="do /Herwig/Particles/h0:SelectDecayModes h0->b,bbar;\n"
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 3\n"
process+="set /Herwig/Particles/h0:HardProcessWidth 0.\n"
process+="do Factory:Process p p e+ e- h0\n"
process+="do Factory:Process p p mu+ mu- h0\n"
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
elif(parameterName.find("UE")>=0) :
logging.error(" Process %s not supported for Matchbox matrix elements" % name)
sys.exit(1)
- elif(parameterName.find("7-Jets")>=0) :
+ elif(parameterName.find("7-DiJets")>=0 or parameterName.find("8-DiJets")>=0) :
process+="set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 0\n"
- process+="do Factory:Process p p j j\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/MaxJetPtScale\n"
+ process+="do Factory:Process p p j j\n"
+ process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/MaxJetPtScale\n"
process+="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n"
process+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n"
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n"
process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n"
- if(parameterName.find("7-Jets-0")>=0) :
+ process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n"
+ process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n"
+ process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n"
+ process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n"
+ process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n"
+ if(parameterName.find("-A")>=0) :
+ process+="set /Herwig/Cuts/FirstJet:PtMin 45.*GeV\n"
+ process+="set /Herwig/Cuts/SecondJet:PtMin 25.*GeV\n"
+ process+="set /Herwig/Cuts/FirstJet:YRange -3. 3.\n"
+ process+="set /Herwig/Cuts/SecondJet:YRange -3. 3.\n"
+ elif(parameterName.find("-B")>=0) :
+ process+="set /Herwig/Cuts/FirstJet:PtMin 20.*GeV\n"
+ process+="set /Herwig/Cuts/SecondJet:PtMin 15.*GeV\n"
+ process+="set /Herwig/Cuts/FirstJet:YRange -2.7 2.7\n"
+ process+="set /Herwig/Cuts/SecondJet:YRange -2.7 2.7\n"
+ elif(parameterName.find("-C")>=0) :
+ process+="set /Herwig/Cuts/FirstJet:PtMin 20.*GeV\n"
+ process+="set /Herwig/Cuts/SecondJet:PtMin 15.*GeV\n"
+ process+="set /Herwig/Cuts/FirstJet:YRange -4.8 4.8\n"
+ process+="set /Herwig/Cuts/SecondJet:YRange -4.8 4.8\n"
+ if(parameterName.find("DiJets-1")>=0) :
+ process+="set /Herwig/Cuts/JetPairMass:MassMin 90.*GeV\n"
+ elif(parameterName.find("DiJets-2")>=0) :
+ process+="set /Herwig/Cuts/JetPairMass:MassMin 200.*GeV\n"
+ elif(parameterName.find("DiJets-3")>=0) :
+ process+="set /Herwig/Cuts/JetPairMass:MassMin 450.*GeV\n"
+ elif(parameterName.find("DiJets-4")>=0) :
+ process+="set /Herwig/Cuts/JetPairMass:MassMin 750.*GeV\n"
+ elif(parameterName.find("DiJets-5")>=0) :
+ process+="set /Herwig/Cuts/JetPairMass:MassMin 950.*GeV\n"
+ elif(parameterName.find("DiJets-6")>=0) :
+ process+="set /Herwig/Cuts/JetPairMass:MassMin 1550.*GeV\n"
+ elif(parameterName.find("DiJets-7")>=0) :
+ process+="set /Herwig/Cuts/JetPairMass:MassMin 2150.*GeV\n"
+ elif(parameterName.find("DiJets-8")>=0) :
+ process+="set /Herwig/Cuts/JetPairMass:MassMin 2750.*GeV\n"
+ elif(parameterName.find("7-Jets")>=0 or parameterName.find("8-Jets")>=0) :
+ process+="set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 0\n"
+ process+="do Factory:Process p p j j\n"
+ process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/MaxJetPtScale\n"
+ process+="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n"
+ process+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n"
+ process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n"
+ process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n"
+ if(parameterName.find("Jets-10")>=0) :
+ process+="set /Herwig/Cuts/FirstJet:PtMin 1800.\n"
+ elif(parameterName.find("Jets-0")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 5.\n"
- elif(parameterName.find("7-Jets-10")>=0) :
- process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n"
- process+="set /Herwig/Cuts/FirstJet:PtMin 20.*GeV\n"
- process+="set /Herwig/Cuts/SecondJet:PtMin 15.*GeV\n"
- process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n"
- process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n"
- process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n"
- process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n"
- process+="set /Herwig/Cuts/JetPairMass:MassMin 200.*GeV\n"
- elif(parameterName.find("7-Jets-11")>=0) :
- process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n"
- process+="set /Herwig/Cuts/FirstJet:PtMin 20.*GeV\n"
- process+="set /Herwig/Cuts/SecondJet:PtMin 15.*GeV\n"
- process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n"
- process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n"
- process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n"
- process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n"
- process+="set /Herwig/Cuts/JetPairMass:MassMin 600.*GeV\n"
- elif(parameterName.find("7-Jets-12")>=0) :
- process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n"
- process+="set /Herwig/Cuts/FirstJet:PtMin 20.*GeV\n"
- process+="set /Herwig/Cuts/SecondJet:PtMin 15.*GeV\n"
- process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n"
- process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n"
- process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n"
- process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n"
- process+="set /Herwig/Cuts/JetPairMass:MassMin 1000.*GeV\n"
- elif(parameterName.find("7-Jets-13")>=0) :
- process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n"
- process+="set /Herwig/Cuts/FirstJet:PtMin 20.*GeV\n"
- process+="set /Herwig/Cuts/SecondJet:PtMin 15.*GeV\n"
- process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n"
- process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n"
- process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n"
- process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n"
- process+="set /Herwig/Cuts/JetPairMass:MassMin 1600.*GeV\n"
- elif(parameterName.find("7-Jets-14")>=0) :
- process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n"
- process+="set /Herwig/Cuts/FirstJet:PtMin 20.*GeV\n"
- process+="set /Herwig/Cuts/SecondJet:PtMin 15.*GeV\n"
- process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n"
- process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n"
- process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n"
- process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n"
- process+="set /Herwig/Cuts/JetPairMass:MassMin 2200.*GeV\n"
- elif(parameterName.find("7-Jets-15")>=0) :
- process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n"
- process+="set /Herwig/Cuts/FirstJet:PtMin 20.*GeV\n"
- process+="set /Herwig/Cuts/SecondJet:PtMin 15.*GeV\n"
- process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n"
- process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n"
- process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n"
- process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n"
- process+="set /Herwig/Cuts/JetPairMass:MassMin 2800.*GeV\n"
- elif(parameterName.find("7-Jets-1")>=0) :
+ elif(parameterName.find("Jets-1")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 10.\n"
- elif(parameterName.find("7-Jets-2")>=0) :
+ elif(parameterName.find("Jets-2")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 20.\n"
- elif(parameterName.find("7-Jets-3")>=0) :
+ elif(parameterName.find("Jets-3")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 40.\n"
- elif(parameterName.find("7-Jets-4")>=0) :
+ elif(parameterName.find("Jets-4")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 70.\n"
- elif(parameterName.find("7-Jets-5")>=0) :
+ elif(parameterName.find("Jets-5")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 150.\n"
- elif(parameterName.find("7-Jets-6")>=0) :
+ elif(parameterName.find("Jets-6")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 200.\n"
- elif(parameterName.find("7-Jets-7")>=0) :
+ elif(parameterName.find("Jets-7")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 300.\n"
- elif(parameterName.find("7-Jets-8")>=0) :
+ elif(parameterName.find("Jets-8")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 500.\n"
- elif(parameterName.find("7-Jets-9")>=0) :
- process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n"
- process+="set /Herwig/Cuts/FirstJet:PtMin 20.*GeV\n"
- process+="set /Herwig/Cuts/SecondJet:PtMin 15.*GeV\n"
- process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n"
- process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n"
- process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n"
- process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n"
- process+="set /Herwig/Cuts/JetPairMass:MassMin 90.*GeV\n"
+ elif(parameterName.find("Jets-9")>=0) :
+ process+="set /Herwig/Cuts/FirstJet:PtMin 800.\n"
elif(parameterName.find("7-Charm")>=0 or \
parameterName.find("7-Bottom")>=0) :
parameters["bscheme"]="read Matchbox/FourFlavourScheme.in"
process+="set /Herwig/Particles/b:HardProcessMass 4.2*GeV\n"
process+="set /Herwig/Particles/bbar:HardProcessMass 4.2*GeV\n"
process+="set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 0\n"
if(parameterName.find("7-Bottom")>=0) :
process+="do Factory:Process p p b bbar\n"
else:
process+="do Factory:Process p p c cbar\n"
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/MaxJetPtScale\n"
process+="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n"
process+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n"
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n"
process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n"
if(parameterName.find("-0")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 0.\n"
elif(parameterName.find("-1")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 5.\n"
elif(parameterName.find("-2")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 20.\n"
elif(parameterName.find("-3")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 50.\n"
elif(parameterName.find("-4")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 80.\n"
elif(parameterName.find("-5")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 110.\n"
elif(parameterName.find("-6")>=0) :
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n"
process+="set /Herwig/Cuts/FirstJet:PtMin 30.\n"
process+="set /Herwig/Cuts/SecondJet:PtMin 25.\n"
process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n"
process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n"
process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n"
process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n"
process+="set /Herwig/Cuts/JetPairMass:MassMin 90.*GeV\n"
elif(parameterName.find("-7")>=0) :
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n"
process+="set /Herwig/Cuts/FirstJet:PtMin 30.\n"
process+="set /Herwig/Cuts/SecondJet:PtMin 25.\n"
process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n"
process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n"
process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n"
process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n"
process+="set /Herwig/Cuts/JetPairMass:MassMin 340.*GeV\n"
elif(parameterName.find("-8")>=0) :
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n"
process+="set /Herwig/Cuts/FirstJet:PtMin 30.\n"
process+="set /Herwig/Cuts/SecondJet:PtMin 25.\n"
process+="create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so\n"
process+="set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet\n"
process+="set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet\n"
process+="insert /Herwig/Cuts/JetCuts:JetPairRegions 0 /Herwig/Cuts/JetPairMass\n"
process+="set /Herwig/Cuts/JetPairMass:MassMin 500.*GeV\n"
elif(parameterName.find("Top-L")>=0) :
process+="set /Herwig/Particles/t:HardProcessWidth 0.*GeV\n"
process+="set /Herwig/Particles/tbar:HardProcessWidth 0.*GeV\n"
process+="set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 0\n"
process+="do Factory:Process p p t tbar\n"
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/TopPairMTScale\n"
process+="do /Herwig/Particles/t:SelectDecayModes t->nu_e,e+,b; t->nu_mu,mu+,b;\n"
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
elif(parameterName.find("Top-SL")>=0) :
process+="set /Herwig/Particles/t:HardProcessWidth 0.*GeV\n"
process+="set /Herwig/Particles/tbar:HardProcessWidth 0.*GeV\n"
process+="set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 0\n"
process+="do Factory:Process p p t tbar\n"
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/TopPairMTScale\n"
process+="set /Herwig/Particles/t:Synchronized Not_synchronized\n"
process+="set /Herwig/Particles/tbar:Synchronized Not_synchronized\n"
process+="do /Herwig/Particles/t:SelectDecayModes t->nu_e,e+,b; t->nu_mu,mu+,b;\n"
process+="do /Herwig/Particles/tbar:SelectDecayModes tbar->b,bbar,cbar; tbar->bbar,cbar,d; tbar->bbar,cbar,s; tbar->bbar,s,ubar; tbar->bbar,ubar,d;\n"
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
elif(parameterName.find("Top-All")>=0) :
process+="set /Herwig/Particles/t:HardProcessWidth 0.*GeV\n"
process+="set /Herwig/Particles/tbar:HardProcessWidth 0.*GeV\n"
process+="set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 0\n"
process+="do Factory:Process p p t tbar\n"
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/TopPairMTScale\n"
elif(parameterName.find("WZ")>=0) :
process+="set /Herwig/Particles/W+:HardProcessWidth 0.*GeV\n"
process+="set /Herwig/Particles/W-:HardProcessWidth 0.*GeV\n"
process+="set /Herwig/Particles/Z0:HardProcessWidth 0.*GeV\n"
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p W+ Z0\ndo Factory:Process p p W- Z0\n"
process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 171.6*GeV\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n\n"
process+="do /Herwig/Particles/W+:SelectDecayModes /Herwig/Particles/W+/W+->nu_e,e+; /Herwig/Particles/W+/W+->nu_mu,mu+;\n"
process+="do /Herwig/Particles/W-:SelectDecayModes /Herwig/Particles/W-/W-->nu_ebar,e-; /Herwig/Particles/W-/W-->nu_mubar,mu-;\n"
process+="do /Herwig/Particles/Z0:SelectDecayModes /Herwig/Particles/Z0/Z0->e-,e+; /Herwig/Particles/Z0/Z0->mu-,mu+;\n"
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
elif(parameterName.find("WW-emu")>=0) :
process+="set /Herwig/Particles/W+:HardProcessWidth 0.*GeV\n"
process+="set /Herwig/Particles/W-:HardProcessWidth 0.*GeV\n"
process+="set /Herwig/Particles/Z0:HardProcessWidth 0.*GeV\n"
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p W+ W-\n"
process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 160.8*GeV\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n"
process+="set /Herwig/Particles/W+:Synchronized 0\n"
process+="set /Herwig/Particles/W-:Synchronized 0\n"
process+="do /Herwig/Particles/W+:SelectDecayModes /Herwig/Particles/W+/W+->nu_e,e+;\n"
process+="do /Herwig/Particles/W-:SelectDecayModes /Herwig/Particles/W-/W-->nu_mubar,mu-;\n"
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
elif(parameterName.find("WW-ll")>=0) :
process+="set /Herwig/Particles/W+:HardProcessWidth 0.*GeV\n"
process+="set /Herwig/Particles/W-:HardProcessWidth 0.*GeV\n"
process+="set /Herwig/Particles/Z0:HardProcessWidth 0.*GeV\n"
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p W+ W-\n"
process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 160.8*GeV\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n"
process+="do /Herwig/Particles/W+:SelectDecayModes /Herwig/Particles/W+/W+->nu_e,e+; /Herwig/Particles/W+/W+->nu_mu,mu+; /Herwig/Particles/W+/W+->nu_tau,tau+;\n"
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
elif(parameterName.find("ZZ-ll")>=0) :
process+="set /Herwig/Particles/W+:HardProcessWidth 0.*GeV\n"
process+="set /Herwig/Particles/W-:HardProcessWidth 0.*GeV\n"
process+="set /Herwig/Particles/Z0:HardProcessWidth 0.*GeV\n"
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p Z0 Z0\n"
process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 182.2*GeV\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n"
process+="do /Herwig/Particles/Z0:SelectDecayModes /Herwig/Particles/Z0/Z0->e-,e+; /Herwig/Particles/Z0/Z0->mu-,mu+; /Herwig/Particles/Z0/Z0->tau-,tau+;\n"
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
elif(parameterName.find("ZZ-lv")>=0) :
process+="set /Herwig/Particles/W+:HardProcessWidth 0.*GeV\n"
process+="set /Herwig/Particles/W-:HardProcessWidth 0.*GeV\n"
process+="set /Herwig/Particles/Z0:HardProcessWidth 0.*GeV\n"
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p Z0 Z0\n"
process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 182.2*GeV\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n"
process+="do /Herwig/Particles/Z0:SelectDecayModes /Herwig/Particles/Z0/Z0->e-,e+; /Herwig/Particles/Z0/Z0->mu-,mu+; /Herwig/Particles/Z0/Z0->tau-,tau+; /Herwig/Particles/Z0/Z0->nu_e,nu_ebar; /Herwig/Particles/Z0/Z0->nu_mu,nu_mubar; /Herwig/Particles/Z0/Z0->nu_tau,nu_taubar;\n"
process+="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
process+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
elif(parameterName.find("W-Z-e")>=0) :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\n"
process+="do Factory:Process p p e+ e-\ndo Factory:Process p p e+ nu\ndo Factory:Process p p e- nu\n"
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
elif(parameterName.find("W-Z-mu")>=0) :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\n"
process+="do Factory:Process p p mu+ mu-\ndo Factory:Process p p mu+ nu\ndo Factory:Process p p mu- nu\n"
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
elif(parameterName.find("W-e")>=0) :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ nu\ndo Factory:Process p p e- nu\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
elif(parameterName.find("W-mu")>=0) :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p mu+ nu\ndo Factory:Process p p mu- nu\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
elif(parameterName.find("Z-e")>=0) :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ e-\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
elif(parameterName.find("Z-mu")>=0) :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p mu+ mu-\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
elif(parameterName.find("Z-jj")>=0) :
process+="set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 2\n"
process+="do Factory:Process p p e+ e- j j\n"
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n"
process+="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n"
process+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n"
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n"
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n"
process+="set /Herwig/Cuts/FirstJet:PtMin 40.*GeV\n"
process+="set /Herwig/Cuts/SecondJet:PtMin 30.*GeV\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
elif(parameterName.find("Z-LowMass-e")>=0) :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ e-\n"
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 20*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 70*GeV\n"
elif(parameterName.find("Z-MedMass-e")>=0) :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ e-\n"
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 40*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 130*GeV\n"
elif(parameterName.find("Z-LowMass-mu")>=0) :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p mu+ mu-\n"
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 10*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 70*GeV\n"
elif(parameterName.find("Z-Mass1")>=0) :
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 10*GeV\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MaxMass 35*GeV\n"
if(parameterName.find("-e")>=0) :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ e-\n"
else :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p mu+ mu-\n"
elif(parameterName.find("Z-Mass2")>=0) :
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 25*GeV\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MaxMass 70*GeV\n"
if(parameterName.find("-e")>=0) :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ e-\n"
else :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p mu+ mu-\n"
elif(parameterName.find("Z-Mass3")>=0) :
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
if(parameterName.find("-e")>=0) :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ e-\n"
else :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p mu+ mu-\n"
elif(parameterName.find("Z-Mass4")>=0) :
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPairMassScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 115*GeV\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MaxMass 8000*GeV\n"
if(parameterName.find("-e")>=0) :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ e-\n"
else :
process+="set Factory:OrderInAlphaS 0\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p mu+ mu-\n"
elif(parameterName.find("W-Jet")>=0) :
process+="set Factory:OrderInAlphaS 1\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ nu j\ndo Factory:Process p p e- nu j\n\n"
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/HTScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
process+="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n"
process+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n"
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n"
if(parameterName.find("W-Jet-1-e")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 100.*GeV\n"
parameterName=parameterName.replace("W-Jet-1-e","W-Jet-e")
elif(parameterName.find("W-Jet-2-e")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 190.0*GeV\n"
parameterName=parameterName.replace("W-Jet-2-e","W-Jet-e")
elif(parameterName.find("W-Jet-3-e")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 270.0*GeV\n"
parameterName=parameterName.replace("W-Jet-3-e","W-Jet-e")
elif(parameterName.find("Z-Jet")>=0) :
process+="set Factory:OrderInAlphaS 1\nset Factory:OrderInAlphaEW 2\n"
if(parameterName.find("-e")>=0) :
process+="do Factory:Process p p e+ e- j\n"
if(parameterName.find("Z-Jet-0-e")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 35.*GeV\n"
parameterName=parameterName.replace("Z-Jet-0-e","Z-Jet-e")
elif(parameterName.find("Z-Jet-1-e")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 100.*GeV\n"
parameterName=parameterName.replace("Z-Jet-1-e","Z-Jet-e")
elif(parameterName.find("Z-Jet-2-e")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 190.0*GeV\n"
parameterName=parameterName.replace("Z-Jet-2-e","Z-Jet-e")
elif(parameterName.find("Z-Jet-3-e")>=0) :
process+="set /Herwig/Cuts/FirstJet:PtMin 270.0*GeV\n"
parameterName=parameterName.replace("Z-Jet-3-e","Z-Jet-e")
else :
process+="do Factory:Process p p mu+ mu- j\n"
process+="set /Herwig/Cuts/FirstJet:PtMin 35.*GeV\n"
parameterName=parameterName.replace("Z-Jet-0-mu","Z-Jet-mu")
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
process+="set Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/HTScale\n"
process+="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n"
process+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n"
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n"
elif(parameterName.find("Z-bb")>=0) :
parameters["bscheme"]="read Matchbox/FourFlavourScheme.in"
process+="set /Herwig/Particles/b:HardProcessMass 4.2*GeV\nset /Herwig/Particles/bbar:HardProcessMass 4.2*GeV\n"
process+="set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ e- b bbar\n"
process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 91.2*GeV\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 66*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 116*GeV\n"
process+="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n"
process+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n"
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n"
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/SecondJet\n"
process+="set /Herwig/Cuts/FirstJet:PtMin 18.*GeV\n"
process+="set /Herwig/Cuts/SecondJet:PtMin 15.*GeV\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
elif(parameterName.find("Z-b")>=0) :
process+="do Factory:StartParticleGroup bjet\n"
process+="insert Factory:ParticleGroup 0 /Herwig/Particles/b\n"
process+="insert Factory:ParticleGroup 0 /Herwig/Particles/bbar\n"
process+="do Factory:EndParticleGroup\n"
process+="set Factory:OrderInAlphaS 1\nset Factory:OrderInAlphaEW 2\ndo Factory:Process p p e+ e- bjet\n"
process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 91.2*GeV\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
process+="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n"
process+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n"
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n"
process+="set /Herwig/Cuts/FirstJet:PtMin 15.*GeV\n"
elif(parameterName.find("W-b")>=0) :
parameters["bscheme"]="read Matchbox/FourFlavourScheme.in"
process += "set /Herwig/Particles/b:HardProcessMass 4.2*GeV\nset /Herwig/Particles/bbar:HardProcessMass 4.2*GeV\n"
process += "set Factory:OrderInAlphaS 2\nset Factory:OrderInAlphaEW 2\n"
process += "do Factory:Process p p e+ nu b bbar\ndo Factory:Process p p e- nu b bbar\n"
process += "do Factory:Process p p mu+ nu b bbar\ndo Factory:Process p p mu- nu b bbar\n"
process += "set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 80.4*GeV\nset Factory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n"
process+="set /Herwig/Cuts/Cuts:JetFinder /Herwig/Cuts/JetFinder\n"
process+="insert /Herwig/Cuts/Cuts:MultiCuts 0 /Herwig/Cuts/JetCuts\n"
process+="insert /Herwig/Cuts/JetCuts:JetRegions 0 /Herwig/Cuts/FirstJet\n"
process+="set /Herwig/Cuts/FirstJet:PtMin 30.*GeV\n"
process+="set /Herwig/Cuts/LeptonPairMassCut:MinMass 60*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass 120*GeV\n"
else :
logging.error(" Process %s not supported for Matchbox matrix elements" % name)
sys.exit(1)
# LHC-GammaGamma
elif(collider=="LHC-GammaGamma" ) :
if(parameterName.find("-7-")>=0) :
process="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 7000.0\n"
elif(parameterName.find("-8-")>=0) :
process="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 8000.0\n"
else :
process="set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 7000.0\n"
if(simulation=="") :
if(parameterName.find("7")>=0) :
process += "insert SimpleQCD:MatrixElements 0 /Herwig/MatrixElements/MEgg2ff\n"
process += "set /Herwig/MatrixElements/MEgg2ff:Process Muon\n"
else :
logging.error(" Process %s not supported for default matrix elements" % name)
sys.exit(1)
else :
logging.error("LHC-GammaGamma not supported for %s " % simulation)
sys.exit(1)
parameters['parameterFile'] = os.path.join(collider,collider+"-"+parameterName+".in")
parameters['runname'] = name
parameters['process'] = process
# write the file
if(simulation=="Matchbox" ) :
with open(os.path.join("Rivet",name+".in") ,'w') as f:
f.write( template.substitute(parameters))
else :
with open(os.path.join("Rivet",name+".in") ,'w') as f:
f.write( template.substitute(parameters))
diff --git a/Tests/python/merge-LEP b/Tests/python/merge-LEP
--- a/Tests/python/merge-LEP
+++ b/Tests/python/merge-LEP
@@ -1,871 +1,917 @@
#! /usr/bin/env python
# import lighthisto
import logging
import sys
if sys.version_info[:3] < (2,4,0):
print "rivet scripts require Python version >= 2.4.0... exiting"
sys.exit(1)
import os, yoda, copy
# # #############################################
def fillAbove(desthisto, sourcehistosbysqrts):
if type(desthisto) is yoda.core.Scatter2D :
if(desthisto.numPoints!=1) :
print desthisto.numPoints
logging.error("Must have one bin for a specific sqrt(s) for %s" % desthisto.path)
sys.exit(1)
for sqrts, h in sorted(sourcehistosbysqrts.iteritems()) :
if(h.numPoints!=1) :
continue
if(desthisto.points[0].x != h.points[0].x) :
desthisto.addPoint(h.points[0])
else :
logging.error("Unknown analysis object" + desthisto.path)
sys.exit(1)
def merge(hpath):
global inhistos
global outhistos
try:
fillAbove(outhistos[hpath], inhistos[hpath])
except:
pass
def useOne(hpath, sqrts):
global inhistos
global outhistos
try:
outhistos[hpath] = inhistos[hpath][float(sqrts)]
except:
pass
if __name__ == "__main__":
import logging
from optparse import OptionParser, OptionGroup
parser = OptionParser(usage="%prog name")
verbgroup = OptionGroup(parser, "Verbosity control")
verbgroup.add_option("-v", "--verbose", action="store_const", const=logging.DEBUG, dest="LOGLEVEL",
default=logging.INFO, help="print debug (very verbose) messages")
verbgroup.add_option("-q", "--quiet", action="store_const", const=logging.WARNING, dest="LOGLEVEL",
default=logging.INFO, help="be very quiet")
parser.add_option_group(verbgroup)
+ parser.add_option("--with-gg",
+ action='store_true' ,
+ dest="gg",
+ default=False,
+ help="Include gg analyese")
+ parser.add_option("--without-gg",
+ action='store_false',
+ dest="gg",
+ default=False,
+ help="Don\'t include gg analyses")
(opts, args) = parser.parse_args()
logging.basicConfig(level=opts.LOGLEVEL, format="%(message)s")
-
## Check args
if len(args) < 1:
logging.error("Must specify at least the name of the files")
sys.exit(1)
#######################################
-yodafiles=["-130.yoda","-133.yoda","-136.yoda","-177.yoda","-192.yoda",
- "-196.yoda","-202.yoda","-206.yoda","-91.yoda" ,"-91-nopi.yoda" ,\
- "-161.yoda","-183.yoda","-197.yoda","-35.yoda" ,"-172.yoda",\
- "-189.yoda","-200.yoda","-44.yoda","-14.yoda","-22.yoda","-10.yoda" ]
-
+yodafiles=["-130","-133","-136","-177","-192",
+ "-196","-202","-206","-91" ,"-91-nopi" ,\
+ "-161","-183","-197","-35" ,"-172",\
+ "-189","-200","-44","-14","-22","-10",\
+ "-12.8","-26.8","-48.0","-93.0" ]
+# add gg if needed
+if(opts.gg) :
+ yodafiles += ["-10.5-gg","-12.8-gg","-16.86-gg","-26.8-gg",\
+ "-35.44-gg","-97.0-gg","-11.96-gg","-13.96-gg",\
+ "-21.84-gg","-28.48-gg","-48.0-gg"]
## Get histos
inhistos = {}
outhistos={}
for f in yodafiles:
- file = args[0]+f
- if(file.find("10")>0) :
+ file = args[0]+f+".yoda"
+ if(file.find("10.5")>0) :
+ sqrts=10.5
+ elif(file.find("10")>0) :
sqrts=10
+ elif(file.find("11.96")>0) :
+ sqrts=11.96
+ elif(file.find("12.8")>0) :
+ sqrts=12.8
+ elif(file.find("13.96")>0) :
+ sqrts=13.96
elif(file.find("14")>0) :
sqrts=14
+ elif(file.find("16.86")>0) :
+ sqrts=16.86
+ elif(file.find("21.84")>0) :
+ sqrts=21.84
elif(file.find("22")>0) :
sqrts=22
+ elif(file.find("26.8")>0) :
+ sqrts=26.8
+ elif(file.find("28.48")>0) :
+ sqrts=28.48
elif(file.find("35")>0) :
sqrts=35
elif(file.find("44")>0) :
sqrts=44
+ elif(file.find("48.0")>0) :
+ sqrts=48.0
elif(file.find("91")>0) :
sqrts=91
+ elif(file.find("93.0")>0) :
+ sqrts=93
+ elif(file.find("97.0")>0) :
+ sqrts=97
elif(file.find("130")>0) :
sqrts=130
elif(file.find("133")>0) :
sqrts=133
elif(file.find("136")>0) :
sqrts=136
elif(file.find("161")>0) :
sqrts=161
elif(file.find("172")>0) :
sqrts=172
elif(file.find("177")>0) :
sqrts=177
elif(file.find("183")>0) :
sqrts=183
elif(file.find("189")>0) :
sqrts=189
elif(file.find("192")>0) :
sqrts=192
elif(file.find("196")>0) :
sqrts=196
elif(file.find("197")>0) :
sqrts=197
elif(file.find("200")>0) :
sqrts=200
elif(file.find("202")>0) :
sqrts=202
elif(file.find("206")>0) :
sqrts=206
+ else :
+ print file
+ quit()
if not os.access(file, os.R_OK):
logging.error("%s can not be read" % file)
continue
try:
aos = yoda.read(file)
except:
logging.error("%s can not be parsed as yoda" % file)
continue
## Get histos from this YODA file
for aopath, ao in aos.iteritems() :
# jet shapes
if(aopath.find("4300807")>0 or aopath.find("6132243")>0 or
aopath.find("5765862")>0 or aopath.find("3612880")>0 or
aopath.find("4328825")>0 or aopath.find("5361494")>0 or
aopath.find("2148048")>0 or aopath.find("MULTIPLICITIES")>0 ) :
if not inhistos.has_key(aopath):
inhistos[aopath] = {}
if not inhistos[aopath].has_key(sqrts):
inhistos[aopath][sqrts] = ao
else:
raise Exception("A set with sqrts = %s already exists" % ( sqrts))
+ elif(aopath.find("OPAL_2004_I648738")>=0) :
+ if(file.find("gg")>=0) :
+ if(aopath.find("y03")>=0) :
+ outhistos[aopath] = ao
+ else :
+ if(aopath.find("y03")<0) :
+ outhistos[aopath] = ao
else :
outhistos[aopath] = ao
# ## Make empty output histos if needed
for hpath,hsets in inhistos.iteritems():
if( hpath.find("4300807")>0 or hpath.find("6132243")>0 or
hpath.find("5765862")>0 or
hpath.find("4328825")>0 or hpath.find("5361494")>0) :
# workhisto = copy.deepcopy(hsets.values()[0])
# outhistos[hpath] = workhisto
outhistos[hpath] = hsets.values()[0]
# tasso
useOne("/TASSO_1990_S2148048/d06-x01-y01","14")
useOne("/TASSO_1990_S2148048/d07-x01-y01","14")
useOne("/TASSO_1990_S2148048/d08-x01-y01","14")
useOne("/TASSO_1990_S2148048/d06-x01-y02","22")
useOne("/TASSO_1990_S2148048/d07-x01-y02","22")
useOne("/TASSO_1990_S2148048/d08-x01-y02","22")
useOne("/TASSO_1990_S2148048/d06-x01-y03","35")
useOne("/TASSO_1990_S2148048/d07-x01-y03","35")
useOne("/TASSO_1990_S2148048/d08-x01-y03","35")
useOne("/TASSO_1990_S2148048/d06-x01-y04","44")
useOne("/TASSO_1990_S2148048/d07-x01-y04","44")
useOne("/TASSO_1990_S2148048/d08-x01-y04","44")
# jade
useOne("/JADE_1998_S3612880/d02-x01-y01","44")
useOne("/JADE_1998_S3612880/d03-x01-y01","44")
useOne("/JADE_1998_S3612880/d04-x01-y01","44")
useOne("/JADE_1998_S3612880/d05-x01-y01","44")
useOne("/JADE_1998_S3612880/d06-x01-y01","35")
useOne("/JADE_1998_S3612880/d07-x01-y01","35")
useOne("/JADE_1998_S3612880/d08-x01-y01","35")
useOne("/JADE_1998_S3612880/d09-x01-y01","35")
useOne("/JADE_1998_S3612880/d10-x01-y01","44")
useOne("/JADE_1998_S3612880/d11-x01-y01","35")
useOne("/JADE_1998_S3612880/d12-x01-y01","22")
# opal/jade
useOne("/JADE_OPAL_2000_S4300807/d07-x01-y01","35")
useOne("/JADE_OPAL_2000_S4300807/d07-x01-y02","35")
useOne("/JADE_OPAL_2000_S4300807/d07-x01-y03","35")
useOne("/JADE_OPAL_2000_S4300807/d07-x01-y04","35")
useOne("/JADE_OPAL_2000_S4300807/d07-x01-y05","35")
useOne("/JADE_OPAL_2000_S4300807/d08-x01-y01","44")
useOne("/JADE_OPAL_2000_S4300807/d08-x01-y02","44")
useOne("/JADE_OPAL_2000_S4300807/d08-x01-y03","44")
useOne("/JADE_OPAL_2000_S4300807/d08-x01-y04","44")
useOne("/JADE_OPAL_2000_S4300807/d08-x01-y05","44")
useOne("/JADE_OPAL_2000_S4300807/d09-x01-y01","91")
useOne("/JADE_OPAL_2000_S4300807/d09-x01-y02","91")
useOne("/JADE_OPAL_2000_S4300807/d09-x01-y03","91")
useOne("/JADE_OPAL_2000_S4300807/d09-x01-y04","91")
useOne("/JADE_OPAL_2000_S4300807/d09-x01-y05","91")
useOne("/JADE_OPAL_2000_S4300807/d10-x01-y01","133")
useOne("/JADE_OPAL_2000_S4300807/d10-x01-y02","133")
useOne("/JADE_OPAL_2000_S4300807/d10-x01-y03","133")
useOne("/JADE_OPAL_2000_S4300807/d10-x01-y04","133")
useOne("/JADE_OPAL_2000_S4300807/d10-x01-y05","133")
useOne("/JADE_OPAL_2000_S4300807/d11-x01-y01","161")
useOne("/JADE_OPAL_2000_S4300807/d11-x01-y02","161")
useOne("/JADE_OPAL_2000_S4300807/d11-x01-y03","161")
useOne("/JADE_OPAL_2000_S4300807/d11-x01-y04","161")
useOne("/JADE_OPAL_2000_S4300807/d11-x01-y05","161")
useOne("/JADE_OPAL_2000_S4300807/d12-x01-y01","172")
useOne("/JADE_OPAL_2000_S4300807/d12-x01-y02","172")
useOne("/JADE_OPAL_2000_S4300807/d12-x01-y03","172")
useOne("/JADE_OPAL_2000_S4300807/d12-x01-y04","172")
useOne("/JADE_OPAL_2000_S4300807/d12-x01-y05","172")
useOne("/JADE_OPAL_2000_S4300807/d13-x01-y01","183")
useOne("/JADE_OPAL_2000_S4300807/d13-x01-y02","183")
useOne("/JADE_OPAL_2000_S4300807/d13-x01-y03","183")
useOne("/JADE_OPAL_2000_S4300807/d13-x01-y04","183")
useOne("/JADE_OPAL_2000_S4300807/d13-x01-y05","183")
useOne("/JADE_OPAL_2000_S4300807/d14-x01-y01","189")
useOne("/JADE_OPAL_2000_S4300807/d14-x01-y02","189")
useOne("/JADE_OPAL_2000_S4300807/d14-x01-y03","189")
useOne("/JADE_OPAL_2000_S4300807/d14-x01-y04","189")
useOne("/JADE_OPAL_2000_S4300807/d14-x01-y05","189")
useOne("/JADE_OPAL_2000_S4300807/d16-x01-y01","35")
useOne("/JADE_OPAL_2000_S4300807/d16-x01-y02","35")
useOne("/JADE_OPAL_2000_S4300807/d16-x01-y03","35")
useOne("/JADE_OPAL_2000_S4300807/d16-x01-y04","35")
useOne("/JADE_OPAL_2000_S4300807/d16-x01-y05","35")
useOne("/JADE_OPAL_2000_S4300807/d17-x01-y01","44")
useOne("/JADE_OPAL_2000_S4300807/d17-x01-y02","44")
useOne("/JADE_OPAL_2000_S4300807/d17-x01-y03","44")
useOne("/JADE_OPAL_2000_S4300807/d17-x01-y04","44")
useOne("/JADE_OPAL_2000_S4300807/d17-x01-y05","44")
useOne("/JADE_OPAL_2000_S4300807/d18-x01-y01","91")
useOne("/JADE_OPAL_2000_S4300807/d18-x01-y02","91")
useOne("/JADE_OPAL_2000_S4300807/d18-x01-y03","91")
useOne("/JADE_OPAL_2000_S4300807/d18-x01-y04","91")
useOne("/JADE_OPAL_2000_S4300807/d18-x01-y05","91")
useOne("/JADE_OPAL_2000_S4300807/d19-x01-y01","133")
useOne("/JADE_OPAL_2000_S4300807/d19-x01-y02","133")
useOne("/JADE_OPAL_2000_S4300807/d19-x01-y03","133")
useOne("/JADE_OPAL_2000_S4300807/d19-x01-y04","133")
useOne("/JADE_OPAL_2000_S4300807/d19-x01-y05","133")
useOne("/JADE_OPAL_2000_S4300807/d20-x01-y01","161")
useOne("/JADE_OPAL_2000_S4300807/d20-x01-y02","161")
useOne("/JADE_OPAL_2000_S4300807/d20-x01-y03","161")
useOne("/JADE_OPAL_2000_S4300807/d20-x01-y04","161")
useOne("/JADE_OPAL_2000_S4300807/d20-x01-y05","161")
useOne("/JADE_OPAL_2000_S4300807/d21-x01-y01","172")
useOne("/JADE_OPAL_2000_S4300807/d21-x01-y02","172")
useOne("/JADE_OPAL_2000_S4300807/d21-x01-y03","172")
useOne("/JADE_OPAL_2000_S4300807/d21-x01-y04","172")
useOne("/JADE_OPAL_2000_S4300807/d21-x01-y05","172")
useOne("/JADE_OPAL_2000_S4300807/d22-x01-y01","183")
useOne("/JADE_OPAL_2000_S4300807/d22-x01-y02","183")
useOne("/JADE_OPAL_2000_S4300807/d22-x01-y03","183")
useOne("/JADE_OPAL_2000_S4300807/d22-x01-y04","183")
useOne("/JADE_OPAL_2000_S4300807/d22-x01-y05","183")
useOne("/JADE_OPAL_2000_S4300807/d23-x01-y01","189")
useOne("/JADE_OPAL_2000_S4300807/d23-x01-y02","189")
useOne("/JADE_OPAL_2000_S4300807/d23-x01-y03","189")
useOne("/JADE_OPAL_2000_S4300807/d23-x01-y04","189")
useOne("/JADE_OPAL_2000_S4300807/d23-x01-y05","189")
useOne("/JADE_OPAL_2000_S4300807/d24-x01-y01","35")
useOne("/JADE_OPAL_2000_S4300807/d24-x01-y02","35")
useOne("/JADE_OPAL_2000_S4300807/d24-x01-y03","35")
useOne("/JADE_OPAL_2000_S4300807/d24-x01-y04","35")
useOne("/JADE_OPAL_2000_S4300807/d25-x01-y01","44")
useOne("/JADE_OPAL_2000_S4300807/d25-x01-y02","44")
useOne("/JADE_OPAL_2000_S4300807/d25-x01-y03","44")
useOne("/JADE_OPAL_2000_S4300807/d25-x01-y04","44")
useOne("/JADE_OPAL_2000_S4300807/d26-x01-y01","91")
useOne("/JADE_OPAL_2000_S4300807/d26-x01-y02","91")
useOne("/JADE_OPAL_2000_S4300807/d26-x01-y03","91")
useOne("/JADE_OPAL_2000_S4300807/d26-x01-y04","91")
useOne("/JADE_OPAL_2000_S4300807/d27-x01-y01","133")
useOne("/JADE_OPAL_2000_S4300807/d27-x01-y02","133")
useOne("/JADE_OPAL_2000_S4300807/d27-x01-y03","133")
useOne("/JADE_OPAL_2000_S4300807/d27-x01-y04","133")
useOne("/JADE_OPAL_2000_S4300807/d28-x01-y01","161")
useOne("/JADE_OPAL_2000_S4300807/d28-x01-y02","161")
useOne("/JADE_OPAL_2000_S4300807/d28-x01-y03","161")
useOne("/JADE_OPAL_2000_S4300807/d28-x01-y04","161")
useOne("/JADE_OPAL_2000_S4300807/d29-x01-y01","172")
useOne("/JADE_OPAL_2000_S4300807/d29-x01-y02","172")
useOne("/JADE_OPAL_2000_S4300807/d29-x01-y03","172")
useOne("/JADE_OPAL_2000_S4300807/d29-x01-y04","172")
useOne("/JADE_OPAL_2000_S4300807/d30-x01-y01","183")
useOne("/JADE_OPAL_2000_S4300807/d30-x01-y02","183")
useOne("/JADE_OPAL_2000_S4300807/d30-x01-y03","183")
useOne("/JADE_OPAL_2000_S4300807/d30-x01-y04","183")
useOne("/JADE_OPAL_2000_S4300807/d31-x01-y01","189")
useOne("/JADE_OPAL_2000_S4300807/d31-x01-y02","189")
useOne("/JADE_OPAL_2000_S4300807/d31-x01-y03","189")
useOne("/JADE_OPAL_2000_S4300807/d31-x01-y04","189")
useOne("/OPAL_2004_S6132243/d01-x01-y01","91")
useOne("/OPAL_2004_S6132243/d01-x01-y02","133")
useOne("/OPAL_2004_S6132243/d01-x01-y03","177")
useOne("/OPAL_2004_S6132243/d01-x01-y04","197")
useOne("/OPAL_2004_S6132243/d02-x01-y01","91")
useOne("/OPAL_2004_S6132243/d02-x01-y02","133")
useOne("/OPAL_2004_S6132243/d02-x01-y03","177")
useOne("/OPAL_2004_S6132243/d02-x01-y04","197")
useOne("/OPAL_2004_S6132243/d03-x01-y01","91")
useOne("/OPAL_2004_S6132243/d03-x01-y02","133")
useOne("/OPAL_2004_S6132243/d03-x01-y03","177")
useOne("/OPAL_2004_S6132243/d03-x01-y04","197")
useOne("/OPAL_2004_S6132243/d04-x01-y01","91")
useOne("/OPAL_2004_S6132243/d04-x01-y02","133")
useOne("/OPAL_2004_S6132243/d04-x01-y03","177")
useOne("/OPAL_2004_S6132243/d04-x01-y04","197")
useOne("/OPAL_2004_S6132243/d05-x01-y01","91")
useOne("/OPAL_2004_S6132243/d05-x01-y02","133")
useOne("/OPAL_2004_S6132243/d05-x01-y03","177")
useOne("/OPAL_2004_S6132243/d05-x01-y04","197")
useOne("/OPAL_2004_S6132243/d06-x01-y01","91")
useOne("/OPAL_2004_S6132243/d06-x01-y02","133")
useOne("/OPAL_2004_S6132243/d06-x01-y03","177")
useOne("/OPAL_2004_S6132243/d06-x01-y04","197")
useOne("/OPAL_2004_S6132243/d07-x01-y01","91")
useOne("/OPAL_2004_S6132243/d07-x01-y02","133")
useOne("/OPAL_2004_S6132243/d07-x01-y03","177")
useOne("/OPAL_2004_S6132243/d07-x01-y04","197")
useOne("/OPAL_2004_S6132243/d08-x01-y01","91")
useOne("/OPAL_2004_S6132243/d08-x01-y02","133")
useOne("/OPAL_2004_S6132243/d08-x01-y03","177")
useOne("/OPAL_2004_S6132243/d08-x01-y04","197")
useOne("/OPAL_2004_S6132243/d09-x01-y01","91")
useOne("/OPAL_2004_S6132243/d09-x01-y02","133")
useOne("/OPAL_2004_S6132243/d09-x01-y03","177")
useOne("/OPAL_2004_S6132243/d09-x01-y04","197")
useOne("/OPAL_2004_S6132243/d10-x01-y01","91")
useOne("/OPAL_2004_S6132243/d10-x01-y02","133")
useOne("/OPAL_2004_S6132243/d10-x01-y03","177")
useOne("/OPAL_2004_S6132243/d10-x01-y04","197")
useOne("/OPAL_2004_S6132243/d11-x01-y01","91")
useOne("/OPAL_2004_S6132243/d11-x01-y02","133")
useOne("/OPAL_2004_S6132243/d11-x01-y03","177")
useOne("/OPAL_2004_S6132243/d11-x01-y04","197")
useOne("/OPAL_2004_S6132243/d12-x01-y01","91")
useOne("/OPAL_2004_S6132243/d12-x01-y02","133")
useOne("/OPAL_2004_S6132243/d12-x01-y03","177")
useOne("/OPAL_2004_S6132243/d12-x01-y04","197")
useOne("/OPAL_2004_S6132243/d13-x01-y01","91")
useOne("/OPAL_2004_S6132243/d13-x01-y02","133")
useOne("/OPAL_2004_S6132243/d13-x01-y03","177")
useOne("/OPAL_2004_S6132243/d13-x01-y04","197")
useOne("/OPAL_2004_S6132243/d14-x01-y01","91")
useOne("/OPAL_2004_S6132243/d14-x01-y02","133")
useOne("/OPAL_2004_S6132243/d14-x01-y03","177")
useOne("/OPAL_2004_S6132243/d14-x01-y04","197")
useOne("/OPAL_2004_S6132243/d15-x01-y01","91")
useOne("/OPAL_2004_S6132243/d15-x01-y02","133")
useOne("/OPAL_2004_S6132243/d15-x01-y03","177")
useOne("/OPAL_2004_S6132243/d15-x01-y04","197")
useOne("/OPAL_2004_S6132243/d16-x01-y01","91")
useOne("/OPAL_2004_S6132243/d16-x01-y02","133")
useOne("/OPAL_2004_S6132243/d16-x01-y03","177")
useOne("/OPAL_2004_S6132243/d16-x01-y04","197")
useOne("/OPAL_2004_S6132243/d17-x01-y01","91")
useOne("/OPAL_2004_S6132243/d17-x01-y02","133")
useOne("/OPAL_2004_S6132243/d17-x01-y03","177")
useOne("/OPAL_2004_S6132243/d17-x01-y04","197")
useOne("/OPAL_2004_S6132243/d18-x01-y01","91")
useOne("/OPAL_2004_S6132243/d18-x01-y02","133")
useOne("/OPAL_2004_S6132243/d18-x01-y03","177")
useOne("/OPAL_2004_S6132243/d18-x01-y04","197")
useOne("/OPAL_2004_S6132243/d19-x01-y01","91")
useOne("/OPAL_2004_S6132243/d19-x01-y02","133")
useOne("/OPAL_2004_S6132243/d19-x01-y03","177")
useOne("/OPAL_2004_S6132243/d19-x01-y04","197")
useOne("/OPAL_2004_S6132243/d20-x01-y01","91")
useOne("/OPAL_2004_S6132243/d20-x01-y02","133")
useOne("/OPAL_2004_S6132243/d20-x01-y03","177")
useOne("/OPAL_2004_S6132243/d20-x01-y04","197")
useOne("/OPAL_2004_S6132243/d21-x01-y01","91")
useOne("/OPAL_2004_S6132243/d21-x01-y02","133")
useOne("/OPAL_2004_S6132243/d21-x01-y03","177")
useOne("/OPAL_2004_S6132243/d21-x01-y04","197")
useOne("/OPAL_2004_S6132243/d22-x01-y01","91")
useOne("/OPAL_2004_S6132243/d22-x01-y02","133")
useOne("/OPAL_2004_S6132243/d22-x01-y03","177")
useOne("/OPAL_2004_S6132243/d22-x01-y04","197")
useOne("/OPAL_2004_S6132243/d23-x01-y01","91")
useOne("/OPAL_2004_S6132243/d23-x01-y02","133")
useOne("/OPAL_2004_S6132243/d23-x01-y03","177")
useOne("/OPAL_2004_S6132243/d23-x01-y04","197")
useOne("/OPAL_2004_S6132243/d24-x01-y01","91")
useOne("/OPAL_2004_S6132243/d24-x01-y02","133")
useOne("/OPAL_2004_S6132243/d24-x01-y03","177")
useOne("/OPAL_2004_S6132243/d24-x01-y04","197")
useOne("/OPAL_2004_S6132243/d25-x01-y01","91")
useOne("/OPAL_2004_S6132243/d25-x01-y02","133")
useOne("/OPAL_2004_S6132243/d25-x01-y03","177")
useOne("/OPAL_2004_S6132243/d25-x01-y04","197")
useOne("/OPAL_2004_S6132243/d26-x01-y01","91")
useOne("/OPAL_2004_S6132243/d26-x01-y02","133")
useOne("/OPAL_2004_S6132243/d26-x01-y03","177")
useOne("/OPAL_2004_S6132243/d26-x01-y04","197")
merge( "/OPAL_2002_S5361494/d01-x01-y01")
merge( "/OPAL_2002_S5361494/d01-x01-y02")
merge( "/OPAL_2002_S5361494/d01-x01-y03")
merge( "/OPAL_2002_S5361494/d01-x01-y04")
merge("/DELPHI_2000_S4328825/d01-x01-y01")
merge("/DELPHI_2000_S4328825/d01-x01-y02")
merge("/DELPHI_2000_S4328825/d01-x01-y03")
merge("/DELPHI_2000_S4328825/d01-x01-y04")
merge("/ALEPH_2004_S5765862/d01-x01-y01")
useOne("/ALEPH_2004_S5765862/d02-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d03-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d04-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d05-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d06-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d07-x01-y01","196")
useOne("/ALEPH_2004_S5765862/d08-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d09-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d11-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d12-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d13-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d14-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d15-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d16-x01-y01","196")
useOne("/ALEPH_2004_S5765862/d17-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d18-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d19-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d20-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d21-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d22-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d23-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d24-x01-y01","196")
useOne("/ALEPH_2004_S5765862/d25-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d26-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d27-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d28-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d29-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d30-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d31-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d32-x01-y01","196")
useOne("/ALEPH_2004_S5765862/d33-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d34-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d35-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d36-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d37-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d38-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d39-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d40-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d41-x01-y01","196")
useOne("/ALEPH_2004_S5765862/d42-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d43-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d44-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d45-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d46-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d47-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d48-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d49-x01-y01","196")
useOne("/ALEPH_2004_S5765862/d50-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d51-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d54-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d55-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d56-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d57-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d58-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d59-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d60-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d61-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d62-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d63-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d64-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d65-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d66-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d67-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d68-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d69-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d70-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d71-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d72-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d73-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d74-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d75-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d76-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d77-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d78-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d79-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d80-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d81-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d82-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d83-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d84-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d85-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d86-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d87-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d88-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d89-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d90-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d91-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d92-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d93-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d94-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d95-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d96-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d97-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d98-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d99-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d100-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d101-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d102-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d103-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d104-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d105-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d106-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d107-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d108-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d109-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d110-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d111-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d112-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d113-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d114-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d115-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d116-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d117-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d118-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d119-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d120-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d121-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d122-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d123-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d124-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d125-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d126-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d127-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d128-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d129-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d130-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d131-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d132-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d133-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d134-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d135-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d136-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d137-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d138-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d139-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d140-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d141-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d142-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d143-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d144-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d145-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d146-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d147-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d148-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d149-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d150-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d151-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d152-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d153-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d154-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d155-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d156-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d157-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d158-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d159-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d160-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d161-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d162-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d163-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d164-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d165-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d166-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d167-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d168-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d169-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d170-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d172-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d173-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d174-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d175-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d176-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d177-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d178-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d179-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d180-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d181-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d182-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d183-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d184-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d185-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d186-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d187-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d188-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d189-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d190-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d191-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d192-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d193-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d194-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d195-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d196-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d197-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d198-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d199-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d200-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d201-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d202-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d203-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d204-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d205-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d206-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d207-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d208-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d209-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d210-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d211-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d212-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d213-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d214-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d215-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d216-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d217-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d218-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d219-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d220-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d221-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d222-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d223-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d224-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d225-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d226-x01-y01","206")
useOne("/ALEPH_2004_S5765862/d227-x01-y01","91")
useOne("/ALEPH_2004_S5765862/d228-x01-y01","133")
useOne("/ALEPH_2004_S5765862/d229-x01-y01","161")
useOne("/ALEPH_2004_S5765862/d230-x01-y01","172")
useOne("/ALEPH_2004_S5765862/d231-x01-y01","183")
useOne("/ALEPH_2004_S5765862/d232-x01-y01","189")
useOne("/ALEPH_2004_S5765862/d233-x01-y01","200")
useOne("/ALEPH_2004_S5765862/d234-x01-y01","206")
# hadron multiplicities
useOne("/PDG_HADRON_MULTIPLICITIES/d01-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d02-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d03-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d04-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d05-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d06-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d07-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d08-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d09-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d13-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d15-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d17-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d18-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d19-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d20-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d21-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d22-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d23-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d25-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d31-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d38-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d39-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d40-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d44-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d45-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d46-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d47-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d48-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d49-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d50-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d51-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d53-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d54-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES/d01-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d02-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d03-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d04-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d05-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d06-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d07-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d08-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d09-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d13-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d15-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d18-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d19-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d20-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d21-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d22-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d31-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d33-x01-y01","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d34-x01-y01","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d38-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d39-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d44-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d46-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d47-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d48-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d50-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d51-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES/d01-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d02-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d03-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d04-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d05-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d06-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d07-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d08-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d09-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d10-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d11-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d12-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d13-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d14-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d15-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d16-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d17-x01-y02","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d18-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d19-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d20-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d21-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d23-x01-y02","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d24-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d25-x01-y02","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d26-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d27-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d28-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d29-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d30-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d31-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d32-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d34-x01-y02","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d35-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d36-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d37-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d38-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d39-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d40-x01-y02","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d41-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d42-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d43-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d44-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d45-x01-y02","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d46-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d47-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d48-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d49-x01-y02","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d50-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d51-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d52-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d54-x01-y02","91")
useOne("/PDG_HADRON_MULTIPLICITIES/d01-x01-y04","177")
useOne("/PDG_HADRON_MULTIPLICITIES/d03-x01-y04","177")
useOne("/PDG_HADRON_MULTIPLICITIES/d04-x01-y04","177")
useOne("/PDG_HADRON_MULTIPLICITIES/d38-x01-y04","177")
useOne("/PDG_HADRON_MULTIPLICITIES/d39-x01-y04","177")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d02-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d03-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d04-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d05-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d06-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d07-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d08-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d09-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d13-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d15-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d17-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d18-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d19-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d20-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d21-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d22-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d23-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d25-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d31-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d38-x01-y01","10" )
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d39-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d40-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d44-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d45-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d46-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d47-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d48-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d49-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d50-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d51-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d53-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d54-x01-y01","10")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d02-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d03-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d04-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d05-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d06-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d07-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d08-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d09-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d13-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d15-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d18-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d19-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d20-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d21-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d22-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d31-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d33-x01-y01","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d34-x01-y01","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d38-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d39-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d44-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d46-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d47-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d48-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d50-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d51-x01-y02","35")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d02-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d03-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d04-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d05-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d06-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d07-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d08-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d09-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d10-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d11-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d12-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d13-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d14-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d15-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d16-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d17-x01-y02","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d18-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d19-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d20-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d21-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d23-x01-y02","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d24-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d25-x01-y02","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d26-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d27-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d28-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d29-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d30-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d31-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d32-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d34-x01-y02","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d35-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d36-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d37-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d38-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d39-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d40-x01-y02","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d41-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d42-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d43-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d44-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d45-x01-y02","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d46-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d47-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d48-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d49-x01-y02","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d50-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d51-x01-y03","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d52-x01-y01","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d54-x01-y02","91")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d03-x01-y04","177")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d04-x01-y04","177")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d38-x01-y04","177")
useOne("/PDG_HADRON_MULTIPLICITIES_RATIOS/d39-x01-y04","177")
# Choose output file
name = args[0]+".yoda"
# output the yoda file
yoda.writeYODA(outhistos,name)
sys.exit(0)
diff --git a/Tests/python/merge-LHC-Jets b/Tests/python/merge-LHC-Jets
--- a/Tests/python/merge-LHC-Jets
+++ b/Tests/python/merge-LHC-Jets
@@ -1,1300 +1,1369 @@
#! /usr/bin/env python
import logging
import sys
+import math
if sys.version_info[:3] < (2,4,0):
print "rivet scripts require Python version >= 2.4.0... exiting"
sys.exit(1)
import os, yoda
# #############################################
def fillAbove(scale,desthisto, sourcehistosbyptmin) :
pthigh= 1e100
ptlow =-1e100
for pt, h in sorted(sourcehistosbyptmin.iteritems(),reverse=True):
ptlow=pt
if(type(desthisto)==yoda.core.Scatter2D) :
for i in range(0,h.numPoints) :
xMin = h.points[i].x-h.points[i].xErrs.minus
if( xMin*scale >= ptlow and
xMin*scale < pthigh ) :
desthisto.addPoint(h.points[i])
elif(type(desthisto)==yoda.core.Profile1D) :
for i in range(0,h.numBins) :
if(h.bins[i].xMin*scale >= ptlow and
h.bins[i].xMin*scale < pthigh ) :
desthisto.bins[i] += h.bins[i]
elif(type(desthisto)==yoda.core.Histo1D) :
for i in range(0,h.numBins) :
if(h.bins[i].xMin*scale >= ptlow and
h.bins[i].xMin*scale < pthigh ) :
desthisto.bins[i] += h.bins[i]
else :
logging.error("Can't merge %s, unknown type" % desthisto.path)
sys.exit(1)
pthigh=pt
def mergeByPt(hpath, sqrts, scale=1.) :
global inhistos_pt
global outhistos
try:
fillAbove(scale,outhistos[hpath], inhistos_pt[hpath][float(sqrts)])
except:
pass
def mergeByMass(hpath, sqrts, scale=1.):
global inhistos_mass
global outhistos
try:
fillAbove(scale,outhistos[hpath], inhistos_mass[hpath][float(sqrts)])
except:
pass
def useOnePt(hpath, sqrts, ptmin):
global inhistos_pt
global outhistos
try:
## Find best pT_min match
ptmins = inhistos_pt[hpath][float(sqrts)].keys()
closest_ptmin = None
for ptm in ptmins:
if closest_ptmin is None or \
abs(ptm-float(ptmin)) < abs(closest_ptmin-float(ptmin)):
closest_ptmin = ptm
if closest_ptmin != float(ptmin):
logging.warning("Inexact match for requested pTmin=%s: " % ptmin + \
"using pTmin=%e instead" % closest_ptmin)
outhistos[hpath] = inhistos_pt[hpath][float(sqrts)][closest_ptmin]
except:
pass
def useOneMass(hpath, sqrts, ptmin):
global inhistos_pt
global outhistos
try:
## Find best pT_min match
ptmins = inhistos_mass[hpath][float(sqrts)].keys()
closest_ptmin = None
for ptm in ptmins:
if closest_ptmin is None or \
abs(ptm-float(ptmin)) < abs(closest_ptmin-float(ptmin)):
closest_ptmin = ptm
if closest_ptmin != float(ptmin):
- logging.warning("Inexact match for requested pTmin=%s: " % ptmin + \
- "using pTmin=%e instead" % closest_ptmin)
+ logging.warning("Inexact match for requested mass=%s: " % ptmin + \
+ "using mass=%e instead" % closest_ptmin)
outhistos[hpath] = inhistos_mass[hpath][float(sqrts)][closest_ptmin]
except:
pass
# #######################################
if __name__ == "__main__":
import logging
from optparse import OptionParser, OptionGroup
parser = OptionParser(usage="%prog name")
verbgroup = OptionGroup(parser, "Verbosity control")
parser.add_option("--with-ue",
action='store_true' ,
dest="ue",
default=True,
help="Include UE analyses")
parser.add_option("--without-ue",
action='store_false',
dest="ue",
default=True,
help="Don\'t include UE analyses")
verbgroup.add_option("-v", "--verbose", action="store_const", const=logging.DEBUG, dest="LOGLEVEL",
default=logging.INFO, help="print debug (very verbose) messages")
verbgroup.add_option("-q", "--quiet", action="store_const", const=logging.WARNING, dest="LOGLEVEL",
default=logging.INFO, help="be very quiet")
parser.add_option_group(verbgroup)
(opts, args) = parser.parse_args()
logging.basicConfig(level=opts.LOGLEVEL, format="%(message)s")
(opts, args) = parser.parse_args()
## Check args
if len(args) < 1:
logging.error("Must specify at least the name of the files")
sys.exit(1)
-
-yodafiles=["-7-Jets-1.yoda","-7-Jets-2.yoda",
- "-7-Jets-3.yoda","-7-Jets-4.yoda","-7-Jets-5.yoda",
- "-7-Jets-6.yoda","-7-Jets-7.yoda","-7-Jets-8.yoda",
- "-7-Bottom-0.yoda","-7-Bottom-1.yoda","-7-Bottom-2.yoda",
+yodafiles=["-7-Bottom-0.yoda","-7-Bottom-1.yoda","-7-Bottom-2.yoda",
"-7-Bottom-3.yoda","-7-Bottom-4.yoda","-7-Bottom-5.yoda",
"-7-Charm-1.yoda","-7-Charm-2.yoda",
"-7-Charm-3.yoda","-7-Charm-4.yoda","-7-Charm-5.yoda",
- "-7-Top-SL.yoda","-7-Top-L.yoda","-7-Top-All.yoda","-8-Top-All.yoda"]
+ "-7-Top-SL.yoda","-7-Top-L.yoda","-7-Top-All.yoda",
+ "-8-Top-All.yoda"]
+
+for i in range(1,10) :
+ yodafiles.append("-7-Jets-%1.1i.yoda" % i)
+ yodafiles.append("-8-Jets-%1.1i.yoda" % i)
if(opts.ue) :
- yodafiles += ["-7-Jets-0.yoda","-900-UE.yoda" ,"-2360-UE.yoda" ,"-2760-UE.yoda" ,
- "-7-UE.yoda" ,"-900-UE-Long.yoda","-8-UE.yoda",
- "-7-UE-Long.yoda","-13-UE.yoda"]
+ yodafiles += ["-7-Jets-0.yoda" ,"-8-Jets-0.yoda" ,"-7-Jets-10.yoda",
+ "-8-Jets-10.yoda" ,"-900-UE.yoda" ,"-2360-UE.yoda" ,
+ "-2760-UE.yoda" ,"-7-UE.yoda" ,"-900-UE-Long.yoda",
+ "-900-UE-Short.yoda","-8-UE.yoda" ,"-7-UE-Long.yoda",
+ "-7-UE-Short.yoda" ,"-7-UE-Long.yoda","-13-UE.yoda"]
## Get histos
inhistos_pt = {}
inhistos_mass = {}
outhistos={}
weights = {}
for f in yodafiles:
file=args[0]+f
+ ptmin=0.
sqrts=7000
- if(file.find("-900-UE")>0) :
+ # CMS energy
+ if(file.find("-900-")>0) :
sqrts=900
+ elif(file.find("-2360-")>0) :
+ sqrts=2360
+ elif(file.find("-2760-")>0) :
+ sqrts=2760
+ elif(file.find("-7-")>=0) :
+ sqrts=7000
+ elif(file.find("-8-")>=0) :
+ sqrts=8000
+ elif(file.find("-13-")>0) :
+ sqrts=13000
+ # pT min
+ if(file.find("UE")>0) :
ptmin=0.
- elif(file.find("-2360-UE")>0) :
- sqrts=2360
- ptmin=0.
- elif(file.find("-2760-UE")>0) :
- sqrts=2760
- ptmin=0.
- elif(file.find("-7-UE")>0) :
- ptmin=0.
- elif(file.find("-13-UE")>0) :
- ptmin=0.
- sqrts=13000
- elif(file.find("-7-Jets-0")>0) :
+ elif(file.find("Jets-0")>0) :
ptmin=4.
- elif(file.find("-7-Jets-1")>0) :
+ elif(file.find("Jets-10")>0) :
+ ptmin=1900.
+ elif(file.find("Jets-1")>0) :
if( not opts.ue) :
ptmin = 10.
else :
ptmin = 20.
- elif(file.find("-7-Jets-2")>0) :
+ elif(file.find("Jets-2")>0) :
ptmin=40.
- elif(file.find("-7-Jets-3")>0) :
+ elif(file.find("Jets-3")>0) :
ptmin=80.
- elif(file.find("-7-Jets-4")>0) :
+ elif(file.find("Jets-4")>0) :
ptmin=110.
- elif(file.find("-7-Jets-5")>0) :
+ elif(file.find("Jets-5")>0) :
ptmin=210.
- elif(file.find("-7-Jets-6")>0) :
+ elif(file.find("Jets-6")>0) :
ptmin=260.
- elif(file.find("-7-Jets-7")>0) :
+ elif(file.find("Jets-7")>0) :
ptmin=400.
- elif(file.find("-7-Jets-8")>0) :
+ elif(file.find("Jets-8")>0) :
ptmin=600.
- elif(file.find("-7-Bottom-0")>0) :
+ elif(file.find("Jets-9")>0) :
+ ptmin=900.
+ elif(file.find("Bottom-0")>0) :
ptmin=0.
- elif(file.find("-7-Bottom-1")>0 or file.find("-7-Charm-1")>0) :
+ elif(file.find("Bottom-1")>0 or file.find("Charm-1")>0) :
ptmin=10.
- elif(file.find("-7-Bottom-2")>0 or file.find("-7-Charm-2")>0) :
+ elif(file.find("Bottom-2")>0 or file.find("Charm-2")>0) :
ptmin=30.
- elif(file.find("-7-Bottom-3")>0 or file.find("-7-Charm-3")>0) :
+ elif(file.find("Bottom-3")>0 or file.find("Charm-3")>0) :
ptmin=70.
- elif(file.find("-7-Bottom-4")>0 or file.find("-7-Charm-4")>0) :
+ elif(file.find("Bottom-4")>0 or file.find("Charm-4")>0) :
ptmin=100.
- elif(file.find("-7-Bottom-5")>0 or file.find("-7-Charm-5")>0) :
+ elif(file.find("Bottom-5")>0 or file.find("Charm-5")>0) :
ptmin=130.
- elif(file.find("-7-Top-SL.yoda")>0 or file.find("-7-Top-L.yoda")>0 or \
- file.find("-7-Top-All.yoda")>0):
+ elif(file.find("Top-SL.yoda")>0 or file.find("Top-L.yoda")>0 or \
+ file.find("Top-All.yoda")>0):
ptmin=0.
if not os.access(file, os.R_OK):
logging.error("%s can not be read" % file)
continue
try:
aos = yoda.read(file)
except:
logging.error("%s can not be parsed as YODA" % file)
continue
## Get histos from this YODA file
for aopath, ao in aos.iteritems() :
- if(aopath.find("S8924791")>0 or
- aopath.find("S8971293")>0 or
- aopath.find("S8817804")>0 or
- aopath.find("I1082936")>0 or
- aopath.find("S8994773")>0 or
- aopath.find("S8918562")>0 or
- aopath.find("S8624100")>0 or
- aopath.find("S8625980")>0 or
- aopath.find("S8894728")>0 or
- aopath.find("S8957746")>0 or
- aopath.find("S9126244")>0 or
- aopath.find("S9120041")>0 or
- aopath.find("S8950903")>0 or
- aopath.find("S9086218")>0 or
- aopath.find("S9088458")>0 or
- aopath.find("I919017" )>0 or
- aopath.find("I926145" )>0 or
- aopath.find("S8941262")>0 or
- aopath.find("S8973270")>0 or
- aopath.find("I1118269")>0 or
- aopath.find("I1188891")>0 or
- aopath.find("I1082009")>0 or
- aopath.find("I1087342")>0 or
- aopath.find("S9035664")>0 or
- aopath.find("I1125575")>0 or
- aopath.find("I1094564")>0 or
- aopath.find("I930220")>0 or
- aopath.find("I1224539")>0 or
- aopath.find("I1273574")>0 or
- aopath.find("I1261026")>0 or
- aopath.find("I1307243")>0 or
- aopath.find("I1325553")>0 or
- aopath.find("I1298810")>0 or
- aopath.find("CMS_2012_PAS_QCD_11_010")>0 or
- aopath.find("CMS_2013_I1208923")>0 or
- aopath.find("ATLAS_2014_I1298811")>0 or
- aopath.find("CMS_2014_I1305624")>0) :
+ if(aopath.find("S8924791")>0 or aopath.find("S8971293")>0 or
+ aopath.find("S8817804")>0 or aopath.find("I1082936")>0 or
+ aopath.find("S8994773")>0 or aopath.find("S8918562")>0 or
+ aopath.find("S8624100")>0 or aopath.find("S8625980")>0 or
+ aopath.find("S8894728")>0 or aopath.find("S8957746")>0 or
+ aopath.find("S9126244")>0 or aopath.find("S9120041")>0 or
+ aopath.find("S8950903")>0 or aopath.find("S9086218")>0 or
+ aopath.find("S9088458")>0 or aopath.find("I919017" )>0 or
+ aopath.find("I926145" )>0 or aopath.find("S8941262")>0 or
+ aopath.find("S8973270")>0 or aopath.find("I1118269")>0 or
+ aopath.find("I1188891")>0 or aopath.find("I1082009")>0 or
+ aopath.find("I1087342")>0 or aopath.find("S9035664")>0 or
+ aopath.find("I1125575")>0 or aopath.find("I1094564")>0 or
+ aopath.find("I930220" )>0 or aopath.find("I1224539")>0 or
+ aopath.find("I1273574")>0 or aopath.find("I1261026")>0 or
+ aopath.find("I1307243")>0 or aopath.find("I1325553")>0 or
+ aopath.find("I1298810")>0 or aopath.find("I1298811")>0 or
+ aopath.find("I1208923")>0 or aopath.find("I1305624")>0 or
+ aopath.find("I1419070")>0 or aopath.find("I1394679")>0 or
+ aopath.find("CMS_2012_PAS_QCD_11_010")>0) :
if not inhistos_pt.has_key(aopath):
inhistos_pt[aopath] = {}
tmpE = inhistos_pt[aopath]
if not tmpE.has_key(sqrts):
tmpE[sqrts] = {}
if not tmpE[sqrts].has_key(ptmin):
tmpE[sqrts][ptmin] = ao
else:
tmpE[sqrts][ptmin] += ao
#raise Exception("A set with ptmin = %s already exists" % ( ptmin))
else :
if(aopath.find("I1243871")>0) :
if(aopath.find("x01")>0 and file.find("-7-Top-L.yoda")>0 ) :
outhistos[aopath] = ao
elif(aopath.find("x02")>0 and file.find("-7-Top-SL.yoda")>0 ) :
outhistos[aopath] = ao
else :
outhistos[aopath] = ao
-yodafiles=["-7-Jets-1.yoda" ,"-7-Jets-9.yoda" ,"-7-Jets-10.yoda",
- "-7-Jets-11.yoda","-7-Jets-12.yoda","-7-Jets-13.yoda",
- "-7-Jets-14.yoda","-7-Jets-15.yoda",
- "-7-Bottom-6.yoda","-7-Bottom-7.yoda","-7-Bottom-8.yoda"]
+
+
+yodafiles=["-7-Bottom-6.yoda","-7-Bottom-7.yoda","-7-Bottom-8.yoda"]
+for i in range(1,8) :
+ yodafiles.append("-7-DiJets-%1.1i-A.yoda" % i)
+ yodafiles.append("-7-DiJets-%1.1i-B.yoda" % i)
+ yodafiles.append("-7-DiJets-%1.1i-C.yoda" % i)
for f in yodafiles:
+ print file
file=args[0]+f
- if(file.find("-7-Jets-1.yoda")>0) :
+ if(file.find("-7-Jets-1")>0) :
sqrts=7000
mass=0
- if(file.find("-7-Jets-9.yoda")>0) :
+ if(file.find("-7-DiJets-1")>0) :
sqrts=7000
mass=100
- elif(file.find("-7-Jets-10.yoda")>0) :
+ elif(file.find("-7-DiJets-2")>0) :
sqrts=7000
mass=250
- elif(file.find("-7-Jets-11.yoda")>0) :
+ elif(file.find("-7-DiJets-3")>0) :
sqrts=7000
- mass=650
- elif(file.find("-7-Jets-12.yoda")>0) :
+ mass=500
+ elif(file.find("-7-DiJets-4")>0) :
sqrts=7000
- mass=1100
- elif(file.find("-7-Jets-13.yoda")>0) :
+ mass=800
+ elif(file.find("-7-DiJets-5")>0) :
sqrts=7000
- mass=1700
- elif(file.find("-7-Jets-14.yoda")>0) :
+ mass=1000
+ elif(file.find("-7-DiJets-6")>0) :
sqrts=7000
- mass=2300
- elif(file.find("-7-Jets-15.yoda")>0) :
+ mass=1600
+ elif(file.find("-7-DiJets-7")>0) :
sqrts=7000
- mass=2900
- elif(file.find("-7-Bottom-6.yoda")>0) :
+ mass=2200
+ elif(file.find("-7-DiJets-8")>0) :
+ sqrts=7000
+ mass=2800
+ elif(file.find("-7-Bottom-6")>0) :
sqrts=7000
mass=110
- elif(file.find("-7-Bottom-7.yoda")>0) :
+ elif(file.find("-7-Bottom-7")>0) :
sqrts=7000
mass=370
- elif(file.find("-7-Bottom-8.yoda")>0) :
+ elif(file.find("-7-Bottom-8")>0) :
sqrts=7000
mass=550
if not os.access(file, os.R_OK):
logging.error("%s can not be read" % file)
continue
try:
aos = yoda.read(file)
except:
logging.error("%s can not be parsed as YODA" % file)
continue
## Get histos from this YODA file
for aopath, ao in aos.iteritems() :
if(aopath.find("8817804")>0 or
+ aopath.find("8968497")>0 or
aopath.find("1082936")>0 or
aopath.find("I930220")>0 or
aopath.find("1261026")>0 or
aopath.find("1090423")>0 or
aopath.find("1268975")>0 or
aopath.find("CMS_2013_I1208923")>0) :
if not inhistos_mass.has_key(aopath):
inhistos_mass[aopath] = {}
tmpE = inhistos_mass[aopath]
if not tmpE.has_key(sqrts):
tmpE[sqrts] = {}
tmpP = tmpE[sqrts]
if not tmpP.has_key(mass):
tmpP[mass] = ao
else:
- raise Exception("A set with mass = %s already exists" % ( mass))
+ print aopath
+ raise Exception("A set with mass = %s already exists" % ( mass))
## Make empty output histos if needed
for hpath,hsets in inhistos_pt.iteritems():
if( hpath.find("8924791")>0 or
hpath.find("8971293")>0 or
hpath.find("8817804")>0 or
hpath.find("8968497")>0 or
(hpath.find("9120041")>0 and (hpath.find("d01")>0 or hpath.find("d02")>0)) or
hpath.find("9126244")>0 or
hpath.find("926145") >0 or
hpath.find("9086218")>0 or
hpath.find("1082936")>0 or
hpath.find("8941262")>0 or
hpath.find("1118269")>0 or
hpath.find("1087342")>0 or
hpath.find("1188891")>0 or
hpath.find("919017")>0 or
hpath.find("9035664")>0 or
hpath.find("1125575")>0 or
hpath.find("1094564")>0 or
hpath.find("I930220")>0 or
hpath.find("S9088458")>0 or
hpath.find("I1273574")>0 or
hpath.find("I1261026")>0 or
hpath.find("I1090423")>0 or
hpath.find("QCD_11_010")>0 or
hpath.find("1298811" )>0 or
hpath.find("I1325553" )>0 or
hpath.find("I1298810" )>0 or
hpath.find("1307243" )>0 or
+ hpath.find("I1419070")>0 or
+ hpath.find("I1394679")>0 or
hpath.find("CMS_2013_I1208923" )>0) :
if(type(hsets.values()[0].values()[0])==yoda.core.Scatter2D) :
outhistos[hpath] = yoda.core.Scatter2D(hsets.values()[0].values()[0].path,
hsets.values()[0].values()[0].title)
elif(type(hsets.values()[0].values()[0])==yoda.core.Profile1D) :
outhistos[hpath] = yoda.core.Profile1D(hsets.values()[0].values()[0].path,
hsets.values()[0].values()[0].title)
for i in range(0,hsets.values()[0].values()[0].numBins) :
outhistos[hpath].addBin(hsets.values()[0].values()[0].bins[i].xMin,
hsets.values()[0].values()[0].bins[i].xMax)
elif(type(hsets.values()[0].values()[0])==yoda.core.Histo1D) :
outhistos[hpath] = yoda.core.Histo1D(hsets.values()[0].values()[0].path,
hsets.values()[0].values()[0].title)
for i in range(0,hsets.values()[0].values()[0].numBins) :
outhistos[hpath].addBin(hsets.values()[0].values()[0].bins[i].xMin,
hsets.values()[0].values()[0].bins[i].xMax)
else :
logging.error("Histogram %s is of unknown type" % hpath)
sys.exit(1)
## Make empty output histos if needed
for hpath,hsets in inhistos_mass.iteritems():
if(hpath.find("1268975")>0) :
if(type(hsets.values()[0].values()[0])==yoda.core.Scatter2D) :
outhistos[hpath] = yoda.core.Scatter2D(hsets.values()[0].values()[0].path,
hsets.values()[0].values()[0].title)
elif(type(hsets.values()[0].values()[0])==yoda.core.Profile1D) :
outhistos[hpath] = yoda.core.Profile1D(hsets.values()[0].values()[0].path,
hsets.values()[0].values()[0].title)
for i in range(0,hsets.values()[0].values()[0].numBins) :
outhistos[hpath].addBin(hsets.values()[0].values()[0].bins[i].xMin,
hsets.values()[0].values()[0].bins[i].xMax)
elif(type(hsets.values()[0].values()[0])==yoda.core.Histo1D) :
outhistos[hpath] = yoda.core.Histo1D(hsets.values()[0].values()[0].path,
hsets.values()[0].values()[0].title)
for i in range(0,hsets.values()[0].values()[0].numBins) :
outhistos[hpath].addBin(hsets.values()[0].values()[0].bins[i].xMin,
hsets.values()[0].values()[0].bins[i].xMax)
else :
logging.error("Histogram %s is of unknown type" % hpath)
sys.exit(1)
logging.info("Processing CMS_2011_S8957746")
useOnePt("/CMS_2011_S8957746/d01-x01-y01", "7000", "80" )
useOnePt("/CMS_2011_S8957746/d02-x01-y01", "7000", "80" )
useOnePt("/CMS_2011_S8957746/d03-x01-y01", "7000", "110" )
useOnePt("/CMS_2011_S8957746/d04-x01-y01", "7000", "110" )
useOnePt("/CMS_2011_S8957746/d05-x01-y01", "7000", "210" )
useOnePt("/CMS_2011_S8957746/d06-x01-y01", "7000", "210" )
logging.info("Processing ATLAS_2010_S8894728")
useOnePt("/ATLAS_2010_S8894728/d01-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d01-x01-y02", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d01-x01-y03", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d02-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d02-x01-y02", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d02-x01-y03", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d03-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d03-x01-y02", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d03-x01-y03", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d04-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d04-x01-y02", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d04-x01-y03", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d05-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d06-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d07-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d08-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d09-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d09-x01-y02", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d09-x01-y03", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d10-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d10-x01-y02", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d10-x01-y03", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d11-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d11-x01-y02", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d11-x01-y03", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d12-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d12-x01-y02", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d12-x01-y03", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d13-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d13-x01-y02", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d13-x01-y03", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d13-x01-y04", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d14-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d14-x01-y02", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d14-x01-y03", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d14-x01-y04", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d15-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d15-x01-y02", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d15-x01-y03", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d15-x01-y04", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d16-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d16-x01-y02", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d16-x01-y03", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d16-x01-y04", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d17-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d17-x01-y02", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d17-x01-y03", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d18-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d18-x01-y02", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d18-x01-y03", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d19-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d19-x01-y02", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d19-x01-y03", "900", "0" )
useOnePt("/ATLAS_2010_S8894728/d20-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d20-x01-y02", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d20-x01-y03", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d21-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8894728/d22-x01-y01", "7000", "0" )
logging.info("Processing ATLAS_2011_S8994773")
useOnePt("/ATLAS_2011_S8994773/d01-x01-y01", "900", "0" )
useOnePt("/ATLAS_2011_S8994773/d02-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2011_S8994773/d03-x01-y01", "900", "0" )
useOnePt("/ATLAS_2011_S8994773/d04-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2011_S8994773/d13-x01-y01", "900", "0" )
useOnePt("/ATLAS_2011_S8994773/d13-x01-y02", "900", "0" )
useOnePt("/ATLAS_2011_S8994773/d13-x01-y03", "900", "0" )
useOnePt("/ATLAS_2011_S8994773/d14-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2011_S8994773/d14-x01-y02", "7000", "0" )
useOnePt("/ATLAS_2011_S8994773/d14-x01-y03", "7000", "0" )
logging.info("Processing ALICE_2010_S8624100")
useOnePt("/ALICE_2010_S8624100/d11-x01-y01", "900", "0" )
useOnePt("/ALICE_2010_S8624100/d12-x01-y01", "900", "0" )
useOnePt("/ALICE_2010_S8624100/d13-x01-y01", "900", "0" )
useOnePt("/ALICE_2010_S8624100/d17-x01-y01","2360", "0" )
useOnePt("/ALICE_2010_S8624100/d18-x01-y01","2360", "0" )
useOnePt("/ALICE_2010_S8624100/d19-x01-y01","2360", "0" )
logging.info("Processing ALICE_2010_S8625980")
useOnePt("/ALICE_2010_S8625980/d03-x01-y01", "7000", "0" )
useOnePt("/ALICE_2010_S8625980/d04-x01-y01", "900", "0" )
useOnePt("/ALICE_2010_S8625980/d05-x01-y01", "2360", "0" )
useOnePt("/ALICE_2010_S8625980/d06-x01-y01", "7000", "0" )
logging.info("Processing ATLAS_2010_S8918562")
useOnePt("/ATLAS_2010_S8918562/d01-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8918562/d02-x01-y01", "2360", "0" )
useOnePt("/ATLAS_2010_S8918562/d03-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8918562/d04-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8918562/d05-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8918562/d06-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8918562/d07-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8918562/d08-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8918562/d09-x01-y01", "2360", "0" )
useOnePt("/ATLAS_2010_S8918562/d10-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8918562/d11-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8918562/d12-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8918562/d13-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8918562/d14-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8918562/d15-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8918562/d16-x01-y01", "2360", "0" )
useOnePt("/ATLAS_2010_S8918562/d17-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8918562/d18-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8918562/d19-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8918562/d20-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8918562/d21-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8918562/d22-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8918562/d23-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8918562/d24-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8918562/d25-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8918562/d26-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8918562/d27-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8918562/d28-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8918562/d29-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8918562/d30-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8918562/d31-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8918562/d32-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8918562/d33-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8918562/d34-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8918562/d35-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8918562/d36-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8918562/d37-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2010_S8918562/d38-x01-y01", "900", "0" )
useOnePt("/ATLAS_2010_S8918562/d39-x01-y01", "7000", "0" )
logging.info("Processing ATLAS_2011_S8971293")
useOnePt("/ATLAS_2011_S8971293/d01-x01-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S8971293/d01-x01-y02", "7000", "110" )
useOnePt("/ATLAS_2011_S8971293/d01-x01-y03", "7000", "210" )
useOnePt("/ATLAS_2011_S8971293/d01-x01-y04", "7000", "260" )
useOnePt("/ATLAS_2011_S8971293/d01-x01-y05", "7000", "260" )
useOnePt("/ATLAS_2011_S8971293/d01-x01-y06", "7000", "400" )
useOnePt("/ATLAS_2011_S8971293/d01-x01-y07", "7000", "400" )
useOnePt("/ATLAS_2011_S8971293/d01-x01-y08", "7000", "600" )
useOnePt("/ATLAS_2011_S8971293/d01-x01-y09", "7000", "600" )
logging.info("Processing ATLAS_2011_S8924791")
-useOnePt("/ATLAS_2011_S8924791/d01-x01-y01", "7000", "30" )
-useOnePt("/ATLAS_2011_S8924791/d01-x01-y02", "7000", "30" )
-useOnePt("/ATLAS_2011_S8924791/d01-x02-y01", "7000", "30" )
-useOnePt("/ATLAS_2011_S8924791/d01-x02-y02", "7000", "30" )
-useOnePt("/ATLAS_2011_S8924791/d01-x03-y01", "7000", "30" )
-useOnePt("/ATLAS_2011_S8924791/d01-x03-y02", "7000", "30" )
-useOnePt("/ATLAS_2011_S8924791/d01-x04-y01", "7000", "30" )
-useOnePt("/ATLAS_2011_S8924791/d01-x04-y02", "7000", "30" )
-useOnePt("/ATLAS_2011_S8924791/d01-x05-y01", "7000", "30" )
-useOnePt("/ATLAS_2011_S8924791/d01-x05-y02", "7000", "30" )
-useOnePt("/ATLAS_2011_S8924791/d01-x06-y01", "7000", "30" )
-useOnePt("/ATLAS_2011_S8924791/d01-x06-y02", "7000", "30" )
+if( not opts.ue) :
+ useOnePt("/ATLAS_2011_S8924791/d01-x01-y01", "7000", "10" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x01-y02", "7000", "10" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x02-y01", "7000", "10" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x02-y02", "7000", "10" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x03-y01", "7000", "10" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x03-y02", "7000", "10" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x04-y01", "7000", "10" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x04-y02", "7000", "10" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x05-y01", "7000", "10" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x05-y02", "7000", "10" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x06-y01", "7000", "10" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x06-y02", "7000", "10" )
+else :
+ useOnePt("/ATLAS_2011_S8924791/d01-x01-y01", "7000", "20" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x01-y02", "7000", "20" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x02-y01", "7000", "20" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x02-y02", "7000", "20" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x03-y01", "7000", "20" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x03-y02", "7000", "20" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x04-y01", "7000", "20" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x04-y02", "7000", "20" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x05-y01", "7000", "20" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x05-y02", "7000", "20" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x06-y01", "7000", "20" )
+ useOnePt("/ATLAS_2011_S8924791/d01-x06-y02", "7000", "20" )
+
useOnePt("/ATLAS_2011_S8924791/d02-x01-y01", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d02-x01-y02", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d02-x02-y01", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d02-x02-y02", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d02-x03-y01", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d02-x03-y02", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d02-x04-y01", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d02-x04-y02", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d02-x05-y01", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d02-x05-y02", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d02-x06-y01", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d02-x06-y02", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d03-x01-y01", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d03-x01-y02", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d03-x02-y01", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d03-x02-y02", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d03-x03-y01", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d03-x03-y02", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d03-x04-y01", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d03-x04-y02", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d03-x05-y01", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d03-x05-y02", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d03-x06-y01", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d03-x06-y02", "7000", "40" )
useOnePt("/ATLAS_2011_S8924791/d04-x01-y01", "7000", "80" )
useOnePt("/ATLAS_2011_S8924791/d04-x01-y02", "7000", "80" )
useOnePt("/ATLAS_2011_S8924791/d04-x02-y01", "7000", "80" )
useOnePt("/ATLAS_2011_S8924791/d04-x02-y02", "7000", "80" )
useOnePt("/ATLAS_2011_S8924791/d04-x03-y01", "7000", "80" )
useOnePt("/ATLAS_2011_S8924791/d04-x03-y02", "7000", "80" )
useOnePt("/ATLAS_2011_S8924791/d04-x04-y01", "7000", "80" )
useOnePt("/ATLAS_2011_S8924791/d04-x04-y02", "7000", "80" )
useOnePt("/ATLAS_2011_S8924791/d04-x05-y01", "7000", "80" )
useOnePt("/ATLAS_2011_S8924791/d04-x05-y02", "7000", "80" )
useOnePt("/ATLAS_2011_S8924791/d04-x06-y01", "7000", "80" )
useOnePt("/ATLAS_2011_S8924791/d04-x06-y02", "7000", "80" )
useOnePt("/ATLAS_2011_S8924791/d05-x01-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d05-x01-y02", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d05-x02-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d05-x02-y02", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d05-x03-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d05-x03-y02", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d05-x04-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d05-x04-y02", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d05-x05-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d05-x05-y02", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d05-x06-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d05-x06-y02", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d06-x01-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d06-x01-y02", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d06-x02-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d06-x02-y02", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d06-x03-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d06-x03-y02", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d06-x04-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d06-x04-y02", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d06-x05-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d06-x05-y02", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d06-x06-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d06-x06-y02", "7000", "110" )
useOnePt("/ATLAS_2011_S8924791/d07-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2011_S8924791/d07-x01-y02", "7000", "210" )
useOnePt("/ATLAS_2011_S8924791/d07-x02-y01", "7000", "210" )
useOnePt("/ATLAS_2011_S8924791/d07-x02-y02", "7000", "210" )
useOnePt("/ATLAS_2011_S8924791/d07-x03-y01", "7000", "210" )
useOnePt("/ATLAS_2011_S8924791/d07-x03-y02", "7000", "210" )
useOnePt("/ATLAS_2011_S8924791/d07-x04-y01", "7000", "210" )
useOnePt("/ATLAS_2011_S8924791/d07-x04-y02", "7000", "210" )
useOnePt("/ATLAS_2011_S8924791/d07-x05-y01", "7000", "210" )
useOnePt("/ATLAS_2011_S8924791/d07-x05-y02", "7000", "210" )
useOnePt("/ATLAS_2011_S8924791/d07-x06-y01", "7000", "210" )
useOnePt("/ATLAS_2011_S8924791/d07-x06-y02", "7000", "210" )
useOnePt("/ATLAS_2011_S8924791/d08-x01-y01", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d08-x01-y02", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d08-x02-y01", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d08-x02-y02", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d08-x03-y01", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d08-x03-y02", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d08-x04-y01", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d08-x04-y02", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d08-x05-y01", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d08-x05-y02", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d08-x06-y01", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d08-x06-y02", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d09-x01-y01", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d09-x01-y02", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d09-x02-y01", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d09-x02-y02", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d09-x03-y01", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d09-x03-y02", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d09-x04-y01", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d09-x04-y02", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d09-x05-y01", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d09-x05-y02", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d09-x06-y01", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d09-x06-y02", "7000", "260" )
useOnePt("/ATLAS_2011_S8924791/d10-x01-y01", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d10-x01-y02", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d10-x02-y01", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d10-x02-y02", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d10-x03-y01", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d10-x03-y02", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d10-x04-y01", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d10-x04-y02", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d10-x05-y01", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d10-x05-y02", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d10-x06-y01", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d10-x06-y02", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d11-x01-y01", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d11-x01-y02", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d11-x02-y01", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d11-x02-y02", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d11-x03-y01", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d11-x03-y02", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d11-x04-y01", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d11-x04-y02", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d11-x05-y01", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d11-x05-y02", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d11-x06-y01", "7000", "400" )
useOnePt("/ATLAS_2011_S8924791/d11-x06-y02", "7000", "400" )
logging.info("Processing ATLAS_2010_S8817804")
mergeByPt("/ATLAS_2010_S8817804/d01-x01-y01", "7000")
mergeByPt("/ATLAS_2010_S8817804/d02-x01-y01", "7000")
mergeByPt("/ATLAS_2010_S8817804/d03-x01-y01", "7000")
mergeByPt("/ATLAS_2010_S8817804/d04-x01-y01", "7000")
mergeByPt("/ATLAS_2010_S8817804/d05-x01-y01", "7000")
mergeByPt("/ATLAS_2010_S8817804/d06-x01-y01", "7000")
mergeByPt("/ATLAS_2010_S8817804/d07-x01-y01", "7000")
mergeByPt("/ATLAS_2010_S8817804/d08-x01-y01", "7000")
mergeByPt("/ATLAS_2010_S8817804/d09-x01-y01", "7000")
mergeByPt("/ATLAS_2010_S8817804/d10-x01-y01", "7000")
mergeByMass("/ATLAS_2010_S8817804/d11-x01-y01", "7000")
mergeByMass("/ATLAS_2010_S8817804/d12-x01-y01", "7000")
mergeByMass("/ATLAS_2010_S8817804/d13-x01-y01", "7000")
mergeByMass("/ATLAS_2010_S8817804/d14-x01-y01", "7000")
mergeByMass("/ATLAS_2010_S8817804/d15-x01-y01", "7000")
mergeByMass("/ATLAS_2010_S8817804/d16-x01-y01", "7000")
mergeByMass("/ATLAS_2010_S8817804/d17-x01-y01", "7000")
mergeByMass("/ATLAS_2010_S8817804/d18-x01-y01", "7000")
mergeByMass("/ATLAS_2010_S8817804/d19-x01-y01", "7000")
mergeByMass("/ATLAS_2010_S8817804/d20-x01-y01", "7000")
-useOneMass("/ATLAS_2010_S8817804/d21-x01-y01", "7000", "300" )
-useOneMass("/ATLAS_2010_S8817804/d22-x01-y01", "7000", "300" )
-useOneMass("/ATLAS_2010_S8817804/d23-x01-y01", "7000", "800" )
-useOneMass("/ATLAS_2010_S8817804/d24-x01-y01", "7000", "300" )
-useOneMass("/ATLAS_2010_S8817804/d25-x01-y01", "7000", "300" )
-useOneMass("/ATLAS_2010_S8817804/d26-x01-y01", "7000", "800" )
+useOneMass("/ATLAS_2010_S8817804/d21-x01-y01", "7000", "250" )
+useOneMass("/ATLAS_2010_S8817804/d22-x01-y01", "7000", "250" )
+useOneMass("/ATLAS_2010_S8817804/d23-x01-y01", "7000", "650" )
+useOneMass("/ATLAS_2010_S8817804/d24-x01-y01", "7000", "250" )
+useOneMass("/ATLAS_2010_S8817804/d25-x01-y01", "7000", "250" )
+useOneMass("/ATLAS_2010_S8817804/d26-x01-y01", "7000", "650" )
logging.info("Processing ATLAS_2011_I930220")
mergeByPt("/ATLAS_2011_I930220/d01-x01-y01", "7000" )
mergeByPt("/ATLAS_2011_I930220/d02-x01-y01", "7000" )
mergeByPt("/ATLAS_2011_I930220/d03-x01-y01", "7000" )
mergeByPt("/ATLAS_2011_I930220/d04-x01-y01", "7000" )
mergeByPt("/ATLAS_2011_I930220/d05-x01-y01", "7000" )
mergeByPt("/ATLAS_2011_I930220/d06-x01-y01", "7000" )
mergeByMass("/ATLAS_2011_I930220/d07-x01-y01", "7000")
useOneMass("/ATLAS_2011_I930220/d08-x01-y01", "7000", "110" )
useOneMass("/ATLAS_2011_I930220/d09-x01-y01", "7000", "110" )
useOneMass("/ATLAS_2011_I930220/d10-x01-y01", "7000", "370" )
logging.info("Processing ATLAS_2012_I1082936")
mergeByPt("/ATLAS_2012_I1082936/d01-x01-y01", "7000")
mergeByPt("/ATLAS_2012_I1082936/d01-x01-y02", "7000")
mergeByPt("/ATLAS_2012_I1082936/d01-x01-y03", "7000")
mergeByPt("/ATLAS_2012_I1082936/d01-x01-y04", "7000")
mergeByPt("/ATLAS_2012_I1082936/d01-x01-y05", "7000")
mergeByPt("/ATLAS_2012_I1082936/d01-x01-y06", "7000")
mergeByPt("/ATLAS_2012_I1082936/d01-x01-y07", "7000")
mergeByPt("/ATLAS_2012_I1082936/d02-x01-y01", "7000")
mergeByPt("/ATLAS_2012_I1082936/d02-x01-y02", "7000")
mergeByPt("/ATLAS_2012_I1082936/d02-x01-y03", "7000")
mergeByPt("/ATLAS_2012_I1082936/d02-x01-y04", "7000")
mergeByPt("/ATLAS_2012_I1082936/d02-x01-y05", "7000")
mergeByPt("/ATLAS_2012_I1082936/d02-x01-y06", "7000")
mergeByPt("/ATLAS_2012_I1082936/d02-x01-y07", "7000")
mergeByMass("/ATLAS_2012_I1082936/d03-x01-y01", "7000", 1000.)
mergeByMass("/ATLAS_2012_I1082936/d03-x01-y02", "7000", 1000.)
mergeByMass("/ATLAS_2012_I1082936/d03-x01-y03", "7000", 1000.)
mergeByMass("/ATLAS_2012_I1082936/d03-x01-y04", "7000", 1000.)
mergeByMass("/ATLAS_2012_I1082936/d03-x01-y05", "7000", 1000.)
mergeByMass("/ATLAS_2012_I1082936/d03-x01-y06", "7000", 1000.)
mergeByMass("/ATLAS_2012_I1082936/d03-x01-y07", "7000", 1000.)
mergeByMass("/ATLAS_2012_I1082936/d03-x01-y08", "7000", 1000.)
mergeByMass("/ATLAS_2012_I1082936/d03-x01-y09", "7000", 1000.)
mergeByMass("/ATLAS_2012_I1082936/d04-x01-y01", "7000", 1000.)
mergeByMass("/ATLAS_2012_I1082936/d04-x01-y02", "7000", 1000.)
mergeByMass("/ATLAS_2012_I1082936/d04-x01-y03", "7000", 1000.)
mergeByMass("/ATLAS_2012_I1082936/d04-x01-y04", "7000", 1000.)
mergeByMass("/ATLAS_2012_I1082936/d04-x01-y05", "7000", 1000.)
mergeByMass("/ATLAS_2012_I1082936/d04-x01-y06", "7000", 1000.)
mergeByMass("/ATLAS_2012_I1082936/d04-x01-y07", "7000", 1000.)
mergeByMass("/ATLAS_2012_I1082936/d04-x01-y08", "7000", 1000.)
mergeByMass("/ATLAS_2012_I1082936/d04-x01-y09", "7000", 1000.)
logging.info("Processing CMS_2011_S8968497")
-useOneMass("/CMS_2011_S8968497/d01-x01-y01", "7000", "2000" )
-useOneMass("/CMS_2011_S8968497/d02-x01-y01", "7000", "1200" )
-useOneMass("/CMS_2011_S8968497/d03-x01-y01", "7000", "1200" )
-useOneMass("/CMS_2011_S8968497/d04-x01-y01", "7000", "800" )
-useOneMass("/CMS_2011_S8968497/d05-x01-y01", "7000", "800" )
-useOneMass("/CMS_2011_S8968497/d06-x01-y01", "7000", "300" )
-useOneMass("/CMS_2011_S8968497/d07-x01-y01", "7000", "300" )
-useOneMass("/CMS_2011_S8968497/d08-x01-y01", "7000", "300" )
-useOneMass("/CMS_2011_S8968497/d09-x01-y01", "7000", "100" )
+useOneMass("/CMS_2011_S8968497/d01-x01-y01", "7000", "1700" )
+useOneMass("/CMS_2011_S8968497/d02-x01-y01", "7000", "1700" )
+useOneMass("/CMS_2011_S8968497/d03-x01-y01", "7000", "1100" )
+useOneMass("/CMS_2011_S8968497/d04-x01-y01", "7000", "1100" )
+useOneMass("/CMS_2011_S8968497/d05-x01-y01", "7000", "650" )
+useOneMass("/CMS_2011_S8968497/d06-x01-y01", "7000", "650" )
+useOneMass("/CMS_2011_S8968497/d07-x01-y01", "7000", "250" )
+useOneMass("/CMS_2011_S8968497/d08-x01-y01", "7000", "250" )
+useOneMass("/CMS_2011_S8968497/d09-x01-y01", "7000", "250" )
logging.info("Processing ATLAS_2011_S9126244")
mergeByPt("/ATLAS_2011_S9126244/d01-x01-y01", "7000")
mergeByPt("/ATLAS_2011_S9126244/d01-x01-y02", "7000")
mergeByPt("/ATLAS_2011_S9126244/d02-x01-y01", "7000")
mergeByPt("/ATLAS_2011_S9126244/d02-x01-y02", "7000")
mergeByPt("/ATLAS_2011_S9126244/d03-x01-y01", "7000")
mergeByPt("/ATLAS_2011_S9126244/d03-x01-y02", "7000")
mergeByPt("/ATLAS_2011_S9126244/d04-x01-y01", "7000")
mergeByPt("/ATLAS_2011_S9126244/d04-x01-y02", "7000")
mergeByPt("/ATLAS_2011_S9126244/d05-x01-y01", "7000")
mergeByPt("/ATLAS_2011_S9126244/d05-x01-y02", "7000")
useOnePt("/ATLAS_2011_S9126244/d06-x01-y01", "7000", "40" )
useOnePt("/ATLAS_2011_S9126244/d06-x01-y02", "7000", "40" )
useOnePt("/ATLAS_2011_S9126244/d07-x01-y01", "7000", "80" )
useOnePt("/ATLAS_2011_S9126244/d07-x01-y02", "7000", "80" )
useOnePt("/ATLAS_2011_S9126244/d08-x01-y01", "7000", "80" )
useOnePt("/ATLAS_2011_S9126244/d08-x01-y02", "7000", "80" )
useOnePt("/ATLAS_2011_S9126244/d09-x01-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S9126244/d09-x01-y02", "7000", "110" )
useOnePt("/ATLAS_2011_S9126244/d10-x01-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S9126244/d10-x01-y02", "7000", "110" )
useOnePt("/ATLAS_2011_S9126244/d11-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2011_S9126244/d11-x01-y02", "7000", "210" )
useOnePt("/ATLAS_2011_S9126244/d12-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2011_S9126244/d12-x01-y02", "7000", "210" )
useOnePt("/ATLAS_2011_S9126244/d13-x01-y01", "7000", "40" )
useOnePt("/ATLAS_2011_S9126244/d13-x01-y02", "7000", "40" )
useOnePt("/ATLAS_2011_S9126244/d14-x01-y01", "7000", "40" )
useOnePt("/ATLAS_2011_S9126244/d14-x01-y02", "7000", "40" )
useOnePt("/ATLAS_2011_S9126244/d15-x01-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S9126244/d15-x01-y02", "7000", "110" )
useOnePt("/ATLAS_2011_S9126244/d16-x01-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S9126244/d16-x01-y02", "7000", "110" )
useOnePt("/ATLAS_2011_S9126244/d17-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2011_S9126244/d17-x01-y02", "7000", "210" )
useOnePt("/ATLAS_2011_S9126244/d18-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2011_S9126244/d18-x01-y02", "7000", "210" )
useOnePt("/ATLAS_2011_S9126244/d19-x01-y01", "7000", "40" )
useOnePt("/ATLAS_2011_S9126244/d20-x01-y01", "7000", "80" )
useOnePt("/ATLAS_2011_S9126244/d21-x01-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S9126244/d22-x01-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S9126244/d23-x01-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S9126244/d24-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2011_S9126244/d25-x01-y01", "7000", "210" )
mergeByPt("/ATLAS_2011_S9126244/d26-x01-y01", "7000")
mergeByPt("/ATLAS_2011_S9126244/d26-x01-y02", "7000")
mergeByPt("/ATLAS_2011_S9126244/d27-x01-y01", "7000")
mergeByPt("/ATLAS_2011_S9126244/d27-x01-y02", "7000")
mergeByPt("/ATLAS_2011_S9126244/d28-x01-y01", "7000")
mergeByPt("/ATLAS_2011_S9126244/d28-x01-y02", "7000")
mergeByPt("/ATLAS_2011_S9126244/d29-x01-y01", "7000")
mergeByPt("/ATLAS_2011_S9126244/d29-x01-y02", "7000")
useOnePt("/ATLAS_2011_S9126244/d30-x01-y01", "7000", "40" )
useOnePt("/ATLAS_2011_S9126244/d31-x01-y01", "7000", "80" )
useOnePt("/ATLAS_2011_S9126244/d32-x01-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S9126244/d33-x01-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S9126244/d34-x01-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S9126244/d35-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2011_S9126244/d36-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2011_S9126244/d37-x01-y01", "7000", "40" )
useOnePt("/ATLAS_2011_S9126244/d37-x01-y02", "7000", "40" )
useOnePt("/ATLAS_2011_S9126244/d38-x01-y01", "7000", "80" )
useOnePt("/ATLAS_2011_S9126244/d38-x01-y02", "7000", "80" )
useOnePt("/ATLAS_2011_S9126244/d39-x01-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S9126244/d39-x01-y02", "7000", "110" )
useOnePt("/ATLAS_2011_S9126244/d40-x01-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S9126244/d40-x01-y02", "7000", "110" )
useOnePt("/ATLAS_2011_S9126244/d41-x01-y01", "7000", "110" )
useOnePt("/ATLAS_2011_S9126244/d41-x01-y02", "7000", "110" )
useOnePt("/ATLAS_2011_S9126244/d42-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2011_S9126244/d42-x01-y02", "7000", "210" )
useOnePt("/ATLAS_2011_S9126244/d43-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2011_S9126244/d43-x01-y02", "7000", "210" )
# CMS_2011_S9120041 UE analysis
logging.info("Processing CMS_2011_S9120041")
mergeByPt("/CMS_2011_S9120041/d01-x01-y01", "7000")
mergeByPt("/CMS_2011_S9120041/d02-x01-y01", "7000")
if(opts.ue) :
useOnePt("/CMS_2011_S9120041/d03-x01-y01", "900", "0" )
useOnePt("/CMS_2011_S9120041/d04-x01-y01", "900", "0" )
useOnePt("/CMS_2011_S9120041/d05-x01-y01", "7000", "0" )
useOnePt("/CMS_2011_S9120041/d06-x01-y01", "7000", "0" )
useOnePt("/CMS_2011_S9120041/d07-x01-y01", "7000", "0" )
useOnePt("/CMS_2011_S9120041/d11-x01-y01", "900", "0" )
useOnePt("/CMS_2011_S9120041/d12-x01-y01", "900", "0" )
useOnePt("/CMS_2011_S9120041/d13-x01-y01", "900", "0" )
useOnePt("/CMS_2011_S9120041/d08-x01-y01", "7000", "20" )
useOnePt("/CMS_2011_S9120041/d09-x01-y01", "7000", "20" )
useOnePt("/CMS_2011_S9120041/d10-x01-y01", "7000", "20" )
else :
useOnePt("/CMS_2011_S9120041/d08-x01-y01", "7000", "10" )
useOnePt("/CMS_2011_S9120041/d09-x01-y01", "7000", "10" )
useOnePt("/CMS_2011_S9120041/d10-x01-y01", "7000", "10" )
# CMS dijet decorrelation
logging.info("Processing CMS_2011_S8950903")
useOnePt("/CMS_2011_S8950903/d01-x01-y01", "7000", "80" )
useOnePt("/CMS_2011_S8950903/d02-x01-y01", "7000", "110" )
useOnePt("/CMS_2011_S8950903/d03-x01-y01", "7000", "110" )
useOnePt("/CMS_2011_S8950903/d04-x01-y01", "7000", "210" )
useOnePt("/CMS_2011_S8950903/d05-x01-y01", "7000", "260" )
# CMS jet cross section
logging.info("Processing CMS_2011_S9086218")
mergeByPt("/CMS_2011_S9086218/d01-x01-y01", "7000")
mergeByPt("/CMS_2011_S9086218/d02-x01-y01", "7000")
mergeByPt("/CMS_2011_S9086218/d03-x01-y01", "7000")
mergeByPt("/CMS_2011_S9086218/d04-x01-y01", "7000")
mergeByPt("/CMS_2011_S9086218/d05-x01-y01", "7000")
mergeByPt("/CMS_2011_S9086218/d06-x01-y01", "7000")
# CMS 2/3 jet cross section ratio
logging.info("Processing CMS_2011_S9086218")
mergeByPt("/CMS_2011_S9088458/d01-x01-y01", "7000",500.)
# ATLAS track jet
logging.info("Processing ATLAS_2011_I919017")
for d in range(1,3) :
for y in range(1,5) :
mergeByPt("/ATLAS_2011_I919017/d0%s-x01-y0%s" % (d,y), "7000")
if( opts.ue) :
for x in range(2,6) :
for y in ["01","02","06","07","11","12","16","17","21","22"] :
useOnePt("/ATLAS_2011_I919017/d0%s-x0%s-y%s" % (d,x,y), "7000", "0" )
for y in ["03","04","08","09","13","14","18","19","23","24"] :
useOnePt("/ATLAS_2011_I919017/d0%s-x0%s-y%s" % (d,x,y), "7000", "4" )
for y in range(5,30,5) :
useOnePt("/ATLAS_2011_I919017/d0%s-x%02d-y%02d" % (d,x,y) , "7000", "20" )
else :
for x in range(2,6) :
for y in range(5,30,5) :
useOnePt("/ATLAS_2011_I919017/d0%s-x%02d-y%02d" % (d,x,y) , "7000", "10" )
logging.info("Processing ATLAS_2011_I926145")
mergeByPt("/ATLAS_2011_I926145/d01-x01-y01", "7000",1.5)
mergeByPt("/ATLAS_2011_I926145/d02-x01-y01", "7000",1.5)
mergeByPt("/ATLAS_2011_I926145/d03-x01-y01", "7000",1.5)
logging.info("Processing CMS_2011_S8941262")
useOnePt("/CMS_2011_S8941262/d01-x01-y01", "7000", "10" )
useOnePt("/CMS_2011_S8941262/d03-x01-y01", "7000", "10" )
mergeByPt("/CMS_2011_S8941262/d02-x01-y01", "7000",1.5)
logging.info("Processing CMS_2011_S8973270")
useOnePt("/CMS_2011_S8973270/d01-x01-y01", "7000", "70" )
useOnePt("/CMS_2011_S8973270/d02-x01-y01", "7000", "100" )
useOnePt("/CMS_2011_S8973270/d03-x01-y01", "7000", "130" )
useOnePt("/CMS_2011_S8973270/d04-x01-y01", "7000", "70" )
useOnePt("/CMS_2011_S8973270/d05-x01-y01", "7000", "100" )
useOnePt("/CMS_2011_S8973270/d06-x01-y01", "7000", "130" )
logging.info("Processing ATLAS_2012_I1082009")
useOnePt("/ATLAS_2012_I1082009/d08-x01-y01", "7000", "40" )
useOnePt("/ATLAS_2012_I1082009/d09-x01-y01", "7000", "40" )
useOnePt("/ATLAS_2012_I1082009/d10-x01-y01", "7000", "40" )
useOnePt("/ATLAS_2012_I1082009/d11-x01-y01", "7000", "80" )
useOnePt("/ATLAS_2012_I1082009/d12-x01-y01", "7000", "80" )
useOnePt("/ATLAS_2012_I1082009/d13-x01-y01", "7000", "40" )
logging.info("Processing ATLAS_2012_I1118269")
mergeByPt("/ATLAS_2012_I1118269/d01-x01-y01", "7000")
useOnePt("/ATLAS_2012_I1118269/d02-x01-y01", "7000", "10" )
logging.info("Processing ATLAS_2012_I1188891")
mergeByPt("/ATLAS_2012_I1188891/d01-x01-y01", "7000")
mergeByPt("/ATLAS_2012_I1188891/d02-x01-y01", "7000")
mergeByPt("/ATLAS_2012_I1188891/d03-x01-y01", "7000")
mergeByPt("/ATLAS_2012_I1188891/d04-x01-y01", "7000")
mergeByPt("/ATLAS_2012_I1188891/d05-x01-y01", "7000")
mergeByPt("/ATLAS_2012_I1188891/d06-x01-y01", "7000")
logging.info("Processing CMS_2012_I1087342")
mergeByPt("/CMS_2012_I1087342/d01-x01-y01", "7000")
mergeByPt("/CMS_2012_I1087342/d02-x01-y01", "7000")
mergeByPt("/CMS_2012_I1087342/d03-x01-y01", "7000")
logging.info("Processing CMS_2012_PAS_QCD_11_010")
mergeByPt("/CMS_2012_PAS_QCD_11_010/d01-x01-y01", "7000")
mergeByPt("/CMS_2012_PAS_QCD_11_010/d02-x01-y01", "7000")
mergeByPt("/CMS_2012_PAS_QCD_11_010/d03-x01-y01", "7000")
mergeByPt("/CMS_2012_PAS_QCD_11_010/d04-x01-y01", "7000")
logging.info("Processing ATLAS_2011_S9035664")
mergeByPt("/ATLAS_2011_S9035664/d11-x01-y01", "7000")
mergeByPt("/ATLAS_2011_S9035664/d12-x01-y01", "7000")
mergeByPt("/ATLAS_2011_S9035664/d13-x01-y01", "7000")
mergeByPt("/ATLAS_2011_S9035664/d14-x01-y01", "7000")
mergeByPt("/ATLAS_2011_S9035664/d15-x01-y01", "7000")
mergeByPt("/ATLAS_2011_S9035664/d16-x01-y01", "7000")
mergeByPt("/ATLAS_2011_S9035664/d17-x01-y01", "7000")
mergeByPt("/ATLAS_2011_S9035664/d18-x01-y01", "7000")
mergeByPt("/ATLAS_2011_S9035664/d20-x01-y01", "7000")
mergeByPt("/ATLAS_2011_S9035664/d21-x01-y01", "7000")
mergeByPt("/ATLAS_2011_S9035664/d22-x01-y01", "7000")
mergeByPt("/ATLAS_2011_S9035664/d23-x01-y01", "7000")
logging.info("Processing ATLAS_2012_I1125575")
mergeByPt("/ATLAS_2012_I1125575/d01-x01-y01", "7000")
mergeByPt("/ATLAS_2012_I1125575/d01-x01-y02", "7000")
mergeByPt("/ATLAS_2012_I1125575/d01-x02-y01", "7000")
mergeByPt("/ATLAS_2012_I1125575/d01-x02-y02", "7000")
mergeByPt("/ATLAS_2012_I1125575/d01-x03-y01", "7000")
mergeByPt("/ATLAS_2012_I1125575/d01-x03-y02", "7000")
mergeByPt("/ATLAS_2012_I1125575/d01-x04-y01", "7000")
mergeByPt("/ATLAS_2012_I1125575/d01-x04-y02", "7000")
mergeByPt("/ATLAS_2012_I1125575/d01-x05-y01", "7000")
mergeByPt("/ATLAS_2012_I1125575/d01-x05-y02", "7000")
mergeByPt("/ATLAS_2012_I1125575/d02-x01-y01", "7000")
mergeByPt("/ATLAS_2012_I1125575/d02-x01-y02", "7000")
mergeByPt("/ATLAS_2012_I1125575/d02-x02-y01", "7000")
mergeByPt("/ATLAS_2012_I1125575/d02-x02-y02", "7000")
mergeByPt("/ATLAS_2012_I1125575/d02-x03-y01", "7000")
mergeByPt("/ATLAS_2012_I1125575/d02-x03-y02", "7000")
mergeByPt("/ATLAS_2012_I1125575/d02-x04-y01", "7000")
mergeByPt("/ATLAS_2012_I1125575/d02-x04-y02", "7000")
mergeByPt("/ATLAS_2012_I1125575/d02-x05-y01", "7000")
mergeByPt("/ATLAS_2012_I1125575/d02-x05-y02", "7000")
mergeByPt("/ATLAS_2012_I1125575/d03-x01-y01", "7000")
mergeByPt("/ATLAS_2012_I1125575/d03-x01-y02", "7000")
mergeByPt("/ATLAS_2012_I1125575/d03-x02-y01", "7000")
mergeByPt("/ATLAS_2012_I1125575/d03-x02-y02", "7000")
mergeByPt("/ATLAS_2012_I1125575/d03-x03-y01", "7000")
mergeByPt("/ATLAS_2012_I1125575/d03-x03-y02", "7000")
mergeByPt("/ATLAS_2012_I1125575/d03-x04-y01", "7000")
mergeByPt("/ATLAS_2012_I1125575/d03-x04-y02", "7000")
mergeByPt("/ATLAS_2012_I1125575/d03-x05-y01", "7000")
mergeByPt("/ATLAS_2012_I1125575/d03-x05-y02", "7000")
for d in range(4,7) :
for x in range(1,6) :
if(opts.ue) :
for y in range(1,9) :
useOnePt("/ATLAS_2012_I1125575/d0%s-x0%s-y0%s" % (d,x,y), "7000", "0" )
for y in ["09","10","11","12","13","14","15","16"] :
useOnePt("/ATLAS_2012_I1125575/d0%s-x0%s-y%s" % (d,x,y), "7000", "0" )
for y in range(17,19) :
useOnePt("/ATLAS_2012_I1125575/d0%s-x0%s-y%s" % (d,x,y), "7000", "20" )
else :
for y in range(17,19) :
useOnePt("/ATLAS_2012_I1125575/d0%s-x0%s-y%s" % (d,x,y), "7000", "10" )
for y in range(19,21) :
useOnePt("/ATLAS_2012_I1125575/d0%s-x0%s-y%s" % (d,x,y), "7000", "40" )
# ATLAS_2012_I1094564
useOnePt("/ATLAS_2012_I1094564/d01-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2012_I1094564/d02-x01-y01", "7000", "260" )
useOnePt("/ATLAS_2012_I1094564/d03-x01-y01", "7000", "400" )
useOnePt("/ATLAS_2012_I1094564/d04-x01-y01", "7000", "400" )
useOnePt("/ATLAS_2012_I1094564/d05-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2012_I1094564/d06-x01-y01", "7000", "260" )
useOnePt("/ATLAS_2012_I1094564/d07-x01-y01", "7000", "400" )
useOnePt("/ATLAS_2012_I1094564/d08-x01-y01", "7000", "400" )
useOnePt("/ATLAS_2012_I1094564/d09-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2012_I1094564/d10-x01-y01", "7000", "260" )
useOnePt("/ATLAS_2012_I1094564/d11-x01-y01", "7000", "400" )
useOnePt("/ATLAS_2012_I1094564/d12-x01-y01", "7000", "400" )
useOnePt("/ATLAS_2012_I1094564/d13-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2012_I1094564/d14-x01-y01", "7000", "260" )
useOnePt("/ATLAS_2012_I1094564/d15-x01-y01", "7000", "400" )
useOnePt("/ATLAS_2012_I1094564/d16-x01-y01", "7000", "400" )
useOnePt("/ATLAS_2012_I1094564/d17-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2012_I1094564/d18-x01-y01", "7000", "260" )
useOnePt("/ATLAS_2012_I1094564/d19-x01-y01", "7000", "400" )
useOnePt("/ATLAS_2012_I1094564/d20-x01-y01", "7000", "400" )
useOnePt("/ATLAS_2012_I1094564/d21-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2012_I1094564/d22-x01-y01", "7000", "260" )
useOnePt("/ATLAS_2012_I1094564/d23-x01-y01", "7000", "400" )
useOnePt("/ATLAS_2012_I1094564/d24-x01-y01", "7000", "400" )
useOnePt("/ATLAS_2012_I1094564/d25-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2012_I1094564/d26-x01-y01", "7000", "260" )
useOnePt("/ATLAS_2012_I1094564/d27-x01-y01", "7000", "400" )
useOnePt("/ATLAS_2012_I1094564/d28-x01-y01", "7000", "400" )
useOnePt("/ATLAS_2012_I1094564/d29-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2012_I1094564/d30-x01-y01", "7000", "260" )
useOnePt("/ATLAS_2012_I1094564/d31-x01-y01", "7000", "400" )
useOnePt("/ATLAS_2012_I1094564/d32-x01-y01", "7000", "400" )
useOnePt("/ATLAS_2012_I1094564/d33-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2012_I1094564/d34-x01-y01", "7000", "260" )
useOnePt("/ATLAS_2012_I1094564/d35-x01-y01", "7000", "400" )
useOnePt("/ATLAS_2012_I1094564/d36-x01-y01", "7000", "400" )
logging.info("Processing CMS_2013_I1224539_DIJET")
useOnePt("/CMS_2013_I1224539_DIJET/d01-x01-y01", "7000", "210" )
useOnePt("/CMS_2013_I1224539_DIJET/d02-x01-y01", "7000", "260" )
useOnePt("/CMS_2013_I1224539_DIJET/d03-x01-y01", "7000", "400" )
useOnePt("/CMS_2013_I1224539_DIJET/d04-x01-y01", "7000", "400" )
useOnePt("/CMS_2013_I1224539_DIJET/d05-x01-y01", "7000", "600" )
useOnePt("/CMS_2013_I1224539_DIJET/d06-x01-y01", "7000", "600" )
useOnePt("/CMS_2013_I1224539_DIJET/d07-x01-y01", "7000", "600" )
useOnePt("/CMS_2013_I1224539_DIJET/d08-x01-y01", "7000", "210" )
useOnePt("/CMS_2013_I1224539_DIJET/d09-x01-y01", "7000", "260" )
useOnePt("/CMS_2013_I1224539_DIJET/d10-x01-y01", "7000", "400" )
useOnePt("/CMS_2013_I1224539_DIJET/d11-x01-y01", "7000", "400" )
useOnePt("/CMS_2013_I1224539_DIJET/d12-x01-y01", "7000", "600" )
useOnePt("/CMS_2013_I1224539_DIJET/d13-x01-y01", "7000", "600" )
useOnePt("/CMS_2013_I1224539_DIJET/d14-x01-y01", "7000", "600" )
useOnePt("/CMS_2013_I1224539_DIJET/d15-x01-y01", "7000", "210" )
useOnePt("/CMS_2013_I1224539_DIJET/d16-x01-y01", "7000", "260" )
useOnePt("/CMS_2013_I1224539_DIJET/d17-x01-y01", "7000", "400" )
useOnePt("/CMS_2013_I1224539_DIJET/d18-x01-y01", "7000", "400" )
useOnePt("/CMS_2013_I1224539_DIJET/d19-x01-y01", "7000", "600" )
useOnePt("/CMS_2013_I1224539_DIJET/d20-x01-y01", "7000", "600" )
useOnePt("/CMS_2013_I1224539_DIJET/d21-x01-y01", "7000", "600" )
useOnePt("/CMS_2013_I1224539_DIJET/d22-x01-y01", "7000", "210" )
useOnePt("/CMS_2013_I1224539_DIJET/d23-x01-y01", "7000", "260" )
useOnePt("/CMS_2013_I1224539_DIJET/d24-x01-y01", "7000", "400" )
useOnePt("/CMS_2013_I1224539_DIJET/d25-x01-y01", "7000", "600" )
useOnePt("/CMS_2013_I1224539_DIJET/d26-x01-y01", "7000", "600" )
useOnePt("/CMS_2013_I1224539_DIJET/d27-x01-y01", "7000", "600" )
useOnePt("/CMS_2013_I1224539_DIJET/d28-x01-y01", "7000", "600" )
useOnePt("/CMS_2013_I1273574/d01-x01-y01", "7000", "80" )
mergeByPt("/CMS_2013_I1273574/d02-x01-y01", "7000",1.)
useOnePt("/CMS_2013_I1273574/d03-x01-y01", "7000", "80" )
useOnePt("/CMS_2013_I1273574/d04-x01-y01", "7000", "80" )
useOnePt("/CMS_2013_I1273574/d05-x01-y01", "7000", "80" )
useOnePt("/CMS_2013_I1273574/d06-x01-y01", "7000", "80" )
mergeByPt("/CMS_2013_I1273574/d07-x01-y01", "7000",1.)
useOnePt("/CMS_2013_I1273574/d08-x01-y01", "7000", "80" )
mergeByPt("/CMS_2013_I1273574/d09-x01-y01", "7000",1.)
useOnePt("/CMS_2013_I1273574/d10-x01-y01", "7000", "80" )
mergeByPt("/CMS_2013_I1273574/d11-x01-y01", "7000",1.)
useOnePt("/CMS_2013_I1261026/d01-x01-y01", "7000", "0" )
useOnePt("/CMS_2013_I1261026/d02-x01-y01", "7000", "0" )
useOnePt("/CMS_2013_I1261026/d03-x01-y01", "7000", "0" )
useOnePt("/CMS_2013_I1261026/d04-x01-y01", "7000", "0" )
useOnePt("/CMS_2013_I1261026/d05-x01-y01", "7000", "0" )
useOnePt("/CMS_2013_I1261026/d06-x01-y01", "7000", "0" )
useOnePt("/CMS_2013_I1261026/d07-x01-y01", "7000", "0" )
useOnePt("/CMS_2013_I1261026/d08-x01-y01", "7000", "0" )
useOnePt("/CMS_2013_I1261026/d09-x01-y01", "7000", "0" )
useOnePt("/CMS_2013_I1261026/d10-x01-y01", "7000", "0" )
useOnePt("/CMS_2013_I1261026/d11-x01-y01", "7000", "0" )
useOnePt("/CMS_2013_I1261026/d12-x01-y01", "7000", "0" )
useOnePt("/CMS_2013_I1261026/d13-x01-y01", "7000", "0" )
useOnePt("/CMS_2013_I1261026/d14-x01-y01", "7000", "0" )
useOnePt("/CMS_2013_I1261026/d15-x01-y01", "7000", "0" )
useOnePt("/CMS_2013_I1261026/d16-x01-y01", "7000", "0" )
useOnePt("/CMS_2013_I1261026/d17-x01-y01", "7000", "0" )
-useOneMass("/CMS_2012_I1090423/d01-x01-y01", "7000", "2000" )
-useOneMass("/CMS_2012_I1090423/d02-x01-y01", "7000", "2000" )
-useOneMass("/CMS_2012_I1090423/d03-x01-y01", "7000", "1200" )
-useOneMass("/CMS_2012_I1090423/d04-x01-y01", "7000", "1200" )
-useOneMass("/CMS_2012_I1090423/d05-x01-y01", "7000", "1200" )
-useOneMass("/CMS_2012_I1090423/d06-x01-y01", "7000", "800" )
-useOneMass("/CMS_2012_I1090423/d07-x01-y01", "7000", "800" )
-useOneMass("/CMS_2012_I1090423/d08-x01-y01", "7000", "300" )
-useOneMass("/CMS_2012_I1090423/d09-x01-y01", "7000", "300" )
+logging.info("Processing CMS_2012_I1090423")
+useOneMass("/CMS_2012_I1090423/d01-x01-y01", "7000", "2900" )
+useOneMass("/CMS_2012_I1090423/d02-x01-y01", "7000", "2300" )
+useOneMass("/CMS_2012_I1090423/d03-x01-y01", "7000", "1700" )
+useOneMass("/CMS_2012_I1090423/d04-x01-y01", "7000", "1100" )
+useOneMass("/CMS_2012_I1090423/d05-x01-y01", "7000", "1100" )
+useOneMass("/CMS_2012_I1090423/d06-x01-y01", "7000", "650" )
+useOneMass("/CMS_2012_I1090423/d07-x01-y01", "7000", "650" )
+useOneMass("/CMS_2012_I1090423/d08-x01-y01", "7000", "250" )
+useOneMass("/CMS_2012_I1090423/d09-x01-y01", "7000", "250" )
+
logging.info("Processing ATLAS_2014_I1298811")
mergeByPt("/ATLAS_2014_I1298811/d01-x01-y01", "7000")
mergeByPt("/ATLAS_2014_I1298811/d01-x01-y02", "7000")
mergeByPt("/ATLAS_2014_I1298811/d02-x01-y01", "7000")
mergeByPt("/ATLAS_2014_I1298811/d02-x01-y02", "7000")
mergeByPt("/ATLAS_2014_I1298811/d03-x01-y01", "7000")
mergeByPt("/ATLAS_2014_I1298811/d03-x01-y02", "7000")
mergeByPt("/ATLAS_2014_I1298811/d04-x01-y01", "7000")
mergeByPt("/ATLAS_2014_I1298811/d04-x01-y02", "7000")
mergeByPt("/ATLAS_2014_I1298811/d05-x01-y01", "7000")
mergeByPt("/ATLAS_2014_I1298811/d05-x01-y02", "7000")
mergeByPt("/ATLAS_2014_I1298811/d06-x01-y01", "7000")
mergeByPt("/ATLAS_2014_I1298811/d06-x01-y02", "7000")
mergeByPt("/ATLAS_2014_I1298811/d07-x01-y01", "7000")
mergeByPt("/ATLAS_2014_I1298811/d07-x01-y02", "7000")
mergeByPt("/ATLAS_2014_I1298811/d08-x01-y01", "7000")
mergeByPt("/ATLAS_2014_I1298811/d08-x01-y02", "7000")
mergeByPt("/ATLAS_2014_I1298811/d09-x01-y01", "7000")
mergeByPt("/ATLAS_2014_I1298811/d09-x01-y02", "7000")
mergeByPt("/ATLAS_2014_I1298811/d10-x01-y01", "7000")
mergeByPt("/ATLAS_2014_I1298811/d10-x01-y02", "7000")
useOnePt("/ATLAS_2014_I1298811/d11-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2014_I1298811/d12-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2014_I1298811/d13-x01-y01", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d13-x01-y02", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d14-x01-y01", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d14-x01-y02", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d15-x01-y01", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d15-x01-y02", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d25-x01-y01", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d25-x01-y02", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d26-x01-y01", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d26-x01-y02", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d27-x01-y01", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d27-x01-y02", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d16-x01-y01", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d16-x01-y02", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d17-x01-y01", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d17-x01-y02", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d18-x01-y01", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d18-x01-y02", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d28-x01-y01", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d28-x01-y02", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d29-x01-y01", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d29-x01-y02", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d30-x01-y01", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d30-x01-y02", "7000", "4" )
useOnePt("/ATLAS_2014_I1298811/d19-x01-y01", "7000", "40" )
useOnePt("/ATLAS_2014_I1298811/d19-x01-y02", "7000", "40" )
useOnePt("/ATLAS_2014_I1298811/d20-x01-y01", "7000", "40" )
useOnePt("/ATLAS_2014_I1298811/d20-x01-y02", "7000", "40" )
useOnePt("/ATLAS_2014_I1298811/d21-x01-y01", "7000", "40" )
useOnePt("/ATLAS_2014_I1298811/d21-x01-y02", "7000", "40" )
useOnePt("/ATLAS_2014_I1298811/d31-x01-y01", "7000", "40" )
useOnePt("/ATLAS_2014_I1298811/d31-x01-y02", "7000", "40" )
useOnePt("/ATLAS_2014_I1298811/d32-x01-y01", "7000", "40" )
useOnePt("/ATLAS_2014_I1298811/d32-x01-y02", "7000", "40" )
useOnePt("/ATLAS_2014_I1298811/d33-x01-y01", "7000", "40" )
useOnePt("/ATLAS_2014_I1298811/d33-x01-y02", "7000", "40" )
useOnePt("/ATLAS_2014_I1298811/d22-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2014_I1298811/d22-x01-y02", "7000", "210" )
useOnePt("/ATLAS_2014_I1298811/d23-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2014_I1298811/d23-x01-y02", "7000", "210" )
useOnePt("/ATLAS_2014_I1298811/d24-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2014_I1298811/d24-x01-y02", "7000", "210" )
useOnePt("/ATLAS_2014_I1298811/d34-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2014_I1298811/d34-x01-y02", "7000", "210" )
useOnePt("/ATLAS_2014_I1298811/d35-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2014_I1298811/d35-x01-y02", "7000", "210" )
useOnePt("/ATLAS_2014_I1298811/d36-x01-y01", "7000", "210" )
useOnePt("/ATLAS_2014_I1298811/d36-x01-y02", "7000", "210" )
logging.info("Processing ATLAS_2014_I1268975")
mergeByMass("/ATLAS_2014_I1268975/d01-x01-y01", "7000", 1000.)
mergeByMass("/ATLAS_2014_I1268975/d01-x01-y02", "7000", 1000.)
mergeByMass("/ATLAS_2014_I1268975/d01-x01-y03", "7000", 1000.)
mergeByMass("/ATLAS_2014_I1268975/d01-x01-y04", "7000", 1000.)
mergeByMass("/ATLAS_2014_I1268975/d01-x01-y05", "7000", 1000.)
mergeByMass("/ATLAS_2014_I1268975/d01-x01-y06", "7000", 1000.)
mergeByMass("/ATLAS_2014_I1268975/d02-x01-y01", "7000", 1000.)
mergeByMass("/ATLAS_2014_I1268975/d02-x01-y02", "7000", 1000.)
mergeByMass("/ATLAS_2014_I1268975/d02-x01-y03", "7000", 1000.)
mergeByMass("/ATLAS_2014_I1268975/d02-x01-y04", "7000", 1000.)
mergeByMass("/ATLAS_2014_I1268975/d02-x01-y05", "7000", 1000.)
mergeByMass("/ATLAS_2014_I1268975/d02-x01-y06", "7000", 1000.)
logging.info("Processing ATLAS_2014_I1307243")
useOnePt( "/ATLAS_2014_I1307243/d01-x01-y01", "7000", "80" )
mergeByPt("/ATLAS_2014_I1307243/d02-x01-y01", "7000")
useOnePt( "/ATLAS_2014_I1307243/d03-x01-y01", "7000", "80" )
mergeByPt("/ATLAS_2014_I1307243/d04-x01-y01", "7000")
useOnePt( "/ATLAS_2014_I1307243/d05-x01-y01", "7000", "80" )
mergeByPt("/ATLAS_2014_I1307243/d06-x01-y01", "7000")
useOnePt( "/ATLAS_2014_I1307243/d07-x01-y01", "7000", "80" )
mergeByPt("/ATLAS_2014_I1307243/d08-x01-y01", "7000")
useOnePt( "/ATLAS_2014_I1307243/d09-x01-y01", "7000", "80" )
mergeByPt("/ATLAS_2014_I1307243/d10-x01-y01", "7000")
useOnePt( "/ATLAS_2014_I1307243/d11-x01-y01", "7000", "80" )
mergeByPt("/ATLAS_2014_I1307243/d12-x01-y01", "7000")
useOnePt( "/ATLAS_2014_I1307243/d13-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d14-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d15-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d16-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d17-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d18-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d19-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d20-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d21-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d22-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d23-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d24-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d25-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d26-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d27-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d28-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d29-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d30-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d31-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d32-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d33-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d34-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d35-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d36-x01-y01", "7000", "80" )
useOnePt( "/ATLAS_2014_I1307243/d37-x01-y01", "7000", "80" )
mergeByPt("/ATLAS_2014_I1307243/d38-x01-y01", "7000")
useOnePt( "/ATLAS_2014_I1307243/d39-x01-y01", "7000", "80" )
mergeByPt("/ATLAS_2014_I1307243/d40-x01-y01", "7000")
logging.info("Processing ATLAS_2014_I1325553")
mergeByPt("/ATLAS_2014_I1325553/d01-x01-y01", "7000")
mergeByPt("/ATLAS_2014_I1325553/d01-x01-y02", "7000")
mergeByPt("/ATLAS_2014_I1325553/d01-x01-y03", "7000")
mergeByPt("/ATLAS_2014_I1325553/d01-x01-y04", "7000")
mergeByPt("/ATLAS_2014_I1325553/d01-x01-y05", "7000")
mergeByPt("/ATLAS_2014_I1325553/d01-x01-y06", "7000")
mergeByPt("/ATLAS_2014_I1325553/d02-x01-y01", "7000")
mergeByPt("/ATLAS_2014_I1325553/d02-x01-y02", "7000")
mergeByPt("/ATLAS_2014_I1325553/d02-x01-y03", "7000")
mergeByPt("/ATLAS_2014_I1325553/d02-x01-y04", "7000")
mergeByPt("/ATLAS_2014_I1325553/d02-x01-y05", "7000")
mergeByPt("/ATLAS_2014_I1325553/d02-x01-y06", "7000")
+logging.info("Processing ATLAS_2016_I1419070")
+for i in range(1,13) :
+ if(i<10) :
+ mergeByPt("/ATLAS_2016_I1419070/d0%s-x01-y01" % i, "8000")
+ else :
+ mergeByPt("/ATLAS_2016_I1419070/d%s-x01-y01" % i, "8000")
+# remake differences and sums
+for ihist in range(1,4) :
+ h1 = outhistos["/ATLAS_2016_I1419070/d0%s-x01-y01" % ihist ]
+ h2 = outhistos["/ATLAS_2016_I1419070/d0%s-x01-y01" % (ihist+3)]
+ sstring = "/ATLAS_2016_I1419070/d%s-x01-y01" % (9+ihist)
+ dstring = "/ATLAS_2016_I1419070/d0%s-x01-y01" % (6+ihist)
+ hdiff = yoda.Scatter2D(dstring,dstring)
+ hsum = yoda.Scatter2D(sstring,sstring)
+ outhistos[dstring]= hdiff
+ outhistos[sstring]= hsum
+ for nbin in range(0,h2.numBins) :
+ bsum = h1.bins[nbin]+h2.bins[nbin]
+ ydiff = h2.bins[nbin].mean-h1.bins[nbin].mean
+ ysum = bsum.mean
+ yerr = math.sqrt(h1.bins[nbin].stdErr**2+h2.bins[nbin].stdErr**2)
+ x = h1.bins[nbin].xMid
+ xerr = 0.5*h1.bins[nbin].xWidth
+ hdiff.addPoint(x,ydiff,xerr,yerr)
+ hsum.addPoint(x,ysum ,xerr,bsum.stdErr)
+
+logging.info("ATLAS_2015_I1394679")
+for i in range(1,5) :
+ mergeByPt("/ATLAS_2015_I1394679/d0%s-x01-y01" % i, "8000")
+for i in range(5,11) :
+ if(i<10) :
+ useOnePt( "/ATLAS_2015_I1394679/d0%s-x01-y01" % i, "8000", "110" )
+ else :
+ useOnePt( "/ATLAS_2015_I1394679/d%s-x01-y01" % i, "8000", "110" )
+
+for i in range(0,4) :
+ useOnePt( "/ATLAS_2015_I1394679/d%s-x01-y01" % (11+4*i), "8000", "110" )
+ useOnePt( "/ATLAS_2015_I1394679/d%s-x01-y01" % (12+4*i), "8000", "260" )
+ useOnePt( "/ATLAS_2015_I1394679/d%s-x01-y01" % (13+4*i), "8000", "600" )
+ useOnePt( "/ATLAS_2015_I1394679/d%s-x01-y01" % (14+4*i), "8000", "900" )
+
+for i in range(0,5) :
+ useOnePt( "/ATLAS_2015_I1394679/d%s-x01-y01" % (27+4*i), "8000", "110" )
+ useOnePt( "/ATLAS_2015_I1394679/d%s-x01-y01" % (28+4*i), "8000", "260" )
+ useOnePt( "/ATLAS_2015_I1394679/d%s-x01-y01" % (29+4*i), "8000", "400" )
+ useOnePt( "/ATLAS_2015_I1394679/d%s-x01-y01" % (30+4*i), "8000", "400" )
+
logging.info("Processing CMS_2013_I1208923")
for i in range(1,6) :
mergeByPt ("/CMS_2013_I1208923/d01-x01-y0%s" % i, "7000")
mergeByMass("/CMS_2013_I1208923/d02-x01-y0%s" % i, "7000", 1.)
logging.info("Processing CMS_2014_I1298810")
for i in range(1,19) :
if(i<10) :
mergeByPt("/CMS_2014_I1298810/d0"+str(i)+"-x01-y01", "7000")
else :
mergeByPt("/CMS_2014_I1298810/d"+str(i)+"-x01-y01", "7000")
logging.info("Processing CMS_2014_I1305624")
for x in range(1,6) :
useOnePt( "/CMS_2014_I1305624/d01-x%02d-y01" % x, "7000", "110" )
useOnePt( "/CMS_2014_I1305624/d01-x%02d-y02" % x, "7000", "110" )
useOnePt( "/CMS_2014_I1305624/d01-x%02d-y03" % x, "7000", "260" )
useOnePt( "/CMS_2014_I1305624/d01-x%02d-y04" % x, "7000", "260" )
useOnePt( "/CMS_2014_I1305624/d01-x%02d-y05" % x, "7000", "400" )
# Choose output file
name = args[0]+"-Jets.yoda"
yoda.writeYODA(outhistos,name)
sys.exit(0)
diff --git a/UnderlyingEvent/MPIHandler.h b/UnderlyingEvent/MPIHandler.h
--- a/UnderlyingEvent/MPIHandler.h
+++ b/UnderlyingEvent/MPIHandler.h
@@ -1,920 +1,920 @@
// -*- C++ -*-
//
// MPIHandler.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_MPIHandler_H
#define HERWIG_MPIHandler_H
//
// This is the declaration of the MPIHandler class.
//
#include "ThePEG/Interface/Interfaced.h"
#include "ThePEG/Handlers/StandardEventHandler.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "Herwig/PDT/StandardMatchers.h"
#include "Herwig/Utilities/GSLBisection.h"
//#include "Herwig/Utilities/GSLMultiRoot.h"
#include "Herwig/Utilities/GSLIntegrator.h"
#include "Herwig/Shower/UEBase.h"
#include <cassert>
#include "ProcessHandler.h"
#include "MPIHandler.fh"
namespace Herwig {
using namespace ThePEG;
/** \ingroup UnderlyingEvent
* \class MPIHandler
* This class is responsible for generating additional
* semi hard partonic interactions.
*
* \author Manuel B\"ahr
*
* @see \ref MPIHandlerInterfaces "The interfaces"
* defined for MPIHandler.
* @see ProcessHandler
* @see ShowerHandler
* @see HwRemDecayer
*/
class MPIHandler: public UEBase {
/**
* Maximum number of scatters
*/
static const unsigned int maxScatters_ = 99;
/**
* Class for the integration is a friend to access private members
*/
friend struct Eikonalization;
friend struct TotalXSecBisection;
friend struct slopeAndTotalXSec;
friend struct slopeInt;
friend struct slopeBisection;
public:
/** A vector of <code>SubProcessHandler</code>s. */
typedef vector<SubHdlPtr> SubHandlerList;
/** A vector of <code>Cut</code>s. */
typedef vector<CutsPtr> CutsList;
/** A vector of <code>ProcessHandler</code>s. */
typedef vector<ProHdlPtr> ProcessHandlerList;
/** A vector of cross sections. */
typedef vector<CrossSection> XSVector;
/** A pair of multiplicities: hard, soft. */
typedef pair<unsigned int, unsigned int> MPair;
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
MPIHandler(): softMult_(0), identicalToUE_(-1),
PtOfQCDProc_(-1.0*GeV), Ptmin_(-1.0*GeV),
hardXSec_(0*millibarn), softXSec_(0*millibarn),
totalXSecExp_(0*millibarn),
softMu2_(ZERO), beta_(100.0/GeV2),
algorithm_(2), numSubProcs_(0),
colourDisrupt_(0.0), softInt_(true), twoComp_(true),
DLmode_(2), avgNhard_(0.0), avgNsoft_(0.0),
energyExtrapolation_(2), EEparamA_(0.6*GeV),
EEparamB_(37.5*GeV), refScale_(7000.*GeV),
pT0_(3.11*GeV), b_(0.21) {}
/**
* The destructor.
*/
virtual ~MPIHandler(){}
//@}
public:
/** @name Methods for the MPI generation. */
//@{
/*
* @return true if for this beam setup MPI can be generated
*/
virtual bool beamOK() const;
/**
* Return true or false depending on whether soft interactions are enabled.
*/
virtual bool softInt() const {return softInt_;}
/**
* Get the soft multiplicity from the pretabulated multiplicity
* distribution. Generated in multiplicity in the first place.
* @return the number of extra soft events in this collision
*/
virtual unsigned int softMultiplicity() const {return softMult_;}
/**
* Sample from the pretabulated multiplicity distribution.
* @return the number of extra events in this collision
*/
virtual unsigned int multiplicity(unsigned int sel=0);
/**
* Select a StandardXComb according to it's weight
* @return that StandardXComb Object
* @param sel is the subprocess that should be returned,
* if more than one is specified.
*/
virtual tStdXCombPtr generate(unsigned int sel=0);
//@}
/** @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();
/**
* Initialize this Multiple Interaction handler and all related objects needed to
* generate additional events.
*/
virtual void initialize();
/**
* Finalize this Multiple Interaction handler and all related objects needed to
* generate additional events.
*/
virtual void finalize();
/**
* Clean up the XCombs from our subprocesses after each event.
* ThePEG cannot see them, so the usual cleaning misses these.
*/
virtual void clean();
/**
* Write out accumulated statistics about integrated cross sections.
*/
void statistics() const;
/**
* The level of statistics. Controlls the amount of statistics
* written out after each run to the <code>EventGenerator</code>s
* <code>.out</code> file. Simply the EventHandler method is called here.
*/
int statLevel() const {return eventHandler()->statLevel();}
/**
* Return the hard cross section above ptmin
*/
CrossSection hardXSec() const { return hardXSec_; }
/**
* Return the soft cross section below ptmin
*/
CrossSection softXSec() const { return softXSec_; }
/**
* Return the inelastic cross section
*/
CrossSection inelasticXSec() const { return inelXSec_; }
/** @name Simple access functions. */
//@{
/**
* Return the ThePEG::EventHandler assigned to this handler.
* This methods shadows ThePEG::StepHandler::eventHandler(), because
* it is not virtual in ThePEG::StepHandler. This is ok, because this
* method would give a null-pointer at some stages, whereas this method
* gives access to the explicitely copied pointer (in initialize())
* to the ThePEG::EventHandler.
*/
tEHPtr eventHandler() const {return theHandler;}
/**
* Return the current handler
*/
static const MPIHandler * currentHandler() {
return currentHandler_;
}
/**
* Return theAlgorithm.
*/
virtual int Algorithm() const {return algorithm_;}
/**
* Return the ptmin parameter of the model
*/
virtual Energy Ptmin() const {
if(Ptmin_ > ZERO)
return Ptmin_;
else
throw Exception() << "MPIHandler::Ptmin called without initialize before"
<< Exception::runerror;
}
/**
* Return the slope of the soft pt spectrum as calculated.
*/
virtual InvEnergy2 beta() const {
if(beta_ != 100.0/GeV2)
return beta_;
else
throw Exception() << "MPIHandler::beta called without initialization"
<< Exception::runerror;
}
/**
* Return the pt Cutoff of the Interaction that is identical to the UE
* one.
*/
virtual Energy PtForVeto() const {return PtOfQCDProc_;}
/**
* Return the number of additional "hard" processes ( = multiple
* parton scattering)
*/
virtual unsigned int additionalHardProcs() const {return numSubProcs_-1;}
/**
* Return the fraction of colour disrupted connections to the
* suprocesses.
*/
virtual double colourDisrupt() const {return colourDisrupt_;}
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;
//@}
private:
/**
* Access the list of sub-process handlers.
*/
const SubHandlerList & subProcesses()
const {return theSubProcesses;}
/**
* Access the list of sub-process handlers.
*/
SubHandlerList & subProcesses() {return theSubProcesses;}
/**
* Access the list of cuts.
*/
const CutsList & cuts() const {return theCuts;}
/**
* Access the list of cuts.
*/
CutsList & cuts() {return theCuts;}
/**
* Access the list of sub-process handlers.
*/
const ProcessHandlerList & processHandlers()
const {return theProcessHandlers;}
/**
* Access the list of sub-process handlers.
*/
ProcessHandlerList & processHandlers() {return theProcessHandlers;}
/**
* Method to calculate the individual probabilities for N scatters in the event.
* @param UEXSecs is(are) the inclusiv cross section(s) for the UE process(es).
*/
void Probs(XSVector UEXSecs);
/**
* Debug method to check the individual probabilities.
* @param filename is the file the output gets written to
*/
void MultDistribution(string filename) const;
/**
* Return the value of the Overlap function A(b) for a given impact
* parameter \a b.
* @param b impact parameter
* @param mu2 = inv hadron radius squared. 0 will use the value of
* invRadius_
* @return inverse area.
*/
InvArea OverlapFunction(Length b, Energy2 mu2=ZERO) const;
/**
* Method to calculate the poisson probability for expectation value
* \f$<n> = A(b)\sigma\f$, and multiplicity N.
*/
double poisson(Length b, CrossSection sigma,
unsigned int N, Energy2 mu2=ZERO) const;
/**
* Return n!
*/
double factorial (unsigned int n) const;
/**
* Returns the total cross section for the current CMenergy. The
* decision which parametrization will be used is steered by a
* external parameter of this class.
*/
CrossSection totalXSecExp() const;
/**
* Difference of the calculated total cross section and the
* experimental one from totalXSecExp.
* @param softXSec = the soft cross section that is used
* @param softMu2 = the soft radius, if 0 the hard radius will be used
*/
CrossSection totalXSecDiff(CrossSection softXSec,
Energy2 softMu2=ZERO) const;
/**
* Difference of the calculated elastic slope and the
* experimental one from slopeExp.
* @param softXSec = the soft cross section that is used
* @param softMu2 = the soft radius, if 0 the hard radius will be used
*/
InvEnergy2 slopeDiff(CrossSection softXSec,
Energy2 softMu2=ZERO) const;
/**
* Returns the value of the elastic slope for the current CMenergy.
* The decision which parametrization will be used is steered by a
* external parameter of this class.
*/
InvEnergy2 slopeExp() const;
/**
* Calculate the minimal transverse momentum from the extrapolation
*/
void overrideUECuts();
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static ClassDescription<MPIHandler> initMPIHandler;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MPIHandler & operator=(const MPIHandler &);
/**
* A pointer to the EventHandler that calls us. Has to be saved, because the
* method eventHandler() inherited from ThePEG::StepHandler returns a null-pointer
* sometimes. Leif changed that in r1053 so that a valid pointer is present, when
* calling doinitrun().
*/
tEHPtr theHandler;
/**
* The list of <code>SubProcessHandler</code>s.
*/
SubHandlerList theSubProcesses;
/**
* The kinematical cuts used for this collision handler.
*/
CutsList theCuts;
/**
* List of ProcessHandler used to sample different processes independently
*/
ProcessHandlerList theProcessHandlers;
/**
* A ThePEG::Selector where the individual Probabilities P_N are stored
* and the actual Multiplicities can be selected.
*/
Selector<MPair> theMultiplicities;
/**
* Variable to store the soft multiplicity generated for a event. This
* has to be stored as it is generated at the time of the hard
* additional interactions but used later on.
*/
unsigned int softMult_;
/**
* Variable to store the multiplicity of the second hard process
*/
vector<int> additionalMultiplicities_;
/**
* Variable to store the information, which process is identical to
* the UE one (QCD dijets).
* 0 means "real" hard one
* n>0 means the nth additional hard scatter
* -1 means no one!
*/
int identicalToUE_;
/**
* Variable to store the minimal pt of the process that is identical
* to the UE one. This only has to be set, if it can't be determined
* automatically (i.e. when reading QCD LesHouches files in).
*/
Energy PtOfQCDProc_;
/**
* Variable to store the parameter ptmin
*/
Energy Ptmin_;
/**
* Variable to store the hard cross section above ptmin
*/
CrossSection hardXSec_;
/**
* Variable to store the final soft cross section below ptmin
*/
CrossSection softXSec_;
/**
* Variable to store the inelastic cross section
*/
CrossSection inelXSec_;
/**
* Variable to store the total pp cross section (assuming rho=0!) as
* measured at LHC. If this variable is set, this value is used in the
* subsequent run instead of any of the Donnachie-Landshoff
* parametrizations.
*/
CrossSection totalXSecExp_;
/**
* Variable to store the soft radius, that is calculated during
* initialization for the two-component model.
*/
Energy2 softMu2_;
/**
* slope to the non-perturbative pt spectrum: \f$d\sigma/dp_T^2 = A \exp
* (- beta p_T^2)\f$. Its value is determined durint initialization.
*/
InvEnergy2 beta_;
/**
* Switch to be set from outside to determine the algorithm used for
* UE activity.
*/
int algorithm_;
/**
* Inverse hadron Radius squared \f$ (\mu^2) \f$. Used inside the overlap function.
*/
Energy2 invRadius_;
/**
* Member variable to store the actual number of separate SubProcesses
*/
unsigned int numSubProcs_;
/**
* Variable to store the relative number of colour disrupted
* connections to additional subprocesses. This variable is used in
* Herwig::HwRemDecayer but store here, to have access to all
* parameters through one Object.
*/
double colourDisrupt_;
/**
* Flag to store whether soft interactions, i.e. pt < ptmin should be
* simulated.
*/
bool softInt_;
/**
* Flag to steer wheather the soft part has a different radius, that
* will be dynamically fixed.
*/
bool twoComp_;
/**
* Switch to determine which Donnachie & Landshoff parametrization
* should be used.
*/
unsigned int DLmode_;
/**
* Variable to store the average hard multiplicity.
*/
double avgNhard_;
/**
* Variable to store the average soft multiplicity.
*/
double avgNsoft_;
/**
* The current handler
*/
static MPIHandler * currentHandler_;
/**
* Flag to store whether to calculate the minimal UE pt according to an
* extrapolation formula or whether to use MPIHandler:Cuts[0]:OneCuts[0]:MinKT
*/
unsigned int energyExtrapolation_;
/**
* Parameters for the energy extrapolation formula
*/
Energy EEparamA_;
Energy EEparamB_;
Energy refScale_;
Energy pT0_;
double b_;
protected:
/** @cond EXCEPTIONCLASSES */
/**
* Exception class used by the MultipleInteractionHandler, when something
* during initialization went wrong.
* \todo understand!!!
*/
class InitError: public Exception {};
/** @endcond */
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of MPIHandler. */
template <>
struct BaseClassTrait<Herwig::MPIHandler,1> {
/** Typedef of the first base class of MPIHandler. */
typedef Interfaced NthBase;
};
/** This template specialization informs ThePEG about the name of
* the MPIHandler class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::MPIHandler>
: public ClassTraitsBase<Herwig::MPIHandler> {
/** Return a platform-independent class name */
static string className() { return "Herwig::MPIHandler"; }
/** Return the name(s) of the shared library (or libraries) be loaded to get
* access to the MPIHandler class and any other class on which it depends
* (except the base class). */
static string library() { return "JetCuts.so SimpleKTCut.so HwMPI.so"; }
};
/** @endcond */
}
namespace Herwig {
/**
* A struct for the 2D root finding that is necessary to determine the
* soft cross section and the soft radius that is needed to describe
* the total cross section correctly.
* NOT IN USE CURRENTLY
*/
struct slopeAndTotalXSec : public GSLHelper<CrossSection, CrossSection> {
public:
/**
* Constructor
*/
slopeAndTotalXSec(tcMPIHPtr handler): handler_(handler) {}
/** second argument type */
typedef Energy2 ArgType2;
/** second value type */
typedef InvEnergy2 ValType2;
/** first element of the vector like function to find root for
* @param softXSec soft cross-section
* @param softMu2 \f$\mu^2\f$
*/
CrossSection f1(ArgType softXSec, ArgType2 softMu2) const {
return handler_->totalXSecDiff(softXSec, softMu2);
}
/** second element of the vector like function to find root for
* @param softXSec soft cross-section
* @param softMu2 \f$\mu^2\f$
*/
InvEnergy2 f2(ArgType softXSec, ArgType2 softMu2) const {
return handler_->slopeDiff(softXSec, softMu2);
}
/** provide the actual units of use */
virtual ValType vUnit() const {return 1.0*millibarn;}
/** otherwise rounding errors may get significant */
virtual ArgType aUnit() const {return 1.0*millibarn;}
/** provide the actual units of use */
ValType2 vUnit2() const {return 1.0/GeV2;}
/** otherwise rounding errors may get significant */
ArgType2 aUnit2() const {return GeV2;}
private:
/**
* Pointer to the handler
*/
tcMPIHPtr handler_;
};
/**
* A struct for the root finding that is necessary to determine the
* slope of the soft pt spectrum to match the soft cross section
*/
struct betaBisection : public GSLHelper<Energy2, InvEnergy2>{
public:
/**
* Constructor.
* @param soft = soft cross section, i.e. the integral of the soft
* pt spectrum f(u=p_T^2) = dsig exp(-beta*u/u_min)
* @param dsig = dsigma_hard/dp_T^2 at the p_T cutoff
* @param ptmin = p_T cutoff
*/
betaBisection(CrossSection soft, DiffXSec dsig, Energy ptmin)
: softXSec_(soft), dsig_(dsig), ptmin_(ptmin) {}
/**
* Operator that is used inside the GSLBisection class
*/
virtual Energy2 operator ()(InvEnergy2 beta) const
{
if( fabs(beta*GeV2) < 1.E-4 )
beta = (beta > ZERO) ? 1.E-4/GeV2 : -1.E-4/GeV2;
return (exp(beta*sqr(ptmin_)) - 1.0)/beta - softXSec_/dsig_;
}
/** provide the actual units of use */
virtual ValType vUnit() const {return 1.0*GeV2;}
/** provide the actual units of use */
virtual ArgType aUnit() const {return 1.0/GeV2;}
private:
/** soft cross section */
CrossSection softXSec_;
/** dsigma/dp_T^2 at ptmin */
DiffXSec dsig_;
/** pt cutoff */
Energy ptmin_;
};
/**
* A struct for the root finding that is necessary to determine the
* soft cross section and soft mu2 that are needed to describe the
* total cross section AND elastic slope correctly.
*/
struct slopeBisection : public GSLHelper<InvEnergy2, Energy2> {
public:
/** Constructor */
slopeBisection(tcMPIHPtr handler) : handler_(handler) {}
/**
* Return the difference of the calculated elastic slope to the
* experimental one for a given value of the soft mu2. During that,
* the soft cross section get fixed.
*/
InvEnergy2 operator ()(Energy2 arg) const;
/** Return the soft cross section that has been calculated */
CrossSection softXSec() const {return softXSec_;}
private:
/** const pointer to the MPIHandler to give access to member functions.*/
tcMPIHPtr handler_;
/** soft cross section that is determined on the fly.*/
mutable CrossSection softXSec_;
};
/**
* A struct for the root finding that is necessary to determine the
* soft cross section that is needed to describe the total cross
* section correctly.
*/
struct TotalXSecBisection : public GSLHelper<CrossSection, CrossSection> {
public:
/**
* Constructor
* @param handler The handler
* @param softMu2 \f$\mu^2\f$
*/
TotalXSecBisection(tcMPIHPtr handler, Energy2 softMu2=ZERO):
handler_(handler), softMu2_(softMu2) {}
/**
* operator to return the cross section
* @param argument input cross section
*/
CrossSection operator ()(CrossSection argument) const {
return handler_->totalXSecDiff(argument, softMu2_);
}
/** provide the actual units of use */
virtual ValType vUnit() const {return 1.0*millibarn;}
/** otherwise rounding errors may get significant */
virtual ArgType aUnit() const {return 1.0*millibarn;}
private:
/**
* The handler
*/
tcMPIHPtr handler_;
/**
* \f$\mu^2\f$
*/
Energy2 softMu2_;
};
/**
* Typedef for derivative of the length
*/
- typedef QTY<1,-2,0>::Type LengthDiff;
+ typedef Qty<1,-2,0> LengthDiff;
/**
* A struct for the integrand for the slope
*/
struct slopeInt : public GSLHelper<LengthDiff, Length>{
public:
/** Constructor
* @param handler The handler
* @param hard The hard cross section
* @param soft The soft cross section
* @param softMu2 \f$\mu^2\f$
*/
slopeInt(tcMPIHPtr handler, CrossSection hard,
CrossSection soft=0*millibarn, Energy2 softMu2=ZERO)
: handler_(handler), hardXSec_(hard),
softXSec_(soft), softMu2_(softMu2) {}
/**
* Operator to return the answer
* @param arg The argument
*/
ValType operator ()(ArgType arg) const;
private:
/**
* Pointer to the Handler that calls this integrand
*/
tcMPIHPtr handler_;
/**
* The hard cross section to be eikonalized
*/
CrossSection hardXSec_;
/**
* The soft cross section to be eikonalized. Default is zero
*/
CrossSection softXSec_;
/**
* The inv radius^2 of the soft interactions.
*/
Energy2 softMu2_;
};
/**
* A struct for the eikonalization of the inclusive cross section.
*/
struct Eikonalization : public GSLHelper<Length, Length>{
/**
* The constructor
* @param handler is the pointer to the MPIHandler to get access to
* MPIHandler::OverlapFunction and member variables of the MPIHandler.
* @param option is a flag, whether the inelastic or the total
* @param handler The handler
* @param hard The hard cross section
* @param soft The soft cross section
* @param softMu2 \f$\mu^2\f$
* cross section should be returned (-2 or -1). For option = N > 0 the integrand
* is N*(A(b)*sigma)^N/N! exp(-A(b)*sigma) this is the P_N*sigma where
* P_N is the Probability of having exactly N interaction (including the hard one)
* This is equation 14 from "Jimmy4: Multiparton Interactions in HERWIG for the LHC"
*/
Eikonalization(tcMPIHPtr handler, int option, CrossSection hard,
CrossSection soft=0*millibarn, Energy2 softMu2=ZERO)
: theHandler(handler), theoption(option), hardXSec_(hard),
softXSec_(soft), softMu2_(softMu2) {}
/**
* Get the function value
*/
Length operator ()(Length argument) const;
private:
/**
* Pointer to the Handler that calls this integrand
*/
tcMPIHPtr theHandler;
/**
* A flag to switch between the calculation of total and inelastic cross section
* or calculations for the individual probabilities. See the constructor
*/
int theoption;
/**
* The hard cross section to be eikonalized
*/
CrossSection hardXSec_;
/**
* The soft cross section to be eikonalized. Default is zero
*/
CrossSection softXSec_;
/**
* The inv radius^2 of the soft interactions.
*/
Energy2 softMu2_;
};
}
#ifndef ThePEG_TEMPLATES_IN_CC_FILE
// #include "MPIHandler.tcc"
#endif
#endif /* HERWIG_MPIHandler_H */
diff --git a/Utilities/GSLHelper.h b/Utilities/GSLHelper.h
--- a/Utilities/GSLHelper.h
+++ b/Utilities/GSLHelper.h
@@ -1,89 +1,89 @@
// -*- C++ -*-
//
// GSLHelper.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_GSLHelper_H
#define HERWIG_GSLHelper_H
//
// This is the declaration of the GSLHelper class.
//
namespace Herwig {
using namespace ThePEG;
/** \ingroup Utilities This class can be used to inherit data structures
* from, which can then be used by the GSL algorithms that need a
* pointer to a function and don't know about Units. This class defines
* the necessary typedefs and forces you to define the "()" operator. In
* addition it implements the vUnit and aUnit static methods which can
* be overwritten if the corresponding base unit is too far from the
* actual used unit. This removes the numerical problem that arises once
* the base unit is several orders of magnitude away from the used unit.
*/
template <typename V, typename T>
struct GSLHelper
{
public:
/**
* Constructor
*/
GSLHelper() {}
/**
* Destructor
*/
virtual ~GSLHelper() {}
/**
* Typedef for Agrument type
*/
typedef T ArgType;
/**
* Typedef for Value type
*/
typedef V ValType;
/**
* Value type
*/
- virtual V vUnit() const {return TypeTraits<V>::baseunit;}
+ virtual V vUnit() const {return TypeTraits<V>::baseunit();}
/**
* Agrument type
*/
- virtual T aUnit() const {return TypeTraits<T>::baseunit;}
+ virtual T aUnit() const {return TypeTraits<T>::baseunit();}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
GSLHelper & operator=(const GSLHelper &);
};
}
namespace {
template <class T> struct GSLparam {
//The function to find root for
const T & function;
};
}
#endif /* HERWIG_GSLHelper_H */
diff --git a/Utilities/GSLIntegrator.tcc b/Utilities/GSLIntegrator.tcc
--- a/Utilities/GSLIntegrator.tcc
+++ b/Utilities/GSLIntegrator.tcc
@@ -1,118 +1,118 @@
// -*- C++ -*-
//
// GSLIntegrator.tcc 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 templated member
// functions of the GSLIntegrator class.
//
using namespace Herwig;
using namespace ThePEG;
namespace {
template <class T> struct param {
//The integrand function
const T & function;
};
template<class T> double integrand(double x , void * p) {
//Units of the argument and return type
const typename T::ValType ValUnit =
- TypeTraits<typename T::ValType>::baseunit;
+ TypeTraits<typename T::ValType>::baseunit();
const typename T::ArgType ArgUnit =
- TypeTraits<typename T::ArgType>::baseunit;
+ TypeTraits<typename T::ArgType>::baseunit();
const T & f = ((struct param<T> *)p)->function;
return f(x * ArgUnit ) / ValUnit;
}
}
namespace Herwig {
using namespace ThePEG;
template <class T>
inline typename BinaryOpTraits<typename T::ValType,
typename T::ArgType>::MulT
GSLIntegrator::value(const T & fn,
const typename T::ArgType lower,
const typename T::ArgType upper) const {
typename BinaryOpTraits<typename T::ValType,
typename T::ArgType>::MulT error;
return value(fn,lower,upper,error);
}
template <class T>
inline typename BinaryOpTraits<typename T::ValType,
typename T::ArgType>::MulT
GSLIntegrator::value(const T & fn,
const typename T::ArgType lower,
const typename T::ArgType upper,
typename BinaryOpTraits<typename T::ValType,
typename T::ArgType>::MulT & error) const {
typedef typename T::ValType ValType;
typedef typename T::ArgType ArgType;
- const ValType ValUnit = TypeTraits<ValType>::baseunit;
- const ArgType ArgUnit = TypeTraits<ArgType>::baseunit;
+ const ValType ValUnit = TypeTraits<ValType>::baseunit();
+ const ArgType ArgUnit = TypeTraits<ArgType>::baseunit();
double result(0.), error2(0.);
param<T> parameters = { fn };
gsl_function integrationFunction;
integrationFunction.function = &integrand<T>;
integrationFunction.params = &parameters;
gsl_integration_workspace * workspace =
gsl_integration_workspace_alloc(_nbins);
//do integration
//Want to check error messages ourselves
gsl_error_handler_t * oldhandler = gsl_set_error_handler_off();
int status = gsl_integration_qags(&integrationFunction, lower/ArgUnit,
upper/ArgUnit, _abserr, _relerr, _nbins,
workspace, &result, &error2);
if( status > 0 ) {
CurrentGenerator::log() << "An error occurred in the GSL "
"integration subroutine:\n";
switch( status ) {
case GSL_EMAXITER:
CurrentGenerator::log() << "The maximum number of subdivisions "
"was exceeded.\n";
break;
case GSL_EROUND:
CurrentGenerator::log() << "Cannot reach tolerance because of "
"roundoff error, or roundoff error was detected in the "
"extrapolation table.\n";
break;
case GSL_ESING:
CurrentGenerator::log() << "A non-integrable singularity or "
"other bad integrand behavior was found in the integration "
"interval.\n";
break;
case GSL_EDIVERGE:
CurrentGenerator::log() << "The integral is divergent, "
"or too slowly convergent to be integrated numerically.\n";
break;
default:
CurrentGenerator::log() << "A general error occurred with code "
<< status << '\n';
}
result = 0.;
}
gsl_set_error_handler(oldhandler);
gsl_integration_workspace_free(workspace);
//fix units and return
error = error2* ValUnit * ArgUnit;
return result * ValUnit * ArgUnit;
}
}
diff --git a/Utilities/GaussianIntegrator.tcc b/Utilities/GaussianIntegrator.tcc
--- a/Utilities/GaussianIntegrator.tcc
+++ b/Utilities/GaussianIntegrator.tcc
@@ -1,114 +1,114 @@
// -*- C++ -*-
//
// GaussianIntegrator.tcc 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 templated member
// functions of the GaussianIntegrator class.
//
namespace Herwig {
using namespace ThePEG;
template <class T>
inline typename BinaryOpTraits<typename T::ValType,
typename T::ArgType>::MulT
GaussianIntegrator::value(const T & function,
const typename T::ArgType lower,
const typename T::ArgType upper) const {
typedef typename T::ValType ValType;
typedef typename T::ArgType ArgType;
- const ValType ValUnit = TypeTraits<ValType>::baseunit;
- const ArgType ArgUnit = TypeTraits<ArgType>::baseunit;
+ const ValType ValUnit = TypeTraits<ValType>::baseunit();
+ const ArgType ArgUnit = TypeTraits<ArgType>::baseunit();
// vector for the limits of the bin
vector<double> lowerlim,upperlim;
// start with the whole interval as 1 bin
lowerlim.push_back(lower/ArgUnit);upperlim.push_back(upper/ArgUnit);
// set the minimum bin width
double xmin=_binwidth*abs(upper-lower)/ArgUnit;
// counters for the number of function evals
int neval=0;
// and number of bad intervals
int nbad=0;
// the output value
double output=0.;
// the loop for the evaluation
double mid,wid; unsigned int ibin,ix=0,iorder;
double testvalue,value,tolerance;
do {
// the bin we are doing (always the last one in the list)
ibin = lowerlim.size()-1;
// midpoint and width of the bin
mid=0.5*(upperlim[ibin]+lowerlim[ibin]);
wid=0.5*(upperlim[ibin]-lowerlim[ibin]);
value=0.;
iorder=0;
// compute a trail value using sixth order GQ
for(ix=0;ix<_weights[0].size();++ix) {
value+=_weights[0][ix]
*( function((mid+wid*_abscissae[0][ix])*ArgUnit)
+function((mid-wid*_abscissae[0][ix])*ArgUnit)
)/ValUnit;
++neval;
if(neval>_maxeval)
CurrentGenerator::log() << "Error in Gaussian Integrator: Setting to zero"
<< endl;
}
value *=wid;
// compute more accurate answers using higher order GQ
do {
// use the next order of quadrature
testvalue=value;
++iorder;
value=0.;
for(ix=0;ix<_weights[iorder].size();++ix) {
value+=_weights[iorder][ix]*
( function((mid+wid*_abscissae[iorder][ix])*ArgUnit)
+function((mid-wid*_abscissae[iorder][ix])*ArgUnit)
)/ValUnit;
++neval;
if(neval>_maxeval)
CurrentGenerator::log() << "Error in Gaussian Integrator: Setting to zero"
<< endl;
}
value *=wid;
tolerance=max(_abserr,_relerr*abs(value));
}
// keep going if possible and not accurate enough
while(iorder<_weights.size()-1&&abs(testvalue-value)>tolerance);
// now decide what to do
// accept this value
if(abs(testvalue-value)<tolerance) {
output+=value;
lowerlim.pop_back();upperlim.pop_back();
}
// bin too small to redivide contribution set to zero
else if(wid<xmin) {
++nbad;
lowerlim.pop_back(); upperlim.pop_back();
}
// otherwise split the bin into two
else {
// reset the limits for the bin
upperlim[ibin]=mid;
// set up a new bin
lowerlim.push_back(mid);
upperlim.push_back(mid+wid);
}
}
// keep going if there's still some bins to evaluate
while(lowerlim.size()>0);
// output an error message if needed
if(nbad!=0)
CurrentGenerator::log() << "Error in GaussianIntegrator: Bad Convergence for "
<< nbad << "intervals" << endl;
// return the answer
return output * ValUnit * ArgUnit;
}
}
diff --git a/Utilities/Histogram.h b/Utilities/Histogram.h
--- a/Utilities/Histogram.h
+++ b/Utilities/Histogram.h
@@ -1,440 +1,440 @@
// -*- C++ -*-
//
// Histogram.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_Histogram_H
#define HERWIG_Histogram_H
//
// This is the declaration of the Histogram class.
//
#include "Histogram.fh"
#include "ThePEG/Interface/Interfaced.h"
#include "Statistic.h"
#include <string>
namespace Herwig {
using namespace ThePEG;
/**
* Options for histogram output.
* They can be combined using the '|' operator, e.g. 'Frame | Ylog'
*/
namespace HistogramOptions {
const unsigned int None = 0; /**< No options */
const unsigned int Frame = 1; /**< Plot on new frame */
const unsigned int Errorbars = 1 << 1; /**< Plot error bars */
const unsigned int Xlog = 1 << 2; /**< log scale for x-axis */
const unsigned int Ylog = 1 << 3; /**< log scale for y-axis */
const unsigned int Smooth = 1 << 4; /**< smooth the line */
const unsigned int Rawcount = 1 << 5; /**< don't normalize to unit area */
}
/**
* The Histogram class is a simple histogram for the Analysis handlers.
*
* @see \ref HistogramInterfaces "The interfaces"
* defined for Histogram.
*/
class Histogram: public Interfaced {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
* @param lower The lower limit of the histogram
* @param upper The upper limit of the histogram
* @param nbin Number of bins
*/
Histogram(double lower=0., double upper=0., unsigned int nbin=0)
: _globalStats(), _havedata(false), _bins(nbin+2),_prefactor(1.),_total(0.) {
if (upper<lower) swap(upper,lower);
_bins[0].limit=-1.e100;
double limit(lower);
double width((upper-lower)/nbin);
for(unsigned int ix=1; ix <= nbin; ++ix) {
_bins[ix].limit=limit;
limit += width;
}
_bins.back().limit=limit;
}
/**
* Constructor for variable width bins
* @param limits The lower limits for the bins followed by the upper limit of the last bin
*/
Histogram(vector<double> limits)
: _globalStats(), _havedata(false), _bins(limits.size()+1), _prefactor(1.),_total(0.) {
_bins[0].limit=-1.e100;
for (size_t i=1; i<=limits.size(); ++i)
_bins[i].limit=limits[i-1];
}
/**
* Constructor with data included
* @param limits The lower limits for the bins followed by the upper limit of the last bin
* @param data The data
* @param dataerror The errors on the data
*/
Histogram(vector<double> limits, vector<double> data, vector<double> dataerror)
: _globalStats(), _havedata(true), _bins(limits.size()+1), _prefactor(1.),_total(0.) {
_bins[0].limit=-1.e100;
for (size_t i=1; i<=limits.size(); ++i)
_bins[i].limit=limits[i-1];
// no data goes into _bins[0] or _bins.back()!
for (size_t i=1; i<=min(limits.size()-1,data.size()); ++i)
_bins[i].data=data[i-1];
for (size_t i=1; i<=min(limits.size()-1,dataerror.size()); ++i)
_bins[i].dataerror=dataerror[i-1];
}
//@}
public:
/**
* Operator to add a point to the histogrma with unit weight
*/
void operator += (double input) {
addWeighted(input,1.0);
}
/**
* Function to add a weighted point to the histogram
*/
void addWeighted(double input, double weight) {
- if(isnan(input)) return;
+ if(std::isnan(input)) return;
unsigned int ibin;
for(ibin=1; ibin<_bins.size(); ++ibin) {
if(input<_bins[ibin].limit)
break;
}
_bins[ibin-1].contents += weight;
_bins[ibin-1].contentsSq += sqr(weight);
_globalStats += weight * input;
_total += weight;
}
/**
* Number of bins (not counting the overflow)
*/
unsigned int numberOfBins() const {
return _bins.size()-2;
}
/**
* Get the prefactor
*/
double prefactor() const {
return _prefactor;
}
/**
* Set the prefactor
*/
void prefactor(double in ) {
_prefactor=in;
}
/**
* Access to the statistics on the total entry of the histogram
*/
const Statistic & globalStatistics() const {
return _globalStats;
}
/**
* Normalise the distributions to the data
*/
void normaliseToData();
/**
* Normalise the distributions to the total cross section
*/
void normaliseToCrossSection();
/**
* Return the chi squared
* @param chisq The chi squared
* @param ndegrees The number of points
* @param minfrac The minimum fractional error on the data point
*/
void chiSquared(double & chisq,
unsigned int & ndegrees, double minfrac=0.) const;
/**
* @brief Output as file ready for usage with flat2aida and other Rivet tools
* @param out The output stream
* @param histogramname The histogram name identifying the histogram. Required
* for comparisons (e.g. with rivet-mkhtml or with
* compare-histos)
* @param analysisname The analysis name
* @param title The title for the top of the plot in LaTeX format
* @param xlabel The x label in LaTeX format
* @param ylabel The y label in LaTeX format
* @param rawcount Don't normalise to unit area.
* @param multiplicator Factor the histogram is multiplied with.
* N.B. Experimental data is not output.
*/
void rivetOutput(ostream & out,
string histogramname = string("default"),
string analysisname = string("default"),
string title = string(),
string xlabel = string(),
string ylabel = string(),
bool rawcount = false,
double multiplicator = 1.0) const;
/**
* Output as a topdrawer file. The histogram is normalised to unit area
* @param out The output stream
* @param flags A bitmask of flags from HistogramOptions, e.g. Frame|Ylog
* @param colour The colour for the line
* @param title The title for the top of the plot
* @param titlecase topdraw format for the title
* @param left Left axis lable
* @param leftcase topdraw format for left axis label
* @param bottom Bottom axis lable
* @param bottomcase Bottom axis lable ofr topdraw
* N.B. in td smoothing only works for histograms with uniform binning.
*/
void topdrawOutput(ostream & out,
unsigned int flags = 0,
string colour = string("BLACK"),
string title = string(),
string titlecase = string(),
string left = string(),
string leftcase = string(),
string bottom = string(),
string bottomcase = string()
) const;
void topdrawMCatNLO(ostream & out,
unsigned int flags =0 ,
string colour = string("BLACK"),
string title = string()
) const;
/**
* Output as a topdrawer file. A bin by bin average is taken.
* @param out The output stream
* @param frame output on a new graph
* @param errorbars output data points with error bars
* @param xlog log scale on x axis
* @param ylog log scale on y axis
* @param colour The colour for the line
* @param title The title for the top of the plot
* @param titlecase topdraw format for the title
* @param left Left axis lable
* @param leftcase topdraw format for left axis label
* @param bottom Bottom axis lable
* @param bottomcase Bottom axis lable ofr topdraw
*/
void topdrawOutputAverage(ostream & out,
bool frame,
bool errorbars,
bool xlog, bool ylog,
string colour=string("BLACK"),
string title=string(),
string titlecase =string(),
string left=string(),
string leftcase =string(),
string bottom=string(),
string bottomcase =string()) const;
/**
* get the number of visible entries (all entries without those in the
* under- and overflow bins) in the histogram. This assumes integer
* entries, ie it gives wrong results for weighted histograms.
*/
unsigned int visibleEntries() const;
/**
* Compute the normalisation of the data.
*/
double dataNorm() const;
/**
* Output into a simple ascii file, easily readable by gnuplot.
*/
void simpleOutput(ostream & out, bool errorbars, bool normdata=false);
/**
* Dump bin data into a vector
*/
vector<double> dumpBins() const;
/**
* Returns a new histogram containing bin-by-bin ratios of two histograms
*/
Histogram ratioWith(const Histogram & h2) const;
/**
* @brief Returns limits for bins with exponentially increasing widths.
* For usage with the variable-bin-width Histogram constructor.
* @param xmin Lower limit of the first bin, needs to be > 0
* @param nbins Number of bins
* @param base The base, needs to be > 1
*/
static
vector<double> LogBins(double xmin, unsigned nbins, double base = 10.0);
public:
/**
* 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;
//@}
private:
/**
* The static object used to initialize the description of this class.
* Indicates that this is a concrete class with persistent data.
*/
static NoPIOClassDescription<Histogram> initHistogram;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
Histogram & operator=(const Histogram &);
private:
/**
* Global statistics of all data that went into the histogram.
*/
Statistic _globalStats;
/**
* Set to true if there is experimental data available
*/
bool _havedata;
/**
* One bin of the histogram. limit is the _lower_ bound of the bin.
*/
struct Bin {
/**
* Default constructor
*/
Bin() : contents(0.0), contentsSq(0.0),
limit(0.0), data(0.0), dataerror(0.0), points(0) {}
/**
* Contents of the bin
*/
double contents;
/**
* Contents squared for the error
*/
double contentsSq;
/**
* The limit for the bin
*/
double limit;
/**
* The experimental value for the bin
*/
double data;
/**
* The error on the experimental value for the bin
*/
double dataerror;
/**
* The number of points in the bin
*/
long points;
};
/**
* The histogram bins. _bins[0] is the underflow, _bins.back() the overflow
*/
vector<Bin> _bins;
/**
* Prefactors to multiply the output by
*/
double _prefactor;
/**
* Total entry
*/
double _total;
public:
/**
* The vector of bins
*/
vector<Bin> bins() const { return _bins; }
};
}
#include "ThePEG/Utilities/ClassTraits.h"
namespace ThePEG {
/** @cond TRAITSPECIALIZATIONS */
/** This template specialization informs ThePEG about the
* base classes of Histogram. */
template <>
struct BaseClassTrait<Herwig::Histogram,1> {
/** Typedef of the first base class of Histogram. */
typedef Herwig::Statistic NthBase;
};
/** This template specialization informs ThePEG about the name of
* the Histogram class and the shared object where it is defined. */
template <>
struct ClassTraits<Herwig::Histogram>
: public ClassTraitsBase<Herwig::Histogram> {
/** Return a platform-independent class name */
static string className() { return "Herwig::Histogram"; }
};
/** @endcond */
}
#endif /* HERWIG_Histogram_H */
diff --git a/Utilities/Interpolator.h b/Utilities/Interpolator.h
--- a/Utilities/Interpolator.h
+++ b/Utilities/Interpolator.h
@@ -1,218 +1,218 @@
// -*- C++ -*-
//
// Interpolator.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_Interpolator_H
#define HERWIG_Interpolator_H
//
// This is the declaration of the Interpolator class.
//
#include "ThePEG/Interface/Interfaced.h"
#include <cassert>
namespace Herwig {
using namespace ThePEG;
/** \ingroup Utilities
* \author Peter Richardson
*
* This class implments a polynominal interpolation of a table of values, it is
* based on the interpolation code in FORTRAN HERWIG.
*
*/
template <typename ValT, typename ArgT>
class Interpolator: public Interfaced {
public:
/**
* Pointer to an Interpolator
*/
typedef typename Ptr<Interpolator<ValT,ArgT> >::pointer Ptr;
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
Interpolator() : _order(3), _copyx(5),_copyfun(5) {}
/**
* Constructor with data as vectors.
*/
Interpolator(const vector<ValT> & f,
const vector<ArgT> & x,
unsigned int order)
: _fun(f.size(),0.0),_xval(x.size(),0.0),_order(order),
- _funit(TypeTraits<ValT>::baseunit),
- _xunit(TypeTraits<ArgT>::baseunit),
+ _funit(TypeTraits<ValT>::baseunit()),
+ _xunit(TypeTraits<ArgT>::baseunit()),
_copyx(order+2),_copyfun(order+2) {
assert(_order>0);
assert(x.size() == f.size());
for (size_t i = 0; i < f.size(); ++i) {
_fun [i] = f[i] / _funit;
_xval[i] = x[i] / _xunit;
}
}
//@}
/**
* Constructor from bare arrays
*/
Interpolator(size_t size,
const double f[], ValT funit,
const double x[], ArgT xunit,
unsigned int order)
: _fun(size,0.0),_xval(size,0.0),_order(order),
_funit(funit),_xunit(xunit), _copyx(order+2),_copyfun(order+2) {
assert(_order>0);
for (size_t i = 0; i < size; ++i) {
_fun [i] = f[i];
_xval[i] = x[i];
}
}
//@}
/**
* Return the interpolated value
*/
ValT operator () (ArgT) const;
/** Return type for GaussianIntegrator */
typedef ValT ValType;
/** Argument type for GaussianIntegrator */
typedef ArgT ArgType;
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 { return new_ptr(*this); }
/** 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 { return new_ptr(*this); }
//@}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
Interpolator & operator=(const Interpolator &);
private:
/**
* the function values.
*/
vector<double> _fun;
/**
* The x values.
*/
vector<double> _xval;
/**
* the order of interpolation.
*/
unsigned int _order;
/**
* The Unit of the function values
*/
ValT _funit;
/**
* The Unit of the argument values
*/
ArgT _xunit;
/**
* Temporary storage vector
*/
mutable vector<double> _copyx;
/**
* Temporary storage vector
*/
mutable vector<double> _copyfun;
};
/**
* helper function to create InterpolatorPtr easily
* (analogous to make_pair() )
*/
template <typename ValT, typename ArgT>
inline typename Interpolator<ValT,ArgT>::Ptr
make_InterpolatorPtr(size_t size,
const double f[], ValT funit,
const double x[], ArgT xunit,
unsigned int order)
{
return new_ptr(Interpolator<ValT,ArgT>(size,
f,funit,
x,xunit,
order));
}
/**
* helper function to create InterpolatorPtr easily
* (analogous to make_pair() )
*/
template <typename ValT, typename ArgT>
inline typename Interpolator<ValT,ArgT>::Ptr
make_InterpolatorPtr(const typename std::vector<ValT> & f,
const typename std::vector<ArgT> & x,
unsigned int order)
{
return new_ptr(Interpolator<ValT,ArgT>(f,x,order));
}
}
#ifndef ThePEG_TEMPLATES_IN_CC_FILE
#include "Interpolator.tcc"
#endif
#endif /* HERWIG_Interpolator_H */
diff --git a/Utilities/Interpolator.tcc b/Utilities/Interpolator.tcc
--- a/Utilities/Interpolator.tcc
+++ b/Utilities/Interpolator.tcc
@@ -1,162 +1,162 @@
// -*- C++ -*-
//
// Interpolator.tcc 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 Interpolator class.
//
#include "Interpolator.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/ParVector.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
template <typename ValT, typename ArgT>
void Interpolator<ValT,ArgT>::persistentOutput(PersistentOStream & os) const {
os << _xval << _fun << _order
- << ounit(_funit,TypeTraits<ValT>::baseunit)
- << ounit(_xunit,TypeTraits<ArgT>::baseunit);
+ << ounit(_funit,TypeTraits<ValT>::baseunit())
+ << ounit(_xunit,TypeTraits<ArgT>::baseunit());
}
template <typename ValT, typename ArgT>
void Interpolator<ValT,ArgT>::persistentInput(PersistentIStream & is, int) {
is >> _xval >> _fun >> _order
- >> iunit(_funit,TypeTraits<ValT>::baseunit)
- >> iunit(_xunit,TypeTraits<ArgT>::baseunit);
+ >> iunit(_funit,TypeTraits<ValT>::baseunit())
+ >> iunit(_xunit,TypeTraits<ArgT>::baseunit());
}
/**
* Macro for Interpolator user classes to use. Only they know what the
* template arguments are going to be.
*/
#define HERWIG_INTERPOLATOR_CLASSDESC(Name,ValT,ArgT) \
/** \
* Register the Interpolator with ThePEG \
*/ \
DescribeClass<Interpolator<ValT,ArgT>,Interfaced> \
describeHerwigInterpolatorFor##Name("Herwig::Interpolator<"#ValT","#ArgT">","");\
template <typename ValT, typename ArgT>
void Interpolator<ValT,ArgT>::Init() {
static ClassDocumentation<Interpolator<ValT,ArgT> > documentation
("The Interpolator class is design to interpolate a table of values");
static Parameter<Interpolator<ValT,ArgT>,unsigned int> interfaceOrder
("Order",
"Order of the interpolation",
&Interpolator::_order, 3, 1, 10,
false, false, Interface::limited);
static ParVector<Interpolator<ValT,ArgT>,double> interfaceXValues
("XValues",
"The x values for the interpolation",
&Interpolator::_xval, -1, 0., 0, 0,
false, false, Interface::nolimits);
static ParVector<Interpolator<ValT,ArgT>,double> interfaceFunctionValues
("FunctionValues",
"The function values for the interpolation",
&Interpolator::_fun, -1, 0., 0, 0,
false, false, Interface::nolimits);
static Parameter<Interpolator<ValT,ArgT>,ValT> interfaceValueType
("ValueType",
"The unit of the function values",
&Interpolator<ValT,ArgT>::_funit,
- TypeTraits<ValT>::baseunit,
- 1.0*TypeTraits<ValT>::baseunit,
- 0*TypeTraits<ValT>::baseunit,
- 0*TypeTraits<ValT>::baseunit,
+ TypeTraits<ValT>::baseunit(),
+ 1.0*TypeTraits<ValT>::baseunit(),
+ 0*TypeTraits<ValT>::baseunit(),
+ 0*TypeTraits<ValT>::baseunit(),
false, true, Interface::nolimits);
static Parameter<Interpolator<ValT,ArgT>,ArgT> interfaceArgType
("ArgType",
"The unit of the function arguments",
&Interpolator<ValT,ArgT>::_xunit,
- TypeTraits<ArgT>::baseunit,
- 1.0*TypeTraits<ArgT>::baseunit,
- 0*TypeTraits<ArgT>::baseunit,
- 0*TypeTraits<ArgT>::baseunit,
+ TypeTraits<ArgT>::baseunit(),
+ 1.0*TypeTraits<ArgT>::baseunit(),
+ 0*TypeTraits<ArgT>::baseunit(),
+ 0*TypeTraits<ArgT>::baseunit(),
false, true, Interface::nolimits);
}
template <typename ValT, typename ArgT>
ValT Interpolator<ValT,ArgT>::operator ()(ArgT xpt) const {
const double xpoint = xpt / _xunit;
// size of the vectors
unsigned int isize(_xval.size());
// workout the numer of points we need
unsigned int m(std::min(_order,isize)),mp(m+1),ix,iy;
// search for the point if the function increases
int mid,iupp=isize,ilow=0;
if(_xval[0]>_xval[_xval.size()-1]) {
do {
mid=(iupp+ilow)/2;
if(xpoint>_xval[mid]){iupp=mid;}
else{ilow=mid;}
}
while(iupp-ilow>1);
}
// search for the point if the function decreases
else {
do {
mid=(iupp+ilow)/2;
if(xpoint<_xval[mid]){iupp=mid;}
else{ilow=mid;}
}
while(iupp-ilow>1);
}
// ilow is now the midpoint
mid=ilow;
// copy the re-ordered interpolation points
// number of points
unsigned int npoints(_order+2-_order%2),icopy,j(0);
int iloc(0),i(0);
do {
icopy=mid+iloc;
if(icopy>isize-1) npoints=mp;
else {
_copyx[j] = _xval[icopy];
_copyfun[j] = _fun [icopy];
++j;
}
iloc=-iloc;
if(iloc>=0){++iloc;}
}
while(j<npoints);
// do this interpolation
bool extra(npoints!=mp);
for(ix=0;ix<m;++ix) {
if(extra) {
icopy=m-ix-1;
_copyfun[m+1]=(_copyfun[m+1]-_copyfun[m-1])/(_copyx[m+1]-_copyx[icopy]);
}
i=m;
for(iy=ix;iy<m;++iy) {
icopy=i-ix-1;
_copyfun[i]=(_copyfun[i]-_copyfun[i-1])/(_copyx[i]-_copyx[icopy]);
--i;
}
}
double sum(_copyfun[m]);
if(extra) sum=0.5*(sum+_copyfun[m+1]);
i=m-1;
for(ix=0;ix<m;++ix) {
sum=_copyfun[i]+(xpoint-_copyx[i])*sum;
--i;
}
return sum * _funit;
}
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)\""
+utilities_test_CPPFLAGS = $(AM_CPPFLAGS) $(BOOST_CPPFLAGS)
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/Utilities/tests/utilitiesTestsGlobalFixture.h b/Utilities/tests/utilitiesTestsGlobalFixture.h
--- a/Utilities/tests/utilitiesTestsGlobalFixture.h
+++ b/Utilities/tests/utilitiesTestsGlobalFixture.h
@@ -1,27 +1,26 @@
// -*- C++ -*-
//
// utilitiesTestGlobalFixture.h is a part of Herwig - A multi-purpose Monte Carlo event generator
// Copyright (C) 2002-2011 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.
//
#include <boost/test/unit_test.hpp>
#include "ThePEG/Repository/StandardRandom.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Config/Unitsystem.h"
struct FixGlobal1 {
- FixGlobal1() {
+ FixGlobal1() : randomNumberStandardGenerator(), dummy(&randomNumberStandardGenerator) {
BOOST_TEST_MESSAGE( "setup global fixture for utilitiesTest" );
-
- // Initialize randomNumberGenerator
- ThePEG::StandardRandom* randomNumberStandardGenerator = new ThePEG::StandardRandom();
- new ThePEG::UseRandom(randomNumberStandardGenerator);
}
~FixGlobal1() { BOOST_TEST_MESSAGE( "teardown global fixture for utilitiesTest" ); }
+
+ ThePEG::StandardRandom randomNumberStandardGenerator;
+ ThePEG::UseRandom dummy;
};
BOOST_GLOBAL_FIXTURE(FixGlobal1);
diff --git a/cat_with_cpplines b/cat_with_cpplines
new file mode 100755
--- /dev/null
+++ b/cat_with_cpplines
@@ -0,0 +1,6 @@
+#! /bin/bash
+for i in "$@"
+do
+ echo "#line 1 \"$i\""
+ cat "$i"
+done
diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -1,245 +1,239 @@
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/array.hpp])
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_FIND_HEADER([boost/scoped_array.hpp])
-BOOST_FIND_HEADER([boost/scoped_ptr.hpp])
-BOOST_FIND_HEADER([boost/utility.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_CHECK_ABS_BUG
-
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/Scales/MatchboxScale.cc
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
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/lib/Makefile.am b/lib/Makefile.am
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,49 +1,49 @@
pkglib_LTLIBRARIES = Herwig.la
Herwig_la_SOURCES =
Herwig_la_LIBTOOLFLAGS = --tag=CXX
Herwig_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 19:0:0
Herwig_la_LDFLAGS += $(THEPEGLDFLAGS) $(BOOST_SYSTEM_LDFLAGS) $(BOOST_FILESYSTEM_LDFLAGS) $(FCLIBS)
Herwig_la_LIBADD = \
$(top_builddir)/Hadronization/libHwHadronization.la \
-$(top_builddir)/Models/StandardModel/libHwStandardModel.la \
+$(top_builddir)/Models/libHwStandardModel.la \
$(top_builddir)/Decay/libHwDecay.la \
$(top_builddir)/Decay/FormFactors/libHwFormFactor.la \
$(top_builddir)/Decay/Radiation/libHwDecRad.la \
$(top_builddir)/Utilities/libHwUtils.la \
-$(top_builddir)/Models/General/libHwModelGenerator.la \
+$(top_builddir)/Models/libHwModelGenerator.la \
$(top_builddir)/Decay/General/libHwGeneralDecay.la \
$(top_builddir)/MatrixElement/General/libHwGeneralME.la \
$(top_builddir)/MatrixElement/libHwME.la \
$(top_builddir)/MatrixElement/Reweighters/libHwReweighters.la \
$(top_builddir)/MatrixElement/Matchbox/libHwMatchbox.la \
$(top_builddir)/Decay/WeakCurrents/libHwWeakCurrent.la \
$(top_builddir)/Looptools/libHwLooptools.la \
$(top_builddir)/Shower/libHwShower.la \
$(THEPEGLIB) $(BOOST_SYSTEM_LIBS) $(BOOST_FILESYSTEM_LIBS) -ldl
dist_noinst_SCRIPTS = fix-osx-path
POSTPROCESSING = done-all-links
if NEED_APPLE_FIXES
POSTPROCESSING += apple-fixes
endif
all-local: $(POSTPROCESSING)
done-all-links: Herwig.la
find $(top_builddir) \( -name '*.so.*' -or -name '*.so' \) \
-not -name 'lib*' -not -path '$(top_builddir)/lib/*' \
-not -path '$(top_builddir)/.hg/*' -exec $(LN_S) -f \{\} \;
$(LN_S) -f .libs/Herwig*so* .
echo "stamp" > $@
apple-fixes: fix-osx-path done-all-links
./$<
echo "stamp" > $@
clean-local:
rm -f *.so *.so.* done-all-links apple-fixes
diff --git a/m4/herwig.m4 b/m4/herwig.m4
--- a/m4/herwig.m4
+++ b/m4/herwig.m4
@@ -1,954 +1,905 @@
-# check for gcc bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34130
-AC_DEFUN([HERWIG_CHECK_ABS_BUG],
-[
-AC_REQUIRE([HERWIG_COMPILERFLAGS])
-if test "$GCC" = "yes"; then
-AC_MSG_CHECKING([for gcc abs bug])
-AC_RUN_IFELSE([
- AC_LANG_PROGRAM(
- [[ int foo (int i) { return -2 * __builtin_abs(i - 2); } ]],
- [[ if ( foo(1) != -2 || foo(3) != -2 ) return 1; ]]
- )],
- [ AC_MSG_RESULT([not found. Compiler is ok.]) ],
- [
- AC_MSG_RESULT([found. Builtin abs() is buggy.])
- AC_MSG_CHECKING([if -fno-builtin-abs works])
- oldcxxflags=$CXXFLAGS
- CXXFLAGS="$CXXFLAGS -fno-builtin-abs"
- AC_RUN_IFELSE([
- AC_LANG_PROGRAM(
- [[
- #include <cstdlib>
- int foo (int i) { return -2 * std::abs(i - 2); }
- ]],
- [[
- if (foo(1) != -2 || foo(3) != -2) return 1;
- ]]
- )],
- [
- AC_MSG_RESULT([yes. Setting -fno-builtin-abs.])
- AM_CXXFLAGS="$AM_CXXFLAGS -fno-builtin-abs"
- AM_CFLAGS="$AM_CFLAGS -fno-builtin-abs"
- ],
- [
- AC_MSG_RESULT([no. Setting -fno-builtin.])
- AC_MSG_WARN([
-*****************************************************************************
-For this version of gcc, -fno-builtin-abs alone did not work to avoid the
-gcc abs() bug. Instead, all gcc builtin functions are now disabled.
-Update gcc if possible.
-*****************************************************************************])
- AM_CXXFLAGS="$AM_CXXFLAGS -fno-builtin"
- AM_CFLAGS="$AM_CFLAGS -fno-builtin"
- ]
- )
- CXXFLAGS=$oldcxxflags
- ]
-)
-fi
-])
-
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/Herwig.cc b/src/Herwig.cc
deleted file mode 100644
--- a/src/Herwig.cc
+++ /dev/null
@@ -1,303 +0,0 @@
-// -*- C++ -*-
-//
-// Herwig.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.
-//
-#include "Herwig.h"
-#include "HerwigUI.h"
-
-#include <ThePEG/Persistency/PersistentIStream.h>
-#include <ThePEG/Repository/EventGenerator.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 <iostream>
-#include <sstream>
-
-#include <unistd.h>
-#include <sys/wait.h>
-
-#include <boost/filesystem.hpp>
-
-#include "Herwig/Utilities/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);
-
-void HerwigGenericRead(const Herwig::HerwigUI & ui);
-void HerwigGenericRun(const Herwig::HerwigUI & ui);
-}
-
-namespace Herwig {
-namespace API {
-
-void init(const HerwigUI & ui) {
- setSearchPaths(ui, false);
- SamplerBase::setRunLevel(SamplerBase::InitMode);
-
- string infile = ui.inputfile();
-
- // If status is INIT, we need an infile name / runname
- if (infile.empty())
- infile = "HerwigDefaults.in";
-
- breakThePEG();
- {
-# ifdef HERWIG_PKGLIBDIR
- DynamicLoader::appendPath(HERWIG_PKGLIBDIR);
-# endif
-# ifdef 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());
-}
-
-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 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 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();
- }
-
- 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();
- 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();
- }
- if ( ui.integrationJob() && !ui.integrationList().empty() )
- eh->sampler()->integrationList(ui.integrationList());
- if ( ui.runMode() == Herwig::RunMode::MERGEGRIDS ) {
- eh->sampler()->prepare();
- return;
- }
- }
-
- 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(), false );
- break; // avoid sub-forks
- }
- // nothing to do here if we're the parent
- }
-
- // children have nothing else to do
- if (pid == 0) return;
-
- if ( ui.tics() ) std::cout << "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 (WIFEXITED(status)) {
- if (WEXITSTATUS(status) != 0)
- cleanrun = false;
- if ( ui.tics() ) std::cout << "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;
- }
- }
- if (! cleanrun) {
- ui.quit();
- }
- }
-}
-}
-
-
diff --git a/src/Herwig.h b/src/Herwig.h
deleted file mode 100644
--- a/src/Herwig.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// -*- 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
-//
-// 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
-
-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 build mode
- *
- *
- */
-void build(const HerwigUI &);
-
-
-/**
- * Herwig integrate mode
- *
- *
- */
-void integrate(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 &);
-
-}
-
-}
-
-#endif
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/HerwigUI.h b/src/HerwigUI.h
deleted file mode 100644
--- a/src/HerwigUI.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// -*- C++ -*-
-//
-// Herwig.h is a part of Herwig - A multi-purpose Monte Carlo event generator
-// Copyright (C) 2002-2015 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>
-
-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;
-
- /// Repository name to operate on
- virtual std::string repository() const = 0;
-
- /// Name of the file to be read
- virtual std::string inputfile() const = 0;
-
- /// Name of the setup file to be read, to modify the repository
- virtual std::string setupfile() const = 0;
-
- /// Try to resume execution from an earlier interrupted run.
- virtual bool resume() const = 0;
-
- /// Require verbose progress markers
- virtual bool tics() const = 0;
-
- /// A user-defined tag to append to the run name.
- virtual std::string tag() const = 0;
-
- virtual std::string integrationList() 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;
-
- /// Directories from which Herwig reads input files, will be appended to the search path.
- virtual const std::vector<std::string> & appendReadDirectories() 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;
-
- virtual void quitWithHelp() const = 0;
-
- virtual void quit() const = 0;
-
- virtual ~HerwigUI() {}
-
- bool integrationJob() const {
- return runMode() == RunMode::INTEGRATE;
- }
-
- };
-
-}
-
-#endif
diff --git a/src/Makefile.am b/src/Makefile.am
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,237 +1,233 @@
SUBDIRS = defaults snippets Matchbox
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 \
LHC-ADD.in \
LHC-diffractive.in \
LHC-GammaGamma.in \
LHC.in \
LHC-Matchbox.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/Matchbox/DiagonalCKM.in b/src/Matchbox/DiagonalCKM.in
--- a/src/Matchbox/DiagonalCKM.in
+++ b/src/Matchbox/DiagonalCKM.in
@@ -1,6 +1,15 @@
# -*- ThePEG-repository -*-
set /Herwig/MatrixElements/Matchbox/Factory:QuarkFlavourDiagonal Yes
set /Herwig/Vertices/FFWMatchboxVertex:Diagonal Yes
+
+cd /Herwig/MatrixElements/Matchbox/Amplitudes/Builtin
+set Amplitudelnuqqbar:Diagonal Yes
+set Amplitudelnuqqbarg:Diagonal Yes
+set Amplitudelnuqqbargg:Diagonal Yes
+set Amplitudelnuqqbarqqbar:Diagonal Yes
+
+
+
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
application/octet-stream
Expires
Mon, Oct 6, 1:44 PM (1 d, 23 h)
Storage Engine
chunks
Storage Format
Chunks
Storage Handle
cYZqlT3Xk2J1
Default Alt Text
(5 MB)

Event Timeline