Page MenuHomeHEPForge

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/Contrib/Herwig-Parallel/source/herwig-parallel-abort b/Contrib/Herwig-Parallel/source/herwig-parallel-abort
--- a/Contrib/Herwig-Parallel/source/herwig-parallel-abort
+++ b/Contrib/Herwig-Parallel/source/herwig-parallel-abort
@@ -1,264 +1,264 @@
#! /usr/bin/env python
## --------------------
## Herwig-Parallel
## --------------------
## Author: Daniel Rauch
## Date: 25 Feb 2015
## --------------------
import sys
import os
import re
import shutil
import datetime
from subprocess import call
from subprocess import check_output
from ConfigParser import SafeConfigParser
from optparse import OptionParser
from hwp import checkConfig
# load cluster configuration file
configFileNameClusters = os.path.dirname(os.path.realpath(sys.argv[0])) + "/../config/clusters.conf"
configParserClusters = SafeConfigParser()
configParserClusters.read(configFileNameClusters)
# load queue configuration file
configFileNameQueues = os.path.dirname(os.path.realpath(sys.argv[0])) + "/../config/queues.conf"
configParserQueues = SafeConfigParser()
configParserQueues.read(configFileNameQueues)
# sanity checks for cluster and queue configuration
checkConfig(configParserClusters,configParserQueues)
# setup command line options & parameters
parser = OptionParser(usage="%prog [options] runname\nIf neither the options '-e' not '-i' are specified the whole run will be aborted.")
parser.add_option("-e", "--exclude-jobs", dest="exclude", default='', help="space-separated list of job numbers and/or job number ranges (e.g. '1 3 5..8') to be excluded from the abortion")
parser.add_option("-i", "--include-jobs", dest="include", default='', help="space-separated list of job numbers and/or job number ranges (e.g. '1 3 5..8') to be included in the abortion")
opts, args = parser.parse_args()
# sanity checks for command line arguments
if len(args) <> 1:
sys.stderr.write("Must specify an unambiguous name of the parallel run to be aborted!\n")
sys.exit(1)
if len(opts.exclude) > 0 and len(opts.include) > 0:
sys.stderr.write("The options '-e/--exclude-jobs' and '-i/--include-jobs' are mutually exclusive!\n Please make up your mind and use only either one of the two!\n")
sys.exit(1)
exclude_jobs = []
include_jobs = []
for j in opts.exclude.split():
if '..' in j: exclude_jobs += range(int(j.split('..')[0]),int(j.split('..')[1])+1)
else: exclude_jobs.append(int(j))
for j in opts.include.split():
if '..' in j: include_jobs += range(int(j.split('..')[0]),int(j.split('..')[1])+1)
else: include_jobs.append(int(j))
exclude = len(exclude_jobs) > 0
include = len(include_jobs) > 0
mergeAll = not (exclude or include)
run_name = args[0].strip('/')
line = '=============================='
for i in range(len(run_name)): line += '='
print(line)
print("HERWIG-PARALLEL: Aborting run {}".format(run_name))
print(line)
print("")
# read required information from 'run.info' file
integrateQueues = []
integrationjobids = []
jobs = []
job_ids = []
queues = []
clusters = []
f_run_info = open(run_name+'/run.info','r')
l = 0
for line in f_run_info:
l += 1
if l == 2:
setupfile = line.replace('\n','').split('/')[-1]
elif l == 3:
generator = line.replace('\n','')
runfile = generator+'.run'
elif l == 4:
buildScript = line.replace('\n','')
buildScriptTitle = buildScript.split('/')[-1]
elif l == 5:
buildCluster = line.replace('\n','')
clusters.append(buildCluster)
elif l == 6: buildjobid = line.replace('\n','')
elif l == 7:
integrateScript = line.replace('\n','')
integrateScriptTitle = integrateScript.split('/')[-1]
elif l == 8:
integrateQueues = line.replace('\n','').strip().split()
for queue in integrateQueues:
cluster = 'local' if queue == 'local' else configParserQueues.get(queue,'cluster')
if not cluster in clusters:
clusters.append(cluster)
elif l == 9: integrationjobids = line.replace('\n','').split()
elif l == 10:
runScript = line.replace('\n','')
runScriptTitle = runScript.split('/')[-1]
elif l > 12:
data = line.replace('\n','').split()
jobs.append(int(data[1].replace('#','').replace(':','')))
queues.append(data[2])
job_ids.append(data[3])
cluster = 'local' if data[2] == 'local' else configParserQueues.get(data[2],'cluster')
if not cluster in clusters:
clusters.append(cluster)
f_run_info.close()
# get joblist
sys.stdout.write('obtaining joblist'+('s' if len(clusters)>1 else '')+'...')
sys.stdout.flush()
for cluster in clusters:
try:
if cluster == 'local':
call('ps -al > '+run_name+'/joblist.'+cluster, shell=True)
else:
call(configParserClusters.get(cluster,'joblist')+' > '+run_name+'/joblist.'+cluster, shell=True)
except:
sys.exit(1)
ansi_escape = re.compile(r'\x1b[^m]*m') # remove ANSI color escape characters
print('\n > done\n')
f_run_log = open(run_name+'/run.log','a')
# abort build job
if buildjobid != '' and not os.path.isfile(run_name+'/read/'+runfile):
jobRunning = False
if buildCluster == 'local':
try:
ps = check_output('grep '+buildjobid+' '+run_name+'/joblist.local', shell=True)
except:
ps = '' # job already finished
for line in ps.split('\n'):
data = line.split()
if len(data) >= 13:
if data[3] == buildjobid and (buildScriptTitle[:10] in data[13] or buildScript[:10] in data[13]) and not '<defunct>' in line:
print("aborting build job with id {}...".format(buildjobid))
buildChildID = check_output('ps -o pid --ppid '+buildjobid+' --noheaders',shell=True)
call('kill '+buildChildID, shell=True) # kill child process 'Herwig++ build ...' first!
call('kill '+buildjobid, shell=True) # kill parent process 'herwig-parallel-build.sh' afterwards!
print(' > killing job\n')
break
else:
status = ansi_escape.sub('', check_output('grep '+buildjobid+' '+run_name+'/joblist.'+buildCluster+' | ' + configParserClusters.get(buildCluster,'status'), shell=True))
if status == configParserClusters.get(buildCluster,'statusQueued') or status == configParserClusters.get(buildCluster,'statusRunning'):
print("aborting build job with id {}...".format(buildjobid))
f_run_log.write(datetime.datetime.now().isoformat(' ')+': herwig-parallel-abort: aborting build job with id {}\n'.format(buildjobid))
command = configParserClusters.get(buildCluster,'abort').replace('@JOBID@',buildjobid)
try:
output = check_output(command, shell=True).strip().replace('\n',' ')
print(' > {}\n'.format(output))
except:
print(" > error when trying to abort build job with id {}\n".format(buildjobid))
# abort integration jobs
if len(integrationjobids) > 0 and not os.path.isfile(run_name+'/read/Herwig/'+generator+'/'+('' if setupfile=='' else setupfile+'/')+'HerwigGrids.xml'):
for j in range(len(integrationjobids)):
integrateCluster = 'local' if integrateQueues[j] == 'local' else configParserQueues.get(integrateQueues[j],'cluster')
if integrateCluster == 'local':
killedJob = False
try:
ps = check_output('grep '+integrationjobids[j]+' '+run_name+"/joblist.local", shell=True)
except:
ps = ''
for line in ps.split('\n'):
data = line.split()
if len(data) >= 13:
- if data[3] == integrationjobids[j] and (integrateScriptTitle[:10] in data[13] or integrateScript[:10] in data[13]) and not '<defunct>' in line:
+ if data[3] == integrationjobids[j] and 'integrate.' in data[13] and not '<defunct>' in line:
print("aborting integration job #{} with id {}...".format(j+1,integrationjobids[j]))
f_run_log.write(datetime.datetime.now().isoformat(' ')+': herwig-parallel-abort: aborting integration job #{} with id {}\n'.format(j+1,integrationjobids[j]))
integrateChildID = check_output('ps -o pid --ppid '+integrationjobids[j]+' --noheaders',shell=True)
- call('kill '+integrateChildID, shell=True) # kill child process 'Herwig++ integrate ...' first!
- call('kill '+integrationjobids[j], shell=True) # kill parent process 'herwig-parallel-integrate.sh' afterwards!
+ call('kill '+integrationjobids[j], shell=True) # kill parent process 'integrate.jobX.sh' first!
+ call('kill '+integrateChildID, shell=True) # kill child process 'Herwig++ integrate ...' afterwards!
print(' > killing job\n')
killedJob = True
break
if not killedJob:
- print("integration job #{} with id {} already completed...\n".format(j+1,integrationjobids[j]))
- f_run_log.write(datetime.datetime.now().isoformat(' ')+': herwig-parallel-abort: integration job #{} with id {} already completed\n'.format(j+1,integrationjobids[j]))
+ print("integration job #{} with id {} not running...\n".format(j+1,integrationjobids[j]))
+ f_run_log.write(datetime.datetime.now().isoformat(' ')+': herwig-parallel-abort: integration job #{} with id {} not running\n'.format(j+1,integrationjobids[j]))
else:
status = ansi_escape.sub('', check_output('grep '+integrationjobids[j]+' '+run_name+'/joblist.'+integrateCluster+' | ' + configParserClusters.get(cluster,'status'), shell=True))
if status == configParserClusters.get(integrateCluster,'statusQueued') or status == configParserClusters.get(integrateCluster,'statusRunning'):
print("aborting integration job #{} with id {}...".format(j+1,integrationjobids[j]))
f_run_log.write(datetime.datetime.now().isoformat(' ')+': herwig-parallel-abort: aborting integration job #{} with id {}\n'.format(j+1,integrationjobids[j]))
try:
command = configParserClusters.get(integrateCluster,'abort').replace('@JOBID@',integrationjobids[j])
output = check_output(command, shell=True).strip().replace('\n',' ')
print(' > {}\n'.format(output))
except:
print(" > error when trying to abort integration job #{} with id {}\n".format(j+1,integrationjobids[j]))
else:
print("integration job #{} with id {} already completed...\n".format(j+1,integrationjobids[j]))
f_run_log.write(datetime.datetime.now().isoformat(' ')+': herwig-parallel-abort: integration job #{} with id {} already completed\n'.format(j+1,integrationjobids[j]))
# abort run jobs
if len(jobs) > 0:
abort_jobs = []
abort_job_ids = []
for j in range(len(jobs)):
if (exclude and not jobs[j] in exclude_jobs) or (include and jobs[j] in include_jobs):
abort_jobs.append(jobs[j])
abort_job_ids.append(job_ids[j])
for j in exclude_jobs:
if j not in jobs:
print("input error: cannot exclude job #{} from abortion because it does not exist\n".format(j))
for j in include_jobs:
if j not in jobs:
print("input error: cannot include job #{} in abortion because it does not exist\n".format(j))
if len(abort_jobs) == 0:
print("No individual jobs given, aborting the whole run!\n")
abort_jobs = jobs
abort_job_ids = job_ids
for j in range(len(abort_jobs)):
cluster = 'local' if queues[abort_jobs[j]-1] == 'local' else configParserQueues.get(queues[abort_jobs[j]-1], 'cluster')
if cluster == 'local':
killedJob = False
try:
ps = check_output('grep '+abort_job_ids[j]+' '+run_name+'/joblist.local', shell=True)
except:
ps = ''
for line in ps.split('\n'):
data = line.split()
if len(data) >= 13:
if data[3] == abort_job_ids[j] and (runScriptTitle[:10] in data[13] or runScript[:10] in data[13]) and not '<defunct>' in line:
print("aborting job #{} with id {}...".format(abort_jobs[j],abort_job_ids[j]))
f_run_log.write(datetime.datetime.now().isoformat(' ')+': herwig-parallel-abort: aborting job #{} with id {}\n'.format(abort_jobs[j],abort_job_ids[j]))
childID = check_output('ps -o pid --ppid '+abort_job_ids[j]+' --noheaders',shell=True)
call('kill '+childID, shell=True) # kill child process 'Herwig++ run ...' first!
call('kill '+abort_job_ids[j], shell=True) # kill parent process 'herwig-parallel-run.sh' afterwards!
print(' > killing job\n')
killedJob = True
break
if not killedJob:
print("job #{} with id {} can't be aborted because it is neither queued nor running...\n".format(abort_jobs[j],abort_job_ids[j]))
else:
status = ansi_escape.sub('', check_output('grep '+abort_job_ids[j]+' '+run_name+'/joblist.'+cluster+' | ' + configParserClusters.get(cluster,'status'), shell=True))
if status == configParserClusters.get(cluster,'statusQueued') or status == configParserClusters.get(cluster,'statusRunning'):
print("aborting job #{} with id {}...".format(abort_jobs[j],abort_job_ids[j]))
f_run_log.write(datetime.datetime.now().isoformat(' ')+': herwig-parallel-abort: aborting job #{} with id {}\n'.format(abort_jobs[j],abort_job_ids[j]))
try:
command = configParserClusters.get(cluster,'abort').replace('@JOBID@',abort_job_ids[j])
output = check_output(command, shell=True).strip().replace('\n',' ')
print(' > {}\n'.format(output))
except:
print(" > error when trying to abort job #{} with id {}\n".format(abort_jobs[j],abort_job_ids[j]))
else:
print("job #{} with id {} can't be aborted because it is neither queued nor running...\n".format(abort_jobs[j],abort_job_ids[j]))
for cluster in clusters:
os.remove(run_name+'/joblist.'+cluster)
f_run_log.close()
diff --git a/Contrib/Herwig-Parallel/source/herwig-parallel-read b/Contrib/Herwig-Parallel/source/herwig-parallel-read
--- a/Contrib/Herwig-Parallel/source/herwig-parallel-read
+++ b/Contrib/Herwig-Parallel/source/herwig-parallel-read
@@ -1,357 +1,359 @@
#! /usr/bin/env python
## --------------------
## Herwig-Parallel
## --------------------
## Author: Daniel Rauch
## Date: 12 Mar 2015
## --------------------
import sys
import os
import re
import signal
import shutil
import glob
import time
import datetime
from subprocess import call
from subprocess import check_output
from subprocess import Popen
from ConfigParser import SafeConfigParser
from optparse import OptionParser
from hwp import checkConfig
from hwp import addToIndex
from hwp import checkIndex
### ------------
### catch Ctrl+C
### ------------
signal.signal(signal.SIGINT, lambda x,y: exit())
### ------------
### main program
### ------------
def main():
# load Herwig-Parallel configuration file
configFileName = os.path.dirname(os.path.realpath(sys.argv[0])) + "/../config/herwig-parallel.conf"
configParser = SafeConfigParser()
configParser.read(configFileName)
# load cluster configuration file
configFileNameClusters = os.path.dirname(os.path.realpath(sys.argv[0])) + "/../config/clusters.conf"
configParserClusters = SafeConfigParser()
configParserClusters.read(configFileNameClusters)
# load queue configuration file
configFileNameQueues = os.path.dirname(os.path.realpath(sys.argv[0])) + "/../config/queues.conf"
configParserQueues = SafeConfigParser()
configParserQueues.read(configFileNameQueues)
# sanity checks for cluster and queue configuration
queues = checkConfig(configParserClusters,configParserQueues)
# set defaults
default_settings = ['buildscript', 'buildqueue','integratescript', 'integratequeue','integratejobs']
default_variables = ['herwig-parallel-build.sh', queues[0], 'herwig-parallel-integrate.sh', queues[0], '1']
for i in range(len(default_settings)):
try:
default_variables[i] = configParser.get('defaults',default_settings[i])
except:
pass
# setup command line options & parameters
optionParser = OptionParser(usage="%prog [options] infile [setupfile]")
optionParser.add_option("-b", "--buildscript", dest="buildscript", default=default_variables[0], help="file name of script that initiates the Herwig++ build step [default: %default]")
optionParser.add_option("-i", "--integratescript", dest="integratescript", default=default_variables[2], help="file name of script that initiates the Herwig++ integrate step [default: %default]")
optionParser.add_option("-d", "--defaultscripts", action="store_true", dest="defaultscripts", default=False, help="use the default build and integrate scripts from the <Herwig-Parallel>-folder [default: %default]")
optionParser.add_option("-j", "--jobs", dest="jobs", default=default_variables[4], help="number of parallel integration jobs that are requested (note: the actual number of integration jobs that are run may be less, depending on the subprocesses) [default: %default]")
optionParser.add_option("-n", "--name", dest="run_name", default="ParallelRun", help="name of parallel run [default: %default]")
optionParser.add_option("-Q", "--buildqueue", dest="buildqueue", default=default_variables[1], help="local, "+repr(queues).replace('[','').replace(']','').replace("'",'')+" [default: %default]")
optionParser.add_option("-q", "--integratequeue", dest="integratequeue", default=default_variables[3], help="local, "+repr(queues).replace('[','').replace(']','').replace("'",'')+" [default: %default]")
opts, args = optionParser.parse_args()
# sanity checks for command line arguments
if len(args) < 1 or len(args) > 2:
sys.stderr.write("Must specify an unambiguous name of the infile and possibly a setupfile to be used!\n")
sys.exit(1)
if opts.buildqueue != 'local' and not opts.buildqueue in queues:
sys.stderr.write("The specified buildqueue '"+opts.buildqueue+"' was not configured in Herwig-Parallel/config/queues.conf! Please choose a different buildqueue or modify the configuration file.\n")
sys.exit(1)
if opts.integratequeue != 'local' and not opts.integratequeue in queues:
sys.stderr.write("The specified integratequeue '"+opts.integratequeue+"' was not configured in Herwig-Parallel/config/queues.conf! Please choose a different integratequeue or modify the configuration file.\n")
sys.exit(1)
if opts.buildqueue != 'local' and opts.integratequeue != 'local':
if configParserQueues.get(opts.buildqueue,'cluster') != configParserQueues.get(opts.integratequeue,'cluster'):
sys.stderr.write("The specified buildqueue and integratequeue belong to different clusters. This behavior is currently not supported. Please select queues on the same cluster!\n")
sys.exit(1)
path = os.path.dirname(os.path.realpath(sys.argv[0]))
run_name = opts.run_name
infile = args[0]
infile_title = infile.split('/')[-1]
setupfile = args[1] if len(args)>1 else ''
setupfile_title = setupfile.split('/')[-1]
buildscript = opts.buildscript
buildscript_title = buildscript.split('/')[-1]
integratescript = opts.integratescript
integratescript_title = integratescript.split('/')[-1]
jobs = int(opts.jobs)
buildCluster = 'local' if opts.buildqueue == 'local' else configParserQueues.get(opts.buildqueue,'cluster')
integrateCluster = 'local' if opts.integratequeue == 'local' else configParserQueues.get(opts.integratequeue,'cluster')
cwd = os.getcwd()
line = '============================================'
for i in range(len(run_name)): line += '='
print(line)
print("HERWIG-PARALLEL: Starting read step for run {}".format(run_name))
print(line)
print("")
# check for all necessary files
if not os.path.isfile(infile):
sys.stderr.write("The specified infile does not exist!\n")
sys.exit(1)
if setupfile != '' and not os.path.isfile(setupfile):
sys.stderr.write("The specified setupfile does not exist!\n")
sys.exit(1)
if not opts.defaultscripts and not os.path.isfile(buildscript):
sys.stderr.write("The specified build-script does not exist!\n")
sys.exit(1)
if not opts.defaultscripts and not os.path.isfile(integratescript):
sys.stderr.write("The specified integrate-script does not exist!\n")
sys.exit(1)
if opts.defaultscripts:
if not os.path.isfile(path+'/../misc/'+buildscript_title):
sys.stderr.write("The default build-script does not exist!\n")
sys.exit(1)
if not os.path.isfile(path+'/../misc/'+integratescript_title):
sys.stderr.write("The default integrate-script does not exist!\n")
sys.exit(1)
# check for run index file size and possibly trim it down
checkIndex()
# find out generator name
try:
grep = check_output("grep 'saverun' "+infile, shell=True).split('\n')
except:
sys.stderr.write("The event generator is not saved in the infile.\n")
sys.stderr.write("Please include a 'saverun' statement at the end of the infile.\n\n")
sys.exit(1)
i = 0
for line in grep:
cmd = line.split('#')[0].split()
if len(cmd) == 3 and cmd[0] == 'saverun':
i += 1
generator = cmd[1].strip()
runfile = generator+'.run'
if i == 0:
sys.stderr.write("The event generator is not saved in the infile.\n")
sys.stderr.write("Please include a 'saverun' statement at the end of the infile.\n\n")
sys.exit(1)
elif i > 1:
sys.stderr.write("Multiple occurrences of the 'saverun' statement found in the infile.\n")
sys.stderr.write("Only the last occurrence is considered for your run.\n\n")
# set up folder structure
if not os.path.exists(run_name):
os.makedirs(run_name)
else:
sys.stderr.write("WARNING: Run already exists!\n")
sys.exit(1)
if not os.path.exists(run_name+'/read'):
os.makedirs(run_name+'/read')
f_run_info = open(run_name+"/run.info","w")
f_run_info.write(cwd+'/'+infile+'\n')
f_run_info.write('\n' if setupfile == '' else cwd+'/'+setupfile+'\n')
f_run_info.write(generator+'\n')
f_run_info.flush()
# copy infiles to read-folder
shutil.copyfile(infile, run_name+'/read/'+infile_title)
if setupfile != '': shutil.copyfile(setupfile, run_name+'/read/'+setupfile_title)
if opts.defaultscripts:
shutil.copyfile(path+'/../misc/'+buildscript_title, run_name+'/read/'+buildscript_title)
else:
shutil.copyfile(buildscript, run_name+'/read/'+buildscript_title)
call('chmod u+x '+run_name+'/read/'+buildscript_title, shell=True) # set execute permission (lost during copying)
if opts.defaultscripts:
shutil.copyfile(path+'/../misc/'+integratescript_title, run_name+'/read/'+integratescript_title)
else:
shutil.copyfile(integratescript, run_name+'/read/'+integratescript_title)
call('chmod u+x '+run_name+'/read/'+integratescript_title, shell=True) # set execute permission (lost during copying)
# copy raw infiles to in-folder
if not os.path.exists(run_name+'/in'):
os.makedirs(run_name+'/in')
shutil.copyfile(infile, run_name+'/in/'+infile_title)
if setupfile != '': shutil.copyfile(setupfile, run_name+'/in/'+setupfile_title)
shutil.copyfile(run_name+'/read/'+buildscript_title, run_name+'/in/'+buildscript_title)
shutil.copyfile(run_name+'/read/'+integratescript_title, run_name+'/in/'+integratescript_title)
# start build script
f_run_info.write((cwd+'/' if not buildscript.startswith('/') else '')+buildscript+'\n')
f_run_info.write(buildCluster+'\n')
f_run_log = open(run_name+'/run.log','a')
os.chdir(run_name+'/read')
call("sed -i 's/@HOSTNAME@/hostname > build.hostname/' "+buildscript_title, shell=True)
call("sed -i 's/@INFILE@/"+infile_title+"/' "+buildscript_title, shell=True)
call("sed -i 's/@JOBS@/"+str(jobs)+"/' "+buildscript_title, shell=True)
if opts.buildqueue == 'local': # run on local machine
buildLog = open('build.log','w')
print("starting build job")
- buildProc = Popen(cwd+'/'+run_name+'/read/'+buildscript_title,shell=True,stdout=buildLog,stderr=buildLog)
+ buildProc = Popen(cwd+'/'+run_name+'/read/'+buildscript_title,shell=True,stdout=buildLog,stderr=buildLog,preexec_fn=os.setpgrp)
jobid = str(buildProc.pid)
print(" > starting job with pid {}\n".format(jobid))
else: # run on cluster
command = configParserQueues.get(opts.buildqueue, 'submit').replace('@SCRIPT@',buildscript_title)
print("starting build job: {}".format(command))
output = check_output(command, shell=True).strip().replace('\n',' ')
print(" > {}\n".format(output))
jobid = check_output("echo '"+output+"' | "+configParserClusters.get(configParserQueues.get(opts.buildqueue,'cluster'),'jobid'), shell=True)
f_run_info.write(jobid+'\n')
f_run_info.flush()
addToIndex(jobid, cwd+'/'+run_name)
f_run_log.write(datetime.datetime.now().isoformat(' ')+': herwig-parallel-read: starting build job with id {}\n'.format(jobid))
f_run_log.flush()
# wait for completion of build step
iCount = 0
iCrash = 0
while not (os.path.isfile(runfile)):
if iCount % 5 == 0:
sys.stdout.write('\r\033[Kwaiting for completion of build-step')
else:
sys.stdout.write('.')
sys.stdout.flush()
# have a look at the process list or the batch queue system to check wether build process/job is still running
if iCount % 15 == 0:
pending = True
if opts.buildqueue == 'local': # build job running on local machine
pending = True
status = check_output('ps -al', shell=True)
for line in status.split('\n'):
data = line.split()
if len(data) > 3 and data[3] == jobid:
pending = not '<defunct>' in line
break
else: # build job running on cluster
call(configParserClusters.get(buildCluster,'joblist')+' > ../joblist.'+buildCluster, shell=True)
ansi_escape = re.compile(r'\x1b[^m]*m') # remove ANSI color escape characters
status = ansi_escape.sub('', check_output('grep '+jobid+' '+'../joblist.'+buildCluster+' | ' + configParserClusters.get(buildCluster,'status'), shell=True))
pending = status == configParserClusters.get(buildCluster,'statusQueued') or status == configParserClusters.get(buildCluster,'statusRunning')
os.remove('../joblist.'+buildCluster)
if not pending: # job neither queued nor running
iCrash += 1
if iCrash == 2:
sys.stderr.write('\r\033[K! It appears that the build job has terminated unsuccessfully.\n')
sys.stderr.write("! Please check whether the file '"+run_name+'/read/'+generator+".run' exists.\n")
sys.stderr.write("! In case it doesn't exist please check the log files for possible errors.\n\n")
iCount = -1 # display full waiting message again
time.sleep(int(1))
iCount += 1
integrationJobs = len(glob.glob('Herwig/Build/integrationJob*'))
print("\n > done: prepared {} integration job{}\n".format(integrationJobs, 's' if integrationJobs > 1 else ''))
# start integrate step/job(s)
f_run_info.write((cwd+'/' if not integratescript.startswith('/') else '')+integratescript+'\n')
for job in range(integrationJobs): f_run_info.write(opts.integratequeue+' ')
f_run_info.write('\n')
integrateLog = []
integrateProc = []
integrationsJobIDs = []
for job in range(1,integrationJobs+1):
### if '.sh' in integratescript_title:
### script = integratescript_title.replace('.sh','.job'+str(job-1)+'.sh')
### else:
### script = integratescript_title+str(job-1)
script = 'integrate.job'+str(job-1)+'.sh'
shutil.copyfile(integratescript_title,script)
call('chmod u+x '+script, shell=True) # set execute permission (lost during copying)
call("sed -i 's/@HOSTNAME@/hostname > integrate.job"+str(job-1)+".hostname/' "+script, shell=True)
call("sed -i 's/@RUNFILE@/"+runfile+"/' "+script, shell=True)
call("sed -i 's/@JOBID@/"+str(job-1)+"/' "+script, shell=True)
call("sed -i 's/@SETUPFILE@/"+('' if setupfile=='' else '--setupfile='+setupfile_title)+"/' "+script, shell=True)
if opts.integratequeue == 'local':
integrateLog.append(open('integrate.job'+str(job-1)+'.log','w'))
print("starting integrate job #{}".format(job))
- integrateProc.append(Popen(cwd+'/'+run_name+'/read/'+script,shell=True,stdout=integrateLog[job-1],stderr=integrateLog[job-1]))
+ integrateProc.append(Popen(cwd+'/'+run_name+'/read/'+script,shell=True,stdout=integrateLog[job-1],stderr=integrateLog[job-1],preexec_fn=os.setpgrp))
jobid = str(integrateProc[job-1].pid)
print(" > starting job with pid {}\n".format(jobid))
else:
command = configParserQueues.get(opts.integratequeue, 'submit').replace('@SCRIPT@',script)
print("starting integrate job #{}: {}".format(job,command))
output = check_output(command, shell=True).strip().replace('\n',' ')
print(" > {}\n".format(output))
jobid = check_output("echo '"+output+"' | "+configParserClusters.get(configParserQueues.get(opts.integratequeue,'cluster'),'jobid'), shell=True)
integrationsJobIDs.append(jobid)
f_run_info.write(jobid+' ')
f_run_info.flush()
addToIndex(jobid, cwd+'/'+run_name)
f_run_log.write(datetime.datetime.now().isoformat(' ')+': herwig-parallel-read: starting integrate job #{} with id {}\n'.format(job,jobid))
f_run_log.flush()
f_run_info.write('\n')
f_run_info.close()
# wait for completion of integrate steps
iCount = 0
finishedIntegrationStep = False
while not finishedIntegrationStep:
# for each step check for the existence of the grid files as indication of the completion of the integration jobs
finishedIntegrationJobs = 0
for job in range(0,integrationJobs):
if os.path.isfile('Herwig/'+generator+('' if setupfile=='' else '/'+setupfile_title)+'/integrationJob'+str(job)+'/HerwigGrids.xml'):
finishedIntegrationJobs += 1
finishedIntegrationStep = (finishedIntegrationJobs == integrationJobs)
### # additionally generate and check job list every now and then to see if jobs are still queued or running
### if iCount % 20 == 0 or finishedIntegrationStep:
### queuedIntegrationJobs = 0
### runningIntegrationJobs = 0
### call(configParserClusters.get(cluster,'joblist')+' > '+'../tmp', shell=True)
### ansi_escape = re.compile(r'\x1b[^m]*m') # remove ANSI color escape characters
### for job in range(0,integrationJobs):
### status = ansi_escape.sub('', check_output('grep '+integrationsJobIDs[job]+' '+'../tmp | ' + configParserClusters.get(cluster,'status'), shell=True))
### if status == configParserClusters.get(cluster,'statusQueued'):
### queuedIntegrationJobs += 1
### elif status == configParserClusters.get(cluster,'statusRunning'):
### runningIntegrationJobs += 1
### os.remove('../tmp')
# generate output
sys.stdout.write('\r\033[Kwaiting for completion of all integration jobs ({}/{} jobs completed)'.format(finishedIntegrationJobs, integrationJobs))
for i in range(iCount % 5): sys.stdout.write('.')
sys.stdout.flush()
time.sleep(int(1))
iCount += 1
print('\n > done\n')
f_run_log.write(datetime.datetime.now().isoformat(' ')+': herwig-parallel-read: completed all integration jobs\n')
f_run_log.flush()
# merge grids
command = configParser.get('tools','mergeGrids')+' '+generator+('' if setupfile=='' else ' --setupfile='+setupfile_title)
print("merging grids: {}".format(command))
output = check_output(command, shell=True)
print(" > {}\n".format('done' if output == '' else output))
f_run_log.write(datetime.datetime.now().isoformat(' ')+': herwig-parallel-read: merged grids\n')
f_run_log.close()
### ------------------------------------------
### remove '^C' outpt when exiting with Ctrl+C
### ------------------------------------------
def exit():
sys.stderr.write("\r\033[K")
sys.stderr.write("Exiting after keyboard interrupt...\n\n")
+ sys.stderr.write("! Any pending build/integrate jobs will continue to run.\n")
+ sys.stderr.write("! To terminate them please use 'herwig-parallel-abort'.\n\n")
sys.exit(1)
### -----------------
### call main program
### -----------------
if __name__ == '__main__':
main()
diff --git a/Contrib/Herwig-Parallel/source/herwig-parallel-run b/Contrib/Herwig-Parallel/source/herwig-parallel-run
--- a/Contrib/Herwig-Parallel/source/herwig-parallel-run
+++ b/Contrib/Herwig-Parallel/source/herwig-parallel-run
@@ -1,312 +1,314 @@
#! /usr/bin/env python
## --------------------
## Herwig-Parallel
## --------------------
## Author: Daniel Rauch
## Date: 12 Mar 2015
## --------------------
import sys
import os
import shutil
import signal
import time
import datetime
from subprocess import call
from subprocess import check_output
from subprocess import Popen
from ConfigParser import SafeConfigParser
from optparse import OptionParser
from hwp import checkConfig
from hwp import addToIndex
### ------------
### catch Ctrl+C
### ------------
signal.signal(signal.SIGINT, lambda x,y: exit())
### ------------
### main program
### ------------
def main():
# load Herwig-Parallel configuration file
configFileName = os.path.dirname(os.path.realpath(sys.argv[0])) + "/../config/herwig-parallel.conf"
configParser = SafeConfigParser()
configParser.read(configFileName)
# load cluster configuration file
configFileNameClusters = os.path.dirname(os.path.realpath(sys.argv[0])) + "/../config/clusters.conf"
configParserClusters = SafeConfigParser()
configParserClusters.read(configFileNameClusters)
# load queue configuration file
configFileNameQueues = os.path.dirname(os.path.realpath(sys.argv[0])) + "/../config/queues.conf"
configParserQueues = SafeConfigParser()
configParserQueues.read(configFileNameQueues)
# sanity checks for cluster and queue configuration
queues = checkConfig(configParserClusters,configParserQueues)
# set defaults
default_settings = ['runscript', 'runqueue','runjobs','events','seedmode', 'seed']
default_variables = ['herwig-parallel-run.sh', queues[0],'1', '1k', 'ascending','1']
for i in range(len(default_settings)):
try:
default_variables[i] = configParser.get('defaults',default_settings[i])
except:
pass
# setup command line options & parameters
optionParser = OptionParser(usage="%prog [options] runname")
optionParser.add_option("-e", "--events", dest="events", default=default_variables[3], help="number of events per job. The suffixes k/m/g may be used to indicate factors of thousands, millions and billions. [default: %default]")
optionParser.add_option("-j", "--jobs", dest="jobs", default=default_variables[2], help="number of parallel runs [default: %default]")
optionParser.add_option("-q", "--queue", dest="queue", default=default_variables[1], help="local, "+repr(queues).replace('[','').replace(']','').replace("'",'')+" [default: %default]")
optionParser.add_option("-r", "--runscript", dest="runscript", default=default_variables[0], help="file name of script that runs Herwig++ [default: %default]")
optionParser.add_option("-d", "--defaultscripts", action="store_true", dest="defaultscripts", default=False, help="use the default run script from the <Herwig-Parallel>-folder [default: %default]")
optionParser.add_option("--seed-mode", dest="seed_mode", default=default_variables[4], help="set what random number seeds are used for the runs, possible values are 'ascending' and 'file' [default: %default]")
optionParser.add_option("--seed", dest="seed", default=default_variables[5], help="first seed for seed mode 'ascending' or name of seed file for seed mode 'file' [default: %default]")
optionParser.add_option("-m", "--monitor", action="store_true", dest="monitoring", default=False, help="automatically start run monitoring after submission of all jobs [default: do not start monitoring]")
opts, args = optionParser.parse_args()
# sanity checks for command line arguments
if len(args) <> 1:
sys.stderr.write("Please specify an unambiguous runname!\n")
sys.exit(1)
if opts.queue != 'local' and not opts.queue in queues:
sys.stderr.write("The specified queue '"+opts.queue+"' was not configured in Herwig-Parallel/config/queues.conf. Please choose a different queue or modify the configuration file!")
sys.exit(1)
if not opts.seed_mode in ['ascending','file']:
sys.stderr.write("The specified seed mode '"+opts.seed_mode+"' is not allowed. Please chose either 'ascending' or 'file' as the seed mode!\n")
sys.exit(1)
if opts.seed_mode == 'file' and not os.path.isfile(opts.seed):
sys.stderr.write("The specified seed file '"+opts.seed+"' does not exist.\n")
sys.exit(1)
cwd = os.getcwd()
path = os.path.dirname(os.path.realpath(sys.argv[0]))
run_name = args[0].strip('/')
runscript = opts.runscript
runscript_title = runscript.split('/')[-1]
if not os.path.exists(run_name):
sys.stderr.write("The specified run '"+run_name+"' does not exist.\n")
sys.exit(1)
if os.path.exists(run_name + '/1'):
sys.stderr.write("Jobs were already started for the run '"+run_name+"'.\n")
sys.stderr.write("Please use 'herwig-parallel-addjobs' to add further jobs to the run.\n")
sys.exit(1)
if not opts.defaultscripts and not os.path.isfile(runscript):
sys.stderr.write("The specified run-script does not exist!\n")
sys.exit(1)
if opts.defaultscripts:
if not os.path.isfile(path+'/../misc/'+runscript_title):
sys.stderr.write("The default run-script does not exist!\n")
sys.exit(1)
line = '==========================================='
for i in range(len(run_name)): line += '='
print(line)
print("HERWIG-PARALLEL: Starting run step for run {}".format(run_name))
print(line)
print("")
# read required information from 'run.info' file
integrateJobIDs = []
f_run_info = open(run_name+'/run.info','r')
l = 0
for line in f_run_info:
l += 1
if l == 2:
setupfile = line.replace('\n','')
setupfile_title = setupfile.split('/')[-1]
elif l == 3:
generator = line.replace('\n','')
runfile = generator+'.run'
elif l == 9: integrateJobIDs = line.replace('\n','').split()
f_run_info.close()
events = float(str(opts.events).replace('k','').replace('K','').replace('m','').replace('M','').replace('g','').replace('G',''))
power = 0
power += (str(opts.events).count('k')+str(opts.events).count('K'))*3
power += (str(opts.events).count('m')+str(opts.events).count('M'))*6
power += (str(opts.events).count('g')+str(opts.events).count('G'))*9
events = int(events*10.0**power)
seeds = []
if opts.seed_mode == 'ascending':
for s in range(int(opts.jobs)):
seeds.append(int(opts.seed)+s)
elif opts.seed_mode == 'file':
f_seeds = open(opts.seed,'r')
for line in f_seeds:
try:
seeds.append(int(line.replace('\n','')))
except:
pass
f_seeds.close()
if len(seeds) < int(opts.jobs):
sys.stderr.write("The specified seed file only contains "+str(len(seeds))+" seed"+('s' if len(seeds)>1 else '')+".\n")
sys.stderr.write("This is too few for the requested number of "+opts.jobs+" job"+('s' if int(opts.jobs)>1 else '')+".\n")
sys.exit(1)
f_run_log = open(run_name+'/run.log','a')
# checks for completion of read step
firsttry = True
print("checking if read step is completed...")
if os.path.exists(run_name+'/read'):
if not os.path.isfile(run_name+'/read/Herwig/'+generator+('' if setupfile_title=='' else '/'+setupfile_title)+'/HerwigGrids.xml'):
print("> not yet\n")
os.chdir(run_name+'/read')
iCount = 0
finishedIntegrationStep = False
while not finishedIntegrationStep:
# for each step check for the existence of the grid files as indication of the completion of the integration jobs
finishedIntegrationJobs = 0
for job in range(len(integrateJobIDs)):
if os.path.isfile('Herwig/'+generator+('' if setupfile=='' else '/'+setupfile_title)+'/integrationJob'+str(job)+'/HerwigGrids.xml'):
finishedIntegrationJobs += 1
finishedIntegrationStep = (finishedIntegrationJobs == len(integrateJobIDs))
if iCount == 0 and not finishedIntegrationStep:
print("Please consider using 'herwig-parallel-status' to check if the missing integration jobs are running.")
print("If that is not the case you can restart them with 'herwig-parallel-restart'.\n")
sys.stdout.write('\r\033[Kwaiting for completion of all integration jobs ({}/{} jobs completed)'.format(finishedIntegrationJobs, len(integrateJobIDs)))
for i in range(iCount % 5): sys.stdout.write('.')
sys.stdout.flush()
time.sleep(int(1))
iCount += 1
print('\n > done\n')
f_run_log.write(datetime.datetime.now().isoformat(' ')+': herwig-parallel-run: completed all integration jobs\n')
f_run_log.flush()
# merge grids
command = configParser.get('tools','mergeGrids')+' '+generator+('' if setupfile=='' else ' --setupfile='+setupfile_title)
print("merging grids: {}".format(command))
output = check_output(command, shell=True)
print(" > {}\n".format('done' if output == '' else output))
f_run_log.write(datetime.datetime.now().isoformat(' ')+': herwig-parallel-run: merged grids\n')
+ else:
+ print(' > done\n')
else:
sys.stderr.write("\nWARNING: Read step has not been done yet!\n")
sys.stderr.write("Please use 'herwig-parallel-read' to do the read step first.\n")
sys.stderr.write("Exiting...\n\n")
sys.exit(1)
os.chdir(cwd)
# create copy of seed file in 'in'-folder
if opts.seed_mode == 'file':
shutil.copyfile(opts.seed,run_name+'/in/'+opts.seed.split('/')[-1])
# create run directories and copy infiles and run scripts to run folders
if os.path.exists(run_name):
f_run_info = open(run_name+"/run.info","a")
f_run_info.write((cwd+'/' if not runscript.startswith('/') else '')+runscript+'\n')
f_run_info.write(opts.seed_mode+'\n')
if opts.seed_mode == 'file':
f_run_info.write(opts.seed+'\n')
else:
f_run_info.write('\n')
else:
sys.stderr.write("\nWARNING: Read step has not been done yet!\n")
sys.stderr.write("Please use 'herwig-parallel-read' to do the read step first.\n")
sys.stderr.write("Exiting...\n\n")
sys.exit(1)
# copy raw infiles to in-folder
if os.path.exists(run_name+'/in'):
if opts.defaultscripts:
shutil.copyfile(path+'/../misc/'+runscript_title, run_name+'/in/'+runscript_title)
else:
shutil.copyfile(runscript, run_name+'/in/'+runscript_title)
else:
sys.stderr.write("\nWARNING: Read step has not been done yet!\n")
sys.stderr.write("Please use 'herwig-parallel-read' to do the read step first.\n")
sys.stderr.write("Exiting...\n\n")
sys.exit(1)
if opts.queue == 'local':
runLog = []
runProc = []
for r in range(1,int(opts.jobs)+1):
os.chdir(cwd)
dir_name = run_name+"/"+str(r)
# create new directories and copy infile and runfiles there
if not os.path.exists(dir_name):
try:
os.makedirs(dir_name)
except:
print("could not create run directory {}".format(dir_name))
if setupfile_title != '': shutil.copyfile(run_name+'/read/'+setupfile_title,dir_name+'/'+setupfile_title)
os.link(run_name+'/read/'+runfile, dir_name+'/'+runfile) # create hardlink of runfile from read-folder in all job folders to save disk space
shutil.copyfile(run_name+'/in/'+runscript_title, dir_name+'/'+runscript_title)
call("chmod u+x "+dir_name+'/'+runscript_title, shell=True) # set execute permission (lost during copying)
os.makedirs(dir_name+'/Herwig')
call('cd '+dir_name+'/Herwig; ln -s ../../read/Herwig/Build', shell=True) # symlink build directory
shutil.copytree(run_name+'/read/Herwig/'+generator,dir_name+'/Herwig/'+generator) # copy run directory
if os.path.exists(run_name+'/read/Herwig/MG_tmp'):
shutil.copytree(run_name+'/read/Herwig/MG_tmp',dir_name+'/Herwig/MG_tmp')
if os.path.exists(run_name+'/read/Matchbox/MG_tmp'):
shutil.copytree(run_name+'/read/Matchbox/MG_tmp',dir_name+'/Matchbox/MG_tmp')
# start jobs
os.chdir(cwd+"/"+dir_name)
call("sed -i 's/@HOSTNAME@/hostname > parallel.hostname/' "+runscript_title, shell=True)
call("sed -i 's/@RUNFILE@/"+runfile+"/' "+runscript_title, shell=True)
call("sed -i 's/@EVENTS@/"+str(events)+"/' "+runscript_title, shell=True)
call("sed -i 's/@SEED@/"+str(seeds[r-1])+"/' "+runscript_title, shell=True)
call("sed -i 's/@SETUPFILE@/"+('' if setupfile_title=='' else '--setupfile='+setupfile_title)+"/' "+runscript_title, shell=True)
call("sed -i 's/@CLEANUP@/rm -f "+runfile+"; rm -rf Herwig; rm -rf Matchbox /' "+runscript_title, shell=True)
if opts.queue == 'local':
runLog.append(open('run.job'+str(r)+'.log','w'))
print("starting job #{}".format(r))
runProc.append(Popen(cwd+'/'+run_name+'/'+str(r)+'/'+runscript_title,shell=True,stdout=runLog[r-1],stderr=runLog[r-1],preexec_fn=os.setpgrp))
jobid = str(runProc[r-1].pid)
print(" > pid {}\n".format(jobid))
else:
command = configParserQueues.get(opts.queue, 'submit').replace('@SCRIPT@',runscript_title)
print("starting job #{}: {}".format(r,command))
try:
output = check_output(command, shell=True).strip().replace('\n',' ')
except Exception, err:
sys.stderr.write("\n--------------------------------------------------")
sys.stderr.write(err)
sys.stderr.write("--------------------------------------------------\n")
f_run_info.close()
f_run_log.close()
sys.exit(1)
print(" > {}\n".format(output))
jobid = check_output("echo '"+output+"' | "+configParserClusters.get(configParserQueues.get(opts.queue,'cluster'),'jobid'), shell=True)
f_run_info.write("job #{}: {} {} {} {}\n".format(str(r), opts.queue, jobid, str(seeds[r-1]), str(events)))
addToIndex(jobid, cwd+'/'+run_name)
f_run_log.write(datetime.datetime.now().isoformat(' ')+': herwig-parallel-run: starting run job #{} with id {}\n'.format(r, jobid))
f_run_info.close()
f_run_log.close()
# possibly start monitoring
if opts.monitoring:
os.chdir(cwd)
call(path+'/herwig-parallel-monitor '+run_name, shell=True)
### ------------------------------------------
### remove '^C' outpt when exiting with Ctrl+C
### ------------------------------------------
def exit():
sys.stderr.write("\r\033[K")
sys.stderr.write("Exiting after keyboard interrupt...\n\n")
sys.exit(1)
### -----------------
### call main program
### -----------------
if __name__ == '__main__':
main()
diff --git a/MatrixElement/Matchbox/Base/MatchboxAmplitude.cc b/MatrixElement/Matchbox/Base/MatchboxAmplitude.cc
--- a/MatrixElement/Matchbox/Base/MatchboxAmplitude.cc
+++ b/MatrixElement/Matchbox/Base/MatchboxAmplitude.cc
@@ -1,850 +1,896 @@
// -*- C++ -*-
//
// MatchboxAmplitude.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.
//
//
// This is the implementation of the non-inlined, non-templated member
// functions of the MatchboxAmplitude class.
//
#include "MatchboxAmplitude.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Command.h"
#include "ThePEG/EventRecord/Particle.h"
#include "ThePEG/Repository/UseRandom.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/SpinorHelicity.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/SU2Helper.h"
#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.h"
#include "ThePEG/Utilities/StringUtils.h"
#include "MatchboxMEBase.h"
#include <boost/numeric/ublas/io.hpp>
#include <boost/numeric/ublas/matrix_proxy.hpp>
#include <iterator>
using std::ostream_iterator;
using namespace Herwig;
MatchboxAmplitude::MatchboxAmplitude()
: Amplitude(), theCleanupAfter(20),
treeLevelHelicityPoints(0),
oneLoopHelicityPoints(0) {
}
MatchboxAmplitude::~MatchboxAmplitude() {}
void MatchboxAmplitude::persistentOutput(PersistentOStream & os) const {
os << theLastXComb << theColourBasis << theFactory
<< theCleanupAfter << treeLevelHelicityPoints << oneLoopHelicityPoints
<< theReshuffleMasses.size();
if ( !theReshuffleMasses.empty() ) {
for ( map<long,Energy>::const_iterator r = theReshuffleMasses.begin();
r != theReshuffleMasses.end(); ++r )
os << r->first << ounit(r->second,GeV);
}
}
void MatchboxAmplitude::persistentInput(PersistentIStream & is, int) {
size_t reshuffleSize;
is >> theLastXComb >> theColourBasis >> theFactory
>> theCleanupAfter >> treeLevelHelicityPoints >> oneLoopHelicityPoints
>> reshuffleSize;
theReshuffleMasses.clear();
while ( reshuffleSize > 0 ) {
long id; Energy m;
is >> id >> iunit(m,GeV);
theReshuffleMasses[id] = m;
--reshuffleSize;
}
lastMatchboxXComb(theLastXComb);
}
Ptr<MatchboxFactory>::tptr MatchboxAmplitude::factory() const {
return theFactory;
}
void MatchboxAmplitude::factory(Ptr<MatchboxFactory>::tptr f) {
theFactory = f;
}
void MatchboxAmplitude::doinit() {
Amplitude::doinit();
if ( colourBasis() ) {
colourBasis()->factory(factory());
colourBasis()->init();
}
}
void MatchboxAmplitude::doinitrun() {
Amplitude::doinitrun();
if ( colourBasis() )
colourBasis()->initrun();
}
void MatchboxAmplitude::cloneDependencies(const std::string&) {}
Ptr<MatchboxMEBase>::ptr MatchboxAmplitude::makeME(const PDVector&) const {
return new_ptr(MatchboxMEBase());
}
Selector<const ColourLines *> MatchboxAmplitude::colourGeometries(tcDiagPtr d) const {
if ( haveColourFlows() )
return colourBasis()->colourGeometries(d,lastLargeNAmplitudes());
return Selector<const ColourLines *>();
}
void MatchboxAmplitude::olpOrderFileHeader(ostream& os) const {
os << "# OLP order file created by Herwig++/Matchbox\n\n";
os << "InterfaceVersion BLHA2\n\n";
os << "Model SM\n"
<< "CorrectionType QCD\n"
<< "IRregularisation " << (isDR() ? "DRED" : "CDR") << "\n"
<< "Extra HelAvgInitial no\n"
<< "Extra ColAvgInitial no\n"
<< "Extra MCSymmetrizeFinal no\n";
os << "\n";
}
void MatchboxAmplitude::olpOrderFileProcesses(ostream& os,
const map<pair<Process,int>,int>& proc) const {
map<int,pair<Process,int> > sorted;
for ( map<pair<Process,int>,int>::const_iterator p = proc.begin();
p != proc.end(); ++p ) {
sorted[p->second] = p->first;
}
unsigned int currentOrderInAlphaS = sorted.begin()->second.first.orderInAlphaS;
unsigned int currentOrderInAlphaEW = sorted.begin()->second.first.orderInAlphaEW;
int currentType = sorted.begin()->second.second;
os << "AlphasPower " << currentOrderInAlphaS << "\n"
<< "AlphaPower " << currentOrderInAlphaEW << "\n"
<< "AmplitudeType ";
if ( currentType == ProcessType::treeME2 ) {
os << "tree\n";
} else if ( currentType == ProcessType::oneLoopInterference ) {
os << "loop\n";
} else if ( currentType == ProcessType::colourCorrelatedME2 ) {
os << "cctree\n";
} else if ( currentType == ProcessType::spinColourCorrelatedME2 ) {
os << "sctree\n";
} else if ( currentType == ProcessType::loopInducedME2 ) {
os << "loopinduced\n";
} else if ( currentType == ProcessType::spinCorrelatedME2 ) {
os << "stree\n";
} else assert(false);
for ( map<int,pair<Process,int> >::const_iterator p = sorted.begin();
p != sorted.end(); ++p ) {
if ( currentOrderInAlphaS != p->second.first.orderInAlphaS ) {
currentOrderInAlphaS = p->second.first.orderInAlphaS;
os << "AlphasPower " << currentOrderInAlphaS << "\n";
}
if ( currentOrderInAlphaEW != p->second.first.orderInAlphaEW ) {
currentOrderInAlphaEW = p->second.first.orderInAlphaEW;
os << "AlphaPower " << currentOrderInAlphaEW << "\n";
}
if ( currentType != p->second.second ) {
currentType = p->second.second;
os << "AmplitudeType ";
if ( currentType == ProcessType::treeME2 ) {
os << "tree\n";
} else if ( currentType == ProcessType::oneLoopInterference ) {
os << "loop\n";
} else if ( currentType == ProcessType::colourCorrelatedME2 ) {
os << "cctree\n";
} else if ( currentType == ProcessType::spinColourCorrelatedME2 ) {
os << "sctree\n";
} else if ( currentType == ProcessType::spinCorrelatedME2 ) {
os << "stree\n";
} else assert(false);
}
os << p->second.first.legs[0]->id() << " "
<< p->second.first.legs[1]->id() << " -> ";
for ( PDVector::const_iterator o = p->second.first.legs.begin() + 2;
o != p->second.first.legs.end(); ++o ) {
os << (**o).id() << " ";
}
os << "\n";
}
}
bool MatchboxAmplitude::startOLP(const map<pair<Process,int>,int>& procs) {
string orderFileName = factory()->buildStorage() + name() + ".OLPOrder.lh";
ofstream orderFile(orderFileName.c_str());
olpOrderFileHeader(orderFile);
olpOrderFileProcesses(orderFile,procs);
string contractFileName = factory()->buildStorage() + name() + ".OLPContract.lh";
signOLP(orderFileName, contractFileName);
// TODO check the contract file
int status = 0;
startOLP(contractFileName, status);
if ( status != 1 )
return false;
return true;
}
struct orderPartonData {
bool operator()(const pair<tcPDPtr,int>& a,
const pair<tcPDPtr,int>& b) const {
if ( a.first == b.first )
return a.second < b.second;
int acolour = a.first->iColour();
int bcolour = b.first->iColour();
if ( abs(acolour) != abs(bcolour) )
return abs(acolour) < abs(bcolour);
if ( a.first->iSpin() != b.first->iSpin() )
return a.first->iSpin() < b.first->iSpin();
int acharge = a.first->iCharge();
int bcharge = b.first->iCharge();
if ( abs(acharge) != abs(bcharge) )
return abs(acharge) < abs(bcharge);
if ( abs(a.first->id()) != abs(b.first->id()) )
return abs(a.first->id()) < abs(b.first->id());
return a.first->id() > b.first->id();
}
};
void MatchboxAmplitude::setXComb(tStdXCombPtr xc) {
theLastXComb = xc;
lastMatchboxXComb(xc);
fillCrossingMap();
if ( treeAmplitudes() || oneLoopAmplitudes() )
for ( size_t k = 0 ; k < meMomenta().size(); ++k )
amplitudeMomenta()[k] = amplitudeMomentum(k);
}
void MatchboxAmplitude::fillCrossingMap(size_t shift) {
if ( !amplitudePartonData().empty() )
return;
double csign = 1.;
set<pair<tcPDPtr,int>,orderPartonData > processLegs;
for ( unsigned int l = 0; l < mePartonData().size(); ++l ) {
if ( l > 1 )
processLegs.insert(make_pair(mePartonData()[l],l));
else {
if ( mePartonData()[l]->CC() ) {
processLegs.insert(make_pair(mePartonData()[l]->CC(),l));
if ( mePartonData()[l]->iSpin() == PDT::Spin1Half )
csign *= -1.;
} else {
processLegs.insert(make_pair(mePartonData()[l],l));
}
}
}
crossingSign(csign);
set<pair<tcPDPtr,int> > amplitudeLegs;
crossingMap().resize(mePartonData().size());
amplitudePartonData().resize(mePartonData().size());
amplitudeMomenta().resize(mePartonData().size());
int ampCount = 0;
// process legs are already sorted, we only need to arrange for
// adjacent particles and anti-particles
while ( !processLegs.empty() ) {
set<pair<tcPDPtr,int>,orderPartonData >::iterator next
= processLegs.begin();
while ( next->first->id() < 0 ) {
if ( ++next == processLegs.end() )
break;
}
//This happens for e.g. p p-> W- gamma & p p->W- W- j j
//Still working for pp->W-H-W- e+ nue jj ???
if(next == processLegs.end()){
next = processLegs.begin();
for (;next!=processLegs.end();next++){
assert(next->first->id() < 0 );
crossingMap()[ampCount] = next->second - shift;
amplitudeLegs.insert(make_pair(next->first,ampCount));
++ampCount;
processLegs.erase(next);
}
break;
}
crossingMap()[ampCount] = next->second - shift;
amplitudeLegs.insert(make_pair(next->first,ampCount));
tcPDPtr check = next->first;
processLegs.erase(next);
++ampCount;
if ( check->CC() ) {
set<pair<tcPDPtr,int>,orderPartonData>::iterator checkcc
= processLegs.end();
for ( set<pair<tcPDPtr,int>,orderPartonData>::iterator c = processLegs.begin();
c != processLegs.end(); ++c ) {
if ( c->first == check->CC() ) {
checkcc = c; break;
}
}
if ( checkcc == processLegs.end() )
for ( set<pair<tcPDPtr,int>,orderPartonData>::iterator c = processLegs.begin();
c != processLegs.end(); ++c ) {
if ( !SU2Helper::SU2CC(check) )
continue;
if ( c->first == SU2Helper::SU2CC(check)->CC() ) {
checkcc = c; break;
}
}
if ( checkcc == processLegs.end() ) {
int f = SU2Helper::family(check);
for ( int i = 1 - f; i < 5 - f; i++ ) {
bool gotone = false;
for ( set<pair<tcPDPtr,int>,orderPartonData>::iterator c = processLegs.begin();
c != processLegs.end(); ++c ) {
if ( !SU2Helper::SU2CC(check,i) )
continue;
if ( c->first == SU2Helper::SU2CC(check,i)->CC() ) {
checkcc = c; gotone = true; break;
}
}
if ( gotone )
break;
}
}
// default to just pick the next available anti-particle
if ( processLegs.empty() ) break;
if ( checkcc == processLegs.end() ) {
checkcc = processLegs.begin();
while ( checkcc->first->id() > 0 )
if ( ++checkcc == processLegs.end() )
break;
}
// if still not there, use whatever is available at the end
if ( checkcc == processLegs.end() )
checkcc = processLegs.begin();
crossingMap()[ampCount] = checkcc->second - shift;
amplitudeLegs.insert(make_pair(checkcc->first,ampCount));
processLegs.erase(checkcc);
++ampCount;
}
}
for ( set<pair<tcPDPtr,int> >::const_iterator l = amplitudeLegs.begin();
l != amplitudeLegs.end(); ++l )
amplitudePartonData()[l->second] = l->first;
if ( colourBasis() ) {
assert(colourBasis()->indexMap().find(mePartonData()) !=
colourBasis()->indexMap().end());
const map<size_t,size_t> colourCross =
colourBasis()->indexMap().find(mePartonData())->second;
for ( size_t k = 0; k < crossingMap().size(); ++k ) {
if ( colourCross.find(crossingMap()[k]) !=
colourCross.end() ) {
size_t ccross = colourCross.find(crossingMap()[k])->second;
amplitudeToColourMap()[k] = ccross;
colourToAmplitudeMap()[ccross] = k;
}
}
}
}
const string& MatchboxAmplitude::colourOrderingString(size_t id) const {
static string empty = "";
if ( !colourBasis() ) {
return empty;
}
return colourBasis()->orderingString(mePartonData(),colourToAmplitudeMap(),id);
}
const set<vector<size_t> >& MatchboxAmplitude::colourOrdering(size_t id) const {
static set<vector<size_t> > empty;
if ( !colourBasis() ) {
return empty;
}
return colourBasis()->ordering(mePartonData(),colourToAmplitudeMap(),id);
}
Lorentz5Momentum MatchboxAmplitude::amplitudeMomentum(int i) const {
int iCrossed = crossingMap()[i];
Lorentz5Momentum res = meMomenta()[iCrossed];
if ( iCrossed < 2 )
res = -res;
res.setMass(meMomenta()[iCrossed].mass());
Energy2 rho = res.t()*res.t() - res.mass2();
res.setRho(sqrt(abs(rho)));
return res;
}
set<vector<int> > MatchboxAmplitude::generateHelicities() const {
set<vector<int> > res;
vector<int> current(amplitudePartonData().size());
doGenerateHelicities(res,current,0);
return res;
}
void MatchboxAmplitude::doGenerateHelicities(set<vector<int> >& res,
vector<int>& current,
size_t pos) const {
if ( pos == amplitudePartonData().size() ) {
res.insert(current);
return;
}
if ( amplitudePartonData()[pos]->iSpin() == PDT::Spin0 ) {
current[pos] = 0;
doGenerateHelicities(res,current,pos+1);
} else if ( amplitudePartonData()[pos]->iSpin() == PDT::Spin1Half ) {
current[pos] = 1;
doGenerateHelicities(res,current,pos+1);
current[pos] = -1;
doGenerateHelicities(res,current,pos+1);
}else if (amplitudePartonData()[pos]->iSpin() == PDT::Spin1 ) {
if (amplitudePartonData()[pos]->mass() != ZERO){
current[pos] = 0;
doGenerateHelicities(res,current,pos+1);
}
current[pos] = 1;
doGenerateHelicities(res,current,pos+1);
current[pos] = -1;
doGenerateHelicities(res,current,pos+1);
}
}
vector<unsigned int> MatchboxAmplitude::physicalHelicities(const vector<int>&) const {
throw Exception()
<< "The amplitude '" << name() << "' does not support the spin correlation algorithm"
<< Exception::abortnow;
static vector<unsigned int> dummy;
return dummy;
}
void MatchboxAmplitude::prepareAmplitudes(Ptr<MatchboxMEBase>::tcptr) {
if ( !calculateTreeAmplitudes() )
return;
bool initialized =
!lastAmplitudes().empty() && treeLevelHelicityPoints > theCleanupAfter;
if ( !initialized ) {
treeLevelHelicityPoints++;
map<vector<int>,CVector> all;
map<vector<int>,CVector> allLargeN;
set<vector<int> > helicities = generateHelicities();
for ( set<vector<int> >::const_iterator h = helicities.begin();
h != helicities.end(); ++h ) {
all.insert(make_pair(*h,CVector(colourBasisDim())));
allLargeN.insert(make_pair(*h,CVector(colourBasisDim())));
}
AmplitudeIterator amp = all.begin();
AmplitudeIterator lamp = allLargeN.begin();
for ( ; amp != all.end(); ++amp, ++lamp ) {
for ( size_t k = 0; k < colourBasisDim(); ++k ){
amp->second(k) = evaluate(k,amp->first,lamp->second(k));
if ( amp->second(k) != Complex(0.0) ) {
if ( lastAmplitudes().find(amp->first)!=lastAmplitudes().end() ) {
lastAmplitudes().find(amp->first)->second = amp->second;
lastLargeNAmplitudes().find(lamp->first)->second = lamp->second;
} else {
lastAmplitudes().insert(*amp);
lastLargeNAmplitudes().insert(*lamp);
}
} else if ( lastAmplitudes().find(amp->first)!=lastAmplitudes().end() ){
lastAmplitudes().find(amp->first)->second = amp->second;
lastLargeNAmplitudes().find(lamp->first)->second = lamp->second;
}
}
}
} else {
AmplitudeIterator amp = lastAmplitudes().begin();
AmplitudeIterator lamp = lastLargeNAmplitudes().begin();
for ( ;amp != lastAmplitudes().end(); ++amp, ++lamp ) {
for ( size_t k = 0; k < colourBasisDim(); ++k ){
amp->second(k) = evaluate(k,amp->first,lamp->second(k));
}
}
}
haveTreeAmplitudes();
}
void MatchboxAmplitude::prepareOneLoopAmplitudes(Ptr<MatchboxMEBase>::tcptr) {
if ( !calculateOneLoopAmplitudes() )
return;
bool initialized =
!lastOneLoopAmplitudes().empty() && oneLoopHelicityPoints > theCleanupAfter;
if ( !initialized ) {
oneLoopHelicityPoints++;
map<vector<int>,CVector> all;
set<vector<int> > helicities = generateHelicities();
for ( set<vector<int> >::const_iterator h = helicities.begin();
h != helicities.end(); ++h ) {
all.insert(make_pair(*h,CVector(colourBasisDim())));
}
AmplitudeIterator amp = all.begin();
for ( ; amp != all.end(); ++amp ) {
for ( size_t k = 0; k < colourBasisDim(); ++k ){
amp->second(k) = evaluateOneLoop(k,amp->first);
if ( amp->second(k) != Complex(0.0) ) {
if ( lastOneLoopAmplitudes().find(amp->first)!=lastOneLoopAmplitudes().end() ) {
lastOneLoopAmplitudes().find(amp->first)->second = amp->second;
} else{
lastOneLoopAmplitudes().insert(*amp);
}
} else if ( lastOneLoopAmplitudes().find(amp->first)!=lastOneLoopAmplitudes().end() ){
lastOneLoopAmplitudes().find(amp->first)->second = amp->second;
}
}
}
} else {
AmplitudeIterator amp = lastOneLoopAmplitudes().begin();
for ( ;amp != lastOneLoopAmplitudes().end(); ++amp ) {
for ( size_t k = 0; k < colourBasisDim(); ++k ){
amp->second(k) = evaluateOneLoop(k,amp->first);
}
}
}
haveOneLoopAmplitudes();
}
Complex MatchboxAmplitude::value(const tcPDVector&,
const vector<Lorentz5Momentum>&,
const vector<int>&) {
assert(false && "ThePEG::Amplitude interface is not sufficient at the moment.");
throw Exception() << "ThePEG::Amplitude interface is not sufficient at the moment."
<< Exception::abortnow;
return 0.;
}
double MatchboxAmplitude::me2() const {
if ( !calculateTreeME2() )
return lastTreeME2();
lastTreeME2(colourBasis()->me2(mePartonData(),lastAmplitudes()));
return lastTreeME2();
}
double MatchboxAmplitude::largeNME2(Ptr<ColourBasis>::tptr largeNBasis) const {
if ( !calculateLargeNME2() )
return lastLargeNME2();
double res = largeNBasis->me2(mePartonData(),lastLargeNAmplitudes());
lastLargeNME2(res);
return res;
}
double MatchboxAmplitude::oneLoopInterference() const {
if ( !calculateOneLoopInterference() )
return lastOneLoopInterference();
lastOneLoopInterference(colourBasis()->interference(mePartonData(),
lastOneLoopAmplitudes(),lastAmplitudes()));
return lastOneLoopInterference();
}
double MatchboxAmplitude::colourCorrelatedME2(pair<int,int> ij) 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 = (sqr(Nc)-1.)/(2.*Nc);
} else assert(false);
if ( !calculateColourCorrelator(ij) )
return lastColourCorrelator(ij)/cfac;
double res =
colourBasis()->colourCorrelatedME2(ij,mePartonData(),lastAmplitudes());
lastColourCorrelator(ij,res);
return res/cfac;
}
double MatchboxAmplitude::largeNColourCorrelatedME2(pair<int,int> ij,
Ptr<ColourBasis>::tptr largeNBasis) 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) )
return lastLargeNColourCorrelator(ij)/cfac;
double res =
largeNBasis->colourCorrelatedME2(ij,mePartonData(),lastLargeNAmplitudes());
lastLargeNColourCorrelator(ij,res);
return res/cfac;
}
// compare int vectors modulo certain element
// which needs to differe between the two
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;
}
LorentzVector<Complex> MatchboxAmplitude::plusPolarization(const Lorentz5Momentum& p,
const Lorentz5Momentum& n,
int) const {
using namespace SpinorHelicity;
LorentzVector<complex<Energy> > num =
PlusSpinorCurrent(PlusConjugateSpinor(n),MinusSpinor(p)).eval();
complex<Energy> den =
sqrt(2.)*PlusSpinorProduct(PlusConjugateSpinor(n),PlusSpinor(p)).eval();
LorentzVector<Complex> polarization(num.x()/den,num.y()/den,num.z()/den,num.t()/den);
return polarization;
}
double MatchboxAmplitude::spinColourCorrelatedME2(pair<int,int> ij,
const SpinCorrelationTensor& c) const {
Lorentz5Momentum p = meMomenta()[ij.first];
Lorentz5Momentum n = meMomenta()[ij.second];
LorentzVector<Complex> polarization = plusPolarization(p,n,ij.first);
Complex pFactor = (polarization*c.momentum())/sqrt(abs(c.scale()));
double avg =
colourCorrelatedME2(ij)*(-c.diagonal()+ (c.scale() > ZERO ? 1. : -1.)*norm(pFactor));
int iCrossed = -1;
for ( unsigned int k = 0; k < crossingMap().size(); ++k )
if ( crossingMap()[k] == ij.first ) {
iCrossed = k;
break;
}
assert(iCrossed >= 0);
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;
}
double MatchboxAmplitude::spinCorrelatedME2(pair<int,int> ij,
const SpinCorrelationTensor& c) const {
Lorentz5Momentum p = meMomenta()[ij.first];
Lorentz5Momentum n = meMomenta()[ij.second];
LorentzVector<Complex> polarization = plusPolarization(p,n,ij.first);
Complex pFactor = (polarization*c.momentum())/sqrt(abs(c.scale()));
double avg =
me2()*(-c.diagonal()+ (c.scale() > ZERO ? 1. : -1.)*norm(pFactor));
int iCrossed = -1;
for ( unsigned int k = 0; k < crossingMap().size(); ++k )
if ( crossingMap()[k] == ij.first ) {
iCrossed = k;
break;
}
assert(iCrossed >= 0);
Complex csCorr = 0.0;
if ( calculateSpinCorrelator(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()->interference(mePartonData(),a->second,b->second);
}
lastSpinCorrelator(ij,csCorr);
} else {
csCorr = lastSpinCorrelator(ij);
}
double corr =
2.*real(csCorr*sqr(pFactor));
return
avg + (c.scale() > ZERO ? 1. : -1.)*corr;
}
+void MatchboxAmplitude::checkReshuffling(Ptr<MatchboxPhasespace>::tptr ps) {
+ set<long> noReshuffle;
+ for ( map<long,Energy>::const_iterator m = reshuffleMasses().begin();
+ m != reshuffleMasses().end(); ++m ) {
+ tcPDPtr data = getParticleData(m->first);
+ assert(data);
+ bool needReshuffle = m->second != data->mass();
+ needReshuffle |=
+ (data->width() != ZERO || data->massGenerator()) &&
+ ps->useMassGenerators();
+ if ( !needReshuffle )
+ noReshuffle.insert(m->first);
+ }
+ for ( set<long>::const_iterator rm = noReshuffle.begin();
+ rm != noReshuffle.end(); ++rm )
+ theReshuffleMasses.erase(*rm);
+}
+
string MatchboxAmplitude::doReshuffle(string in) {
in = StringUtils::stripws(in);
if ( in.empty() )
throw Exception() << "expecting PDG id and mass value"
<< Exception::abortnow;
istringstream ins(in);
long id;
ins >> id;
if ( ins.eof() )
throw Exception() << "expecting PDG id and mass value"
<< Exception::abortnow;
Energy m;
ins >> iunit(m,GeV);
theReshuffleMasses[id] = m;
return "";
}
string MatchboxAmplitude::doMassless(string in) {
in = StringUtils::stripws(in);
if ( in.empty() )
throw Exception() << "expecting PDG id"
<< Exception::abortnow;
istringstream ins(in);
long id;
ins >> id;
theReshuffleMasses[id] = ZERO;
return "";
}
+string MatchboxAmplitude::doOnShell(string in) {
+ in = StringUtils::stripws(in);
+ if ( in.empty() )
+ throw Exception() << "expecting PDG id"
+ << Exception::abortnow;
+ istringstream ins(in);
+ long id;
+ ins >> id;
+ tcPDPtr data = getParticleData(id);
+ assert(data);
+ theReshuffleMasses[id] = data->mass();
+ return "";
+}
+
+string MatchboxAmplitude::doClearReshuffling(string) {
+ theReshuffleMasses.clear();
+ return "";
+}
void MatchboxAmplitude::Init() {
static ClassDocumentation<MatchboxAmplitude> documentation
("MatchboxAmplitude is the base class for amplitude "
"implementations inside Matchbox.");
static Reference<MatchboxAmplitude,ColourBasis> interfaceColourBasis
("ColourBasis",
"Set the colour basis implementation.",
&MatchboxAmplitude::theColourBasis, false, false, true, true, false);
static Parameter<MatchboxAmplitude,int> interfaceCleanupAfter
("CleanupAfter",
"The number of points after which helicity combinations are cleaned up.",
&MatchboxAmplitude::theCleanupAfter, 20, 1, 0,
false, false, Interface::lowerlim);
static Command<MatchboxAmplitude> interfaceReshuffle
("Reshuffle",
"Reshuffle the mass for the given PDG id to a different mass shell for amplitude evaluation.",
&MatchboxAmplitude::doReshuffle, false);
static Command<MatchboxAmplitude> interfaceMassless
("Massless",
"Reshuffle the mass for the given PDG id to be massless for amplitude evaluation.",
&MatchboxAmplitude::doMassless, false);
+ static Command<MatchboxAmplitude> interfaceOnShell
+ ("OnShell",
+ "Reshuffle the mass for the given PDG id to be the on-shell mass for amplitude evaluation.",
+ &MatchboxAmplitude::doOnShell, false);
+
+ static Command<MatchboxAmplitude> interfaceClearReshuffling
+ ("ClearReshuffling",
+ "Do not perform any reshuffling.",
+ &MatchboxAmplitude::doClearReshuffling, 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).
DescribeAbstractClass<MatchboxAmplitude,Amplitude>
describeMatchboxAmplitude("Herwig::MatchboxAmplitude", "Herwig.so");
diff --git a/MatrixElement/Matchbox/Base/MatchboxAmplitude.h b/MatrixElement/Matchbox/Base/MatchboxAmplitude.h
--- a/MatrixElement/Matchbox/Base/MatchboxAmplitude.h
+++ b/MatrixElement/Matchbox/Base/MatchboxAmplitude.h
@@ -1,673 +1,689 @@
// -*- C++ -*-
//
// MatchboxAmplitude.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_MatchboxAmplitude_H
#define HERWIG_MatchboxAmplitude_H
//
// This is the declaration of the MatchboxAmplitude class.
//
#include "ThePEG/MatrixElement/Amplitude.h"
#include "ThePEG/Handlers/LastXCombInfo.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/ColourBasis.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/SpinCorrelationTensor.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/LastMatchboxXCombInfo.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/MatchboxXComb.h"
+#include "Herwig++/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h"
#include "Herwig++/MatrixElement/Matchbox/Base/MatchboxMEBase.fh"
#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.fh"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief Process information with coupling order
*/
struct Process {
PDVector legs;
unsigned int orderInAlphaS;
unsigned int orderInAlphaEW;
Process()
: orderInAlphaS(0), orderInAlphaEW(0) {}
Process(const PDVector& p,
unsigned int oas,
unsigned int oae)
: legs(p), orderInAlphaS(oas), orderInAlphaEW(oae) {}
bool operator==(const Process& other) const {
return
legs == other.legs &&
orderInAlphaS == other.orderInAlphaS &&
orderInAlphaEW == other.orderInAlphaEW;
}
bool operator<(const Process& other) const {
if ( orderInAlphaS != other.orderInAlphaS )
return orderInAlphaS < other.orderInAlphaS;
if ( orderInAlphaEW != other.orderInAlphaEW )
return orderInAlphaEW < other.orderInAlphaEW;
return legs < other.legs;
}
void persistentOutput(PersistentOStream & os) const {
os << legs << orderInAlphaS << orderInAlphaEW;
}
void persistentInput(PersistentIStream & is) {
is >> legs >> orderInAlphaS >> orderInAlphaEW;
}
};
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief Enumerate the type of calculation required
*/
namespace ProcessType {
enum Types {
treeME2 = 0,
colourCorrelatedME2,
spinColourCorrelatedME2,
oneLoopInterference,
loopInducedME2,
spinCorrelatedME2
};
}
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief MatchboxAmplitude is the base class for amplitude
* implementations inside Matchbox.
*
* @see \ref MatchboxAmplitudeInterfaces "The interfaces"
* defined for MatchboxAmplitude.
*/
class MatchboxAmplitude:
public Amplitude,
public LastXCombInfo<StandardXComb>,
public LastMatchboxXCombInfo {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
MatchboxAmplitude();
/**
* The destructor.
*/
virtual ~MatchboxAmplitude();
//@}
public:
/**
* Return the amplitude. Needs to be implemented from
* ThePEG::Amplitude but is actually ill-defined, as colours of the
* external particles are not specified. To this extent, this
* implementation just asserts.
*/
virtual Complex value(const tcPDVector & particles,
const vector<Lorentz5Momentum> & momenta,
const vector<int> & helicities);
/**
* Return the factory which produced this matrix element
*/
Ptr<MatchboxFactory>::tptr factory() const;
/**
* Set the factory which produced this matrix element
*/
virtual void factory(Ptr<MatchboxFactory>::tptr f);
/** @name Subprocess information */
//@{
/**
* Return true, if this amplitude can handle the given process.
*/
virtual bool canHandle(const PDVector& p,
Ptr<MatchboxFactory>::tptr,
bool) const { return canHandle(p); }
/**
* Return true, if this amplitude can handle the given process.
*/
virtual bool canHandle(const PDVector&) const { return false; }
/**
* Return the number of random numbers required to evaluate this
* amplitude at a fixed phase space point.
*/
virtual int nDimAdditional() const { return 0; }
/**
* Return a ME instance appropriate for this amplitude and the given
* subprocesses
*/
virtual Ptr<MatchboxMEBase>::ptr makeME(const PDVector&) const;
/**
* Set the (tree-level) order in \f$g_S\f$ in which this matrix
* element should be evaluated.
*/
virtual void orderInGs(unsigned int) {}
/**
* Return the (tree-level) order in \f$g_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInGs() const = 0;
/**
* Set the (tree-level) order in \f$g_{EM}\f$ in which this matrix
* element should be evaluated.
*/
virtual void orderInGem(unsigned int) {}
/**
* Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInGem() const = 0;
/**
* Return the Herwig++ StandardModel object
*/
Ptr<StandardModel>::tcptr standardModel() {
if ( !hwStandardModel() )
hwStandardModel(dynamic_ptr_cast<Ptr<StandardModel>::tcptr>(HandlerBase::standardModel()));
return hwStandardModel();
}
/**
* Return true, if this amplitude already includes averaging over
* incoming parton's quantum numbers.
*/
virtual bool hasInitialAverage() const { return false; }
/**
* Return true, if this amplitude already includes symmetry factors
* for identical outgoing particles.
*/
virtual bool hasFinalStateSymmetry() const { return false; }
/**
* Return true, if this amplitude is handled by a BLHA one-loop provider
*/
virtual bool isOLPTree() const { return false; }
/**
* Return true, if this amplitude is handled by a BLHA one-loop provider
*/
virtual bool isOLPLoop() const { return false; }
/**
* Return true, if colour and spin correlated matrix elements should
* be ordered from the OLP
*/
virtual bool needsOLPCorrelators() const { return true; }
/**
* Write the order file header
*/
virtual void olpOrderFileHeader(ostream&) const;
/**
* Write the order file process list
*/
virtual void olpOrderFileProcesses(ostream&,
const map<pair<Process,int>,int>& procs) const;
/**
* Start the one loop provider, if appropriate, giving order and
* contract files
*/
virtual void signOLP(const string&, const string&) { }
/**
* Start the one loop provider, if appropriate
*/
virtual void startOLP(const string&, int& status) { status = -1; }
/**
* Start the one loop provider, if appropriate. This default
* implementation writes an BLHA 2.0 order file and starts the OLP
*/
virtual bool startOLP(const map<pair<Process,int>,int>& procs);
/**
* Return true, if this amplitude needs to initialize an external
* code.
*/
virtual bool isExternal() const { return false; }
/**
* Initialize this amplitude
*/
virtual bool initializeExternal() { return false; }
/**
* Return a generic process id for the given process
*/
virtual int externalId(const cPDVector&) { return 0; }
/**
* Return the map with masses to be used for amplitude evaluation
*/
const map<long,Energy>& reshuffleMasses() const { return theReshuffleMasses; }
+ /**
+ * Check if reshuffling is needed at all
+ */
+ void checkReshuffling(Ptr<MatchboxPhasespace>::tptr);
+
//@}
/** @name Colour basis. */
//@{
/**
* Return the colour basis.
*/
virtual Ptr<ColourBasis>::tptr colourBasis() const { return theColourBasis; }
/**
* Return true, if the colour basis is capable of assigning colour
* flows.
*/
virtual bool haveColourFlows() const {
return colourBasis() ? colourBasis()->haveColourFlows() : false;
}
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
*/
virtual Selector<const ColourLines *> colourGeometries(tcDiagPtr diag) const;
/**
* Return an ordering identifier for the current subprocess and
* colour absis tensor index.
*/
const string& colourOrderingString(size_t id) const;
/**
* Return an ordering identifier for the current subprocess and
* colour absis tensor index.
*/
const set<vector<size_t> >& colourOrdering(size_t id) const;
//@}
/** @name Phasespace point, crossing and helicities */
//@{
/**
* Set the xcomb object.
*/
virtual void setXComb(tStdXCombPtr xc);
/**
* Return the momentum as crossed appropriate for this amplitude.
*/
Lorentz5Momentum amplitudeMomentum(int) const;
/**
* Perform a normal ordering of external legs and fill the
* crossing information as. This default implementation sorts
* lexicographically in (abs(colour)/spin/abs(charge)), putting pairs
* of particles/anti-particles where possible.
*/
virtual void fillCrossingMap(size_t shift = 0);
/**
* Generate the helicity combinations.
*/
virtual set<vector<int> > generateHelicities() const;
/**
* Return the helicity combination of the physical process in the
* conventions used by the spin correlation algorithm.
*/
virtual vector<unsigned int> physicalHelicities(const vector<int>&) const;
//@}
/** @name Tree-level amplitudes */
//@{
/**
* Calculate the tree level amplitudes for the phasespace point
* stored in lastXComb.
*/
virtual void prepareAmplitudes(Ptr<MatchboxMEBase>::tcptr);
/**
* Return the matrix element squared.
*/
virtual double me2() const;
/**
* Return the largeN matrix element squared.
*/
virtual double largeNME2(Ptr<ColourBasis>::tptr largeNBasis) const;
/**
* Return the colour correlated matrix element.
*/
virtual double colourCorrelatedME2(pair<int,int> ij) const;
/**
* Return the large-N colour correlated matrix element.
*/
virtual double largeNColourCorrelatedME2(pair<int,int> ij,
Ptr<ColourBasis>::tptr largeNBasis) const;
/**
* Return true, if this amplitude is capable of consistently filling
* the rho matrices for the spin correllations
*/
virtual bool canFillRhoMatrix() const { return false; }
/**
* Return a positive helicity polarization vector for a gluon of
* momentum p (with reference vector n) to be used when evaluating
* spin correlations.
*/
virtual LorentzVector<Complex> plusPolarization(const Lorentz5Momentum& p,
const Lorentz5Momentum& n,
int id = -1) const;
/**
* Return the colour and spin correlated matrix element.
*/
virtual double spinColourCorrelatedME2(pair<int,int> emitterSpectator,
const SpinCorrelationTensor& c) const;
/**
* Return the spin correlated matrix element.
*/
virtual double spinCorrelatedME2(pair<int,int> emitterSpectator,
const SpinCorrelationTensor& c) const;
/**
* Return true, if tree-level contributions will be evaluated at amplitude level.
*/
virtual bool treeAmplitudes() const { return true; }
/**
* Evaluate the amplitude for the given colour tensor id and
* helicity assignment
*/
virtual Complex evaluate(size_t, const vector<int>&, Complex&) { return 0.; }
//@}
/** @name One-loop amplitudes */
//@{
/**
* Return the one-loop amplitude, if applicable.
*/
virtual Ptr<MatchboxAmplitude>::tptr oneLoopAmplitude() const {
return Ptr<MatchboxAmplitude>::tptr();
}
/**
* Diasble one-loop functionality if not needed.
*/
virtual void disableOneLoop() {}
/**
* Return true, if this amplitude is capable of calculating one-loop
* (QCD) corrections.
*/
virtual bool haveOneLoop() const { return false; }
/**
* Return true, if this amplitude only provides
* one-loop (QCD) corrections.
*/
virtual bool onlyOneLoop() const { return false; }
/**
* Return true, if one-loop contributions will be evaluated at amplitude level.
*/
virtual bool oneLoopAmplitudes() const { return true; }
/**
* Return true, if one loop corrections have been calculated in
* dimensional reduction. Otherwise conventional dimensional
* regularization is assumed. Note that renormalization is always
* assumed to be MSbar.
*/
virtual bool isDR() const { return false; }
/**
* Return true, if the amplitude is DRbar renormalized, otherwise
* MSbar is assumed.
*/
virtual bool isDRbar() const { return true; }
/**
* Return true, if one loop corrections are given in the conventions
* of the integrated dipoles.
*/
virtual bool isCS() const { return false; }
/**
* Return true, if one loop corrections are given in the conventions
* of BDK.
*/
virtual bool isBDK() const { return false; }
/**
* Return true, if one loop corrections are given in the conventions
* of everything expanded.
*/
virtual bool isExpanded() const { return false; }
/**
* Return the value of the dimensional regularization
* parameter. Note that renormalization scale dependence is fully
* restored in DipoleIOperator.
*/
virtual Energy2 mu2() const { return 0.*GeV2; }
/**
* If defined, return the coefficient of the pole in epsilon^2
*/
virtual double oneLoopDoublePole() const { return 0.; }
/**
* If defined, return the coefficient of the pole in epsilon
*/
virtual double oneLoopSinglePole() const { return 0.; }
/**
* Calculate the one-loop amplitudes for the phasespace point
* stored in lastXComb, if provided.
*/
virtual void prepareOneLoopAmplitudes(Ptr<MatchboxMEBase>::tcptr);
/**
* Return the one-loop/tree interference.
*/
virtual double oneLoopInterference() const;
/**
* Evaluate the amplitude for the given colour tensor id and
* helicity assignment
*/
virtual Complex evaluateOneLoop(size_t, const vector<int>&) { return 0.; }
//@}
/** @name Caching and helpers to setup amplitude objects. */
//@{
/**
* Flush all cashes.
*/
virtual void flushCaches() {}
/**
* Clone this amplitude.
*/
Ptr<MatchboxAmplitude>::ptr cloneMe() const {
return dynamic_ptr_cast<Ptr<MatchboxAmplitude>::ptr>(clone());
}
/**
* Clone the dependencies, using a given prefix.
*/
virtual void cloneDependencies(const std::string& prefix = "");
//@}
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();
// If needed, insert declarations of virtual function defined in the
// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs).
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 factory which produced this matrix element
*/
Ptr<MatchboxFactory>::tptr theFactory;
/**
* Recursively generate helicities
*/
void doGenerateHelicities(set<vector<int> >& res,
vector<int>& current,
size_t pos) const;
/**
* The colour basis implementation to be used.
*/
Ptr<ColourBasis>::ptr theColourBasis;
/**
* The number of points after which helicity combinations wil be
* cleaned up
*/
int theCleanupAfter;
/**
* The number of points that are calculated before a certain
* helicity is excluded. Needed in pp->V
*/
int treeLevelHelicityPoints;
/**
* The number of points that are calculated before a certain
* helicity is excluded. Needed in pp->V
*/
int oneLoopHelicityPoints;
/**
* The map with masses to be used for amplitude evaluation
*/
map<long,Energy> theReshuffleMasses;
/**
* A command to fill the reshuffle mass map
*/
string doReshuffle(string);
/**
* A command to fill the reshuffle mass map
*/
string doMassless(string);
/**
+ * A command to fill the reshuffle mass map
+ */
+ string doOnShell(string);
+
+ /**
+ * Clear the reshuffling map
+ */
+ string doClearReshuffling(string);
+
+ /**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MatchboxAmplitude & operator=(const MatchboxAmplitude &);
};
inline PersistentOStream& operator<<(PersistentOStream& os,
const Process& h) {
h.persistentOutput(os);
return os;
}
inline PersistentIStream& operator>>(PersistentIStream& is,
Process& h) {
h.persistentInput(is);
return is;
}
}
#endif /* HERWIG_MatchboxAmplitude_H */
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,1702 +1,1689 @@
// -*- 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++/MatrixElement/ProductionMatrixElement.h"
#include "Herwig++/MatrixElement/HardVertex.h"
#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::abortnow;
}
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::abortnow;
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().mass() == ZERO);
} 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::abortnow;
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() ) {
- size_t nout = diagrams().front()->partons().size()-2;
- int n = phasespace()->nDim(nout);
- if ( phasespace()->useMassGenerators() ) {
- for ( cPDVector::const_iterator pd =
- diagrams().front()->partons().begin();
- pd != diagrams().front()->partons().end(); ++pd ) {
- if ( processData()->massGenerator(*pd) ||
- (**pd).width() != ZERO ) {
- ++n;
- }
- }
- }
- return n;
- }
+ if ( phasespace() )
+ return phasespace()->nDim(diagrams().front()->partons());
throw Exception()
<< "MatchboxMEBase::nDim() expects a MatchboxPhasespace object.\n"
<< "Please check your setup." << Exception::abortnow;
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);
+ 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::abortnow;
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::abortnow;
return ZERO;
}
Energy2 MatchboxMEBase::renormalizationScaleQED() const {
if ( scaleChoice() ) {
return scaleChoice()->renormalizationScaleQED();
}
return renormalizationScale();
}
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) const {
assert(lastXCombPtr()->partonBins().first->pdf());
if ( xEx < 1. && lastX1() >= xEx ) {
return
( ( 1. - lastX1() ) / ( 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())/lastX1();
}
double MatchboxMEBase::pdf2(Energy2 fscale, double xEx) const {
assert(lastXCombPtr()->partonBins().second->pdf());
if ( xEx < 1. && lastX2() >= xEx ) {
return
( ( 1. - lastX2() ) / ( 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())/lastX2();
}
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::abortnow;
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::abortnow;
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 ) {
fac *= pow(lastAlphaS()/SM().alphaS(),double(orderInAlphaS()+addAlphaS));
couplings *= pow(lastAlphaS(),double(orderInAlphaS()+addAlphaS));
}
if ( orderInAlphaEW() > 0 ) {
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() ) {
lastME2(0.0);
lastMECrossSection(ZERO);
return lastMECrossSection();
}
double xme2 = me2();
lastME2(xme2);
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() )
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::abortnow;
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) ) {
++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 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()) ) {
Ptr<SubtractionDipole>::ptr nDipole = (**d).cloneMe();
res.push_back(nDipole);
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 InitException() << "Dipole " << dname.str() << " already existing.";
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());
}
}
}
}
}
}
for ( vector<Ptr<SubtractionDipole>::ptr>::iterator d = res.begin();
d != res.end(); ++d )
(**d).partnerDipoles(res);
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::abortnow;
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::abortnow;
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::abortnow;
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::abortnow;
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)
<< " me2 = " << lastME2() << "\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 InitException() << "Phasespace generator " << pname.str() << " already existing.";
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 InitException() << "Amplitude " << pname.str() << " already existing.";
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 InitException() << "Scale choice " << pname.str() << " already existing.";
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 InitException() << "Reweight " << pname.str() << " already existing.";
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 InitException() << "Insertion operator " << pname.str() << " already existing.";
*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() ) {
- size_t nout = diagrams().front()->partons().size()-2;
- xc.nDimPhasespace(phasespace()->nDim(nout));
- }
+ 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() ) {
string fname = name() + ".diagrams";
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/Base/MatchboxMEBase.h b/MatrixElement/Matchbox/Base/MatchboxMEBase.h
--- a/MatrixElement/Matchbox/Base/MatchboxMEBase.h
+++ b/MatrixElement/Matchbox/Base/MatchboxMEBase.h
@@ -1,1120 +1,1119 @@
// -*- C++ -*-
//
// MatchboxMEBase.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_MatchboxMEBase_H
#define HERWIG_MatchboxMEBase_H
//
// This is the declaration of the MatchboxMEBase class.
//
#include "ThePEG/MatrixElement/MEBase.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/SpinCorrelationTensor.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/Tree2toNGenerator.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/MatchboxScaleChoice.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/ProcessData.h"
-#include "Herwig++/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h"
#include "Herwig++/MatrixElement/Matchbox/Base/MatchboxAmplitude.h"
#include "Herwig++/MatrixElement/Matchbox/Base/MatchboxReweightBase.h"
#include "Herwig++/MatrixElement/Matchbox/Base/MatchboxMEBase.fh"
#include "Herwig++/MatrixElement/Matchbox/Dipoles/SubtractionDipole.fh"
#include "Herwig++/MatrixElement/Matchbox/InsertionOperators/MatchboxInsertionOperator.h"
#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.fh"
#include "Herwig++/MatrixElement/Matchbox/Utility/LastMatchboxXCombInfo.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/MatchboxXComb.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief MatchboxMEBase is the base class for matrix elements
* in the context of the matchbox NLO interface.
*
* @see \ref MatchboxMEBaseInterfaces "The interfaces"
* defined for MatchboxMEBase.
*/
class MatchboxMEBase:
public MEBase, public LastMatchboxXCombInfo {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
MatchboxMEBase();
/**
* The destructor.
*/
virtual ~MatchboxMEBase();
//@}
public:
/**
* Return the factory which produced this matrix element
*/
Ptr<MatchboxFactory>::tptr factory() const;
/**
* Set the factory which produced this matrix element
*/
void factory(Ptr<MatchboxFactory>::tptr f);
/** @name Subprocess and diagram information. */
//@{
/**
* Return the subprocess.
*/
const Process& subProcess() const { return theSubprocess; }
/**
* Access the subprocess.
*/
Process& subProcess() { return theSubprocess; }
/**
* Return the diagram generator.
*/
Ptr<Tree2toNGenerator>::tptr diagramGenerator() const;
/**
* Return the process data.
*/
Ptr<ProcessData>::tptr processData() const;
/**
* Return true, if this matrix element does not want to
* make use of mirroring processes; in this case all
* possible partonic subprocesses with a fixed assignment
* of incoming particles need to be provided through the diagrams
* added with the add(...) method.
*/
virtual bool noMirror () const { return true; }
/**
* Add all possible diagrams with the add() function.
*/
virtual void getDiagrams() const;
using MEBase::getDiagrams;
/**
* 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.
*/
virtual Selector<DiagramIndex> diagrams(const DiagramVector &) const;
using MEBase::diagrams;
/**
* Return a Selector with possible colour geometries for the selected
* diagram weighted by their relative probabilities.
*/
virtual Selector<const ColourLines *>
colourGeometries(tcDiagPtr diag) const;
/**
* Return true, if this amplitude is capable of consistently filling
* the rho matrices for the spin correllations
*/
virtual bool canFillRhoMatrix() const {
if ( matchboxAmplitude() )
return matchboxAmplitude()->canFillRhoMatrix();
return false;
}
/**
* construct the spin information for the interaction
*/
virtual void constructVertex(tSubProPtr) {}
/**
* construct the spin information for the interaction
*/
virtual void constructVertex(tSubProPtr sub, const ColourLines* cl);
/**
* Return the order in \f$\alpha_S\f$ in which this matrix element
* is given.
*/
virtual unsigned int orderInAlphaS() const;
using MEBase::orderInAlphaS;
/**
* Return the order in \f$\alpha_{EM}\f$ in which this matrix
* element is given. Returns 0.
*/
virtual unsigned int orderInAlphaEW() const;
using MEBase::orderInAlphaEW;
/**
* Return true, if this amplitude already includes averaging over
* incoming parton's quantum numbers.
*/
virtual bool hasInitialAverage() const {
return matchboxAmplitude() ? matchboxAmplitude()->hasInitialAverage() : false;
}
/**
* Return true, if this amplitude already includes symmetry factors
* for identical outgoing particles.
*/
virtual bool hasFinalStateSymmetry() const {
return matchboxAmplitude() ? matchboxAmplitude()->hasFinalStateSymmetry() : false;
}
/**
* Return the number of light flavours, this matrix
* element is calculated for.
*/
virtual unsigned int getNLight() const;
/**
* Return the vector that contains the PDG ids of
* the light flavours, which are contained in the
* jet particle group.
*/
virtual vector<int> getNLightJetVec() const;
/**
* Return the vector that contains the PDG ids of
* the heavy flavours, which are contained in the
* jet particle group.
*/
virtual vector<int> getNHeavyJetVec() const;
/**
* Return the vector that contains the PDG ids of
* the light flavours, which are contained in the
* proton particle group.
*/
virtual vector<int> getNLightProtonVec() const;
/**
* Return true, if this matrix element is handled by a BLHA one-loop provider
*/
virtual bool isOLPTree() const {
return matchboxAmplitude() ? matchboxAmplitude()->isOLPTree() : false;
}
/**
* Return true, if this matrix element is handled by a BLHA one-loop provider
*/
virtual bool isOLPLoop() const {
return matchboxAmplitude() ? matchboxAmplitude()->isOLPLoop() : false;
}
/**
* Return true, if colour and spin correlated matrix elements should
* be ordered from the OLP
*/
virtual bool needsOLPCorrelators() const {
return matchboxAmplitude() ? matchboxAmplitude()->needsOLPCorrelators() : true;
}
/**
* Return the process index, if this is an OLP handled matrix element
*/
const vector<int>& olpProcess() const { return theOLPProcess; }
/**
* Set the process index, if this is an OLP handled matrix element
*/
void olpProcess(int pType, int id) {
if ( theOLPProcess.empty() )
theOLPProcess.resize(5,0);
theOLPProcess[pType] = id;
}
/**
* Return true, if this is a real emission matrix element which does
* not require colour correlators.
*/
bool noCorrelations() const {
return theNoCorrelations;
}
/**
* Indicate that this is a real emission matrix element which does
* not require colour correlators.
*/
void needsNoCorrelations() {
theNoCorrelations = true;
}
/**
* Indicate that this is a virtual matrix element which does
* require colour correlators.
*/
void needsCorrelations() {
theNoCorrelations = false;
}
//@}
/** @name Phasespace generation */
//@{
/**
* Return the phase space generator to be used.
*/
Ptr<MatchboxPhasespace>::tptr phasespace() const { return thePhasespace; }
/**
* Set the phase space generator to be used.
*/
void phasespace(Ptr<MatchboxPhasespace>::ptr ps) { thePhasespace = ps; }
/**
* Set the XComb object to be used in the next call to
* generateKinematics() and dSigHatDR().
*/
virtual void setXComb(tStdXCombPtr xc);
/**
* Return true, if the XComb steering this matrix element
* should keep track of the random numbers used to generate
* the last phase space point
*/
virtual bool keepRandomNumbers() const { return true; }
/**
* Generate incoming parton momenta. This default
* implementation performs the standard mapping
* from x1,x2 -> tau,y making 1/tau flat; incoming
* parton momenta are stored in meMomenta()[0,1],
* only massless partons are supported so far;
* return the Jacobian of the mapping
*/
double generateIncomingPartons(const double* r1, const double* r2);
/**
* 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. The return value should
* be true of the generation succeeded. If so the generated momenta
* should be stored in the meMomenta() vector. Derived classes
* must call this method once internal degrees of freedom are setup
* and finally return the result of this method.
*/
virtual bool generateKinematics(const double * r);
/**
* The number of internal degreed of freedom used in the matrix
* element.
*/
virtual int nDim() const;
/**
* The number of internal degrees of freedom used in the matrix
* element for generating a Born phase space point
*/
virtual int nDimBorn() const;
/**
* Return true, if this matrix element will generate momenta for the
* incoming partons itself. The matrix element is required to store
* the incoming parton momenta in meMomenta()[0,1]. No mapping in
* tau and y is performed by the PartonExtractor object, if a
* derived class returns true here. The phase space jacobian is to
* include a factor 1/(x1 x2).
*/
virtual bool haveX1X2() const {
return
(phasespace() ? phasespace()->haveX1X2() : false) ||
diagrams().front()->partons().size() == 3;
}
/**
* Return true, if this matrix element expects
* the incoming partons in their center-of-mass system
*/
virtual bool wantCMS() const {
return
(phasespace() ? phasespace()->wantCMS() : true) &&
diagrams().front()->partons().size() != 3; }
/**
* Return the meMomenta as generated at the last
* phase space point.
*/
const vector<Lorentz5Momentum>& lastMEMomenta() const { return meMomenta(); }
/**
* Access the meMomenta.
*/
vector<Lorentz5Momentum>& lastMEMomenta() { return meMomenta(); }
//@}
/** @name Scale choices, couplings and PDFs */
//@{
/**
* Set the scale choice object
*/
void scaleChoice(Ptr<MatchboxScaleChoice>::ptr sc) { theScaleChoice = sc; }
/**
* Return the scale choice object
*/
Ptr<MatchboxScaleChoice>::tptr scaleChoice() const { return theScaleChoice; }
/**
* Set scales and alphaS
*/
void setScale() const;
/**
* Return the scale associated with the phase space point provided
* by the last call to setKinematics().
*/
virtual Energy2 scale() const { return lastScale(); }
/**
* Return the renormalization scale for the last generated phasespace point.
*/
virtual Energy2 factorizationScale() const;
/**
* Get the factorization scale factor
*/
virtual double factorizationScaleFactor() const;
/**
* Return the (QCD) renormalization scale for the last generated phasespace point.
*/
virtual Energy2 renormalizationScale() const;
/**
* Get the renormalization scale factor
*/
virtual double renormalizationScaleFactor() const;
/**
* Return the QED renormalization scale for the last generated phasespace point.
*/
virtual Energy2 renormalizationScaleQED() const;
/**
* Set veto scales on the particles at the given
* SubProcess which has been generated using this
* matrix element.
*/
virtual void setVetoScales(tSubProPtr) const;
/**
* Return true, if fixed couplings are used.
*/
bool fixedCouplings() const;
/**
* Return true, if fixed couplings are used.
*/
bool fixedQEDCouplings() const;
/**
* Return the value of \f$\alpha_S\f$ associated with the phase
* space point provided by the last call to setKinematics(). This
* versions returns SM().alphaS(scale()).
*/
virtual double alphaS() const { return lastAlphaS(); }
/**
* Return the value of \f$\alpha_EM\f$ associated with the phase
* space point provided by the last call to setKinematics(). This
* versions returns SM().alphaEM(scale()).
*/
virtual double alphaEM() const { return lastAlphaEM(); }
/**
* Return true, if this matrix element provides the PDF
* weight for the first incoming parton itself.
*/
virtual bool havePDFWeight1() const;
/**
* Return true, if this matrix element provides the PDF
* weight for the second incoming parton itself.
*/
virtual bool havePDFWeight2() const;
/**
* Set the PDF weight.
*/
void getPDFWeight(Energy2 factorizationScale = ZERO) const;
/**
* Supply the PDF weight for the first incoming parton.
*/
double pdf1(Energy2 factorizationScale = ZERO,
double xEx = 1.) const;
/**
* Supply the PDF weight for the second incoming parton.
*/
double pdf2(Energy2 factorizationScale = ZERO,
double xEx = 1.) const;
//@}
/** @name Amplitude information and matrix element evaluation */
//@{
/**
* Return the amplitude.
*/
Ptr<MatchboxAmplitude>::tptr matchboxAmplitude() const { return theAmplitude; }
/**
* Set the amplitude.
*/
void matchboxAmplitude(Ptr<MatchboxAmplitude>::ptr amp) { theAmplitude = amp; }
/**
* Return the matrix element for the kinematical configuation
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
*/
virtual double me2() const;
/**
* Return the matrix element for the kinematical configuation
* previously provided by the last call to setKinematics(), suitably
* scaled by sHat() to give a dimension-less number.
*/
virtual double largeNME2(Ptr<ColourBasis>::tptr largeNBasis) const;
/**
* Return the symmetry factor for identical final state particles.
*/
virtual double finalStateSymmetry() const;
/**
* Return the normalizing factor for the matrix element averaged
* over quantum numbers and including running couplings.
*/
double me2Norm(unsigned int addAlphaS = 0) const;
/**
* Return the matrix element squared differential in the variables
* given by the last call to generateKinematics().
*/
virtual CrossSection dSigHatDR() const;
//@}
/** @name One-loop corrections */
//@{
/**
* Return the one-loop/tree interference.
*/
virtual double oneLoopInterference() const;
/**
* Return true, if this matrix element is capable of calculating
* one-loop (QCD) corrections.
*/
virtual bool haveOneLoop() const;
/**
* Return true, if this matrix element only provides
* one-loop (QCD) corrections.
*/
virtual bool onlyOneLoop() const;
/**
* Return true, if the amplitude is DRbar renormalized, otherwise
* MSbar is assumed.
*/
virtual bool isDRbar() const;
/**
* Return true, if one loop corrections have been calculated in
* dimensional reduction. Otherwise conventional dimensional
* regularization is assumed. Note that renormalization is always
* assumed to be MSbar.
*/
virtual bool isDR() const;
/**
* Return true, if one loop corrections are given in the conventions
* of the integrated dipoles.
*/
virtual bool isCS() const;
/**
* Return true, if one loop corrections are given in the conventions
* of BDK.
*/
virtual bool isBDK() const;
/**
* Return true, if one loop corrections are given in the conventions
* of everything expanded.
*/
virtual bool isExpanded() const;
/**
* Return the value of the dimensional regularization
* parameter. Note that renormalization scale dependence is fully
* restored in DipoleIOperator.
*/
virtual Energy2 mu2() const;
/**
* If defined, return the coefficient of the pole in epsilon^2
*/
virtual double oneLoopDoublePole() const;
/**
* If defined, return the coefficient of the pole in epsilon
*/
virtual double oneLoopSinglePole() const;
/**
* Return true, if cancellationn of epsilon poles should be checked.
*/
bool checkPoles() const;
/**
* Simple histogram for accuracy checks
*/
struct AccuracyHistogram {
/**
* The lower bound
*/
double lower;
/**
* The upper bound
*/
double upper;
/**
* The bins, indexed by upper bound.
*/
map<double,double> bins;
/**
* The number of points of same sign
*/
unsigned long sameSign;
/**
* The number of points of opposite sign
*/
unsigned long oppositeSign;
/**
* The number of points being nan or inf
*/
unsigned long nans;
/**
* The overflow
*/
unsigned long overflow;
/**
* The underflow
*/
unsigned long underflow;
/**
* Constructor
*/
AccuracyHistogram(double low = -40.,
double up = 0.,
unsigned int nbins = 80);
/**
* Book two values to be checked for numerical compatibility
*/
void book(double a, double b);
/**
* Write to file.
*/
void dump(const std::string& folder, const std::string& prefix,
const cPDVector& proc) const;
/**
* Write to persistent ostream
*/
void persistentOutput(PersistentOStream&) const;
/**
* Read from persistent istream
*/
void persistentInput(PersistentIStream&);
};
/**
* Perform the check of epsilon pole cancellation.
*/
void logPoles() const;
/**
* Return the virtual corrections
*/
const vector<Ptr<MatchboxInsertionOperator>::ptr>& virtuals() const {
return theVirtuals;
}
/**
* Return the virtual corrections
*/
vector<Ptr<MatchboxInsertionOperator>::ptr>& virtuals() {
return theVirtuals;
}
/**
* Instruct this matrix element to include one-loop corrections
*/
void doOneLoop() { theOneLoop = true; }
/**
* Return true, if this matrix element includes one-loop corrections
*/
bool oneLoop() const { return theOneLoop; }
/**
* Instruct this matrix element to include one-loop corrections but
* no Born contributions
*/
void doOneLoopNoBorn() { theOneLoop = true; theOneLoopNoBorn = true; }
/**
* Return true, if this matrix element includes one-loop corrections
* but no Born contributions
*/
bool oneLoopNoBorn() const { return theOneLoopNoBorn || onlyOneLoop(); }
/**
* Instruct this matrix element to include one-loop corrections but
* no actual loop contributions
*/
void doOneLoopNoLoops() { theOneLoop = true; theOneLoopNoLoops = true; }
/**
* Return true, if this matrix element includes one-loop corrections
* but no actual loop contributions
*/
bool oneLoopNoLoops() const { return theOneLoopNoLoops; }
//@}
/** @name Dipole subtraction */
//@{
/**
* If this matrix element is considered a real
* emission matrix element, return all subtraction
* dipoles needed given a set of subtraction terms
* and underlying Born matrix elements to choose
* from.
*/
vector<Ptr<SubtractionDipole>::ptr>
getDipoles(const vector<Ptr<SubtractionDipole>::ptr>&,
const vector<Ptr<MatchboxMEBase>::ptr>&) const;
/**
* If this matrix element is considered a real emission matrix
* element, but actually neglecting a subclass of the contributing
* diagrams, return true if the given emitter-emission-spectator
* configuration should not be considered when setting up
* subtraction dipoles.
*/
virtual bool noDipole(int,int,int) const { return false; }
/**
* If this matrix element is considered an underlying Born matrix
* element in the context of a subtracted real emission, but
* actually neglecting a subclass of the contributing diagrams,
* return true if the given emitter-spectator configuration
* should not be considered when setting up subtraction dipoles.
*/
virtual bool noDipole(int,int) const { return false; }
/**
* Return the colour correlated matrix element squared with
* respect to the given two partons as appearing in mePartonData(),
* suitably scaled by sHat() to give a dimension-less number.
*/
virtual double colourCorrelatedME2(pair<int,int>) const;
/**
* Return the colour correlated matrix element squared in the
* large-N approximation with respect to the given two partons as
* appearing in mePartonData(), suitably scaled by sHat() to give a
* dimension-less number.
*/
virtual double largeNColourCorrelatedME2(pair<int,int> ij,
Ptr<ColourBasis>::tptr largeNBasis) const;
/**
* Return the colour and spin correlated matrix element squared for
* the gluon indexed by the first argument using the given
* correlation tensor.
*/
virtual double spinColourCorrelatedME2(pair<int,int> emitterSpectator,
const SpinCorrelationTensor& c) const;
/**
* Return the spin correlated matrix element squared for
* the vector boson indexed by the first argument using the given
* correlation tensor.
*/
virtual double spinCorrelatedME2(pair<int,int> emitterSpectator,
const SpinCorrelationTensor& c) const;
//@}
/** @name Caching and diagnostic information */
//@{
/**
* Inform this matrix element that a new phase space
* point is about to be generated, so all caches should
* be flushed.
*/
virtual void flushCaches();
/**
* Return true, if verbose
*/
bool verbose() const;
/**
* Return true, if verbose
*/
bool initVerbose() const;
/**
* Dump the setup to an ostream
*/
void print(ostream&) const;
/**
* Print debug information on the last event
*/
virtual void printLastEvent(ostream&) const;
/**
* Write out diagnostic information for
* generateKinematics
*/
void logGenerateKinematics(const double * r) const;
/**
* Write out diagnostic information for
* setting scales
*/
void logSetScale() const;
/**
* Write out diagnostic information for
* pdf evaluation
*/
void logPDFWeight() const;
/**
* Write out diagnostic information for
* me2 evaluation
*/
void logME2() const;
/**
* Write out diagnostic information
* for dsigdr evaluation
*/
void logDSigHatDR() const;
//@}
/** @name Reweight objects */
//@{
/**
* Insert a reweight object
*/
void addReweight(Ptr<MatchboxReweightBase>::ptr rw) { theReweights.push_back(rw); }
/**
* Return the reweights
*/
const vector<Ptr<MatchboxReweightBase>::ptr>& reweights() const { return theReweights; }
/**
* Access the reweights
*/
vector<Ptr<MatchboxReweightBase>::ptr>& reweights() { return theReweights; }
//@}
/** @name Methods used to setup MatchboxMEBase objects */
//@{
/**
* Return true if this object needs to be initialized before all
* other objects (except those for which this function also returns
* true). This default version always returns false, but subclasses
* may override it to return true.
*/
virtual bool preInitialize() const { return true; }
/**
* Clone this matrix element.
*/
Ptr<MatchboxMEBase>::ptr cloneMe() const {
return dynamic_ptr_cast<Ptr<MatchboxMEBase>::ptr>(clone());
}
/**
* Clone the dependencies, using a given prefix.
*/
void cloneDependencies(const std::string& prefix = "");
/**
* Prepare an xcomb
*/
void prepareXComb(MatchboxXCombData&) const;
/**
* For the given event generation setup return a xcomb object
* appropriate to this matrix element.
*/
virtual StdXCombPtr 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& allPBins,
tStdXCombPtr newHead = tStdXCombPtr(),
tMEPtr newME = tMEPtr());
/**
* For the given event generation setup return a dependent xcomb object
* appropriate to this matrix element.
*/
virtual StdXCombPtr makeXComb(tStdXCombPtr newHead,
const PBPair & newPartonBins,
const DiagramVector & newDiagrams,
tMEPtr newME = tMEPtr());
//@}
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. */
//@{
/**
* Initialize this object after the setup phase before saving an
* EventGenerator to disk.
* @throws InitException if object could not be initialized properly.
*/
virtual void doinit();
/**
* Initialize this object. Called in the run phase just before
* a run begins.
*/
virtual void doinitrun();
/**
* Finalize this object. Called in the run phase just after a
* run has ended. Used eg. to write out statistics.
*/
virtual void dofinish();
//@}
private:
/**
* The factory which produced this matrix element
*/
Ptr<MatchboxFactory>::tptr theFactory;
/**
* The phase space generator to be used.
*/
Ptr<MatchboxPhasespace>::ptr thePhasespace;
/**
* The amplitude to be used
*/
Ptr<MatchboxAmplitude>::ptr theAmplitude;
/**
* The scale choice object
*/
Ptr<MatchboxScaleChoice>::ptr theScaleChoice;
/**
* The virtual corrections.
*/
vector<Ptr<MatchboxInsertionOperator>::ptr> theVirtuals;
/**
* A vector of reweight objects the sum of which
* should be applied to reweight this matrix element
*/
vector<Ptr<MatchboxReweightBase>::ptr> theReweights;
private:
/**
* The subprocess to be considered.
*/
Process theSubprocess;
/**
* True, if this matrix element includes one-loop corrections
*/
bool theOneLoop;
/**
* True, if this matrix element includes one-loop corrections
* but no Born contributions
*/
bool theOneLoopNoBorn;
/**
* True, if this matrix element includes one-loop corrections
* but no actual loop contributions (e.g. finite collinear terms)
*/
bool theOneLoopNoLoops;
/**
* The process index, if this is an OLP handled matrix element
*/
vector<int> theOLPProcess;
/**
* Histograms of epsilon^2 pole cancellation
*/
mutable map<cPDVector,AccuracyHistogram> epsilonSquarePoleHistograms;
/**
* Histograms of epsilon pole cancellation
*/
mutable map<cPDVector,AccuracyHistogram> epsilonPoleHistograms;
/**
* True, if this is a real emission matrix element which does
* not require colour correlators.
*/
bool theNoCorrelations;
/**
* Flag which pdfs should be included.
*/
mutable pair<bool,bool> theHavePDFs;
/**
* True, if already checked for which PDFs to include.
*/
mutable bool checkedPDFs;
/**
* Diagnostic Diagram for TreePhaseSpace
*/
void bookMEoverDiaWeight(double x) const;
mutable map<double,double > MEoverDiaWeight;
mutable int Nevents;
/**
* Range of diagram weight verbosity
*/
mutable double theDiagramWeightVerboseDown, theDiagramWeightVerboseUp;
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MatchboxMEBase & operator=(const MatchboxMEBase &);
};
inline PersistentOStream& operator<<(PersistentOStream& os,
const MatchboxMEBase::AccuracyHistogram& h) {
h.persistentOutput(os);
return os;
}
inline PersistentIStream& operator>>(PersistentIStream& is,
MatchboxMEBase::AccuracyHistogram& h) {
h.persistentInput(is);
return is;
}
}
#endif /* HERWIG_MatchboxMEBase_H */
diff --git a/MatrixElement/Matchbox/Base/MatchboxOLPME.cc b/MatrixElement/Matchbox/Base/MatchboxOLPME.cc
--- a/MatrixElement/Matchbox/Base/MatchboxOLPME.cc
+++ b/MatrixElement/Matchbox/Base/MatchboxOLPME.cc
@@ -1,242 +1,268 @@
// -*- C++ -*-
//
// MatchboxOLPME.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 MatchboxOLPME class.
//
#include "MatchboxOLPME.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 "MatchboxMEBase.h"
#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.h"
+#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
MatchboxOLPME::MatchboxOLPME()
- : theOrderInGs(0), theOrderInGem(0) {}
+ : theOrderInGs(0), theOrderInGem(0), theSetMuToMuR(false) {}
MatchboxOLPME::~MatchboxOLPME() {}
bool MatchboxOLPME::canHandle(const PDVector& p,
Ptr<MatchboxFactory>::tptr factory,
bool) 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;
return true;
}
void MatchboxOLPME::setXComb(tStdXCombPtr xc) {
theLastXComb = xc;
lastMatchboxXComb(xc);
}
double MatchboxOLPME::me2() const {
if ( !calculateTreeME2() )
return lastTreeME2();
evalSubProcess();
return lastTreeME2();
}
double MatchboxOLPME::colourCorrelatedME2(pair<int,int> ij) 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 = (sqr(Nc)-1.)/(2.*Nc);
} else assert(false);
if ( !calculateColourCorrelator(ij) )
return lastColourCorrelator(ij)/cfac;
evalColourCorrelator(ij);
return lastColourCorrelator(ij)/cfac;
}
double MatchboxOLPME::spinColourCorrelatedME2(pair<int,int> ij,
const SpinCorrelationTensor& c) const {
Lorentz5Momentum p = meMomenta()[ij.first];
Lorentz5Momentum n = meMomenta()[ij.second];
LorentzVector<Complex> polarization = plusPolarization(p,n,ij.first);
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) )
evalSpinColourCorrelator(ij);
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;
}
double MatchboxOLPME::spinCorrelatedME2(pair<int,int> ij,
const SpinCorrelationTensor& c) const {
Lorentz5Momentum p = meMomenta()[ij.first];
Lorentz5Momentum n = meMomenta()[ij.second];
LorentzVector<Complex> polarization = plusPolarization(p,n,ij.first);
Complex pFactor = (polarization*c.momentum())/sqrt(abs(c.scale()));
double avg =
me2()*(-c.diagonal()+ (c.scale() > ZERO ? 1. : -1.)*norm(pFactor));
Complex csCorr = 0.0;
if ( calculateSpinCorrelator(ij) )
evalSpinCorrelator(ij);
csCorr = lastSpinCorrelator(ij);
double corr =
2.*real(csCorr*sqr(pFactor));
return
avg + (c.scale() > ZERO ? 1. : -1.)*corr;
}
void MatchboxOLPME::evalSpinCorrelator(pair<int,int>) const {
throw Exception()
<< "MatchboxOLPME::spinCorrelatedME2() is not implemented.\n"
<< "Please check your setup." << Exception::abortnow;
}
double MatchboxOLPME::oneLoopDoublePole() const {
if ( !calculateOneLoopPoles() )
return lastOneLoopPoles().first;
evalSubProcess();
return lastOneLoopPoles().first;
}
double MatchboxOLPME::oneLoopSinglePole() const {
if ( !calculateOneLoopPoles() )
return lastOneLoopPoles().second;
evalSubProcess();
return lastOneLoopPoles().second;
}
double MatchboxOLPME::oneLoopInterference() const {
if ( !calculateOneLoopInterference() )
return lastOneLoopInterference();
evalSubProcess();
return lastOneLoopInterference();
}
double MatchboxOLPME::largeNColourCorrelatedME2(pair<int,int>,
Ptr<ColourBasis>::tptr) const {
throw Exception() << "largeNColourCorrelatedME2 not supported by MatchboxOLPME"
<< Exception::abortnow;
return 0.;
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void MatchboxOLPME::doinit() {
if ( !didStartOLP() ) {
string contractFileName =
optionalContractFile().empty() ?
factory()->buildStorage() + name() + ".OLPContract.lh" :
optionalContractFile();
int status = -1;
startOLP(contractFileName,status);
didStartOLP()=true;
if ( status != 1 ) {
throw Exception()
<< "Failed to restart one loop provider for amplitude '"
<< name() << "'\n" << Exception::abortnow;
}
}
MatchboxAmplitude::doinit();
}
void MatchboxOLPME::doinitrun() {
if ( !didStartOLP() ) {
string contractFileName =
optionalContractFile().empty() ?
factory()->buildStorage() + name() + ".OLPContract.lh" :
optionalContractFile();
int status = -1;
startOLP(contractFileName,status);
didStartOLP()=true;
if ( status != 1 ) {
throw Exception()
<< "Failed to restart one loop provider for amplitude '"
<< name() << "'\n" << Exception::abortnow;
}
}
MatchboxAmplitude::doinitrun();
}
+
+Energy2 MatchboxOLPME::mu2() const {
+ if (theSetMuToMuR) {
+ return lastMatchboxXComb()->lastRenormalizationScale();
+ }
+ return lastSHat();
+}
+
void MatchboxOLPME::persistentOutput(PersistentOStream & os) const {
- os << theOrderInGs << theOrderInGem;
+ os << theOrderInGs << theOrderInGem << theSetMuToMuR;
}
void MatchboxOLPME::persistentInput(PersistentIStream & is, int) {
- is >> theOrderInGs >> theOrderInGem;
+ is >> theOrderInGs >> theOrderInGem >> theSetMuToMuR;
}
// *** 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<MatchboxOLPME,MatchboxAmplitude>
describeHerwigMatchboxOLPME("Herwig::MatchboxOLPME", "Herwig.so");
void MatchboxOLPME::Init() {
static ClassDocumentation<MatchboxOLPME> documentation
("MatchboxOLPME implements OLP interfaces.");
+ static Switch<MatchboxOLPME,bool> interfaceSetMuToMuR
+ ("SetMuToMuR",
+ "Switch On to set the value of the dimensional regularization parameter mu2 for this OLP"
+ "to the value of the renormalization scale muR2. Default is Off. The restoration for the "
+ "full renormalization scale dependence in the DipoleIOperator isn't needed in this case.",
+ &MatchboxOLPME::theSetMuToMuR, false, false, false);
+ static SwitchOption interfaceSetMuToMuROn
+ (interfaceSetMuToMuR,
+ "On",
+ "On",
+ true);
+ static SwitchOption interfaceSetMuToMuROff
+ (interfaceSetMuToMuR,
+ "Off",
+ "Off",
+ false);
+
}
diff --git a/MatrixElement/Matchbox/Base/MatchboxOLPME.h b/MatrixElement/Matchbox/Base/MatchboxOLPME.h
--- a/MatrixElement/Matchbox/Base/MatchboxOLPME.h
+++ b/MatrixElement/Matchbox/Base/MatchboxOLPME.h
@@ -1,300 +1,305 @@
// -*- C++ -*-
//
// MatchboxOLPME.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_MatchboxOLPME_H
#define Herwig_MatchboxOLPME_H
//
// This is the declaration of the MatchboxOLPME class.
//
#include "Herwig++/MatrixElement/Matchbox/Base/MatchboxAmplitude.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief MatchboxOLPME implements OLP interfaces.
*/
class MatchboxOLPME: public MatchboxAmplitude {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
MatchboxOLPME();
/**
* The destructor.
*/
virtual ~MatchboxOLPME();
//@}
public:
/**
* Return true, if this amplitude can handle the given process.
*/
virtual bool canHandle(const PDVector& p,
Ptr<MatchboxFactory>::tptr,
bool) const;
/**
* Set the (tree-level) order in \f$g_S\f$ in which this matrix
* element should be evaluated.
*/
virtual void orderInGs(unsigned int ogs) { theOrderInGs = ogs; }
/**
* Return the (tree-level) order in \f$g_S\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInGs() const { return theOrderInGs; }
/**
* Set the (tree-level) order in \f$g_{EM}\f$ in which this matrix
* element should be evaluated.
*/
virtual void orderInGem(unsigned int oge) { theOrderInGem = oge; }
/**
* Return the (tree-level) order in \f$g_{EM}\f$ in which this matrix
* element is given.
*/
virtual unsigned int orderInGem() const { return theOrderInGem; }
/**
* Return true, if this amplitude is handled by a BLHA one-loop provider
*/
virtual bool isOLPTree() const { return true; }
/**
* Return true, if this amplitude is handled by a BLHA one-loop provider
*/
virtual bool isOLPLoop() const { return true; }
/**
* Return true, if the colour basis is capable of assigning colour
* flows.
*/
virtual bool haveColourFlows() const { return false; }
/**
* Set the xcomb object.
*/
virtual void setXComb(tStdXCombPtr xc);
/**
* Calculate the tree level amplitudes for the phasespace point
* stored in lastXComb.
*/
virtual void prepareAmplitudes(Ptr<MatchboxMEBase>::tcptr) {}
/**
* Return the matrix element squared.
*/
virtual double me2() const;
/**
* Return the colour correlated matrix element.
*/
virtual double colourCorrelatedME2(pair<int,int> ij) const;
/**
* Return the large-N colour correlated matrix element.
*/
virtual double largeNColourCorrelatedME2(pair<int,int>,
Ptr<ColourBasis>::tptr) const;
/**
* Return the colour and spin correlated matrix element.
*/
virtual double spinColourCorrelatedME2(pair<int,int> ij,
const SpinCorrelationTensor& c) const;
/**
* Return the spin correlated matrix element.
*/
virtual double spinCorrelatedME2(pair<int,int> ij,
const SpinCorrelationTensor& c) const;
/**
* Return true, if tree-level contributions will be evaluated at amplitude level.
*/
virtual bool treeAmplitudes() const { return false; }
/**
* Return true, if this amplitude is capable of calculating one-loop
* (QCD) corrections.
*/
virtual bool haveOneLoop() const { return true; }
/**
* Return true, if this amplitude only provides
* one-loop (QCD) corrections.
*/
virtual bool onlyOneLoop() const { return false; }
/**
* Return true, if one-loop contributions will be evaluated at amplitude level.
*/
virtual bool oneLoopAmplitudes() const { return false; }
/**
* Return true, if one loop corrections are given in the conventions
* of everything expanded.
*/
virtual bool isExpanded() const { return true; }
/**
* Return the value of the dimensional regularization
* parameter. Note that renormalization scale dependence is fully
* restored in DipoleIOperator.
*/
- virtual Energy2 mu2() const { return lastSHat(); }
+ virtual Energy2 mu2() const;
/**
* If defined, return the coefficient of the pole in epsilon^2
*/
virtual double oneLoopDoublePole() const;
/**
* If defined, return the coefficient of the pole in epsilon
*/
virtual double oneLoopSinglePole() const;
/**
* Calculate the one-loop amplitudes for the phasespace point
* stored in lastXComb, if provided.
*/
virtual void prepareOneLoopAmplitudes(Ptr<MatchboxMEBase>::tcptr) {}
/**
* Return the one-loop/tree interference.
*/
virtual double oneLoopInterference() const;
public:
/**
* Call OLP_EvalSubProcess and fill in the results
*/
virtual void evalSubProcess() const = 0;
/**
* Fill in results for the given colour correlator
*/
virtual void evalColourCorrelator(pair<int,int> ij) const = 0;
/**
* Fill in results for the given colour/spin correlator
*/
virtual void evalSpinColourCorrelator(pair<int,int> ij) const = 0;
/**
* Fill in results for the given spin correlator; may not be supported
*/
virtual void evalSpinCorrelator(pair<int,int> ij) 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();
// If needed, insert declarations of virtual function defined in the
// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs).
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();
//@}
/**
* Set an optional contract file name to be used
*/
static string& optionalContractFile() {
static string s = "";
return s;
}
/**
* Indicate that the OLP has been started
*/
static bool& didStartOLP() {
static bool f = false;
return f;
}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MatchboxOLPME & operator=(const MatchboxOLPME &);
/**
* The (tree-level) order in \f$g_S\f$ in which this matrix
* element is given.
*/
unsigned int theOrderInGs;
/**
* The (tree-level) order in \f$g_{EM}\f$ in which this matrix
* element is given.
*/
unsigned int theOrderInGem;
+ /**
+ * Set the value of the dimensional regularization parameter
+ * to the value of the renormalization scale
+ */
+ bool theSetMuToMuR;
};
}
#endif /* Herwig_MatchboxOLPME_H */
diff --git a/MatrixElement/Matchbox/External/GoSam/GoSamAmplitude.cc.in b/MatrixElement/Matchbox/External/GoSam/GoSamAmplitude.cc.in
--- a/MatrixElement/Matchbox/External/GoSam/GoSamAmplitude.cc.in
+++ b/MatrixElement/Matchbox/External/GoSam/GoSamAmplitude.cc.in
@@ -1,918 +1,933 @@
// -*- C++ -*-
//
// GoSamAmplitude.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 GoSamAmplitude class.
//
#include "GoSamAmplitude.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/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Command.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "ThePEG/Utilities/StringUtils.h"
#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.h"
#include <boost/progress.hpp>
#include <boost/filesystem.hpp>
#include <fstream>
#include <sstream>
#include <string>
#include <cstdlib>
#include <exception>
using namespace Herwig;
namespace bfs = boost::filesystem;
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
GoSamAmplitude::GoSamAmplitude(){
theCodeExists=false;
isitDR=false;
theFormOpt=true;
theNinja=true;
theHiggsEff=false;
theAccuracyTarget=6;
theMassiveLeptons=false;
doneGoSamInit=false;
doneGoSamInitRun=false;}
GoSamAmplitude::~GoSamAmplitude() {}
IBPtr GoSamAmplitude::clone() const {
return new_ptr(*this);
}
IBPtr GoSamAmplitude::fullclone() const {
return new_ptr(*this);
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void GoSamAmplitude::doinit() {
optionalContractFile() = name() + ".OLPContract.lh";
MatchboxOLPME::doinit();
doneGoSamInit = true;
}
void GoSamAmplitude::doinitrun() {
optionalContractFile() = name() + ".OLPContract.lh";
MatchboxOLPME::doinitrun();
doneGoSamInitRun = true;
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
extern "C" void OLP_Start(const char*, int* i);
extern "C" void OLP_Polvec(double*, double*, double*);
extern "C" void OLP_SetParameter(char*, double*, double*, int*);
extern "C" void OLP_PrintParameter(char*);
extern "C" void OLP_EvalSubProcess2(int*, double*, double*, double*, double*);
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
bool GoSamAmplitude::startOLP(const map<pair<Process, int>, int>& procs) {
char char_cwd[256];
getcwd(char_cwd, sizeof(char_cwd));
string cwd = string(char_cwd);
string folderMatchboxBuild = factory()->buildStorage();
folderMatchboxBuild.erase(folderMatchboxBuild.begin());
// set all necessary path and file names
gosamPath = gosamPathInterface == "" ? cwd + folderMatchboxBuild + "GoSam" : gosamPathInterface;
// When transitioning to C++ 11 this length()-1 workaround can be replaced by string.back()
if (gosamPath.at(gosamPath.length()-1) != '/') gosamPath.append("/");
gosamSourcePath = gosamPath + "source/";
gosamInstallPath = gosamPath + "build/";
// create all the directories
if (!bfs::is_directory(gosamPath)){
try {
bfs::create_directory(gosamPath);
} catch (exception& e) {
cerr << "--------------------------------------------------------------------------------\n";
cerr << "The following exception occured:\n\n";
cerr << " " << e.what() << "\n\n";
cerr << " -> Please create the parent directory of\n";
cerr << " " << gosamPath << "\n";
cerr << " manually!\n";
cerr << "--------------------------------------------------------------------------------\n";
abort();
}
}
if (!bfs::is_directory(gosamSourcePath)) bfs::create_directory(gosamSourcePath);
if (!bfs::is_directory(gosamInstallPath)) bfs::create_directory(gosamInstallPath);
contractFileTitle = name() + ".OLPContract.lh";
contractFileName = gosamPath + "/" + contractFileTitle;
string orderFileName = gosamPath + "/" + name() + ".OLPOrder.lh";
// Set the path variable (plus file name) where to find the GoSam specific input file
gosamSetupInFileName = gosamSetupInFileNameInterface == "" ? gosamPath + "/setup.gosam.in" : gosamSetupInFileNameInterface;
// Use the python script GoSamHelper.py to make replacements in the GoSam
// specific input file at gosamSetupInFileName. If the GoSam input file
// does not exist yet at gosamSetupInFileName the python script will get
// it from src/defaults/ before making the replacements.
string cmd = "python @prefix@/bin/GoSamHelper.py ";
cmd+=" --usrinfile="+gosamSetupInFileNameInterface;
cmd+=" --infile="+gosamSetupInFileName+".tbu";
cmd+=" --definfile=@prefix@/share/Herwig++/defaults/setup.gosam.in";
cmd+=" --formtempdir="+StringUtils::replace(gosamSourcePath, string("/"), string("\\/")); //@FORMTEMPDIR@
cmd+=" --reduction="+(theNinja ? string("ninja,golem95") : string("samurai,golem95")); //@REDUCTIONPROGRAMS@
cmd+=" --formopt="+(theFormOpt ? string("") : string(", noformopt")); //@FORMOPT@
cmd+=" --higgseff="+(theHiggsEff ? string("smehc") : string("smdiag")); //@MODEL@
std::system(cmd.c_str());
generator()->log() << "\n\n>>> NOTE: According to the repository settings for the GoSam interface:\n" << flush;
if (theHiggsEff) generator()->log() << "\n -- GoSam will use a model with an effective ggH coupling (model=smehc).\n" << flush;
else if (!theHiggsEff) generator()->log() << "\n -- GoSam will use its default model (model=smdiag).\n" << flush;
if (theNinja) generator()->log() << " -- GoSam will use Ninja as reduction program (reduction_programs=ninja,golem95).\n" << flush;
else if (!theNinja) generator()->log() << " -- GoSam will use Samurai as reduction program (reduction_programs=samurai,golem95).\n" << flush;
if (theFormOpt) generator()->log() << " -- Form optimization switched on (extensions=autotools).\n" << flush;
else if (!theFormOpt) generator()->log() << " -- Form optimization switched off (extensions=autotools, noformopt).\n" << flush;
if (theNinja && !theFormOpt) throw Exception() << "\n\n>>> NOTE: Ninja reduction needs form optimization!\n" << Exception::abortnow;
if (gosamSetupInFileNameInterface == "") {
generator()->log() << "\n Please be aware that you are using a copy of the default GoSam input file!\n"
<< " Please note that if you need special options to be considered for the specific\n"
<< " process you are looking at (diagram filtering, etc.) these are not automatically\n"
<< " set for you. In that case please consider to specify your own GoSam input file\n"
<< " via 'set " << name() << ":SetupInFilename' in the input file.\n\n" << flush;
}
// If one uses a custom GoSam input file at gosamSetupInFileName = gosamSetupInFileNameInterface
// then please note that not all options in there might match the corresponding Herwig repository
// options
if (gosamSetupInFileNameInterface != "") {
generator()->log() << "\n Please be aware that you are using a custom GoSam input file!\n"
<< " Please note that if you have set the options for model, reduction_programs,\n"
<< " extensions and/or form.tempdir manually these will of course not be replaced\n"
<< " by the corresponding repository settings mentioned above.\n\n" << flush;
}
+ generator()->log() << "\n>>> NOTE: GoSam may return the set of used parameters for this process via the OLP_PrintParameter() function:\n\n"
+ << " -- If Debug::level > 1, the OLP parameters are being written to file: at " << factory()->runStorage() + name() + ".OLPParameters.lh.\n\n" << flush;
+
double accuracyTarget = 1.0/pow(10.0,accuracyTargetNegExp());
time_t rawtime;
time (&rawtime);
accuracyFileTitle = name() + ".OLPAccuracy.lh";
accuracyFile = factory()->buildStorage() + accuracyFileTitle;
ofstream accuracyFileStream;
- accuracyFileStream.open(accuracyFile.c_str()); // Opening accuracyFile once here removes all previous content before the read step
- accuracyFileStream << "\nFile to contain those PSPs for which GoSam evaluated one-loop interference terms or loop induced ME2s\n"
- << "with acc > target accuracy = " << accuracyTarget << ". Date/Time: " << ctime(&rawtime) << endl;
+
+ if ( Debug::level > 1 ) {
+ accuracyFileStream.open(accuracyFile.c_str()); // Opening accuracyFile once here removes all previous content before the read step
+ accuracyFileStream << "\nFile to contain those PSPs for which GoSam evaluated one-loop interference terms or loop induced ME2s\n"
+ << "with acc > target accuracy = " << accuracyTarget << ". Date/Time: " << ctime(&rawtime) << endl;
+ }
+
generator()->log() << "\n>>> NOTE: GoSam will return the accuracy of one-loop interference terms or loop induced ME2s\n"
<< " at every PSP via the BLHA2 acc parameter:\n\n"
<< " -- In cases where acc > 10^-AccuracyTarget = " << accuracyTarget << " the corresponding PSPs are being dis-\n"
- << " carded after being written to the file at " + accuracyFile << ".\n"
+ << " carded.\n"
<< " -- The default value for AccuracyTarget is 6, but you may consider setting it otherwise\n"
<< " via 'set " << name() << ":AccuracyTarget' in the input file.\n"
<< " -- Currently the value for AccuracyTarget is set to " << accuracyTargetNegExp() << ".\n"
+ << " -- If Debug::level > 1, the discarded PSPs are being written to file: at " + accuracyFile << ".\n"
<< " -- If the amount of PSPs with acc > " << accuracyTarget << " is significant, please consider to re-evaluate\n"
<< " your process setup (accuracy target, masses, cuts, etc.)!\n\n\n" << flush;
// check for old order file and create it if it doesn't already exist
fillOrderFile(procs, orderFileName);
ifstream ifile(contractFileName.c_str());
if(!ifile){
signOLP(orderFileName, contractFileName);
}
if ( !checkOLPContract(contractFileName) ) {
throw Exception() << "failed to start GoSam" << Exception::abortnow;
}
if (!( DynamicLoader::load(gosamInstallPath+"/lib/libgolem_olp.so")
|| DynamicLoader::load(gosamInstallPath+"/lib64/libgolem_olp.so")
|| DynamicLoader::load(gosamInstallPath+"/lib/libgolem_olp.dylib")
|| DynamicLoader::load(gosamInstallPath+"/lib64/libgolem_olp.dylib"))) buildGoSam();
int status = -1;
startOLP(contractFileTitle, status);
if ( status != 1 ) return false;
return true;
}
void GoSamAmplitude::startOLP(const string& contract, int& status) {
string tempcontract = contract;
char char_cwd[256];
getcwd(char_cwd, sizeof(char_cwd));
string cwd = string(char_cwd);
string folderMatchboxBuild = factory()->buildStorage();
folderMatchboxBuild.erase(folderMatchboxBuild.begin());
gosamPath = gosamPathInterface == "" ? cwd + folderMatchboxBuild + "GoSam" : gosamPathInterface;
// When transitioning to C++ 11 this length()-1 workaround can be replaced by string.back()
if (gosamPath.at(gosamPath.length()-1) != '/') gosamPath.append("/");
if (!( DynamicLoader::load(gosamPath+"build/lib/libgolem_olp.so")
|| DynamicLoader::load(gosamPath+"build/lib64/libgolem_olp.so")
|| DynamicLoader::load(gosamPath+"build/lib/libgolem_olp.dylib")
|| DynamicLoader::load(gosamPath+"build/lib64/libgolem_olp.dylib")))
throw Exception() << "Failed to load GoSam. Please check the log file.\n"
<< Exception::abortnow;
tempcontract = gosamPath + tempcontract;
OLP_Start(tempcontract.c_str(), &status);
// hand over input parameters for EW scheme considered
int pStatus = 0;
double zero = 0.0;
if ( SM().ewScheme() == 0 || SM().ewScheme() == 6 ) { // EW/Scheme Default and EW/Scheme Independent
throw Exception() << "`Best value' schemes are not supported by GoSam"
<< Exception::abortnow;
} else if ( SM().ewScheme() == 4 ) { // EW/Scheme mW (uses mW,GF,sin2thetaW) seems not to be supported by GoSam
throw Exception() << "`mW' scheme is not supported by GoSam"
<< Exception::abortnow;
} else if ( SM().ewScheme() == 1 ) { // EW/Scheme GMuScheme (uses mW,mZ,GF)
double in1=getParticleData(ParticleID::Z0)->mass()/GeV;
double in2=getParticleData(ParticleID::Wplus)->mass()/GeV;
double in3=SM().fermiConstant()*GeV2;
OLP_SetParameter((char *)"mass(23)",&in1,&zero,&pStatus);
OLP_SetParameter((char *)"mass(24)",&in2,&zero,&pStatus);
OLP_SetParameter((char *)"Gf",&in3,&zero,&pStatus);
} else if ( SM().ewScheme() == 2 ) { // EW/Scheme alphaMZScheme (uses mW,mZ,alpha(mZ))
double in1=getParticleData(ParticleID::Z0)->mass()/GeV;
double in2=getParticleData(ParticleID::Wplus)->mass()/GeV;
double in3=SM().alphaEMMZ();
OLP_SetParameter((char *)"mass(23)",&in1,&zero,&pStatus);
OLP_SetParameter((char *)"mass(24)",&in2,&zero,&pStatus);
OLP_SetParameter((char *)"alpha",&in3,&zero,&pStatus);
} else if ( SM().ewScheme() == 3 ) { // EW/Scheme NoMass (uses alpha(mZ),GF,sin2thetaW)
double in1=SM().fermiConstant()*GeV2;
double in2=SM().alphaEMMZ();
double in3=SM().sin2ThetaW();
OLP_SetParameter((char *)"Gf",&in1,&zero,&pStatus);
OLP_SetParameter((char *)"alpha",&in2,&zero,&pStatus);
OLP_SetParameter((char *)"sw2",&in3,&zero,&pStatus);
} else if ( SM().ewScheme() == 5 ) { // EW/Scheme mZ (uses mZ,alphaEM,sin2thetaW)
double in1=getParticleData(ParticleID::Z0)->mass()/GeV;
double in2=SM().alphaEMMZ();
double in3=SM().sin2ThetaW();
OLP_SetParameter((char *)"mass(23)",&in1,&zero,&pStatus);
OLP_SetParameter((char *)"alpha",&in2,&zero,&pStatus);
OLP_SetParameter((char *)"sw2",&in3,&zero,&pStatus);
}
// hand over mass and width of the Higgs
double wH = getParticleData(25)->width()/GeV;
double mH = getParticleData(25)->mass()/GeV;
OLP_SetParameter((char*)"width(25)",&wH,&zero,&pStatus);
OLP_SetParameter((char*)"mass(25)",&mH,&zero,&pStatus);
// hand over input parameter for alphaS
double as = SM().alphaS();
OLP_SetParameter((char *)"alphaS", &as, &zero, &pStatus);
// fill massive Particle vector
if (massiveParticles.empty()) {
// with quark masses
for (int i=1; i<=6; ++i)
if (getParticleData(i)->mass()/GeV > 0.0) massiveParticles.push_back(i);
// with lepton masses
if (theMassiveLeptons && getParticleData(11)->mass()/GeV > 0.0) massiveParticles.push_back(11);
if (theMassiveLeptons && getParticleData(13)->mass()/GeV > 0.0) massiveParticles.push_back(13);
if (theMassiveLeptons && getParticleData(15)->mass()/GeV > 0.0) massiveParticles.push_back(15);
}
// hand over quark (and possibly lepton) masses and widths (iff massive)
if ( massiveParticles.size() != 0 ) {
for ( vector<int>::const_iterator mID = massiveParticles.begin(); mID != massiveParticles.end(); ++mID ) {
string mstr;
string wstr;
int mInt = *mID;
double mass=getParticleData(mInt)->mass()/GeV;
double width=getParticleData(mInt)->width()/GeV;
std::stringstream ss;
ss << mInt;
string str = ss.str();
mstr="mass("+str+")";
wstr="width("+str+")";
char * mchar = new char[mstr.size()+1];
char * wchar = new char[wstr.size()+1];
std::copy(mstr.begin(),mstr.end(),mchar);
std::copy(wstr.begin(),wstr.end(),wchar);
mchar[mstr.size()] = '\0';
wchar[wstr.size()] = '\0';
OLP_SetParameter( mchar, &mass, &zero, &pStatus );
OLP_SetParameter( wchar, &width, &zero, &pStatus );
delete[] mchar;
delete[] wchar;
// Nicer but not working properly:
// double mass=getParticleData(*mID)->mass()/GeV;
// double width=getParticleData(*mID)->width()/GeV;
// string mstr="mass("+static_cast<ostringstream*>(&(ostringstream()<<(*mID)))->str()+")";
// string wstr="width("+static_cast<ostringstream*>(&(ostringstream()<<(*mID)))->str()+")";
// cout<<"\n massiv "<<mstr;
//
// OLP_SetParameter((char *)&mstr,&mass, &zero, &pStatus );
// OLP_SetParameter((char *)&wstr,&width, &zero, &pStatus );
}
}
// Note: In the GoSam input file, the standard is to set the parameter
// 'symmetries' for quark families and lepton generations, which allow
// for flavour changing only between families/generations. If this pa-
// rameter is set, GoSam won't allow to set electron and muon mass and
// width via the interface. Also setting mass and width for the tau is
// not yet considered.
// print OLP parameters
- if ( Debug::level > 1 ) {
+ if ( Debug::level > 1 ) {
string ppstr = factory()->runStorage() + name() + ".OLPParameters.lh";
OLP_PrintParameter(const_cast<char*>(ppstr.c_str()));
- }
+ }
didStartOLP() = true;
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void GoSamAmplitude::fillOrderFile(const map<pair<Process, int>, int>& procs, string orderFileName) {
for ( map<pair<Process, int>, int>::const_iterator p = procs.begin() ; p != procs.end() ; ++p ) {
std::stringstream Processstr;
std::stringstream Typestr;
Processstr << (*p).first.first.legs[0]->id() << " " << (*p).first.first.legs[1]->id() << " -> ";
for ( PDVector::const_iterator o = (*p).first.first.legs.begin() + 2 ; o != (*p).first.first.legs.end() ; ++o )
Processstr << (**o).id() << " ";
if ( (*p).first.second == ProcessType::treeME2 ) {
Typestr << "Tree";
} else if ( (*p).first.second == ProcessType::loopInducedME2 ) {
Typestr << "LoopInduced";
} else if ( (*p).first.second == ProcessType::colourCorrelatedME2 ) {
Typestr << "ccTree";
} else if ( (*p).first.second == ProcessType::spinColourCorrelatedME2 ) {
Typestr << "scTree";
} else if ( (*p).first.second == ProcessType::oneLoopInterference ) {
Typestr << "Loop";
}
gosamprocinfo pro = gosamprocinfo((*p).second, -1, Processstr.str(), Typestr.str());
pro.setOAs(p->first.first.orderInAlphaS);
pro.setOAew(p->first.first.orderInAlphaEW);
processmap[(*p).second] = pro;
}
ifstream oldOrderFileStream(orderFileName.c_str());
if (oldOrderFileStream){
oldOrderFileStream.close();
return;
}
ofstream orderFile(orderFileName.c_str());
int asPower = 100;
int minlegs = 100;
int maxlegs = -1;
int maxasPower = -1;
int aewPower = 100;
int maxaewPower = -1;
for ( map<pair<Process, int>, int>::const_iterator t = procs.begin() ; t != procs.end() ; ++t ) {
asPower = min(asPower, static_cast<int>(t->first.first.orderInAlphaS));
minlegs = min(minlegs, static_cast<int>(t->first.first.legs.size()));
maxlegs = max(maxlegs, static_cast<int>(t->first.first.legs.size()));
maxasPower = max(maxasPower, static_cast<int>(t->first.first.orderInAlphaS));
aewPower = min(aewPower, static_cast<int>(t->first.first.orderInAlphaEW));
maxaewPower = max(maxaewPower, static_cast<int>(t->first.first.orderInAlphaEW));
}
orderFile << "# OLP order file created by Herwig++/Matchbox for GoSam\n\n";
orderFile << "InterfaceVersion BLHA2\n";
orderFile << "MatrixElementSquareType CHsummed\n";
orderFile << "CorrectionType QCD\n";
orderFile << "IRregularisation " << (isDR() ? "DRED" : "CDR") << "\n";
// loop over quarks to check if they have non-zero masses
for (int i=1; i<=6; ++i) if (getParticleData(i)->mass()/GeV > 0.0) massiveParticles.push_back(i);
// check if leptons have non-zero masses (iff theMassiveLeptons==true)
if (theMassiveLeptons && getParticleData(11)->mass()/GeV > 0.0) massiveParticles.push_back(11);
if (theMassiveLeptons && getParticleData(13)->mass()/GeV > 0.0) massiveParticles.push_back(13);
if (theMassiveLeptons && getParticleData(15)->mass()/GeV > 0.0) massiveParticles.push_back(15);
if ( massiveParticles.size() != 0 ) {
orderFile << "MassiveParticles ";
for ( vector<int>::const_iterator mID = massiveParticles.begin(); mID != massiveParticles.end(); ++mID ) {
int mInt = *mID;
orderFile << mInt << " ";
}
orderFile << "\n";
}
orderFile << "\n";
vector < string > types;
types.push_back("Tree");
types.push_back("LoopInduced");
types.push_back("ccTree");
types.push_back("scTree");
types.push_back("Loop");
for ( int i = asPower ; i != maxasPower + 1 ; i++ ) {
for ( int j = aewPower ; j != maxaewPower + 1 ; j++ ) {
orderFile << "\nAlphasPower " << i << "\n";
orderFile << "AlphaPower " << j << "\n";
for ( vector<string>::iterator it = types.begin() ; it != types.end() ; it++ ) {
if ( *it == "LoopInduced" ) continue;
for ( map<int, gosamprocinfo>::iterator p = processmap.begin() ; p != processmap.end() ; ++p )
if ( (*p).second.Tstr() == *it && i == (*p).second.orderAs() && j == (*p).second.orderAew() ) {
orderFile << "\nAmplitudeType " << *it << "\n";
break;
}
for ( map<int, gosamprocinfo>::iterator p = processmap.begin() ; p != processmap.end() ; ++p )
if ( (*p).second.Tstr() == *it && i == (*p).second.orderAs() && j == (*p).second.orderAew() ) {
orderFile << (*p).second.Pstr() << "\n";
}
}
}
}
// Write out the loop induced processes separately
int asPowerLI = 100;
int aewPowerLI = 100;
for ( map<int, gosamprocinfo>::iterator p = processmap.begin() ; p != processmap.end() ; ++p ) {
if ( (*p).second.Tstr() != "LoopInduced" ) continue;
if ( (*p).second.orderAs() != asPowerLI || (*p).second.orderAew() != aewPowerLI ) {
asPowerLI = (*p).second.orderAs();
aewPowerLI = (*p).second.orderAew();
// At the moment GoSam requires for qcd loop induced processes the as coupling power
// which would correspond to an associated fictitious Born process
orderFile << "\nAlphasPower " << (asPowerLI-2) << "\n";
orderFile << "AlphaPower " << aewPowerLI << "\n";
orderFile << "\nAmplitudeType " << "LoopInduced" << "\n";
}
orderFile << (*p).second.Pstr() << "\n";
}
orderFile << flush;
}
void GoSamAmplitude::signOLP(const string& order, const string& contract) {
if(!theCodeExists){
char char_cwd[256];
getcwd(char_cwd, sizeof(char_cwd));
string cwd = string(char_cwd);
string folderMatchboxBuild = factory()->buildStorage();
folderMatchboxBuild.erase(folderMatchboxBuild.begin());
generator()->log() << "\n>>> generating GoSam amplitudes. This may take some time, please be patient.\n"
<< ">>> see " + cwd + folderMatchboxBuild + "gosam-amplitudes.log for details.\n" << flush;
string cmd = "@GOSAMPREFIX@/bin/gosam.py --olp --output-file=" + contract + " --config=" +
gosamSetupInFileName+".tbu" + " --destination=" + gosamSourcePath + " " + order + " > " + cwd + folderMatchboxBuild + "gosam-amplitudes.log 2>&1";
std::system(cmd.c_str());
cmd = "python @prefix@/bin/GoSamHelper.py ";
cmd += " --makelink ";
cmd += " --makelinkfrom=contract ";
cmd += " --makelinkto="+factory()->buildStorage() + name() + ".OLPContract.lh";
std::system(cmd.c_str());
}
}
bool GoSamAmplitude::checkOLPContract(string contractFileName) {
ifstream infile(contractFileName.c_str());
string line;
vector < string > contractfile;
while (std::getline(infile, line)) contractfile.push_back(line);
for ( map<int, gosamprocinfo>::iterator p = processmap.begin() ; p != processmap.end() ; p++ ) {
bool righttype = false;
for ( vector<string>::iterator linex = contractfile.begin() ; linex != contractfile.end() ; ++linex ) {
if ( (*linex).find("AmplitudeType ")!= std::string::npos ) {
if ( (*linex).find(" " + (*p).second.Tstr() + " ")!= std::string::npos ) {
righttype = true;
} else {
righttype = false;
}
}
if ( righttype ) {
if ( (*linex).find((*p).second.Pstr()) != std::string::npos && (*p).second.Pstr().length() == (*linex).find("|") ) {
string sub = (*linex).substr((*linex).find("|") + 1, (*linex).find("#") - (*linex).find("|") - 1); // | 1 23 # buggy??
if ( sub.find(" 1 ") != 0 )
throw Exception() << "Failed to check contractfile. Please check the logfile.\n"
<< Exception::abortnow;
string subx = sub.substr(3);
int subint;
istringstream(subx) >> subint;
(*p).second.setGID(subint);
}
}
}
}
string ids = factory()->buildStorage() + "GoSam.ids.dat";
ofstream IDS(ids.c_str());
idpair.clear();
for ( map<int, gosamprocinfo>::iterator p = processmap.begin() ; p != processmap.end() ; p++ )
idpair.push_back(-1);
idpair.push_back(-1);
for ( map<int, gosamprocinfo>::iterator p = processmap.begin() ; p != processmap.end() ; p++ ) {
idpair[(*p).second.HID()]=(*p).second.GID();
IDS << (*p).second.HID() << " " << (*p).second.GID() << " " << (*p).second.Tstr() << "\n";
if ( (*p).second.GID() == -1 ) return 0;
}
IDS << flush;
return 1;
}
bool GoSamAmplitude::buildGoSam() {
if(!theCodeExists){
generator()->log() << "\n>>> compiling GoSam amplitudes. This may take some time, please be patient.\n"
<< ">>> see " + gosamSourcePath + "gosam-build.log for details.\n\n" << flush;
string cmd = "cd " + gosamSourcePath + " && sh autogen.sh FCFLAGS=-g --prefix=" +
gosamInstallPath + " --disable-static > gosam-build.log 2>&1";
std::system(cmd.c_str());
if (!gosamBuildScript.empty()) {
cmd = "cd " + gosamSourcePath + " && " + gosamBuildScript + " >> gosam-build.log 2>&1";
std::system(cmd.c_str());
}
std::system(cmd.c_str());
cmd = "cd " + gosamSourcePath + " && make install >> gosam-build.log 2>&1";
std::system(cmd.c_str());
}
theCodeExists=true;
return 1;
}
void GoSamAmplitude::getids() const {
string line = factory()->buildStorage() + "GoSam.ids.dat";
ifstream infile(line.c_str());
int hid;
int gid;
string type;
while (std::getline(infile, line)) {
idpair.push_back(-1);
idtypepair.push_back(" ");
}
infile.close();
string line2 = factory()->buildStorage() + "GoSam.ids.dat";
ifstream infile2(line2.c_str());
idpair.push_back(-1);
idtypepair.push_back(" ");
while (std::getline(infile2, line2)) {
istringstream(line2) >> hid >> gid >> type;
idpair[hid]=gid;
idtypepair[hid]=type;
}
infile.close();
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void GoSamAmplitude::evalSubProcess() const {
useMe();
double units = pow(lastSHat() / GeV2, int(mePartonData().size()) - 4.);
fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses());
double scale = sqrt(mu2() / GeV2);
double out[7] = { };
double acc;
if ( idpair.size() == 0 ){ getids(); }
int id = -99;
if ( olpId()[ProcessType::loopInducedME2] ) id = olpId()[ProcessType::loopInducedME2];
else if ( olpId()[ProcessType::oneLoopInterference] ) id = olpId()[ProcessType::oneLoopInterference];
else id = olpId()[ProcessType::treeME2];
int callid(idpair[id]); // If id denotes the Herwig ID, this returns the GoSam ID
string calltype(idtypepair[id]); // If id denotes the Herwig ID, this returns the amplitude type
OLP_EvalSubProcess2(&(callid), olpMomenta(), &scale, out, &acc);
+ double accuracyTarget = 1.0/pow(10.0,accuracyTargetNegExp());
accuracyFileTitle = name() + ".OLPAccuracy.lh";
accuracyFile = factory()->buildStorage() + accuracyFileTitle;
ofstream accuracyFileStream;
- accuracyFileStream.open(accuracyFile.c_str(),ios::app);
- double accuracyTarget = 1.0/pow(10.0,accuracyTargetNegExp());
+
+ if ( Debug::level > 1 ) {
+ accuracyFileStream.open(accuracyFile.c_str(),ios::app);
+ }
+
if ( (olpId()[ProcessType::oneLoopInterference]||olpId()[ProcessType::loopInducedME2]) && acc > accuracyTarget ) {
- vector<Lorentz5Momentum> currentpsp = lastXComb().meMomenta();
- time_t rawtime;
- time (&rawtime);
- if (doneGoSamInit) accuracyFileStream << "READ phase: ";
- else if (doneGoSamInitRun) accuracyFileStream << "RUN phase: ";
- accuracyFileStream << "Sub-process with Herwig ID = " << id << " and GoSam ID = " << callid << ", " << ctime(&rawtime);
- accuracyFileStream << "GoSam evaluated one-loop interference or loop induced ME2 with acc = " << acc
- << " > target accuracy = " << accuracyTarget << ", at PSP [in units of GeV]:" << endl;
- for (size_t i=0; i!=currentpsp.size(); ++i) {
- accuracyFileStream << "(t,x,y,z,mass;m)[" << i << "]=("
- << currentpsp[i].t()/GeV << ","
- << currentpsp[i].x()/GeV << ","
- << currentpsp[i].y()/GeV << ","
- << currentpsp[i].z()/GeV << ","
- << currentpsp[i].mass()/GeV << ";"
- << currentpsp[i].m()/GeV << ")"
- << endl;
+ if ( Debug::level > 1 ) {
+ vector<Lorentz5Momentum> currentpsp = lastXComb().meMomenta();
+ time_t rawtime;
+ time (&rawtime);
+ if (doneGoSamInit) accuracyFileStream << "READ phase: ";
+ else if (doneGoSamInitRun) accuracyFileStream << "RUN phase: ";
+ accuracyFileStream << "Sub-process with Herwig ID = " << id << " and GoSam ID = " << callid << ", " << ctime(&rawtime);
+ accuracyFileStream << "GoSam evaluated one-loop interference or loop induced ME2 with acc = " << acc
+ << " > target accuracy = " << accuracyTarget << ", at PSP [in units of GeV]:" << endl;
+ for (size_t i=0; i!=currentpsp.size(); ++i) {
+ accuracyFileStream << "(t,x,y,z,mass;m)[" << i << "]=("
+ << currentpsp[i].t()/GeV << ","
+ << currentpsp[i].x()/GeV << ","
+ << currentpsp[i].y()/GeV << ","
+ << currentpsp[i].z()/GeV << ","
+ << currentpsp[i].mass()/GeV << ";"
+ << currentpsp[i].m()/GeV << ")"
+ << endl;
+ }
+ accuracyFileStream << endl;
}
- accuracyFileStream << endl;
throw Veto(); // Dispose of PSP
}
if ( olpId()[ProcessType::oneLoopInterference] ) {
if (calculateTreeME2()) 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[3] * units);
} else if ( olpId()[ProcessType::loopInducedME2] ) {
lastTreeME2(out[2] * units);
}
}
void GoSamAmplitude::evalColourCorrelator(pair<int, int> ) const {
double units = pow(lastSHat() / GeV2, int(mePartonData().size()) - 4.);
fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses());
double scale = sqrt(mu2() / GeV2);
int n = lastXComb().meMomenta().size();
colourCorrelatorResults.resize(n * (n - 1) / 2);
if ( idpair.size() == 0 ) getids();
int callid(idpair[olpId()[ProcessType::colourCorrelatedME2]]);
double acc;
OLP_EvalSubProcess2(&(callid), olpMomenta(), &scale, &colourCorrelatorResults[0], &acc);
cPDVector particles = lastXComb().matrixElement()->mePartonData();
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 GoSamAmplitude::evalSpinColourCorrelator(pair<int , int > ) const {
double units = pow(lastSHat() / GeV2, int(mePartonData().size()) - 4.);
fillOLPMomenta(lastXComb().meMomenta(),mePartonData(),reshuffleMasses());
double scale = sqrt(mu2() / GeV2);
int n = lastXComb().meMomenta().size();
spinColourCorrelatorResults.resize(2*n*n);
if ( idpair.size() == 0 ) getids();
double acc;
int callid(idpair[olpId()[ProcessType::spinColourCorrelatedME2]]);
OLP_EvalSubProcess2(&(callid), olpMomenta(), &scale, &spinColourCorrelatorResults[0], &acc);
for ( int i = 0; i < n; ++i ) {
for ( int j = 0; j < n; ++j ) {
Complex scc(spinColourCorrelatorResults[2*i+2*n*j]*units, spinColourCorrelatorResults[2*i+2*n*j+1]*units);
lastColourSpinCorrelator(make_pair(i,j),scc);
}
}
}
LorentzVector<Complex> GoSamAmplitude::plusPolarization(const Lorentz5Momentum& p, const Lorentz5Momentum& n, int inc) const {
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;
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void GoSamAmplitude::persistentOutput(PersistentOStream & os) const {
os << idpair << idtypepair << processmap << gosamPathInterface
<< gosamSetupInFileNameInterface << gosamBuildScript << gosamPath
<< gosamSourcePath << gosamInstallPath << gosamSetupInFileName
<< orderFileTitle << contractFileTitle
<< contractFileName << orderFileName
<< theCodeExists << theFormOpt << theNinja << isitDR << massiveParticles << theHiggsEff
<< theAccuracyTarget;
}
void GoSamAmplitude::persistentInput(PersistentIStream & is, int) {
is >> idpair >> idtypepair >> processmap >> gosamPathInterface
>> gosamSetupInFileNameInterface >> gosamBuildScript >> gosamPath
>> gosamSourcePath >> gosamInstallPath >> gosamSetupInFileName
>> orderFileTitle >> contractFileTitle
>> contractFileName >> orderFileName
>> theCodeExists >> theFormOpt >> theNinja >> isitDR >> massiveParticles >> theHiggsEff
>> theAccuracyTarget;
}
// *** 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<GoSamAmplitude, MatchboxOLPME> describeHerwigGoSamAmplitude("Herwig::GoSamAmplitude", "HwMatchboxGoSam.so");
void GoSamAmplitude::Init() {
static ClassDocumentation<GoSamAmplitude> documentation("GoSamAmplitude implements an interface to GoSam.", "Matrix elements have been calculated using GoSam");
static Parameter<GoSamAmplitude,string> interfaceProcessPath
("ProcessPath",
"Prefix for the process source code, include files and library produced by GoSam.",
&GoSamAmplitude::gosamPathInterface, "",
false, false);
static Parameter<GoSamAmplitude,string> interfaceSetupInFilename
("SetupInFilename",
"File name of the GoSam infile (typically setup.gosam.in) to be used. If left empty a new setup.gosam.in is created in the location specified in Path",
&GoSamAmplitude::gosamSetupInFileNameInterface, "",
false, false);
static Switch<GoSamAmplitude,bool> interfaceCodeExists
("CodeExists",
"Switch on or off if Code already exists/not exists.",
&GoSamAmplitude::theCodeExists, true, false, false);
static SwitchOption interfaceCodeExistsOn
(interfaceCodeExists,
"True",
"Switch True if Code already exists.",
true);
static SwitchOption interfaceCodeExistsOff
(interfaceCodeExists,
"False",
"Switch False if Code has to be build.",
false);
static Switch<GoSamAmplitude,bool> interfaceisitDR
("isDR",
"Switch on or off DR.",
&GoSamAmplitude::isitDR, false, false, false);
static SwitchOption interfaceisitDROn
(interfaceisitDR,
"True",
"Switch True.",
true);
static SwitchOption interfaceisitDROff
(interfaceisitDR,
"False",
"Switch False.",
false);
static Switch<GoSamAmplitude,bool> interfaceFormOpt
("FormOpt",
"Switch On/Off formopt",
&GoSamAmplitude::theFormOpt, true, false, false);
static SwitchOption interfaceFormOptOn
(interfaceFormOpt,
"On",
"On",
true);
static SwitchOption interfaceFormOptOff
(interfaceFormOpt,
"Off",
"Off",
false);
static Switch<GoSamAmplitude,bool> interfaceNinja
("Ninja",
"Switch On/Off for reduction with Ninja. If Off then Samurai is used.",
&GoSamAmplitude::theNinja, true, false, false);
static SwitchOption interfaceNinjaOn
(interfaceNinja,
"On",
"On",
true);
static SwitchOption interfaceNinjaOff
(interfaceNinja,
"Off",
"Off",
false);
static Switch<GoSamAmplitude,bool> interfaceHiggsEff
("HiggsEff",
"Switch On/Off for effective higgs model.",
&GoSamAmplitude::theHiggsEff, false, false, false);
static SwitchOption interfaceHiggsEffOn
(interfaceHiggsEff,
"On",
"On",
true);
static SwitchOption interfaceHiggsEffOff
(interfaceHiggsEff,
"Off",
"Off",
false);
static Parameter<GoSamAmplitude,string> interfaceBuildScript
("BuildScript",
"File name of a custom build script, which is called between 'autogen.sh'"
"and 'make install'. It can be used for parallelization.",
&GoSamAmplitude::gosamBuildScript, "",
false, false);
static Parameter<GoSamAmplitude,int> interfaceAccuracyTarget
("AccuracyTarget",
"Integer to parametrize the threshold value for the BLHA2 acc parameter, returned by GoSam in the case of "
"sub-processes with one-loop intereference terms or loop induced sub-processes."
- "If acc > 10^-AccuracyTarget the corresponding phase space point is being written to file and disposed of.",
+ "If acc > 10^-AccuracyTarget the corresponding PSP is being discarded. Discarded PSPs are written to file "
+ "if Debug::level > 1.",
&GoSamAmplitude::theAccuracyTarget, 6, 0, 0,
false, false, Interface::lowerlim);
static Switch<GoSamAmplitude,bool> interfaceMassiveLeptons
("MassiveLeptons",
"If set to Yes, then pass on the light lepton masses - as well as the tau mass - to GoSam."
"Otherwise GoSam will use light leptons of zero mass as default, as well as its own default tau mass.",
&GoSamAmplitude::theMassiveLeptons, false, false, false);
static SwitchOption interfaceMassiveLeptonsNo
(interfaceMassiveLeptons,
"No",
"No",
false);
static SwitchOption interfaceMassiveLeptonsYes
(interfaceMassiveLeptons,
"Yes",
"Yes",
true);
}
diff --git a/MatrixElement/Matchbox/External/GoSam/GoSamAmplitude.h b/MatrixElement/Matchbox/External/GoSam/GoSamAmplitude.h
--- a/MatrixElement/Matchbox/External/GoSam/GoSamAmplitude.h
+++ b/MatrixElement/Matchbox/External/GoSam/GoSamAmplitude.h
@@ -1,305 +1,310 @@
// -*- C++ -*-
//
// GoSamAmplitude.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_GoSamAmplitude_H
#define Herwig_GoSamAmplitude_H
//
// This is the declaration of the GoSamAmplitude class.
//
#include "Herwig++/MatrixElement/Matchbox/Base/MatchboxOLPME.h"
#include "ThePEG/Utilities/DynamicLoader.h"
namespace Herwig {
using namespace ThePEG;
class gosamprocinfo{
public:
gosamprocinfo(){};
gosamprocinfo(int HID,int GID, string procstr,string typestr):
theHOlpId(HID),theGOlpId(GID),theProcstr(procstr),theTypestr(typestr){
}
~gosamprocinfo(){}
int HID() const {return theHOlpId;}
int GID() const {return theGOlpId;}
string Pstr() const {return theProcstr;}
string Tstr() const {return theTypestr;}
void setGID(int g){theGOlpId=g;}
void setOAs(int i){ orderAlphas=i;}
int orderAs(){return orderAlphas;}
void setOAew(int j){ orderAlphaew=j;}
int orderAew(){return orderAlphaew;}
private:
int theHOlpId;
int theGOlpId;
string theProcstr;
string theTypestr;
int orderAlphas;
int orderAlphaew;
public:
void persistentOutput(PersistentOStream & os) const{os<<theHOlpId<<theGOlpId<<theProcstr<<theTypestr<<orderAlphas<<orderAlphaew;}
void persistentInput(PersistentIStream &is) {is>>theHOlpId>>theGOlpId>>theProcstr>>theTypestr>>orderAlphas>>orderAlphaew;}
};
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief GoSamAmplitude implements an interface to GoSam
*/
class GoSamAmplitude: public MatchboxOLPME {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
GoSamAmplitude();
/**
* The destructor.
*/
virtual ~GoSamAmplitude();
//@}
public:
virtual void fillOrderFile(const map<pair<Process,int>,int>& procs, string OrderFileName);
virtual bool isCS() const { return false; }
virtual bool isExpanded() const { return true; }
virtual bool isBDK() const { return false; }
virtual bool isDR() const { return isitDR; }
virtual bool isDRbar() const {return false;}
/**
* Start the one loop provider, if appropriate, giving order and
* contract files
*/
virtual void signOLP(const string&, const string&);
virtual bool checkOLPContract(string contractFileName);
/**
* Return true, if this amplitude already includes symmetry factors
* for identical outgoing particles.
*/
// virtual bool hasFinalStateSymmetry() const { return true; }
virtual bool hasFinalStateSymmetry() const { return false; }
virtual bool buildGoSam();
/**
* Start the one loop provider, if appropriate
*/
virtual void startOLP(const string&, int& status);
- virtual Energy2 mu2() const { return lastSHat(); }
+ /**
+ * Return the value of the dimensional regularization
+ * parameter. Note that renormalization scale dependence is fully
+ * restored in DipoleIOperator.
+ */
+ // virtual Energy2 mu2() const { return lastSHat(); }
/**
* Start the one loop provider, if appropriate. This default
* implementation writes an BLHA 2.0 order file and starts the OLP
*/
virtual bool startOLP(const map<pair<Process,int>,int>& procs);
/**
* Call OLP_EvalSubProcess and fill in the results
*/
void evalSubProcess() const;
/**
* Fill in results for the given colour correlator
*/
virtual void evalColourCorrelator(pair<int,int> ij) const;
/**
* Return a positive helicity polarization vector for a gluon of
* momentum p (with reference vector n) to be used when evaluating
* spin correlations.
*/
virtual LorentzVector<Complex> plusPolarization(const Lorentz5Momentum& p,
const Lorentz5Momentum& n, int inc) const;
/**
* Fill in results for the given colour/spin correlator
*/
virtual void evalSpinColourCorrelator(pair<int,int> ij) const;
void getids() const;
int accuracyTargetNegExp() const { return theAccuracyTarget; }
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();
/**
* Initialize this object. Called in the run phase just before
* a run begins.
*/
virtual void doinitrun();
//@}
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.
*/
GoSamAmplitude & operator=(const GoSamAmplitude &);
/**
* Store colour correlator results
*/
mutable vector<double> colourCorrelatorResults;
/**
* Store spin colour correlator results
*/
mutable vector<double> spinColourCorrelatorResults;
/**
* first is the olp id from herwig, second the answer from gosam
*/
mutable vector<int> idpair;
/**
* first is the olp id from herwig, second the amplitude type
*/
mutable vector<string> idtypepair;
/**
* Map to store all processes handled by this Amplitude
*/
map<int , gosamprocinfo > processmap;
mutable string gosamPathInterface;
mutable string gosamSetupInFileNameInterface;
mutable string gosamBuildScript;
mutable string gosamPath;
mutable string gosamSourcePath;
mutable string gosamInstallPath;
mutable string gosamSetupInFileName;
mutable string orderFileTitle;
mutable string contractFileTitle;
mutable string contractFileName;
mutable string orderFileName;
mutable string accuracyFileTitle;
mutable string accuracyFile;
int theAccuracyTarget;
bool theCodeExists;
bool theFormOpt;
bool theNinja;
bool theHiggsEff;
bool theMassiveLeptons;
bool isitDR;
mutable bool doneGoSamInit;
mutable bool doneGoSamInitRun;
/**
* The PDG codes of those quarks with mass
*/
vector<int> massiveParticles; //theMassiveParticles;
/**
* Method to create the setup.in file for GoSam
*/
void setupGoSamIn(string setupGoSamInFile);
}; // end "class GoSamAmplitude: public MatchboxOLPME"
inline PersistentOStream& operator<<(PersistentOStream& os, const gosamprocinfo& p) {
p.persistentOutput(os); return os;
}
inline PersistentIStream& operator>>(PersistentIStream& is, gosamprocinfo& p) {
p.persistentInput(is); return is;
}
} // end "namespace Herwig"
#endif /* Herwig_GoSamAmplitude_H */
diff --git a/MatrixElement/Matchbox/External/MadGraph/MadGraphAmplitude.cc.in b/MatrixElement/Matchbox/External/MadGraph/MadGraphAmplitude.cc.in
--- a/MatrixElement/Matchbox/External/MadGraph/MadGraphAmplitude.cc.in
+++ b/MatrixElement/Matchbox/External/MadGraph/MadGraphAmplitude.cc.in
@@ -1,757 +1,758 @@
// -*- 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;
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) {}
MadGraphAmplitude::~MadGraphAmplitude() {
}
IBPtr MadGraphAmplitude::clone() const {
return new_ptr(*this);
}
IBPtr MadGraphAmplitude::fullclone() const {
return new_ptr(*this);
}
map<string,int>& MadGraphAmplitude::processmap() {
static map<string,int> theProcessMap;
return theProcessMap;
}
template<class ProcType>
string processId(const ProcType& p) {
string orderFileName = "";
for (typename ProcType::const_iterator it=p.begin();it!=p.end();it++)
orderFileName +=boost::lexical_cast<string>( (*it)->id());
orderFileName+=".MG";
return orderFileName;
}
bool MadGraphAmplitude::initializedMad=false;
void MadGraphAmplitude::initProcess(const cPDVector& ) {
if ( lastMatchboxXComb()->initialized() )
return;
string MGProcLibPath = theProcessPath == "" ? factory()->buildStorage()+"MadGraphAmplitudes" : theProcessPath;
if (MGProcLibPath.at(MGProcLibPath.length()-1) != '/') MGProcLibPath.append("/");
if ( !DynamicLoader::load(MGProcLibPath+"InterfaceMadGraph.so") )
throw Exception() << "Failed to load MadGraph amplitudes\n"
<< DynamicLoader::lastErrorMessage
<< Exception::abortnow;
if (!initializedMad){
string mstr=(factory()->runStorage()+"MadGraphAmplitudes"+"/param_card"+((theMGmodel=="loop_sm")?"":("_"+theMGmodel))+".dat");
size_t len = mstr.size();
mginitproc_(const_cast<char*>(mstr.c_str()),len);
initializedMad=true;
}
lastMatchboxXComb()->isInitialized();
}
bool MadGraphAmplitude::initializeExternal() {
loadProcessMap();
string MGProcLibPath = theProcessPath == "" ? factory()->buildStorage()+"MadGraphAmplitudes" : theProcessPath;
if (MGProcLibPath.at(MGProcLibPath.length()-1) != '/') MGProcLibPath.append("/");
if ( boost::filesystem::exists(MGProcLibPath) ) {
if ( !boost::filesystem::is_directory(MGProcLibPath) )
throw Exception() << "MadGraph amplitude storage '"
<< MGProcLibPath << "' existing but not a directory."
<< Exception::abortnow;
} else {
boost::filesystem::create_directories(MGProcLibPath);
}
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();
}
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.close();
}
string runAmplitudes = factory()->runStorage() + "/MadGraphAmplitudes";
if ( boost::filesystem::exists(runAmplitudes) ) {
if ( !boost::filesystem::is_directory(runAmplitudes) )
throw Exception() << "MadGraph amplitude storage '"
<< runAmplitudes << "' existing but not a directory."
<< Exception::abortnow;
} else {
boost::filesystem::create_directories(runAmplitudes);
}
//EW-consistency check:
Energy MW=getParticleData(ParticleID::Wplus)->mass();
Energy MZ=getParticleData(ParticleID::Z0)->mass();
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()))){
cerr<<"\n\n-----!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!-----";
cerr << "\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)->width() /GeV;
params<<"\n$WW$ " <<std::setiosflags(ios::scientific) <<getParticleData(ParticleID::Wplus)->width()/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)->mass() /GeV<<flush;
params<<"\n$MW$ " <<std::setiosflags(ios::scientific) <<getParticleData(ParticleID::Wplus)->mass() /GeV<<flush;
params<<"\n$sw2$ " <<std::setiosflags(ios::scientific) << SM().sin2ThetaW() <<flush;
if(theMGmodel=="heft"&&!keepinputtopmass){
cerr<<"\n---------------------------------------------------------------";
cerr<<"\n---------------------------------------------------------------";
cerr<<"\nNote: You are using the Higgs Effective model (heft) in ";
cerr<<"\n Madgraph. We assume you try to calculate NLO with ";
cerr<<"\n the GoSam virtual amplitudes. To match the models we ";
cerr<<"\n therefore set the topmass to 10000000 GeV.";
cerr<<"\n\n For more information see the \\tau parameter in:";
cerr<<"\n https://cp3.irmp.ucl.ac.be/projects/madgraph/wiki/Models/HiggsEffective";
cerr<<"\n\n The Effective Higgs model in Gosam is using mT=infinity";
cerr<<"\n\n\n If you want to use the LO matrixelements of MadGraph with finite' topmass you need to add: ";
cerr<<"\n\n set Madgraph:KeepInputTopMass True";
cerr<<"\n\n to your input file.";
cerr<<"\n---------------------------------------------------------------";
cerr<<"\n---------------------------------------------------------------\n";
params<<"\n$MT$ 10000000." <<flush;
}else{
params<<"\n$MT$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::t)->mass() /GeV <<flush;
}
params<<"\n$WT$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::t)->width() /GeV <<flush;
params<<"\n$MB$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::b)->mass() /GeV <<flush;
params<<"\n$MH$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::h0)->mass() /GeV <<flush;
params<<"\n$WH$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::h0)->width() /GeV <<flush;
params<<"\n$MTA$ " <<std::setiosflags(ios::scientific) << getParticleData(ParticleID::tauplus)->mass() /GeV <<flush;
string cmd = "python @prefix@/bin/mg2Matchbox.py ";
cmd +=" --buildpath "+MGProcLibPath;
cmd +=" --model "+theMGmodel;
cmd +=" --runpath "+factory()->runStorage()+"/MadGraphAmplitudes " ;
std::stringstream as,aem;
as << factory()->orderInAlphaS();
cmd +=" --orderas "+as.str() ;
aem <<factory()->orderInAlphaEW();
cmd +=" --orderew "+aem.str();
// TODO move to boost::system
if ( !processmap().empty() ){
//set the parameters
std::system(cmd.c_str());
ranMadGraphInitializeExternal = true;
return true;
}
char cwd[1024];
if ( !getcwd(cwd,sizeof(cwd)) )
throw Exception() << "failed to determine current working directory\n"
<< Exception::abortnow;
cmd +=" --madgraph @MADGRAPHPREFIX@/bin " ;
cmd +="--build > ";
cmd += MGProcLibPath+"MG.log 2>&1";
generator()->log() << "\n\nCompiling 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 @prefix@/bin/mg2Matchbox.py ";
cmd +=" --buildpath "+MGProcLibPath;
cmd +=" --model "+theMGmodel;
cmd +=" --runpath "+factory()->runStorage()+"/MadGraphAmplitudes " ;
as.clear();
aem.clear();
as << factory()->orderInAlphaS();
cmd +=" --orderas "+as.str() ;
aem <<factory()->orderInAlphaEW();
cmd +=" --orderew "+aem.str();
std::system(cmd.c_str());
loadProcessMap();
ranMadGraphInitializeExternal = true;
return !processmap().empty();
}
int MadGraphAmplitude::externalId(const cPDVector& proc) {
for (int i=0;i<100;i++){
colourindex.push_back(-2);
}
assert(!BornAmplitudes.empty()||!VirtAmplitudes.empty());
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+=" > ";
}
for (vector<string>::iterator amps=BornAmplitudes.begin();amps!=BornAmplitudes.end();amps++,res++)
if(amp==*amps)return res+1;
for (vector<string>::iterator amps=VirtAmplitudes.begin();amps!=VirtAmplitudes.end();amps++,res++)
if(amp==*amps)return res+1;
throw Exception() << "One amplitude has no externalId. Please remove the MadGraphAmplitude-folder and rebuild.\n" << Exception::abortnow;
return res;
}
void MadGraphAmplitude::loadProcessMap() {
if ( !processmap().empty() )
return;
string MGProcLibPath = theProcessPath == "" ? factory()->buildStorage()+"MadGraphAmplitudes" : theProcessPath;
if (MGProcLibPath.at(MGProcLibPath.length()-1) != '/') MGProcLibPath.append("/");
string line = MGProcLibPath+"processmap.dat";
ifstream infile(line.c_str());
if ( !infile )
return;
string process;
int id;
while (std::getline(infile, line)) {
std::stringstream ss(line);
getline( ss, process, ' ' );
ss >> id;
processmap().insert(make_pair(process,id));
}
}
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+=" > ";
}
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[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);
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);
}
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;
}
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 assert(false);
}
return res;
}
LorentzVector<Complex> MadGraphAmplitude::plusPolarization(const Lorentz5Momentum& p,
const Lorentz5Momentum& n,
int i) const {
int tmp=i;
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.conjugate();
}
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);
Complex pFactor = (polarization*c.momentum())/sqrt(abs(c.scale()));
double avg =
colourCorrelatedME2(ij)*(-c.diagonal()+ (c.scale() > ZERO ? 1. : -1.)*norm(pFactor));
int iCrossed = crossingMap()[ij.first];
iCrossed = ij.first;
for ( unsigned int k = 0; k < crossingMap().size(); ++k )
if ( crossingMap()[k] == ij.first ) {
iCrossed = k;
break;
}
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);
}
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;
}
void MadGraphAmplitude::persistentInput(PersistentIStream & is, int) {
is >> theOrderInGs >> theOrderInGem >> BornAmplitudes >> VirtAmplitudes
>> colourindex>>crossing >> theProcessPath >> theMGmodel;
}
// *** 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");
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);
}
diff --git a/MatrixElement/Matchbox/External/NLOJet/NLOJetPhasespace.h b/MatrixElement/Matchbox/External/NLOJet/NLOJetPhasespace.h
--- a/MatrixElement/Matchbox/External/NLOJet/NLOJetPhasespace.h
+++ b/MatrixElement/Matchbox/External/NLOJet/NLOJetPhasespace.h
@@ -1,256 +1,256 @@
// -*- C++ -*-
//
// NLOJetPhasespace.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_NLOJetPhasespace_H
#define HERWIG_NLOJetPhasespace_H
//
// This is the declaration of the NLOJetPhasespace class.
//
#include "Herwig++/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h"
#include "NLOJetRandomWrapper.h"
#include "nlo++/bits/hep-lorentzvector.h"
#include "nlo++/bits/psg-phasespace.h"
#include "nlo++/bits/nlo-phasespace.h"
#include "nlo++/bits/nlo-event.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief Convert nlo::lorentzvector<double> to Lorentz5Vector<Energy>,
* assuming nlo::lorentzvector<double> is given in units og GeV
*/
struct NLOMomentumConverter {
Lorentz5Momentum operator()(const nlo::lorentzvector<double>& v) const {
return Lorentz5Momentum(v.X()*GeV,v.Y()*GeV,v.Z()*GeV,v.T()*GeV);
}
nlo::lorentzvector<double> operator()(const Lorentz5Momentum& v) const {
return nlo::lorentzvector<double>(v.x()/GeV,v.y()/GeV,v.z()/GeV,v.t()/GeV);
}
};
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief Keys for XComb meta information
*/
struct NLOMetaKeys {
enum Keys {
HadronicEvent
};
};
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief NLOJetPhasespace provides an interface to
* nlojet's phasespace generator classes.
*
* @see \ref NLOJetPhasespaceInterfaces "The interfaces"
* defined for NLOJetPhasespace.
*/
template<unsigned int N, unsigned int I, unsigned int F>
class NLOJetPhasespace: public Herwig::MatchboxPhasespace {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
NLOJetPhasespace();
/**
* The destructor.
*/
virtual ~NLOJetPhasespace();
//@}
public:
/**
* Define the event type.
*/
typedef typename nlo::hadronic_event<nlo::lorentzvector<double>,
nlo::hadronic_event_traits<N,I,F> > NLOEvent;
/**
* Define the type of the nlojet phasespace generator.
*/
typedef typename nlo::basic_phasespace<NLOEvent> NLOPhasespace;
/**
* Get the phasepsace generator to wrap around.
*/
NLOPhasespace* nloPhasespace() const { return theNLOPhasespace; }
/**
* Prepare a phase space generator for the given xcomb object.
*/
virtual void prepare(tStdXCombPtr xc, bool verbose = false);
/**
* Generate a phase space point and return its weight.
*/
virtual double generateTwoToNKinematics(const double* r,
vector<Lorentz5Momentum>& momenta);
/**
* Return the number of random numbers required to produce a given
* multiplicity final state.
*/
- virtual int nDim(int nFinal) const;
+ virtual int nDimPhasespace(int nFinal) const;
/**
* Return true, if this phasespace generator will generate incoming
* partons itself.
*/
virtual bool haveX1X2() const { return true; }
/**
* Return true, if this phase space generator expects
* the incoming partons in their center-of-mass system
*/
virtual bool wantCMS() const { return false; }
/**
* Fill a diagram selector for the last phase space point.
*/
virtual Selector<MEBase::DiagramIndex> selectDiagrams(const MEBase::DiagramVector&) const {
return Selector<MEBase::DiagramIndex>();
}
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:
/** @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 number of outgoing partons from which on dipole generation is
* used.
*/
unsigned int nHard;
/**
* The phasepsace generator to wrap around.
*/
NLOPhasespace* theNLOPhasespace;
/**
* The random number wrapper
*/
NLOJetRandomWrapper nloRnd;
/**
* The event to be filled
*/
NLOEvent* nloEvent;
/**
* The hard event to start with
*/
NLOEvent* nloHardEvent;
/**
* The XCombPtr to nloEvent pointer map
*/
map < XCPtr, NLOEvent * > theXCtoEvents;
/**
* The XCombPtr to nloHardEvent pointer map
*/
map < XCPtr, NLOEvent * > theXCtoHardEvents;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
NLOJetPhasespace & operator=(const NLOJetPhasespace &);
};
}
#include "NLOJetPhasespace.tcc"
#endif /* HERWIG_NLOJetPhasespace_H */
diff --git a/MatrixElement/Matchbox/External/NLOJet/NLOJetPhasespace.tcc b/MatrixElement/Matchbox/External/NLOJet/NLOJetPhasespace.tcc
--- a/MatrixElement/Matchbox/External/NLOJet/NLOJetPhasespace.tcc
+++ b/MatrixElement/Matchbox/External/NLOJet/NLOJetPhasespace.tcc
@@ -1,170 +1,170 @@
// -*- C++ -*-
//
// NLOJetPhasespace.tcc 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 NLOJetPhasespace class.
//
#include "ThePEG/Interface/ClassDocumentation.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 "nlo++/bits/psg-phasespace_n0i0f0.h"
#include "nlo++/bits/psg-phasespace_n0i2f0.h"
//#include "nlo++/bits/psg-phasespace_n1i1f0.h"
#include "nlo++/bits/psg-phasespace_n2i2f0.h"
namespace Herwig {
template<unsigned int N, unsigned int I, unsigned int F>
NLOJetPhasespace<N,I,F>::NLOJetPhasespace()
: MatchboxPhasespace(), theNLOPhasespace(0), nloEvent(0), nloHardEvent(0) {}
template<unsigned int N, unsigned int I, unsigned int F>
NLOJetPhasespace<N,I,F>::~NLOJetPhasespace() {
if ( theNLOPhasespace ) {
delete theNLOPhasespace;
theNLOPhasespace = 0;
}
for(typename map < XCPtr, NLOEvent* >::iterator it= theXCtoEvents.begin();
it != theXCtoEvents.end(); ++it )
delete (*it).second;
nloEvent = 0;
for(typename map < XCPtr, NLOEvent* >::iterator it= theXCtoHardEvents.begin();
it != theXCtoHardEvents.end(); ++it )
delete (*it).second;
nloHardEvent = 0;
}
template<unsigned int N, unsigned int I, unsigned int F>
IBPtr NLOJetPhasespace<N,I,F>::clone() const {
return new_ptr(*this);
}
template<unsigned int N, unsigned int I, unsigned int F>
IBPtr NLOJetPhasespace<N,I,F>::fullclone() const {
return new_ptr(*this);
}
template<unsigned int N, unsigned int I, unsigned int F>
void NLOJetPhasespace<N,I,F>::doinit() {
MatchboxPhasespace::doinit();
double s = sqr(generator()->maximumCMEnergy()/GeV);
if ( theNLOPhasespace )
delete theNLOPhasespace;
theNLOPhasespace = new NLOPhasespace(&nloRnd,s);
}
template<unsigned int N, unsigned int I, unsigned int F>
void NLOJetPhasespace<N,I,F>::doinitrun() {
MatchboxPhasespace::doinitrun();
double s = sqr(generator()->maximumCMEnergy()/GeV);
if ( theNLOPhasespace )
delete theNLOPhasespace;
theNLOPhasespace = new NLOPhasespace(&nloRnd,s);
}
template<unsigned int N, unsigned int I, unsigned int F>
void NLOJetPhasespace<N,I,F>::prepare(tStdXCombPtr xc, bool) {
theLastXComb = xc;
if( theXCtoEvents.find( lastXCombPtr() ) != theXCtoEvents.end() ){
nloEvent=theXCtoEvents[lastXCombPtr()];
}
else{
nloEvent= new NLOEvent(nHard-F);
theXCtoEvents[lastXCombPtr()]=nloEvent;
}
if( theXCtoHardEvents.find(lastXCombPtr()) != theXCtoHardEvents.end() ){
nloHardEvent=theXCtoHardEvents[lastXCombPtr()];
}
else{
nloHardEvent= new NLOEvent(mePartonData().size()-2-N-F);
theXCtoHardEvents[lastXCombPtr()]=nloHardEvent;
}
}
template<unsigned int N, unsigned int I, unsigned int F>
-int NLOJetPhasespace<N,I,F>::nDim(int nFinal) const {
+int NLOJetPhasespace<N,I,F>::nDimPhasespace(int nFinal) const {
// rambo + x's + dipoles
return
4*(N+nHard) + 2*I + 8*(nFinal-N-nHard);
}
template<unsigned int N, unsigned int I, unsigned int F>
double NLOJetPhasespace<N,I,F>::generateTwoToNKinematics(const double* r,
vector<Lorentz5Momentum>& momenta) {
nloRnd.numbers(r);
double weight = (*nloPhasespace())(*nloHardEvent);
if ( weight == 0. )
return 0.;
weight *= (*nloPhasespace())(*nloHardEvent,*nloEvent);
if ( weight == 0. )
return 0.;
NLOMomentumConverter converter;
momenta[0] = converter((*nloEvent)[-1]);
momenta[1] = converter((*nloEvent)[0]);
for ( unsigned int k = 1; k <= F; ++k )
momenta[k+1] = converter((*nloEvent)[-1-k]);
for ( unsigned int k = 1; k <= momenta.size()-2-F; ++k )
momenta[k+F+1] = converter((*nloEvent)[k]);
lastXCombPtr()->meta(NLOMetaKeys::HadronicEvent,*nloEvent);
double x1 = momenta[0].plus()/lastParticles().first->momentum().plus();
double x2 = momenta[1].minus()/lastParticles().second->momentum().minus();
lastXCombPtr()->lastX1X2(make_pair(x1,x2));
lastXCombPtr()->lastSHat((momenta[0]+momenta[1]).m2());
return pow(lastSHat()/GeV2,-(double)(momenta.size()-4))*weight/(x1*x2);
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
template<unsigned int N, unsigned int I, unsigned int F>
void NLOJetPhasespace<N,I,F>::persistentOutput(PersistentOStream & os) const {
os << nHard;
}
template<unsigned int N, unsigned int I, unsigned int F>
void NLOJetPhasespace<N,I,F>::persistentInput(PersistentIStream & is, int) {
is >> nHard;
}
template<unsigned int N, unsigned int I, unsigned int F>
void NLOJetPhasespace<N,I,F>::Init() {
static ClassDocumentation<NLOJetPhasespace<N,I,F> > documentation
("NLOJetPhasespace provides an interface to "
"nlojet's phasespace generator classes.");
static Parameter<NLOJetPhasespace,unsigned int> interfaceNHard
("NHard",
"The number of outgoing partons from which on dipole generation is used.",
&NLOJetPhasespace::nHard, 2, 1, 0,
false, false, Interface::lowerlim);
}
}
diff --git a/MatrixElement/Matchbox/External/OpenLoops/OpenLoopsAmplitude.h b/MatrixElement/Matchbox/External/OpenLoops/OpenLoopsAmplitude.h
--- a/MatrixElement/Matchbox/External/OpenLoops/OpenLoopsAmplitude.h
+++ b/MatrixElement/Matchbox/External/OpenLoops/OpenLoopsAmplitude.h
@@ -1,319 +1,325 @@
// -*- C++ -*-
//
// OpenLoopsAmplitude.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_OpenLoopsAmplitude_H
#define Herwig_OpenLoopsAmplitude_H
//
// This is the declaration of the OpenLoopsAmplitude class.
//
#include "Herwig++/MatrixElement/Matchbox/Base/MatchboxOLPME.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Johannes Bellm, Simon Platzer
*
* \brief Process information for OpenLoops
*/
class OpenLoopsProcInfo{
public:
/**
* Default constructor
*/
OpenLoopsProcInfo() {}
/**
* Construct giving data
*/
OpenLoopsProcInfo(int HID,int GID, string procstr,string typestr)
: theHOlpId(HID), theGOlpId(GID), theProcstr(procstr), theTypestr(typestr) {}
/**
* Document me
*/
int HID() const { return theHOlpId; }
/**
* Document me
*/
int GID() const { return theGOlpId; }
/**
* Document me
*/
const string& Pstr() const { return theProcstr; }
/**
* Document me
*/
const string& Tstr() const { return theTypestr; }
/**
* Document me
*/
void setGID(int g) { theGOlpId=g; }
/**
* Document me
*/
void setOAs(int i) { orderAlphas=i; }
/**
* Document me
*/
int orderAs() { return orderAlphas; }
private:
/**
* Document me
*/
int theHOlpId;
/**
* Document me
*/
int theGOlpId;
/**
* Document me
*/
string theProcstr;
/**
* Document me
*/
string theTypestr;
/**
* Document me
*/
int orderAlphas;
public:
/**
* Write to persistent stream
*/
void persistentOutput(PersistentOStream & os) const{
os << theHOlpId << theGOlpId << theProcstr << theTypestr << orderAlphas;
}
/**
* Read from persistent stream
*/
void persistentInput(PersistentIStream &is) {
is >> theHOlpId >> theGOlpId >> theProcstr >> theTypestr >> orderAlphas;
}
};
/**
* \ingroup Matchbox
* \author Johannes Bellm, Simon Platzer
*
* \brief OpenLoopsAmplitude implements an interface to OpenLoops
*/
class OpenLoopsAmplitude: public MatchboxOLPME {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
OpenLoopsAmplitude();
/**
* The destructor.
*/
virtual ~OpenLoopsAmplitude();
//@}
public:
virtual void fillOrderFile(const map<pair<Process,int>,int>& procs);
virtual bool isCS() const { return false; }
virtual bool isExpanded() const { return true; }
virtual bool isBDK() const { return false; }
//virtual bool isDR() const { return true; }
/**
* Start the one loop provider, if appropriate, giving order and
* contract files
*/
virtual bool checkOLPContract();
/**
* Start the one loop provider, if appropriate
*/
virtual void startOLP(const string&, int& status);
virtual void getids() const ;
- virtual Energy2 mu2() const { return lastSHat(); }
+ /**
+ * Return the value of the dimensional regularization
+ * parameter. Note that renormalization scale dependence is fully
+ * restored in DipoleIOperator.
+ */
+ // virtual Energy2 mu2() const { return lastSHat(); }
+
/**
* Start the one loop provider, if appropriate. This default
* implementation writes an BLHA 2.0 order file and starts the OLP
*/
virtual bool startOLP(const map<pair<Process,int>,int>& procs);
/**
* Return true, if this amplitude already includes averaging over
* incoming parton's quantum numbers.
*/
virtual bool hasInitialAverage() const { return true; }
/**
* Return true, if this amplitude already includes symmetry factors
* for identical outgoing particles.
*/
virtual bool hasFinalStateSymmetry() const { return true; }
/**
* Call OLP_EvalSubProcess and fill in the results
*/
void evalSubProcess() const;
/**
* Fill in results for the given colour correlator
*/
virtual void evalColourCorrelator(pair<int,int> ij) const;
/**
* Fill in results for the given colour/spin correlator
*/
virtual void evalSpinColourCorrelator(pair<int,int> ij) const;
/**
* Return the colour and spin correlated matrix element.
*/
virtual double spinColourCorrelatedME2(pair<int,int> ij,
const SpinCorrelationTensor& c) 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;
//@}
virtual void doinitrun();
// 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.
*/
OpenLoopsAmplitude & operator=(const OpenLoopsAmplitude &);
/**
* Store colour correlator results
*/
mutable vector<double> colourCorrelatorResults;
/**
* Store spin colour correlator results
*/
mutable vector<double> spinColourCorrelatorResults;
/**
* first is the olp id from herwig, second the answer from openloops
*/
mutable map< int , int > idpair;
/**
* Helper map to store information in different procs.
*/
map<int , OpenLoopsProcInfo > processmap;
/**
* Extra argument of BLHA2 to tell the Amplitude which OpenLoops installation to use.
*/
mutable string extraOpenLoopsPath;
/**
* Complex Mass Scheme.
*/
bool use_cms;
/**
* parameter to set Phase space tolerance for massiv particles.
* Should not be used. Better: set Openloops:Massless 11
*/
int psp_tolerance;
};
}
#endif /* Herwig_OpenLoopsAmplitude_H */
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,192 +1,192 @@
// -*- 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 "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) {
string vbfnlolib = DEFSTR(VBFNLOLIB);
vbfnlolib += "/";
if ( !DynamicLoader::load(vbfnlolib+"libVBFNLO.so") )
if ( !DynamicLoader::load("libVBFNLO.so") )
throw Exception() << "failed to load libVBFNLO.so\n"
<< DynamicLoader::lastErrorMessage
<< Exception::abortnow;
}
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);
// 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() << "VBFNLO failed to set parameter '"
<< name << "' to " << value << "\n"
<< Exception::abortnow;
}
}
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() << "negative weight in VBFNLOPhaseSpace\n"
<< Exception::abortnow;
}
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);
double masssq = p[4*i]*p[4*i]-p[4*i+1]*p[4*i+1]-p[4*i+2]*p[4*i+2]-p[4*i+3]*p[4*i+3];
if (masssq/p[4*i]*p[4*i] <= 1e-12) { // no abs: negative masssq always -> 0
momenta[i].setMass(0*GeV);
} else {
momenta[i].setMass(sqrt(masssq)*GeV);
}
}
delete p;
if ( !matchConstraints(momenta) )
return 0.;
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();
lastXCombPtr()->lastX1X2(make_pair(x1,x2));
lastXCombPtr()->lastSHat(thisSHat);
weight /= pow(thisSHat/GeV2,momenta.size()-4);
weight /= x1*x2;
fillDiagramWeights();
return weight;
}
-int VBFNLOPhasespace::nDim(int nFinal) const {
+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() << "cannot get phasespace dimension in VBFNLOPhaseSpace\n"
<< "error code: " << pStatus << "\n"
<< Exception::abortnow;
}
// one additional number (first) needed for channel selection
// one additional number (last) needed for global phi integration
return value+2;
}
// If needed, insert default implementations of virtual function defined
// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
void VBFNLOPhasespace::doinit() {
MatchboxPhasespace::doinit();
}
void VBFNLOPhasespace::doinitrun() {
MatchboxPhasespace::doinitrun();
}
void VBFNLOPhasespace::persistentOutput(PersistentOStream & os) const {
os << theLastXComb;
}
void VBFNLOPhasespace::persistentInput(PersistentIStream & is, int) {
is >> 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/External/VBFNLO/VBFNLOPhasespace.h b/MatrixElement/Matchbox/External/VBFNLO/VBFNLOPhasespace.h
--- a/MatrixElement/Matchbox/External/VBFNLO/VBFNLOPhasespace.h
+++ b/MatrixElement/Matchbox/External/VBFNLO/VBFNLOPhasespace.h
@@ -1,181 +1,181 @@
// -*- C++ -*-
//
// VBFNLOPhasespace.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_VBFNLOPhasespace_H
#define Herwig_VBFNLOPhasespace_H
//
// This is the declaration of the VBFNLOPhasespace class.
//
#include "Herwig++/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Michael Rauch
*
* \brief 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.
*
* @see \ref VBFNLOPhasespaceInterfaces "The interfaces"
* defined for VBFNLOPhasespace.
*/
class VBFNLOPhasespace: public MatchboxPhasespace {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
VBFNLOPhasespace();
/**
* The destructor.
*/
virtual ~VBFNLOPhasespace();
//@}
public:
/**
* Prepare a phase space generator for the given xcomb object.
*/
virtual void setXComb(tStdXCombPtr);
/**
* Generate a phase space point and return its weight.
*/
virtual double generateTwoToNKinematics(const double*,
vector<Lorentz5Momentum>& momenta);
/**
* Generate a phase space point and return its weight.
*/
virtual double generateKinematics(const double* random,
vector<Lorentz5Momentum>& momenta) {
return generateTwoToNKinematics(random,momenta);
}
/**
* Return the number of random numbers required to produce a given
* multiplicity final state.
*/
- virtual int nDim(int nFinal) const;
+ virtual int nDimPhasespace(int nFinal) const;
/**
* Return true, if this phasespace generator will generate incoming
* partons itself.
*/
virtual bool haveX1X2() const { return true; }
/**
* Return true, if this phase space generator expects
* the incoming partons in their center-of-mass system
*/
virtual bool wantCMS() const { return false; }
/**
* Return true, if this phase space generator is invertible
*/
virtual bool isInvertible() const { return false; }
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:
/** @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:
/**
* Last hadronic centre-of-mass energy, to update VBFNLO value only
* when this has changed.
*/
Energy lastSqrtS;
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
VBFNLOPhasespace & operator=(const VBFNLOPhasespace &);
};
}
#endif /* Herwig_VBFNLOPhasespace_H */
diff --git a/MatrixElement/Matchbox/InsertionOperators/DipoleIOperator.cc b/MatrixElement/Matchbox/InsertionOperators/DipoleIOperator.cc
--- a/MatrixElement/Matchbox/InsertionOperators/DipoleIOperator.cc
+++ b/MatrixElement/Matchbox/InsertionOperators/DipoleIOperator.cc
@@ -1,400 +1,402 @@
// -*- C++ -*-
//
// DipoleIOperator.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 DipoleIOperator class.
//
#include "DipoleIOperator.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/MatrixElement/Matchbox/Base/DipoleRepository.h"
#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.h"
using namespace Herwig;
using Constants::pi;
DipoleIOperator::DipoleIOperator()
: MatchboxInsertionOperator(),
CA(-1.0), CF(-1.0),
gammaQuark(-1.0), gammaGluon(-1.0),
betaZero(-1.),
KQuark(-1.0), KGluon(-1.0) {}
DipoleIOperator::~DipoleIOperator() {}
IBPtr DipoleIOperator::clone() const {
return new_ptr(*this);
}
IBPtr DipoleIOperator::fullclone() const {
return new_ptr(*this);
}
//////////////////////////////////////////////////////////////////////
bool DipoleIOperator::apply(const cPDVector& pd) const {
// DipoleIOperator should only apply if in the overall
// process only massless partons can occur.
// Prohibit splittings g->Q\bar{Q} in the final state.
// These are covered completely by DipoleMIOperator.
if ( NHeavyJetVec().size()!=0 ) {
return false;
}
bool first = false;
bool second = false;
for ( cPDVector::const_iterator p = pd.begin();
p != pd.end(); ++p ) {
// Since this loop only checks for at least one exis-
// ting combination: Return false if any massive par-
// tons are present (covered by DipoleMIOperator).
if ( (*p)->coloured() && (*p)->mass()!=ZERO ) {
return false;
}
if ( !first ) {
if ( apply(*p) )
first = true;
} else {
if ( apply(*p) )
second = true;
}
}
return first && second;
}
bool DipoleIOperator::apply(tcPDPtr pd) const {
return
pd->mass() == ZERO &&
(abs(pd->id()) < 7 || pd->id() == ParticleID::g);
}
void DipoleIOperator::setXComb(tStdXCombPtr xc) {
MatchboxInsertionOperator::setXComb(xc);
if ( CA < 0. ) {
CA = SM().Nc();
CF = (SM().Nc()*SM().Nc()-1.0)/(2.*SM().Nc());
gammaQuark = (3./2.)*CF;
- gammaGluon = (11./6.)*CA - (1./3.)*NLightJetVec().size();
+ // gammaGluon = (11./6.)*CA - (1./3.)*NLightJetVec().size();
+ gammaGluon = (11./6.)*CA - (1./3.)*lastBorn()->nLightJetVec().size();
betaZero = gammaGluon;
KQuark = (7./2.-sqr(pi)/6.)*CF;
- KGluon = (67./18.-sqr(pi)/6.)*CA-(5./9.)*NLightJetVec().size();
+ // KGluon = (67./18.-sqr(pi)/6.)*CA-(5./9.)*NLightJetVec().size();
+ KGluon = (67./18.-sqr(pi)/6.)*CA-(5./9.)*lastBorn()->nLightJetVec().size();
if ( isDR() ) {
gammaQuark -= CF/2.;
gammaGluon -= CA/6.;
}
}
}
//////////////////////////////////////////////////////////////////////
vector<int> DipoleIOperator::NLightJetVec() const {
// const map<string,PDVector>& theParticleGroups = MatchboxFactory::currentFactory()->particleGroups();
const map<string,PDVector>& theParticleGroups = factory()->particleGroups();
map<string,PDVector>::const_iterator theIt = theParticleGroups.find("j");
if ( theIt == theParticleGroups.end() )
throw Exception() << "DipoleIOperator::NLightJetVec(): Could not find a jet particle group named 'j'" << Exception::abortnow;
const PDVector& theJetConstitutents = theIt->second;
vector<int> theNLightJetVec;
for ( PDVector::const_iterator theP = theJetConstitutents.begin();
theP != theJetConstitutents.end(); ++theP ) {
if ( (**theP).id() > 0 && (**theP).id() < 7 && (**theP).mass() == ZERO )
theNLightJetVec.push_back( (**theP).id() );
}
return theNLightJetVec;
}
vector<int> DipoleIOperator::NHeavyJetVec() const {
// const map<string,PDVector>& theParticleGroups = MatchboxFactory::currentFactory()->particleGroups();
const map<string,PDVector>& theParticleGroups = factory()->particleGroups();
map<string,PDVector>::const_iterator theIt = theParticleGroups.find("j");
if ( theIt == theParticleGroups.end() )
throw Exception() << "DipoleIOperator::NHeavyJetVec(): Could not find a jet particle group named 'j'" << Exception::abortnow;
const PDVector& theJetConstitutents = theIt->second;
vector<int> theNHeavyJetVec;
for ( PDVector::const_iterator theP = theJetConstitutents.begin();
theP != theJetConstitutents.end(); ++theP ) {
if ( (**theP).id() > 0 && (**theP).id() < 7 && (**theP).mass() != ZERO )
theNHeavyJetVec.push_back( (**theP).id() );
}
return theNHeavyJetVec;
}
vector<int> DipoleIOperator::NLightBornVec() const {
// For the moment just count all quark and antiquark
// constituents in the Born process.
vector<int> theNLightBornVec;
for ( cPDVector::const_iterator j = mePartonData().begin();
j != mePartonData().end(); ++j ) {
if ( abs((**j).id()) < 7 && (**j).mass() == ZERO )
theNLightBornVec.push_back( (**j).id() );
}
return theNLightBornVec;
}
vector<int> DipoleIOperator::NHeavyBornVec() const {
// For the moment just count all quark and antiquark
// constituents in the Born process.
vector<int> theNHeavyBornVec;
for ( cPDVector::const_iterator j = mePartonData().begin();
j != mePartonData().end(); ++j ) {
if ( abs((**j).id()) < 7 && (**j).mass() != ZERO )
theNHeavyBornVec.push_back( (**j).id() );
}
return theNHeavyBornVec;
}
vector<int> DipoleIOperator::NLightProtonVec() const {
// const map<string,PDVector>& theParticleGroups = MatchboxFactory::currentFactory()->particleGroups();
const map<string,PDVector>& theParticleGroups = factory()->particleGroups();
map<string,PDVector>::const_iterator theIt = theParticleGroups.find("p");
if ( theIt == theParticleGroups.end() )
throw Exception() << "DipoleIOperator::NLightProtonVec(): Could not find a proton particle group named 'p'" << Exception::abortnow;
const PDVector& theProtonConstitutents = theIt->second;
vector<int> theNLightProtonVec;
for ( PDVector::const_iterator theP = theProtonConstitutents.begin();
theP != theProtonConstitutents.end(); ++theP ) {
if ( (**theP).id() > 0 && (**theP).id() < 7 && (**theP).mass() == ZERO )
theNLightProtonVec.push_back( (**theP).id() );
}
return theNLightProtonVec;
}
//////////////////////////////////////////////////////////////////////
double DipoleIOperator::me2() const {
double res = 0.;
int idi = 0; int idj = 0;
Energy2 mu2 = lastBorn()->mu2();
for ( cPDVector::const_iterator i = mePartonData().begin();
i != mePartonData().end(); ++i, ++idi ) {
if ( !apply(*i) )
continue;
idj = 0;
for ( cPDVector::const_iterator j = mePartonData().begin();
j != mePartonData().end(); ++j, ++idj ) {
if ( !apply(*j) )
continue;
if ( i == j || lastBorn()->noDipole(idi,idj) )
continue;
double delta = 0.;
double xgammaGluon = gammaGluon;
double xgammaQuark = gammaQuark;
if ( isDR() ) {
xgammaGluon += CA/6.;
xgammaQuark += CF/2.;
}
if ( isBDK() ) {
assert(!isCS() && !isExpanded());
delta =
((**i).id() == ParticleID::g ? xgammaGluon : xgammaQuark) *
log(mu2/(2.*(meMomenta()[idi]*meMomenta()[idj])));
if ( (idi < 2 && idj < 2) ||
(idi > 1 && idj > 1) )
delta +=
((**i).id() == ParticleID::g ? CA : CF) * sqr(pi) / 2.;
}
if ( isExpanded() ) {
assert(!isCS() && !isBDK());
double theLog = log(mu2/(2.*(meMomenta()[idi]*meMomenta()[idj])));
delta =
((**i).id() == ParticleID::g ? CA : CF) * 0.5 * sqr(theLog) +
((**i).id() == ParticleID::g ? xgammaGluon : xgammaQuark) * theLog;
}
res +=
( ((**i).id() == ParticleID::g ? CA : CF) * (-sqr(pi)/3.) +
((**i).id() == ParticleID::g ? gammaGluon : gammaQuark) +
((**i).id() == ParticleID::g ? KGluon : KQuark) +
delta ) *
lastBorn()->colourCorrelatedME2(make_pair(idi,idj));
}
}
// NOTE: In the following we account for the full scale restoration
// if \mu of the OLP differs from \mu_R.
// Note: In the GoSam OLP interface, it is possible to directly set
// \mu = \mu_R, via the switch SetMuToMuR (for debugging purposes).
Energy2 muR2 =
lastBorn()->renormalizationScale()*
sqr(lastBorn()->renormalizationScaleFactor());
if ( muR2 != mu2 ) {
res -=
betaZero *
lastBorn()->orderInAlphaS() * log(muR2/mu2) *
lastBorn()->me2();
}
// include the finite renormalization for DR here; ATTENTION this
// has to be mentioned in the manual! see hep-ph/9305239 for
// details; this guarantees an expansion in alpha_s^\bar{MS} when
// using dimensional reduction
if ( isDR() && isDRbar() ) {
res -= (CA/6.)*lastBorn()->orderInAlphaS()*lastBorn()->me2();
}
res *= ( - lastBorn()->lastAlphaS() / (2.*pi) );
return res;
}
double DipoleIOperator::oneLoopDoublePole() const {
if ( !isExpanded() )
return 0.;
double res = 0.;
for ( cPDVector::const_iterator i = mePartonData().begin();
i != mePartonData().end(); ++i ) {
if ( !apply(*i) )
continue;
res += (**i).id() == ParticleID::g ? CA : CF;
}
res *= ( - lastBorn()->lastAlphaS() / (2.*pi) ) * ( - lastBorn()->me2() );
return res;
}
double DipoleIOperator::oneLoopSinglePole() const {
if ( !isExpanded() )
return 0.;
double res = 0.;
int idi = 0; int idj = 0;
Energy2 mu2 = lastBorn()->mu2();
for ( cPDVector::const_iterator i = mePartonData().begin();
i != mePartonData().end(); ++i, ++idi ) {
if ( !apply(*i) )
continue;
idj = 0;
for ( cPDVector::const_iterator j = mePartonData().begin();
j != mePartonData().end(); ++j, ++idj ) {
if ( !apply(*j) )
continue;
if ( i == j || lastBorn()->noDipole(idi,idj) )
continue;
double xgammaGluon = gammaGluon;
double xgammaQuark = gammaQuark;
if ( isDR() ) {
xgammaGluon += CA/6.;
xgammaQuark += CF/2.;
}
double theLog = log(mu2/(2.*(meMomenta()[idi]*meMomenta()[idj])));
double delta =
((**i).id() == ParticleID::g ? CA : CF) * theLog +
((**i).id() == ParticleID::g ? xgammaGluon : xgammaQuark);
res +=
delta * lastBorn()->colourCorrelatedME2(make_pair(idi,idj));
}
}
res *= ( - lastBorn()->lastAlphaS() / (2.*pi) );
return res;
}
//////////////////////////////////////////////////////////////////////
void DipoleIOperator::persistentOutput(PersistentOStream & os) const {
os << CA << CF << gammaQuark << gammaGluon << betaZero
<< KQuark << KGluon;
}
void DipoleIOperator::persistentInput(PersistentIStream & is, int) {
is >> CA >> CF >> gammaQuark >> gammaGluon >> betaZero
>> KQuark >> KGluon;
}
// *** 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<DipoleIOperator,MatchboxInsertionOperator>
describeHerwigDipoleIOperator("Herwig::DipoleIOperator", "Herwig.so");
void DipoleIOperator::Init() {
static ClassDocumentation<DipoleIOperator> documentation
("DipoleIOperator");
DipoleRepository::registerInsertionIOperator<0,DipoleIOperator>("LightIOperator");
}
diff --git a/MatrixElement/Matchbox/InsertionOperators/DipoleMIOperator.cc b/MatrixElement/Matchbox/InsertionOperators/DipoleMIOperator.cc
--- a/MatrixElement/Matchbox/InsertionOperators/DipoleMIOperator.cc
+++ b/MatrixElement/Matchbox/InsertionOperators/DipoleMIOperator.cc
@@ -1,754 +1,762 @@
// -*- C++ -*-
//
// DipoleMIOperator.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 DipoleMIOperator class.
//
#include "DipoleMIOperator.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/MatrixElement/Matchbox/Base/DipoleRepository.h"
#include "ThePEG/PDT/DecayMode.h"
#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.h"
#include <gsl/gsl_sf_dilog.h>
using namespace Herwig;
using Constants::pi;
DipoleMIOperator::DipoleMIOperator()
: MatchboxInsertionOperator(),
CA(-1.0), CF(-1.0),
gammaQuark(-1.0), gammaGluon(-1.0),
betaZero(-1.),
KQuark(-1.0), KGluon(-1.0) {}
DipoleMIOperator::~DipoleMIOperator() {}
IBPtr DipoleMIOperator::clone() const {
return new_ptr(*this);
}
IBPtr DipoleMIOperator::fullclone() const {
return new_ptr(*this);
}
//////////////////////////////////////////////////////////////////////
bool DipoleMIOperator::apply(const cPDVector& pd) const {
// DipoleMIOperator should apply as soon as massive
// partons can occur in the overall process.
// DipoleIOperator should not apply then.
// A gluon in the Born final state can give rise to
// a splitting g->Q\bar{Q} in the real radiation.
// This can happen if massive partons are specified
// inside the jet (aka if the Born process does not
// exclude accompanying subprocesses with light par
// tons).
bool mFSet = false;
if ( NHeavyJetVec().size() != 0 ) {
mFSet = true;
}
// Partons in the initial state are massless in the CS
// approach:
// The following loop checks for at least one existing
// combination (note that the single apply function is
// not checking for massless condition) 'n in addition
// for at least one massive parton in the final state,
// 'n for only massless partons in the initial state.
bool first = false;
bool second = false;
bool finalmass = false;
bool initialmass = false;
int idp = 0;
for ( cPDVector::const_iterator p = pd.begin();
p != pd.end(); ++p, ++idp ) {
if ( (*p)->coloured() && (*p)->mass()!=ZERO && idp > 1 ) {
finalmass = true;
}
if ( (*p)->coloured() && (*p)->mass()!=ZERO && idp < 2 ) {
initialmass = true;
}
if ( !first ) {
if ( apply(*p) ) {
first = true;
}
} else {
if ( apply(*p) ) {
second = true;
}
}
}
return first && second && (finalmass || mFSet) && !initialmass;
}
bool DipoleMIOperator::apply(tcPDPtr pd) const {
return
(abs(pd->id()) < 7 || pd->id() == ParticleID::g);
}
void DipoleMIOperator::setXComb(tStdXCombPtr xc) {
MatchboxInsertionOperator::setXComb(xc);
if ( CA < 0. ) {
CA = SM().Nc();
CF = (SM().Nc()*SM().Nc()-1.0)/(2.*SM().Nc());
gammaQuark = (3./2.)*CF;
- gammaGluon = (11./6.)*CA - (1./3.)*NLightJetVec().size();
- betaZero = (11./6.)*CA - (1./3.)*(NLightJetVec().size()+NHeavyJetVec().size());
+ // gammaGluon = (11./6.)*CA - (1./3.)*NLightJetVec().size();
+ // betaZero = (11./6.)*CA - (1./3.)*(NLightJetVec().size()+NHeavyJetVec().size());
+ gammaGluon = (11./6.)*CA - (1./3.)*lastBorn()->nLightJetVec().size();
+ betaZero = (11./6.)*CA - (1./3.)*(lastBorn()->nLightJetVec().size()+lastBorn()->nHeavyJetVec().size());
KQuark = (7./2.-sqr(pi)/6.)*CF;
- KGluon = (67./18.-sqr(pi)/6.)*CA-(5./9.)*NLightJetVec().size();
+ // KGluon = (67./18.-sqr(pi)/6.)*CA-(5./9.)*NLightJetVec().size();
+ KGluon = (67./18.-sqr(pi)/6.)*CA-(5./9.)*lastBorn()->nLightJetVec().size();
}
}
//////////////////////////////////////////////////////////////////////
vector<int> DipoleMIOperator::NLightJetVec() const {
// const map<string,PDVector>& theParticleGroups = MatchboxFactory::currentFactory()->particleGroups();
const map<string,PDVector>& theParticleGroups = factory()->particleGroups();
map<string,PDVector>::const_iterator theIt = theParticleGroups.find("j");
if ( theIt == theParticleGroups.end() )
throw Exception() << "DipoleMIOperator::NLightJetVec(): Could not find a jet particle group named 'j'" << Exception::abortnow;
const PDVector& theJetConstitutents = theIt->second;
vector<int> theNLightJetVec;
for ( PDVector::const_iterator theP = theJetConstitutents.begin();
theP != theJetConstitutents.end(); ++theP ) {
if ( (**theP).id() > 0 && (**theP).id() < 7 && (**theP).mass() == ZERO )
theNLightJetVec.push_back( (**theP).id() );
}
return theNLightJetVec;
}
vector<int> DipoleMIOperator::NHeavyJetVec() const {
// const map<string,PDVector>& theParticleGroups = MatchboxFactory::currentFactory()->particleGroups();
const map<string,PDVector>& theParticleGroups = factory()->particleGroups();
map<string,PDVector>::const_iterator theIt = theParticleGroups.find("j");
if ( theIt == theParticleGroups.end() )
throw Exception() << "DipoleMIOperator::NHeavyJetVec(): Could not find a jet particle group named 'j'" << Exception::abortnow;
const PDVector& theJetConstitutents = theIt->second;
vector<int> theNHeavyJetVec;
for ( PDVector::const_iterator theP = theJetConstitutents.begin();
theP != theJetConstitutents.end(); ++theP ) {
if ( (**theP).id() > 0 && (**theP).id() < 7 && (**theP).mass() != ZERO )
theNHeavyJetVec.push_back( (**theP).id() );
}
return theNHeavyJetVec;
}
vector<int> DipoleMIOperator::NLightBornVec() const {
// For the moment just count all quark and antiquark
// constituents in the Born process.
vector<int> theNLightBornVec;
for ( cPDVector::const_iterator j = mePartonData().begin();
j != mePartonData().end(); ++j ) {
if ( abs((**j).id()) < 7 && (**j).mass() == ZERO )
theNLightBornVec.push_back( (**j).id() );
}
return theNLightBornVec;
}
vector<int> DipoleMIOperator::NHeavyBornVec() const {
// For the moment just count all quark and antiquark
// constituents in the Born process.
vector<int> theNHeavyBornVec;
for ( cPDVector::const_iterator j = mePartonData().begin();
j != mePartonData().end(); ++j ) {
if ( abs((**j).id()) < 7 && (**j).mass() != ZERO )
theNHeavyBornVec.push_back( (**j).id() );
}
return theNHeavyBornVec;
}
vector<int> DipoleMIOperator::NLightProtonVec() const {
// const map<string,PDVector>& theParticleGroups = MatchboxFactory::currentFactory()->particleGroups();
const map<string,PDVector>& theParticleGroups = factory()->particleGroups();
map<string,PDVector>::const_iterator theIt = theParticleGroups.find("p");
if ( theIt == theParticleGroups.end() )
throw Exception() << "DipoleMIOperator::NLightProtonVec(): Could not find a proton particle group named 'p'" << Exception::abortnow;
const PDVector& theProtonConstitutents = theIt->second;
vector<int> theNLightProtonVec;
for ( PDVector::const_iterator theP = theProtonConstitutents.begin();
theP != theProtonConstitutents.end(); ++theP ) {
if ( (**theP).id() > 0 && (**theP).id() < 7 && (**theP).mass() == ZERO )
theNLightProtonVec.push_back( (**theP).id() );
}
return theNLightProtonVec;
}
//////////////////////////////////////////////////////////////////////
double DipoleMIOperator::me2() const {
if ( !isExpanded() )
throw InitException() << "DipoleMIOperator only implemented in the expanded convention.";
if ( isDR() )
throw InitException() << "DipoleMIOperator not implemented for dimensional reduction.";
Energy2 mu2 = lastBorn()->mu2();
double kappa=0.;
bool appendixB = true;
// Note: We are using a parametrization where we keep s_{ja'}=2p_jp_a' fixed,
// rather than s_{ja}=2p_jp_a, due to the substitution \eta->x/z and the sub-
// sequent shift of the z-dependence from the hard Born ME into the PDF.
// Thus we need to make sure to keep the right kinematic variable fixed while
// performig the z-integration, i.e. s_{ja'} in our case. This is partly des-
// cribed in appendix B of the massive CS paper, but also in the last term of
// eq. (6.55) in the massive CS paper we need to consider that s_{ja'} is our
// fixed variable and not s_{ja}.
// This also means that in the sum over heavy quark flavours, in the g->QQbar
// contributions, we need to sum over N_F and not just N_F^{ja} (see appendix
// B in the massive CS paper, last sentence on p. 51 in arXiv:hep-ph/0201036)
// which is important for the massive I operator here but especially for the
// massive PK operator.
double res = 0.;
int idj = 0; int idk = 0;
// j is emitter, k is spectator
for ( cPDVector::const_iterator j = mePartonData().begin();
j != mePartonData().end(); ++j, ++idj ) {
if ( !apply(*j) ) {
continue;
}
if ( apply(*j) && idj < 2 && (**j).mass() != ZERO )
throw InitException() << "DipoleMIOperator: Initial state partons must not be massive!";
idk = 0;
for ( cPDVector::const_iterator k = mePartonData().begin();
k != mePartonData().end(); ++k, ++idk ) {
if ( !apply(*k) ) {
continue;
}
if ( j == k || lastBorn()->noDipole(idj,idk) ) {
continue;
}
if ( apply(*k) && idk < 2 && (**k).mass() != ZERO )
throw InitException() << "DipoleMIOperator: Initial state partons must not be massive!";
double delta = 0.0;
Energy2 sjk = 2.*meMomenta()[idj]*meMomenta()[idk];
if ( idj > 1 ) { // Involves idk > 1 as well as idk < 2
delta +=
( ((**j).id() == ParticleID::g ? CA : CF) *
( Vj(**j,**k,sjk,kappa,appendixB) - sqr(pi)/3. ) +
((**j).id() == ParticleID::g ? GammaGluon() : GammaQuark(**j)) +
((**j).id() == ParticleID::g ? gammaGluon : gammaQuark) * (1 + log(mu2/sjk)) +
((**j).id() == ParticleID::g ? KGluon : KQuark) );
}
if ( idj < 2 && idk > 1 ) {
delta +=
( ((**j).id() == ParticleID::g ? CA : CF) *
( Vj(**j,**k,sjk,2./3.,appendixB,true) - sqr(pi)/3. ) +
((**j).id() == ParticleID::g ? gammaGluon : gammaQuark) * (1 + log(mu2/sjk)) +
((**j).id() == ParticleID::g ? KGluon : KQuark) );
}
// If j and k are incoming, same contribution as in DipoleIOperator.
// Master apply prevents the DipoleIOperator though from applying in
// case of at least one massive parton in the overall process.
// So, need to add the expanded finite term for initial-initial cor-
// relations here (DipoleMIOperator) as well.
if ( idj < 2 && idk < 2 ) {
delta += ( ((**j).id() == ParticleID::g ? CA : CF) * ( -1.*sqr(pi)/3. + 1./2.*log(mu2/sjk)*log(mu2/sjk) ) +
((**j).id() == ParticleID::g ? gammaGluon : gammaQuark) * ( 1. + log(mu2/sjk) ) +
((**j).id() == ParticleID::g ? KGluon : KQuark) );
}
delta *= lastBorn()->colourCorrelatedME2(make_pair(idj,idk));
res += delta;
}
}
// NOTE: In the following we account for the full scale restoration
// if \mu of the OLP differs from \mu_R - same as in massless case.
// Note: In the GoSam OLP interface, it is possible to directly set
// \mu = \mu_R, via the switch SetMuToMuR (for debugging purposes).
Energy2 muR2 =
lastBorn()->renormalizationScale()*
sqr(lastBorn()->renormalizationScaleFactor());
if ( muR2 != mu2 ) {
res -=
betaZero *
lastBorn()->orderInAlphaS() * log(muR2/mu2) *
lastBorn()->me2();
}
// // include the finite renormalization for DR here; ATTENTION this
// // has to be mentioned in the manual! see hep-ph/9305239 for
// // details; this guarantees an expansion in alpha_s^\bar{MS} when
// // using dimensional reduction
// if ( isDR() && isDRbar() )
// res -= (CA/6.)*lastBorn()->orderInAlphaS()*lastBorn()->me2();
res *= ( - lastBorn()->lastAlphaS() / (2.*pi) );
return res;
}
double DipoleMIOperator::oneLoopDoublePole() const {
if ( !isExpanded() )
throw InitException() << "DipoleMIOperator only implemented in the expanded convention.";
if ( isDR() )
throw InitException() << "DipoleMIOperator not implemented for dimensional reduction.";
double res = 0.;
int idj = 0; int idk = 0;
// j is emitter, k is spectator
for ( cPDVector::const_iterator j = mePartonData().begin();
j != mePartonData().end(); ++j, ++idj ) {
if ( !apply(*j) ) {
continue;
}
if ( apply(*j) && idj < 2 && (**j).mass() != ZERO )
throw InitException() << "DipoleMIOperator: Initial state partons must not be massive!";
idk = 0;
for ( cPDVector::const_iterator k = mePartonData().begin();
k != mePartonData().end(); ++k, ++idk ) {
if ( !apply(*k) ) {
continue;
}
if ( j == k || lastBorn()->noDipole(idj,idk) ) {
continue;
}
if ( apply(*k) && idk < 2 && (**k).mass() != ZERO )
throw InitException() << "DipoleMIOperator: Initial state partons must not be massive!";
double delta = 0.0;
if (idj>1) { // Involves idk > 1 as well as idk < 2
delta += ( (**j).id() == ParticleID::g ? CA : CF ) * VsDoublePole(**j,**k);
}
else if (idj<2 && idk>1) {
delta += ( (**j).id() == ParticleID::g ? CA : CF ) * VsDoublePole(**j,**k);
}
else if (idj<2 && idk<2) {
delta += ( (**j).id() == ParticleID::g ? CA : CF );
}
delta *= lastBorn()->colourCorrelatedME2(make_pair(idj,idk));
res += delta;
}
}
res *= ( - lastBorn()->lastAlphaS() / (2.*pi) );
return res;
}
double DipoleMIOperator::oneLoopSinglePole() const {
if ( !isExpanded() )
throw InitException() << "DipoleMIOperator only implemented in the expanded convention.";
if ( isDR() )
throw InitException() << "DipoleMIOperator not implemented for dimensional reduction.";
Energy2 mu2 = lastBorn()->mu2();
double res = 0.;
int idj = 0; int idk = 0;
// j is emitter, k is spectator
for ( cPDVector::const_iterator j = mePartonData().begin();
j != mePartonData().end(); ++j, ++idj ) {
if ( !apply(*j) ) {
continue;
}
if ( apply(*j) && idj < 2 && (**j).mass() != ZERO )
throw InitException() << "DipoleMIOperator: Initial state partons must not be massive!";
idk = 0;
for ( cPDVector::const_iterator k = mePartonData().begin();
k != mePartonData().end(); ++k, ++idk ) {
if ( !apply(*k) ) {
continue;
}
if ( j == k || lastBorn()->noDipole(idj,idk) ) {
continue;
}
if ( apply(*k) && idk < 2 && (**k).mass() != ZERO )
throw InitException() << "DipoleMIOperator: Initial state partons must not be massive!";
double delta = 0.0;
Energy2 sjk = 2.*meMomenta()[idj]*meMomenta()[idk];
if (idj>1) { // Involves idk > 1 as well as idk < 2
delta += ( (**j).id() == ParticleID::g ? CA : CF ) * VsSinglePole(**j,**k,sjk);
delta += ( (**j).id() == ParticleID::g ? GammaGluonSinglePole() : GammaQuarkSinglePole(**j) );
}
else if (idj<2 && idk>1) {
delta += ( (**j).id() == ParticleID::g ? CA : CF ) * VsSinglePole(**j,**k,sjk);
delta += ( (**j).id() == ParticleID::g ? gammaGluon : gammaQuark );
}
else if (idj<2 && idk<2) {
delta += ( (**j).id() == ParticleID::g ? CA : CF ) * log(mu2/sjk);
delta += ( (**j).id() == ParticleID::g ? gammaGluon : gammaQuark );
}
delta *= lastBorn()->colourCorrelatedME2(make_pair(idj,idk));
res += delta;
}
}
res *= ( - lastBorn()->lastAlphaS() / (2.*pi) );
return res;
}
//////////////////////////////////////////////////////////////////////
double DipoleMIOperator::Vj(const ParticleData& j, const ParticleData& k,
Energy2 sjk, double kappa, bool appendixB,
bool mFSetEmpty) const {
Energy2 mu2 = lastBorn()->mu2();
double res = 0.;
// sjk is being handed over as input parameter to DipoleMIOperator::Vj()
// kappa is being handed over as input parameter to DipoleMIOperator::Vj()
Energy2 mj2 = sqr(j.mass()), mk2 = sqr(k.mass());
Energy mj = j.mass(), mk = k.mass();
Energy2 Qjk2 = sjk + mj2 + mk2;
Energy Qjk = sqrt(Qjk2);
double vjk = rootOfKallen(Qjk2,mj2,mk2) / sjk;
double rho = sqrt( abs(1.-vjk)/(1.+vjk) ); // abs() because for small mass 1.-vjk can get O(-1.e-16)
double rhoj = sqrt( ( 1. - vjk + 2.*mj2/Qjk2 / (1.-mj2/Qjk2-mk2/Qjk2) ) /
( 1. + vjk + 2.*mj2/Qjk2 / (1.-mj2/Qjk2-mk2/Qjk2) ) );
double rhok = sqrt( ( 1. - vjk + 2.*mk2/Qjk2 / (1.-mj2/Qjk2-mk2/Qjk2) ) /
( 1. + vjk + 2.*mk2/Qjk2 / (1.-mj2/Qjk2-mk2/Qjk2) ) );
//////////////////////////////////////
// Finite terms of S part (6.20) //
// Expanded convention //
//////////////////////////////////////
ParticleData l = ( mj2 == ZERO ? k : j );
// both masses zero
if( mj2 == ZERO && mk2 == ZERO ) {
res += 0.0;
// Expanded
res += 1./2.*log(mu2/sjk)*log(mu2/sjk);
}
// one mass zero
else if( mj2 == ZERO || mk2 == ZERO ) {
Energy2 m2 = sqr(l.mass());
res += -1./4.*sqr(log(m2/sjk)) - sqr(pi)/12. -
1./2.*log(m2/sjk)*log(sjk/Qjk2) - 1./2.*log(m2/Qjk2)*log(sjk/Qjk2);
// Expanded
res += 1./2.*log(mu2/sjk)*log(m2/sjk) +
1./4.*log(mu2/sjk)*log(mu2/sjk);
}
// no mass zero
else if( mj2 != ZERO && mk2 != ZERO ) {
res += 1./vjk * ( -1./4.*sqr(log(rhoj*rhoj)) - 1./4.*sqr(log(rhok*rhok)) -
sqr(pi)/6. + ( rho==0. ? 0. : log(rho)*log(Qjk2/sjk) ) );
// Expanded
res += 1./vjk * ( rho==0. ? 0. : log(rho)*log(mu2/sjk) );
}
//////////////////////////////////////
// NS part (6.21)-(6.26) //
//////////////////////////////////////
// V_q (j is quark)
// j is massive quark
if( mj2 != ZERO ) {
assert( abs(j.id()) < 7);
// common part iff j is massive quark and k either massive quark
// or massless parton (6.21),(6.22)
res += gammaQuark/CF * log(sjk/Qjk2);
// k is massive quark (6.21)
if( mk2 != ZERO ) {
assert( abs(k.id()) < 7);
res += 1./vjk * ( ( rho==0. ? 0. : log(rho*rho)*log(1.+rho*rho) ) + 2.*gsl_sf_dilog(rho*rho) -
gsl_sf_dilog(1.-rhoj*rhoj) - gsl_sf_dilog(1.-rhok*rhok) - sqr(pi)/6. ) +
log((Qjk-mk)/Qjk) - 2.*log((sqr(Qjk-mk)-mj2)/Qjk2) - 2.*mj2/sjk*log(mj/(Qjk-mk)) -
mk/(Qjk-mk) + 2.*mk*(2.*mk-Qjk)/sjk + sqr(pi)/2.;
}
// k is massless parton (6.22)
else {
res += sqr(pi)/6. - gsl_sf_dilog(sjk/Qjk2) -
2.*log(sjk/Qjk2) - mj2/sjk*log(mj2/Qjk2);
}
}
// V_j (j either massless quark (6.23) or gluon (6.24),(6.26))
else {
// k is massless parton
if( mk == ZERO ) {
// only contributes if j is gluon (6.26)
if( j.id() == ParticleID::g ) {
// sum over all quark flavours
if( !mFSetEmpty )
- for( size_t f=0; f<NHeavyJetVec().size(); ++f ) { // only heavy quarks in jet (aka g->QQbar at NLO)
- Energy2 mF2 = sqr( getParticleData(NHeavyJetVec()[f])->mass() );
+ // for( size_t f=0; f<NHeavyJetVec().size(); ++f ) { // only heavy quarks in jet (aka g->QQbar at NLO)
+ // Energy2 mF2 = sqr( getParticleData(NHeavyJetVec()[f])->mass() );
+ for( size_t f=0; f<lastBorn()->nHeavyJetVec().size(); ++f ) { // only heavy quarks in jet (aka g->QQbar at NLO)
+ Energy2 mF2 = sqr( getParticleData(lastBorn()->nHeavyJetVec()[f])->mass() );
// sum only over quarks which meet special condition
// but not if method of appendix B is used (see note
// at the end of appendix B)
if( !appendixB && sjk <= 4.*sqrt(mF2)*(sqrt(mF2)+mk) )
continue;
double rho1 = sqrt( 1. - 4.*mF2 / sqr(Qjk-mk) );
res += 2./3./CA * ( log((1.+rho1)/2.) - rho1/3.*(3.+sqr(rho1)) - 0.5*log(mF2/sjk) );
}
// The last term with Q_{aux} in (6.26) cancels against a similar term in GammaGluon().
}
}
// k is massive quark
else {
assert( abs(k.id()) < 7);
// part common to j massless quark or gluon (6.23),(6.24)
res += sqr(pi)/6. - gsl_sf_dilog(sjk/Qjk2);
// j is massless quark (6.23)
if( abs(j.id()) < 7)
res += gammaQuark/CF * ( log(sjk/Qjk2) - 2.*log((Qjk-mk)/Qjk) - 2.*mk/(Qjk+mk) );
// j is gluon (6.24)
else if( j.id() == ParticleID::g ) {
// part independent of other heavy quark flavours
res += gammaGluon/CA * ( log(sjk/Qjk2) - 2.*log((Qjk-mk)/Qjk) - 2.*mk/(Qjk+mk) ) +
- (kappa-2./3.) * mk2/sjk * (1./CA*NLightJetVec().size()-1.) * log(2.*mk/(Qjk+mk));
+ // (kappa-2./3.) * mk2/sjk * (1./CA*NLightJetVec().size()-1.) * log(2.*mk/(Qjk+mk));
+ (kappa-2./3.) * mk2/sjk * (1./CA*lastBorn()->nLightJetVec().size()-1.) * log(2.*mk/(Qjk+mk));
// part containing other heavy quark flavours
if( !mFSetEmpty )
- for( size_t f=0; f<NHeavyJetVec().size(); ++f ) { // only heavy quarks in jet (aka g->QQbar at NLO)
- Energy2 mF2 = sqr( getParticleData(NHeavyJetVec()[f])->mass() );
+ // for( size_t f=0; f<NHeavyJetVec().size(); ++f ) { // only heavy quarks in jet (aka g->QQbar at NLO)
+ // Energy2 mF2 = sqr( getParticleData(NHeavyJetVec()[f])->mass() );
+ for( size_t f=0; f<lastBorn()->nHeavyJetVec().size(); ++f ) { // only heavy quarks in jet (aka g->QQbar at NLO)
+ Energy2 mF2 = sqr( getParticleData(lastBorn()->nHeavyJetVec()[f])->mass() );
// sum only over quarks which meet special condition
// but not if method of appendix B is used (see note
// at the end of appendix B)
if( !appendixB && sjk <= 4.*sqrt(mF2)*(sqrt(mF2)+mk) )
continue;
double rho1 = sqrt( 1. - 4.*mF2 / sqr(Qjk-mk) );
double rho2 = sqrt( 1. - 4.*mF2 / (Qjk2-mk2) );
res += 2./3./CA * ( log((Qjk-mk)/Qjk) + mk*rho1*rho1*rho1/(Qjk+mk) + log((1.+rho1)/2.) -
rho1/3.*(3.+sqr(rho1)) - 1./2.*log(mF2/Qjk2) ) +
1./CA * ( rho2*rho2*rho2*log((rho2-rho1)/(rho2+rho1)) - log((1.-rho1)/(1.+rho1)) -
8.*rho1*mF2/sjk ) * (kappa-2./3.) * mk2/sjk;
}
// The term with Q_{aux} in (6.24) cancels against a similar term in GammaGluon().
}
}
}
return res;
}
double DipoleMIOperator::VsDoublePole(const ParticleData& j, const ParticleData& k) const {
double res = 0.;
////////////////////////////////////////////////
// Double pole coefficient of S part (6.20) //
// Expanded convention //
////////////////////////////////////////////////
Energy2 mj2 = sqr(j.mass()), mk2 = sqr(k.mass());
// both masses zero
if( mj2 == ZERO && mk2 == ZERO ) {
res += 1.0;
}
// one mass zero
else if( mj2 == ZERO || mk2 == ZERO ) {
res += 1./2.;
}
// no mass zero
else if( mj2 != ZERO && mk2 != ZERO ) {
res += 0.0;
}
return res;
}
double DipoleMIOperator::VsSinglePole(const ParticleData& j, const ParticleData& k,
Energy2 sjk) const {
Energy2 mu2 = lastBorn()->mu2();
double res = 0.;
// sjk is being handed over as input parameter to DipoleMIOperator::VsDoublePole()
Energy2 mj2 = sqr(j.mass()), mk2 = sqr(k.mass());
Energy2 Qjk2 = sjk + mj2 + mk2;
double vjk = rootOfKallen(Qjk2,mj2,mk2) / sjk;
double rho = sqrt( abs(1.-vjk)/(1.+vjk) ); // abs() because for small mass 1.-vjk can get O(-1.e-16)
////////////////////////////////////////////////
// Single pole coefficient of S part (6.20) //
// Expanded convention //
////////////////////////////////////////////////
ParticleData l = ( mj2 == ZERO ? k : j );
// both masses zero
if( mj2 == ZERO && mk2 == ZERO ) {
res += log(mu2/sjk);
}
// one mass zero
else if( mj2 == ZERO || mk2 == ZERO ) {
Energy2 m2 = sqr(l.mass());
res += 1./2.*(log(mu2/sjk) + log(m2/sjk));
}
// no mass zero
else if( mj2 != ZERO && mk2 != ZERO ) {
res += 1./vjk * ( rho==0. ? 0. : log(rho) );
}
return res;
}
double DipoleMIOperator::GammaQuark(const ParticleData& j) const {
if ( j.mass() == ZERO )
return 0.;
Energy2 mu2 = lastBorn()->mu2();
return CF * ( 0.5*log(sqr(j.mass())/mu2) - 2. );
}
double DipoleMIOperator::GammaGluon() const {
// Finite contribution cancels with similar contribution in VjNS.
return 0.;
}
double DipoleMIOperator::GammaQuarkSinglePole(const ParticleData& j) const {
if ( j.mass() == ZERO ) {
return gammaQuark;
}
return CF;
}
double DipoleMIOperator::GammaGluonSinglePole() const {
return gammaGluon;
}
//////////////////////////////////////////////////////////////////////
void DipoleMIOperator::persistentOutput(PersistentOStream & os) const {
os << CA << CF << gammaQuark << gammaGluon << betaZero
<< KQuark << KGluon;
}
void DipoleMIOperator::persistentInput(PersistentIStream & is, int) {
is >> CA >> CF >> gammaQuark >> gammaGluon >> betaZero
>> KQuark >> KGluon;
}
// *** 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<DipoleMIOperator,MatchboxInsertionOperator>
describeHerwigDipoleMIOperator("Herwig::DipoleMIOperator", "Herwig.so");
void DipoleMIOperator::Init() {
static ClassDocumentation<DipoleMIOperator> documentation
("DipoleMIOperator");
DipoleRepository::registerInsertionIOperator<0,DipoleMIOperator>("MassiveIOperator");
}
diff --git a/MatrixElement/Matchbox/InsertionOperators/DipoleMPKOperator.cc b/MatrixElement/Matchbox/InsertionOperators/DipoleMPKOperator.cc
--- a/MatrixElement/Matchbox/InsertionOperators/DipoleMPKOperator.cc
+++ b/MatrixElement/Matchbox/InsertionOperators/DipoleMPKOperator.cc
@@ -1,1226 +1,1248 @@
// -*- C++ -*-
//
// DipoleMPKOperator.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 DipoleMPKOperator class.
//
#include "DipoleMPKOperator.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Utilities/Rebinder.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/MatrixElement/Matchbox/Base/DipoleRepository.h"
#include "Herwig++/MatrixElement/Matchbox/Phasespace/RandomHelpers.h"
#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.h"
#include <gsl/gsl_sf_dilog.h>
using namespace Herwig;
using Constants::pi;
DipoleMPKOperator::DipoleMPKOperator()
: MatchboxInsertionOperator(),
CA(-1.0), CF(-1.0),
gammaQuark(-1.0), gammaGluon(-1.0),
KQuark(-1.0), KGluon(-1.0) {}
DipoleMPKOperator::~DipoleMPKOperator() {}
IBPtr DipoleMPKOperator::clone() const {
return new_ptr(*this);
}
IBPtr DipoleMPKOperator::fullclone() const {
return new_ptr(*this);
}
//////////////////////////////////////////////////////////////////////
bool DipoleMPKOperator::apply(const cPDVector& pd) const {
// DipoleMPKOperator should apply as soon as massive
// partons can occur in the overall process.
// DipolePKOperator should not apply then.
if ( !apply(pd[0]) && !apply(pd[1]) ) {
return false;
}
// A gluon in the Born final state can give rise to
// a splitting g->Q\bar{Q} in the real radiation.
// This can happen if massive partons are specified
// inside the jet (aka if the Born process does not
// exclude accompanying subprocesses with light par
// tons).
bool mFSet = false;
if ( NHeavyJetVec().size() != 0 ) {
mFSet = true;
}
// Partons in the initial state are massless in the CS
// approach:
// The following loop checks for at least one existing
// combination 'n in addition for at least one massive
// parton in the final state 'n for only massless par-
// tons in the initial state.
bool first = false;
bool second = false;
bool finalmass = false;
bool initialmass = false;
int idp = 0;
for ( cPDVector::const_iterator p = pd.begin();
p != pd.end(); ++p, ++idp ) {
if ( (*p)->coloured() && (*p)->mass()!=ZERO && idp > 1 ) {
finalmass = true;
}
if ( (*p)->coloured() && (*p)->mass()!=ZERO && idp < 2 ) {
initialmass = true;
}
if ( !first ) {
if ( applyNotMassless(*p) ) {
first = true;
}
} else {
if ( applyNotMassless(*p) ) {
second = true;
}
}
}
return first && second && (finalmass || mFSet) && !initialmass;
}
bool DipoleMPKOperator::apply(tcPDPtr pd) const {
return
pd->mass() == ZERO &&
(abs(pd->id()) < 7 || pd->id() == ParticleID::g);
}
bool DipoleMPKOperator::applyNotMassless(tcPDPtr pd) const {
return
(abs(pd->id()) < 7 || pd->id() == ParticleID::g);
}
void DipoleMPKOperator::setXComb(tStdXCombPtr xc) {
MatchboxInsertionOperator::setXComb(xc);
if ( CA < 0. ) {
CA = SM().Nc();
CF = (SM().Nc()*SM().Nc()-1.0)/(2.*SM().Nc());
gammaQuark = (3./2.)*CF;
- gammaGluon = (11./6.)*CA - (1./3.)*NLightJetVec().size();
+ // gammaGluon = (11./6.)*CA - (1./3.)*NLightJetVec().size();
+ gammaGluon = (11./6.)*CA - (1./3.)*lastBorn()->nLightJetVec().size();
KQuark = (7./2.-sqr(pi)/6.)*CF;
- KGluon = (67./18.-sqr(pi)/6.)*CA-(5./9.)*NLightJetVec().size();
+ // KGluon = (67./18.-sqr(pi)/6.)*CA-(5./9.)*NLightJetVec().size();
+ KGluon = (67./18.-sqr(pi)/6.)*CA-(5./9.)*lastBorn()->nLightJetVec().size();
}
}
//////////////////////////////////////////////////////////////////////
vector<int> DipoleMPKOperator::NLightJetVec() const {
// const map<string,PDVector>& theParticleGroups = MatchboxFactory::currentFactory()->particleGroups();
const map<string,PDVector>& theParticleGroups = factory()->particleGroups();
map<string,PDVector>::const_iterator theIt = theParticleGroups.find("j");
if ( theIt == theParticleGroups.end() )
throw Exception() << "DipolePKOperator::NLightJetVec(): Could not find a jet particle group named 'j'" << Exception::abortnow;
const PDVector& theJetConstitutents = theIt->second;
vector<int> theNLightJetVec;
for ( PDVector::const_iterator theP = theJetConstitutents.begin();
theP != theJetConstitutents.end(); ++theP ) {
if ( (**theP).id() > 0 && (**theP).id() < 7 && (**theP).mass() == ZERO )
theNLightJetVec.push_back( (**theP).id() );
}
return theNLightJetVec;
}
vector<int> DipoleMPKOperator::NHeavyJetVec() const {
// const map<string,PDVector>& theParticleGroups = MatchboxFactory::currentFactory()->particleGroups();
const map<string,PDVector>& theParticleGroups = factory()->particleGroups();
map<string,PDVector>::const_iterator theIt = theParticleGroups.find("j");
if ( theIt == theParticleGroups.end() )
throw Exception() << "DipolePKOperator::NHeavyJetVec(): Could not find a jet particle group named 'j'" << Exception::abortnow;
const PDVector& theJetConstitutents = theIt->second;
vector<int> theNHeavyJetVec;
for ( PDVector::const_iterator theP = theJetConstitutents.begin();
theP != theJetConstitutents.end(); ++theP ) {
if ( (**theP).id() > 0 && (**theP).id() < 7 && (**theP).mass() != ZERO )
theNHeavyJetVec.push_back( (**theP).id() );
}
return theNHeavyJetVec;
}
vector<int> DipoleMPKOperator::NLightBornVec() const {
// For the moment just count all quark and antiquark
// constituents in the Born process.
vector<int> theNLightBornVec;
for ( cPDVector::const_iterator j = mePartonData().begin();
j != mePartonData().end(); ++j ) {
if ( abs((**j).id()) < 7 && (**j).mass() == ZERO )
theNLightBornVec.push_back( (**j).id() );
}
return theNLightBornVec;
}
vector<int> DipoleMPKOperator::NHeavyBornVec() const {
// For the moment just count all quark and antiquark
// constituents in the Born process.
vector<int> theNHeavyBornVec;
for ( cPDVector::const_iterator j = mePartonData().begin();
j != mePartonData().end(); ++j ) {
if ( abs((**j).id()) < 7 && (**j).mass() != ZERO )
theNHeavyBornVec.push_back( (**j).id() );
}
return theNHeavyBornVec;
}
vector<int> DipoleMPKOperator::NLightProtonVec() const {
// const map<string,PDVector>& theParticleGroups = MatchboxFactory::currentFactory()->particleGroups();
const map<string,PDVector>& theParticleGroups = factory()->particleGroups();
map<string,PDVector>::const_iterator theIt = theParticleGroups.find("p");
if ( theIt == theParticleGroups.end() )
throw Exception() << "DipoleMPKOperator::NLightProtonVec(): Could not find a proton particle group named 'p'" << Exception::abortnow;
const PDVector& theProtonConstitutents = theIt->second;
vector<int> theNLightProtonVec;
for ( PDVector::const_iterator theP = theProtonConstitutents.begin();
theP != theProtonConstitutents.end(); ++theP ) {
if ( (**theP).id() > 0 && (**theP).id() < 7 && (**theP).mass() == ZERO )
theNLightProtonVec.push_back( (**theP).id() );
}
return theNLightProtonVec;
}
//////////////////////////////////////////////////////////////////////
double DipoleMPKOperator::me2() const {
if ( isDR() )
throw InitException() << "DipoleMPKOperator not implemented for dimensional reduction.";
scale = lastBorn()->lastScale();
double res = 0.0;
if ( apply(mePartonData()[0]) ) {
if ( mePartonData()[0]->coloured() ) {
if ( mePartonData()[1]->coloured() )
res += lastBorn()->pdf2()*sumParton(0);
else
res += sumParton(0);
}
}
if ( apply(mePartonData()[1]) ) {
if ( mePartonData()[1]->coloured() ) {
if ( mePartonData()[0]->coloured() )
res += lastBorn()->pdf1()*sumParton(1);
else
res += sumParton(1);
}
}
return (lastBorn()->lastAlphaS()/(2.*pi)) * res;
}
//////////////////////////////////////////////////////////////////////
double DipoleMPKOperator::sumParton(int id) const {
// sumParton(int id) sums for a specific id=a'=0,1
// over all a (see CS paper)
bool appendixB = true;
// Note: We are using a parametrization where we keep s_{ja'}=2p_jp_a' fixed,
// rather than s_{ja}=2p_jp_a, due to the substitution \eta->x/z and the sub-
// sequent shift of the z-dependence from the hard Born ME into the PDF.
// Thus we need to make sure to keep the right kinematic variable fixed while
// performig the z-integration, i.e. s_{ja'} in our case. This is partly des-
// cribed in appendix B of the massive CS paper, but also in the last term of
// eq. (6.55) in the massive CS paper we need to consider that s_{ja'} is our
// fixed variable and not s_{ja}.
// This also means that in the sum over heavy quark flavours, in the g->QQbar
// contributions, we need to sum over N_F and not just N_F^{ja} (see appendix
// B in the massive CS paper, last sentence on p. 51 in arXiv:hep-ph/0201036)
// which is not only important for the massive PK operator here but actually
// also for the I operator in the massive case.
pdf =
id == 0 ?
lastXCombPtr()->partonBins().first->pdf() :
lastXCombPtr()->partonBins().second->pdf();
x =
id == 0 ?
lastXCombPtr()->lastX1() :
lastXCombPtr()->lastX2();
parton =
id == 0 ?
mePartonData()[0] :
mePartonData()[1];
particle =
id == 0 ?
lastParticles().first->dataPtr() :
lastParticles().second->dataPtr();
using namespace RandomHelpers;
double r = insertionRandomNumbers().front();
double eps = 1e-3;
pair<double,double> zw =
generate( ( piecewise(),
flat(0.0,x),
match(inverse(0.0,x,1.0) + inverse(1.0+eps,x,1.0)) ),
r );
z = zw.first;
double mapz = zw.second;
// For every new momentum fraction at which we want to evaluate a pdf
// we introduce a new member to the pdf cache: Initialize the cache.
// Remember, that there are potentially as many different values for
// z_+ (zbar_+ in the method of appendix B) as there are heavy quark
// flavours in the jet.
vector<double> nullPDFCacheVector;
- for( size_t f=0; f<NHeavyJetVec().size(); ++f ) nullPDFCacheVector.push_back(0.0);
+ // for( size_t f=0; f<NHeavyJetVec().size(); ++f ) nullPDFCacheVector.push_back(0.0);
+ for( size_t f=0; f<lastBorn()->nHeavyJetVec().size(); ++f ) nullPDFCacheVector.push_back(0.0);
nullPDFCacheVector.push_back(0.0);
nullPDFCacheVector.push_back(0.0);
for ( map<pair<tcPDFPtr,tcPDPtr>,vector<double> >::iterator cache =
pdfCache.begin(); cache != pdfCache.end(); ++cache ) cache->second = nullPDFCacheVector;
assert(pdf);
double res = 0.;
////////////////////////////
// K operator //
// non-color correlated //
////////////////////////////
// The non-color correlated contributions of the K operator
// are equal in the massive and massless case.
// Master apply prevents the DipolePKOperator though
// from applying in the case of at least one massive
// parton in the overall process. So need to add the
// corresponding contributions here (DipoleMPKOpera-
// tor) as well.
if ( mePartonData()[id]->id() == ParticleID::g )
res += (KBargg() + KBarqg())*lastBorn()->me2();
if ( abs(mePartonData()[id]->id()) < 7 )
res += (KBarqq() + KBargq())*lastBorn()->me2();
////////////////////////////
double theGammaSoft = 0.0;
double thePqq = 0.0;
double thePqg = 0.0;
double thePgq = 0.0;
double thePgg = 0.0;
double thePqqreg = 0.0;
double thePqgreg = 0.0;
double thePgqreg = 0.0;
double thePggreg = 0.0;
double ifCorrelated = 0.0;
double fiCorrelated = 0.0;
int idi = 2;
vector<Lorentz5Momentum>::const_iterator Pi = meMomenta().begin() + 2;
double disFinite = 0.0;
double glueFinite = 0.0;
//////////////////////////////////////////////////////////
// Initial-Final and Final-Initial contributions //
//////////////////////////////////////////////////////////
for ( cPDVector::const_iterator i = mePartonData().begin() + 2;
i != mePartonData().end(); ++i, ++Pi, ++idi ) {
if ( !applyNotMassless(*i) || lastBorn()->noDipole(idi,id) )
continue;
fiCorrelated = lastBorn()->colourCorrelatedME2(make_pair(idi,id));
ifCorrelated = lastBorn()->colourCorrelatedME2(make_pair(id,idi));
if ( theGammaSoft == 0.0 )
theGammaSoft = gammaSoft();
if ( mePartonData()[id]->id() == ParticleID::g &&
thePgg == 0.0 ) {
thePqg = Pqg();
thePgg = Pgg();
}
if ( abs(mePartonData()[id]->id()) < 7 &&
thePqq == 0.0 ) {
thePgq = Pgq();
thePqq = Pqq();
}
//////////////////////////
// K operator, the rest //
//////////////////////////
// // For m_j=0 and {m_F}=empty we can use the exact massless case.
// // This case, however, should actually not occur here.
// if ( (**i).mass() == ZERO && NHeavyJetVec().size() == 0 ) {
// throw InitException() << "DipoleMPKOperator::sumParton: m_j=0 and {m_F}=empty. This should not have happened.";
// // Last term in massless K operator in (C.31) in massless paper.
// res +=
// ( (**i).id() == ParticleID::g ? gammaGluon : gammaQuark ) *
// theGammaSoft * fiCorrelated;
// // gammaSoft() * fiCorrelated;
// }
// For m_j=0 and {m_F}=empty we can use the exact massless case.
- if ( (**i).mass() == ZERO && NHeavyJetVec().size() == 0 ) {
+ // if ( (**i).mass() == ZERO && NHeavyJetVec().size() == 0 ) {
+ if ( (**i).mass() == ZERO && lastBorn()->nHeavyJetVec().size() == 0 ) {
// Last term in massless K operator in (C.31) in massless paper.
res +=
( (**i).id() == ParticleID::g ? gammaGluon : gammaQuark ) *
theGammaSoft * fiCorrelated;
// gammaSoft() * fiCorrelated;
}
// For m_j!=0 or {m_F}!=empty we use the massive formulae.
else {
Energy2 mj2 = sqr((**i).mass());
Energy2 sja = 2.*( (*Pi) * meMomenta()[id]/z );
Energy2 Qja2 = mj2 - z*sja;
// Next-to-Last term in massive K operator in (6.55) in massive paper.
// Corresponds in massless limit to the last term in massless K operator.
if ( mePartonData()[id]->id() == ParticleID::g ) {
res -=
( (**i).id() == ParticleID::g ? CA : CF ) *
fiCorrelated *
( appendixB
? ( (**i).id() == ParticleID::g ? ( Kscriptbarqg_g() + Kscriptbargg_g(Qja2,appendixB) )
: ( Kscriptbarqg_q(Qja2,mj2) + Kscriptbargg_q(Qja2,mj2,appendixB) ) )
: ( (**i).id() == ParticleID::g ? ( Kscriptqg_g() + Kscriptgg_g(sja,appendixB) )
: ( Kscriptqg_q(sja,mj2) + Kscriptgg_q(sja,mj2,appendixB) ) )
);
}
if ( abs(mePartonData()[id]->id()) < 7 ) {
res -=
( (**i).id() == ParticleID::g ? CA : CF ) *
fiCorrelated *
( appendixB
? ( (**i).id() == ParticleID::g ? ( Kscriptbarqq_g(Qja2,appendixB) + Kscriptbargq_g() )
: ( Kscriptbarqq_q(Qja2,mj2,appendixB) + Kscriptbargq_q() ) )
: ( (**i).id() == ParticleID::g ? ( Kscriptqq_g(sja,appendixB) + Kscriptgq_g() )
: ( Kscriptqq_q(sja,mj2,appendixB) + Kscriptgq_q() ) )
);
}
// The regular splitting functions, not
// folded with 1/z*PDF(x/z)*\Theta(z-x)
if (thePqqreg == 0.0) thePqqreg = -1.*CF*(1.+z);
if (thePqgreg == 0.0) thePqgreg = CF*(1.+(1.-z)*(1.-z))/z;
if (thePgqreg == 0.0) thePgqreg = 1./2.*(z*z + (1.-z)*(1.-z));
if (thePggreg == 0.0) thePggreg = 2.*CA*((1.-z)/z - 1. + z*(1.-z));
// double thePqqreg = -1.*CF*(1.+z);
// double thePqgreg = CF*(1.+(1.-z)*(1.-z))/z;
// double thePgqreg = 1./2.*(z*z + (1.-z)*(1.-z));
// double thePggreg = 2.*CA*((1.-z)/z - 1. + z*(1.-z));
// Last term in massive K operator in (6.55) in massive paper.
// Vanishes theoretically in the massless limit.
if (!appendixB) {
if ( mePartonData()[id]->id() == ParticleID::g ) {
double quarkpdfsum = 0.0;
- int nlp = NLightProtonVec().size();
+ // int nlp = NLightProtonVec().size();
+ int nlp = lastBorn()->nLightProtonVec().size();
for ( int f = -nlp; f <= nlp; ++f ) {
if ( f == 0 ) continue;
quarkpdfsum += PDFxByz(getParticleData(f));
}
res -=
ifCorrelated *
( ( z>x ? 1./z*( thePqgreg*quarkpdfsum + thePggreg*PDFxByz(parton) )*log((1.-z)*sja/((1.-z)*sja+mj2)) : 0. ) +
(gammaGluon)*PDFx(parton)*( log((sja-2.*sqrt(mj2)*sqrt(sja+mj2)+2.*mj2)/sja) + 2.*sqrt(mj2)/(sqrt(sja+mj2)+sqrt(mj2)) ) );
}
if ( abs(mePartonData()[id]->id()) < 7 ) {
res -=
ifCorrelated *
( ( z>x ? 1./z*( thePqqreg*PDFxByz(parton) + thePgqreg*PDFxByz(getParticleData(ParticleID::g)) )*log((1.-z)*sja/((1.-z)*sja+mj2)) : 0. ) +
(gammaQuark)*PDFx(parton)*( log((sja-2.*sqrt(mj2)*sqrt(sja+mj2)+2.*mj2)/sja) + 2.*sqrt(mj2)/(sqrt(sja+mj2)+sqrt(mj2)) ) );
}
}
else if (appendixB) {
if ( mePartonData()[id]->id() == ParticleID::g ) {
double quarkpdfsum = 0.0;
- int nlp = NLightProtonVec().size();
+ // int nlp = NLightProtonVec().size();
+ int nlp = lastBorn()->nLightProtonVec().size();
for ( int f = -nlp; f <= nlp; ++f ) {
if ( f == 0 ) continue;
quarkpdfsum += PDFxByz(getParticleData(f));
}
res -=
ifCorrelated *
( ( z>x ? 1./z*( thePqgreg*quarkpdfsum + thePggreg*PDFxByz(parton) )*log((1.-z)*sja/((1.-z)*sja+mj2)) : 0. ) +
(gammaGluon)*PDFx(parton)*( log((z*sja-2.*sqrt(mj2)*sqrt(z*sja+mj2)+2.*mj2)/(z*sja)) + 2.*sqrt(mj2)/(sqrt(z*sja+mj2)+sqrt(mj2)) ) );
}
if ( abs(mePartonData()[id]->id()) < 7 ) {
res -=
ifCorrelated *
( ( z>x ? 1./z*( thePqqreg*PDFxByz(parton) + thePgqreg*PDFxByz(getParticleData(ParticleID::g)) )*log((1.-z)*sja/((1.-z)*sja+mj2)) : 0. ) +
(gammaQuark)*PDFx(parton)*( log((z*sja-2.*sqrt(mj2)*sqrt(z*sja+mj2)+2.*mj2)/(z*sja)) + 2.*sqrt(mj2)/(sqrt(z*sja+mj2)+sqrt(mj2)) ) );
}
}
}
////////////////
// P operator //
////////////////
// The contributions of the P operator are equal
// in the massive and massless case.
// Master apply prevents the DipolePKOperator though
// from applying in the case of at least one massive
// parton in the overall process. So need to add the
// corresponding contributions here (DipoleMPKOpera-
// tor) as well.
double theLog = log(scale/(2.*((*Pi)*meMomenta()[id])));
// Note: In the CS paper theLog is given by
// \log(\mu_F^2/(2zp_Ip_a)) = \log(\mu_F^2/(2p_Ip_a'))
// Note: The AP splitting kernels P^{aa'} contain plus
// distributions
// Note however: In our implementation p_Ip_a' is kept
// fixed, so we don't have a z dependence there
if ( mePartonData()[id]->id() == ParticleID::g ) {
res +=
( thePgg + thePqg ) * theLog * ifCorrelated;
// ( Pgg() + Pqg() ) * theLog * ifCorrelated;
}
if ( abs(mePartonData()[id]->id()) < 7 ) {
res +=
( thePqq + thePgq ) * theLog * ifCorrelated;
// ( Pqq() + Pgq() ) * theLog * ifCorrelated;
// if ( disFinite == 0.0 && z > x ) {
// extra terms only present in massless dipoles, idi is spectator
if ( disFinite == 0.0 && z > x && mePartonData()[idi]->mass() == ZERO ) {
disFinite = CF*PDFxByz(parton)*(1.+3.*z/2.)/z;
}
// if ( z > x )
// extra terms only present in massless dipoles, idi is spectator
if ( z > x && mePartonData()[idi]->mass() == ZERO )
res -= disFinite*ifCorrelated;
}
if ( abs(mePartonData()[idi]->id()) < 7 ) {
// if ( disFinite == 0.0 && z > x ) {
// extra terms only present in massless dipoles, idi is emitter
if ( disFinite == 0.0 && z > x && mePartonData()[idi]->mass() == ZERO ) {
disFinite = CF*PDFxByz(parton)*(1.+3.*z/2.)/z;
}
// if ( z > x )
// extra terms only present in massless dipoles, idi is emitter
if ( z > x && mePartonData()[idi]->mass() == ZERO )
res -= disFinite*fiCorrelated;
}
if ( mePartonData()[idi]->id() == ParticleID::g ) {
if ( glueFinite == 0.0 && z > x ) {
glueFinite = 2.*CA*PDFxByz(parton)*(1.+z/6.)/z;
}
if ( z > x )
res -= glueFinite*fiCorrelated;
}
} // end loop over i
//////////////////////////////////////////////////////////
// Initial-Initial contributions //
//////////////////////////////////////////////////////////
if ( mePartonData()[ id == 0 ? 1 : 0 ]->coloured() &&
!lastBorn()->noDipole(id == 0 ? 0 : 1,
id == 0 ? 1 : 0) ) {
if ( mePartonData()[id]->id() == ParticleID::g &&
thePgg == 0.0 ) {
thePqg = Pqg();
thePgg = Pgg();
}
if ( abs(mePartonData()[id]->id()) < 7 &&
thePqq == 0.0 ) {
thePgq = Pgq();
thePqq = Pqq();
}
double theLog = log(scale/(2.*(meMomenta()[0]*meMomenta()[1])));
// Note: In the CS paper theLog is given by
// \log(\mu_F^2/(2zp_Ip_a)) = \log(\mu_F^2/(2p_Ip_a'))
// Note: The AP splitting kernels P^{aa'} contain plus
// distributions
// Note however: In our implementation p_Ip_a' is kept
// fixed, so we don't have a z dependence there
pair<int,int> corr = id == 0 ? make_pair(0,1) : make_pair(1,0);
double iiCorrelated = lastBorn()->colourCorrelatedME2(corr);
if ( mePartonData()[id]->id() == ParticleID::g ) {
res +=
( thePgg + thePqg ) * theLog * iiCorrelated;
// ( Pgg() + Pqg() ) * theLog * iiCorrelated;
res -=
( KTildegg() + KTildeqg() ) * iiCorrelated;
}
if ( abs(mePartonData()[id]->id()) < 7 ) {
res +=
( thePqq + thePgq ) * theLog * iiCorrelated;
// ( Pqq() + Pgq() ) * theLog * iiCorrelated;
res -=
( KTildeqq() + KTildegq() ) * iiCorrelated;
}
}
//////////////////////////////////////////////////////////
return res * mapz;
}
//////////////////////////////////////////////////////////////////////
double DipoleMPKOperator::gammaSoft() const {
double res = (1.+log(1.-x))*PDFx(parton);
if ( z > x )
res +=
(PDFxByz(parton) - z*PDFx(parton)) / (z*(1.-z));
return res;
}
double DipoleMPKOperator::softLogByz(tcPDPtr p) const {
double res = ( sqr(log(1.-x))/2. - sqr(pi)/6. ) * PDFx(p);
if ( z > x ) {
res += (PDFxByz(p) - z*PDFx(p))*log(1.-z)/(z*(1.-z));
res -= PDFxByz(p)*log(z)/(z*(1.-z));
}
return res;
}
double DipoleMPKOperator::softLog(tcPDPtr p) const {
double res = sqr(log(1.-x)) * PDFx(p) / 2.;
if ( z > x ) {
res += (PDFxByz(p) - z*PDFx(p))*log(1.-z)/(z*(1.-z));
}
return res;
}
double DipoleMPKOperator::KBarqq() const {
assert(abs(parton->id()) < 7);
double res =
2.*softLogByz(parton) +
(sqr(pi) - 5.)*PDFx(parton);
if ( z > x ) {
res += PDFxByz(parton)*( (1.-z) - (1.+z)*log((1.-z)/z) ) / z;
}
return (res * CF);
}
double DipoleMPKOperator::KTildeqq() const {
assert(abs(parton->id()) < 7);
double res =
2.*CF*softLog(parton) - CF*(sqr(pi)/3.)*PDFx(parton);
if ( z > x ) {
res -= ( CF * (1.+z) * log(1.-z) ) * PDFxByz(parton) / z;
}
return res;
}
double DipoleMPKOperator::Pqq() const {
assert(abs(parton->id()) < 7);
double res = (3./2.+2.*log(1.-x)) * PDFx(parton);
if ( z > x ) {
res += 2.*(PDFxByz(parton) - z*PDFx(parton))/(z*(1.-z));
res -= PDFxByz(parton) * (1.+z)/z;
}
return (CF*res);
}
double DipoleMPKOperator::KBarqg() const {
assert(parton->id() == ParticleID::g);
if ( z < x )
return 0.0;
double res = 0.0;
double factor = CF * ( ( (1.+sqr(1.-z)) / z ) * log((1.-z)/z) + z ) / z;
- int nlp = NLightProtonVec().size();
+ // int nlp = NLightProtonVec().size();
+ int nlp = lastBorn()->nLightProtonVec().size();
for ( int f = -nlp; f <= nlp; ++f ) {
if ( f == 0 )
continue;
res += PDFxByz(getParticleData(f));
}
return res*factor;
}
double DipoleMPKOperator::KTildeqg() const {
if ( z < x )
return 0.0;
return Pqg() * log(1.-z);
}
double DipoleMPKOperator::Pqg() const {
assert(parton->id() == ParticleID::g);
if ( z < x )
return 0.0;
double res = 0.0;
double factor = CF * ( 1. + sqr(1.-z) ) / sqr(z);
- int nlp = NLightProtonVec().size();
+ // int nlp = NLightProtonVec().size();
+ int nlp = lastBorn()->nLightProtonVec().size();
for ( int f = -nlp; f <= nlp; ++f ) {
if ( f == 0 )
continue;
res += PDFxByz(getParticleData(f));
}
return res*factor;
}
double DipoleMPKOperator::KBargq() const {
assert(abs(parton->id()) < 7);
if ( z < x )
return 0.0;
return
PDFxByz(getParticleData(ParticleID::g)) *
( 0.5*(sqr(z)+sqr(1.-z))*log((1.-z)/z) + z*(1.-z) ) / z;
}
double DipoleMPKOperator::KTildegq() const {
assert(abs(parton->id()) < 7);
if ( z < x )
return 0.0;
return Pgq() * log(1.-z);
}
double DipoleMPKOperator::Pgq() const {
assert(abs(parton->id()) < 7);
if ( z < x )
return 0.0;
return 0.5 * ( sqr(z) + sqr(1.-z) ) * PDFxByz(getParticleData(ParticleID::g)) / z;
}
double DipoleMPKOperator::KBargg() const {
assert(parton->id() == ParticleID::g);
double res =
2.* CA* softLogByz(parton) +
- ( CA*( sqr(pi) - 50./9. ) + (8./9.)*NLightJetVec().size() ) * PDFx(parton);
+ // ( CA*( sqr(pi) - 50./9. ) + (8./9.)*NLightJetVec().size() ) * PDFx(parton);
+ ( CA*( sqr(pi) - 50./9. ) + (8./9.)*lastBorn()->nLightJetVec().size() ) * PDFx(parton);
if ( z > x ) {
res += 2.*CA*((1.-z)/z-1.+z*(1.-z))*log((1.-z)/z)*PDFxByz(parton)/z;
}
return res;
}
double DipoleMPKOperator::KTildegg() const {
assert(parton->id() == ParticleID::g);
double res =
2.*CA*softLog(parton) - CA*(sqr(pi)/3.)*PDFx(parton);
if ( z > x ) {
res += ( 2.*CA * ( (1.-z)/z -1. + z*(1.-z) ) * log(1.-z) ) * PDFxByz(parton) / z;
}
return res;
}
double DipoleMPKOperator::Pgg() const {
assert(parton->id() == ParticleID::g);
double res =
- ( (11./6.) * CA - (1./3.)*NLightJetVec().size() + 2.*CA*log(1.-x) ) * PDFx(parton);
+ // ( (11./6.) * CA - (1./3.)*NLightJetVec().size() + 2.*CA*log(1.-x) ) * PDFx(parton);
+ ( (11./6.) * CA - (1./3.)*lastBorn()->nLightJetVec().size() + 2.*CA*log(1.-x) ) * PDFx(parton);
if ( z > x ) {
res += 2. * CA * ( PDFxByz(parton) - z*PDFx(parton) ) / (z*(1.-z));
res += 2.* CA *( (1.-z)/z - 1. + z*(1.-z) ) * PDFxByz(parton) / z;
}
return res;
}
//////////////////////////////////////////////////////////////////////
double DipoleMPKOperator::Ja_gQplus(double muQ2) const {
double res =
-1. * PDFx(parton) * ( (1.-z)/(2.*(1.-z+muQ2)*(1.-z+muQ2)) - 2./(1.-z)*(1.+log((1.-z+muQ2)/(1.+muQ2))) );
if ( z > x ) {
res += 1./z * PDFxByz(parton) * ( (1.-z)/(2.*(1.-z+muQ2)*(1.-z+muQ2)) - 2./(1.-z)*(1.+log((1.-z+muQ2)/(2.-z+muQ2))) );
}
return res;
}
double DipoleMPKOperator::gammaSoft2(double muQ2) const {
double res =
(1./(1.-z)) * ( -1. * PDFx(parton) * log( 1./(1.+muQ2) ) );
if ( z > x ) {
res += (1./(1.-z)) * ( 1./z * PDFxByz(parton) * log( (2.-z)/(2.-z+muQ2) ) );
}
return res;
}
double DipoleMPKOperator::Ja_gQplusmod(double muQ2) const {
double res =
-1. * PDFx(parton) * ( (1.-z)/(2.*(1.-z+muQ2)*(1.-z+muQ2)) - 2./(1.-z)*(1.+log((1.-z+muQ2)/(1.+muQ2/z))) );
if ( z > x ) {
res += 1./z * PDFxByz(parton) * ( (1.-z)/(2.*(1.-z+muQ2)*(1.-z+muQ2)) - 2./(1.-z)*(1.+log((1.-z+muQ2)/(2.-z+muQ2))) );
}
return res;
}
double DipoleMPKOperator::gammaSoft2mod(double muQ2) const {
double res =
(1./(1.-z)) * ( -1. * PDFx(parton) * log( 1./(1.+muQ2/z) ) );
if ( z > x ) {
res += (1./(1.-z)) * ( 1./z * PDFxByz(parton) * log( (2.-z)/(2.-z+muQ2) ) );
}
return res;
}
double DipoleMPKOperator::Kscriptqq_q(Energy2 sja, Energy2 mj2, bool appendixB) const {
assert(abs(parton->id()) < 7);
double muQ2 = mj2/sja;
double res =
2. * softLog(parton) +
( appendixB ? Ja_gQplusmod(muQ2) : Ja_gQplus(muQ2) ) +
2. * ( appendixB ? gammaSoft2mod(muQ2) : gammaSoft2(muQ2) ) -
gammaQuark/CF * PDFx(parton) +
( appendixB ? muQ2/z*log(muQ2/(z+muQ2)) + 1./2.*(muQ2/(z+muQ2)) : muQ2*log(muQ2/(1.+muQ2)) + 1./2.*(muQ2/(1.+muQ2)) ) * PDFx(parton);
if ( z > x ) {
res += 1./z * PDFxByz(parton) * (
-2. * log(2.-z)/(1.-z) );
}
return res;
}
double DipoleMPKOperator::Kscriptqg_q(Energy2 sja, Energy2 mj2) const {
assert(parton->id() == ParticleID::g);
if ( z < x )
return 0.0;
double muQ2 = mj2/sja;
double res = 0.0;
double factor = 1./z * ( 2.*CF/CA*muQ2/z*log(muQ2/(1.-z+muQ2)) );
- int nlp = NLightProtonVec().size();
+ // int nlp = NLightProtonVec().size();
+ int nlp = lastBorn()->nLightProtonVec().size();
for ( int f = -nlp; f <= nlp; ++f ) {
if ( f == 0 )
continue;
res += PDFxByz(getParticleData(f));
}
return res*factor;
}
double DipoleMPKOperator::Kscriptgq_q() const {
assert(abs(parton->id()) < 7);
double res = 0.0;
return res;
}
double DipoleMPKOperator::Kscriptgg_q(Energy2 sja, Energy2 mj2, bool appendixB) const {
assert(parton->id() == ParticleID::g);
// The pdf folding has to be with the gluon pdf here, not with
// the quark pdf's. Hence the contributions of Kscriptqg_q and
// Kscriptqq_q are implemented here separately again since the
// safeguard assert functions would trigger if we used the im-
// plementations above. The parton is nevertheless a gluon, so
// we can simply use PDFx...(parton) here.
double muQ2 = mj2/sja;
double res = 0.0;
// CA/CF*Kscriptqg_q contribution
double factor = 0.0;
if ( z > x ) {
factor += 1./z * PDFxByz(parton) * (
2.*CF/CA*muQ2/z*log(muQ2/(1.-z+muQ2)) );
}
res += CA/CF * factor;
// Kscriptqq_q contribution
res += 2. * softLog(parton) +
( appendixB ? Ja_gQplusmod(muQ2) : Ja_gQplus(muQ2) ) +
2. * ( appendixB ? gammaSoft2mod(muQ2) : gammaSoft2(muQ2) ) -
gammaQuark/CF * PDFx(parton) +
( appendixB ? muQ2/z*log(muQ2/(z+muQ2)) + 1./2.*(muQ2/(z+muQ2)) : muQ2*log(muQ2/(1.+muQ2)) + 1./2.*(muQ2/(1.+muQ2)) ) * PDFx(parton);
if ( z > x ) {
res += 1./z * PDFxByz(parton) * (
-2. * log(2.-z)/(1.-z) );
}
return res;
}
double DipoleMPKOperator::Kscriptbarqq_q(Energy2 Qja2, Energy2 mj2, bool appendixB) const {
assert(abs(parton->id()) < 7);
double mubarQ2 = mj2/(-Qja2);
double res = 0.0;
Energy2 sjamod = (mj2-Qja2)/z; // Since Qja2=mj2-z*sja this gives sja again
res += Kscriptqq_q(sjamod, mj2, appendixB)
// \deltaqq*\delta(1-z)*DeltaJbaraNS_gQ(mj2/-Qja2) contribution
+ PDFx(parton)*( sqr(pi)/3. - 2.*gsl_sf_dilog(1./(1.+mubarQ2)) + 2.*gsl_sf_dilog(-mubarQ2/(1.+mubarQ2))
+ 0.5*log((1.+mubarQ2)/(1.+2.*mubarQ2)) + 0.5*mubarQ2*(2.+mubarQ2)*log((1.+mubarQ2)/mubarQ2)
- mubarQ2*(1.+mubarQ2)/(1.+2.*mubarQ2) );
return res;
}
double DipoleMPKOperator::Kscriptbarqg_q(Energy2 Qja2, Energy2 mj2) const {
assert(parton->id() == ParticleID::g);
double res = 0.0;
Energy2 sjamod = (mj2-Qja2)/z; // Since Qja2=mj2-z*sja this gives sja again
res += Kscriptqg_q(sjamod, mj2);
// \deltaqg*\delta(1-z)*DeltaJbaraNS_gQ(mj2/-Qja2) contribution is zero
return res;
}
double DipoleMPKOperator::Kscriptbargq_q() const {
assert(abs(parton->id()) < 7);
double res = 0.0;
return res;
}
double DipoleMPKOperator::Kscriptbargg_q(Energy2 Qja2, Energy2 mj2, bool appendixB) const {
assert(parton->id() == ParticleID::g);
double mubarQ2 = mj2/(-Qja2);
double res = 0.0;
Energy2 sjamod = (mj2-Qja2)/z; // Since Qja2=mj2-z*sja this gives sja again
res += Kscriptgg_q(sjamod, mj2, appendixB)
// \deltagg*\delta(1-z)*DeltaJbaraNS_gQ(mj2/-Qja2) contribution
+ PDFx(parton)*( sqr(pi)/3. - 2.*gsl_sf_dilog(1./(1.+mubarQ2)) + 2.*gsl_sf_dilog(-mubarQ2/(1.+mubarQ2))
+ 0.5*log((1.+mubarQ2)/(1.+2.*mubarQ2)) + 0.5*mubarQ2*(2.+mubarQ2)*log((1.+mubarQ2)/mubarQ2)
- mubarQ2*(1.+mubarQ2)/(1.+2.*mubarQ2) );
return res;
}
//////////////////////////////
double DipoleMPKOperator::JaNS_QQ(double muQ2) const {
double res =
10./9. * ( 1. - sqrt(1.-4.*muQ2) ) -
8./9. * muQ2 * sqrt(1.-4.*muQ2) +
4./3. * log( (1.+sqrt(1.-4.*muQ2))/2. );
return res;
}
double DipoleMPKOperator::Ja_QQzplus(double muQ2, int F, double zplus) const {
double res = 0.0;
if ( z > x && z < zplus ) {
res += ( 1./z*PDFxByz(parton) - 1./zplus*PDFxByzplus(parton,F,zplus) ) * 2./3.*( (1.-z+2.*muQ2)/((1.-z)*(1.-z)) * sqrt(1.-4.*muQ2/(1.-z)) );
}
if ( z > x && z < zplus ) {
res += ( 1./zplus*PDFxByzplus(parton,F,zplus) ) * 2./3.*( (1.-z+2.*muQ2)/((1.-z)*(1.-z)) * sqrt(1.-4.*muQ2/(1.-z)) );
}
if ( zplus > x && z < zplus ) {
res -= ( 1./zplus*PDFxByzplus(parton,F,zplus) ) * 2./3.*( (1.-z+2.*muQ2)/((1.-z)*(1.-z)) * sqrt(1.-4.*muQ2/(1.-z)) );
}
return res;
}
double DipoleMPKOperator::Ja_QQzplusmod(double muQ2, int F, double zplus) const {
// This should actually be the same as Ja_QQzplus()
double res = 0.0;
if ( z > x && z < zplus ) {
res += ( 1./z*PDFxByz(parton) ) * 2./3.*( (1.-z+2.*muQ2)/((1.-z)*(1.-z)) * sqrt(1.-4.*muQ2/(1.-z)) );
}
if ( zplus > x && z < zplus ) {
res -= ( 1./zplus*PDFxByzplus(parton,F,zplus) ) * 2./3.*( (1.-z+2.*muQ2)/((1.-z)*(1.-z)) * sqrt(1.-4.*muQ2/(1.-z)) );
}
return res;
}
double DipoleMPKOperator::Kscriptqq_g(Energy2 sja, bool appendixB) const {
assert(abs(parton->id()) < 7);
double res = -1.*gammaGluon/CA*gammaSoft();
- for( size_t f=0; f<NHeavyJetVec().size(); ++f ) { // sum over heavy flavours
- Energy2 mF2 = sqr( getParticleData(NHeavyJetVec()[f])->mass() );
+ // for( size_t f=0; f<NHeavyJetVec().size(); ++f ) { // sum over heavy flavours
+ // Energy2 mF2 = sqr( getParticleData(NHeavyJetVec()[f])->mass() );
+ for( size_t f=0; f<lastBorn()->nHeavyJetVec().size(); ++f ) { // sum over heavy flavours
+ Energy2 mF2 = sqr( getParticleData(lastBorn()->nHeavyJetVec()[f])->mass() );
double muQ2 = mF2/sja;
double muQ2prime = mF2/(z*sja);
double muQ2bar = mF2/(-z*sja); // only for modified zplus, see appendix B, remember that m_j=m_g=0
double zplus = (appendixB ? 1./(1.+4.*muQ2bar) : 1. - 4*muQ2);
// sum only over heavy quarks which meet special condition
// but not if method of appendix B is used (see comment at
// the end of appendix B, also need different zplus then)
if( !appendixB && sja <= 4.*mF2 ) continue;
res += 1./(2.*CA) * (
PDFx(parton)*( ( appendixB ? 2./3.*(log(muQ2prime)+5./3.) - JaNS_QQ(muQ2prime)
: 2./3.*(log(muQ2)+5./3.) - JaNS_QQ(muQ2) ) ) -
( x<zplus ? ( appendixB ? 1./zplus*PDFxByzplus(parton,f,zplus)*( 2./3.*(log(zplus*muQ2prime)+5./3.) - JaNS_QQ(zplus*muQ2prime) )
: 1./zplus*PDFxByzplus(parton,f,zplus)*( 2./3.*(log(muQ2)+5./3.) - JaNS_QQ(muQ2) ) ) : 0. ) +
( appendixB ? Ja_QQzplusmod(muQ2,f,zplus) : Ja_QQzplus(muQ2,f,zplus) ) +
( appendixB ? PDFx(parton)*( 2./3.*sqrt((1.-4.*muQ2prime)*(1.-4.*muQ2prime)*(1.-4.*muQ2prime)) )
: PDFx(parton)*( 2./3.*sqrt((1.-4.*muQ2)*(1.-4.*muQ2)*(1.-4.*muQ2)) ) )
);
}
return res;
}
double DipoleMPKOperator::Kscriptqg_g() const {
assert(parton->id() == ParticleID::g);
double res = 0.0;
return res;
}
double DipoleMPKOperator::Kscriptgq_g() const {
assert(abs(parton->id()) < 7);
double res = 0.0;
return res;
}
double DipoleMPKOperator::Kscriptgg_g(Energy2 sja, bool appendixB) const {
assert(parton->id() == ParticleID::g);
double res = -1.*gammaGluon/CA*gammaSoft();
- for( size_t f=0; f<NHeavyJetVec().size(); ++f ) { // sum over heavy flavours
- Energy2 mF2 = sqr( getParticleData(NHeavyJetVec()[f])->mass() );
+ // for( size_t f=0; f<NHeavyJetVec().size(); ++f ) { // sum over heavy flavours
+ // Energy2 mF2 = sqr( getParticleData(NHeavyJetVec()[f])->mass() );
+ for( size_t f=0; f<lastBorn()->nHeavyJetVec().size(); ++f ) { // sum over heavy flavours
+ Energy2 mF2 = sqr( getParticleData(lastBorn()->nHeavyJetVec()[f])->mass() );
double muQ2 = mF2/sja;
double muQ2prime = mF2/(z*sja);
double muQ2bar = mF2/(-z*sja); // only for modified zplus, see appendix B, remember that m_j=m_g=0
double zplus = (appendixB ? 1./(1.+4.*muQ2bar) : 1. - 4*muQ2);
// sum only over heavy quarks which meet special condition
// but not if method of appendix B is used (see comment at
// the end of appendix B, also need different zplus then)
if( !appendixB && sja <= 4.*mF2 ) continue;
res += 1./(2.*CA) * (
PDFx(parton)*( ( appendixB ? 2./3.*(log(muQ2prime)+5./3.) - JaNS_QQ(muQ2prime)
: 2./3.*(log(muQ2)+5./3.) - JaNS_QQ(muQ2) ) ) -
( x<zplus ? ( appendixB ? 1./zplus*PDFxByzplus(parton,f,zplus)*( 2./3.*(log(zplus*muQ2prime)+5./3.) - JaNS_QQ(zplus*muQ2prime) )
: 1./zplus*PDFxByzplus(parton,f,zplus)*( 2./3.*(log(muQ2)+5./3.) - JaNS_QQ(muQ2) ) ) : 0. ) +
( appendixB ? Ja_QQzplusmod(muQ2,f,zplus) : Ja_QQzplus(muQ2,f,zplus) ) +
( appendixB ? PDFx(parton)*( 2./3.*sqrt((1.-4.*muQ2prime)*(1.-4.*muQ2prime)*(1.-4.*muQ2prime)) )
: PDFx(parton)*( 2./3.*sqrt((1.-4.*muQ2)*(1.-4.*muQ2)*(1.-4.*muQ2)) ) )
);
}
return res;
}
double DipoleMPKOperator::Kscriptbarqq_g(Energy2 Qja2, bool appendixB) const {
assert(abs(parton->id()) < 7);
double res = 0.0;
Energy2 sjamod = -Qja2/z; // Since Qja2=-z*sja (mj2=0) this gives sja again
res += Kscriptqq_g(sjamod,appendixB); // z_+ is automatically modified
// + \deltaqq*\delta(zplusbar-z)*T_R/C_A*\sum_{N_F}DeltaJbaraNS_QQbar(mF2/-Qja2) contribution
- for( size_t f=0; f<NHeavyJetVec().size(); ++f ) { // sum over heavy flavours
- Energy2 mF2 = sqr( getParticleData(NHeavyJetVec()[f])->mass() );
+ // for( size_t f=0; f<NHeavyJetVec().size(); ++f ) { // sum over heavy flavours
+ // Energy2 mF2 = sqr( getParticleData(NHeavyJetVec()[f])->mass() );
+ for( size_t f=0; f<lastBorn()->nHeavyJetVec().size(); ++f ) { // sum over heavy flavours
+ Energy2 mF2 = sqr( getParticleData(lastBorn()->nHeavyJetVec()[f])->mass() );
double mubarQ2 = mF2/(-Qja2);
double zplus = 1./(1.+4.*mubarQ2); // actually zbar_plus, see appendix B
res += 1./(2.*CA)*PDFxByzplus(parton,f,zplus)
*( 8./3.*mubarQ2 - 10./9. + (10./9.+16./3.*mubarQ2)/sqrt((1.+4.*mubarQ2)*(1.+4.*mubarQ2)*(1.+4.*mubarQ2))
+ 4./3.*( (1.-2.*mubarQ2)*sqrt(1.+4.*mubarQ2) - 1. )*log( (sqrt(1.+4.*mubarQ2)+1.)/(2.*sqrt(mubarQ2)) ) );
}
return res;
}
double DipoleMPKOperator::Kscriptbarqg_g() const {
assert(parton->id() == ParticleID::g);
double res = 0.0;
return res;
}
double DipoleMPKOperator::Kscriptbargq_g() const {
assert(abs(parton->id()) < 7);
double res = 0.0;
return res;
}
double DipoleMPKOperator::Kscriptbargg_g(Energy2 Qja2, bool appendixB) const {
assert(parton->id() == ParticleID::g);
double res = 0.0;
Energy2 sjamod = -Qja2/z; // Since Qja2=-z*sja (mj2=0) this gives sja again
res += Kscriptgg_g(sjamod,appendixB); // z_+ is automatically modified
// + \deltagg*\delta(zplusbar-z)*T_R/C_A*\sum_{N_F}DeltaJbaraNS_QQbar(mF2/-Qja2) contribution
- for( size_t f=0; f<NHeavyJetVec().size(); ++f ) { // sum over heavy flavours
- Energy2 mF2 = sqr( getParticleData(NHeavyJetVec()[f])->mass() );
+ // for( size_t f=0; f<NHeavyJetVec().size(); ++f ) { // sum over heavy flavours
+ // Energy2 mF2 = sqr( getParticleData(NHeavyJetVec()[f])->mass() );
+ for( size_t f=0; f<lastBorn()->nHeavyJetVec().size(); ++f ) { // sum over heavy flavours
+ Energy2 mF2 = sqr( getParticleData(lastBorn()->nHeavyJetVec()[f])->mass() );
double mubarQ2 = mF2/(-Qja2);
double zplus = 1./(1.+4.*mubarQ2); // actually zbar_plus, see appendix B
res += 1./(2.*CA)*PDFxByzplus(parton,f,zplus)
*( 8./3.*mubarQ2 - 10./9. + (10./9.+16./3.*mubarQ2)/sqrt((1.+4.*mubarQ2)*(1.+4.*mubarQ2)*(1.+4.*mubarQ2))
+ 4./3.*( (1.-2.*mubarQ2)*sqrt(1.+4.*mubarQ2) - 1. )*log( (sqrt(1.+4.*mubarQ2)+1.)/(2.*sqrt(mubarQ2)) ) );
}
return res;
}
//////////////////////////////////////////////////////////////////////
// For every new momentum fraction at which we want to evaluate a pdf
// we introduce a new member to the pdf cache.
double DipoleMPKOperator::PDFx(tcPDPtr pd) const {
vector<double> nullPDFCacheVector;
- for( size_t f=0; f<NHeavyJetVec().size(); ++f ) nullPDFCacheVector.push_back(0.0);
+ // for( size_t f=0; f<NHeavyJetVec().size(); ++f ) nullPDFCacheVector.push_back(0.0);
+ for( size_t f=0; f<lastBorn()->nHeavyJetVec().size(); ++f ) nullPDFCacheVector.push_back(0.0);
nullPDFCacheVector.push_back(0.0);
nullPDFCacheVector.push_back(0.0);
map<pair<tcPDFPtr,tcPDPtr>,vector<double> >::iterator cached = pdfCache.find(make_pair(pdf,pd));
if ( cached == pdfCache.end() ) {
pdfCache[make_pair(pdf,pd)] = nullPDFCacheVector;
cached = pdfCache.find(make_pair(pdf,pd));
}
// The convention of the pdf sets is always to return a*f(a). Upon usage,
// we have to remember that and rescale the result of the pdf accordingly
// again, i.e. a*f(a)/a.
if ( cached->second.at(0) == 0.0 ) cached->second.at(0) = pdf->xfx(particle,pd,scale,x)/x;
return cached->second.at(0);
}
double DipoleMPKOperator::PDFxByz(tcPDPtr pd) const {
vector<double> nullPDFCacheVector;
- for( size_t f=0; f<NHeavyJetVec().size(); ++f ) nullPDFCacheVector.push_back(0.0);
+ // for( size_t f=0; f<NHeavyJetVec().size(); ++f ) nullPDFCacheVector.push_back(0.0);
+ for( size_t f=0; f<lastBorn()->nHeavyJetVec().size(); ++f ) nullPDFCacheVector.push_back(0.0);
nullPDFCacheVector.push_back(0.0);
nullPDFCacheVector.push_back(0.0);
map<pair<tcPDFPtr,tcPDPtr>,vector<double> >::iterator cached = pdfCache.find(make_pair(pdf,pd));
if ( cached == pdfCache.end() ) {
pdfCache[make_pair(pdf,pd)] = nullPDFCacheVector;
cached = pdfCache.find(make_pair(pdf,pd));
}
// The convention of the pdf sets is always to return a*f(a). Upon usage,
// we have to remember that and rescale the result of the pdf accordingly
// again, i.e. a*f(a)/a.
if ( cached->second.at(1) == 0.0 ) cached->second.at(1) = pdf->xfx(particle,pd,scale,x/z)*z/x;
return cached->second.at(1);
}
//////////////////////////////
// For every new momentum fraction at which we want to evaluate a pdf
// we introduce a new member to the pdf cache.
// Remember, that there are potentially as many different values for
// z_+ (zbar_+ in the method of appendix B) as there are heavy quark
// flavours in the jet.
double DipoleMPKOperator::PDFxByzplus(tcPDPtr pd, int F, double zplus) const {
vector<double> nullPDFCacheVector;
- for( size_t f=0; f<NHeavyJetVec().size(); ++f ) nullPDFCacheVector.push_back(0.0);
+ // for( size_t f=0; f<NHeavyJetVec().size(); ++f ) nullPDFCacheVector.push_back(0.0);
+ for( size_t f=0; f<lastBorn()->nHeavyJetVec().size(); ++f ) nullPDFCacheVector.push_back(0.0);
nullPDFCacheVector.push_back(0.0);
nullPDFCacheVector.push_back(0.0);
int pdfFCacheID = 1+F;
map<pair<tcPDFPtr,tcPDPtr>,vector<double> >::iterator cached = pdfCache.find(make_pair(pdf,pd));
if ( cached == pdfCache.end() ) {
pdfCache[make_pair(pdf,pd)] = nullPDFCacheVector;
cached = pdfCache.find(make_pair(pdf,pd));
}
// The convention of the pdf sets is always to return a*f(a). Upon usage,
// we have to remember that and rescale the result of the pdf accordingly
// again, i.e. a*f(a)/a.
if ( cached->second.at(pdfFCacheID) == 0.0 ) cached->second.at(pdfFCacheID) = pdf->xfx(particle,pd,scale,x/zplus)*zplus/x;
return cached->second.at(pdfFCacheID);
}
//////////////////////////////////////////////////////////////////////
void DipoleMPKOperator::persistentOutput(PersistentOStream & os) const {
os << CA << CF << gammaQuark << gammaGluon << KQuark << KGluon
<< ounit(scale,GeV2) << pdf << particle << x << z << pdfCache << parton;
}
void DipoleMPKOperator::persistentInput(PersistentIStream & is, int) {
is >> CA >> CF >> gammaQuark >> gammaGluon >> KQuark >> KGluon
>> iunit(scale,GeV2) >> pdf >> particle >> x >> z >> pdfCache >> parton;
}
// *** 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<DipoleMPKOperator,MatchboxInsertionOperator>
describeHerwigDipoleMPKOperator("Herwig::DipoleMPKOperator", "Herwig.so");
void DipoleMPKOperator::Init() {
static ClassDocumentation<DipoleMPKOperator> documentation
("DipoleMPKOperator");
DipoleRepository::registerInsertionPKOperator<0,DipoleMPKOperator>("MassivePKOperator");
}
diff --git a/MatrixElement/Matchbox/InsertionOperators/DipolePKOperator.cc b/MatrixElement/Matchbox/InsertionOperators/DipolePKOperator.cc
--- a/MatrixElement/Matchbox/InsertionOperators/DipolePKOperator.cc
+++ b/MatrixElement/Matchbox/InsertionOperators/DipolePKOperator.cc
@@ -1,672 +1,678 @@
// -*- C++ -*-
//
// DipolePKOperator.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 DipolePKOperator class.
//
#include "DipolePKOperator.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Utilities/Rebinder.h"
#include "ThePEG/StandardModel/StandardModelBase.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Utilities/Throw.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/MatrixElement/Matchbox/Base/DipoleRepository.h"
#include "Herwig++/MatrixElement/Matchbox/Phasespace/RandomHelpers.h"
#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.h"
using namespace Herwig;
using Constants::pi;
DipolePKOperator::DipolePKOperator()
: MatchboxInsertionOperator(),
CA(-1.0), CF(-1.0),
gammaQuark(-1.0), gammaGluon(-1.0),
KQuark(-1.0), KGluon(-1.0) {}
DipolePKOperator::~DipolePKOperator() {}
IBPtr DipolePKOperator::clone() const {
return new_ptr(*this);
}
IBPtr DipolePKOperator::fullclone() const {
return new_ptr(*this);
}
//////////////////////////////////////////////////////////////////////
bool DipolePKOperator::apply(const cPDVector& pd) const {
// DipolePKOperator should only apply if in the overall
// process only massless partons can occur.
if ( !apply(pd[0]) && !apply(pd[1]) ) {
return false;
}
// Prohibit splittings g->Q\bar{Q} in the final state.
// These are covered completely by DipoleMPKOperator.
if ( NHeavyJetVec().size()!=0 ) {
return false;
}
bool first = false;
bool second = false;
for ( cPDVector::const_iterator p = pd.begin();
p != pd.end(); ++p ) {
// Since this loop only checks for at least one exis-
// ting combination: Return false if any massive par-
// tons are present (covered by DipoleMPKOperator).
if ( (*p)->coloured() && (*p)->mass()!=ZERO ) {
return false;
}
if ( !first ) {
if ( apply(*p) )
first = true;
} else {
if ( apply(*p) )
second = true;
}
}
return first && second;
}
bool DipolePKOperator::apply(tcPDPtr pd) const {
return
pd->mass() == ZERO &&
(abs(pd->id()) < 7 || pd->id() == ParticleID::g);
}
void DipolePKOperator::setXComb(tStdXCombPtr xc) {
MatchboxInsertionOperator::setXComb(xc);
if ( CA < 0. ) {
CA = SM().Nc();
CF = (SM().Nc()*SM().Nc()-1.0)/(2.*SM().Nc());
gammaQuark = (3./2.)*CF;
- gammaGluon = (11./6.)*CA - (1./3.)*NLightJetVec().size();
+ // gammaGluon = (11./6.)*CA - (1./3.)*NLightJetVec().size();
+ gammaGluon = (11./6.)*CA - (1./3.)*lastBorn()->nLightJetVec().size();
KQuark = (7./2.-sqr(pi)/6.)*CF;
- KGluon = (67./18.-sqr(pi)/6.)*CA-(5./9.)*NLightJetVec().size();
+ // KGluon = (67./18.-sqr(pi)/6.)*CA-(5./9.)*NLightJetVec().size();
+ KGluon = (67./18.-sqr(pi)/6.)*CA-(5./9.)*lastBorn()->nLightJetVec().size();
if ( isDR() ) {
gammaQuark -= CF/2.;
gammaGluon -= CA/6.;
}
}
}
//////////////////////////////////////////////////////////////////////
vector<int> DipolePKOperator::NLightJetVec() const {
// const map<string,PDVector>& theParticleGroups = MatchboxFactory::currentFactory()->particleGroups();
const map<string,PDVector>& theParticleGroups = factory()->particleGroups();
map<string,PDVector>::const_iterator theIt = theParticleGroups.find("j");
if ( theIt == theParticleGroups.end() )
throw Exception() << "DipolePKOperator::NLightJetVec(): Could not find a jet particle group named 'j'" << Exception::abortnow;
const PDVector& theJetConstitutents = theIt->second;
vector<int> theNLightJetVec;
for ( PDVector::const_iterator theP = theJetConstitutents.begin();
theP != theJetConstitutents.end(); ++theP ) {
if ( (**theP).id() > 0 && (**theP).id() < 7 && (**theP).mass() == ZERO )
theNLightJetVec.push_back( (**theP).id() );
}
return theNLightJetVec;
}
vector<int> DipolePKOperator::NHeavyJetVec() const {
// const map<string,PDVector>& theParticleGroups = MatchboxFactory::currentFactory()->particleGroups();
const map<string,PDVector>& theParticleGroups = factory()->particleGroups();
map<string,PDVector>::const_iterator theIt = theParticleGroups.find("j");
if ( theIt == theParticleGroups.end() )
throw Exception() << "DipolePKOperator::NHeavyJetVec(): Could not find a jet particle group named 'j'" << Exception::abortnow;
const PDVector& theJetConstitutents = theIt->second;
vector<int> theNHeavyJetVec;
for ( PDVector::const_iterator theP = theJetConstitutents.begin();
theP != theJetConstitutents.end(); ++theP ) {
if ( (**theP).id() > 0 && (**theP).id() < 7 && (**theP).mass() != ZERO )
theNHeavyJetVec.push_back( (**theP).id() );
}
return theNHeavyJetVec;
}
vector<int> DipolePKOperator::NLightBornVec() const {
// For the moment just count all quark and antiquark
// constituents in the Born process.
vector<int> theNLightBornVec;
for ( cPDVector::const_iterator j = mePartonData().begin();
j != mePartonData().end(); ++j ) {
if ( abs((**j).id()) < 7 && (**j).mass() == ZERO )
theNLightBornVec.push_back( (**j).id() );
}
return theNLightBornVec;
}
vector<int> DipolePKOperator::NHeavyBornVec() const {
// For the moment just count all quark and antiquark
// constituents in the Born process.
vector<int> theNHeavyBornVec;
for ( cPDVector::const_iterator j = mePartonData().begin();
j != mePartonData().end(); ++j ) {
if ( abs((**j).id()) < 7 && (**j).mass() != ZERO )
theNHeavyBornVec.push_back( (**j).id() );
}
return theNHeavyBornVec;
}
vector<int> DipolePKOperator::NLightProtonVec() const {
// const map<string,PDVector>& theParticleGroups = MatchboxFactory::currentFactory()->particleGroups();
const map<string,PDVector>& theParticleGroups = factory()->particleGroups();
map<string,PDVector>::const_iterator theIt = theParticleGroups.find("p");
if ( theIt == theParticleGroups.end() )
throw Exception() << "DipolePKOperator::NLightProtonVec(): Could not find a proton particle group named 'p'" << Exception::abortnow;
const PDVector& theProtonConstitutents = theIt->second;
vector<int> theNLightProtonVec;
for ( PDVector::const_iterator theP = theProtonConstitutents.begin();
theP != theProtonConstitutents.end(); ++theP ) {
if ( (**theP).id() > 0 && (**theP).id() < 7 && (**theP).mass() == ZERO )
theNLightProtonVec.push_back( (**theP).id() );
}
return theNLightProtonVec;
}
//////////////////////////////////////////////////////////////////////
double DipolePKOperator::me2() const {
scale = lastBorn()->lastScale();
double res = 0.0;
if ( apply(mePartonData()[0]) ) {
if ( mePartonData()[0]->coloured() ) {
if ( mePartonData()[1]->coloured() )
res += lastBorn()->pdf2()*sumParton(0);
else
res += sumParton(0);
}
}
if ( apply(mePartonData()[1]) ) {
if ( mePartonData()[1]->coloured() ) {
if ( mePartonData()[0]->coloured() )
res += lastBorn()->pdf1()*sumParton(1);
else
res += sumParton(1);
}
}
return (lastBorn()->lastAlphaS()/(2.*pi)) * res;
}
//////////////////////////////////////////////////////////////////////
double DipolePKOperator::sumParton(int id) const {
// sumParton(int id) sums for a specific id=a'=0,1
// over all a (see CS paper)
pdf =
id == 0 ?
lastXCombPtr()->partonBins().first->pdf() :
lastXCombPtr()->partonBins().second->pdf();
x =
id == 0 ?
lastXCombPtr()->lastX1() :
lastXCombPtr()->lastX2();
parton =
id == 0 ?
mePartonData()[0] :
mePartonData()[1];
particle =
id == 0 ?
lastParticles().first->dataPtr() :
lastParticles().second->dataPtr();
using namespace RandomHelpers;
double r = insertionRandomNumbers().front();
double eps = 1e-3;
pair<double,double> zw =
generate((piecewise(),
flat(0.0,x),
match(inverse(0.0,x,1.0) + inverse(1.0+eps,x,1.0))),r);
z = zw.first;
double mapz = zw.second;
// For every new momentum fraction at which we want to evaluate a pdf
// we introduce a new member to the pdf cache: Initialize the cache.
for ( map<pair<tcPDFPtr,tcPDPtr>,pair<double,double> >::iterator cache =
pdfCache.begin(); cache != pdfCache.end(); ++cache )
cache->second = make_pair(0.0,0.0);
assert(pdf);
double res = 0.;
////////////////////////////
// K operator //
// non-color correlated //
////////////////////////////
if ( mePartonData()[id]->id() == ParticleID::g )
res += (KBargg() + KBarqg())*lastBorn()->me2();
if ( abs(mePartonData()[id]->id()) < 7 )
res += (KBarqq() + KBargq())*lastBorn()->me2();
////////////////////////////
double theGammaSoft = 0.0;
double thePqq = 0.0;
double thePqg = 0.0;
double thePgq = 0.0;
double thePgg = 0.0;
double ifCorrelated = 0.0;
double fiCorrelated = 0.0;
int idi = 2;
vector<Lorentz5Momentum>::const_iterator Pi = meMomenta().begin() + 2;
double disFinite = 0.0;
double glueFinite = 0.0;
//////////////////////////////////////////////////////////
// Initial-Final and Final-Initial contributions //
//////////////////////////////////////////////////////////
for ( cPDVector::const_iterator i = mePartonData().begin() + 2;
i != mePartonData().end(); ++i, ++Pi, ++idi ) {
if ( !apply(*i) || lastBorn()->noDipole(idi,id) )
continue;
fiCorrelated = lastBorn()->colourCorrelatedME2(make_pair(idi,id));
ifCorrelated = lastBorn()->colourCorrelatedME2(make_pair(id,idi));
if ( theGammaSoft == 0.0 )
theGammaSoft = gammaSoft();
if ( mePartonData()[id]->id() == ParticleID::g &&
thePgg == 0.0 ) {
thePqg = Pqg();
thePgg = Pgg();
}
if ( abs(mePartonData()[id]->id()) < 7 &&
thePqq == 0.0 ) {
thePgq = Pgq();
thePqq = Pqq();
}
//////////////////////////
// K operator, the rest //
//////////////////////////
// Last term in massless K operator in (C.31) in massless paper
res +=
( (**i).id() == ParticleID::g ? gammaGluon : gammaQuark ) *
theGammaSoft * fiCorrelated;
////////////////
// P operator //
////////////////
// The extra terms, which render the dipole kernels
// positive definite, are subtracted here again in
// integrated form (disfinite and gluefinite).
double theLog = log(scale/(2.*((*Pi)*meMomenta()[id])));
// Note: In the CS paper theLog is given by
// \log(\mu_F^2/(2zp_Ip_a)) = \log(\mu_F^2/(2p_Ip_a'))
// Note: The AP splitting kernels P^{aa'} contain plus
// distributions
// Note however: In our implementation p_Ip_a' is kept
// fixed, so we don't have a z dependence there
if ( mePartonData()[id]->id() == ParticleID::g ) {
res +=
( thePgg + thePqg ) * theLog * ifCorrelated;
}
if ( abs(mePartonData()[id]->id()) < 7 ) {
res +=
( thePqq + thePgq ) * theLog * ifCorrelated;
if ( disFinite == 0.0 && z > x ) {
disFinite = CF*PDFxByz(parton)*(1.+3.*z/2.)/z;
}
if ( z > x )
res -= disFinite*ifCorrelated;
}
if ( abs(mePartonData()[idi]->id()) < 7 ) {
if ( disFinite == 0.0 && z > x ) {
disFinite = CF*PDFxByz(parton)*(1.+3.*z/2.)/z;
}
if ( z > x )
res -= disFinite*fiCorrelated;
}
if ( mePartonData()[idi]->id() == ParticleID::g ) {
if ( glueFinite == 0.0 && z > x ) {
glueFinite = 2.*CA*PDFxByz(parton)*(1.+z/6.)/z;
}
if ( z > x )
res -= glueFinite*fiCorrelated;
}
} // end loop over i
//////////////////////////////////////////////////////////
// Initial-Initial contributions //
//////////////////////////////////////////////////////////
if ( mePartonData()[ id == 0 ? 1 : 0 ]->coloured() &&
!lastBorn()->noDipole(id == 0 ? 0 : 1,
id == 0 ? 1 : 0) ) {
if ( mePartonData()[id]->id() == ParticleID::g &&
thePgg == 0.0 ) {
thePqg = Pqg();
thePgg = Pgg();
}
if ( abs(mePartonData()[id]->id()) < 7 &&
thePqq == 0.0 ) {
thePgq = Pgq();
thePqq = Pqq();
}
double theLog = log(scale/(2.*(meMomenta()[0]*meMomenta()[1])));
// Note: In the CS paper theLog is given by
// \log(\mu_F^2/(2zp_Ip_a)) = \log(\mu_F^2/(2p_Ip_a'))
// Note: The AP splitting kernels P^{aa'} contain plus
// distributions
// Note however: In our implementation p_Ip_a' is kept
// fixed, so we don't have a z dependence there
pair<int,int> corr = id == 0 ? make_pair(0,1) : make_pair(1,0);
double iiCorrelated = lastBorn()->colourCorrelatedME2(corr);
if ( mePartonData()[id]->id() == ParticleID::g ) {
res +=
( thePgg + thePqg ) * theLog * iiCorrelated;
res -=
( KTildegg() + KTildeqg() ) * iiCorrelated;
}
if ( abs(mePartonData()[id]->id()) < 7 ) {
res +=
( thePqq + thePgq ) * theLog * iiCorrelated;
res -=
( KTildeqq() + KTildegq() ) * iiCorrelated;
}
}
//////////////////////////////////////////////////////////
return res * mapz;
}
//////////////////////////////////////////////////////////////////////
double DipolePKOperator::gammaSoft() const {
double res = (1.+log(1.-x))*PDFx(parton);
if ( z > x )
res +=
(PDFxByz(parton) - z*PDFx(parton)) / (z*(1.-z));
return res;
}
double DipolePKOperator::softLogByz(tcPDPtr p) const {
double res = ( sqr(log(1.-x))/2. - sqr(pi)/6. ) * PDFx(p);
if ( z > x ) {
res += (PDFxByz(p) - z*PDFx(p))*log(1.-z)/(z*(1.-z));
res -= PDFxByz(p)*log(z)/(z*(1.-z));
}
return res;
}
double DipolePKOperator::softLog(tcPDPtr p) const {
double res = sqr(log(1.-x)) * PDFx(p) / 2.;
if ( z > x ) {
res += (PDFxByz(p) - z*PDFx(p))*log(1.-z)/(z*(1.-z));
}
return res;
}
double DipolePKOperator::KBarqq() const {
assert(abs(parton->id()) < 7);
double res =
2.*softLogByz(parton) +
(sqr(pi) - 5.)*PDFx(parton);
if ( z > x ) {
res += PDFxByz(parton)*( (1.-z) - (1.+z)*log((1.-z)/z) ) / z;
}
return (res * CF);
}
double DipolePKOperator::KTildeqq() const {
assert(abs(parton->id()) < 7);
double res =
2.*CF*softLog(parton) - CF*(sqr(pi)/3.)*PDFx(parton);
if ( z > x ) {
res -= ( CF * (1.+z) * log(1.-z) ) * PDFxByz(parton) / z;
}
return res;
}
double DipolePKOperator::Pqq() const {
assert(abs(parton->id()) < 7);
double res = (3./2.+2.*log(1.-x)) * PDFx(parton);
if ( z > x ) {
res += 2.*(PDFxByz(parton) - z*PDFx(parton))/(z*(1.-z));
res -= PDFxByz(parton) * (1.+z)/z;
}
return (CF*res);
}
double DipolePKOperator::KBarqg() const {
assert(parton->id() == ParticleID::g);
if ( z < x )
return 0.0;
double res = 0.0;
double factor = CF * ( ( (1.+sqr(1.-z)) / z ) * log((1.-z)/z) + z ) / z;
- int nlp = NLightProtonVec().size();
+ // int nlp = NLightProtonVec().size();
+ int nlp = lastBorn()->nLightProtonVec().size();
for ( int f = -nlp; f <= nlp; ++f ) {
if ( f == 0 )
continue;
res += PDFxByz(getParticleData(f))*factor;
}
return res;
}
double DipolePKOperator::KTildeqg() const {
if ( z < x )
return 0.0;
return Pqg() * log(1.-z);
}
double DipolePKOperator::Pqg() const {
assert(parton->id() == ParticleID::g);
if ( z < x )
return 0.0;
double res = 0.0;
double factor = CF * ( 1. + sqr(1.-z) ) / sqr(z);
- int nlp = NLightProtonVec().size();
+ // int nlp = NLightProtonVec().size();
+ int nlp = lastBorn()->nLightProtonVec().size();
for ( int f = -nlp; f <= nlp; ++f ) {
if ( f == 0 )
continue;
res += PDFxByz(getParticleData(f))*factor;
}
return res;
}
double DipolePKOperator::KBargq() const {
assert(abs(parton->id()) < 7);
if ( z < x )
return 0.0;
return
PDFxByz(getParticleData(ParticleID::g)) *
( 0.5*(sqr(z)+sqr(1.-z))*log((1.-z)/z) + z*(1.-z) ) / z;
}
double DipolePKOperator::KTildegq() const {
assert(abs(parton->id()) < 7);
if ( z < x )
return 0.0;
return Pgq() * log(1.-z);
}
double DipolePKOperator::Pgq() const {
assert(abs(parton->id()) < 7);
if ( z < x )
return 0.0;
return 0.5 * ( sqr(z) + sqr(1.-z) ) * PDFxByz(getParticleData(ParticleID::g)) / z;
}
double DipolePKOperator::KBargg() const {
assert(parton->id() == ParticleID::g);
double res =
2.* CA* softLogByz(parton) +
- ( CA*( sqr(pi) - 50./9. ) + (8./9.)*NLightJetVec().size() ) * PDFx(parton);
+ // ( CA*( sqr(pi) - 50./9. ) + (8./9.)*NLightJetVec().size() ) * PDFx(parton);
+ ( CA*( sqr(pi) - 50./9. ) + (8./9.)*lastBorn()->nLightJetVec().size() ) * PDFx(parton);
if ( z > x ) {
res += 2.*CA*((1.-z)/z-1.+z*(1.-z))*log((1.-z)/z)*PDFxByz(parton)/z;
}
return res;
}
double DipolePKOperator::KTildegg() const {
assert(parton->id() == ParticleID::g);
double res =
2.*CA*softLog(parton) - CA*(sqr(pi)/3.)*PDFx(parton);
if ( z > x ) {
res += ( 2.*CA * ( (1.-z)/z -1. + z*(1.-z) ) * log(1.-z) ) * PDFxByz(parton) / z;
}
return res;
}
double DipolePKOperator::Pgg() const {
assert(parton->id() == ParticleID::g);
double res =
- ( (11./6.) * CA - (1./3.)*NLightJetVec().size() + 2.*CA*log(1.-x) ) * PDFx(parton);
+ // ( (11./6.) * CA - (1./3.)*NLightJetVec().size() + 2.*CA*log(1.-x) ) * PDFx(parton);
+ ( (11./6.) * CA - (1./3.)*lastBorn()->nLightJetVec().size() + 2.*CA*log(1.-x) ) * PDFx(parton);
if ( z > x ) {
res += 2. * CA * ( PDFxByz(parton) - z*PDFx(parton) ) / (z*(1.-z));
res += 2.* CA *( (1.-z)/z - 1. + z*(1.-z) ) * PDFxByz(parton) / z;
}
return res;
}
//////////////////////////////////////////////////////////////////////
// For every new momentum fraction at which we want to evaluate a pdf
// we introduce a new member to the pdf cache.
double DipolePKOperator::PDFx(tcPDPtr pd) const {
map<pair<tcPDFPtr,tcPDPtr>,pair<double,double> >::iterator
cached = pdfCache.find(make_pair(pdf,pd));
if ( cached == pdfCache.end() ) {
pdfCache[make_pair(pdf,pd)] = make_pair(0.0,0.0);
cached = pdfCache.find(make_pair(pdf,pd));
}
// The convention of the pdf sets is always to return a*f(a). Upon usage,
// we have to remember that and rescale the result of the pdf accordingly
// again, i.e. a*f(a)/a.
if ( cached->second.first == 0.0 )
cached->second.first =
pdf->xfx(particle,pd,scale,x)/x;
return cached->second.first;
}
double DipolePKOperator::PDFxByz(tcPDPtr pd) const {
map<pair<tcPDFPtr,tcPDPtr>,pair<double,double> >::iterator
cached = pdfCache.find(make_pair(pdf,pd));
if ( cached == pdfCache.end() ) {
pdfCache[make_pair(pdf,pd)] = make_pair(0.0,0.0);
cached = pdfCache.find(make_pair(pdf,pd));
}
// The convention of the pdf sets is always to return a*f(a). Upon usage,
// we have to remember that and rescale the result of the pdf accordingly
// again, i.e. a*f(a)/a.
if ( cached->second.second == 0.0 )
cached->second.second =
pdf->xfx(particle,pd,scale,x/z)*z/x;
return cached->second.second;
}
//////////////////////////////////////////////////////////////////////
void DipolePKOperator::persistentOutput(PersistentOStream & os) const {
os << CA << CF << gammaQuark << gammaGluon << KQuark << KGluon
<< ounit(scale,GeV2) << pdf << particle << x << z << pdfCache << parton;
}
void DipolePKOperator::persistentInput(PersistentIStream & is, int) {
is >> CA >> CF >> gammaQuark >> gammaGluon >> KQuark >> KGluon
>> iunit(scale,GeV2) >> pdf >> particle >> x >> z >> pdfCache >> parton;
}
// *** 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<DipolePKOperator,MatchboxInsertionOperator>
describeHerwigDipolePKOperator("Herwig::DipolePKOperator", "Herwig.so");
void DipolePKOperator::Init() {
static ClassDocumentation<DipolePKOperator> documentation
("DipolePKOperator");
DipoleRepository::registerInsertionPKOperator<0,DipolePKOperator>("LightPKOperator");
}
diff --git a/MatrixElement/Matchbox/MatchboxFactory.cc b/MatrixElement/Matchbox/MatchboxFactory.cc
--- a/MatrixElement/Matchbox/MatchboxFactory.cc
+++ b/MatrixElement/Matchbox/MatchboxFactory.cc
@@ -1,1870 +1,1877 @@
// -*- 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 <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) {}
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);
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 InitException()
<< "Ambiguous amplitude setup - please check your input files.\n"
<< "To avoid this problem use the SelectAmplitudes or DeselectAmplitudes interfaces.\n";
}
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 InitException() << "Matrix element " << pname << " already existing.";
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()
<< "At least one cross section contribution needs to be enabled.\n"
<< "Please check your setup.\n"
<< Exception::abortnow;
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 ( 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() << "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::abortnow;
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 InitException() << "Could not find a jet particle group named 'j'";
// 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).mass() == ZERO )
++nl;
if ( (**p).id() > 0 && (**p).id() < 7 && (**p).mass() == ZERO )
nLightJetVec( (**p).id() );
if ( (**p).id() > 0 && (**p).id() < 7 && (**p).mass() != ZERO )
nHeavyJetVec( (**p).id() );
}
nLight(nl/2);
const PDVector& partonsInP = particleGroups()["p"];
for ( PDVector::const_iterator pip = partonsInP.begin();
pip != partonsInP.end(); ++pip ) {
if ( (**pip).id() > 0 && (**pip).id() < 7 && (**pip).mass() == 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()))
&& realEmissionMEs().empty() ) {
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()))
&& realEmissionMEs().empty() ) {
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 InitException() << "No matrix elements have been found.\n\
Please check if your order of Alpha_s and Alpha_ew have the right value.\n";
// 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 InitException() << "Could not find amplitudes for all virtual contributions needed.\n";
}
if ( virtualsAreDR && virtualsAreCDR ) {
throw InitException() << "Virtual corrections use inconsistent regularization schemes.\n";
}
if ( (virtualsAreCS && virtualsAreBDK) ||
(virtualsAreCS && virtualsAreExpanded) ||
(virtualsAreBDK && virtualsAreExpanded) ||
(!virtualsAreCS && !virtualsAreBDK && !virtualsAreExpanded) ) {
throw InitException() << "Virtual corrections use inconsistent conventions on finite terms.\n";
}
}
// 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() && 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 ( independentVirtuals() )
pname += ".Born";
if ( ! (generator()->preinitRegister(bornme,pname) ) )
throw InitException() << "Matrix element " << pname << " already existing.";
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 InitException() << "Matrix element " << pname << " already existing.";
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 InitException() << "NLO ME " << pname << " already existing.";
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 InitException() << "No insertion operators have been found for "
<< (**born).name() << "\n";
if ( checkPoles() ) {
if ( !virtualsAreExpanded ) {
throw InitException() << "Cannot check epsilon poles if virtuals are not in `expanded' convention.\n";
}
}
}
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 InitException() << "NLO ME " << pnamepk << " already existing.";
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 InitException() << "Subtracted ME " << pname << " already existing.";
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 InitException() << "ME " << qname << " already existing.";
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 InitException() << "Subtracted ME " << vname << " already existing.";
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 InitException() << "Subtracted ME " << vname << " already existing.";
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 InitException() << "Dipole '" << dname << "' already existing.";
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 InitException()
<< "error: failed to initialize amplitude '" << (**ext).name() << "'\n";
}
}
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 InitException()
<< "error: failed to start OLP for amplitude '" << olpit->first->name() << "'\n";
}
}
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>::ptr>::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::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);
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;
}
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;
}
string MatchboxFactory::startParticleGroup(string name) {
particleGroupName = StringUtils::stripws(name);
particleGroup.clear();
return "";
}
string MatchboxFactory::endParticleGroup(string) {
if ( particleGroup.empty() )
throw InitException() << "Empty particle group.";
particleGroups()[particleGroupName] = particleGroup;
particleGroup.clear();
return "";
}
string MatchboxFactory::doProcess(string in) {
vector<string> process = StringUtils::split(in);
if ( process.size() < 3 )
throw InitException() << "Invalid process.";
for ( vector<string>::iterator p = process.begin();
p != process.end(); ++p ) {
*p = StringUtils::stripws(*p);
}
processes.push_back(process);
return "";
}
string MatchboxFactory::doLoopInducedProcess(string in) {
vector<string> loopInducedProcess = StringUtils::split(in);
if ( loopInducedProcess.size() < 3 )
throw InitException() << "Invalid process.";
for ( vector<string>::iterator p = loopInducedProcess.begin();
p != loopInducedProcess.end(); ++p ) {
*p = StringUtils::stripws(*p);
}
loopInducedProcesses.push_back(loopInducedProcess);
return "";
}
string MatchboxFactory::doSingleRealProcess(string in) {
vector<string> realEmissionProcess = StringUtils::split(in);
if ( realEmissionProcess.size() < 3 )
throw InitException() << "Invalid process.";
for ( vector<string>::iterator p = realEmissionProcess.begin();
p != realEmissionProcess.end(); ++p ) {
*p = StringUtils::stripws(*p);
}
realEmissionProcesses.push_back(realEmissionProcess);
return "";
}
struct SortPID {
inline bool operator()(PDPtr a, PDPtr b) const {
return a->id() < b->id();
}
};
set<PDVector> MatchboxFactory::
makeSubProcesses(const vector<string>& proc) const {
if ( proc.empty() )
throw InitException() << "No process specified.";
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 InitException() << "particle group '"
<< *gr << "' not defined.";
}
groups.push_back(git->second);
}
vector<size_t> counts(groups.size(),0);
PDVector proto(groups.size());
set<PDVector> allProcs;
/*
cerr << "using the groups:\n";
for ( size_t k = 0; k < groups.size(); ++k ) {
cerr << k << " : ";
for ( PDVector::const_iterator p = groups[k].begin();
p != groups[k].end(); ++p )
cerr << (**p).PDGName() << " ";
cerr << "\n" << flush;
}
*/
while ( true ) {
for ( size_t k = 0; k < groups.size(); ++k )
proto[k] = groups[k][counts[k]];
/*
cerr << "trying : ";
for ( vector<size_t>::const_iterator c = counts.begin();
c != counts.end(); ++c )
cerr << *c << " ";
cerr << "\n" << flush;
for ( size_t k = 0; k < groups.size(); ++k )
cerr << groups[k][counts[k]]->PDGName() << " ";
cerr << "\n" << flush;
*/
int charge = -proto[0]->iCharge() -proto[1]->iCharge();
for ( size_t k = 2; k < proto.size(); ++k )
charge += proto[k]->iCharge();
if ( charge == 0 ) {
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{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 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);
}
// *** 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/MatchboxFactory.h b/MatrixElement/Matchbox/MatchboxFactory.h
--- a/MatrixElement/Matchbox/MatchboxFactory.h
+++ b/MatrixElement/Matchbox/MatchboxFactory.h
@@ -1,1201 +1,1213 @@
// -*- C++ -*-
//
// MatchboxFactory.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_MatchboxFactory_H
#define HERWIG_MatchboxFactory_H
//
// This is the declaration of the MatchboxFactory class.
//
#include "ThePEG/Handlers/SubProcessHandler.h"
#include "Herwig++/MatrixElement/Matchbox/Base/MatchboxAmplitude.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/Tree2toNGenerator.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/ProcessData.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/MatchboxScaleChoice.h"
#include "Herwig++/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h"
#include "Herwig++/MatrixElement/Matchbox/Base/MatchboxMEBase.h"
#include "Herwig++/MatrixElement/Matchbox/Base/SubtractedME.h"
#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.fh"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief MatchboxFactory automatically sets up a NLO
* QCD calculation carried out in dipole subtraction.
*
* @see \ref MatchboxFactoryInterfaces "The interfaces"
* defined for MatchboxFactory.
*/
class MatchboxFactory: public SubProcessHandler {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
MatchboxFactory();
/**
* The destructor.
*/
virtual ~MatchboxFactory();
//@}
public:
+ /**
+ * Flag to indicate that at least one MatchboxFactory object is in action
+ */
+ static bool isMatchboxRun() {
+ return theIsMatchboxRun();
+ }
+
/** @name Process and diagram information */
//@{
/**
* Return the diagram generator.
*/
Ptr<Tree2toNGenerator>::tptr diagramGenerator() const { return theDiagramGenerator; }
/**
* Set the diagram generator.
*/
void diagramGenerator(Ptr<Tree2toNGenerator>::ptr dg) { theDiagramGenerator = dg; }
/**
* Return the process data.
*/
Ptr<ProcessData>::tptr processData() const { return theProcessData; }
/**
* Set the process data.
*/
void processData(Ptr<ProcessData>::ptr pd) { theProcessData = pd; }
/**
* Return the number of light flavours, this matrix
* element is calculated for.
*/
unsigned int nLight() const { return theNLight; }
/**
* Set the number of light flavours, this matrix
* element is calculated for.
*/
void nLight(unsigned int n) { theNLight = n; }
/**
* Return the vector that contains the PDG ids of
* the light flavours, which are contained in the
* jet particle group.
*/
vector<int> nLightJetVec() const { return theNLightJetVec; }
/**
* Set the elements of the vector that contains the PDG
* ids of the light flavours, which are contained in the
* jet particle group.
*/
void nLightJetVec(int n) { theNLightJetVec.push_back(n); }
/**
* Return the vector that contains the PDG ids of
* the heavy flavours, which are contained in the
* jet particle group.
*/
vector<int> nHeavyJetVec() const { return theNHeavyJetVec; }
/**
* Set the elements of the vector that contains the PDG
* ids of the heavy flavours, which are contained in the
* jet particle group.
*/
void nHeavyJetVec(int n) { theNHeavyJetVec.push_back(n); }
/**
* Return the vector that contains the PDG ids of
* the light flavours, which are contained in the
* proton particle group.
*/
vector<int> nLightProtonVec() const { return theNLightProtonVec; }
/**
* Set the elements of the vector that contains the PDG
* ids of the light flavours, which are contained in the
* proton particle group.
*/
void nLightProtonVec(int n) { theNLightProtonVec.push_back(n); }
/**
* Return the order in \f$\alpha_S\f$.
*/
unsigned int orderInAlphaS() const { return theOrderInAlphaS; }
/**
* Set the order in \f$\alpha_S\f$.
*/
void orderInAlphaS(unsigned int o) { theOrderInAlphaS = o; }
/**
* Return the order in \f$\alpha_{EM}\f$.
*/
unsigned int orderInAlphaEW() const { return theOrderInAlphaEW; }
/**
* Set the order in \f$\alpha_{EM}\f$.
*/
void orderInAlphaEW(unsigned int o) { theOrderInAlphaEW = o; }
/**
* Return true, if all processes up to a maximum order are considered
*/
bool allProcesses() const { return theAllProcesses; }
/**
* Switch on/off inclusino off all processes up to a maximum order
*/
void setAllProcesses(bool on = true) { theAllProcesses = on; }
/**
* Return true, if Born contributions should be included.
*/
bool bornContributions() const { return theBornContributions; }
/**
* Switch on or off Born contributions
*/
void setBornContributions(bool on = true) { theBornContributions = on; }
/**
* Return true, if virtual contributions should be included.
*/
bool virtualContributions() const { return theVirtualContributions; }
/**
* Switch on or off virtual contributions
*/
void setVirtualContributions(bool on = true) { theVirtualContributions = on; }
/**
* Produce matrix element corrections, but no NLO
*/
bool meCorrectionsOnly() const { return theMECorrectionsOnly; }
/**
* Switch to produce matrix element corrections, but no NLO
*/
void setMECorrectionsOnly(bool on = true) { theMECorrectionsOnly = on; }
/**
* Produce matrix element corrections, with LoopSim NLO
*/
bool loopSimCorrections() const { return theLoopSimCorrections; }
/**
* Switch to produce matrix element corrections, with LoopSim NLO
*/
void setLoopSimCorrections(bool on = true) { theLoopSimCorrections = on; }
/**
* Return true, if subtracted real emission contributions should be included.
*/
bool realContributions() const { return theRealContributions; }
/**
* Switch on or off subtracted real emission contributions
*/
void setRealContributions(bool on = true) { theRealContributions = on; }
/**
* Return true, if virtual contributions should be treated as independent subprocesses
*/
bool independentVirtuals() const { return theIndependentVirtuals; }
/**
* Switch on/off virtual contributions should be treated as independent subprocesses
*/
void setIndependentVirtuals(bool on = true) { theIndependentVirtuals = on; }
/**
* Return true, if PK operator contributions should be treated as independent subprocesses
*/
bool independentPKs() const { return theIndependentPKs; }
/**
* Switch on/off PK operator contributions should be treated as independent subprocesses
*/
void setIndependentPKs(bool on = true) { theIndependentPKs = on; }
/**
* Return true, if SubProcessGroups should be
* setup from this MEGroup. If not, a single SubProcess
* is constructed from the data provided by the
* head matrix element.
*/
bool subProcessGroups() const { return theSubProcessGroups; }
/**
* Switch on or off producing subprocess groups.
*/
void setSubProcessGroups(bool on = true) { theSubProcessGroups = on; }
/**
* Return true, if subtraction scales should be caluclated from real emission kinematics
*/
bool realEmissionScales() const { return theRealEmissionScales; }
/**
* Switch on/off that subtraction scales should be caluclated from real emission kinematics
*/
void setRealEmissionScales(bool on = true) { theRealEmissionScales = on; }
/**
* Set the shower approximation.
*/
void showerApproximation(Ptr<ShowerApproximation>::tptr app) { theShowerApproximation = app; }
/**
* Return the shower approximation.
*/
Ptr<ShowerApproximation>::tptr showerApproximation() const { return theShowerApproximation; }
//@}
/** @name Phasespace generation and scale choice */
//@{
/**
* Return the phase space generator to be used.
*/
Ptr<MatchboxPhasespace>::tptr phasespace() const { return thePhasespace; }
/**
* Set the phase space generator to be used.
*/
void phasespace(Ptr<MatchboxPhasespace>::ptr ps) { thePhasespace = ps; }
/**
* Set the scale choice object
*/
void scaleChoice(Ptr<MatchboxScaleChoice>::ptr sc) { theScaleChoice = sc; }
/**
* Return the scale choice object
*/
Ptr<MatchboxScaleChoice>::tptr scaleChoice() const { return theScaleChoice; }
/**
* 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; }
/**
* Return true, if fixed couplings are used.
*/
bool fixedCouplings() const { return theFixedCouplings; }
/**
* Switch on fixed couplings.
*/
void setFixedCouplings(bool on = true) { theFixedCouplings = on; }
/**
* Return true, if fixed couplings are used.
*/
bool fixedQEDCouplings() const { return theFixedQEDCouplings; }
/**
* Switch on fixed couplings.
*/
void setFixedQEDCouplings(bool on = true) { theFixedQEDCouplings = on; }
/**
* Return true, if veto scales should be set
* for the real emission
*/
bool vetoScales() const { return theVetoScales; }
/**
* Switch on setting veto scales
*/
void doVetoScales() { theVetoScales = true; }
/**
* Switch off setting veto scales
*/
void noVetoScales() { theVetoScales = true; }
//@}
/** @name Amplitudes and caching */
//@{
/**
* Return the amplitudes to be considered
*/
const vector<Ptr<MatchboxAmplitude>::ptr>& amplitudes() const { return theAmplitudes; }
/**
* Access the amplitudes to be considered
*/
vector<Ptr<MatchboxAmplitude>::ptr>& amplitudes() { return theAmplitudes; }
//@}
/** @name Matrix element objects. */
//@{
/**
* Return the Born matrix elements to be considered
*/
const vector<Ptr<MatchboxMEBase>::ptr>& bornMEs() const { return theBornMEs; }
/**
* Access the Born matrix elements to be considered
*/
vector<Ptr<MatchboxMEBase>::ptr>& bornMEs() { return theBornMEs; }
/**
* Return the loop induced matrix elements to be considered
*/
const vector<Ptr<MatchboxMEBase>::ptr>& loopInducedMEs() const { return theLoopInducedMEs; }
/**
* Access the loop induced matrix elements to be considered
*/
vector<Ptr<MatchboxMEBase>::ptr>& loopInducedMEs() { return theLoopInducedMEs; }
/**
* Return the processes to be ordered from an OLP
*/
const map<Ptr<MatchboxAmplitude>::tptr,
map<pair<Process,int>,int> >&
olpProcesses() const { return theOLPProcesses; }
/**
* Access the processes to be ordered from an OLP
*/
map<Ptr<MatchboxAmplitude>::tptr,
map<pair<Process,int>,int> >&
olpProcesses() { return theOLPProcesses; }
/**
* Order an OLP process and return its id
*/
int orderOLPProcess(const Process& p,
Ptr<MatchboxAmplitude>::tptr amp,
int type);
/**
* Return the amplitudes which need external initialization
*/
const set<Ptr<MatchboxAmplitude>::tptr>& externalAmplitudes() const {
return theExternalAmplitudes;
}
/**
* Access the amplitudes which need external initialization
*/
set<Ptr<MatchboxAmplitude>::tptr>& externalAmplitudes() {
return theExternalAmplitudes;
}
/**
* Return the virtual corrections to be considered
*/
const vector<Ptr<MatchboxInsertionOperator>::ptr>& virtuals() const { return theVirtuals; }
/**
* Access the virtual corrections to be considered
*/
vector<Ptr<MatchboxInsertionOperator>::ptr>& virtuals() { return theVirtuals; }
/**
* Return the produced NLO matrix elements
*/
const vector<Ptr<MatchboxMEBase>::ptr>& bornVirtualMEs() const { return theBornVirtualMEs; }
/**
* Access the produced NLO matrix elements
*/
vector<Ptr<MatchboxMEBase>::ptr>& bornVirtualMEs() { return theBornVirtualMEs; }
/**
* Return the real emission matrix elements to be considered
*/
const vector<Ptr<MatchboxMEBase>::ptr>& realEmissionMEs() const { return theRealEmissionMEs; }
/**
* Access the real emission matrix elements to be considered
*/
vector<Ptr<MatchboxMEBase>::ptr>& realEmissionMEs() { return theRealEmissionMEs; }
/**
* Return, which set of dipoles should be considered
*/
int dipoleSet() const { return theDipoleSet; }
/**
* Return, which set of dipoles should be considered
*/
void dipoleSet(int s) { theDipoleSet = s; }
/**
* Return the produced subtracted matrix elements
*/
const vector<Ptr<SubtractedME>::ptr>& subtractedMEs() const { return theSubtractedMEs; }
/**
* Access the produced subtracted matrix elements
*/
vector<Ptr<SubtractedME>::ptr>& subtractedMEs() { return theSubtractedMEs; }
/**
* Return the produced finite real emission matrix elements
*/
const vector<Ptr<MatchboxMEBase>::ptr>& finiteRealMEs() const { return theFiniteRealMEs; }
/**
* Access the produced finite real emission elements
*/
vector<Ptr<MatchboxMEBase>::ptr>& finiteRealMEs() { return theFiniteRealMEs; }
/**
* Return the map of Born processes to splitting dipoles
*/
const map<cPDVector,set<Ptr<SubtractionDipole>::ptr> >& splittingDipoles() const {
return theSplittingDipoles;
}
/**
* Identify a splitting channel
*/
struct SplittingChannel {
/**
* The Born XComb
*/
StdXCombPtr bornXComb;
/**
* The real XComb
*/
StdXCombPtr realXComb;
/**
* The set of tilde XCombs to consider for the real xcomb
*/
vector<StdXCombPtr> tildeXCombs;
/**
* The dipole in charge of the splitting
*/
Ptr<SubtractionDipole>::ptr dipole;
/**
* Dump the setup
*/
void print(ostream&) const;
};
/**
* Generate all splitting channels for the Born process handled by
* the given XComb
*/
list<SplittingChannel> getSplittingChannels(tStdXCombPtr xc) const;
/**
* Return the reweight objects for matrix elements
*/
const vector<ReweightPtr>& reweighters() const { return theReweighters; }
/**
* Access the reweight objects for matrix elements
*/
vector<ReweightPtr>& reweighters() { return theReweighters; }
/**
* Return the preweight objects for matrix elements
*/
const vector<ReweightPtr>& preweighters() const { return thePreweighters; }
/**
* Access the preweight objects for matrix elements
*/
vector<ReweightPtr>& preweighters() { return thePreweighters; }
//@}
/** @name Setup the matrix elements */
//@{
/**
* Return true if this object needs to be initialized before all
* other objects (except those for which this function also returns
* true). This default version always returns false, but subclasses
* may override it to return true.
*/
virtual bool preInitialize() const { return true; }
/**
* Prepare a matrix element.
*/
void prepareME(Ptr<MatchboxMEBase>::ptr);
/**
* Check consistency and switch to porduction mode.
*/
void productionMode();
/**
* Setup everything
*/
virtual void setup();
/**
* The highest multiplicity of legs having virtual contributions.(needed for madgraph)
*/
size_t highestVirt(){return theHighestVirtualsize;}
//@}
/** @name Diagnostic information */
//@{
/**
* Return true, if verbose
*/
bool verbose() const { return theVerbose; }
/**
* Switch on diagnostic information.
*/
void setVerbose(bool on = true) { theVerbose = on; }
/**
* Return true, if diagram weight is verbose
*/
bool verboseDia() const { return theDiagramWeightVerbose; }
/**
* Number of bins for diagram weight verbosity
*/
int diagramWeightVerboseNBins() const {return theDiagramWeightVerboseNBins;}
/**
* Return true, if verbose while initializing
*/
bool initVerbose() const { return theInitVerbose || verbose(); }
/**
* Switch on diagnostic information while initializing
*/
void setInitVerbose(bool on = true) { theInitVerbose = on; }
/**
* Dump the setup
*/
void print(ostream&) const;
/**
* Return the subtraction data prefix.
*/
const string& subtractionData() const { return theSubtractionData; }
/**
* Set the subtraction data prefix.
*/
void subtractionData(const string& s) { theSubtractionData = s; }
/**
* Return the subtraction plot type.
*/
const int& subtractionPlotType() const { return theSubtractionPlotType; }
/**
* Set the subtraction plot type.
*/
void subtractionPlotType(const int& t) { theSubtractionPlotType = t; }
/**
* Return whether subtraction data should be plotted for all phase space points individually
*/
const bool& subtractionScatterPlot() const { return theSubtractionScatterPlot; }
/**
* Set whether subtraction data should be plotted for all phase space points individually
*/
void subtractionScatterPlot(const bool& s) { theSubtractionScatterPlot = s; }
/**
* Return the pole data prefix.
*/
const string& poleData() const { return thePoleData; }
/**
* Set the pole data prefix.
*/
void poleData(const string& s) { thePoleData = s; }
/**
* Return true, if cancellationn of epsilon poles should be checked.
*/
bool checkPoles() const { return poleData() != ""; }
//@}
/** @name Process generation */
//@{
/**
* Return the particle groups.
*/
const map<string,PDVector>& particleGroups() const { return theParticleGroups; }
/**
* Access the particle groups.
*/
map<string,PDVector>& particleGroups() { return theParticleGroups; }
/**
* Return true, if the given particle is incoming
*/
bool isIncoming(cPDPtr p) const {
return theIncoming.find(p->id()) != theIncoming.end();
}
/**
* Return true, if spin correlation information should be provided, if possible.
*/
bool spinCorrelations() const { return theSpinCorrelations; }
/**
* Indicate that spin correlation information should be provided, if possible.
*/
void setSpinCorrelations(bool yes) { theSpinCorrelations = yes; }
//@}
/** @name Truncated qtilde shower information */
//@{
/**
* Return the subprocess of the real emission
*/
tSubProPtr hardTreeSubprocess() { return theHardtreeSubprocess; }
/**
* Set the subprocess of the real emission for use in calculating the shower hardtree
*/
void setHardTreeSubprocess(tSubProPtr hardTree) { theHardtreeSubprocess = hardTree; }
/**
* Return the born emitter
*/
int hardTreeEmitter() { return theHardtreeEmitter; }
/**
* Set the born emitter for use in calculating the shower hardtree
*/
void setHardTreeEmitter(int emitter) { theHardtreeEmitter = emitter; }
//@}
/** @name Data handling */
//@{
/**
* Return (and possibly create) a directory to contain amplitude
* information.
*/
const string& buildStorage();
/**
* Return (and possibly create) a directory to contain integration grid
* information.
*/
const string& runStorage();
//@}
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. */
//@{
/**
* 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:
/**
+ * Flag to indicate that at least one MatchboxFactory object is in action
+ */
+ static bool& theIsMatchboxRun();
+
+ /**
* The diagram generator.
*/
Ptr<Tree2toNGenerator>::ptr theDiagramGenerator;
/**
* The process data object to be used
*/
Ptr<ProcessData>::ptr theProcessData;
/**
* The number of light flavours, this matrix
* element is calculated for.
*/
unsigned int theNLight;
/**
* Vector with the PDG ids of the light quark flavours,
* which are contained in the jet particle group.
*/
vector<int> theNLightJetVec;
/**
* Vector with the PDG ids of the heavy quark flavours,
* which are contained in the jet particle group.
*/
vector<int> theNHeavyJetVec;
/**
* Vector with the PDG ids of the light quark flavours,
* which are contained in the proton particle group.
*/
vector<int> theNLightProtonVec;
/**
* The order in \f$\alpha_S\f$.
*/
unsigned int theOrderInAlphaS;
/**
* The order in \f$\alpha_{EM}\f$.
*/
unsigned int theOrderInAlphaEW;
/**
* Switch on or off Born contributions
*/
bool theBornContributions;
/**
* Switch on or off virtual contributions
*/
bool theVirtualContributions;
/**
* Switch on or off subtracted real emission contributions should be included.
*/
bool theRealContributions;
/**
* True if virtual contributions should be treated as independent subprocesses
*/
bool theIndependentVirtuals;
/**
* True if PK operator contributions should be treated as independent subprocesses
*/
bool theIndependentPKs;
/**
* True, if SubProcessGroups should be
* setup from this MEGroup. If not, a single SubProcess
* is constructed from the data provided by the
* head matrix element.
*/
bool theSubProcessGroups;
/**
* The phase space generator to be used.
*/
Ptr<MatchboxPhasespace>::ptr thePhasespace;
/**
* The scale choice object
*/
Ptr<MatchboxScaleChoice>::ptr theScaleChoice;
/**
* The factorization scale factor.
*/
double theFactorizationScaleFactor;
/**
* The renormalization scale factor.
*/
double theRenormalizationScaleFactor;
/**
* Use non-running couplings.
*/
bool theFixedCouplings;
/**
* Use non-running couplings.
*/
bool theFixedQEDCouplings;
/**
* True, if veto scales should be set
* for the real emission
*/
bool theVetoScales;
/**
* The amplitudes to be considered
*/
vector<Ptr<MatchboxAmplitude>::ptr> theAmplitudes;
/**
* The Born matrix elements to be considered
*/
vector<Ptr<MatchboxMEBase>::ptr> theBornMEs;
/**
* The loop induced matrix elements to be considered
*/
vector<Ptr<MatchboxMEBase>::ptr> theLoopInducedMEs;
/**
* The virtual corrections to be considered
*/
vector<Ptr<MatchboxInsertionOperator>::ptr> theVirtuals;
/**
* The real emission matrix elements to be considered
*/
vector<Ptr<MatchboxMEBase>::ptr> theRealEmissionMEs;
/**
* The produced NLO matrix elements
*/
vector<Ptr<MatchboxMEBase>::ptr> theBornVirtualMEs;
/**
* The produced subtracted matrix elements
*/
vector<Ptr<SubtractedME>::ptr> theSubtractedMEs;
/**
* The produced finite real emission matrix elements
*/
vector<Ptr<MatchboxMEBase>::ptr> theFiniteRealMEs;
/**
* Which set of dipoles should be considered
*/
int theDipoleSet;
/**
* Switch on or off verbosity
*/
bool theVerbose;
/**
* Switch on or off diagram weight verbosity
*/
bool theDiagramWeightVerbose;
/**
* Number of bins for diagram weight verbosity
*/
int theDiagramWeightVerboseNBins;
/**
* True, if verbose while initializing
*/
bool theInitVerbose;
/**
* Prefix for subtraction data
*/
string theSubtractionData;
/**
* Set the type of plot that is to be generated for subtraction checking
*/
int theSubtractionPlotType;
/**
* Set whether subtraction data should be plotted for all phase space points individually
*/
bool theSubtractionScatterPlot;
/**
* Prefix for pole data.
*/
string thePoleData;
/**
* Command to limit the real emission process to be considered.
*/
string doSingleRealProcess(string);
/**
* The real emission process to be included; if empty, all possible
* ones will be considered.
*/
vector<vector<string> > realEmissionProcesses;
/**
* Particle groups.
*/
map<string,PDVector> theParticleGroups;
/**
* Command to start a particle group.
*/
string startParticleGroup(string);
/**
* The name of the particle group currently edited.
*/
string particleGroupName;
/**
* The particle group currently edited.
*/
PDVector particleGroup;
/**
* Command to end a particle group.
*/
string endParticleGroup(string);
/**
* Command to set the process.
*/
string doProcess(string);
/**
* Command to set the process.
*/
string doLoopInducedProcess(string);
/**
* The process to consider in terms of particle groups.
*/
vector<vector<string> > processes;
/**
* The loop induced process to consider in terms of particle groups.
*/
vector<vector<string> > loopInducedProcesses;
/**
* Generate subprocesses.
*/
set<PDVector> makeSubProcesses(const vector<string>&) const;
/**
* Generate matrix element objects for the given process.
*/
vector<Ptr<MatchboxMEBase>::ptr> makeMEs(const vector<string>&,
unsigned int orderas,
bool virt);
/**
* The shower approximation.
*/
Ptr<ShowerApproximation>::ptr theShowerApproximation;
/**
* The map of Born processes to splitting dipoles
*/
map<cPDVector,set<Ptr<SubtractionDipole>::ptr> > theSplittingDipoles;
/**
* True, if subtraction scales should be caluclated from real emission kinematics
*/
bool theRealEmissionScales;
/**
* Consider all processes with order in couplings specifying the
* maximum order.
*/
bool theAllProcesses;
/**
* The processes to be ordered from an OLP
*/
map<Ptr<MatchboxAmplitude>::tptr,map<pair<Process,int>,int> > theOLPProcesses;
/**
* Amplitudes which need external initialization
*/
set<Ptr<MatchboxAmplitude>::tptr> theExternalAmplitudes;
/**
* Amplitudes to be selected on clashing responsibilities.
*/
vector<Ptr<MatchboxAmplitude>::ptr> theSelectedAmplitudes;
/**
* Amplitudes to be deselected on clashing responsibilities.
*/
vector<Ptr<MatchboxAmplitude>::ptr> theDeselectedAmplitudes;
/**
* Reweight objects for matrix elements
*/
vector<ReweightPtr> theReweighters;
/**
* Preweight objects for matrix elements
*/
vector<ReweightPtr> thePreweighters;
/**
* Produce matrix element corrections, but no NLO
*/
bool theMECorrectionsOnly;
/**
* The highest multiplicity of legs having virtual contributions.(needed for madgraph)
*/
int theHighestVirtualsize;
/**
* Produce matrix element corrections, with LoopSim NLO
*/
bool theLoopSimCorrections;
/**
* True, if the setup has already been run.
*/
bool ranSetup;
/**
* PDG ids of incoming particles
*/
set<long> theIncoming;
/**
* True, if first incoming partons originate from perturbative PDF
*/
bool theFirstPerturbativePDF;
/**
* True, if second incoming partons originate from perturbative PDF
*/
bool theSecondPerturbativePDF;
/**
* True, if this Factory is in production mode.
*/
bool inProductionMode;
/**
* The real emission subprocess used when calculating the hardtree
* in the truncated qtilde shower
*/
tSubProPtr theHardtreeSubprocess;
/**
* The born emitter used when calculating the hardtree in
* the truncated shower
*/
int theHardtreeEmitter;
/**
* True, if spin correlation information should be provided, if possible.
*/
bool theSpinCorrelations;
/**
* Command for production mode
*/
string doProductionMode(string) {
productionMode(); return "";
}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MatchboxFactory & operator=(const MatchboxFactory &);
};
}
#endif /* HERWIG_MatchboxFactory_H */
diff --git a/MatrixElement/Matchbox/Matching/ShowerApproximationGenerator.cc b/MatrixElement/Matchbox/Matching/ShowerApproximationGenerator.cc
--- a/MatrixElement/Matchbox/Matching/ShowerApproximationGenerator.cc
+++ b/MatrixElement/Matchbox/Matching/ShowerApproximationGenerator.cc
@@ -1,485 +1,485 @@
// -*- C++ -*-
//
// ShowerApproximationGenerator.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 ShowerApproximationGenerator class.
//
#include <config.h>
#include "ShowerApproximationGenerator.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.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/PDT/EnumParticles.h"
#include "ThePEG/PDF/PartonExtractor.h"
#include "ThePEG/Cuts/Cuts.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
ShowerApproximationGenerator::ShowerApproximationGenerator()
: thePresamplingPoints(2000), theMaxTry(100000), theFreezeGrid(500000),
theDoCompensate(false) {}
ShowerApproximationGenerator::~ShowerApproximationGenerator() {}
double ShowerApproximationGenerator::generateFraction(tcPDPtr pd, double r, double xmin) const {
if ( pd->coloured() || pd->id() == ParticleID::gamma ) {
return pow(xmin,r);
}
double x0 = 1.e-5;
return 1. + x0 - x0*pow((1.+x0)/x0,r);
}
double ShowerApproximationGenerator::invertFraction(tcPDPtr pd, double x, double xmin) const {
if ( pd->coloured() || pd->id() == ParticleID::gamma ) {
return log(x)/log(xmin);
}
double x0 = 1.e-5;
return log((1.-x+x0)/x0)/log((1.+x0)/x0);
}
bool ShowerApproximationGenerator::prepare() {
tSubProPtr oldSub = lastIncomingXComb->subProcess();
tcStdXCombPtr cIncomingXC = lastIncomingXComb;
bool hasFractions =
thePhasespace->haveX1X2() ||
cIncomingXC->mePartonData().size() == 3;
theLastMomenta.resize(cIncomingXC->mePartonData().size());
if ( !hasFractions )
- theLastRandomNumbers.resize(thePhasespace->nDim(theLastMomenta.size()-2) + 2);
+ theLastRandomNumbers.resize(thePhasespace->nDim(cIncomingXC->mePartonData()) + 2);
else
- theLastRandomNumbers.resize(thePhasespace->nDim(theLastMomenta.size()-2));
+ theLastRandomNumbers.resize(thePhasespace->nDim(cIncomingXC->mePartonData()));
if ( !hasFractions ) {
double x1 =
oldSub->incoming().first->momentum().plus() /
lastIncomingXComb->lastParticles().first->momentum().plus();
theLastRandomNumbers[0] = invertFraction(oldSub->incoming().first->dataPtr(),x1,
lastIncomingXComb->cuts()->x1Min());
double x2 =
oldSub->incoming().second->momentum().minus() /
lastIncomingXComb->lastParticles().second->momentum().minus();
theLastRandomNumbers[1] = invertFraction(oldSub->incoming().second->dataPtr(),x2,
lastIncomingXComb->cuts()->x2Min());
}
Boost toCMS =
(oldSub->incoming().first->momentum() +
oldSub->incoming().second->momentum()).findBoostToCM();
theLastMomenta[0] = oldSub->incoming().first->momentum();
if ( !hasFractions )
theLastMomenta[0].boost(toCMS);
theLastMomenta[1] = oldSub->incoming().second->momentum();
if ( !hasFractions )
theLastMomenta[1].boost(toCMS);
ParticleVector::const_iterator out = oldSub->outgoing().begin();
vector<Lorentz5Momentum>::iterator p = theLastMomenta.begin() + 2;
for ( ; out != oldSub->outgoing().end(); ++out, ++p ) {
*p = (**out).momentum();
if ( !hasFractions )
p->boost(toCMS);
}
theLastPartons.first =
oldSub->incoming().first->data().produceParticle(oldSub->incoming().first->momentum());
theLastPartons.second =
oldSub->incoming().second->data().produceParticle(oldSub->incoming().second->momentum());
thePhasespace->setXComb(lastIncomingXComb);
thePhasespace->invertKinematics(theLastMomenta,
!hasFractions ? &theLastRandomNumbers[2] : &theLastRandomNumbers[0]);
theLastBornXComb->clean();
theLastBornXComb->fill(lastIncomingXComb->lastParticles(),theLastPartons,
theLastMomenta,theLastRandomNumbers);
if ( !theLastBornXComb->cuts()->initSubProcess(theLastBornXComb->lastSHat(),
theLastBornXComb->lastY(),
theLastBornXComb->mirror()) )
return false;
theLastBornME->setXComb(theLastBornXComb);
if ( !theLastBornME->generateKinematics(!hasFractions ? &theLastRandomNumbers[2] : &theLastRandomNumbers[0]) )
return false;
CrossSection bornXS = theLastBornME->dSigHatDR();
if ( bornXS == ZERO )
return false;
return true;
}
bool ShowerApproximationGenerator::generate(const vector<double>& r) {
theLastBornXComb->clean();
bool hasFractions =
thePhasespace->haveX1X2() ||
theLastBornXComb->mePartonData().size() == 3;
if ( !hasFractions ) {
double x = generateFraction(theLastPartons.first->dataPtr(),r[0],
lastIncomingXComb->cuts()->x1Min());
Energy Q = lastIncomingXComb->lastParticles().first->momentum().plus();
Energy mass = theLastPartons.first->dataPtr()->mass();
double xi = (sqr(x*Q) - sqr(mass))/(sqr(Q)*x);
Lorentz5Momentum p1(ZERO,ZERO,xi*Q/2.);
p1.setMass(mass); p1.rescaleEnergy();
theLastPartons.first->set5Momentum(p1);
x = generateFraction(theLastPartons.second->dataPtr(),r[1],
lastIncomingXComb->cuts()->x2Min());
Q = lastIncomingXComb->lastParticles().second->momentum().minus();
mass = theLastPartons.second->dataPtr()->mass();
xi = (sqr(x*Q) - sqr(mass))/(sqr(Q)*x);
Lorentz5Momentum p2(ZERO,ZERO,-xi*Q/2.);
p2.setMass(mass); p2.rescaleEnergy();
theLastPartons.second->set5Momentum(p2);
} else {
theLastBornME->setXComb(theLastBornXComb);
theLastBornXComb->lastParticles(lastIncomingXComb->lastParticles());
theLastBornXComb->lastP1P2(make_pair(0.0, 0.0));
theLastBornXComb->lastS(lastIncomingXComb->lastS());
if ( !theLastBornME->generateKinematics(&r[0]) )
return false;
theLastPartons.first->set5Momentum(theLastBornME->lastMEMomenta()[0]);
theLastPartons.second->set5Momentum(theLastBornME->lastMEMomenta()[1]);
}
theLastPresamplingMomenta.resize(theLastMomenta.size());
Boost toCMS =
(theLastPartons.first->momentum() +
theLastPartons.second->momentum()).findBoostToCM();
theLastPresamplingMomenta[0] = theLastPartons.first->momentum();
if ( !hasFractions )
theLastPresamplingMomenta[0].boost(toCMS);
theLastPresamplingMomenta[1] = theLastPartons.second->momentum();
if ( !hasFractions )
theLastPresamplingMomenta[1].boost(toCMS);
if ( hasFractions ) {
for ( size_t k = 2; k < theLastBornME->lastMEMomenta().size(); ++k )
theLastPresamplingMomenta[k] = theLastBornME->lastMEMomenta()[k];
}
theLastBornXComb->fill(lastIncomingXComb->lastParticles(),theLastPartons,
theLastPresamplingMomenta,r);
if ( !theLastBornXComb->cuts()->initSubProcess(theLastBornXComb->lastSHat(),
theLastBornXComb->lastY(),
theLastBornXComb->mirror()) )
return false;
if ( !hasFractions ) {
theLastBornME->setXComb(theLastBornXComb);
if ( !theLastBornME->generateKinematics(&r[2]) )
return false;
}
CrossSection bornXS = theLastBornME->dSigHatDR();
if ( bornXS == ZERO )
return false;
return true;
}
void ShowerApproximationGenerator::restore() {
tSubProPtr oldSub = lastIncomingXComb->subProcess();
theLastPartons.first->set5Momentum(oldSub->incoming().first->momentum());
theLastPartons.second->set5Momentum(oldSub->incoming().second->momentum());
theLastBornXComb->clean();
theLastBornXComb->fill(lastIncomingXComb->lastParticles(),theLastPartons,
theLastMomenta,theLastRandomNumbers);
theLastBornME->setXComb(theLastBornXComb);
theLastBornME->generateKinematics(&theLastRandomNumbers[2]);
theLastBornME->dSigHatDR();
}
void ShowerApproximationGenerator::
handle(EventHandler & eh, const tPVector &,
const Hint &) {
theFactory->setHardTreeEmitter(-1);
theFactory->setHardTreeSubprocess(SubProPtr());
lastIncomingXComb = dynamic_ptr_cast<tStdXCombPtr>(eh.lastXCombPtr());
if ( !lastIncomingXComb )
throw Exception() << "expecting a standard event handler"
<< Exception::abortnow;
if ( lastIncomingXComb->lastProjector() )
lastIncomingXComb = lastIncomingXComb->lastProjector();
const StandardXComb& xc = *lastIncomingXComb;
map<cPDVector,set<Ptr<ShowerApproximationKernel>::ptr> >::const_iterator
kernelit = theKernelMap.find(xc.mePartonData());
if ( kernelit == theKernelMap.end() ) {
list<MatchboxFactory::SplittingChannel> channels =
theFactory->getSplittingChannels(lastIncomingXComb);
set<Ptr<ShowerApproximationKernel>::ptr> newKernels;
for ( list<MatchboxFactory::SplittingChannel>::const_iterator c =
channels.begin(); c != channels.end(); ++c ) {
Ptr<ShowerApproximationKernel>::ptr kernel =
new_ptr(ShowerApproximationKernel());
kernel->setBornXComb(c->bornXComb);
kernel->setRealXComb(c->realXComb);
kernel->setTildeXCombs(c->tildeXCombs);
kernel->setDipole(c->dipole);
kernel->showerApproximation(theShowerApproximation);
kernel->presamplingPoints(thePresamplingPoints);
kernel->maxtry(theMaxTry);
kernel->freezeGrid(theFreezeGrid);
kernel->showerApproximationGenerator(this);
kernel->doCompensate(theDoCompensate);
if ( kernel->dipole()->bornEmitter() > 1 &&
kernel->dipole()->bornSpectator() > 1 ) {
kernel->ptCut(ffPtCut());
} else if ( ( kernel->dipole()->bornEmitter() > 1 &&
kernel->dipole()->bornSpectator() < 2 ) ||
( kernel->dipole()->bornEmitter() < 2 &&
kernel->dipole()->bornSpectator() > 1 ) ) {
kernel->ptCut(fiPtCut());
} else {
assert(kernel->dipole()->bornEmitter() < 2 &&
kernel->dipole()->bornSpectator() < 2);
kernel->ptCut(iiPtCut());
}
newKernels.insert(kernel);
}
theKernelMap[xc.mePartonData()] = newKernels;
kernelit = theKernelMap.find(xc.mePartonData());
}
if ( kernelit->second.empty() )
return;
const set<Ptr<ShowerApproximationKernel>::ptr>& kernels = kernelit->second;
theLastBornME = (**kernels.begin()).dipole()->underlyingBornME();
theLastBornME->phasespace(thePhasespace);
theLastBornXComb = (**kernels.begin()).bornXComb();
if ( !prepare() )
return;
Energy winnerPt = ZERO;
Ptr<ShowerApproximationKernel>::ptr winnerKernel;
for ( set<Ptr<ShowerApproximationKernel>::ptr>::const_iterator k =
kernels.begin(); k != kernels.end(); ++k ) {
if ( (**k).generate() != 0. && (*k)->dipole()->lastPt() > winnerPt){
winnerKernel = *k;
winnerPt = winnerKernel->dipole()->lastPt();
}
}
if ( !winnerKernel || winnerPt == ZERO )
return;
SubProPtr oldSub = lastIncomingXComb->subProcess();
SubProPtr newSub;
try {
newSub = winnerKernel->realXComb()->construct();
} catch(Veto&) {
return;
}
if ( !theShowerApproximation->needsTruncatedShower() ){
tParticleSet firstS = oldSub->incoming().first->siblings();
assert(firstS.empty() || firstS.size() == 1);
if ( !firstS.empty() ) {
eh.currentStep()->removeParticle(*firstS.begin());
}
tParticleSet secondS = oldSub->incoming().second->siblings();
assert(secondS.empty() || secondS.size() == 1);
if ( !secondS.empty() ) {
eh.currentStep()->removeParticle(*secondS.begin());
}
// prevent the colliding particles from disappearing
// in the initial state and appearing
// in the final state when we've cut off all their
// (physical) children; only applies to the case
// where we have a parton extractor not build from
// noPDF, so check wether the incoming particle
// doesnt equal the incoming parton -- this needs fixing in ThePEG
PPtr dummy = new_ptr(Particle(getParticleData(ParticleID::gamma)));
bool usedDummy = false;
if ( eh.currentStep()->incoming().first != oldSub->incoming().first ) {
eh.currentStep()->addDecayProduct(eh.currentStep()->incoming().first,dummy);
usedDummy = true;
}
if ( eh.currentStep()->incoming().second != oldSub->incoming().second ) {
eh.currentStep()->addDecayProduct(eh.currentStep()->incoming().second,dummy);
usedDummy = true;
}
eh.currentStep()->removeSubProcess(oldSub);
eh.currentStep()->addSubProcess(newSub);
// get rid of the dummy
if ( usedDummy ) {
eh.currentStep()->removeParticle(dummy);
}
eh.select(winnerKernel->realXComb());
winnerKernel->realXComb()->recreatePartonBinInstances(winnerKernel->realXComb()->lastScale());
winnerKernel->realXComb()->refillPartonBinInstances(&(xc.lastRandomNumbers()[0]));
winnerKernel->realXComb()->pExtractor()->constructRemnants(winnerKernel->realXComb()->partonBinInstances(),
newSub, eh.currentStep());
}
else{
theFactory->setHardTreeSubprocess(newSub);
theFactory->setHardTreeEmitter(winnerKernel->dipole()->bornEmitter());
}
}
IBPtr ShowerApproximationGenerator::clone() const {
return new_ptr(*this);
}
IBPtr ShowerApproximationGenerator::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 ShowerApproximationGenerator::persistentOutput(PersistentOStream & os) const {
os << theShowerApproximation << thePhasespace << theFactory
<< theKernelMap << thePresamplingPoints << theMaxTry << theFreezeGrid
<< lastIncomingXComb << theLastBornME << ounit(theLastMomenta,GeV)
<< ounit(theLastPresamplingMomenta,GeV) << theLastRandomNumbers
<< theLastBornXComb << theLastPartons << theDoCompensate;
}
void ShowerApproximationGenerator::persistentInput(PersistentIStream & is, int) {
is >> theShowerApproximation >> thePhasespace >> theFactory
>> theKernelMap >> thePresamplingPoints >> theMaxTry >> theFreezeGrid
>> lastIncomingXComb >> theLastBornME >> iunit(theLastMomenta,GeV)
>> iunit(theLastPresamplingMomenta,GeV) >> theLastRandomNumbers
>> theLastBornXComb >> theLastPartons >> theDoCompensate;
}
// *** 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<ShowerApproximationGenerator,StepHandler>
describeHerwigShowerApproximationGenerator("Herwig::ShowerApproximationGenerator", "Herwig.so");
void ShowerApproximationGenerator::Init() {
static ClassDocumentation<ShowerApproximationGenerator> documentation
("ShowerApproximationGenerator generates emissions according to a "
"shower approximation entering a NLO matching.");
static Reference<ShowerApproximationGenerator,ShowerApproximation> interfaceShowerApproximation
("ShowerApproximation",
"Set the shower approximation to sample.",
&ShowerApproximationGenerator::theShowerApproximation, false, false, true, false, false);
static Reference<ShowerApproximationGenerator,MatchboxPhasespace> interfacePhasespace
("Phasespace",
"The phase space generator to use.",
&ShowerApproximationGenerator::thePhasespace, false, false, true, false, false);
static Reference<ShowerApproximationGenerator,MatchboxFactory> interfaceFactory
("Factory",
"The factory object to use.",
&ShowerApproximationGenerator::theFactory, false, false, true, false, false);
static Parameter<ShowerApproximationGenerator,unsigned long> interfacePresamplingPoints
("PresamplingPoints",
"Set the number of presampling points.",
&ShowerApproximationGenerator::thePresamplingPoints, 2000, 1, 0,
false, false, Interface::lowerlim);
static Parameter<ShowerApproximationGenerator,unsigned long> interfaceMaxTry
("MaxTry",
"Set the number of maximum attempts.",
&ShowerApproximationGenerator::theMaxTry, 100000, 1, 0,
false, false, Interface::lowerlim);
static Parameter<ShowerApproximationGenerator,unsigned long> interfaceFreezeGrid
("FreezeGrid",
"",
&ShowerApproximationGenerator::theFreezeGrid, 500000, 1, 0,
false, false, Interface::lowerlim);
static Switch<ShowerApproximationGenerator,bool> interfaceDoCompensate
("DoCompensate",
"",
&ShowerApproximationGenerator::theDoCompensate, false, false, false);
static SwitchOption interfaceDoCompensateYes
(interfaceDoCompensate,
"Yes",
"",
true);
static SwitchOption interfaceDoCompensateNo
(interfaceDoCompensate,
"No",
"",
false);
}
diff --git a/MatrixElement/Matchbox/Phasespace/FlatInvertiblePhasespace.h b/MatrixElement/Matchbox/Phasespace/FlatInvertiblePhasespace.h
--- a/MatrixElement/Matchbox/Phasespace/FlatInvertiblePhasespace.h
+++ b/MatrixElement/Matchbox/Phasespace/FlatInvertiblePhasespace.h
@@ -1,194 +1,194 @@
// -*- C++ -*-
//
// FlatInvertiblePhasespace.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_FlatInvertiblePhasespace_H
#define Herwig_FlatInvertiblePhasespace_H
//
// This is the declaration of the FlatInvertiblePhasespace class.
//
#include "Herwig++/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief FlatInvertiblePhasespace implements flat, invertible phase space generation.
*
*/
class FlatInvertiblePhasespace: public MatchboxPhasespace {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
FlatInvertiblePhasespace();
/**
* The destructor.
*/
virtual ~FlatInvertiblePhasespace();
//@}
public:
/**
* Generate a phase space point and return its weight.
*/
virtual double generateTwoToNKinematics(const double*,
vector<Lorentz5Momentum>& momenta);
/**
* Return the number of random numbers required to produce a given
* multiplicity final state.
*/
- virtual int nDim(int nFinal) const {
+ virtual int nDimPhasespace(int nFinal) const {
if ( nFinal == 1 )
return 1;
return 3*nFinal - 4;
}
public:
/**
* Return true, if this phase space generator is invertible
*/
virtual bool isInvertible() const { return true; }
/**
* Invert the given phase space point to the random numbers which
* would have generated it.
*/
virtual double invertTwoToNKinematics(const vector<Lorentz5Momentum>& momenta,
double* r) const {
return invertKinematics(momenta,(momenta[0]+momenta[1]).m(),r);
}
private:
/**
* Solve v = (n+2) * u^(n+1) - (n+1) * u^(n+2) for u
*/
double bisect(double v, double n,
double target = -16., double maxLevel = 80.) const;
/**
* Return rho
*/
double rho(Energy M, Energy N, Energy m) const {
return sqrt((sqr(M)-sqr(N+m))*(sqr(M)-sqr(N-m)))/(8.*sqr(M));
}
/**
* Generate intermediate masses for a massless final state
*/
double generateIntermediates(vector<Energy>& K,
const double* r) const;
/**
* Invert intermediate masses for a massless final state
*/
double invertIntermediates(const vector<Energy>& K,
double* r) const;
/**
* Generate intermediate masses for a massive final state
*/
double generateIntermediates(vector<Energy>& M,
const vector<Energy>& m,
const double* r) const;
/**
* Invert intermediate masses for a massive final state
*/
double invertIntermediates(const vector<Energy>& M,
const vector<Energy>& m,
double* r) const;
/**
* Generate momenta in the CMS
*/
double generateKinematics(vector<Lorentz5Momentum>& P,
Energy Ecm,
const double* r) const;
/**
* Invert momenta in the CMS
*/
double invertKinematics(const vector<Lorentz5Momentum>& P,
Energy Ecm,
double* r) 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 assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
FlatInvertiblePhasespace & operator=(const FlatInvertiblePhasespace &);
};
}
#endif /* Herwig_FlatInvertiblePhasespace_H */
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,541 +1,559 @@
// -*- 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/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 =
- processData()->massGenerator(*pd);
+ 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).width() != 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).mass()))/((**pd).mass() * (**pd).width()));
double bwIUp =
atan((sqr(massMax)-sqr((**pd).mass()))/((**pd).mass() * (**pd).width()));
gmass = sqrt(sqr((**pd).mass()) +
(**pd).mass()*(**pd).width()*tan(bwILow+r[0]*(bwIUp-bwILow)));
++r;
} else {
gmass = (**pd).mass();
}
maxMass -= gmass;
p->setMass(gmass);
summ += gmass;
}
} else {
for ( ; pd != mePartonData().end(); ++pd, ++p ) {
summ += (**pd).mass();
p->setMass((**pd).mass());
}
}
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).width() != ZERO ) {
Energy massMax = min((**pd).massMax(),maxMass);
Energy massMin = (**pd).massMin();
if ( massMin > massMax )
return 0.0;
double bwILow =
atan((sqr(massMin)-sqr((**pd).mass()))/((**pd).mass() * (**pd).width()));
double bwIUp =
atan((sqr(massMax)-sqr((**pd).mass()))/((**pd).mass() * (**pd).width()));
gmass = p->mass();
double bw =
atan((sqr(gmass)-sqr((**pd).mass()))/((**pd).mass() * (**pd).width()));
r[0] = (bw-bwILow)/(bwIUp-bwILow);
++r;
} else {
gmass = (**pd).mass();
}
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 ) {
couplings[LTriple(a,b,c)] = coupling;
return;
}
if ( A->CC() ) {
couplings[LTriple(-a,b,c)] = coupling;
couplings[LTriple(-a,c,b)] = coupling;
} else {
couplings[LTriple(a,b,c)] = coupling;
couplings[LTriple(a,c,b)] = coupling;
}
if ( B->CC() ) {
couplings[LTriple(-b,a,c)] = coupling;
couplings[LTriple(-b,c,a)] = coupling;
} else {
couplings[LTriple(b,a,c)] = coupling;
couplings[LTriple(b,c,a)] = coupling;
}
if ( C->CC() ) {
couplings[LTriple(-c,a,b)] = coupling;
couplings[LTriple(-c,b,a)] = coupling;
} else {
couplings[LTriple(c,a,b)] = coupling;
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 = couplings.find(vertexKey);
if ( cit != 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>();
}
Energy2 mass2 = sqr(diag.allPartons()[branch]->mass());
Energy2 width2 = sqr(diag.allPartons()[branch]->width());
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 = couplings.find(vertexKey);
if ( cit != 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>();
}
if ( children.first == diag.nSpace() - 1 ) {
return res.first;
}
res.second = incoming - res.second;
Energy2 mass2 = sqr(diag.allPartons()[children.first]->mass());
Energy2 width2 = sqr(diag.allPartons()[children.first]->width());
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).width() != 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;
//<< couplings; // no idea why this isn't working
os << couplings.size();
for ( map<LTriple,double>::const_iterator cit =
couplings.begin(); cit != couplings.end(); ++cit )
os << cit->first << cit->second;
}
void MatchboxPhasespace::persistentInput(PersistentIStream & is, int) {
is >> theLastXComb
>> iunit(singularCutoff,GeV) >> theUseMassGenerators >> theLoopParticleIdMin >> theLoopParticleIdMax;
//>> couplings; // no idea why this isn't working
couplings.clear();
size_t size;
LTriple k;
is >> size;
while ( size-- && is ) {
is >> k;
is >> couplings[k];
}
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);
}
diff --git a/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h b/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h
--- a/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h
+++ b/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h
@@ -1,368 +1,374 @@
// -*- C++ -*-
//
// MatchboxPhasespace.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_MatchboxPhasespace_H
#define HERWIG_MatchboxPhasespace_H
//
// This is the declaration of the MatchboxPhasespace class.
//
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/Handlers/HandlerBase.h"
#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/LastMatchboxXCombInfo.h"
#include "Herwig++/MatrixElement/Matchbox/Utility/ProcessData.fh"
#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.fh"
#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;
inline PersistentOStream& operator<<(PersistentOStream& os, const LTriple& t) {
os << t.get<0>() << t.get<1>() << t.get<2>();
return os;
}
inline PersistentIStream& operator>>(PersistentIStream& is, LTriple& t) {
is >> t.get<0>() >> t.get<1>() >> t.get<2>();
return is;
}
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief Wrap around a vector of random numbers to behave as a stream
* of those.
*/
struct StreamingRnd {
/**
* The random numbers
*/
const double* numbers;
/**
* The number of random numbers available.
*/
size_t nRnd;
/**
* Default constructor.
*/
StreamingRnd()
: numbers(0), nRnd(0) {}
/**
* Construct from random numbers.
*/
explicit StreamingRnd(const double* newNumbers,
size_t n)
: numbers(newNumbers), nRnd(n) {}
/**
* Return next random number
*/
inline double operator()() {
assert(numbers && nRnd > 0);
const double ret = numbers[0];
++numbers; --nRnd;
return ret;
}
};
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief MatchboxPhasespace defines an abstract interface to a phase
* space generator.
*
*/
class MatchboxPhasespace:
public HandlerBase,
public LastXCombInfo<StandardXComb>,
public LastMatchboxXCombInfo {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
MatchboxPhasespace();
/**
* The destructor.
*/
virtual ~MatchboxPhasespace();
//@}
public:
/**
* Set the XComb object steering the Born matrix
* element this class represents virtual corrections to.
*/
virtual void setXComb(tStdXCombPtr xc) {
theLastXComb = xc;
lastMatchboxXComb(xc);
}
/**
* Return the factory object
*/
Ptr<MatchboxFactory>::tcptr factory() const;
/**
* Return the process data object
*/
Ptr<ProcessData>::tptr processData() const;
/**
* Generate a phase space point and return its weight.
*/
virtual double generateKinematics(const double* r,
vector<Lorentz5Momentum>& momenta);
/**
* Generate a phase space point and return its weight.
*/
virtual double generateTwoToNKinematics(const double*,
vector<Lorentz5Momentum>& momenta) = 0;
/**
* Generate a 2 -> 1 phase space point and return its weight.
*/
virtual double generateTwoToOneKinematics(const double*,
vector<Lorentz5Momentum>& momenta);
/**
* Return the number of random numbers required to produce a given
* multiplicity final state.
*/
- virtual int nDim(int nFinal) const = 0;
+ virtual int nDim(const cPDVector&) const;
+
+ /**
+ * Return the number of random numbers required to produce a given
+ * multiplicity final state.
+ */
+ virtual int nDimPhasespace(int nFinal) const = 0;
/**
* Return true, if this phasespace generator will generate incoming
* partons itself.
*/
virtual bool haveX1X2() const { return false; }
/**
* Return true, if this phase space generator expects
* the incoming partons in their center-of-mass system
*/
virtual bool wantCMS() const { return true; }
/**
* True, if mass generators should be used instead of fixed masses
*/
bool useMassGenerators() const { return theUseMassGenerators; }
/**
* Fill a diagram selector for the last phase space point.
*/
virtual Selector<MEBase::DiagramIndex> selectDiagrams(const MEBase::DiagramVector&) const;
/**
* Return the momentum and weight appropriate to the given timelike
* branch of the diagram.
*/
pair<double,Lorentz5Momentum> timeLikeWeight(const Tree2toNDiagram& diag,
int branch, double flatCut) const;
/**
* Return the weight appropriate to the given spacelike branch of
* the diagram.
*/
double spaceLikeWeight(const Tree2toNDiagram& diag,
const Lorentz5Momentum& incoming,
int branch, double flatCut) const;
/**
* Return the weight appropriate to the given diagram.
*/
double diagramWeight(const Tree2toNDiagram& diag) const {
assert( !diagramWeights().empty() );
return diagramWeights().find(diag.id())->second;
}
/**
* Fill the diagram weights.
*/
void fillDiagramWeights(double flatCut = 0.0);
/**
* Clone this phase space generator.
*/
Ptr<MatchboxPhasespace>::ptr cloneMe() const {
return dynamic_ptr_cast<Ptr<MatchboxPhasespace>::ptr>(clone());
}
/**
* Clone the dependencies, using a given prefix.
*/
virtual void cloneDependencies(const std::string& prefix = "");
public:
/**
* Return true, if this phase space generator is invertible
*/
virtual bool isInvertible() const { return false; }
/**
* Invert the given phase space point to the random numbers which
* would have generated it.
*/
virtual double invertKinematics(const vector<Lorentz5Momentum>& momenta,
double* r) const;
/**
* Invert the given phase space point to the random numbers which
* would have generated it.
*/
virtual double invertTwoToNKinematics(const vector<Lorentz5Momentum>&,
double*) const {
return 0.;
}
/**
* Invert the given 2 -> 1 phase space point to the random numbers which
* would have generated it.
*/
virtual double invertTwoToOneKinematics(const vector<Lorentz5Momentum>&, double*) const;
public:
/**
* Limit phasespace generation to a given collinear or soft limit.
*/
void singularLimit(size_t i, size_t j) {
if ( i > j )
swap(i,j);
singularLimits().insert(make_pair(i,j));
}
/**
* Return the last matched singular limit.
*/
const pair<size_t,size_t>& lastSingularIndices() const {
assert(lastSingularLimit() != singularLimits().end());
return *lastSingularLimit();
}
/**
* Return true, if constraints on phasespace generation have been met.
*/
bool matchConstraints(const vector<Lorentz5Momentum>& momenta);
protected:
/**
* Set a coupling for the given vertex; the convention is that all
* legs are outgoing, and all possible crossings will be taken care
* of. If not set, coupling weights default to one.
*/
void setCoupling(long a, long b, long c,
double coupling, bool includeCrossings = 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);
//@}
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();
// If needed, insert declarations of virtual function defined in the
// InterfacedBase class here (using ThePEG-interfaced-decl in Emacs).
private:
/**
* A cutoff below which a region is considered singular.
*/
Energy singularCutoff;
/**
* True, if mass generators should be used instead of fixed masses
*/
bool theUseMassGenerators;
/**
* Couplings to be used in diagram weighting
*/
map<LTriple,double> couplings;
/**
* Interface function to setcoupling
*/
string doSetCoupling(string);
/**
* Interface function to setcoupling
*/
string doSetPhysicalCoupling(string);
/**
* The 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.
*/
int theLoopParticleIdMin;
/**
* The 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.
*/
int theLoopParticleIdMax;
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
MatchboxPhasespace & operator=(const MatchboxPhasespace &);
};
}
#endif /* HERWIG_MatchboxPhasespace_H */
diff --git a/MatrixElement/Matchbox/Phasespace/MatchboxRambo.h b/MatrixElement/Matchbox/Phasespace/MatchboxRambo.h
--- a/MatrixElement/Matchbox/Phasespace/MatchboxRambo.h
+++ b/MatrixElement/Matchbox/Phasespace/MatchboxRambo.h
@@ -1,186 +1,188 @@
// -*- C++ -*-
//
// MatchboxRambo.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_MatchboxRambo_H
#define Herwig_MatchboxRambo_H
//
// This is the declaration of the MatchboxRambo class.
//
#include "Herwig++/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief MatchboxRambo implements RAMBO phase space generation.
*
*/
class MatchboxRambo: public MatchboxPhasespace {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
MatchboxRambo();
/**
* The destructor.
*/
virtual ~MatchboxRambo();
//@}
public:
/**
* Prepare a phase space generator for the given xcomb object.
*/
virtual void setXComb(tStdXCombPtr);
/**
* Generate a phase space point and return its weight.
*/
virtual double generateTwoToNKinematics(const double*,
vector<Lorentz5Momentum>& momenta);
/**
* Return the number of random numbers required to produce a given
* multiplicity final state.
*/
- virtual int nDim(int nFinal) const {
+ virtual int nDimPhasespace(int nFinal) const {
+ if ( nFinal == 1 )
+ return 1;
return 4*nFinal;
}
protected:
/**
* The function object defining the equation
* to be solved.
*/
struct ReshuffleEquation {
typedef double ArgType;
typedef Energy ValType;
static double aUnit() { return 1.; }
static Energy vUnit() { return 1.*GeV; }
Energy operator() (double xi) const;
Energy w;
cPDVector::const_iterator dataBegin;
cPDVector::const_iterator dataEnd;
vector<Lorentz5Momentum>::const_iterator momentaBegin;
vector<Lorentz5Momentum>::const_iterator momentaEnd;
ReshuffleEquation(Energy q,
cPDVector::const_iterator dBegin,
cPDVector::const_iterator dEnd,
vector<Lorentz5Momentum>::const_iterator mBegin,
vector<Lorentz5Momentum>::const_iterator mEnd)
: w(q),
dataBegin(dBegin), dataEnd(dEnd),
momentaBegin(mBegin),
momentaEnd(mEnd) {}
};
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.
*/
MatchboxRambo & operator=(const MatchboxRambo &);
/**
* Whether or not we need to reshuffle.
*/
bool needToReshuffle;
/**
* True, if a reference sample of phasespace points should be
* generated.
*/
bool theMakeReferenceSample;
/**
* Map processes to streams for reference samples
*/
map<cPDVector,ofstream*> referenceSamples;
/**
* The stream to fill for the reference sample
*/
ofstream* referenceSample;
/**
* Write the generated point to the reference sample
*/
void dumpReference(const vector<Lorentz5Momentum>&, double) const;
};
}
#endif /* Herwig_MatchboxRambo_H */
diff --git a/MatrixElement/Matchbox/Phasespace/MatchboxReference.h b/MatrixElement/Matchbox/Phasespace/MatchboxReference.h
--- a/MatrixElement/Matchbox/Phasespace/MatchboxReference.h
+++ b/MatrixElement/Matchbox/Phasespace/MatchboxReference.h
@@ -1,138 +1,140 @@
// -*- C++ -*-
//
// MatchboxReference.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_MatchboxReference_H
#define Herwig_MatchboxReference_H
//
// This is the declaration of the MatchboxReference class.
//
#include "Herwig++/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief MatchboxReference implements reference sample phase space generation.
*
*/
class MatchboxReference: public MatchboxPhasespace {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
MatchboxReference();
/**
* The destructor.
*/
virtual ~MatchboxReference();
//@}
public:
/**
* Generate a phase space point and return its weight.
*/
virtual double generateTwoToNKinematics(const double*,
vector<Lorentz5Momentum>& momenta);
/**
* Return the number of random numbers required to produce a given
* multiplicity final state.
*/
- virtual int nDim(int nFinal) const {
+ virtual int nDimPhasespace(int nFinal) const {
+ if ( nFinal == 1 )
+ return 1;
return 4*nFinal + 2;
}
/**
* Return true, if this phasespace generator will generate incoming
* partons itself.
*/
virtual bool haveX1X2() const { return true; }
/**
* Return true, if this phase space generator expects
* the incoming partons in their center-of-mass system
*/
virtual bool wantCMS() const { return false; }
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.
*/
MatchboxReference & operator=(const MatchboxReference &);
/**
* Stream to read the reference samples.
*/
map<cPDVector,ifstream*> referenceSamples;
};
}
#endif /* Herwig_MatchboxReference_H */
diff --git a/MatrixElement/Matchbox/Phasespace/TreePhasespace.h b/MatrixElement/Matchbox/Phasespace/TreePhasespace.h
--- a/MatrixElement/Matchbox/Phasespace/TreePhasespace.h
+++ b/MatrixElement/Matchbox/Phasespace/TreePhasespace.h
@@ -1,217 +1,217 @@
// -*- C++ -*-
//
// TreePhasespace.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_TreePhasespace_H
#define Herwig_TreePhasespace_H
//
// This is the declaration of the TreePhasespace class.
//
#include "Herwig++/MatrixElement/Matchbox/Phasespace/MatchboxPhasespace.h"
#include "Herwig++/MatrixElement/Matchbox/Phasespace/TreePhasespaceChannels.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Simon Platzer, Ken Arnold
*
* \brief TreePhasespace is a multichannel phasespace generator
* adapting to singularity structures as determined from the matrix
* elements diagrams.
*
* @see \ref TreePhasespaceInterfaces "The interfaces"
* defined for TreePhasespace.
*/
class TreePhasespace: public MatchboxPhasespace {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* The default constructor.
*/
TreePhasespace();
/**
* The destructor.
*/
virtual ~TreePhasespace();
//@}
public:
/**
* Prepare a phase space generator for the given xcomb object.
*/
virtual void setXComb(tStdXCombPtr);
/**
* Generate a phase space point and return its weight.
*/
virtual double generateTwoToNKinematics(const double*,
vector<Lorentz5Momentum>& momenta);
/**
* Return the number of random numbers required to produce a given
* multiplicity final state.
*/
- virtual int nDim(int nFinal) const {
+ virtual int nDimPhasespace(int nFinal) const {
if ( nFinal == 1 )
return 1;
return 3*(nFinal - 1); // one additional number needed for channel selection
}
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:
/** @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 object storing channel maps
*/
Ptr<TreePhasespaceChannels>::ptr theChannelMap;
/**
* Map xcomb's to channel vectors indexed by diagram id.
*/
map<tStdXCombPtr,
map<Ptr<Tree2toNDiagram>::ptr,
pair <PhasespaceHelpers::PhasespaceTree, PhasespaceHelpers::PhasespaceTree> > >&
channelMap() { return theChannelMap->channelMap(); }
/**
* The currently active channels.
*/
map<tStdXCombPtr,
map<Ptr<Tree2toNDiagram>::ptr,
pair <PhasespaceHelpers::PhasespaceTree, PhasespaceHelpers::PhasespaceTree> > >::iterator
lastChannelsIterator;
/**
* The phasespace info object to be used.
*/
PhasespaceHelpers::PhasespaceInfo lastPhasespaceInfo;
/**
* Parameter steering from which on propagator virtualities are
* sampled flat.
*/
double x0;
/**
* Parameter steering at which virtuality singularities of
* propagators are actually cut off.
*/
double xc;
/**
* Parameter steering from which on propagator virtualities are
* sampled flat.
*/
Energy M0;
/**
* Parameter steering at which virtuality singularities of
* propagators are actually cut off.
*/
Energy Mc;
/**
* Choose whether to also use mirrored phasespace generation
*/
bool theIncludeMirrored;
/**
* Return the currently active channels.
*/
map<Ptr<Tree2toNDiagram>::ptr,
pair <PhasespaceHelpers::PhasespaceTree, PhasespaceHelpers::PhasespaceTree> >& lastChannels() {
return lastChannelsIterator->second;
}
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
TreePhasespace & operator=(const TreePhasespace &);
};
}
#endif /* Herwig_TreePhasespace_H */
diff --git a/MatrixElement/Matchbox/Utility/LastMatchboxXCombInfo.h b/MatrixElement/Matchbox/Utility/LastMatchboxXCombInfo.h
--- a/MatrixElement/Matchbox/Utility/LastMatchboxXCombInfo.h
+++ b/MatrixElement/Matchbox/Utility/LastMatchboxXCombInfo.h
@@ -1,518 +1,528 @@
// -*- C++ -*-
//
// MatchboxXComb.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_LastMatchboxXCombInfo_H
#define Herwig_LastMatchboxXCombInfo_H
//
// This is the declaration of the MatchboxXComb class.
//
#include "Herwig++/MatrixElement/Matchbox/Utility/MatchboxXCombData.h"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief Provide easy access to MatchboxXComb XComb extensions
*/
class LastMatchboxXCombInfo {
public:
/**
* Default constructor
*/
LastMatchboxXCombInfo()
: theLastMatchboxXComb(0), theLastHeadMatchboxXComb(0) {}
/**
* Return a pointer to the last selected XComb.
*/
MatchboxXCombData* lastMatchboxXComb() const { return theLastMatchboxXComb; }
/**
* If the last selected XComb object belongs to a
* group of XComb's return a pointer to the head
* XComb object for this group.
*/
MatchboxXCombData* lastHeadMatchboxXComb() const { return theLastHeadMatchboxXComb; }
public:
/**
* The crossing information as filled by the last call to
* fillCrossingMap()
*/
const vector<int>& crossingMap() const { return lastMatchboxXComb()->crossingMap(); }
/**
* The colour crossing information as filled by the last call to
* fillCrossingMap()
*/
const map<size_t,size_t>& amplitudeToColourMap() const { return lastMatchboxXComb()->amplitudeToColourMap(); }
/**
* The colour crossing information as filled by the last call to
* fillCrossingMap()
*/
const map<size_t,size_t>& colourToAmplitudeMap() const { return lastMatchboxXComb()->colourToAmplitudeMap(); }
/**
* The crossing sign as filled by the last call to
* fillCrossingMap()
*/
double crossingSign() const { return lastMatchboxXComb()->crossingSign(); }
/**
+ * The last renormalization scale
+ */
+ Energy2 lastRenormalizationScale() const { return lastMatchboxXComb()->lastRenormalizationScale(); }
+
+ /**
* The amplitude parton data.
*/
const cPDVector& amplitudePartonData() const { return lastMatchboxXComb()->amplitudePartonData(); }
/**
* The crossed momenta
*/
const vector<Lorentz5Momentum>& amplitudeMomenta() const { return lastMatchboxXComb()->amplitudeMomenta(); }
/**
* True, if the the tree level amplitudes need to be calculated
*/
bool calculateTreeAmplitudes() const { return lastMatchboxXComb()->calculateTreeAmplitudes(); }
/**
* The amplitude values which have been contributing
* to the last call of prepareAmplitudes.
*/
const map<vector<int>,CVector>& lastAmplitudes() const { return lastMatchboxXComb()->lastAmplitudes(); }
/**
* The leading N amplitude values which have been
* contributing to the last call of prepareAmplitudes.
*/
const map<vector<int>,CVector>& lastLargeNAmplitudes() const { return lastMatchboxXComb()->lastLargeNAmplitudes(); }
/**
* True, if the the one-loop amplitudes need to be calculated
*/
bool calculateOneLoopAmplitudes() const { return lastMatchboxXComb()->calculateOneLoopAmplitudes(); }
/**
* The one-loop amplitude values which have been contributing
* to the last call of prepareAmplitudes.
*/
const map<vector<int>,CVector>& lastOneLoopAmplitudes() const { return lastMatchboxXComb()->lastOneLoopAmplitudes(); }
/**
* True, if the tree-level matrix element squared needs to be
* calculated.
*/
bool calculateTreeME2() const { return lastMatchboxXComb()->calculateTreeME2(); }
/**
* The last tree-level matrix element squared
*/
double lastTreeME2() const { return lastMatchboxXComb()->lastTreeME2(); }
/**
* True, if the tree-level matrix element squared needs to be
* calculated.
*/
bool calculateLargeNME2() const { return lastMatchboxXComb()->calculateLargeNME2(); }
/**
* The last tree-level matrix element squared
*/
double lastLargeNME2() const { return lastMatchboxXComb()->lastLargeNME2(); }
/**
* True, if the one-loop/tree-level interference.
* be calculated.
*/
bool calculateOneLoopInterference() const { return lastMatchboxXComb()->calculateOneLoopInterference(); }
/**
* The last one-loop/tree-level interference.
*/
double lastOneLoopInterference() const { return lastMatchboxXComb()->lastOneLoopInterference(); }
/**
* True, if the one-loop/tree-level interference.
* be calculated.
*/
bool calculateOneLoopPoles() const { return lastMatchboxXComb()->calculateOneLoopPoles(); }
/**
* The last one-loop/tree-level interference.
*/
pair<double,double> lastOneLoopPoles() const { return lastMatchboxXComb()->lastOneLoopPoles(); }
/**
* True, if the indexed colour correlated matrix element needs to be
* calculated.
*/
bool calculateColourCorrelator(const pair<int,int>& ij) const { return lastMatchboxXComb()->calculateColourCorrelator(ij); }
/**
* The colour correlated matrix element.
*/
double lastColourCorrelator(const pair<int,int>& ij) const { return lastMatchboxXComb()->lastColourCorrelator(ij); }
/**
* True, if the indexed large-N colour correlated matrix element needs to be
* calculated.
*/
bool calculateLargeNColourCorrelator(const pair<int,int>& ij) const { return lastMatchboxXComb()->calculateLargeNColourCorrelator(ij); }
/**
* The large-N colour correlated matrix element.
*/
double lastLargeNColourCorrelator(const pair<int,int>& ij) const { return lastMatchboxXComb()->lastLargeNColourCorrelator(ij); }
/**
* True, if the indexed colour/spin correlated matrix element needs to be
* calculated.
*/
bool calculateColourSpinCorrelator(const pair<int,int>& ij) const { return lastMatchboxXComb()->calculateColourSpinCorrelator(ij); }
/**
* The colour/spin correlated matrix element.
*/
Complex lastColourSpinCorrelator(const pair<int,int>& ij) const { return lastMatchboxXComb()->lastColourSpinCorrelator(ij); }
/**
* True, if the indexed spin correlated matrix element needs to be
* calculated.
*/
bool calculateSpinCorrelator(const pair<int,int>& ij) const { return lastMatchboxXComb()->calculateSpinCorrelator(ij); }
/**
* The spin correlated matrix element.
*/
Complex lastSpinCorrelator(const pair<int,int>& ij) const { return lastMatchboxXComb()->lastSpinCorrelator(ij); }
/**
* Return the number of light flavours to be considered for this process.
*/
unsigned int nLight() const { return lastMatchboxXComb()->nLight(); }
/**
* Return the vector that contains the PDG ids of
* the light flavours, which are contained in the
* jet particle group.
*/
vector<int> nLightJetVec() const { return lastMatchboxXComb()->nLightJetVec(); }
/**
* Return the vector that contains the PDG ids of
* the heavy flavours, which are contained in the
* jet particle group.
*/
vector<int> nHeavyJetVec() const { return lastMatchboxXComb()->nHeavyJetVec(); }
/**
* Return the vector that contains the PDG ids of
* the light flavours, which are contained in the
* proton particle group.
*/
vector<int> nLightProtonVec() const { return lastMatchboxXComb()->nLightProtonVec(); }
/**
* Get the dimensionality of the colour basis for this process.
*/
size_t colourBasisDim() const { return lastMatchboxXComb()->colourBasisDim(); }
/**
* Return the number of degrees of freedom required by the phase space generator
*/
int nDimPhasespace() const { return lastMatchboxXComb()->nDimPhasespace(); }
/**
* Return the number of degrees of freedom required by the amplitude
*/
int nDimAmplitude() const { return lastMatchboxXComb()->nDimAmplitude(); }
/**
* Return the number of degrees of freedom required by the insertion operators
*/
int nDimInsertions() const { return lastMatchboxXComb()->nDimInsertions(); }
/**
* Get the additional random numbers required by the amplitude
*/
const vector<double>& amplitudeRandomNumbers() const { return lastMatchboxXComb()->amplitudeRandomNumbers(); }
/**
* Get the additional random numbers required by the insertion operator
*/
const vector<double>& insertionRandomNumbers() const { return lastMatchboxXComb()->insertionRandomNumbers(); }
/**
* Return the diagram weights indexed by diagram id.
*/
const map<int,double>& diagramWeights() const { return lastMatchboxXComb()->diagramWeights(); }
/**
* Return the singular limits
*/
const set<pair<size_t,size_t> >& singularLimits() const { return lastMatchboxXComb()->singularLimits(); }
/**
* Return the last matched singular limit.
*/
const set<pair<size_t,size_t> >::const_iterator& lastSingularLimit() const { return lastMatchboxXComb()->lastSingularLimit(); }
/**
* Get the Herwig++ StandardModel object
*/
Ptr<StandardModel>::tcptr hwStandardModel() const { return lastMatchboxXComb()->hwStandardModel(); }
/**
* Return the symmetry factor
*/
double symmetryFactor() const { return lastMatchboxXComb()->symmetryFactor(); }
/**
* Return the OLP process id
*/
const vector<int>& olpId() const { return lastMatchboxXComb()->olpId(); }
/**
* Return the olp momentum vector
*/
double* olpMomenta() const { return lastMatchboxXComb()->olpMomenta(); }
/**
* Fill the olp momentum vector
*/
void fillOLPMomenta(const vector<Lorentz5Momentum>& mm,
const cPDVector& mePartonData,
const map<long,Energy>& reshuffleMap) const {
lastMatchboxXComb()->fillOLPMomenta(mm,mePartonData,reshuffleMap);
}
protected:
/**
* The crossing information as filled by the last call to
* fillCrossingMap()
*/
vector<int>& crossingMap() { return lastMatchboxXComb()->crossingMap(); }
/**
* The colour crossing information as filled by the last call to
* fillCrossingMap()
*/
map<size_t,size_t>& amplitudeToColourMap() { return lastMatchboxXComb()->amplitudeToColourMap(); }
/**
* The colour crossing information as filled by the last call to
* fillCrossingMap()
*/
map<size_t,size_t>& colourToAmplitudeMap() { return lastMatchboxXComb()->colourToAmplitudeMap(); }
/**
* The crossing sign as filled by the last call to
* fillCrossingMap()
*/
void crossingSign(double c) { lastMatchboxXComb()->crossingSign(c); }
/**
+ * The last renormalization scale
+ */
+ void lastRenormalizationScale(Energy2 lrs) { lastMatchboxXComb()->lastRenormalizationScale(lrs); }
+
+ /**
* The amplitude parton data.
*/
cPDVector& amplitudePartonData() { return lastMatchboxXComb()->amplitudePartonData(); }
/**
* The crossed momenta
*/
vector<Lorentz5Momentum>& amplitudeMomenta() { return lastMatchboxXComb()->amplitudeMomenta(); }
/**
* True, if the the tree level amplitudes need to be calculated
*/
void haveTreeAmplitudes(bool f = true) { lastMatchboxXComb()->haveTreeAmplitudes(f); }
/**
* The amplitude values which have been contributing
* to the last call of prepareAmplitudes.
*/
map<vector<int>,CVector>& lastAmplitudes() { return lastMatchboxXComb()->lastAmplitudes(); }
/**
* The leading N amplitude values which have been
* contributing to the last call of prepareAmplitudes.
*/
map<vector<int>,CVector>& lastLargeNAmplitudes() { return lastMatchboxXComb()->lastLargeNAmplitudes(); }
/**
* True, if the the one-loop amplitudes need to be calculated
*/
void haveOneLoopAmplitudes(bool f = true) { lastMatchboxXComb()->haveOneLoopAmplitudes(f); }
/**
* The one-loop amplitude values which have been contributing
* to the last call of prepareAmplitudes.
*/
map<vector<int>,CVector>& lastOneLoopAmplitudes() { return lastMatchboxXComb()->lastOneLoopAmplitudes(); }
/**
* The last tree-level matrix element squared
*/
void lastTreeME2(double v) const { lastMatchboxXComb()->lastTreeME2(v); }
/**
* The last tree-level matrix element squared
*/
void lastLargeNME2(double v) const { lastMatchboxXComb()->lastLargeNME2(v); }
/**
* The last one-loop/tree-level interference.
*/
void lastOneLoopInterference(double v) const { lastMatchboxXComb()->lastOneLoopInterference(v); }
/**
* The last one-loop/tree-level interference.
*/
void lastOneLoopPoles(pair<double,double> v) const { lastMatchboxXComb()->lastOneLoopPoles(v); }
/**
* The colour correlated matrix element.
*/
void lastColourCorrelator(const pair<int,int>& ij, double v) const { lastMatchboxXComb()->lastColourCorrelator(ij,v); }
/**
* The large-N colour correlated matrix element.
*/
void lastLargeNColourCorrelator(const pair<int,int>& ij, double v) const { lastMatchboxXComb()->lastLargeNColourCorrelator(ij,v); }
/**
* The colour/spin correlated matrix element.
*/
void lastColourSpinCorrelator(const pair<int,int>& ij, Complex v) const { lastMatchboxXComb()->lastColourSpinCorrelator(ij,v); }
/**
* The spin correlated matrix element.
*/
void lastSpinCorrelator(const pair<int,int>& ij, Complex v) const { lastMatchboxXComb()->lastSpinCorrelator(ij,v); }
/**
* Set the number of light flavours to be considered for this process.
*/
void nLight(unsigned int n) { lastMatchboxXComb()->nLight(n); }
/**
* Set the elements of the vector that contains the PDG
* ids of the light flavours, which are contained in the
* jet particle group.
*/
void nLightJetVec(int n) { lastMatchboxXComb()->nLightJetVec(n); }
/**
* Set the elements of the vector that contains the PDG
* ids of the heavy flavours, which are contained in the
* jet particle group.
*/
void nHeavyJetVec(int n) { lastMatchboxXComb()->nHeavyJetVec(n); }
/**
* Set the elements of the vector that contains the PDG
* ids of the light flavours, which are contained in the
* proton particle group.
*/
void nLightProtonVec(int n) { lastMatchboxXComb()->nLightProtonVec(n); }
/**
* Set the dimensionality of the colour basis for this process.
*/
void colourBasisDim(size_t d) { lastMatchboxXComb()->colourBasisDim(d); }
/**
* Set the number of degrees of freedom required by the phase space generator
*/
void nDimPhasespace(int d) { lastMatchboxXComb()->nDimPhasespace(d); }
/**
* Set the number of degrees of freedom required by the amplitude
*/
void nDimAmplitude(int d) { lastMatchboxXComb()->nDimAmplitude(d); }
/**
* Set the number of degrees of freedom required by the insertion operators
*/
void nDimInsertions(int d) { lastMatchboxXComb()->nDimInsertions(d); }
/**
* Access the additional random numbers required by the amplitude
*/
vector<double>& amplitudeRandomNumbers() { return lastMatchboxXComb()->amplitudeRandomNumbers(); }
/**
* Access the additional random numbers required by the insertion operator
*/
vector<double>& insertionRandomNumbers() { return lastMatchboxXComb()->insertionRandomNumbers(); }
/**
* Access the diagram weights indexed by diagram id.
*/
map<int,double>& diagramWeights() { return lastMatchboxXComb()->diagramWeights(); }
/**
* Access the singular limits
*/
set<pair<size_t,size_t> >& singularLimits() { return lastMatchboxXComb()->singularLimits(); }
/**
* Access the last matched singular limit.
*/
set<pair<size_t,size_t> >::const_iterator& lastSingularLimit() { return lastMatchboxXComb()->lastSingularLimit(); }
/**
* Set the Herwig++ StandardModel object
*/
void hwStandardModel(Ptr<StandardModel>::tcptr sm) { lastMatchboxXComb()->hwStandardModel(sm); }
/**
* Set the symmetry factor
*/
void symmetryFactor(double f) const { lastMatchboxXComb()->symmetryFactor(f); }
/**
* Set the OLP process id
*/
void olpId(int pType, int id) { lastMatchboxXComb()->olpId(pType,id); }
protected:
/**
* Set the XComb pointer cast to MatchboxXComb
*/
void lastMatchboxXComb(tStdXCombPtr xc) {
theLastMatchboxXComb = xc ? &dynamic_cast<MatchboxXCombData&>(*xc) : 0;
theLastHeadMatchboxXComb =
xc && xc->head() ? &dynamic_cast<MatchboxXCombData&>(*xc->head()) : 0;
}
/**
* The XComb pointer cast to MatchboxXComb
*/
MatchboxXCombData* theLastMatchboxXComb;
/**
* The head XComb pointer cast to MatchboxXComb
*/
MatchboxXCombData* theLastHeadMatchboxXComb;
};
}
#endif // Herwig_LastMatchboxXCombInfo_H
diff --git a/MatrixElement/Matchbox/Utility/Makefile.am b/MatrixElement/Matchbox/Utility/Makefile.am
--- a/MatrixElement/Matchbox/Utility/Makefile.am
+++ b/MatrixElement/Matchbox/Utility/Makefile.am
@@ -1,32 +1,33 @@
noinst_LTLIBRARIES = libHwMatchboxUtility.la
libHwMatchboxUtility_la_SOURCES = \
AmplitudeCache.h \
AmplitudeCache.tcc \
ColourBasis.cc \
ColourBasis.h \
DiagramDrawer.cc \
DiagramDrawer.h \
MatchboxScaleChoice.cc \
MatchboxScaleChoice.h \
ProcessData.h \
ProcessData.fh \
ProcessData.cc \
SimpleColourBasis.cc \
SimpleColourBasis.h \
SimpleColourBasis2.cc \
SimpleColourBasis2.h \
SpinCorrelationTensor.h \
SpinorHelicity.h \
SU2Helper.cc \
SU2Helper.h \
Tree2toNGenerator.cc \
Tree2toNGenerator.h \
MatchboxXComb.h \
MatchboxXComb.cc \
MatchboxXCombGroup.h \
MatchboxXCombGroup.cc \
MatchboxXCombData.h \
MatchboxXCombData.cc \
-LastMatchboxXCombInfo.h
-
+LastMatchboxXCombInfo.h \
+MatchboxFactoryMatcher.h \
+MatchboxFactoryMatcher.cc
diff --git a/MatrixElement/Matchbox/Utility/MatchboxFactoryMatcher.cc b/MatrixElement/Matchbox/Utility/MatchboxFactoryMatcher.cc
new file mode 100644
--- /dev/null
+++ b/MatrixElement/Matchbox/Utility/MatchboxFactoryMatcher.cc
@@ -0,0 +1,107 @@
+// -*- C++ -*-
+//
+// MatchboxFactoryMatcher.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 MatchboxFactoryMatcher class.
+//
+
+#include "MatchboxFactoryMatcher.h"
+#include "ThePEG/Interface/ClassDocumentation.h"
+#include "ThePEG/Interface/Reference.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"
+
+using namespace Herwig;
+
+MatchboxFactoryMatcher::MatchboxFactoryMatcher()
+ : theGroup("") {}
+
+MatchboxFactoryMatcher::~MatchboxFactoryMatcher() {}
+
+IBPtr MatchboxFactoryMatcher::clone() const {
+ return new_ptr(*this);
+}
+
+IBPtr MatchboxFactoryMatcher::fullclone() const {
+ return new_ptr(*this);
+}
+
+PMPtr MatchboxFactoryMatcher::pmclone() const {
+ return new_ptr(*this);
+}
+
+bool MatchboxFactoryMatcher::check(const ParticleData & data) const {
+ return theIds.find(data.id()) != theIds.end();
+}
+
+// If needed, insert default implementations of virtual function defined
+// in the InterfacedBase class here (using ThePEG-interfaced-impl in Emacs).
+
+
+void MatchboxFactoryMatcher::persistentOutput(PersistentOStream & os) const {
+ os << theFactory << theGroup << theIds;
+}
+
+void MatchboxFactoryMatcher::persistentInput(PersistentIStream & is, int) {
+ is >> theFactory >> theGroup >> theIds;
+}
+
+void MatchboxFactoryMatcher::doinit() {
+ if ( !MatchboxFactory::isMatchboxRun() )
+ return;
+ if ( !theFactory )
+ throw InitException()
+ << "No factory object has been set for the matcher '"
+ << name() << "'" << Exception::abortnow;
+ map<string,PDVector>::const_iterator grp
+ = theFactory->particleGroups().find(theGroup);
+ if ( grp == theFactory->particleGroups().end() )
+ throw InitException()
+ << "Particle group '" << theGroup << "' not defined in factory object '"
+ << theFactory->name() << "'" << Exception::abortnow;
+ theIds.clear();
+ for ( PDVector::const_iterator p = grp->second.begin();
+ p != grp->second.end(); ++p )
+ theIds.insert((**p).id());
+ MatcherBase::doinit();
+}
+
+// *** 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<MatchboxFactoryMatcher,ThePEG::MatcherBase>
+ describeHerwigMatchboxFactoryMatcher("Herwig::MatchboxFactoryMatcher", "Herwig.so");
+
+void MatchboxFactoryMatcher::Init() {
+
+ static ClassDocumentation<MatchboxFactoryMatcher> documentation
+ ("MatchboxFactoryMatcher matches particles according to MatchboxFatory particle groups");
+
+ static Reference<MatchboxFactoryMatcher,MatchboxFactory> interfaceFactory
+ ("Factory",
+ "Set the factory to query for particle groups.",
+ &MatchboxFactoryMatcher::theFactory, false, false, true, true, false);
+
+ static Parameter<MatchboxFactoryMatcher,string> interfaceGroup
+ ("Group",
+ "Set the group name to match.",
+ &MatchboxFactoryMatcher::theGroup, "",
+ false, false);
+
+}
+
diff --git a/MatrixElement/Matchbox/Utility/MatchboxFactoryMatcher.h b/MatrixElement/Matchbox/Utility/MatchboxFactoryMatcher.h
new file mode 100644
--- /dev/null
+++ b/MatrixElement/Matchbox/Utility/MatchboxFactoryMatcher.h
@@ -0,0 +1,152 @@
+// -*- C++ -*-
+//
+// MatchboxFactoryMatcher.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_MatchboxFactoryMatcher_H
+#define Herwig_MatchboxFactoryMatcher_H
+//
+// This is the declaration of the MatchboxFactoryMatcher class.
+//
+
+#include "ThePEG/PDT/MatcherBase.h"
+#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.h"
+
+namespace Herwig {
+
+using namespace ThePEG;
+
+/**
+ * \ingroup Matchbox
+ * \author Simon Platzer
+ *
+ * \brief MatchboxFactoryMatcher matches particles according to
+ * MatchboxFatory particle groups
+ *
+ * @see \ref MatchboxFactoryMatcherInterfaces "The interfaces"
+ * defined for MatchboxFactoryMatcher.
+ */
+class MatchboxFactoryMatcher: public ThePEG::MatcherBase {
+
+public:
+
+ /** @name Standard constructors and destructors. */
+ //@{
+ /**
+ * The default constructor.
+ */
+ MatchboxFactoryMatcher();
+
+ /**
+ * The destructor.
+ */
+ virtual ~MatchboxFactoryMatcher();
+ //@}
+
+public:
+
+ /**
+ * Check if a particle type meets the criteria.
+ */
+ virtual bool check(const ParticleData &) const;
+
+ /**
+ * Specialized clone method for MatcherBase used by the
+ * Repository. A sub class must make sure that also the MatcherBase
+ * object corresponding to the complex conjugate of this is cloned.
+ */
+ virtual PMPtr pmclone() 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).
+
+
+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:
+
+ /**
+ * A pointer to the factory to be used
+ */
+ Ptr<MatchboxFactory>::ptr theFactory;
+
+ /**
+ * The particle group to be matched
+ */
+ string theGroup;
+
+ /**
+ * The set of particle ids to be matched
+ */
+ set<long> theIds;
+
+private:
+
+ /**
+ * The assignment operator is private and must never be called.
+ * In fact, it should not even be implemented.
+ */
+ MatchboxFactoryMatcher & operator=(const MatchboxFactoryMatcher &);
+
+};
+
+}
+
+#endif /* Herwig_MatchboxFactoryMatcher_H */
diff --git a/MatrixElement/Matchbox/Utility/MatchboxXCombData.cc b/MatrixElement/Matchbox/Utility/MatchboxXCombData.cc
--- a/MatrixElement/Matchbox/Utility/MatchboxXCombData.cc
+++ b/MatrixElement/Matchbox/Utility/MatchboxXCombData.cc
@@ -1,320 +1,330 @@
// -*- C++ -*-
//
// MatchboxXCombData.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 MatchboxXCombData class.
//
#include "MatchboxXCombData.h"
#include "Herwig++/MatrixElement/Matchbox/Base/MatchboxMEBase.h"
#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.h"
#include "Herwig++/MatrixElement/Matchbox/Dipoles/SubtractionDipole.h"
#include "Herwig++/Utilities/GSLBisection.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
using namespace Herwig;
MatchboxXCombData::MatchboxXCombData()
: theCrossingSign(1.0), theCalculateTreeAmplitudes(true),
theCalculateOneLoopAmplitudes(true), theCalculateTreeME2(true),
theLastTreeME2(0.0), theCalculateLargeNME2(true),
theLastLargeNME2(0.0), theCalculateOneLoopInterference(true),
theLastOneLoopInterference(0.0), theCalculateOneLoopPoles(true),
theLastOneLoopPoles(0.0,0.0),
theNLight(0),
theColourBasisDim(0), theNDimPhasespace(0),
theNDimAmplitude(0), theNDimInsertions(0),
theSymmetryFactor(0.0), theOLPMomenta(0),
filledOLPMomenta(false), theExternalId(0),
theInitialized(false), filledExternalMomenta(false) {
flushCaches();
}
MatchboxXCombData::~MatchboxXCombData() {
if ( theOLPMomenta ) {
delete[] theOLPMomenta;
theOLPMomenta = 0;
}
for ( vector<double*>::iterator k = theExternalMomenta.begin();
k != theExternalMomenta.end(); ++k ) {
delete[] *k;
*k = 0;
}
theExternalMomenta.clear();
}
MatchboxXCombData::MatchboxXCombData(tMEPtr newME)
: theCrossingSign(1.0), theCalculateTreeAmplitudes(true),
theCalculateOneLoopAmplitudes(true), theCalculateTreeME2(true),
theLastTreeME2(0.0), theCalculateLargeNME2(true),
theLastLargeNME2(0.0), theCalculateOneLoopInterference(true),
theLastOneLoopInterference(0.0), theCalculateOneLoopPoles(true),
theLastOneLoopPoles(0.0,0.0), theNLight(0),
theColourBasisDim(0), theNDimPhasespace(0),
theNDimAmplitude(0), theNDimInsertions(0),
theSymmetryFactor(0.0), theOLPMomenta(0),
filledOLPMomenta(false), theExternalId(0),
theInitialized(false), filledExternalMomenta(false) {
flushCaches();
theMatchboxME = dynamic_ptr_cast<Ptr<MatchboxMEBase>::tptr>(newME);
theSubtractionDipole = dynamic_ptr_cast<Ptr<SubtractionDipole>::tptr>(newME);
Ptr<SubtractedME>::tptr subme =
dynamic_ptr_cast<Ptr<SubtractedME>::tptr>(newME);
if ( !theMatchboxME && !theSubtractionDipole && subme )
theMatchboxME = dynamic_ptr_cast<Ptr<MatchboxMEBase>::tptr>(subme->head());
assert(theMatchboxME || theSubtractionDipole);
if ( theMatchboxME )
theFactory = theMatchboxME->factory();
else if ( theSubtractionDipole )
theFactory = theSubtractionDipole->realEmissionME()->factory();
assert(theFactory);
}
double MatchboxXCombData::ReshuffleEquation::operator() (double xi) const {
double res = -q/GeV;
cPDVector::const_iterator dit = dBegin;
vector<Lorentz5Momentum>::const_iterator mit = mBegin;
for ( ; dit != dEnd; ++dit, ++mit ) {
map<long,Energy>::const_iterator rm =
reshuffleMap->find((**dit).id());
Energy2 tmass2 =
rm == reshuffleMap->end() ?
mit->mass2() : sqr(rm->second);
res += sqrt(sqr(xi)*(mit->vect().mag2()) + tmass2)/GeV;
}
return res;
}
void MatchboxXCombData::reshuffle(vector<Lorentz5Momentum>& momenta,
const cPDVector& mePartonData,
const map<long,Energy>& reshuffleMap) const {
- if ( momenta.size() == 3 ) // nothing to do; don't thro an exception
+ if ( momenta.size() == 3 ) // nothing to do; don't throw an exception
+ return;
+
+ bool needDoSomething = false;
+ for ( cPDVector::const_iterator d = mePartonData.begin() + 2;
+ d != mePartonData.end(); ++d )
+ needDoSomething |= reshuffleMap.find((**d).id()) != reshuffleMap.end();
+
+ if ( !needDoSomething )
return;
Lorentz5Momentum Q(ZERO,ZERO,ZERO,ZERO);
for ( vector<Lorentz5Momentum>::const_iterator p = momenta.begin()+2;
p != momenta.end(); ++p )
Q += *p;
Boost beta = Q.findBoostToCM();
bool needBoost = (beta.mag2() > Constants::epsilon);
if ( needBoost ) {
for ( vector<Lorentz5Momentum>::iterator p = momenta.begin()+2;
p != momenta.end(); ++p )
p->boost(beta);
}
ReshuffleEquation solve(Q.m(),
mePartonData.begin() + 2,
mePartonData.end(),
momenta.begin() + 2, &reshuffleMap);
double xi = 1.;
GSLBisection solver(1e-10,1e-8,10000);
try {
xi = solver.value(solve,0.0,1.1);
} catch (GSLBisection::GSLerror) {
throw Veto();
} catch (GSLBisection::IntervalError) {
throw Veto();
}
cPDVector::const_iterator d = mePartonData.begin() + 2;
vector<Lorentz5Momentum>::iterator p = momenta.begin() + 2;
for ( ; d != mePartonData.end(); ++d, ++p ) {
p->setVect(xi*p->vect());
map<long,Energy>::const_iterator mit =
reshuffleMap.find((**d).id());
Energy2 newMass2 = mit == reshuffleMap.end() ? p->mass2() : sqr(mit->second);
p->setE(sqrt(p->vect().mag2() + newMass2));
p->rescaleMass();
}
if ( needBoost ) {
for ( vector<Lorentz5Momentum>::iterator p = momenta.begin()+2;
p != momenta.end(); ++p )
p->boost(-beta);
}
}
void MatchboxXCombData::fillOLPMomenta(const vector<Lorentz5Momentum>& memomenta,
const cPDVector& mePartonData,
const map<long,Energy>& reshuffleMap) {
if ( filledOLPMomenta )
return;
if ( !reshuffleMap.empty() && memomenta.size() > 3 ) {
vector<Lorentz5Momentum> reshuffled = memomenta;
reshuffle(reshuffled,mePartonData,reshuffleMap);
fillOLPMomenta(reshuffled);
return;
}
if ( !theOLPMomenta ) {
theOLPMomenta = new double[5*memomenta.size()];
}
for ( size_t p = 0; p < memomenta.size(); ++p ) {
theOLPMomenta[5*p] = memomenta[p].t()/GeV;
theOLPMomenta[5*p+1] = memomenta[p].x()/GeV;
theOLPMomenta[5*p+2] = memomenta[p].y()/GeV;
theOLPMomenta[5*p+3] = memomenta[p].z()/GeV;
theOLPMomenta[5*p+4] = memomenta[p].mass()/GeV;
}
filledOLPMomenta = true;
}
void MatchboxXCombData::fillExternalMomenta(const vector<Lorentz5Momentum>& memomenta) {
if ( filledExternalMomenta )
return;
if ( theExternalMomenta.empty() ) {
theExternalMomenta.resize(memomenta.size());
for ( size_t k = 0; k < memomenta.size(); ++k )
theExternalMomenta[k] = new double[4];
}
for ( size_t p = 0; p < memomenta.size(); ++p ) {
theExternalMomenta[p][0] = memomenta[p].t()/GeV;
theExternalMomenta[p][1] = memomenta[p].x()/GeV;
theExternalMomenta[p][2] = memomenta[p].y()/GeV;
theExternalMomenta[p][3] = memomenta[p].z()/GeV;
}
filledExternalMomenta = true;
}
Ptr<MatchboxFactory>::tcptr MatchboxXCombData::factory() const {
return theFactory;
}
Ptr<MatchboxMEBase>::tptr MatchboxXCombData::matchboxME() const {
return theMatchboxME;
}
Ptr<SubtractionDipole>::tptr MatchboxXCombData::subtractionDipole() const {
return theSubtractionDipole;
}
void MatchboxXCombData::flushCaches() {
theCalculateTreeAmplitudes = true;
theCalculateOneLoopAmplitudes = true;
theCalculateTreeME2 = true;
theCalculateLargeNME2 = true;
theCalculateOneLoopInterference = true;
theCalculateOneLoopPoles = true;
for ( map<pair<int,int>,bool>::iterator f = theCalculateColourCorrelators.begin();
f != theCalculateColourCorrelators.end(); ++f )
f->second = true;
for ( map<pair<int,int>,bool>::iterator f = theCalculateLargeNColourCorrelators.begin();
f != theCalculateLargeNColourCorrelators.end(); ++f )
f->second = true;
for ( map<pair<int,int>,bool>::iterator f = theCalculateColourSpinCorrelators.begin();
f != theCalculateColourSpinCorrelators.end(); ++f )
f->second = true;
for ( map<pair<int,int>,bool>::iterator f = theCalculateSpinCorrelators.begin();
f != theCalculateSpinCorrelators.end(); ++f )
f->second = true;
filledOLPMomenta = false;
filledExternalMomenta = false;
}
void MatchboxXCombData::putCVector(PersistentOStream& os, const CVector& v) {
size_t n = v.size();
os << n;
for ( size_t k = 0; k < n; k++ )
os << v(k);
}
void MatchboxXCombData::getCVector(PersistentIStream& is, CVector& v) {
size_t n; is >> n;
v.resize(n);
Complex value;
for ( size_t k = 0; k < n; k++ ) {
is >> value; v(k) = value;
}
}
void MatchboxXCombData::putAmplitudeMap(PersistentOStream& os, const map<vector<int>,CVector>& amps) {
os << amps.size();
for ( map<vector<int>,CVector>::const_iterator a = amps.begin();
a != amps.end(); ++a ) {
os << a->first;
putCVector(os,a->second);
}
}
void MatchboxXCombData::getAmplitudeMap(PersistentIStream& is, map<vector<int>,CVector>& amps) {
size_t n; is >> n;
for ( size_t k = 0; k < n; ++k ) {
vector<int> hel; is >> hel;
getCVector(is,amps[hel]);
}
}
void MatchboxXCombData::persistentOutput(PersistentOStream & os) const {
os << theFactory << theMatchboxME << theSubtractionDipole << theCrossingMap
<< theAmplitudeToColourMap << theColourToAmplitudeMap
<< theCrossingSign << theAmplitudePartonData << ounit(theAmplitudeMomenta,GeV)
+ << ounit(theLastRenormalizationScale,GeV2)
<< theCalculateTreeAmplitudes /* << theLastAmplitudes << theLastLargeNAmplitudes */
<< theCalculateOneLoopAmplitudes /* << theLastOneLoopAmplitudes */
<< theCalculateTreeME2 << theLastTreeME2
<< theCalculateLargeNME2 << theLastLargeNME2
<< theCalculateOneLoopInterference
<< theLastOneLoopInterference << theCalculateOneLoopPoles
<< theLastOneLoopPoles << theCalculateColourCorrelators
<< theColourCorrelators << theCalculateLargeNColourCorrelators
<< theLargeNColourCorrelators << theCalculateColourSpinCorrelators
<< theColourSpinCorrelators << theCalculateSpinCorrelators
<< theSpinCorrelators << theNLight
<< theNLightJetVec << theNHeavyJetVec << theNLightProtonVec
<< theColourBasisDim
<< theNDimPhasespace << theNDimAmplitude << theNDimInsertions
<< theAmplitudeRandomNumbers << theInsertionRandomNumbers
<< theDiagramWeights << theSingularLimits// << theLastSingularLimit
<< theStandardModel << theSymmetryFactor
<< theOLPId << theExternalId;
putAmplitudeMap(os,theLastAmplitudes);
putAmplitudeMap(os,theLastLargeNAmplitudes);
putAmplitudeMap(os,theLastOneLoopAmplitudes);
}
void MatchboxXCombData::persistentInput(PersistentIStream & is, int) {
is >> theFactory >> theMatchboxME >> theSubtractionDipole >> theCrossingMap
>> theAmplitudeToColourMap >> theColourToAmplitudeMap
>> theCrossingSign >> theAmplitudePartonData >> iunit(theAmplitudeMomenta,GeV)
+ >> iunit(theLastRenormalizationScale,GeV2)
>> theCalculateTreeAmplitudes /* >> theLastAmplitudes >> theLastLargeNAmplitudes */
>> theCalculateOneLoopAmplitudes /* >> theLastOneLoopAmplitudes */
>> theCalculateTreeME2 >> theLastTreeME2
>> theCalculateLargeNME2 >> theLastLargeNME2
>> theCalculateOneLoopInterference
>> theLastOneLoopInterference >> theCalculateOneLoopPoles
>> theLastOneLoopPoles >> theCalculateColourCorrelators
>> theColourCorrelators >> theCalculateLargeNColourCorrelators
>> theLargeNColourCorrelators >> theCalculateColourSpinCorrelators
>> theColourSpinCorrelators >> theCalculateSpinCorrelators
>> theSpinCorrelators >> theNLight
>> theNLightJetVec >> theNHeavyJetVec >> theNLightProtonVec
>> theColourBasisDim
>> theNDimPhasespace >> theNDimAmplitude >> theNDimInsertions
>> theAmplitudeRandomNumbers >> theInsertionRandomNumbers
>> theDiagramWeights >> theSingularLimits// >> theLastSingularLimit
>> theStandardModel >> theSymmetryFactor
>> theOLPId >> theExternalId;
getAmplitudeMap(is,theLastAmplitudes);
getAmplitudeMap(is,theLastLargeNAmplitudes);
getAmplitudeMap(is,theLastOneLoopAmplitudes);
}
diff --git a/MatrixElement/Matchbox/Utility/MatchboxXCombData.h b/MatrixElement/Matchbox/Utility/MatchboxXCombData.h
--- a/MatrixElement/Matchbox/Utility/MatchboxXCombData.h
+++ b/MatrixElement/Matchbox/Utility/MatchboxXCombData.h
@@ -1,1091 +1,1106 @@
// -*- C++ -*-
//
// MatchboxXCombData.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_MatchboxXCombData_H
#define Herwig_MatchboxXCombData_H
//
// This is the declaration of the MatchboxXCombData class.
//
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <boost/numeric/ublas/symmetric.hpp>
#include <boost/numeric/ublas/vector.hpp>
#include "ThePEG/MatrixElement/MEBase.h"
#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.fh"
#include "Herwig++/MatrixElement/Matchbox/Base/MatchboxMEBase.fh"
#include "Herwig++/MatrixElement/Matchbox/Dipoles/SubtractionDipole.fh"
#include "Herwig++/Models/StandardModel/StandardModel.h"
#include "ThePEG/Persistency/PersistentOStream.fh"
#include "ThePEG/Persistency/PersistentIStream.fh"
namespace Herwig {
using namespace ThePEG;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief Define complex vector from boost::uBLAS
*/
typedef boost::numeric::ublas::vector<Complex> CVector;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief Define how amplitudes are stored
*/
typedef map<vector<int>,CVector> AmplitudeMap;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief Define amplitude iterators
*/
typedef map<vector<int>,CVector>::iterator AmplitudeIterator;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief Define amplitude const iterators
*/
typedef map<vector<int>,CVector>::const_iterator AmplitudeConstIterator;
/**
* \ingroup Matchbox
* \author Simon Platzer
*
* \brief Matchbox extensions to StandardXComb
*/
class MatchboxXCombData {
public:
/** @name Standard constructors and destructors. */
//@{
/**
* Standard constructor.
*/
explicit MatchboxXCombData(tMEPtr newME);
/**
* Default constructor.
*/
MatchboxXCombData();
/**
* Destructor.
*/
virtual ~MatchboxXCombData();
//@}
public:
/**
* Reset all cache flags
*/
void flushCaches();
public:
/**
* Get the factory
*/
Ptr<MatchboxFactory>::tcptr factory() const;
/**
* Get the matrix element; may return null
*/
Ptr<MatchboxMEBase>::tptr matchboxME() const;
/**
* Get the dipole; may return null
*/
Ptr<SubtractionDipole>::tptr subtractionDipole() const;
/**
* The crossing information as filled by the last call to
* fillCrossingMap()
*/
const vector<int>& crossingMap() const { return theCrossingMap; }
/**
* The crossing information as filled by the last call to
* fillCrossingMap()
*/
vector<int>& crossingMap() { return theCrossingMap; }
/**
* The colour crossing information as filled by the last call to
* fillCrossingMap()
*/
const map<size_t,size_t>& amplitudeToColourMap() const { return theAmplitudeToColourMap; }
/**
* The colour crossing information as filled by the last call to
* fillCrossingMap()
*/
map<size_t,size_t>& amplitudeToColourMap() { return theAmplitudeToColourMap; }
/**
* The colour crossing information as filled by the last call to
* fillCrossingMap()
*/
const map<size_t,size_t>& colourToAmplitudeMap() const { return theColourToAmplitudeMap; }
/**
* The colour crossing information as filled by the last call to
* fillCrossingMap()
*/
map<size_t,size_t>& colourToAmplitudeMap() { return theColourToAmplitudeMap; }
/**
* The crossing sign as filled by the last call to
* fillCrossingMap()
*/
double crossingSign() const { return theCrossingSign; }
/**
* The crossing sign as filled by the last call to
* fillCrossingMap()
*/
void crossingSign(double c) { theCrossingSign = c; }
/**
+ * The last renormalization scale
+ */
+ Energy2 lastRenormalizationScale() const { return theLastRenormalizationScale; }
+
+ /**
+ * The last renormalization scale
+ */
+ void lastRenormalizationScale(Energy2 lrs) { theLastRenormalizationScale = lrs; }
+
+ /**
* The amplitude parton data.
*/
const cPDVector& amplitudePartonData() const { return theAmplitudePartonData; }
/**
* The amplitude parton data.
*/
cPDVector& amplitudePartonData() { return theAmplitudePartonData; }
/**
* The crossed momenta
*/
const vector<Lorentz5Momentum>& amplitudeMomenta() const { return theAmplitudeMomenta; }
/**
* The crossed momenta
*/
vector<Lorentz5Momentum>& amplitudeMomenta() { return theAmplitudeMomenta; }
/**
* True, if the the tree level amplitudes need to be calculated
*/
bool calculateTreeAmplitudes() const { return theCalculateTreeAmplitudes; }
/**
* The amplitude values which have been contributing
* to the last call of prepareAmplitudes.
*/
const map<vector<int>,CVector>& lastAmplitudes() const { return theLastAmplitudes; }
/**
* True, if the the tree level amplitudes need to be calculated
*/
void haveTreeAmplitudes(bool f = true) { theCalculateTreeAmplitudes = !f; }
/**
* The amplitude values which have been contributing
* to the last call of prepareAmplitudes.
*/
map<vector<int>,CVector>& lastAmplitudes() { return theLastAmplitudes; }
/**
* The leading N amplitude values which have been
* contributing to the last call of prepareAmplitudes.
*/
const map<vector<int>,CVector>& lastLargeNAmplitudes() const { return theLastLargeNAmplitudes; }
/**
* The leading N amplitude values which have been
* contributing to the last call of prepareAmplitudes.
*/
map<vector<int>,CVector>& lastLargeNAmplitudes() { return theLastLargeNAmplitudes; }
/**
* True, if the the one-loop amplitudes need to be calculated
*/
bool calculateOneLoopAmplitudes() const { return theCalculateOneLoopAmplitudes; }
/**
* The one-loop amplitude values which have been contributing
* to the last call of prepareAmplitudes.
*/
const map<vector<int>,CVector>& lastOneLoopAmplitudes() const { return theLastOneLoopAmplitudes; }
/**
* True, if the the one-loop amplitudes need to be calculated
*/
void haveOneLoopAmplitudes(bool f = true) { theCalculateOneLoopAmplitudes = !f; }
/**
* The one-loop amplitude values which have been contributing
* to the last call of prepareAmplitudes.
*/
map<vector<int>,CVector>& lastOneLoopAmplitudes() { return theLastOneLoopAmplitudes; }
/**
* True, if the tree-level matrix element squared needs to be
* calculated.
*/
bool calculateTreeME2() const { return theCalculateTreeME2; }
/**
* The last tree-level matrix element squared
*/
double lastTreeME2() const { return theLastTreeME2; }
/**
* The last tree-level matrix element squared
*/
void lastTreeME2(double v) {
theLastTreeME2 = v; theCalculateTreeME2 = false;
}
/**
* True, if the tree-level matrix element squared needs to be
* calculated.
*/
bool calculateLargeNME2() const { return theCalculateLargeNME2; }
/**
* The last tree-level matrix element squared
*/
double lastLargeNME2() const { return theLastLargeNME2; }
/**
* The last tree-level matrix element squared
*/
void lastLargeNME2(double v) {
theLastLargeNME2 = v; theCalculateLargeNME2 = false;
}
/**
* True, if the one-loop/tree-level interference.
* be calculated.
*/
bool calculateOneLoopInterference() const { return theCalculateOneLoopInterference; }
/**
* The last one-loop/tree-level interference.
*/
double lastOneLoopInterference() const { return theLastOneLoopInterference; }
/**
* The last one-loop/tree-level interference.
*/
void lastOneLoopInterference(double v) {
theLastOneLoopInterference = v; theCalculateOneLoopInterference = false;
}
/**
* True, if the one-loop/tree-level interference.
* be calculated.
*/
bool calculateOneLoopPoles() const { return theCalculateOneLoopPoles; }
/**
* The last one-loop/tree-level interference.
*/
pair<double,double> lastOneLoopPoles() const { return theLastOneLoopPoles; }
/**
* The last one-loop/tree-level interference.
*/
void lastOneLoopPoles(pair<double,double> v) {
theLastOneLoopPoles = v; theCalculateOneLoopPoles = false;
}
/**
* True, if the indexed colour correlated matrix element needs to be
* calculated.
*/
bool calculateColourCorrelator(pair<int,int> ij) const {
if ( ij.first > ij.second )
swap(ij.first,ij.second);
map<pair<int,int>,bool>::const_iterator f =
theCalculateColourCorrelators.find(ij);
if ( f == theCalculateColourCorrelators.end() )
return true;
return f->second;
}
/**
* The colour correlated matrix element.
*/
double lastColourCorrelator(pair<int,int> ij) const {
if ( ij.first > ij.second )
swap(ij.first,ij.second);
map<pair<int,int>,double>::const_iterator v =
theColourCorrelators.find(ij);
if ( v == theColourCorrelators.end() )
return 0.;
return v->second;
}
/**
* The colour correlated matrix element.
*/
void lastColourCorrelator(pair<int,int> ij, double v) {
if ( ij.first > ij.second )
swap(ij.first,ij.second);
theColourCorrelators[ij] = v;
theCalculateColourCorrelators[ij] = false;
}
/**
* True, if the indexed large-N colour correlated matrix element needs to be
* calculated.
*/
bool calculateLargeNColourCorrelator(pair<int,int> ij) const {
if ( ij.first > ij.second )
swap(ij.first,ij.second);
map<pair<int,int>,bool>::const_iterator f =
theCalculateLargeNColourCorrelators.find(ij);
if ( f == theCalculateLargeNColourCorrelators.end() )
return true;
return f->second;
}
/**
* The large-N colour correlated matrix element.
*/
double lastLargeNColourCorrelator(pair<int,int> ij) const {
if ( ij.first > ij.second )
swap(ij.first,ij.second);
map<pair<int,int>,double>::const_iterator v =
theLargeNColourCorrelators.find(ij);
if ( v == theLargeNColourCorrelators.end() )
return 0.;
return v->second;
}
/**
* The large-N colour correlated matrix element.
*/
void lastLargeNColourCorrelator(pair<int,int> ij, double v) {
if ( ij.first > ij.second )
swap(ij.first,ij.second);
theLargeNColourCorrelators[ij] = v;
theCalculateLargeNColourCorrelators[ij] = false;
}
/**
* True, if the indexed colour/spin correlated matrix element needs to be
* calculated.
*/
bool calculateColourSpinCorrelator(const pair<int,int>& ij) const {
map<pair<int,int>,bool>::const_iterator f =
theCalculateColourSpinCorrelators.find(ij);
if ( f == theCalculateColourSpinCorrelators.end() )
return true;
return f->second;
}
/**
* The colour/spin correlated matrix element.
*/
Complex lastColourSpinCorrelator(const pair<int,int>& ij) const {
map<pair<int,int>,Complex>::const_iterator v =
theColourSpinCorrelators.find(ij);
if ( v == theColourSpinCorrelators.end() )
return 0.;
return v->second;
}
/**
* The colour/spin correlated matrix element.
*/
void lastColourSpinCorrelator(const pair<int,int>& ij, Complex v) {
theColourSpinCorrelators[ij] = v;
theCalculateColourSpinCorrelators[ij] = false;
}
/**
* True, if the indexed spin correlated matrix element needs to be
* calculated.
*/
bool calculateSpinCorrelator(const pair<int,int>& ij) const {
map<pair<int,int>,bool>::const_iterator f =
theCalculateSpinCorrelators.find(ij);
if ( f == theCalculateSpinCorrelators.end() )
return true;
return f->second;
}
/**
* The spin correlated matrix element.
*/
Complex lastSpinCorrelator(const pair<int,int>& ij) const {
map<pair<int,int>,Complex>::const_iterator v =
theSpinCorrelators.find(ij);
if ( v == theSpinCorrelators.end() )
return 0.;
return v->second;
}
/**
* The spin correlated matrix element.
*/
void lastSpinCorrelator(const pair<int,int>& ij, Complex v) {
theSpinCorrelators[ij] = v;
theCalculateSpinCorrelators[ij] = false;
}
/**
* Return the number of light flavours to be considered for this process.
*/
unsigned int nLight() const { return theNLight; }
/**
* Set the number of light flavours to be considered for this process.
*/
void nLight(unsigned int n) { theNLight = n; }
/**
* Return the vector that contains the PDG ids of
* the light flavours, which are contained in the
* jet particle group.
*/
vector<int> nLightJetVec() const { return theNLightJetVec; }
/**
* Set the elements of the vector that contains the PDG
* ids of the light flavours, which are contained in the
* jet particle group.
*/
void nLightJetVec(int n) { theNLightJetVec.push_back(n); }
/**
* Return the vector that contains the PDG ids of
* the heavy flavours, which are contained in the
* jet particle group.
*/
vector<int> nHeavyJetVec() const { return theNHeavyJetVec; }
/**
* Set the elements of the vector that contains the PDG
* ids of the heavy flavours, which are contained in the
* jet particle group.
*/
void nHeavyJetVec(int n) { theNHeavyJetVec.push_back(n); }
/**
* Return the vector that contains the PDG ids of
* the light flavours, which are contained in the
* proton particle group.
*/
vector<int> nLightProtonVec() const { return theNLightProtonVec; }
/**
* Set the elements of the vector that contains the PDG
* ids of the light flavours, which are contained in the
* proton particle group.
*/
void nLightProtonVec(int n) { theNLightProtonVec.push_back(n); }
/**
* Get the dimensionality of the colour basis for this process.
*/
size_t colourBasisDim() const { return theColourBasisDim; }
/**
* Set the dimensionality of the colour basis for this process.
*/
void colourBasisDim(size_t d) { theColourBasisDim = d; }
/**
* Return the number of degrees of freedom required by the phase space generator
*/
int nDimPhasespace() const { return theNDimPhasespace; }
/**
* Set the number of degrees of freedom required by the phase space generator
*/
void nDimPhasespace(int d) { theNDimPhasespace = d; }
/**
* Return the number of degrees of freedom required by the amplitude
*/
int nDimAmplitude() const { return theNDimAmplitude; }
/**
* Set the number of degrees of freedom required by the amplitude
*/
void nDimAmplitude(int d) { theNDimAmplitude = d; }
/**
* Return the number of degrees of freedom required by the insertion operators
*/
int nDimInsertions() const { return theNDimInsertions; }
/**
* Set the number of degrees of freedom required by the insertion operators
*/
void nDimInsertions(int d) { theNDimInsertions = d; }
/**
* Get the additional random numbers required by the amplitude
*/
const vector<double>& amplitudeRandomNumbers() const { return theAmplitudeRandomNumbers; }
/**
* Access the additional random numbers required by the amplitude
*/
vector<double>& amplitudeRandomNumbers() { return theAmplitudeRandomNumbers; }
/**
* Get the additional random numbers required by the insertion operator
*/
const vector<double>& insertionRandomNumbers() const { return theInsertionRandomNumbers; }
/**
* Access the additional random numbers required by the insertion operator
*/
vector<double>& insertionRandomNumbers() { return theInsertionRandomNumbers; }
/**
* Return the diagram weights indexed by diagram id.
*/
const map<int,double>& diagramWeights() const { return theDiagramWeights; }
/**
* Access the diagram weights indexed by diagram id.
*/
map<int,double>& diagramWeights() { return theDiagramWeights; }
/**
* Return the singular limits
*/
const set<pair<size_t,size_t> >& singularLimits() const { return theSingularLimits; }
/**
* Access the singular limits
*/
set<pair<size_t,size_t> >& singularLimits() { return theSingularLimits; }
/**
* Return the last matched singular limit.
*/
const set<pair<size_t,size_t> >::const_iterator& lastSingularLimit() const { return theLastSingularLimit; }
/**
* Access the last matched singular limit.
*/
set<pair<size_t,size_t> >::const_iterator& lastSingularLimit() { return theLastSingularLimit; }
/**
* Set the Herwig++ StandardModel object
*/
void hwStandardModel(Ptr<StandardModel>::tcptr sm) { theStandardModel = sm; }
/**
* Get the Herwig++ StandardModel object
*/
Ptr<StandardModel>::tcptr hwStandardModel() const { return theStandardModel; }
/**
* Return the symmetry factor
*/
double symmetryFactor() const { return theSymmetryFactor; }
/**
* Set the symmetry factor
*/
void symmetryFactor(double f) { theSymmetryFactor = f; }
/**
* Return the OLP process ids
*/
const vector<int>& olpId() const { return theOLPId; }
/**
* Set the OLP process ids
*/
void olpId(int pType, int id) {
if ( theOLPId.empty() )
theOLPId.resize(4,0);
theOLPId[pType] = id;
}
/**
* Set the OLP process ids
*/
void olpId(const vector<int>& id) {
theOLPId = id;
}
/**
* Return the olp momentum vector
*/
double* olpMomenta() { return theOLPMomenta; }
/**
* Fill the olp momentum vector
*/
void fillOLPMomenta(const vector<Lorentz5Momentum>& mm,
const cPDVector& mePartonData = cPDVector(),
const map<long,Energy>& reshuffleMap = map<long,Energy>());
/**
* Helper struct to define the reshuffling equation
*/
struct ReshuffleEquation {
ReshuffleEquation(Energy xq,
cPDVector::const_iterator xdBegin,
cPDVector::const_iterator xdEnd,
vector<Lorentz5Momentum>::const_iterator xmBegin,
const map<long,Energy>* xreshuffleMap)
: q(xq), dBegin(xdBegin), dEnd(xdEnd), mBegin(xmBegin),
reshuffleMap(xreshuffleMap) {}
typedef double ArgType;
typedef double ValType;
static double aUnit() { return 1.; }
static double vUnit() { return 1.; }
double operator() (double xi) const;
Energy q;
cPDVector::const_iterator dBegin;
cPDVector::const_iterator dEnd;
vector<Lorentz5Momentum>::const_iterator mBegin;
const map<long,Energy>* reshuffleMap;
};
/**
* Perform a reshuffling to the mass shells contained in the map
*/
void reshuffle(vector<Lorentz5Momentum>& momenta,
const cPDVector& mePartonData,
const map<long,Energy>& reshuffleMap) const;
/**
* Return a generic process id to communicate with external codes
*/
int externalId() const { return theExternalId; }
/**
* Set a generic process id to communicate with external codes
*/
void externalId(int id) { theExternalId = id; }
/**
* True if the process has been initialized
*/
bool initialized() const { return theInitialized; }
/**
* True if the process has been initialized
*/
void isInitialized(bool is = true) { theInitialized = is; }
/**
* Return the external momentum vector
*/
const vector<double*>& externalMomenta() const { return theExternalMomenta; }
/**
* Fill the external momentum vector
*/
void fillExternalMomenta(const vector<Lorentz5Momentum>&);
/**
* Caching for the external madgraph colour structures
*/
const map<vector<int>,vector < complex<double> > >& heljamp() const { return theHelJamp; }
/**
* Caching for the external madgraph colour structures (large N)
*/
const map<vector<int>,vector < complex<double> > >& helLNjamp() const { return theLNHelJamp; }
/**
* pushback the madgraph colour structures
*/
void pushheljamp(const vector<int>& hel, const complex<double>& jamp) { theHelJamp[hel].push_back(jamp); }
/**
* clear the madgraph colour structures
*/
void clearheljamp() { theHelJamp.clear(); }
/**
* pushback the madgraph colour structures (large N)
*/
void pushhelLNjamp(const vector<int>& hel, const complex<double>& jamp) { theLNHelJamp[hel].push_back(jamp); }
/**
* clear the madgraph colour structures (large N)
*/
void clearhelLNjamp() { theLNHelJamp.clear(); }
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);
/**
* Put a CVector to the persistent ostream
*/
static void putCVector(PersistentOStream&, const CVector&);
/**
* Get a CVector from the persistent istream
*/
static void getCVector(PersistentIStream&, CVector&);
/**
* Put an amplitude map to the persistent ostream
*/
static void putAmplitudeMap(PersistentOStream&, const map<vector<int>,CVector>&);
/**
* Get an amplitude map from the persistent istream
*/
static void getAmplitudeMap(PersistentIStream&, map<vector<int>,CVector>&);
//@}
/**
* 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.
*/
MatchboxXCombData & operator=(const MatchboxXCombData &);
private:
/**
* The factory
*/
Ptr<MatchboxFactory>::tcptr theFactory;
/**
* The matrix element
*/
Ptr<MatchboxMEBase>::tptr theMatchboxME;
/**
* The dipole
*/
Ptr<SubtractionDipole>::tptr theSubtractionDipole;
/**
* The crossing information as filled by the last call to
* fillCrossingMap()
*/
vector<int> theCrossingMap;
/**
* The colour crossing information as filled by the last call to
* fillCrossingMap()
*/
map<size_t,size_t> theAmplitudeToColourMap;
/**
* The colour crossing information as filled by the last call to
* fillCrossingMap()
*/
map<size_t,size_t> theColourToAmplitudeMap;
/**
* The crossing sign as filled by the last call to
* fillCrossingMap()
*/
double theCrossingSign;
/**
+ * The last renormalization scale
+ */
+ Energy2 theLastRenormalizationScale;
+
+ /**
* The amplitude parton data.
*/
cPDVector theAmplitudePartonData;
/**
* The ccrossed momenta
*/
vector<Lorentz5Momentum> theAmplitudeMomenta;
/**
* True, if the the tree level amplitudes need to be calculated
*/
bool theCalculateTreeAmplitudes;
/**
* The amplitude values which have been contributing
* to the last call of prepareAmplitudes.
*/
map<vector<int>,CVector> theLastAmplitudes;
/**
* The leading N amplitude values which have been
* contributing to the last call of prepareAmplitudes.
*/
map<vector<int>,CVector> theLastLargeNAmplitudes;
/**
* True, if the the one-loop amplitudes need to be calculated
*/
bool theCalculateOneLoopAmplitudes;
/**
* The one-loop amplitude values which have been contributing
* to the last call of prepareAmplitudes.
*/
map<vector<int>,CVector> theLastOneLoopAmplitudes;
/**
* True, if the tree-level matrix element squared needs to be
* calculated.
*/
bool theCalculateTreeME2;
/**
* The last tree-level matrix element squared
*/
double theLastTreeME2;
/**
* True, if the tree-level matrix element squared needs to be
* calculated.
*/
bool theCalculateLargeNME2;
/**
* The last tree-level matrix element squared
*/
double theLastLargeNME2;
/**
* True, if the one-loop/tree-level interference.
* be calculated.
*/
bool theCalculateOneLoopInterference;
/**
* The last one-loop/tree-level interference.
*/
double theLastOneLoopInterference;
/**
* True, if the one-loop/tree-level interference.
* be calculated.
*/
bool theCalculateOneLoopPoles;
/**
* The last one-loop/tree-level interference.
*/
pair<double,double> theLastOneLoopPoles;
/**
* True, if the indexed colour correlated matrix element needs to be
* calculated.
*/
map<pair<int,int>,bool> theCalculateColourCorrelators;
/**
* The colour correlated matrix element.
*/
map<pair<int,int>,double> theColourCorrelators;
/**
* True, if the indexed large-N colour correlated matrix element needs to be
* calculated.
*/
map<pair<int,int>,bool> theCalculateLargeNColourCorrelators;
/**
* The large-N colour correlated matrix element.
*/
map<pair<int,int>,double> theLargeNColourCorrelators;
/**
* True, if the indexed colour/spin correlated matrix element needs to be
* calculated.
*/
map<pair<int,int>,bool> theCalculateColourSpinCorrelators;
/**
* The colour/spin correlated matrix element.
*/
map<pair<int,int>,Complex> theColourSpinCorrelators;
/**
* True, if the indexed spin correlated matrix element needs to be
* calculated.
*/
map<pair<int,int>,bool> theCalculateSpinCorrelators;
/**
* The spin correlated matrix element.
*/
map<pair<int,int>,Complex> theSpinCorrelators;
/**
* The number of light flavours to be considered for this process.
*/
unsigned int theNLight;
/**
* Vector with the PDG ids of the light quark flavours,
* which are contained in the jet particle group.
*/
vector<int> theNLightJetVec;
/**
* Vector with the PDG ids of the heavy quark flavours,
* which are contained in the jet particle group.
*/
vector<int> theNHeavyJetVec;
/**
* Vector with the PDG ids of the light quark flavours,
* which are contained in the proton particle group.
*/
vector<int> theNLightProtonVec;
/**
* The dimensionality of the colour basis for this process.
*/
size_t theColourBasisDim;
/**
* The number of degrees of freedom required by the phase space generator
*/
int theNDimPhasespace;
/**
* The number of degrees of freedom required by the amplitude
*/
int theNDimAmplitude;
/**
* The number of degrees of freedom required by the insertion operators
*/
int theNDimInsertions;
/**
* Additional random numbers required by the amplitude
*/
vector<double> theAmplitudeRandomNumbers;
/**
* Additional random numbers required by the insertion operator
*/
vector<double> theInsertionRandomNumbers;
/**
* The diagram weights indexed by diagram id.
*/
map<int,double> theDiagramWeights;
/**
* If not empty, the entries here serve to limit phasespace
* generation to the corresponding collinear limits, or soft limits
* if both pair entries are equal.
*/
set<pair<size_t,size_t> > theSingularLimits;
/**
* The last matched singular limit.
*/
set<pair<size_t,size_t> >::const_iterator theLastSingularLimit;
/**
* The Herwig++ StandardModel object
*/
Ptr<StandardModel>::tcptr theStandardModel;
/**
* The symmetry factor
*/
double theSymmetryFactor;
/**
* The OLP process id
*/
vector<int> theOLPId;
/**
* Return the olp momentum vector
*/
double* theOLPMomenta;
/**
* True, if olp momenta have been filled
*/
bool filledOLPMomenta;
/**
* A generic process id to communicate with external codes
*/
int theExternalId;
/**
* True if the process has been initialized
*/
bool theInitialized;
/**
* The external momenta
*/
vector<double*> theExternalMomenta;
/**
* True, if external momenta have been filled
*/
bool filledExternalMomenta;
/**
* caching of different colour structures (MadGraph-Interface)
*/
map<vector<int>,vector < complex<double> > > theHelJamp;
/**
* caching of different colour structures (MadGraph-Interface)
*/
map<vector<int>,vector < complex<double> > > theLNHelJamp;
};
}
#endif /* Herwig_MatchboxXCombData_H */
diff --git a/Shower/Base/Evolver.cc b/Shower/Base/Evolver.cc
--- a/Shower/Base/Evolver.cc
+++ b/Shower/Base/Evolver.cc
@@ -1,2647 +1,2672 @@
// -*- C++ -*-
//
// Evolver.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 Evolver class.
//
#include "Evolver.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "ThePEG/Interface/Reference.h"
#include "ThePEG/Interface/RefVector.h"
#include "ThePEG/Interface/Switch.h"
#include "ThePEG/Interface/Parameter.h"
#include "ThePEG/Persistency/PersistentOStream.h"
#include "ThePEG/Persistency/PersistentIStream.h"
#include "Herwig++/Shower/Base/ShowerParticle.h"
#include "ThePEG/Utilities/EnumIO.h"
#include "ShowerKinematics.h"
#include "ThePEG/PDT/EnumParticles.h"
#include "ThePEG/Repository/EventGenerator.h"
#include "ThePEG/Handlers/EventHandler.h"
#include "ThePEG/Utilities/Throw.h"
#include "ShowerTree.h"
#include "ShowerProgenitor.h"
#include "KinematicsReconstructor.h"
#include "PartnerFinder.h"
#include "ThePEG/Handlers/StandardXComb.h"
#include "ThePEG/PDT/DecayMode.h"
#include "Herwig++/Shower/ShowerHandler.h"
#include "ThePEG/Utilities/DescribeClass.h"
#include "ShowerVertex.h"
#include "ThePEG/Repository/CurrentGenerator.h"
#include "Herwig++/MatrixElement/Matchbox/Base/SubtractedME.h"
#include "Herwig++/MatrixElement/Matchbox/MatchboxFactory.h"
#include "ThePEG/Handlers/StandardXComb.h"
using namespace Herwig;
namespace {
/**
* 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;
}
}
DescribeClass<Evolver,Interfaced>
describeEvolver ("Herwig::Evolver","HwShower.so");
bool Evolver::_hardEmissionModeWarn = true;
bool Evolver::_missingTruncWarn = true;
IBPtr Evolver::clone() const {
return new_ptr(*this);
}
IBPtr Evolver::fullclone() const {
return new_ptr(*this);
}
void Evolver::persistentOutput(PersistentOStream & os) const {
os << _model << _splittingGenerator << _maxtry
<< _meCorrMode << _hardVetoMode << _hardVetoRead << _hardVetoReadOption
<< _limitEmissions << _spinOpt << _softOpt
<< ounit(_iptrms,GeV) << _beta << ounit(_gamma,GeV) << ounit(_iptmax,GeV)
<< _vetoes << _trunc_Mode << _hardEmissionMode << _reconOpt
<< isMCatNLOSEvent << isMCatNLOHEvent
<< isPowhegSEvent << isPowhegHEvent
<< theFactorizationScaleFactor << theRenormalizationScaleFactor
<< interaction_<< interactions_.size();
for(unsigned int ix=0;ix<interactions_.size();++ix)
os << oenum(interactions_[ix]);
}
void Evolver::persistentInput(PersistentIStream & is, int) {
unsigned int isize;
is >> _model >> _splittingGenerator >> _maxtry
>> _meCorrMode >> _hardVetoMode >> _hardVetoRead >> _hardVetoReadOption
>> _limitEmissions >> _spinOpt >> _softOpt
>> iunit(_iptrms,GeV) >> _beta >> iunit(_gamma,GeV) >> iunit(_iptmax,GeV)
>> _vetoes >> _trunc_Mode >> _hardEmissionMode >> _reconOpt
>> isMCatNLOSEvent >> isMCatNLOHEvent
>> isPowhegSEvent >> isPowhegHEvent
>> theFactorizationScaleFactor >> theRenormalizationScaleFactor
>> interaction_ >> isize;
interactions_.resize(isize);
for(unsigned int ix=0;ix<interactions_.size();++ix)
is >> ienum(interactions_[ix]);
}
void Evolver::doinit() {
Interfaced::doinit();
// interactions may have been changed through a setup file so we
// clear it up here
interactions_.clear();
if(interaction_==0) {
interactions_.push_back(ShowerInteraction::QCD);
interactions_.push_back(ShowerInteraction::QED);
}
else if(interaction_==1) {
interactions_.push_back(ShowerInteraction::QCD);
}
else if(interaction_==2) {
interactions_.push_back(ShowerInteraction::QED);
interactions_.push_back(ShowerInteraction::QCD);
}
else if(interaction_==3) {
interactions_.push_back(ShowerInteraction::QED);
}
else if(interaction_==4) {
interactions_.push_back(ShowerInteraction::Both);
}
}
void Evolver::Init() {
static ClassDocumentation<Evolver> documentation
("This class is responsible for carrying out the showering,",
"including the kinematics reconstruction, in a given scale range,"
"including the option of the POWHEG approach to simulated next-to-leading order"
" radiation\\cite{Nason:2004rx}.",
"%\\cite{Nason:2004rx}\n"
"\\bibitem{Nason:2004rx}\n"
" P.~Nason,\n"
" ``A new method for combining NLO QCD with shower Monte Carlo algorithms,''\n"
" JHEP {\\bf 0411} (2004) 040\n"
" [arXiv:hep-ph/0409146].\n"
" %%CITATION = JHEPA,0411,040;%%\n");
static Reference<Evolver,SplittingGenerator>
interfaceSplitGen("SplittingGenerator",
"A reference to the SplittingGenerator object",
&Herwig::Evolver::_splittingGenerator,
false, false, true, false);
static Reference<Evolver,ShowerModel> interfaceShowerModel
("ShowerModel",
"The pointer to the object which defines the shower evolution model.",
&Evolver::_model, false, false, true, false, false);
static Parameter<Evolver,unsigned int> interfaceMaxTry
("MaxTry",
"The maximum number of attempts to generate the shower from a"
" particular ShowerTree",
&Evolver::_maxtry, 100, 1, 1000,
false, false, Interface::limited);
static Switch<Evolver, unsigned int> ifaceMECorrMode
("MECorrMode",
"Choice of the ME Correction Mode",
&Evolver::_meCorrMode, 1, false, false);
static SwitchOption off
(ifaceMECorrMode,"No","MECorrections off", 0);
static SwitchOption on
(ifaceMECorrMode,"Yes","hard+soft on", 1);
static SwitchOption hard
(ifaceMECorrMode,"Hard","only hard on", 2);
static SwitchOption soft
(ifaceMECorrMode,"Soft","only soft on", 3);
static Switch<Evolver, unsigned int> ifaceHardVetoMode
("HardVetoMode",
"Choice of the Hard Veto Mode",
&Evolver::_hardVetoMode, 1, false, false);
static SwitchOption HVoff
(ifaceHardVetoMode,"No","hard vetos off", 0);
static SwitchOption HVon
(ifaceHardVetoMode,"Yes","hard vetos on", 1);
static SwitchOption HVIS
(ifaceHardVetoMode,"Initial", "only IS emissions vetoed", 2);
static SwitchOption HVFS
(ifaceHardVetoMode,"Final","only FS emissions vetoed", 3);
static Switch<Evolver, unsigned int> ifaceHardVetoRead
("HardVetoScaleSource",
"If hard veto scale is to be read",
&Evolver::_hardVetoRead, 0, false, false);
static SwitchOption HVRcalc
(ifaceHardVetoRead,"Calculate","Calculate from hard process", 0);
static SwitchOption HVRread
(ifaceHardVetoRead,"Read","Read from XComb->lastScale", 1);
static Switch<Evolver, bool> ifaceHardVetoReadOption
("HardVetoReadOption",
"Apply read-in scale veto to all collisions or just the primary one?",
&Evolver::_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<Evolver, Energy> ifaceiptrms
("IntrinsicPtGaussian",
"RMS of intrinsic pT of Gaussian distribution:\n"
"2*(1-Beta)*exp(-sqr(intrinsicpT/RMS))/sqr(RMS)",
&Evolver::_iptrms, GeV, ZERO, ZERO, 1000000.0*GeV,
false, false, Interface::limited);
static Parameter<Evolver, double> ifacebeta
("IntrinsicPtBeta",
"Proportion of inverse quadratic distribution in generating intrinsic pT.\n"
"(1-Beta) is the proportion of Gaussian distribution",
&Evolver::_beta, 0, 0, 1,
false, false, Interface::limited);
static Parameter<Evolver, Energy> ifacegamma
("IntrinsicPtGamma",
"Parameter for inverse quadratic:\n"
"2*Beta*Gamma/(sqr(Gamma)+sqr(intrinsicpT))",
&Evolver::_gamma,GeV, ZERO, ZERO, 100000.0*GeV,
false, false, Interface::limited);
static Parameter<Evolver, Energy> ifaceiptmax
("IntrinsicPtIptmax",
"Upper bound on intrinsic pT for inverse quadratic",
&Evolver::_iptmax,GeV, ZERO, ZERO, 100000.0*GeV,
false, false, Interface::limited);
static RefVector<Evolver,ShowerVeto> ifaceVetoes
("Vetoes",
"The vetoes to be checked during showering",
&Evolver::_vetoes, -1,
false,false,true,true,false);
static Switch<Evolver,unsigned int> interfaceLimitEmissions
("LimitEmissions",
"Limit the number and type of emissions for testing",
&Evolver::_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<Evolver,bool> interfaceTruncMode
("TruncatedShower", "Include the truncated shower?",
&Evolver::_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<Evolver,unsigned int> interfaceHardEmissionMode
("HardEmissionMode",
"Whether to use ME corrections or POWHEG for the hardest emission",
&Evolver::_hardEmissionMode, 0, false, false);
static SwitchOption interfaceHardEmissionModeMECorrection
(interfaceHardEmissionMode,
"MECorrection",
"Old fashioned ME correction",
0);
static SwitchOption interfaceHardEmissionModePOWHEG
(interfaceHardEmissionMode,
"POWHEG",
"Powheg style hard emission using internal matrix elements",
1);
static SwitchOption interfaceHardEmissionModeMatchboxPOWHEG
(interfaceHardEmissionMode,
"MatchboxPOWHEG",
"Powheg style emission for the hard process using Matchbox",
2);
static SwitchOption interfaceHardEmissionModeFullPOWHEG
(interfaceHardEmissionMode,
"FullPOWHEG",
"Powheg style emission for the hard process using Matchbox "
"and decays using internal matrix elements",
3);
static Switch<Evolver,unsigned int > interfaceInteractions
("Interactions",
"The interactions to be used in the shower",
&Evolver::interaction_, 1, false, false);
static SwitchOption interfaceInteractionsQCDFirst
(interfaceInteractions,
"QCDFirst",
"QCD first then QED",
0);
static SwitchOption interfaceInteractionsQCDOnly
(interfaceInteractions,
"QCDOnly",
"Only QCD",
1);
static SwitchOption interfaceInteractionsQEDFirst
(interfaceInteractions,
"QEDFirst",
"QED first then QCD",
2);
static SwitchOption interfaceInteractionsQEDOnly
(interfaceInteractions,
"QEDOnly",
"Only QED",
3);
static SwitchOption interfaceInteractionsBothAtOnce
(interfaceInteractions,
"BothAtOnce",
"Generate both at the same time",
4);
static Switch<Evolver,unsigned int> interfaceReconstructionOption
("ReconstructionOption",
"Treatment of the reconstruction of the transverse momentum of "
"a branching from the evolution scale.",
&Evolver::_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",
1);
static Switch<Evolver,unsigned int> interfaceSpinCorrelations
("SpinCorrelations",
"Treatment of spin correlations in the parton shower",
&Evolver::_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<Evolver,unsigned int> interfaceSoftCorrelations
("SoftCorrelations",
"Option for the treatment of soft correlations in the parton shower",
&Evolver::_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);
}
void Evolver::generateIntrinsicpT(vector<ShowerProgenitorPtr> particlesToShower) {
_intrinsic.clear();
if ( !ipTon() || !isISRadiationON() ) return;
// don't do anything for the moment for secondary scatters
if( !ShowerHandler::currentHandler()->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 Evolver::setupMaximumScales(const vector<ShowerProgenitorPtr> & p,
XCPtr xcomb) {
// let POWHEG events radiate freely
if(_hardEmissionMode>0&&hardTree()) {
vector<ShowerProgenitorPtr>::const_iterator ckt = p.begin();
for (; ckt != p.end(); ckt++) (*ckt)->maxHardPt(Constants::MaxEnergy);
return;
}
// return if no vetos
if (!hardVetoOn()) 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 (!hardVetoXComb()||
(hardVetoReadOption()&&
!ShowerHandler::currentHandler()->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(hardVetoXComb()&&hardVetoReadOption()&&
!ShowerHandler::currentHandler()->firstInteraction()) {
ptmax=min(ptmax,sqrt(xcomb->lastCentralScale()));
}
}
// 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->lastCentralScale() );
}
else {
ptmax = currentTree()->incomingLines().begin()->first
->progenitor()->momentum().mass();
}
}
ptmax *= ShowerHandler::currentHandler()->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 Evolver::showerHardProcess(ShowerTreePtr hard, XCPtr xcomb) {
isMCatNLOSEvent = false;
isMCatNLOHEvent = false;
isPowhegSEvent = false;
isPowhegHEvent = false;
Ptr<SubtractedME>::tptr subme;
Ptr<MatchboxMEBase>::tptr me;
Ptr<SubtractionDipole>::tptr dipme;
Ptr<StandardXComb>::ptr sxc = dynamic_ptr_cast<Ptr<StandardXComb>::ptr>(xcomb);
if ( sxc ) {
subme = dynamic_ptr_cast<Ptr<SubtractedME>::tptr>(sxc->matrixElement());
me = dynamic_ptr_cast<Ptr<MatchboxMEBase>::tptr>(sxc->matrixElement());
dipme = dynamic_ptr_cast<Ptr<SubtractionDipole>::tptr>(sxc->matrixElement());
}
if ( subme ) {
if ( subme->showerApproximation() ) {
theShowerApproximation = subme->showerApproximation();
// separate MCatNLO and POWHEG-type corrections
if ( !subme->showerApproximation()->needsSplittingGenerator() ) {
if ( subme->realShowerSubtraction() )
isMCatNLOHEvent = true;
else if ( subme->virtualShowerSubtraction() )
isMCatNLOSEvent = true;
}
else {
if ( subme->realShowerSubtraction() )
isPowhegHEvent = true;
else if ( subme->virtualShowerSubtraction() || subme->loopSimSubtraction() )
isPowhegSEvent = true;
}
}
} else if ( me ) {
if ( me->factory()->showerApproximation() ) {
theShowerApproximation = me->factory()->showerApproximation();
if ( !me->factory()->showerApproximation()->needsSplittingGenerator() )
isMCatNLOSEvent = true;
else
isPowhegSEvent = true;
}
}
string error = "Inconsistent hard emission set-up in Evolver::showerHardProcess(). ";
if ( ( isMCatNLOSEvent || isMCatNLOHEvent ) ){
if (_hardEmissionMode > 1)
throw Exception() << error
<< "Cannot generate POWHEG matching with MC@NLO shower "
<< "approximation. Add 'set Evolver:HardEmissionMode 0' to input file."
<< Exception::runerror;
if ( ShowerHandler::currentHandler()->canHandleMatchboxTrunc())
throw Exception() << error
<< "Cannot use truncated qtilde shower with MC@NLO shower "
<< "approximation. Set LHCGenerator:EventHandler"
<< ":CascadeHandler to '/Herwig/Shower/ShowerHandler' or "
<< "'/Herwig/DipoleShower/DipoleShowerHandler'."
<< Exception::runerror;
}
else if ( ((isPowhegSEvent || isPowhegHEvent) || dipme) &&
_hardEmissionMode < 2){
if ( ShowerHandler::currentHandler()->canHandleMatchboxTrunc())
throw Exception() << error
<< "Unmatched events requested for POWHEG shower "
<< "approximation. Set Evolver:HardEmissionMode to "
<< "'MatchboxPOWHEG' or 'FullPOWHEG'."
<< Exception::runerror;
else if (_hardEmissionModeWarn){
_hardEmissionModeWarn = false;
_hardEmissionMode+=2;
throw Exception() << error
<< "Unmatched events requested for POWHEG shower "
<< "approximation. Changing Evolver:HardEmissionMode from "
<< _hardEmissionMode-2 << " to " << _hardEmissionMode
<< Exception::warning;
}
}
if ( isPowhegSEvent || isPowhegHEvent) {
if (theShowerApproximation->needsTruncatedShower() &&
!ShowerHandler::currentHandler()->canHandleMatchboxTrunc() )
throw Exception() << error
<< "Current shower handler cannot generate truncated shower. "
<< "Set Generator:EventHandler:CascadeHandler to "
<< "'/Herwig/Shower/PowhegShowerHandler'."
<< Exception::runerror;
}
else if ( dipme && _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 &&
ShowerHandler::currentHandler()->firstInteraction())
throw Exception() << error
<< "POWHEG matching requested for LO events. Include "
<< "'set Factory:ShowerApproximation MEMatching' in input file."
<< Exception::runerror;
_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());
// number of attempts if more than one interaction switched on
unsigned int interactionTry=0;
do {
try {
// generate the showering
doShowering(true,xcomb);
// if no vetos return
return;
}
catch (InteractionVeto) {
currentTree()->clear();
++interactionTry;
}
}
while(interactionTry<=5);
throw Exception() << "Too many tries for shower in "
<< "Evolver::showerHardProcess()"
<< Exception::eventerror;
}
void Evolver::hardMatrixElementCorrection(bool hard) {
// set the initial enhancement factors for the soft correction
_initialenhance = 1.;
_finalenhance = 1.;
// if hard matrix element switched off return
if(!MECOn()) return;
// see if we can get the correction from the matrix element
// or decayer
if(hard) {
if(_hardme&&_hardme->hasMECorrection()) {
_hardme->initializeMECorrection(_currenttree,
_initialenhance,_finalenhance);
if(hardMEC())
_hardme->applyHardMatrixElementCorrection(_currenttree);
}
}
else {
if(_decayme&&_decayme->hasMECorrection()) {
_decayme->initializeMECorrection(_currenttree,
_initialenhance,_finalenhance);
if(hardMEC())
_decayme->applyHardMatrixElementCorrection(_currenttree);
}
}
}
bool Evolver::timeLikeShower(tShowerParticlePtr particle,
ShowerInteraction::Type type,
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;
}
ShowerParticleVector theChildren;
int ntry=0;
do {
++ntry;
// generate the emission
Branching fb;
while (true) {
fb=_splittingGenerator->chooseForwardBranching(*particle,_finalenhance,type);
// no emission return
if(!fb.kinematics) {
if(particle->spinInfo()) particle->spinInfo()->develop();
return false;
}
// if emission OK break
if(!timeLikeVetoed(fb,particle)) break;
// otherwise reset scale and continue - SO IS involved in veto algorithm
particle->vetoEmission(fb.type,fb.kinematics->scale());
if(particle->spinInfo()) particle->spinInfo()->decayVertex(VertexPtr());
}
// has emitted
// Assign the shower kinematics to the emitting particle.
particle->showerKinematics(fb.kinematics);
if(fb.kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(fb.kinematics->pT());
// Assign the splitting function to the emitting particle.
// For the time being we are considering only 1->2 branching
// 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
tcPDPtr pdata[2];
for(unsigned int ix=0;ix<2;++ix) pdata[ix]=getParticleData(fb.ids[ix+1]);
if(particle->id()!=fb.ids[0]) {
for(unsigned int ix=0;ix<2;++ix) {
tPDPtr cc(pdata[ix]->CC());
if(cc) pdata[ix]=cc;
}
}
- theChildren.push_back(new_ptr(ShowerParticle(pdata[0],true)));
- theChildren.push_back(new_ptr(ShowerParticle(pdata[1],true)));
+ for(unsigned int ix=0;ix<2;++ix) {
+ theChildren.push_back(new_ptr(ShowerParticle(pdata[ix],true)));
+ if(theChildren[ix]->id()==_progenitor->id()&&!pdata[ix]->stable())
+ theChildren[ix]->set5Momentum(Lorentz5Momentum(_progenitor->progenitor()->mass()));
+ else
+ theChildren[ix]->set5Momentum(Lorentz5Momentum(pdata[ix]->mass()));
+ }
// update the children
particle->showerKinematics()->
updateChildren(particle, theChildren,fb.type);
// update number of emissions
++_nfs;
if(_limitEmissions!=0) {
if(theChildren[0]->spinInfo()) theChildren[0]->spinInfo()->develop();
if(theChildren[1]->spinInfo()) theChildren[1]->spinInfo()->develop();
if(particle->spinInfo()) particle->spinInfo()->develop();
return true;
}
// shower the first particle
timeLikeShower(theChildren[0],type,false);
if(theChildren[0]->spinInfo()) theChildren[0]->spinInfo()->develop();
// shower the second particle
timeLikeShower(theChildren[1],type,false);
if(theChildren[1]->spinInfo()) theChildren[1]->spinInfo()->develop();
// that's if for old approach
if(_reconOpt==0) break;
// branching has happened
particle->showerKinematics()->
updateParent(particle, theChildren,fb.type);
// clean up the vetoed emission
if(particle->virtualMass()==ZERO) {
particle->showerKinematics(ShoKinPtr());
for(unsigned int ix=0;ix<theChildren.size();++ix)
particle->abandonChild(theChildren[ix]);
theChildren.clear();
}
}
while(particle->virtualMass()==ZERO&&ntry<50);
if(first)
particle->showerKinematics()->resetChildren(particle,theChildren);
if(particle->spinInfo()) particle->spinInfo()->develop();
return true;
}
bool
Evolver::spaceLikeShower(tShowerParticlePtr particle, PPtr beam,
ShowerInteraction::Type 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(ShowerHandler::currentHandler()->firstPDF().particle() == _beam)
pdf = ShowerHandler::currentHandler()->firstPDF().pdf();
if(ShowerHandler::currentHandler()->secondPDF().particle() == _beam)
pdf = ShowerHandler::currentHandler()->secondPDF().pdf();
Energy freeze = ShowerHandler::currentHandler()->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]={getParticleData(bb.ids[0]),
getParticleData(bb.ids[2])};
if(particle->id()!=bb.ids[1]) {
if(part[0]->CC()) part[0]=part[0]->CC();
if(part[1]->CC()) part[1]=part[1]->CC();
}
// 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);
if(_limitEmissions!=0) {
if(particle->spinInfo()) particle->spinInfo()->develop();
return true;
}
// perform the shower of the final-state particle
timeLikeShower(otherChild,type,true);
if(theChildren[1]->spinInfo()) theChildren[1]->spinInfo()->develop();
// return the emitted
if(particle->spinInfo()) particle->spinInfo()->develop();
return true;
}
void Evolver::showerDecay(ShowerTreePtr decay) {
_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()
+ "->";
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
it=decay->outgoingLines().begin();it!=decay->outgoingLines().end();++it) {
if(it!=decay->outgoingLines().begin()) tag += ",";
tag += it->first->original()->dataPtr()->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());
unsigned int interactionTry=0;
do {
try {
// 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();
}
// and then return
return;
}
catch (InteractionVeto) {
currentTree()->clear();
++interactionTry;
}
}
while(interactionTry<=5);
throw Exception() << "Too many tries for QED shower in Evolver::showerDecay()"
<< Exception::eventerror;
}
bool Evolver::spaceLikeDecayShower(tShowerParticlePtr particle,
const ShowerParticle::EvolutionScales & maxScales,
Energy minmass,ShowerInteraction::Type type) {
Branching fb;
while (true) {
fb=_splittingGenerator->chooseDecayBranching(*particle,maxScales,minmass,
_initialenhance,type);
// return if no radiation
if(!fb.kinematics) return false;
// if not vetoed break
if(!spaceLikeDecayVetoed(fb,particle)) break;
// otherwise reset scale and continue
particle->vetoEmission(fb.type,fb.kinematics->scale());
}
// has emitted
// Assign the shower kinematics to the emitting particle.
particle->showerKinematics(fb.kinematics);
if(fb.kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(fb.kinematics->pT());
// For the time being we are considering only 1->2 branching
// 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
tcPDPtr pdata[2];
for(unsigned int ix=0;ix<2;++ix) pdata[ix]=getParticleData(fb.ids[ix+1]);
if(particle->id()!=fb.ids[0]) {
for(unsigned int ix=0;ix<2;++ix) {
tPDPtr cc(pdata[ix]->CC());
if(cc) pdata[ix]=cc;
}
}
ShowerParticleVector theChildren;
- theChildren.push_back(new_ptr(ShowerParticle(pdata[0],true)));
- theChildren.push_back(new_ptr(ShowerParticle(pdata[1],true)));
+ for(unsigned int ix=0;ix<2;++ix) {
+ theChildren.push_back(new_ptr(ShowerParticle(pdata[ix],true)));
+ if(theChildren[ix]->id()==_progenitor->id()&&!pdata[ix]->stable())
+ theChildren[ix]->set5Momentum(Lorentz5Momentum(_progenitor->progenitor()->mass()));
+ else
+ theChildren[ix]->set5Momentum(Lorentz5Momentum(pdata[ix]->mass()));
+ }
// some code moved to updateChildren
particle->showerKinematics()->
updateChildren(particle, theChildren, fb.type);
// 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,theChildren[0]);
_currenttree->addInitialStateBranching(particle,theChildren[0],theChildren[1]);
// shower the first particle
spaceLikeDecayShower(theChildren[0],maxScales,minmass,type);
// shower the second particle
timeLikeShower(theChildren[1],type,true);
// branching has happened
return true;
}
vector<ShowerProgenitorPtr> Evolver::setupShower(bool hard) {
// generate POWHEG hard emission if needed
if(_hardEmissionMode>0) hardestEmission(hard);
ShowerInteraction::Type inter = interactions_[0];
if(_hardtree&&inter!=ShowerInteraction::Both) {
inter = _hardtree->interaction();
}
// set the initial colour partners
setEvolutionPartners(hard,inter,false);
// generate hard me if needed
if(_hardEmissionMode==0) hardMatrixElementCorrection(hard);
// get the particles to be showered
vector<ShowerProgenitorPtr> particlesToShower =
currentTree()->extractProgenitors();
// remake the colour partners if needed
if(_hardEmissionMode==0 && _currenttree->hardMatrixElementCorrection()) {
setEvolutionPartners(hard,interactions_[0],true);
_currenttree->resetShowerProducts();
}
// return the answer
return particlesToShower;
}
void Evolver::setEvolutionPartners(bool hard,ShowerInteraction::Type type,
bool clear) {
// match the particles in the ShowerTree and hardTree
if(hardTree() && !hardTree()->connect(currentTree()))
throw Exception() << "Can't match trees in "
<< "Evolver::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) {
tHardBranchingPtr partner =
hardTree()->particles()[particles[ix]]->colourPartner();
if(!partner) continue;
for(map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
it=hardTree()->particles().begin();
it!=hardTree()->particles().end();++it) {
if(it->second==partner) particles[ix]->partner(it->first);
}
if(!particles[ix]->partner())
throw Exception() << "Can't match partners in "
<< "Evolver::setEvolutionPartners()"
<< Exception::eventerror;
}
}
// Set the initial evolution scales
showerModel()->partnerFinder()->
setInitialEvolutionScales(particles,!hard,type,!_hardtree);
}
void Evolver::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 Evolver::startTimeLikeShower(ShowerInteraction::Type type) {
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);
if(output) updateHistory(progenitor()->progenitor());
return output;
}
}
bool output = hardOnly() ? false :
timeLikeShower(progenitor()->progenitor() ,type,true) ;
if(output) updateHistory(progenitor()->progenitor());
return output;
}
bool Evolver::startSpaceLikeShower(PPtr parent, ShowerInteraction::Type type) {
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 );
}
}
return hardOnly() ? false :
spaceLikeShower(progenitor()->progenitor(),parent,type);
}
bool Evolver::
startSpaceLikeDecayShower(const ShowerParticle::EvolutionScales & maxScales,
Energy minimumMass,ShowerInteraction::Type type) {
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);
}
}
return hardOnly() ? false :
spaceLikeDecayShower(progenitor()->progenitor(),maxScales,minimumMass,type);
}
bool Evolver::timeLikeVetoed(const Branching & fb,
ShowerParticlePtr particle) {
// work out type of interaction
ShowerInteraction::Type type = fb.type==ShowerPartnerType::QED ?
ShowerInteraction::QED : ShowerInteraction::QCD;
// check whether emission was harder than largest pt of hard subprocess
if ( hardVetoFS() && 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;
}
// check for MC@NLO profile scale veto
if ( isMCatNLOSEvent && !_progenitor->profileVetoed() ) {
assert(theShowerApproximation);
double weight = theShowerApproximation->hardScaleProfile(_progenitor->maxHardPt(),fb.kinematics->pT());
if ( UseRandom::rnd() > weight )
return true;
_progenitor->didProfileVeto();
}
return false;
}
bool Evolver::spaceLikeVetoed(const Branching & bb,
ShowerParticlePtr particle) {
// work out type of interaction
ShowerInteraction::Type type = bb.type==ShowerPartnerType::QED ?
ShowerInteraction::QED : ShowerInteraction::QCD;
// check whether emission was harder than largest pt of hard subprocess
if (hardVetoIS() && 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;
}
// check for MC@NLO profile scale veto
if ( isMCatNLOSEvent && !_progenitor->profileVetoed() ) {
assert(theShowerApproximation);
double weight = theShowerApproximation->hardScaleProfile(_progenitor->maxHardPt(),bb.kinematics->pT());
if ( UseRandom::rnd() > weight )
return true;
_progenitor->didProfileVeto();
}
return false;
}
bool Evolver::spaceLikeDecayVetoed( const Branching & fb,
ShowerParticlePtr particle) {
// work out type of interaction
ShowerInteraction::Type type = fb.type==ShowerPartnerType::QED ?
ShowerInteraction::QED : ShowerInteraction::QCD;
// 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 Evolver::hardestEmission(bool hard) {
HardTreePtr ISRTree;
if( ( _hardme && _hardme->hasPOWHEGCorrection()!=0 && _hardEmissionMode< 2) ||
( _decayme && _decayme->hasPOWHEGCorrection()!=0 && _hardEmissionMode!=2) ) {
if(_hardme) {
assert(hard);
if(interaction_==4) {
vector<ShowerInteraction::Type> inter(2);
inter[0] = ShowerInteraction::QCD;
inter[1] = ShowerInteraction::QED;
_hardtree = _hardme->generateHardest( currentTree(),inter );
}
else {
_hardtree = _hardme->generateHardest( currentTree(),interactions_ );
}
}
else {
assert(!hard);
_hardtree = _decayme->generateHardest( currentTree() );
}
// store initial state POWHEG radiation
if(_hardtree && _hardme && _hardme->hasPOWHEGCorrection()==1)
ISRTree=_hardtree;
}
else if (_hardEmissionMode>1 && hard) {
// Get minimum pT cutoff used in shower approximation
Energy maxpt = 1.*GeV;
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+=1;
}
for( map< ShowerProgenitorPtr, ShowerParticlePtr >::iterator it
= currentTree()->incomingLines().begin();
it != currentTree()->incomingLines().end(); ++it ) {
if( ! it->second->coloured() ) colouredIn+=1;
}
if ( theShowerApproximation ){
if ( theShowerApproximation->ffPtCut() == theShowerApproximation->fiPtCut() &&
theShowerApproximation->ffPtCut() == theShowerApproximation->iiPtCut() )
maxpt = theShowerApproximation->ffPtCut();
else if ( colouredIn == 2 && colouredOut == 0 )
maxpt = theShowerApproximation->iiPtCut();
else if ( colouredIn == 0 && colouredOut > 1 )
maxpt = theShowerApproximation->ffPtCut();
else if ( colouredIn == 2 && colouredOut == 1 )
maxpt = min(theShowerApproximation->iiPtCut(), theShowerApproximation->fiPtCut());
else if ( colouredIn == 1 && colouredOut > 1 )
maxpt = min(theShowerApproximation->ffPtCut(), theShowerApproximation->fiPtCut());
else
maxpt = min(min(theShowerApproximation->iiPtCut(), theShowerApproximation->fiPtCut()),
theShowerApproximation->ffPtCut());
}
// Generate hardtree from born and real emission subprocesses
_hardtree = ShowerHandler::currentHandler()->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();
}
}
}
}
// Set maxpt to pT of emission when showering POWHEG real-emission subprocesses
if (!isPowhegSEvent && !isPowhegHEvent){
vector<int> outGluon;
vector<int> outQuark;
map< ShowerProgenitorPtr, tShowerParticlePtr >::iterator it;
for( it = currentTree()->outgoingLines().begin();
it != currentTree()->outgoingLines().end(); ++it ) {
if ( abs(it->second->id())< 6) outQuark.push_back(it->second->id());
if ( it->second->id()==21 ) outGluon.push_back(it->second->id());
}
if (outGluon.size() + outQuark.size() == 1){
for( it = currentTree()->outgoingLines().begin();
it != currentTree()->outgoingLines().end(); ++it ) {
if ( abs(it->second->id())< 6 || it->second->id()==21 )
maxpt = it->second->momentum().perp();
}
}
else if (outGluon.size() + outQuark.size() > 1){
// assume qqbar pair from a Z/gamma
if (outGluon.size()==1 && outQuark.size() == 2 && outQuark[0]==-outQuark[1]){
for( it = currentTree()->outgoingLines().begin();
it != currentTree()->outgoingLines().end(); ++it ) {
if ( it->second->id()==21 )
maxpt = it->second->momentum().perp();
}
}
// otherwise take the lowest pT avoiding born DY events
else {
maxpt = generator()->maximumCMEnergy();
for( it = currentTree()->outgoingLines().begin();
it != currentTree()->outgoingLines().end(); ++it ) {
if ( abs(it->second->id())< 6 || it->second->id()==21 )
maxpt = min(maxpt,it->second->momentum().perp());
}
}
}
}
// set maximum pT for subsequent emissions from S events
if ( isPowhegSEvent || (!isPowhegSEvent && !isPowhegHEvent)){
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 = ShowerHandler::currentHandler()->generateCKKW(currentTree());
// if hard me doesn't have a FSR powheg
// correction use decay powheg correction
if (_hardme && _hardme->hasPOWHEGCorrection()<2) {
// 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){
if(_hardtree) connectTrees(currentTree(),_hardtree,hard);
return;
}
map<ShowerProgenitorPtr, tShowerParticlePtr > out = currentTree()->outgoingLines();
// ignore cases where outgoing particles are not coloured
if (out.size()!=2 ||
out. begin()->second->dataPtr()->iColour()==PDT::Colour0 ||
out.rbegin()->second->dataPtr()->iColour()==PDT::Colour0) {
if(_hardtree) connectTrees(currentTree(),_hardtree,hard);
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){
if(_hardtree) connectTrees(currentTree(),_hardtree,hard);
return;
}
// generate the hardest emission
ShowerDecayMap decay;
PPtr in = new_ptr(*inter[0]);
ShowerTreePtr decayTree = new_ptr(ShowerTree(in, decay));
HardTreePtr FSRTree = decayer->generateHardest(decayTree);
if (!FSRTree) {
if(_hardtree) connectTrees(currentTree(),_hardtree,hard);
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;
}
}
if(_hardtree){
connectTrees(currentTree(),_hardtree,hard);
}
}
bool Evolver::truncatedTimeLikeShower(tShowerParticlePtr particle,
HardBranchingPtr branch,
ShowerInteraction::Type type) {
int ntry=0;
do {
++ntry;
Branching fb;
unsigned int iout=0;
tcPDPtr pdata[2];
while (true) {
// no truncated shower break
if(!isTruncatedShowerON()||hardOnly()) break;
// generate emission
fb=splittingGenerator()->chooseForwardBranching(*particle,1.,type);
// no emission break
if(!fb.kinematics) break;
// check haven't evolved too far
if(fb.kinematics->scale() < branch->scale()) {
fb=Branching();
break;
}
// get the particle data objects
for(unsigned int ix=0;ix<2;++ix) pdata[ix]=getParticleData(fb.ids[ix+1]);
if(particle->id()!=fb.ids[0]) {
for(unsigned int ix=0;ix<2;++ix) {
tPDPtr cc(pdata[ix]->CC());
if(cc) pdata[ix]=cc;
}
}
// find the truncated line
iout=0;
if(pdata[0]->id()!=pdata[1]->id()) {
if(pdata[0]->id()==particle->id()) iout=1;
else if (pdata[1]->id()==particle->id()) iout=2;
}
else if(pdata[0]->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 = fb.type==ShowerPartnerType::QED ?
ShowerInteraction::QED : ShowerInteraction::QCD;
// 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;
}
// should do base class vetos as well
if(timeLikeVetoed(fb,particle)) {
particle->vetoEmission(fb.type,fb.kinematics->scale());
continue;
}
break;
}
// if no branching force trunctaed emission
if(!fb.kinematics) {
// construct the kinematics for the hard emission
ShoKinPtr showerKin=
branch->sudakov()->createFinalStateBranching(branch->scale(),
branch->children()[0]->z(),
branch->phi(),
branch->children()[0]->pT());
showerKin->initialize( *particle,PPtr() );
IdList idlist(3);
idlist[0] = particle->id();
idlist[1] = branch->children()[0]->branchingParticle()->id();
idlist[2] = branch->children()[1]->branchingParticle()->id();
fb = Branching( showerKin, idlist, branch->sudakov(),branch->type() );
// Assign the shower kinematics to the emitting particle.
particle->showerKinematics( fb.kinematics );
if(fb.kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(fb.kinematics->pT());
// Assign the splitting function to the emitting particle.
// For the time being we are considering only 1->2 branching
// 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 theChildren;
- theChildren.push_back(new_ptr(ShowerParticle(branch->children()[0]->
- branchingParticle()->dataPtr(),true)));
- theChildren.push_back(new_ptr(ShowerParticle(branch->children()[1]->
- branchingParticle()->dataPtr(),true)));
+ for(unsigned int ix=0;ix<2;++ix) {
+ theChildren.push_back(new_ptr(ShowerParticle(branch->children()[ix]->
+ branchingParticle()->dataPtr(),true)));
+ if(theChildren[ix]->id()==_progenitor->id()&&!theChildren[ix]->dataPtr()->stable())
+ theChildren[ix]->set5Momentum(Lorentz5Momentum(_progenitor->progenitor()->mass()));
+ else
+ theChildren[ix]->set5Momentum(Lorentz5Momentum(theChildren[ix]->dataPtr()->mass()));
+ }
particle->showerKinematics()->
updateChildren(particle, theChildren,fb.type);
// shower the first particle
if( branch->children()[0]->children().empty() ) {
if( ! hardOnly() )
timeLikeShower(theChildren[0],type,false);
}
else {
truncatedTimeLikeShower( theChildren[0],branch->children()[0],type);
}
// shower the second particle
if( branch->children()[1]->children().empty() ) {
if( ! hardOnly() )
timeLikeShower( theChildren[1] , type,false);
}
else {
truncatedTimeLikeShower( theChildren[1],branch->children()[1] ,type);
}
// that's if for old approach
if(_reconOpt==0) return true;
// branching has happened
particle->showerKinematics()->updateParent(particle, theChildren,fb.type);
// clean up the vetoed emission
if(particle->virtualMass()==ZERO) {
particle->showerKinematics(ShoKinPtr());
for(unsigned int ix=0;ix<theChildren.size();++ix)
particle->abandonChild(theChildren[ix]);
theChildren.clear();
}
else return true;
}
// has emitted
// Assign the shower kinematics to the emitting particle.
particle->showerKinematics(fb.kinematics);
if(fb.kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(fb.kinematics->pT());
// Assign the splitting function to the emitting particle.
// For the time being we are considering only 1->2 branching
// 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 theChildren;
- theChildren.push_back( new_ptr( ShowerParticle( pdata[0], true ) ) );
- theChildren.push_back( new_ptr( ShowerParticle( pdata[1], true ) ) );
+ for(unsigned int ix=0;ix<2;++ix) {
+ theChildren.push_back( new_ptr( ShowerParticle( pdata[ix], true ) ) );
+ if(theChildren[ix]->id()==_progenitor->id()&&!pdata[ix]->stable())
+ theChildren[ix]->set5Momentum(Lorentz5Momentum(_progenitor->progenitor()->mass()));
+ else
+ theChildren[ix]->set5Momentum(Lorentz5Momentum(pdata[ix]->mass()));
+ }
particle->showerKinematics()->
updateChildren( particle, theChildren , fb.type);
// shower the first particle
if( iout == 1 ) truncatedTimeLikeShower( theChildren[0], branch , type );
else timeLikeShower( theChildren[0] , type,false);
// shower the second particle
if( iout == 2 ) truncatedTimeLikeShower( theChildren[1], branch , type );
else timeLikeShower( theChildren[1] , type,false);
// that's if for old approach
if(_reconOpt==0) return true;
// branching has happened
particle->showerKinematics()->updateParent(particle, theChildren,fb.type);
// clean up the vetoed emission
if(particle->virtualMass()==ZERO) {
particle->showerKinematics(ShoKinPtr());
for(unsigned int ix=0;ix<theChildren.size();++ix)
particle->abandonChild(theChildren[ix]);
theChildren.clear();
}
else return true;
}
while(ntry<50);
return false;
}
bool Evolver::truncatedSpaceLikeShower(tShowerParticlePtr particle, PPtr beam,
HardBranchingPtr branch,
ShowerInteraction::Type type) {
tcPDFPtr pdf;
if(ShowerHandler::currentHandler()->firstPDF().particle() == beamParticle())
pdf = ShowerHandler::currentHandler()->firstPDF().pdf();
if(ShowerHandler::currentHandler()->secondPDF().particle() == beamParticle())
pdf = ShowerHandler::currentHandler()->secondPDF().pdf();
Energy freeze = ShowerHandler::currentHandler()->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] = getParticleData( bb.ids[0] );
part[1] = getParticleData( bb.ids[2] );
//is emitter anti-particle
if( particle->id() != bb.ids[1]) {
if( part[0]->CC() ) part[0] = part[0]->CC();
if( part[1]->CC() ) part[1] = part[1]->CC();
}
double zsplit = bb.kinematics->z();
// apply the vetos for the truncated shower
// if doesn't carry most of momentum
ShowerInteraction::Type type2 = bb.type==ShowerPartnerType::QED ?
ShowerInteraction::QED : ShowerInteraction::QCD;
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() );
kinematics->initialize( *particle, beam );
// 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);
if(hardOnly()) return true;
// perform the shower of the final-state particle
if( timelike->children().empty() ) {
timeLikeShower( otherChild , type,true);
}
else {
truncatedTimeLikeShower( otherChild, timelike , type);
}
// 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);
// perform the shower of the final-state particle
timeLikeShower( otherChild , type,true);
// return the emitted
return true;
}
bool Evolver::
truncatedSpaceLikeDecayShower(tShowerParticlePtr particle,
const ShowerParticle::EvolutionScales & maxScales,
Energy minmass, HardBranchingPtr branch,
ShowerInteraction::Type type) {
Branching fb;
unsigned int iout=0;
tcPDPtr pdata[2];
while (true) {
// no truncated shower break
if(!isTruncatedShowerON()||hardOnly()) break;
fb=splittingGenerator()->chooseDecayBranching(*particle,maxScales,minmass,1.,type);
// return if no radiation
if(!fb.kinematics) break;
// check haven't evolved too far
if(fb.kinematics->scale() < branch->scale()) {
fb=Branching();
break;
}
// get the particle data objects
for(unsigned int ix=0;ix<2;++ix) pdata[ix]=getParticleData(fb.ids[ix+1]);
if(particle->id()!=fb.ids[0]) {
for(unsigned int ix=0;ix<2;++ix) {
tPDPtr cc(pdata[ix]->CC());
if(cc) pdata[ix]=cc;
}
}
// find the truncated line
iout=0;
if(pdata[0]->id()!=pdata[1]->id()) {
if(pdata[0]->id()==particle->id()) iout=1;
else if (pdata[1]->id()==particle->id()) iout=2;
}
else if(pdata[0]->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 = fb.type==ShowerPartnerType::QED ?
ShowerInteraction::QED : ShowerInteraction::QCD;
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;
}
// should do base class vetos as well
// if not vetoed break
if(!spaceLikeDecayVetoed(fb,particle)) break;
// otherwise reset scale and continue
particle->vetoEmission(fb.type,fb.kinematics->scale());
}
// this may not be currently used but in principle could be
// and should be included
if (!fb.kinematics) {
// construct the kinematics for the hard emission
ShoKinPtr showerKin=
branch->sudakov()->createDecayBranching(branch->scale(),
branch->children()[0]->z(),
branch->phi(),
branch->children()[0]->pT());
showerKin->initialize( *particle,PPtr() );
IdList idlist(3);
idlist[0] = particle->id();
idlist[1] = branch->children()[0]->branchingParticle()->id();
idlist[2] = branch->children()[1]->branchingParticle()->id();
// create the branching
fb = Branching( showerKin, idlist, branch->sudakov(),ShowerPartnerType::QCDColourLine );
// Assign the shower kinematics to the emitting particle.
particle->showerKinematics( fb.kinematics );
if(fb.kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(fb.kinematics->pT());
// Assign the splitting function to the emitting particle.
// For the time being we are considering only 1->2 branching
// 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 theChildren;
theChildren.push_back(new_ptr(ShowerParticle(branch->children()[0]->
branchingParticle()->dataPtr(),true)));
theChildren.push_back(new_ptr(ShowerParticle(branch->children()[1]->
branchingParticle()->dataPtr(),true)));
particle->showerKinematics()->
updateChildren(particle, theChildren,fb.type);
if(theChildren[0]->id()==particle->id()) {
// update the history if needed
currentTree()->updateInitialStateShowerProduct(progenitor(),theChildren[0]);
currentTree()->addInitialStateBranching(particle,theChildren[0],theChildren[1]);
// shower the space-like particle
if( branch->children()[0]->children().empty() ) {
if( ! hardOnly() ) spaceLikeDecayShower(theChildren[0],maxScales,minmass,type);
}
else {
truncatedSpaceLikeDecayShower( theChildren[0],maxScales,minmass,
branch->children()[0],type);
}
// shower the second particle
if( branch->children()[1]->children().empty() ) {
if( ! hardOnly() ) timeLikeShower( theChildren[1] , type,true);
}
else {
truncatedTimeLikeShower( theChildren[1],branch->children()[1] ,type);
}
}
else {
// update the history if needed
currentTree()->updateInitialStateShowerProduct(progenitor(),theChildren[1]);
currentTree()->addInitialStateBranching(particle,theChildren[0],theChildren[1]);
// shower the space-like particle
if( branch->children()[1]->children().empty() ) {
if( ! hardOnly() ) spaceLikeDecayShower(theChildren[1],maxScales,minmass,type);
}
else {
truncatedSpaceLikeDecayShower( theChildren[1],maxScales,minmass,
branch->children()[1],type);
}
// shower the second particle
if( branch->children()[0]->children().empty() ) {
if( ! hardOnly() ) timeLikeShower( theChildren[0] , type,true);
}
else {
truncatedTimeLikeShower( theChildren[0],branch->children()[0] ,type);
}
}
return true;
}
// has emitted
// Assign the shower kinematics to the emitting particle.
particle->showerKinematics(fb.kinematics);
if(fb.kinematics->pT()>progenitor()->highestpT())
progenitor()->highestpT(fb.kinematics->pT());
// For the time being we are considering only 1->2 branching
// 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 theChildren;
theChildren.push_back(new_ptr(ShowerParticle(pdata[0],true)));
theChildren.push_back(new_ptr(ShowerParticle(pdata[1],true)));
particle->showerKinematics()->updateChildren(particle, theChildren,fb.type);
// 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(),theChildren[0]);
currentTree()->addInitialStateBranching(particle,theChildren[0],theChildren[1]);
// shower the first particle
truncatedSpaceLikeDecayShower(theChildren[0],maxScales,minmass,branch,type);
// shower the second particle
timeLikeShower(theChildren[1],type,true);
// branching has happened
return true;
}
bool Evolver::constructDecayTree(vector<ShowerProgenitorPtr> & particlesToShower,
ShowerInteraction::Type inter) {
Energy ptmax(-GeV);
// get the maximum pt is all ready a hard tree
if(hardTree()) {
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
if(particlesToShower[ix]->maximumpT(inter)>ptmax&&
particlesToShower[ix]->progenitor()->isFinalState())
ptmax = particlesToShower[ix]->maximumpT(inter);
}
}
vector<HardBranchingPtr> spaceBranchings,allBranchings;
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
if(particlesToShower[ix]->progenitor()->isFinalState()) {
HardBranchingPtr newBranch;
if(particlesToShower[ix]->hasEmitted()) {
newBranch =
new_ptr(HardBranching(particlesToShower[ix]->progenitor(),
particlesToShower[ix]->progenitor()->
showerKinematics()->SudakovFormFactor(),
HardBranchingPtr(),HardBranching::Outgoing));
constructTimeLikeLine(newBranch,particlesToShower[ix]->progenitor());
}
else {
newBranch =
new_ptr(HardBranching(particlesToShower[ix]->progenitor(),
SudakovPtr(),HardBranchingPtr(),
HardBranching::Outgoing));
}
allBranchings.push_back(newBranch);
}
else {
HardBranchingPtr newBranch;
if(particlesToShower[ix]->hasEmitted()) {
newBranch =
new_ptr(HardBranching(particlesToShower[ix]->progenitor(),
particlesToShower[ix]->progenitor()->
showerKinematics()->SudakovFormFactor(),
HardBranchingPtr(),HardBranching::Decay));
constructTimeLikeLine(newBranch,particlesToShower[ix]->progenitor());
HardBranchingPtr last=newBranch;
do {
for(unsigned int ix=0;ix<last->children().size();++ix) {
if(last->children()[ix]->branchingParticle()->id()==
particlesToShower[ix]->id()) {
last = last->children()[ix];
continue;
}
}
}
while(!last->children().empty());
last->status(HardBranching::Incoming);
spaceBranchings.push_back(newBranch);
allBranchings .push_back(last);
}
else {
newBranch =
new_ptr(HardBranching(particlesToShower[ix]->progenitor(),
SudakovPtr(),HardBranchingPtr(),
HardBranching::Incoming));
spaceBranchings.push_back(newBranch);
allBranchings .push_back(newBranch);
}
}
}
HardTreePtr QCDTree = new_ptr(HardTree(allBranchings,spaceBranchings,inter));
// set the charge partners
ShowerParticleVector particles;
particles.push_back(spaceBranchings.back()->branchingParticle());
for(set<HardBranchingPtr>::iterator cit=QCDTree->branchings().begin();
cit!=QCDTree->branchings().end();++cit) {
if((*cit)->status()==HardBranching::Outgoing)
particles.push_back((*cit)->branchingParticle());
}
// get the partners
showerModel()->partnerFinder()->setInitialEvolutionScales(particles,true,inter,true);
// do the inverse recon
if(!showerModel()->kinematicsReconstructor()->
deconstructDecayJets(QCDTree,this,inter)) {
return false;
}
// clear the old shower
currentTree()->clear();
// set the hard tree
hardTree(QCDTree);
// set the charge partners
setEvolutionPartners(false,inter,false);
// get the particles to be showered
map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator cit;
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator cjt;
particlesToShower.clear();
// incoming particles
for(cit=currentTree()->incomingLines().begin();
cit!=currentTree()->incomingLines().end();++cit)
particlesToShower.push_back(((*cit).first));
assert(particlesToShower.size()==1);
// outgoing particles
for(cjt=currentTree()->outgoingLines().begin();
cjt!=currentTree()->outgoingLines().end();++cjt) {
particlesToShower.push_back(((*cjt).first));
if(ptmax>ZERO) particlesToShower.back()->maximumpT(ptmax,inter);
}
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
eit=hardTree()->particles().end(),
mit = hardTree()->particles().find(particlesToShower[ix]->progenitor());
if( mit != eit) {
if(mit->second->status()==HardBranching::Outgoing)
particlesToShower[ix]->progenitor()->set5Momentum(mit->second->pVector());
}
}
return true;
}
bool Evolver::constructHardTree(vector<ShowerProgenitorPtr> & particlesToShower,
ShowerInteraction::Type inter) {
bool noEmission = true;
vector<HardBranchingPtr> spaceBranchings,allBranchings;
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
if(particlesToShower[ix]->progenitor()->isFinalState()) {
HardBranchingPtr newBranch;
if(particlesToShower[ix]->hasEmitted()) {
noEmission = false;
newBranch =
new_ptr(HardBranching(particlesToShower[ix]->progenitor(),
particlesToShower[ix]->progenitor()->
showerKinematics()->SudakovFormFactor(),
HardBranchingPtr(),HardBranching::Outgoing));
constructTimeLikeLine(newBranch,particlesToShower[ix]->progenitor());
}
else {
newBranch =
new_ptr(HardBranching(particlesToShower[ix]->progenitor(),
SudakovPtr(),HardBranchingPtr(),
HardBranching::Outgoing));
}
allBranchings.push_back(newBranch);
}
else {
HardBranchingPtr first,last;
if(!particlesToShower[ix]->progenitor()->parents().empty()) {
noEmission = false;
constructSpaceLikeLine(particlesToShower[ix]->progenitor(),
first,last,SudakovPtr(),
particlesToShower[ix]->original()->parents()[0]);
}
else {
first = new_ptr(HardBranching(particlesToShower[ix]->progenitor(),
SudakovPtr(),HardBranchingPtr(),
HardBranching::Incoming));
if(particlesToShower[ix]->original()->parents().empty())
first->beam(particlesToShower[ix]->original());
else
first->beam(particlesToShower[ix]->original()->parents()[0]);
last = first;
}
spaceBranchings.push_back(first);
allBranchings.push_back(last);
}
}
if(!noEmission) {
HardTreePtr QCDTree = new_ptr(HardTree(allBranchings,spaceBranchings,
inter));
// set the charge partners
ShowerParticleVector particles;
for(set<HardBranchingPtr>::iterator cit=QCDTree->branchings().begin();
cit!=QCDTree->branchings().end();++cit) {
particles.push_back((*cit)->branchingParticle());
}
// get the partners
showerModel()->partnerFinder()->setInitialEvolutionScales(particles,false,
inter,true);
// do the inverse recon
if(!showerModel()->kinematicsReconstructor()->
deconstructHardJets(QCDTree,this,inter))
throw Exception() << "Can't to shower deconstruction for QED shower in"
<< "QEDEvolver::showerHard" << Exception::eventerror;
// set the hard tree
hardTree(QCDTree);
}
// clear the old shower
currentTree()->clear();
// set the charge partners
setEvolutionPartners(true,inter,false);
// get the particles to be showered
particlesToShower = currentTree()->extractProgenitors();
// reset momenta
if(hardTree()) {
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
map<ShowerParticlePtr,tHardBranchingPtr>::const_iterator
eit=hardTree()->particles().end(),
mit = hardTree()->particles().find(particlesToShower[ix]->progenitor());
if( mit != eit) {
particlesToShower[ix]->progenitor()->set5Momentum(mit->second->showerMomentum());
}
}
}
return true;
}
void Evolver::constructTimeLikeLine(tHardBranchingPtr branch,
tShowerParticlePtr particle) {
for(unsigned int ix=0;ix<particle->children().size();++ix) {
HardBranching::Status status = branch->status();
tShowerParticlePtr child =
dynamic_ptr_cast<ShowerParticlePtr>(particle->children()[ix]);
if(child->children().empty()) {
HardBranchingPtr newBranch =
new_ptr(HardBranching(child,SudakovPtr(),branch,status));
branch->addChild(newBranch);
}
else {
HardBranchingPtr newBranch =
new_ptr(HardBranching(child,child->showerKinematics()->SudakovFormFactor(),
branch,status));
constructTimeLikeLine(newBranch,child);
branch->addChild(newBranch);
}
}
// sort out the type of interaction
if(!branch->children().empty()) {
if(branch->branchingParticle()->id()==ParticleID::gamma ||
branch->children()[0]->branchingParticle()->id()==ParticleID::gamma ||
branch->children()[1]->branchingParticle()->id()==ParticleID::gamma)
branch->type(ShowerPartnerType::QED);
else {
if(branch->branchingParticle()->id()==
branch->children()[0]->branchingParticle()->id()) {
if(branch->branchingParticle()->dataPtr()->iColour()==PDT::Colour8) {
tShowerParticlePtr emittor =
branch->branchingParticle()->showerKinematics()->z()>0.5 ?
branch->children()[0]->branchingParticle() :
branch->children()[1]->branchingParticle();
if(branch->branchingParticle()->colourLine()==emittor->colourLine())
branch->type(ShowerPartnerType::QCDAntiColourLine);
else if(branch->branchingParticle()->antiColourLine()==emittor->antiColourLine())
branch->type(ShowerPartnerType::QCDColourLine);
else
assert(false);
}
else if(branch->branchingParticle()->colourLine()) {
branch->type(ShowerPartnerType::QCDColourLine);
}
else if(branch->branchingParticle()->antiColourLine()) {
branch->type(ShowerPartnerType::QCDAntiColourLine);
}
else
assert(false);
}
else if(branch->branchingParticle()->id()==ParticleID::g &&
branch->children()[0]->branchingParticle()->id()==
-branch->children()[1]->branchingParticle()->id()) {
if(branch->branchingParticle()->showerKinematics()->z()>0.5)
branch->type(ShowerPartnerType::QCDAntiColourLine);
else
branch->type(ShowerPartnerType::QCDColourLine);
}
else
assert(false);
}
}
}
void Evolver::constructSpaceLikeLine(tShowerParticlePtr particle,
HardBranchingPtr & first,
HardBranchingPtr & last,
SudakovPtr sud,PPtr beam) {
if(!particle) return;
if(!particle->parents().empty()) {
tShowerParticlePtr parent =
dynamic_ptr_cast<ShowerParticlePtr>(particle->parents()[0]);
SudakovPtr newSud=particle->showerKinematics()->SudakovFormFactor();
constructSpaceLikeLine(parent,first,last,newSud,beam);
}
HardBranchingPtr newBranch =
new_ptr(HardBranching(particle,sud,last,HardBranching::Incoming));
newBranch->beam(beam);
if(!first) {
first=newBranch;
last =newBranch;
return;
}
last->addChild(newBranch);
tShowerParticlePtr timeChild =
dynamic_ptr_cast<ShowerParticlePtr>(particle->parents()[0]->children()[1]);
HardBranchingPtr timeBranch;
if(!timeChild->children().empty()) {
timeBranch =
new_ptr(HardBranching(timeChild,
timeChild->showerKinematics()->SudakovFormFactor(),
last,HardBranching::Outgoing));
constructTimeLikeLine(timeBranch,timeChild);
}
else {
timeBranch =
new_ptr(HardBranching(timeChild,SudakovPtr(),last,HardBranching::Outgoing));
}
last->addChild(timeBranch);
// sort out the type
if(last->branchingParticle() ->id() == ParticleID::gamma ||
newBranch->branchingParticle() ->id() == ParticleID::gamma ||
timeBranch->branchingParticle()->id() == ParticleID::gamma) {
last->type(ShowerPartnerType::QED);
}
else if(last->branchingParticle()->id()==newBranch->branchingParticle()->id()) {
if(last->branchingParticle()->id()==ParticleID::g) {
if(last->branchingParticle()->colourLine()==
newBranch->branchingParticle()->colourLine()) {
last->type(ShowerPartnerType::QCDAntiColourLine);
}
else {
last->type(ShowerPartnerType::QCDColourLine);
}
}
else if(last->branchingParticle()->hasColour()) {
last->type(ShowerPartnerType::QCDColourLine);
}
else if(last->branchingParticle()->hasAntiColour()) {
last->type(ShowerPartnerType::QCDAntiColourLine);
}
else
assert(false);
}
else if(newBranch->branchingParticle()->id()==ParticleID::g) {
if(last->branchingParticle()->hasColour()) {
last->type(ShowerPartnerType::QCDAntiColourLine);
}
else if(last->branchingParticle()->hasAntiColour()) {
last->type(ShowerPartnerType::QCDColourLine);
}
else
assert(false);
}
else if(newBranch->branchingParticle()->hasColour()) {
last->type(ShowerPartnerType::QCDColourLine);
}
else if(newBranch->branchingParticle()->hasAntiColour()) {
last->type(ShowerPartnerType::QCDAntiColourLine);
}
else {
assert(false);
}
last=newBranch;
}
void Evolver::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;
IdList 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.second;
if(ids[0]==br[0]&&ids[1]==br[1]&&ids[2]==br[2]) {
sudakov=cjt->second.first;
break;
}
}
if(!sudakov) throw Exception() << "Can't find Sudakov for the hard emission in "
<< "Evolver::connectTrees() for ISR"
<< Exception::runerror;
(**cit).parent()->sudakov(sudakov);
}
// Sudakovs for FSR
else if(!(**cit).children().empty()) {
++_nfs;
IdList 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.second;
if(ids[0]==br[0]&&ids[1]==br[1]&&ids[2]==br[2]) {
sudakov=cjt->second.first;
break;
}
}
if(!sudakov) throw Exception() << "Can't find Sudakov for the hard emission in "
<< "Evolver::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,hardTree->interaction(),
!hardTree->partnersSet());
hardTree->partnersSet(true);
// inverse reconstruction
if(hard)
showerModel()->kinematicsReconstructor()->
deconstructHardJets(hardTree,ShowerHandler::currentHandler()->evolver(),
hardTree->interaction());
else
showerModel()->kinematicsReconstructor()->
deconstructDecayJets(hardTree,ShowerHandler::currentHandler()->evolver(),
hardTree->interaction());
// now reset the momenta of the showering particles
vector<ShowerProgenitorPtr> particlesToShower;
for(map<ShowerProgenitorPtr,ShowerParticlePtr>::const_iterator
cit=showerTree->incomingLines().begin();
cit!=showerTree->incomingLines().end();++cit )
particlesToShower.push_back(cit->first);
// extract the showering particles
for(map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator
cit=showerTree->outgoingLines().begin();
cit!=showerTree->outgoingLines().end();++cit )
particlesToShower.push_back(cit->first);
// match them
vector<bool> matched(particlesToShower.size(),false);
for(set<HardBranchingPtr>::const_iterator cit=hardTree->branchings().begin();
cit!=hardTree->branchings().end();++cit) {
Energy2 dmin( 1e30*GeV2 );
int iloc(-1);
for(unsigned int ix=0;ix<particlesToShower.size();++ix) {
if(matched[ix]) continue;
if( (**cit).branchingParticle()->id() != particlesToShower[ix]->progenitor()->id() ) continue;
if( (**cit).branchingParticle()->isFinalState() !=
particlesToShower[ix]->progenitor()->isFinalState() ) continue;
Energy2 dtest =
sqr( particlesToShower[ix]->progenitor()->momentum().x() - (**cit).showerMomentum().x() ) +
sqr( particlesToShower[ix]->progenitor()->momentum().y() - (**cit).showerMomentum().y() ) +
sqr( particlesToShower[ix]->progenitor()->momentum().z() - (**cit).showerMomentum().z() ) +
sqr( particlesToShower[ix]->progenitor()->momentum().t() - (**cit).showerMomentum().t() );
// add mass difference for identical particles (e.g. Z0 Z0 production)
dtest += 1e10*sqr(particlesToShower[ix]->progenitor()->momentum().m()-
(**cit).showerMomentum().m());
if( dtest < dmin ) {
iloc = ix;
dmin = dtest;
}
}
if(iloc<0) throw Exception() << "Failed to match shower and hard trees in Evolver::hardestEmission"
<< Exception::eventerror;
- particlesToShower[iloc]->progenitor()->set5Momentum((**cit).showerMomentum());
+ if(particlesToShower[iloc]->progenitor()->dataPtr()->stable()) {
+ particlesToShower[iloc]->progenitor()->set5Momentum((**cit).showerMomentum());
+ }
+ else {
+ particlesToShower[iloc]->progenitor()->boost(particlesToShower[iloc]->progenitor()->momentum().findBoostToCM());
+ particlesToShower[iloc]->progenitor()->boost((**cit).showerMomentum().boostVector());
+ }
matched[iloc] = true;
}
// 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());
boost.boost (-newMomentum.findBoostToCM(),newMomentum.e()/newMomentum.mass());
decayTree->transform(boost,true);
}
}
void Evolver::doShowering(bool hard,XCPtr xcomb) {
// order of the interactions
bool showerOrder(true);
// zero number of emissions
_nis = _nfs = 0;
// if MC@NLO H event and limited emissions
// indicate both final and initial state emission
if ( isMCatNLOHEvent && _limitEmissions != 0 ) {
_nis = _nfs = 1;
}
// extract particles to shower
vector<ShowerProgenitorPtr> particlesToShower(setupShower(hard));
// setup the maximum scales for the shower
if (hardVetoOn()) setupMaximumScales(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() << "Evolver.cc: Mass of decaying particle is "
<< "below constituent masses of decay products."
<< Exception::eventerror;
}
}
// check if interactions in right order
if(hardTree() && interaction_!=4 &&
hardTree()->interaction()!=interactions_[0]) {
assert(interactions_.size()==2);
showerOrder = false;
swap(interactions_[0],interactions_[1]);
}
// loop over possible interactions
for(unsigned int inter=0;inter<interactions_.size();++inter) {
// set up for second pass if required
if(inter!=0) {
// zero intrinsic pt so only added first time round
intrinsicpT().clear();
// construct the tree and throw veto if not possible
if(!(hard ?
constructHardTree (particlesToShower,interactions_[inter]) :
constructDecayTree(particlesToShower,interactions_[inter])))
throw InteractionVeto();
}
// 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,interactions_[inter],true);
_nis = _nfs = 0;
// if MC@NLO H event and limited emissions
// indicate both final and initial state emission
if ( 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());
}
}
}
// create random particle vector
vector<ShowerProgenitorPtr> tmp;
while(particlesToShower.size()>0){
unsigned int xx=UseRandom::irnd(particlesToShower.size());
tmp.push_back(particlesToShower[xx]);
particlesToShower.erase(particlesToShower.begin()+xx);
}
particlesToShower=tmp;
// 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(!isFSRadiationON()) continue;
// perform shower
progenitor()->hasEmitted(startTimeLikeShower(interactions_[inter]));
}
// initial-state radiation
else {
if(!isISRadiationON()) 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,
interactions_[inter]));
}
// 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,
interactions_[inter]));
}
}
}
// do the kinematic reconstruction, checking if it worked
reconstructed = hard ?
showerModel()->kinematicsReconstructor()->
reconstructHardJets (currentTree(),intrinsicpT(),interactions_[inter]) :
showerModel()->kinematicsReconstructor()->
reconstructDecayJets(currentTree(),interactions_[inter]);
}
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 Evolver::showerDecay()"
<< Exception::eventerror;
}
}
// tree has now showered
_currenttree->hasShowered(true);
if(!showerOrder) swap(interactions_[0],interactions_[1]);
hardTree(HardTreePtr());
}
diff --git a/Shower/Base/ShowerTree.cc b/Shower/Base/ShowerTree.cc
--- a/Shower/Base/ShowerTree.cc
+++ b/Shower/Base/ShowerTree.cc
@@ -1,1376 +1,1401 @@
// -*- 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/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;
set<long> ShowerTree::_decayInShower = set<long>();
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];
}
}
}
// constructor from hard process
ShowerTree::ShowerTree(const PPair incoming, const ParticleVector & out,
ShowerDecayMap& decay)
: _hardMECorrection(false), _wasHard(true),
_parent(), _hasShowered(false) {
tPPair beam = CurrentGenerator::current().currentEvent()->incoming();
findBeam(beam.first ,incoming.first );
findBeam(beam.second,incoming.second);
_incoming = incoming;
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();
// temporary vectors to contain all the particles before insertion into
// the data structure
vector<PPtr> original,copy;
vector<ShowerParticlePtr> shower;
// create copies of ThePEG particles for the incoming particles
original.push_back(_incoming.first);
copy.push_back(new_ptr(Particle(*_incoming.first)));
original.push_back(_incoming.second);
copy.push_back(new_ptr(Particle(*_incoming.second)));
// and same for outgoing
map<PPtr,ShowerTreePtr> trees;
for (ParticleVector::const_iterator it = out.begin();
it != out.end(); ++it) {
// if decayed or should be decayed in shower make the tree
PPtr orig = *it;
- if(!orig->children().empty() ||
- (decaysInShower(orig->id())&&!orig->dataPtr()->stable())) {
+ bool radiates = false;
+ if(!orig->children().empty()) {
+ // remove d,u,s,c,b quarks and leptons other than on-shell taus
+ if(StandardQCDPartonMatcher::Check(orig->id())||
+ (LeptonMatcher::Check(orig->id())&& !(abs(orig->id())==ParticleID::tauminus && abs(orig->mass()-orig->dataPtr()->mass())<MeV))) {
+ radiates = true;
+ }
+ else
+ for(unsigned int iy=0;iy<orig->children().size();++iy) {
+ if(orig->children()[iy]->id()==orig->id()) {
+ radiates = true;
+ break;
+ }
+ }
+ }
+ if(radiates) {
+ findDecayProducts(orig,original,copy,decay,trees);
+ }
+ else if(!orig->children().empty()||
+ (decaysInShower(orig->id())&&!orig->dataPtr()->stable())) {
ShowerTreePtr newtree=new_ptr(ShowerTree(orig,decay));
newtree->setParents();
trees.insert(make_pair(orig,newtree));
Energy width=orig->dataPtr()->generateWidth(orig->mass());
decay.insert(make_pair(width,newtree));
+ original.push_back(orig);
+ copy.push_back(new_ptr(Particle(*orig)));
}
- original.push_back(orig);
- copy.push_back(new_ptr(Particle(*orig)));
+ else {
+ original.push_back(orig);
+ copy.push_back(new_ptr(Particle(*orig)));
+ }
}
// colour isolate the hard process
colourIsolate(original,copy);
// now create the Shower particles
// create ShowerParticles for the incoming particles
assert(original.size() == copy.size());
for(unsigned int ix=0;ix<original.size();++ix) {
ShowerParticlePtr temp=new_ptr(ShowerParticle(*copy[ix],1,ix>=2));
fixColour(temp);
// incoming
if(ix<2) {
temp->x(ix==0 ? x1 : x2);
_incomingLines.insert(make_pair(new_ptr(ShowerProgenitor(original[ix],
copy[ix],temp)),temp));
_backward.insert(temp);
}
// outgoing
else {
_outgoingLines.insert(make_pair(new_ptr(ShowerProgenitor(original[ix],
copy[ix],temp)),temp));
_forward.insert(temp);
}
}
// set up the map of daughter trees
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator mit;
for(mit=_outgoingLines.begin();mit!=_outgoingLines.end();++mit) {
map<PPtr,ShowerTreePtr>::const_iterator tit=trees.find(mit->first->original());
if(tit!=trees.end())
_treelinks.insert(make_pair(tit->second,
make_pair(mit->first,mit->first->progenitor())));
}
}
void ShowerTree::findDecayProducts(PPtr in, vector<PPtr> & original, vector<PPtr> & copy,
ShowerDecayMap& decay, map<PPtr,ShowerTreePtr> & trees) {
ParticleVector children=in->children();
for(unsigned int ix=0;ix<children.size();++ix) {
// if decayed or should be decayed in shower make the tree
PPtr orig=children[ix];
in->abandonChild(orig);
bool radiates = false;
if(!orig->children().empty()) {
- if(StandardQCDPartonMatcher::Check(orig->id())) {
+ // remove d,u,s,c,b quarks and leptons other than on-shell taus
+ if(StandardQCDPartonMatcher::Check(orig->id())||
+ (LeptonMatcher::Check(orig->id())&& !(abs(orig->id())==ParticleID::tauminus && abs(orig->mass()-orig->dataPtr()->mass())<MeV))) {
radiates = true;
}
else
for(unsigned int iy=0;iy<orig->children().size();++iy) {
if(orig->children()[iy]->id()==orig->id()) {
radiates = true;
break;
}
}
}
if(radiates) {
findDecayProducts(orig,original,copy,decay,trees);
}
else if(!orig->children().empty()||
(decaysInShower(orig->id())&&!orig->dataPtr()->stable())) {
ShowerTreePtr newtree=new_ptr(ShowerTree(orig,decay));
trees.insert(make_pair(orig,newtree));
Energy width=orig->dataPtr()->generateWidth(orig->mass());
decay.insert(make_pair(width,newtree));
newtree->setParents();
newtree->_parent=this;
original.push_back(orig);
copy.push_back(new_ptr(Particle(*orig)));
}
else {
original.push_back(orig);
copy.push_back(new_ptr(Particle(*orig)));
}
}
}
ShowerTree::ShowerTree(PPtr in,
ShowerDecayMap& decay)
: _hardMECorrection(false), _wasHard(false), _hasShowered(false) {
// there must be an incoming particle
assert(in);
// temporary vectors to contain all the particles before insertion into
// the data structure
vector<PPtr> original,copy;
// insert place holder for incoming particle
original.push_back(in);
copy.push_back(PPtr());
// we need to deal with the decay products if decayed
map<PPtr,ShowerTreePtr> trees;
if(!in->children().empty()) {
ParticleVector children=in->children();
for(unsigned int ix=0;ix<children.size();++ix) {
// if decayed or should be decayed in shower make the tree
PPtr orig=children[ix];
in->abandonChild(orig);
bool radiates = false;
if(!orig->children().empty()) {
- if(StandardQCDPartonMatcher::Check(orig->id())) {
+ if(StandardQCDPartonMatcher::Check(orig->id())||
+ (LeptonMatcher::Check(orig->id())&& !(abs(orig->id())==ParticleID::tauminus && abs(orig->mass()-orig->dataPtr()->mass())<MeV))) {
radiates = true;
}
else {
for(unsigned int iy=0;iy<orig->children().size();++iy) {
if(orig->children()[iy]->id()==orig->id()) {
radiates = true;
break;
}
}
}
// finally assume all non-decaying particles are in this class
if(!radiates) {
radiates = !decaysInShower(orig->id());
}
}
if(radiates) {
findDecayProducts(orig,original,copy,decay,trees);
}
else if(!orig->children().empty()||
(decaysInShower(orig->id())&&!orig->dataPtr()->stable())) {
ShowerTreePtr newtree=new_ptr(ShowerTree(orig,decay));
trees.insert(make_pair(orig,newtree));
Energy width=orig->dataPtr()->generateWidth(orig->mass());
decay.insert(make_pair(width,newtree));
newtree->setParents();
newtree->_parent=this;
original.push_back(orig);
copy.push_back(new_ptr(Particle(*orig)));
}
else {
original.push_back(orig);
copy.push_back(new_ptr(Particle(*orig)));
}
}
}
// create the incoming particle
copy[0] = new_ptr(Particle(*in));
// isolate the colour
colourIsolate(original,copy);
// create the parent
ShowerParticlePtr sparent(new_ptr(ShowerParticle(*copy[0],2,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;
// create the children
assert(copy.size() == original.size());
for (unsigned int ix=1;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);
}
// set up the map of daughter trees
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator mit;
for(mit=_outgoingLines.begin();mit!=_outgoingLines.end();++mit) {
map<PPtr,ShowerTreePtr>::const_iterator tit=trees.find(mit->first->original());
if(tit!=trees.end())
_treelinks.insert(make_pair(tit->second,
make_pair(mit->first,mit->first->progenitor())));
}
}
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::isolateLine(vector<PPair>::const_iterator cit,
vector<PPair> & particles,
tcColinePtr oldline,
tColinePtr newline) {
// loop over particles
for(vector<PPair>::const_iterator cjt=particles.begin();
cjt!=particles.end();++cjt) {
if(cjt==cit) continue;
// if particle has colour line
if((*cjt).second->colourLine()) {
// if only one check if current line and reset
if(int((*cjt).second->colourInfo()->colourLines().size())==1) {
if((*cjt).second->colourLine()==oldline)
newline->addColoured((*cjt).first);
}
// if more than one check if each line current line and reset
else {
Ptr<MultiColour>::pointer colour1 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>
((*cjt).second->colourInfo());
Ptr<MultiColour>::pointer colour2 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>
((*cjt).first ->colourInfo());
for(unsigned int ix=0;ix<colour1->colourLines().size();++ix) {
if(colour1->colourLines()[ix]==oldline)
colour2->colourLine(newline,int(ix)+1);
}
}
}
// if particle has anticolour line
if((*cjt).second->antiColourLine()) {
// if only one check if current line and reset
if(int((*cjt).second->colourInfo()->antiColourLines().size())==1) {
if((*cjt).second->antiColourLine()==oldline)
newline->addColoured((*cjt).first,true);
}
// if more than one check if each line current line and reset
else {
Ptr<MultiColour>::pointer colour1 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>
((*cjt).second->colourInfo());
Ptr<MultiColour>::pointer colour2 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>
((*cjt).first ->colourInfo());
for(unsigned int ix=0;ix<colour1->antiColourLines().size();++ix) {
if(colour1->antiColourLines()[ix]==oldline)
colour2->antiColourLine(newline, int(ix)+1);
}
}
}
}
}
void ShowerTree::colourIsolate(const vector<PPtr> & original,
const vector<PPtr> & copy) {
// vectors must have same size
assert(original.size()==copy.size());
// create a temporary map with all the particles to make looping easier
vector<PPair> particles;
particles.reserve(original.size());
for(unsigned int ix=0;ix<original.size();++ix)
particles.push_back(make_pair(copy[ix],original[ix]));
// reset the colour of the copies
vector<PPair>::const_iterator cit;
// make the colour connections of the copies
for(cit=particles.begin();cit!=particles.end();++cit) {
if((*cit).first->colourInfo()) {
if((*cit).first->dataPtr()->iColour() == PDT::Colour6 ||
(*cit).first->dataPtr()->iColour() == PDT::Colour6bar)
(*cit).first->colourInfo(new_ptr(MultiColour()));
else
(*cit).first->colourInfo(new_ptr(ColourBase()));
}
}
map<tcColinePtr,tColinePtr> cmap;
// make the colour connections of the copies
// loop over the particles
for(cit=particles.begin();cit!=particles.end();++cit) {
// if particle has at least one colour line
if((*cit).second->colourLine()) {
// one and only one line
if(int((*cit).second->colourInfo()->colourLines().size())==1) {
// if not already change
if(!(*cit).first->colourLine()) {
// make new line
tcColinePtr oldline=(*cit).second->colourLine();
ColinePtr newline=ColourLine::create((*cit).first);
cmap[oldline]=newline;
isolateLine(cit,particles,oldline,newline);
}
}
// more than one line
else {
Ptr<MultiColour>::pointer colour1 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>
((*cit).second->colourInfo());
vector<tcColinePtr> lines1 = colour1->colourLines();
Ptr<MultiColour>::pointer colour2 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>
((*cit).first->colourInfo());
vector<tcColinePtr> lines2 = colour2->colourLines();
// loop over lines
for(unsigned int ix=0;ix<lines1.size();++ix) {
if( (lines2.size()>ix && !lines2[ix]) ||
lines2.size()<=ix) {
tcColinePtr oldline = lines1[ix];
ColinePtr newline = new_ptr(ColourLine());
cmap[oldline]=newline;
colour2->colourLine(newline, int(ix)+1);
isolateLine(cit,particles,oldline,newline);
}
}
}
}
// if anticolour line
if((*cit).second->antiColourLine()) {
// one and only one line
if(int((*cit).second->colourInfo()->antiColourLines().size())==1) {
// if not already change
if(!(*cit).first->antiColourLine()) {
// make new line
tcColinePtr oldline=(*cit).second->antiColourLine();
ColinePtr newline=ColourLine::create((*cit).first, true);
cmap[oldline]=newline;
isolateLine(cit,particles,oldline,newline);
}
}
// more than one line
else {
Ptr<MultiColour>::pointer colour1 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>
((*cit).second->colourInfo());
vector<tcColinePtr> lines1 = colour1->antiColourLines();
Ptr<MultiColour>::pointer colour2 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>
((*cit).first->colourInfo());
vector<tcColinePtr> lines2 = colour2->antiColourLines();
// loop over lines
for(unsigned int ix=0;ix<lines1.size();++ix) {
if( (lines2.size()>ix && !lines2[ix]) ||
lines2.size()<=ix) {
tcColinePtr oldline = lines1[ix];
ColinePtr newline = new_ptr(ColourLine());
cmap[oldline]=newline;
colour2->antiColourLine(newline, int(ix)+1);
isolateLine(cit,particles,oldline,newline);
}
}
}
}
}
// sort out sinks and sources
for(cit=particles.begin();cit!=particles.end();++cit) {
tColinePtr cline[2];
tColinePair cpair;
for(unsigned int ix=0;ix<4;++ix) {
cline[0] = ix<2 ? cit->second->colourLine() : cit->second->antiColourLine();
cline[1] = ix<2 ? cit->first ->colourLine() : cit->first ->antiColourLine();
if(cline[0]) {
switch (ix) {
case 0: case 2:
cpair = cline[0]->sinkNeighbours();
break;
case 1: case 3:
cpair = cline[0]->sourceNeighbours();
break;
};
}
else {
cpair = make_pair(tColinePtr(),tColinePtr());
}
if(cline[0]&&cpair.first) {
map<tcColinePtr,tColinePtr>::const_iterator
mit[2] = {cmap.find(cpair.first),cmap.find(cpair.second)};
if(mit[0]!=cmap.end()&&mit[1]!=cmap.end()) {
if(ix==0||ix==2) {
cline[1]->setSinkNeighbours(mit[0]->second,mit[1]->second);
}
else {
cline[1]->setSourceNeighbours(mit[0]->second,mit[1]->second);
}
}
}
}
}
}
void ShowerTree::mapColour(PPtr original,
PPtr copy) {
// has colour line
if(copy->colourLine()) {
// one and only one
if(copy->colourInfo()->colourLines().size()==1) {
_colour.insert(make_pair(copy->colourLine(),
original->colourLine()));
}
// more than one
else {
Ptr<MultiColour>::pointer colour1 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>(copy->colourInfo());
vector<tcColinePtr> lines1 = colour1->colourLines();
Ptr<MultiColour>::pointer colour2 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>(original->colourInfo());
vector<tcColinePtr> lines2 = colour2->colourLines();
for(unsigned int ix=0;ix<lines1.size();++ix)
_colour.insert(make_pair(const_ptr_cast<ColinePtr>(lines1[ix]),
const_ptr_cast<ColinePtr>(lines2[ix])));
}
}
// has anticolour line
if(copy->antiColourLine()) {
// one and only one
if(copy->colourInfo()->antiColourLines().size()==1) {
_colour.insert(make_pair(copy->antiColourLine(),
original->antiColourLine()));
}
// more than one
else {
Ptr<MultiColour>::pointer colour1 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>(copy->colourInfo());
vector<tcColinePtr> lines1 = colour1->antiColourLines();
Ptr<MultiColour>::pointer colour2 =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>(original->colourInfo());
vector<tcColinePtr> lines2 = colour2->antiColourLines();
for(unsigned int ix=0;ix<lines1.size();++ix)
_colour.insert(make_pair(const_ptr_cast<ColinePtr>(lines1[ix]),
const_ptr_cast<ColinePtr>(lines2[ix])));
}
}
}
void ShowerTree::insertHard(StepPtr pstep, bool ISR, bool) {
assert(_incomingLines.size()==2);
_colour.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);
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);
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);
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);
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());
(*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());
(*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);
// insert shower products
addFinalStateShower(init,pstep);
}
_colour.clear();
}
void ShowerTree::addFinalStateShower(PPtr p, StepPtr s) {
// if endpoint assume doesn't travel
if(p->children().empty()) {
p->setLifeLength(Lorentz5Distance());
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);
s->addDecayProduct(*child);
(**child).setVertex(p->decayVertex());
addFinalStateShower(*child,s);
}
}
void ShowerTree::updateColour(PPtr particle) {
// if attached to a colour line
if(particle->colourLine()) {
// one and only one
if(particle->colourInfo()->colourLines().size()==1) {
bool reset=false;
// if colour line from hard process reconnect
ColinePtr c1=particle->colourLine();
if(_colour.find(c1)!=_colour.end()) {
c1->removeColoured(particle);
_colour[c1]->addColoured(particle);
reset=true;
}
// ensure properly connected to the line
if(!reset) {
ColinePtr c1=particle->colourLine();
c1->removeColoured(particle);
c1->addColoured(particle);
}
}
else {
Ptr<MultiColour>::pointer colour =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>(particle->colourInfo());
vector<tcColinePtr> lines = colour->colourLines();
for(unsigned int ix=0;ix<lines.size();++ix) {
ColinePtr c1 = const_ptr_cast<ColinePtr>(lines[ix]);
if(_colour.find(c1)!=_colour.end()) {
colour->colourLine(_colour[c1],int(ix)+1);
c1->removeColoured(particle);
}
}
}
}
// if attached to an anticolour line
if(particle->antiColourLine()) {
bool reset=false;
// one and only one
if(particle->colourInfo()->antiColourLines().size()==1) {
// if anti colour line from hard process reconnect
ColinePtr c1=particle->antiColourLine();
if(_colour.find(c1)!=_colour.end()) {
c1->removeColoured(particle,true);
_colour[c1]->addColoured(particle,true);
reset=true;
}
if(!reset) {
ColinePtr c1=particle->antiColourLine();
c1->removeColoured(particle,true);
c1->addColoured(particle,true);
}
}
else {
Ptr<MultiColour>::pointer colour =
dynamic_ptr_cast<Ptr<MultiColour>::pointer>(particle->colourInfo());
vector<tcColinePtr> lines = colour->antiColourLines();
for(unsigned int ix=0;ix<lines.size();++ix) {
ColinePtr c1 = const_ptr_cast<ColinePtr>(lines[ix]);
if(_colour.find(c1)!=_colour.end()) {
colour->antiColourLine(_colour[c1],int(ix)+1);
c1->removeColoured(particle,true);
}
}
}
}
}
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);
// 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);
// 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::decay(ShowerDecayMap & decay) {
// must be one incoming particle
assert(_incomingLines.size()==1);
// if already decayed return
if(!_outgoingLines.empty()) return;
// otherwise decay it
applyTransforms();
// now we need to replace the particle with a new copy after the shower
// find particle after the shower
ShowerParticlePtr newparent=_parent->_treelinks[this].second;
// now make the new progenitor
vector<PPtr> original,copy;
original.push_back(newparent);
copy.push_back(new_ptr(Particle(*newparent)));
// reisolate 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));
// now we need to decay the copy
PPtr parent=copy[0];
if(parent->spinInfo()) parent->spinInfo()->decay(true);
unsigned int ntry = 0;
while (true) {
// exit if fails
if (++ntry>=200)
throw Exception() << "Failed to perform decay in ShowerTree::decay()"
<< " after " << 200
<< " attempts for " << parent->PDGName()
<< Exception::eventerror;
// select decay mode
tDMPtr dm(parent->data().selectMode(*parent));
if(!dm)
throw Exception() << "Failed to select decay mode in ShowerTree::decay()"
<< "for " << newparent->PDGName()
<< Exception::eventerror;
if(!dm->decayer())
throw Exception() << "No Decayer for selected decay mode "
<< " in ShowerTree::decay()"
<< Exception::runerror;
// start of try block
try {
ParticleVector children = dm->decayer()->decay(*dm, *parent);
// if no children have another go
if(children.empty()) continue;
// set up parent
parent->decayMode(dm);
// add children
for (unsigned int i = 0, N = children.size(); i < N; ++i ) {
children[i]->setLabVertex(parent->labDecayVertex());
parent->addChild(children[i]);
parent->scale(ZERO);
}
// if succeeded break out of loop
break;
}
catch(KinematicsReconstructionVeto) {}
}
// insert the trees from the children
ParticleVector children=parent->children();
map<PPtr,ShowerTreePtr> trees;
for(unsigned int ix=0;ix<children.size();++ix) {
PPtr orig=children[ix];
parent->abandonChild(orig);
// if particle has children or decays in shower
if(!orig->children().empty()||
(decaysInShower(orig->id())&&!orig->dataPtr()->stable())) {
ShowerTreePtr newtree=new_ptr(ShowerTree(orig,decay));
trees.insert(make_pair(orig,newtree));
Energy width=orig->dataPtr()->generateWidth(orig->mass());
decay.insert(make_pair(width,newtree));
}
// now create the shower progenitors
PPtr ncopy=new_ptr(Particle(*orig));
//copy[0]->addChild(ncopy);
ShowerParticlePtr nshow=new_ptr(ShowerParticle(*ncopy,2,true));
fixColour(nshow);
ShowerProgenitorPtr prog=new_ptr(ShowerProgenitor(children[ix],
ncopy,nshow));
_outgoingLines.insert(make_pair(prog,nshow));
}
// set up the map of daughter trees
map<ShowerProgenitorPtr,tShowerParticlePtr>::const_iterator mit;
for(mit=_outgoingLines.begin();mit!=_outgoingLines.end();++mit) {
map<PPtr,ShowerTreePtr>::const_iterator tit=trees.find(mit->first->original());
if(tit!=trees.end()) {
_treelinks.insert(make_pair(tit->second,
make_pair(mit->first,
mit->first->progenitor())));
tit->second->_parent=this;
}
}
}
void ShowerTree::insertDecay(StepPtr pstep,bool ISR, bool) {
assert(_incomingLines.size()==1);
_colour.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);
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;
_colour.clear();
mapColour(final,copy);
}
// get the decaying particles
// make the copy
tColinePair cline=make_pair(copy->colourLine(),copy->antiColourLine());
updateColour(copy);
// 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());
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);
}
// from a matrix element correction
else {
if(copy->children().end()==
find(copy->children().begin(),copy->children().end(),
cit->first->original())) {
updateColour(cit->first->original());
copy->addChild(cit->first->original());
pstep->addDecayProduct(cit->first->original());
}
updateColour(cit->first->copy());
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);
}
// 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);
}
_colour.clear();
}
void ShowerTree::clear() {
// reset the has showered flag
_hasShowered=false;
// clear the colour map
_colour.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(decaysInShower((**cit).id())&&
hard.find(*cit)==hard.end()) {
ShowerTreePtr newtree=new_ptr(ShowerTree(*cit,decay));
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 {
Lorentz5Momentum ptemp1 = _incomingLines.begin()->first->progenitor()->momentum();
Lorentz5Momentum ptemp2 = ptemp1;
ptemp1 *= _transforms;
ptemp1 *= boost;
_transforms.transform(boost);
ptemp2 *= _transforms;
}
// 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;
}
namespace {
bool decayProduct(tSubProPtr subProcess,
tPPtr particle) {
// must be time-like and not incoming
if(particle->momentum().m2()<=ZERO||
particle == subProcess->incoming().first||
particle == subProcess->incoming().second) return false;
// if only 1 outgoing and this is it
if(subProcess->outgoing().size()==1 &&
subProcess->outgoing()[0]==particle) return true;
// must not be the s-channel intermediate otherwise
if(find(subProcess->incoming().first->children().begin(),
subProcess->incoming().first->children().end(),particle)!=
subProcess->incoming().first->children().end()&&
find(subProcess->incoming().second->children().begin(),
subProcess->incoming().second->children().end(),particle)!=
subProcess->incoming().second->children().end()&&
subProcess->incoming().first ->children().size()==1&&
subProcess->incoming().second->children().size()==1)
return false;
// if non-coloured this is enough
if(!particle->dataPtr()->coloured()) return true;
// if coloured must be unstable
if(particle->dataPtr()->stable()) return false;
// must not have same particle type as a child
int id = particle->id();
for(unsigned int ix=0;ix<particle->children().size();++ix)
if(particle->children()[ix]->id()==id) return false;
// otherwise its a decaying particle
return true;
}
PPtr findParent(PPtr original, bool & isHard,
set<PPtr> outgoingset,
tSubProPtr subProcess) {
PPtr parent=original;
isHard |=(outgoingset.find(original) != outgoingset.end());
if(!original->parents().empty()) {
PPtr orig=original->parents()[0];
if(CurrentGenerator::current().currentEventHandler()->currentStep()->
find(orig)&&decayProduct(subProcess,orig)) {
parent=findParent(orig,isHard,outgoingset,subProcess);
}
}
return parent;
}
}
void ShowerTree::constructTrees(tSubProPtr subProcess, ShowerTreePtr & hard,
ShowerDecayMap & decay, tPVector tagged) {
// temporary storage of the particles
set<PPtr> hardParticles;
// loop over the tagged particles
bool isHard=false;
for (tParticleVector::const_iterator taggedP = tagged.begin();
taggedP != tagged.end(); ++taggedP) {
// if a remnant don't consider
if(CurrentGenerator::current().currentEventHandler()->currentCollision()->isRemnant(*taggedP))
continue;
// find the parent and whether its a colourless s-channel resonance
bool isDecayProd=false;
tPPtr parent = *taggedP;
// check if from s channel decaying colourless particle
while(parent&&!parent->parents().empty()&&!isDecayProd) {
parent = parent->parents()[0];
if(parent == subProcess->incoming().first ||
parent == subProcess->incoming().second ) break;
isDecayProd = decayProduct(subProcess,parent);
}
set<PPtr> outgoingset(tagged.begin(),tagged.end());
// add to list of outgoing hard particles if needed
isHard |=(outgoingset.find(*taggedP) != outgoingset.end());
// not sure what the evolver bit was doing here ?
// if (isDecayProd && evolver_->_hardEmissionMode<2)
if (isDecayProd)
hardParticles.insert(findParent(parent,isHard,outgoingset,subProcess));
else hardParticles.insert(*taggedP);
}
// there must be something to shower
if(hardParticles.empty())
throw Exception() << "No particles to shower in "
<< "ShowerTree::constructTrees()"
<< Exception::eventerror;
if(!isHard)
throw Exception() << "Starting on decay not yet implemented in "
<< "ShowerTree::constructTrees()"
<< Exception::runerror;
// create the hard process ShowerTree
ParticleVector out(hardParticles.begin(),hardParticles.end());
hard=new_ptr(ShowerTree(subProcess->incoming(),out, decay));
hard->setParents();
}
diff --git a/Shower/Default/Decay_QTildeShowerKinematics1to2.cc b/Shower/Default/Decay_QTildeShowerKinematics1to2.cc
--- a/Shower/Default/Decay_QTildeShowerKinematics1to2.cc
+++ b/Shower/Default/Decay_QTildeShowerKinematics1to2.cc
@@ -1,113 +1,111 @@
// -*- 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/SplittingFunctions/SplittingFunction.h"
#include "Herwig++/Shower/Base/ShowerParticle.h"
#include <cassert>
#include "Herwig++/Shower/ShowerHandler.h"
#include "Herwig++/Shower/Base/Evolver.h"
#include "Herwig++/Shower/Base/PartnerFinder.h"
#include "Herwig++/Shower/Base/ShowerModel.h"
#include "Herwig++/Shower/Base/KinematicsReconstructor.h"
#include "Herwig++/Shower/Base/ShowerVertex.h"
using namespace Herwig;
void Decay_QTildeShowerKinematics1to2::
updateChildren(const tShowerParticlePtr parent,
const ShowerParticleVector & children,
ShowerPartnerType::Type partnerType) const {
assert(children.size() == 2);
// calculate the scales
splittingFn()->evaluateDecayScales(partnerType,scale(),z(),parent,
children[0],children[1]);
// 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]);
- if(! ShowerHandler::currentHandler()->evolver()->correlations()) return;
- SpinPtr pspin(parent->spinInfo());
// set the momenta of the children
- ShowerParticleVector::const_iterator pit;
- for(pit=children.begin();pit!=children.end();++pit) {
+ for(ShowerParticleVector::const_iterator pit=children.begin();
+ pit!=children.end();++pit) {
setMomentum(*pit,true);
}
}
void Decay_QTildeShowerKinematics1to2::
reconstructParent( const tShowerParticlePtr, const ParticleVector &) const {
throw Exception() << "Decay_QTildeShowerKinematics1to2::updateParent 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 )*pVector().m2())
/ ( 2.*last->showerParameters().alpha*p_dot_n() );
// set that new momentum
last->set5Momentum( sudakov2Momentum( last->showerParameters().alpha,
last->showerParameters().beta,
last->showerParameters().ptx,
last->showerParameters().pty) );
}
void Decay_QTildeShowerKinematics1to2::initialize(ShowerParticle & particle,PPtr) {
Lorentz5Momentum p, n, ppartner, pcm;
Frame frame;
assert(particle.perturbative()!=1);
// this is for the initial decaying particle
if(particle.perturbative()==2) {
p = particle.momentum();
ShowerParticlePtr partner=particle.partner();
Lorentz5Momentum ppartner(partner->momentum());
// reomved 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);
frame = Rest;
}
else {
tShoKinPtr kin=dynamic_ptr_cast<ShowerParticlePtr>(particle.parents()[0])
->showerKinematics();
p = kin->getBasis()[0];
n = kin->getBasis()[1];
frame = kin->frame();
}
setBasis(p,n,frame);
}
diff --git a/Shower/Default/FS_QTildeShowerKinematics1to2.cc b/Shower/Default/FS_QTildeShowerKinematics1to2.cc
--- a/Shower/Default/FS_QTildeShowerKinematics1to2.cc
+++ b/Shower/Default/FS_QTildeShowerKinematics1to2.cc
@@ -1,217 +1,218 @@
// -*- 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/SplittingFunctions/SplittingFunction.h"
#include "Herwig++/Shower/Base/ShowerParticle.h"
#include "ThePEG/Utilities/Debug.h"
#include "Herwig++/Shower/ShowerHandler.h"
#include "Herwig++/Shower/Base/Evolver.h"
#include "Herwig++/Shower/Base/PartnerFinder.h"
#include "Herwig++/Shower/Base/ShowerModel.h"
#include "Herwig++/Shower/Base/KinematicsReconstructor.h"
#include "Herwig++/Shower/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) const {
assert(children.size()==2);
// calculate the scales
splittingFn()->evaluateFinalStateScales(partnerType,scale(),z(),parent,
children[0],children[1]);
// 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) {
+ setMomentum(*pit,true);
+ }
// sort out the helicity stuff
if(! ShowerHandler::currentHandler()->evolver()->correlations()) return;
SpinPtr pspin(parent->spinInfo());
- // set the momenta of the children
- ShowerParticleVector::const_iterator pit;
- for(pit=children.begin();pit!=children.end();++pit) {
- setMomentum(*pit,true);
- }
if(!pspin || !ShowerHandler::currentHandler()->evolver()->spinCorrelations() ) return;
Energy2 t = sqr(scale())*z()*(1.-z());
IdList ids;
ids.push_back(parent->id());
ids.push_back(children[0]->id());
ids.push_back(children[1]->id());
// create the vertex
SVertexPtr vertex(new_ptr(ShowerVertex()));
// set the matrix element
vertex->ME(splittingFn()->matrixElement(z(),t,ids,phi()));
// set the incoming particle for the vertex
parent->spinInfo()->decayVertex(vertex);
- for(pit=children.begin();pit!=children.end();++pit) {
+ for(ShowerParticleVector::const_iterator pit=children.begin();
+ pit!=children.end();++pit) {
// construct the spin info for the children
constructSpinInfo(*pit,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;
parent->set5Momentum( c1->momentum() + c2->momentum() );
}
-void FS_QTildeShowerKinematics1to2::reconstructLast(const tShowerParticlePtr theLast,
+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 : theLast->data().constituentMass();
- ShowerParticle::Parameters & last = theLast->showerParameters();
- last.beta = ( sqr(theMass) + sqr(last.pt) - sqr(last.alpha) * pVector().m2() )
- / ( 2. * last.alpha * p_dot_n() );
+ Energy theMass = mass > ZERO ? mass : last->data().constituentMass();
+ ShowerParticle::Parameters & lastParam = last->showerParameters();
+ lastParam.beta = ( sqr(theMass) + sqr(lastParam.pt) - sqr(lastParam.alpha) * pVector().m2() )
+ / ( 2. * lastParam.alpha * p_dot_n() );
// set that new momentum
- theLast->set5Momentum(sudakov2Momentum( last.alpha, last.beta,
- last.ptx, last.pty) );
+ last->set5Momentum(sudakov2Momentum( lastParam.alpha, lastParam.beta,
+ lastParam.ptx , lastParam.pty) );
}
void FS_QTildeShowerKinematics1to2::initialize(ShowerParticle & particle,PPtr) {
// set the basis vectors
Lorentz5Momentum p,n;
Frame frame;
if(particle.perturbative()!=0) {
// find the partner and its momentum
ShowerParticlePtr partner=particle.partner();
Lorentz5Momentum ppartner(partner->momentum());
// momentum of the emitting particle
p = particle.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(particle.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);
}
}
frame = BackToBack;
}
else if(particle.initiatesTLS()) {
tShoKinPtr kin=dynamic_ptr_cast<ShowerParticlePtr>
(particle.parents()[0]->children()[0])->showerKinematics();
p = kin->getBasis()[0];
n = kin->getBasis()[1];
frame = kin->frame();
}
else {
tShoKinPtr kin=dynamic_ptr_cast<ShowerParticlePtr>(particle.parents()[0])
->showerKinematics();
p = kin->getBasis()[0];
n = kin->getBasis()[1];
frame = kin->frame();
}
// set the basis vectors
setBasis(p,n,frame);
}
void FS_QTildeShowerKinematics1to2::updateParent(const tShowerParticlePtr parent,
const ShowerParticleVector & children,
ShowerPartnerType::Type) const {
IdList ids(3);
ids[0] = parent->id();
ids[1] = children[0]->id();
ids[2] = children[1]->id();
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]!=ParticleID::g) pt2 += z()*(1.-z())*sqr(virtualMasses[0]);
Energy2 q2 =
sqr(children[0]->virtualMass())/z() +
sqr(children[1]->virtualMass())/(1.-z()) +
pt2/z()/(1.-z());
if(pt2<ZERO) {
parent->virtualMass(ZERO);
}
else {
parent->virtualMass(sqrt(q2));
pT(sqrt(pt2));
}
}
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/Default/IS_QTildeShowerKinematics1to2.cc b/Shower/Default/IS_QTildeShowerKinematics1to2.cc
--- a/Shower/Default/IS_QTildeShowerKinematics1to2.cc
+++ b/Shower/Default/IS_QTildeShowerKinematics1to2.cc
@@ -1,192 +1,192 @@
// -*- 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/Base/ShowerParticle.h"
#include "ThePEG/Utilities/Debug.h"
#include "Herwig++/Shower/ShowerHandler.h"
#include "Herwig++/Shower/Base/Evolver.h"
#include "Herwig++/Shower/Base/PartnerFinder.h"
#include "Herwig++/Shower/Base/ShowerModel.h"
#include "Herwig++/Shower/Base/KinematicsReconstructor.h"
#include "Herwig++/Shower/Base/ShowerVertex.h"
#include <cassert>
using namespace Herwig;
void IS_QTildeShowerKinematics1to2::
updateChildren( const tShowerParticlePtr theParent,
const ShowerParticleVector & theChildren,
ShowerPartnerType::Type) const {
const ShowerParticle::Parameters & parent = theParent->showerParameters();
ShowerParticle::Parameters & child0 = theChildren[0]->showerParameters();
ShowerParticle::Parameters & child1 = theChildren[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;
}
void IS_QTildeShowerKinematics1to2::
updateParent(const tShowerParticlePtr parent,
const ShowerParticleVector & children,
ShowerPartnerType::Type 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
- if(! ShowerHandler::currentHandler()->evolver()->correlations()) return;
// 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();
setMomentum(parent,false);
setMomentum(children[1],true);
+ if(! ShowerHandler::currentHandler()->evolver()->correlations()) return;
SpinPtr pspin(children[0]->spinInfo());
if(!pspin || !ShowerHandler::currentHandler()->evolver()->spinCorrelations() ) return;
// compute the matrix element for spin correlations
IdList ids;
ids.push_back(parent->id());
ids.push_back(children[0]->id());
ids.push_back(children[1]->id());
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()));
// set the incoming particle for the vertex
// (in reality the first child as going backwards)
pspin->decayVertex(vertex);
// construct the spin infos
constructSpinInfo(parent,false);
constructSpinInfo(children[1],true);
// connect the spinInfo objects to the vertex
parent ->spinInfo()->productionVertex(vertex);
children[1]->spinInfo()->productionVertex(vertex);
}
void IS_QTildeShowerKinematics1to2::
reconstructParent(const tShowerParticlePtr theParent,
const ParticleVector & theChildren ) const {
PPtr c1 = theChildren[0];
ShowerParticlePtr c2 = dynamic_ptr_cast<ShowerParticlePtr>(theChildren[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 * p_dot_n() );
c2->set5Momentum( sudakov2Momentum(c2param.alpha, c2param.beta,
c2param.ptx , c2param.pty) );
// spacelike child
Lorentz5Momentum pc1(theParent->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();
Energy2 pt2 = sqr(px) + sqr(py);
last.alpha = theLast->x();
last.beta = 0.5 * pt2 / last.alpha / 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);
}
void IS_QTildeShowerKinematics1to2::initialize(ShowerParticle & particle, PPtr parent) {
// For the time being we are considering only 1->2 branching
Lorentz5Momentum p, n, pthis, pcm;
assert(particle.perturbative()!=2);
Frame frame;
if(particle.perturbative()==1) {
// find the partner and its momentum
ShowerParticlePtr partner=particle.partner();
assert(partner);
if(partner->isFinalState()) {
Lorentz5Momentum pa = -particle.momentum()+partner->momentum();
Lorentz5Momentum pb = particle.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());
}
frame = BackToBack;
}
else {
p = dynamic_ptr_cast<ShowerParticlePtr>(particle.children()[0])
->showerKinematics()->getBasis()[0];
n = dynamic_ptr_cast<ShowerParticlePtr>(particle.children()[0])
->showerKinematics()->getBasis()[1];
frame = dynamic_ptr_cast<ShowerParticlePtr>(particle.children()[0])
->showerKinematics()->frame();
}
setBasis(p,n,frame);
}
diff --git a/Shower/Default/QTildeShowerKinematics1to2.cc b/Shower/Default/QTildeShowerKinematics1to2.cc
--- a/Shower/Default/QTildeShowerKinematics1to2.cc
+++ b/Shower/Default/QTildeShowerKinematics1to2.cc
@@ -1,152 +1,133 @@
// -*- C++ -*-
//
// 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 QTildeShowerKinematics1to2 class.
//
#include "QTildeShowerKinematics1to2.h"
#include "ThePEG/Interface/ClassDocumentation.h"
#include "Herwig++/Shower/Base/ShowerParticle.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 "ThePEG/Helicity/LorentzSpinorBar.h"
using namespace Herwig;
using namespace ThePEG::Helicity;
vector<Lorentz5Momentum> QTildeShowerKinematics1to2::getBasis() const {
vector<Lorentz5Momentum> dum;
dum.push_back( _pVector );
dum.push_back( _nVector );
return dum;
}
void QTildeShowerKinematics1to2::setBasis(const Lorentz5Momentum &p,
const Lorentz5Momentum & n,
Frame inframe) {
_pVector=p;
_nVector=n;
frame(inframe);
-}
-
-Lorentz5Momentum QTildeShowerKinematics1to2::
-sudakov2Momentum(double alpha, double beta, Energy px, Energy py) const {
- if(isnan(beta)||isinf(beta))
- throw Exception() << "beta infinite in "
- << "QTildeShowerKinematics1to2::sudakov2Momentum()"
- << Exception::eventerror;
Boost beta_bb;
if(frame()==BackToBack) {
beta_bb = -(_pVector + _nVector).boostVector();
}
else if(frame()==Rest) {
beta_bb = -pVector().boostVector();
}
else
assert(false);
Lorentz5Momentum p_bb = pVector();
Lorentz5Momentum n_bb = nVector();
p_bb.boost( beta_bb );
n_bb.boost( beta_bb );
- // momentum without transverse components
- Lorentz5Momentum dq;
- if(frame()==BackToBack) {
- dq=Lorentz5Momentum(ZERO, ZERO, (alpha - beta)*p_bb.vect().mag(),
- alpha*p_bb.t() + beta*n_bb.t());
- }
- else if(frame()==Rest) {
- dq=Lorentz5Momentum (ZERO, ZERO, 0.5*beta*pVector().mass(),
- alpha*pVector().mass() + 0.5*beta*pVector().mass());
- }
- else
- assert(false);
- // add transverse components
- dq.setX(px);
- dq.setY(py);
// rotate to have z-axis parallel to p/n
Axis axis;
if(frame()==BackToBack) {
axis = p_bb.vect().unit();
}
else if(frame()==Rest) {
axis = n_bb.vect().unit();
}
else
assert(false);
LorentzRotation rot;
if(axis.perp2()>1e-10) {
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.));
}
- dq.transform(rot);
+ _xPerp=LorentzVector<double>(1.,0.,0.,0.);
+ _yPerp=LorentzVector<double>(0.,1.,0.,0.);
+ _xPerp.transform(rot);
+ _yPerp.transform(rot);
// boost back
- dq.boost( -beta_bb );
- dq.rescaleMass();
- return dq;
+ _xPerp.boost( -beta_bb );
+ _yPerp.boost( -beta_bb );
}
void QTildeShowerKinematics1to2::setMomentum(tShowerParticlePtr particle,
bool timeLike) const {
- Energy mass = particle->data().mass();
+ Energy mass = particle->mass() > ZERO ? particle->mass() : particle->data().mass();
// calculate the momentum of the assuming on-shell
Energy2 pt2 = sqr(particle->showerParameters().pt);
double alpha = timeLike ? particle->showerParameters().alpha : particle->x();
double beta = 0.5*(sqr(mass) + pt2 - sqr(alpha)*pVector().m2())/(alpha*p_dot_n());
Lorentz5Momentum porig=sudakov2Momentum(alpha,beta,
particle->showerParameters().ptx,
particle->showerParameters().pty);
porig.setMass(mass);
particle->set5Momentum(porig);
}
void QTildeShowerKinematics1to2::constructSpinInfo(tShowerParticlePtr particle,
bool timeLike) const {
// now construct the required spininfo and calculate the basis states
PDT::Spin spin(particle->dataPtr()->iSpin());
if(spin==PDT::Spin0) {
ScalarWaveFunction::constructSpinInfo(particle,outgoing,timeLike);
}
// calculate the basis states and construct the SpinInfo for a spin-1/2 particle
else if(spin==PDT::Spin1Half) {
// outgoing particle
if(particle->id()>0) {
vector<LorentzSpinorBar<SqrtEnergy> > stemp;
SpinorBarWaveFunction::calculateWaveFunctions(stemp,particle,outgoing);
SpinorBarWaveFunction::constructSpinInfo(stemp,particle,outgoing,timeLike);
}
// outgoing antiparticle
else {
vector<LorentzSpinor<SqrtEnergy> > stemp;
SpinorWaveFunction::calculateWaveFunctions(stemp,particle,outgoing);
SpinorWaveFunction::constructSpinInfo(stemp,particle,outgoing,timeLike);
}
}
// calculate the basis states and construct the SpinInfo for a spin-1 particle
else if(spin==PDT::Spin1) {
bool massless(particle->id()==ParticleID::g||particle->id()==ParticleID::gamma);
vector<Helicity::LorentzPolarizationVector> vtemp;
VectorWaveFunction::calculateWaveFunctions(vtemp,particle,outgoing,massless);
VectorWaveFunction::constructSpinInfo(vtemp,particle,outgoing,timeLike,massless);
}
else {
throw Exception() << "Spins higher than 1 are not yet implemented in "
<< "FS_QtildaShowerKinematics1to2::constructVertex() "
<< Exception::runerror;
}
}
void QTildeShowerKinematics1to2::transform(const LorentzRotation & r) {
_pVector *= r;
- //_nVector *= r;
+ _nVector *= r;
+ _xPerp *= r;
+ _yPerp *= r;
}
diff --git a/Shower/Default/QTildeShowerKinematics1to2.h b/Shower/Default/QTildeShowerKinematics1to2.h
--- a/Shower/Default/QTildeShowerKinematics1to2.h
+++ b/Shower/Default/QTildeShowerKinematics1to2.h
@@ -1,120 +1,132 @@
// -*- C++ -*-
//
// 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_QTildeShowerKinematics1to2_H
#define HERWIG_QTildeShowerKinematics1to2_H
//
// This is the declaration of the QTildeShowerKinematics1to2 class.
//
#include "Herwig++/Shower/Base/ShowerKinematics.h"
#include "ThePEG/Vectors/Lorentz5Vector.h"
#include "QTildeShowerKinematics1to2.fh"
namespace Herwig {
using namespace ThePEG;
/** \ingroup Shower
*
* This abstract class describes the common features for initial and final
* state radiation kinematics for \f$1\to2\f$ branchings and for
* the choice of \f$\tilde{q}\f$ as evolution variable.
*
* @see ShowerKinematics
* @see IS_QTildeShowerKinematics1to2
* @see FS_QTildeShowerKinematics1to2
* @see KinematicsReconstructor
*/
class QTildeShowerKinematics1to2: public ShowerKinematics {
public:
/**
* Implementation of the virtual function returning a set of basis vectors, specific to
* the type of evolution. This function will be used by the
* ForwardShowerEvolver in order to access \f$p\f$
* and \f$n\f$.
*/
virtual vector<Lorentz5Momentum> getBasis() const;
/**
* Access to the \f$p\f$ vector used to describe the kinematics.
*/
const Lorentz5Momentum & pVector() const {return _pVector;}
/**
* Access to the \f$n\f$ vector used to describe the kinematics.
*/
const Lorentz5Momentum & nVector() const {return _nVector;}
/**
* Dot product of thew basis vectors
*/
Energy2 p_dot_n() const {return _pVector*_nVector;}
/**
* Converts a Sudakov parametrization of a momentum w.r.t. the given
* basis \f$p\f$ and \f$n\f$ into a 5 momentum.
* @param alpha The \f$\alpha\f$ parameter of the Sudakov parameterisation
* @param beta The \f$\beta\f$ parameter of the Sudakov parameterisation
* @param px The \f$x\f$-component of the transverse momentum in the Sudakov
* parameterisation
* @param py The \f$x\f$-component of the transverse momentum in the Sudakov
* parameterisation
*/
Lorentz5Momentum sudakov2Momentum(double alpha, double beta,
- Energy px, Energy py) const;
+ Energy px, Energy py) const {
+ return alpha*_pVector + beta*_nVector + px*_xPerp+py*_yPerp;
+ }
/**
* Transform the shower kinematics (usually the reference vectors)
*/
virtual void transform(const LorentzRotation & r);
protected:
/**
* Set the basis vectors
*/
- void setBasis(const Lorentz5Momentum &p, const Lorentz5Momentum & n, Frame frame);
+ void setBasis(const Lorentz5Momentum &p, const Lorentz5Momentum & n,
+ Frame frame);
/**
* Set a preliminary momentum for the particle
*/
void setMomentum(tShowerParticlePtr,bool timelike) const;
/**
* Construct the spin info object for a shower particle
*/
void constructSpinInfo(tShowerParticlePtr,bool timelike) const;
private:
/**
* The assignment operator is private and must never be called.
* In fact, it should not even be implemented.
*/
QTildeShowerKinematics1to2 & operator=(const QTildeShowerKinematics1to2 &);
private:
/**
* The \f$p\f$ reference vector
*/
Lorentz5Momentum _pVector;
/**
* The \f$n\f$ reference vector
*/
Lorentz5Momentum _nVector;
+ /**
+ * x \f$q_\perp\f$ reference vector
+ */
+ LorentzVector<double> _xPerp;
+
+ /**
+ * y \f$q_\perp\f$reference vector
+ */
+ LorentzVector<double> _yPerp;
};
}
#endif /* HERWIG_QTildeShowerKinematics1to2_H */
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,1668 +1,1668 @@
#! /usr/bin/env python
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
# #############################################
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)
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")
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")
## Prefix used in dat file headers
headerprefix = "# "
yodafiles=["-900-UE.yoda" ,"-2360-UE.yoda" ,"-2760-UE.yoda" ,
- "-7-UE.yoda" ,"-900-UE-Long.yoda","-8-UE.yoda"
+ "-7-UE.yoda" ,"-900-UE-Long.yoda","-8-UE.yoda",
"-7-UE-Long.yoda","-7-Jets-0.yoda",
"-7-Jets-All-1.yoda","-7-Jets-All-2.yoda",
"-7-Jets-All-3.yoda","-7-Jets-All-4.yoda","-7-Jets-All-5.yoda",
"-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-Heavy-0.yoda","-7-Heavy-1.yoda","-7-Heavy-2.yoda",
"-7-Heavy-3.yoda","-7-Heavy-4.yoda","-7-Heavy-5.yoda",
"-7-Top-SL.yoda","-7-Top-L.yoda"]
## Get histos
inhistos_pt = {}
inhistos_mass = {}
outhistos={}
weights = {}
for f in yodafiles:
file="LHC"+f
sqrts=7000
if(file.find("-900-UE")>0) :
sqrts=900
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("-7-Jets-0")>0) :
ptmin=4.
elif(file.find("-7-Jets-1")>0) :
ptmin=30.
elif(file.find("-7-Jets-2")>0) :
ptmin=40.
elif(file.find("-7-Jets-3")>0) :
ptmin=80.
elif(file.find("-7-Jets-4")>0) :
ptmin=110.
elif(file.find("-7-Jets-5")>0) :
ptmin=210.
elif(file.find("-7-Jets-6")>0) :
ptmin=260.
elif(file.find("-7-Jets-7")>0) :
ptmin=400.
elif(file.find("-7-Jets-8")>0) :
ptmin=600.
elif(file.find("-7-Heavy-0.yoda")>0) :
ptmin=0.
elif(file.find("-7-Heavy-1.yoda")>0) :
ptmin=10.
elif(file.find("-7-Heavy-2.yoda")>0) :
ptmin=30.
elif(file.find("-7-Heavy-3.yoda")>0) :
ptmin=70.
elif(file.find("-7-Heavy-4.yoda")>0) :
ptmin=100.
elif(file.find("-7-Heavy-5.yoda")>0) :
ptmin=130.
elif(file.find("-7-Top-SL.yoda")>0 or file.find("-7-Top-L.yoda")>0):
ptmin=0.
elif(file.find("-7-Jets-All-1")>0) :
ptmin=25.
elif(file.find("-7-Jets-All-2")>0) :
ptmin=50.
elif(file.find("-7-Jets-All-3")>0) :
ptmin=100.
elif(file.find("-7-Jets-All-4")>0) :
ptmin=170.
elif(file.find("-7-Jets-All-5")>0) :
ptmin=320.
if not os.access(file, os.R_OK):
logging.error("%s can not be read" % file)
break
try:
aos = yoda.read(file)
except:
logging.error("%s can not be parsed as YODA" % file)
break
## 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("CMS_2012_PAS_QCD_11_010")>0 or
aopath.find("ATLAS_2014_I1298811")>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:
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-Heavy-6.yoda","-7-Heavy-7.yoda","-7-Heavy-8.yoda"]
for f in yodafiles:
file="LHC"+f
if(file.find("-7-Jets-1.yoda")>0) :
sqrts=7000
mass=0
if(file.find("-7-Jets-9.yoda")>0) :
sqrts=7000
mass=100
elif(file.find("-7-Jets-10.yoda")>0) :
sqrts=7000
mass=300
elif(file.find("-7-Jets-11.yoda")>0) :
sqrts=7000
mass=800
elif(file.find("-7-Jets-12.yoda")>0) :
sqrts=7000
mass=1200
elif(file.find("-7-Jets-13.yoda")>0) :
sqrts=7000
mass=2000
elif(file.find("-7-Heavy-6.yoda")>0) :
sqrts=7000
mass=110
elif(file.find("-7-Heavy-7.yoda")>0) :
sqrts=7000
mass=370
elif(file.find("-7-Heavy-8.yoda")>0) :
sqrts=7000
mass=550
if not os.access(file, os.R_OK):
logging.error("%s can not be read" % file)
break
try:
aos = yoda.read(file)
except:
logging.error("%s can not be parsed as YODA" % file)
break
## Get histos from this YODA file
for aopath, ao in aos.iteritems() :
if(aopath.find("8817804")>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) :
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))
## 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 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) :
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)
print hpath,type(hsets.values()[0].values()[0])
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)
print hpath,type(hsets.values()[0].values()[0])
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" )
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" )
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" )
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")
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/d08-x01-y01", "7000", "0" )
useOnePt("/CMS_2011_S9120041/d09-x01-y01", "7000", "0" )
useOnePt("/CMS_2011_S9120041/d10-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" )
# 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")
mergeByPt("/ATLAS_2011_I919017/d01-x01-y01", "7000")
mergeByPt("/ATLAS_2011_I919017/d01-x01-y02", "7000")
mergeByPt("/ATLAS_2011_I919017/d01-x01-y03", "7000")
mergeByPt("/ATLAS_2011_I919017/d01-x01-y04", "7000")
useOnePt("/ATLAS_2011_I919017/d01-x02-y01", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y02", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y03", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y04", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y05", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y06", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y07", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y08", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y09", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y10", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y11", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y12", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y13", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y14", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y15", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y16", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y17", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y18", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y19", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y20", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y21", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y22", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y23", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y24", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x02-y25", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y01", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y02", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y03", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y04", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y05", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y06", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y07", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y08", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y09", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y10", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y11", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y12", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y13", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y14", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y15", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y16", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y17", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y18", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y19", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y20", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y21", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y22", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y23", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y24", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x03-y25", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y01", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y02", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y03", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y04", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y05", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y06", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y07", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y08", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y09", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y10", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y11", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y12", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y13", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y14", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y15", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y16", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y17", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y18", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y19", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y20", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y21", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y22", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y23", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y24", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x04-y25", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y01", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y02", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y03", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y04", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y05", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y06", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y07", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y08", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y09", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y10", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y11", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y12", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y13", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y14", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y15", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y16", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y17", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y18", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y19", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y20", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y21", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y22", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y23", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y24", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d01-x05-y25", "7000", "30" )
mergeByPt("/ATLAS_2011_I919017/d02-x01-y01", "7000")
mergeByPt("/ATLAS_2011_I919017/d02-x01-y02", "7000")
mergeByPt("/ATLAS_2011_I919017/d02-x01-y03", "7000")
mergeByPt("/ATLAS_2011_I919017/d02-x01-y04", "7000")
useOnePt("/ATLAS_2011_I919017/d02-x02-y01", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y02", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y03", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y04", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y05", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y06", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y07", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y08", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y09", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y10", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y11", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y12", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y13", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y14", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y15", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y16", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y17", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y18", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y19", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y20", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y21", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y22", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y23", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y24", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x02-y25", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y01", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y02", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y03", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y04", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y05", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y06", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y07", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y08", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y09", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y10", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y11", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y12", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y13", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y14", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y15", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y16", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y17", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y18", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y19", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y20", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y21", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y22", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y23", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y24", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x03-y25", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y01", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y02", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y03", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y04", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y05", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y06", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y07", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y08", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y09", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y10", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y11", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y12", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y13", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y14", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y15", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y16", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y17", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y18", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y19", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y20", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y21", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y22", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y23", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y24", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x04-y25", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y01", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y02", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y03", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y04", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y05", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y06", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y07", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y08", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y09", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y10", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y11", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y12", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y13", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y14", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y15", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y16", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y17", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y18", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y19", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y20", "7000", "30" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y21", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y22", "7000", "0" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y23", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y24", "7000", "4" )
useOnePt("/ATLAS_2011_I919017/d02-x05-y25", "7000", "30" )
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", "25" )
useOnePt("/ATLAS_2012_I1082009/d09-x01-y01", "7000", "25" )
useOnePt("/ATLAS_2012_I1082009/d10-x01-y01", "7000", "25" )
useOnePt("/ATLAS_2012_I1082009/d11-x01-y01", "7000", "50" )
useOnePt("/ATLAS_2012_I1082009/d12-x01-y01", "7000", "50" )
useOnePt("/ATLAS_2012_I1082009/d13-x01-y01", "7000", "25" )
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")
useOnePt("/ATLAS_2012_I1125575/d04-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x01-y02", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x01-y03", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x01-y04", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x01-y05", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x01-y06", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x01-y07", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x01-y08", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x01-y09", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x01-y10", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x01-y11", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x01-y12", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x01-y13", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x01-y14", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x01-y15", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x01-y16", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x01-y17", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d04-x01-y18", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d04-x01-y19", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d04-x01-y20", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d04-x02-y01", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x02-y02", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x02-y03", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x02-y04", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x02-y05", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x02-y06", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x02-y07", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x02-y08", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x02-y09", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x02-y10", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x02-y11", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x02-y12", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x02-y13", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x02-y14", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x02-y15", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x02-y16", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x02-y17", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d04-x02-y18", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d04-x02-y19", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d04-x02-y20", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d04-x03-y01", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x03-y02", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x03-y03", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x03-y04", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x03-y05", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x03-y06", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x03-y07", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x03-y08", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x03-y09", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x03-y10", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x03-y11", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x03-y12", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x03-y13", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x03-y14", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x03-y15", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x03-y16", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x03-y17", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d04-x03-y18", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d04-x03-y19", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d04-x03-y20", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d04-x04-y01", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x04-y02", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x04-y03", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x04-y04", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x04-y05", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x04-y06", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x04-y07", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x04-y08", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x04-y09", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x04-y10", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x04-y11", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x04-y12", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x04-y13", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x04-y14", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x04-y15", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x04-y16", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x04-y17", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d04-x04-y18", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d04-x04-y19", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d04-x04-y20", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d04-x05-y01", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x05-y02", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x05-y03", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x05-y04", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x05-y05", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x05-y06", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x05-y07", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x05-y08", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d04-x05-y09", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x05-y10", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x05-y11", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x05-y12", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x05-y13", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x05-y14", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x05-y15", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x05-y16", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d04-x05-y17", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d04-x05-y18", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d04-x05-y19", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d04-x05-y20", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d05-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x01-y02", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x01-y03", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x01-y04", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x01-y05", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x01-y06", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x01-y07", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x01-y08", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x01-y09", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x01-y10", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x01-y11", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x01-y12", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x01-y13", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x01-y14", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x01-y15", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x01-y16", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x01-y17", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d05-x01-y18", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d05-x01-y19", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d05-x01-y20", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d05-x02-y01", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x02-y02", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x02-y03", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x02-y04", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x02-y05", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x02-y06", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x02-y07", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x02-y08", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x02-y09", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x02-y10", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x02-y11", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x02-y12", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x02-y13", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x02-y14", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x02-y15", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x02-y16", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x02-y17", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d05-x02-y18", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d05-x02-y19", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d05-x02-y20", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d05-x03-y01", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x03-y02", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x03-y03", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x03-y04", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x03-y05", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x03-y06", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x03-y07", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x03-y08", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x03-y09", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x03-y10", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x03-y11", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x03-y12", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x03-y13", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x03-y14", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x03-y15", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x03-y16", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x03-y17", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d05-x03-y18", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d05-x03-y19", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d05-x03-y20", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d05-x04-y01", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x04-y02", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x04-y03", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x04-y04", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x04-y05", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x04-y06", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x04-y07", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x04-y08", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x04-y09", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x04-y10", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x04-y11", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x04-y12", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x04-y13", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x04-y14", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x04-y15", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x04-y16", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x04-y17", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d05-x04-y18", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d05-x04-y19", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d05-x04-y20", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d05-x05-y01", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x05-y02", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x05-y03", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x05-y04", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x05-y05", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x05-y06", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x05-y07", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x05-y08", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d05-x05-y09", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x05-y10", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x05-y11", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x05-y12", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x05-y13", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x05-y14", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x05-y15", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x05-y16", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d05-x05-y17", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d05-x05-y18", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d05-x05-y19", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d05-x05-y20", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d06-x01-y01", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x01-y02", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x01-y03", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x01-y04", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x01-y05", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x01-y06", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x01-y07", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x01-y08", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x01-y09", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x01-y10", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x01-y11", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x01-y12", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x01-y13", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x01-y14", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x01-y15", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x01-y16", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x01-y17", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d06-x01-y18", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d06-x01-y19", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d06-x01-y20", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d06-x02-y01", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x02-y02", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x02-y03", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x02-y04", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x02-y05", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x02-y06", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x02-y07", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x02-y08", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x02-y09", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x02-y10", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x02-y11", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x02-y12", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x02-y13", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x02-y14", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x02-y15", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x02-y16", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x02-y17", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d06-x02-y18", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d06-x02-y19", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d06-x02-y20", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d06-x03-y01", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x03-y02", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x03-y03", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x03-y04", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x03-y05", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x03-y06", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x03-y07", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x03-y08", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x03-y09", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x03-y10", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x03-y11", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x03-y12", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x03-y13", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x03-y14", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x03-y15", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x03-y16", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x03-y17", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d06-x03-y18", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d06-x03-y19", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d06-x03-y20", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d06-x04-y01", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x04-y02", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x04-y03", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x04-y04", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x04-y05", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x04-y06", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x04-y07", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x04-y08", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x04-y09", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x04-y10", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x04-y11", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x04-y12", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x04-y13", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x04-y14", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x04-y15", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x04-y16", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x04-y17", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d06-x04-y18", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d06-x04-y19", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d06-x04-y20", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d06-x05-y01", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x05-y02", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x05-y03", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x05-y04", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x05-y05", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x05-y06", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x05-y07", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x05-y08", "7000", "0" )
useOnePt("/ATLAS_2012_I1125575/d06-x05-y09", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x05-y10", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x05-y11", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x05-y12", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x05-y13", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x05-y14", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x05-y15", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x05-y16", "7000", "4" )
useOnePt("/ATLAS_2012_I1125575/d06-x05-y17", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d06-x05-y18", "7000", "30" )
useOnePt("/ATLAS_2012_I1125575/d06-x05-y19", "7000", "40" )
useOnePt("/ATLAS_2012_I1125575/d06-x05-y20", "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 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.)
# Choose output file
name = "LHC"+"-Jets.yoda"
yoda.writeYODA(outhistos,name)
sys.exit(0)
diff --git a/m4/herwig.m4 b/m4/herwig.m4
--- a/m4/herwig.m4
+++ b/m4/herwig.m4
@@ -1,909 +1,924 @@
# 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])
])
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$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
VBFNLOINCLUDE=${with_vbfnlo}/include
AC_SUBST(VBFNLOINCLUDE)
VBFNLOLIB=${with_vbfnlo}/${have_vbfnlo}/VBFNLO
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 ##### nlojet #####
AC_DEFUN([HERWIG_CHECK_NLOJET],
[
AC_MSG_CHECKING([for nlojet])
AC_ARG_WITH([nlojet],
AS_HELP_STRING([--with-nlojet=DIR], [Installation path of nlojet]),
[],
[with_nlojet=no]
)
AC_MSG_RESULT([$with_nlojet])
AS_IF([test "x$with_nlojet" != "xno"],
[AC_CHECK_FILES(
${with_nlojet}/lib/libnlo++.so,
[have_nlojet=lib], [have_nlojet=no])],
[have_nlojet=no])
AS_IF([test "x$with_nlojet" != "xno" -a "x$have_nlojet" = "xno" ],
[AC_CHECK_FILES(
${with_nlojet}/lib64/libnlo++.so,
[have_nlojet=lib64], [have_nlojet=no])])
AS_IF([test "x$have_nlojet" = "xlib"],
[NLOJETLIBPATH=${with_nlojet}/lib
AC_SUBST(NLOJETLIBPATH)
NLOJETINCLUDEPATH=${with_nlojet}/include
AC_SUBST(NLOJETINCLUDEPATH)
])
AS_IF([test "x$have_nlojet" = "xlib64"],
[NLOJETLIBPATH=${with_nlojet}/lib64
AC_SUBST(NLOJETLIBPATH)
NLOJETINCLUDEPATH=${with_nlojet}/include
AC_SUBST(NLOJETINCLUDEPATH)
])
AS_IF([test "x$with_nlojet" != "xno" -a "x$have_nlojet" = "xno"],
[AC_MSG_ERROR([nlojet requested but not found])])
AM_CONDITIONAL(HAVE_NLOJET,[test "x$have_nlojet" = "xlib" -o "x$have_nlojet" = "xlib64"])
if test "x$have_nlojet" = "xlib" -o "x$have_nlojet" = "xlib64" ; then
LOAD_NLOJET="library"
CREATE_NLOJET="create"
INSERT_NLOJET="insert"
else
LOAD_NLOJET="# library"
CREATE_NLOJET="# create"
INSERT_NLOJET="# insert"
fi
AC_SUBST([LOAD_NLOJET])
AC_SUBST([CREATE_NLOJET])
AC_SUBST([INSERT_NLOJET])
])
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$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 ##### hej #####
AC_DEFUN([HERWIG_CHECK_HEJ],
[
AC_MSG_CHECKING([for hej])
AC_ARG_WITH([hej],
AS_HELP_STRING([--with-hej=DIR], [Installation path of HEJ]),
[],
[with_hej=no]
)
AC_MSG_RESULT([$with_hej])
AS_IF([test "x$with_hej" != "xno"],
[AC_CHECK_FILES(
${with_hej}/lib/libJets.so
${with_hej}/include/HEJ/Jets.h,
[have_hej=yes], [have_hej=no])],
[have_hej=no])
AS_IF([test "x$have_hej" = "xyes"],
[HEJLIBPATH=${with_hej}/lib
AC_SUBST(HEJLIBPATH)
HEJCPPFLAGS=`${with_hej}/bin/hej-config --cppflags`
AC_SUBST(HEJCPPFLAGS)
],
[AS_IF([test "x$with_hej" != "xno"],
[AC_MSG_ERROR([hej requested but not found])
])
])
AM_CONDITIONAL(HAVE_HEJ,[test "x$have_hej" = "xyes"])
])
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"
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"
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"
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_DEFUN([HERWIG_VERSIONSTRING],
[
if test -d $srcdir/.svn; then
AC_CHECK_PROG(have_svnversion,[svnversion],[yes],[no])
fi
AM_CONDITIONAL(USE_SVNVERSION,[test "x$have_svnversion" = "xyes"])
])
dnl ##### COMPILERFLAGS #####
AC_DEFUN([HERWIG_COMPILERFLAGS],
[
AC_REQUIRE([HERWIG_CHECK_GSL])
AC_REQUIRE([HERWIG_CHECK_THEPEG])
AC_REQUIRE([BOOST_REQUIRE])
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="-ansi -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
AC_SUBST(AM_CPPFLAGS)
AC_SUBST(AM_CFLAGS, ["$warnflags $debugflags"])
AC_SUBST(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
***
*** VBFNLO: $with_vbfnlo
*** nlojet: $with_nlojet
*** njet: $with_njet
*** GoSam: $with_gosam
*** GoSam-Contrib: $with_gosam_contrib
*** OpenLoops: $with_openloops
*** MadGraph: $with_madgraph
*** HEJ: $with_hej
***
*** 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/DIS-Matchbox.in b/src/DIS-Matchbox.in
--- a/src/DIS-Matchbox.in
+++ b/src/DIS-Matchbox.in
@@ -1,254 +1,256 @@
##################################################
## Herwig++/Matchbox example input file
##################################################
##################################################
## Technical parameters for this run
##################################################
cd /Herwig/Generators
set DISGenerator:RandomNumberGenerator:Seed 31122001
set DISGenerator:DebugLevel 1
set DISGenerator:PrintEvent 10
set DISGenerator:MaxErrors 10000
set DISGenerator:NumberOfEvents 100000000
cd /Herwig/EventHandlers
set DISHandler:Weighted Off
set DISHandler:Sampler /Herwig/Samplers/Sampler
set DISHandler:CascadeHandler:MPIHandler NULL
##################################################
## beam energy
##################################################
set /Herwig/EventHandlers/DISHandler:BeamA /Herwig/Particles/e+
set /Herwig/EventHandlers/DISLuminosity:BeamEMaxA 27.5.*GeV
set /Herwig/EventHandlers/DISHandler:BeamB /Herwig/Particles/p+
set /Herwig/EventHandlers/DISLuminosity:BeamEMaxB 820.*GeV
cd /Herwig/MatrixElements/Matchbox
insert /Herwig/Generators/DISGenerator:EventHandler:SubProcessHandlers[0] DISFactory
##################################################
## PDF choice
##################################################
cd /Herwig/Partons
create ThePEG::LHAPDF PDFSet ThePEGLHAPDF.so
set PDFSet:RemnantHandler HadronRemnants
set /Herwig/Partons/PDFSet:PDFName CT10.LHgrid
set /Herwig/Particles/p+:PDF PDFSet
set /Herwig/Particles/pbar-:PDF PDFSet
##################################################
## 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. NLO
## matched simulations are generated by default, as long as virtual
## corrections are available.
## Set the order of the couplings
cd /Herwig/MatrixElements/Matchbox
set DISFactory:OrderInAlphaS 0
set DISFactory:OrderInAlphaEW 2
## Select the process
## You may use identifiers such as p, pbar, j, l, mu+, h0 etc.
do DISFactory:Process e+ p e+ j
## If a swap of beams, p e+/- is needed comment in this
# set DISFactory:FirstPerturbativePDF Yes
# set DISFactory:SecondPerturbativePDF No
##################################################
## Cut Selection
##################################################
## For finite calculations make resonable cuts! Check the wiki and manual
## for other cut options and different jet algorithms.
cd /Herwig/Cuts
+set MatchboxJetMatcher:Factory /Herwig/MatrixElements/Matchbox/DISFactory
+
## Cut on lepton pair invariant mass
# set MassCut:MinM 66*GeV
# set MassCut:MaxM 116*GeV
## Cuts on jets
# set JetFinder:Variant SphericalKt
# set JetFinder:RecombinationScheme E
# set JetFinder:Mode Inclusive
# set JetFinder:ConeRadius 0.7
# insert JetCuts:JetRegions 0 FirstJet
# insert JetCuts:JetRegions 1 SecondJet
# insert JetCuts:JetRegions 1 ThirdJet
# set DISCuts:JetFinder JetFinder
# insert DISCuts:MultiCuts 0 JetCuts
##################################################
## Matrix Elements
##################################################
## Builtin matrix elements are available for a small range of processes
## such as V, V+j, gg -> h0 and do not require further modifaction
## below.
cd /Herwig/MatrixElements/Matchbox/Amplitudes
##################################################
## Generic Procsses
##################################################
## Enable generic processes
# clear /Herwig/MatrixElements/Matchbox/DISFactory:Amplitudes
# insert /Herwig/MatrixElements/Matchbox/DISFactory:Amplitudes 0 GenericProcesses
## Choose a tree-level provider
## MadGraph : requires --with-madgraph
# set GenericProcesses:TreeLevelAmplitude MadGraph
## Choose a one-loop provider
## GoSam : requires --with-gosam and --with-gosam-contrib
# set GenericProcesses:OneLoopAmplitude GoSam
## NJet : requires --with-njet
# set GenericProcesses:OneLoopAmplitude NJet
## OpenLoops : requires --with-openloops
# set GenericProcesses:OneLoopAmplitude OpenLoops
##################################################
## LO or parts of NLO Calculations
##################################################
# cd /Herwig/MatrixElements/Matchbox
# set DISFactory:VirtualContributions Off
# set DISFactory:RealContributions Off
##################################################
## Matching
##################################################
cd /Herwig/MatrixElements/Matchbox
## MC@NLO-type next-to-leading order for use with default shower
set DISFactory:ShowerApproximation QTildeMatching
set /Herwig/Shower/Evolver:HardVetoScaleSource Read
set /Herwig/Shower/Evolver:MECorrMode No
cd /Herwig/MatrixElements/Matchbox
## MC@NLO-type next-to-leading order for use with dipole shower
# set DISFactory:ShowerApproximation DipoleMatching
# cd /Herwig/EventHandlers
# set DISHandler:CascadeHandler /Herwig/DipoleShower/DipoleShowerHandler
# set /Herwig/DipoleShower/DipoleShowerHandler:MaxPtIsMuF Yes
# set DISHandler:CascadeHandler:MPIHandler NULL
# read DipoleShowerParameters.in
# cd /Herwig/MatrixElements/Matchbox
## POWHEG-type next-to-leading order
# set DISFactory:ShowerApproximation MEMatching
# set MECorrectionHandler:Factory DISFactory
# cd /Herwig/Generators
# insert DISGenerator:EventHandler:PostSubProcessHandlers[0] /Herwig/MatrixElements/Matchbox/MECorrectionHandler
# cd /Herwig/MatrixElements/Matchbox
##################################################
## Scales variations
##################################################
cd /Herwig/MatrixElements/Matchbox
## Scale choice
set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 91.2*GeV
set DISFactory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale
# set DISFactory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPtScale
# set DISFactory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/MaxptScale
# set DISFactory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/HTScale
# set DISFactory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonMassScale
## Hard process scale variation
set DISFactory:RenormalizationScaleFactor 1.0
set DISFactory:FactorizationScaleFactor 1.0
## Matching scale variation for MEMatching
## - other scale factors are deduced from the shower handlers
set MEMatching:RenormalizationScaleFactor 1.0
set MEMatching:FactorizationScaleFactor 1.0
## Shower scale variations
set /Herwig/DipoleShower/DipoleShowerHandler:RenormalizationScaleFactor 1.0
set /Herwig/DipoleShower/DipoleShowerHandler:FactorizationScaleFactor 1.0
set /Herwig/DipoleShower/DipoleShowerHandler:HardScaleFactor 1.0
set /Herwig/Shower/ShowerHandler:RenormalizationScaleFactor 1.0
set /Herwig/Shower/ShowerHandler:FactorizationScaleFactor 1.0
set /Herwig/Shower/ShowerHandler:HardScaleFactor 1.0
# switch off final-state electron/muon FSR
do /Herwig/Shower/SplittingGenerator:DeleteFinalSplitting e-->e-,gamma; /Herwig/Shower/LtoLGammaSudakov
do /Herwig/Shower/SplittingGenerator:DeleteFinalSplitting mu-->mu-,gamma; /Herwig/Shower/LtoLGammaSudakov
do /Herwig/Shower/SplittingGenerator:DeleteFinalSplitting tau-->tau-,gamma; /Herwig/Shower/LtoLGammaSudakov
##################################################
## Analyses
##################################################
## Rivet Analyses:
## requires installation of Rivet and --with-rivet while installing
## ThePEG please use NLORivetAnalysis for plain NLO runs
# cd /Herwig/Analysis
# create ThePEG::RivetAnalysis RivetAnalysis RivetAnalysis.so
# create ThePEG::NLORivetAnalysis RivetAnalysis RivetAnalysis.so
# insert /Herwig/Generators/DISGenerator:AnalysisHandlers 0 RivetAnalysis
# Energy flow in DIS:
# insert RivetAnalysis:Analyses 0 H1_2000_S4129130
# Energy flow and charged particle spectra in DIS:
# insert RivetAnalysis:Analyses 0 H1_1994_S2919893
##################################################
## Cleanup
##################################################
## Change only if you know what you are doing.
## For the moment, we only deal with massless partons
cd /Herwig/Particles
set d:NominalMass 0*GeV
set dbar:NominalMass 0*GeV
set u:NominalMass 0*GeV
set ubar:NominalMass 0*GeV
set s:NominalMass 0*GeV
set sbar:NominalMass 0*GeV
set c:NominalMass 0*GeV
set cbar:NominalMass 0*GeV
set b:NominalMass 0*GeV
set bbar:NominalMass 0*GeV
set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV
set /Herwig/Generators/DISGenerator:EventHandler:CollisionCuts Off
##################################################
## Parallel integration
##################################################
## uncomment if you want parallel integration for the adaption of grids
# cd /Herwig/Samplers
# set Sampler:ParallelIntegration Yes
# set Sampler:IntegratePerJob 10
##################################################
## Save the generator
##################################################
do /Herwig/MatrixElements/Matchbox/DISFactory:ProductionMode
cd /Herwig/Generators
saverun DIS-Matchbox DISGenerator
diff --git a/src/LEP-Matchbox.in b/src/LEP-Matchbox.in
--- a/src/LEP-Matchbox.in
+++ b/src/LEP-Matchbox.in
@@ -1,224 +1,226 @@
##################################################
## Herwig++/Matchbox example input file
##################################################
##################################################
## Technical parameters for this run
##################################################
cd /Herwig/Generators
set LEPGenerator:RandomNumberGenerator:Seed 31122001
set LEPGenerator:DebugLevel 1
set LEPGenerator:PrintEvent 10
set LEPGenerator:MaxErrors 10000
set LEPGenerator:NumberOfEvents 100000000
cd /Herwig/EventHandlers
set LEPHandler:Weighted Off
set LEPHandler:Sampler /Herwig/Samplers/Sampler
set LEPHandler:CascadeHandler:MPIHandler NULL
##################################################
## beam energy sqrt(s) = 91.2 GeV!
##################################################
set /Herwig/EventHandlers/LEPHandler:LuminosityFunction:Energy 91.2*GeV
cd /Herwig/MatrixElements/Matchbox
insert /Herwig/Generators/LEPGenerator:EventHandler:SubProcessHandlers[0] EEFactory
##################################################
## 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. NLO
## matched simulations are generated by default, as long as virtual
## corrections are available.
## Set the order of the couplings
cd /Herwig/MatrixElements/Matchbox
set EEFactory:OrderInAlphaS 0
set EEFactory:OrderInAlphaEW 2
## Select the process
## You may use identifiers such as p, pbar, j, l, mu+, h0 etc.
do EEFactory:Process e- e+ j j
##################################################
## Cut Selection
##################################################
## For finite calculations make resonable cuts! Check the wiki and manual
## for other cut options and different jet algorithms.
cd /Herwig/Cuts
+set MatchboxJetMatcher:Factory /Herwig/MatrixElements/Matchbox/EEFactory
+
## Cut on lepton pair invariant mass
# set MassCut:MinM 66*GeV
# set MassCut:MaxM 116*GeV
## Cuts on jets
# set JetFinder:Variant SphericalKt
# set JetFinder:RecombinationScheme E
# set JetFinder:Mode Exclusive
# set JetFinder:ConeRadius 6.283185307
# set JetFinder:DCut 50*GeV2
# set NJetsCut:NJetsMin 3
# set EECuts:JetFinder JetFinder
# insert EECuts:MultiCuts 0 NJetsCut
##################################################
## Matrix Elements
##################################################
## Builtin matrix elements are available for a small range of processes
## such as e+ e- -> 2..4 jets (4 jets leading order only) and do not
## require modifaction.
cd /Herwig/MatrixElements/Matchbox/Amplitudes
##################################################
## Generic Procsses
##################################################
## Enable generic processes
# clear /Herwig/MatrixElements/Matchbox/EEFactory:Amplitudes
# insert /Herwig/MatrixElements/Matchbox/EEFactory:Amplitudes 0 GenericProcesses
## Choose a tree-level provider
## MadGraph : requires --with-madgraph
# set GenericProcesses:TreeLevelAmplitude MadGraph
## Choose a one-loop provider
## GoSam : requires --with-gosam and --with-gosam-contrib
# set GenericProcesses:OneLoopAmplitude GoSam
## NJet : requires --with-njet
# set GenericProcesses:OneLoopAmplitude NJet
## OpenLoops : requires --with-openloops
# set GenericProcesses:OneLoopAmplitude OpenLoops
##################################################
## LO or parts of NLO Calculations
##################################################
# cd /Herwig/MatrixElements/Matchbox
# set EEFactory:VirtualContributions Off
# set EEFactory:RealContributions Off
##################################################
## Matching
##################################################
cd /Herwig/MatrixElements/Matchbox
## MC@NLO-type next-to-leading order for use with default shower
set EEFactory:ShowerApproximation QTildeMatching
set /Herwig/Shower/Evolver:HardVetoScaleSource Read
set /Herwig/Shower/Evolver:MECorrMode No
## MC@NLO-type next-to-leading order for use with dipole shower
# set EEFactory:ShowerApproximation DipoleMatching
# cd /Herwig/EventHandlers
# set LEPHandler:CascadeHandler /Herwig/DipoleShower/DipoleShowerHandler
# set /Herwig/DipoleShower/DipoleShowerHandler:MaxPtIsMuF Yes
# set LEPHandler:CascadeHandler:MPIHandler NULL
# read DipoleShowerParameters.in
# cd /Herwig/MatrixElements/Matchbox
## POWHEG-type next-to-leading order
# set EEFactory:ShowerApproximation MEMatching
# set MECorrectionHandler:Factory EEFactory
# cd /Herwig/Generators
# insert LEPGenerator:EventHandler:PostSubProcessHandlers[0] /Herwig/MatrixElements/Matchbox/MECorrectionHandler
##################################################
## Scales variations
##################################################
cd /Herwig/MatrixElements/Matchbox
## Scale choice
set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 91.2*GeV
set EEFactory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale
# set EEFactory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPtScale
# set EEFactory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/MaxptScale
# set EEFactory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/HTScale
# set EEFactory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonMassScale
## Hard process scale variation
set EEFactory:RenormalizationScaleFactor 1.0
set EEFactory:FactorizationScaleFactor 1.0
## Matching scale variation for MEMatching
## - other scale factors are deduced from the shower handlers
set MEMatching:RenormalizationScaleFactor 1.0
set MEMatching:FactorizationScaleFactor 1.0
## Shower scale variations
set /Herwig/DipoleShower/DipoleShowerHandler:RenormalizationScaleFactor 1.0
set /Herwig/DipoleShower/DipoleShowerHandler:FactorizationScaleFactor 1.0
set /Herwig/DipoleShower/DipoleShowerHandler:HardScaleFactor 1.0
set /Herwig/Shower/ShowerHandler:RenormalizationScaleFactor 1.0
set /Herwig/Shower/ShowerHandler:FactorizationScaleFactor 1.0
set /Herwig/Shower/ShowerHandler:HardScaleFactor 1.0
##################################################
## Analyses
##################################################
## Rivet Analyses:
## requires installation of Rivet and --with-rivet while installing
## ThePEG please use NLORivetAnalysis for plain NLO runs
# cd /Herwig/Analysis
# create ThePEG::RivetAnalysis RivetAnalysis RivetAnalysis.so
# create ThePEG::NLORivetAnalysis RivetAnalysis RivetAnalysis.so
# insert /Herwig/Generators/LEPGenerator:AnalysisHandlers 0 RivetAnalysis
# insert RivetAnalysis:Analyses 0 MC_JETS
# Studies of QCD:
# insert RivetAnalysis:Analyses 0 ALEPH_1996_S3486095
# Event shapes and identified particles:
# insert RivetAnalysis:Analyses 0 DELPHI_1996_S3430090
##################################################
## Cleanup
##################################################
## Change only if you know what you are doing.
## For the moment, we only deal with massless partons
cd /Herwig/Particles
set d:NominalMass 0*GeV
set dbar:NominalMass 0*GeV
set u:NominalMass 0*GeV
set ubar:NominalMass 0*GeV
set s:NominalMass 0*GeV
set sbar:NominalMass 0*GeV
set c:NominalMass 0*GeV
set cbar:NominalMass 0*GeV
set b:NominalMass 0*GeV
set bbar:NominalMass 0*GeV
set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV
set /Herwig/Generators/LEPGenerator:EventHandler:CollisionCuts Off
##################################################
## Parallel integration
##################################################
## uncomment if you want parallel integration for the adaption of grids
# cd /Herwig/Samplers
# set Sampler:ParallelIntegration Yes
# set Sampler:IntegratePerJob 10
##################################################
## Save the generator
##################################################
do /Herwig/MatrixElements/Matchbox/EEFactory:ProductionMode
cd /Herwig/Generators
saverun LEP-Matchbox LEPGenerator
diff --git a/src/LHC-Matchbox.in b/src/LHC-Matchbox.in
--- a/src/LHC-Matchbox.in
+++ b/src/LHC-Matchbox.in
@@ -1,269 +1,271 @@
##################################################
## Herwig++/Matchbox example input file
##################################################
##################################################
## Technical parameters for this run
##################################################
cd /Herwig/Generators
set LHCGenerator:RandomNumberGenerator:Seed 31122001
set LHCGenerator:DebugLevel 1
set LHCGenerator:PrintEvent 10
set LHCGenerator:MaxErrors 10000
set LHCGenerator:NumberOfEvents 100000000
cd /Herwig/EventHandlers
set LHCHandler:Weighted Off
set LHCHandler:Sampler /Herwig/Samplers/Sampler
##################################################
## beam energy sqrt(s) = 8 TeV!
##################################################
set /Herwig/EventHandlers/LHCHandler:LuminosityFunction:Energy 8000.0*GeV
cd /Herwig/MatrixElements/Matchbox
insert /Herwig/Generators/LHCGenerator:EventHandler:SubProcessHandlers[0] PPFactory
##################################################
## PDF choice
##################################################
cd /Herwig/Partons
create ThePEG::LHAPDF PDFSet ThePEGLHAPDF.so
set PDFSet:RemnantHandler HadronRemnants
set /Herwig/Partons/PDFSet:PDFName CT10.LHgrid
set /Herwig/Particles/p+:PDF PDFSet
set /Herwig/Particles/pbar-:PDF PDFSet
##################################################
## 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. NLO
## matched simulations are generated by default, as long as virtual
## corrections are available.
## Set the order of the couplings
cd /Herwig/MatrixElements/Matchbox
set PPFactory:OrderInAlphaS 0
set PPFactory:OrderInAlphaEW 2
## Select the process
## You may use identifiers such as p, pbar, j, l, mu+, h0 etc.
do PPFactory:Process p p e+ e-
##################################################
## Cut Selection
##################################################
## For finite calculations make resonable cuts! Check the wiki and manual
## for other cut options and different jet algorithms.
cd /Herwig/Cuts
+set MatchboxJetMatcher:Factory /Herwig/MatrixElements/Matchbox/PPFactory
+
## Cut on lepton pair invariant mass
set MassCut:MinM 66*GeV
set MassCut:MaxM 116*GeV
## Cuts on jets
# set QCDCuts:JetFinder JetFinder
# insert QCDCuts:MultiCuts 0 JetCuts
# insert JetCuts:JetRegions 0 FirstJet
# insert JetCuts:JetRegions 1 SecondJet
##################################################
## Matrix Elements
##################################################
## Builtin matrix elements are available for a small range of processes
## such as V, V+j, gg -> h0 and do not require further modifaction
## below.
cd /Herwig/MatrixElements/Matchbox/Amplitudes
##################################################
## Generic Procsses
##################################################
## Enable generic processes
# clear /Herwig/MatrixElements/Matchbox/PPFactory:Amplitudes
# insert /Herwig/MatrixElements/Matchbox/PPFactory:Amplitudes 0 GenericProcesses
## Choose a tree-level provider
## MadGraph : requires --with-madgraph
# set GenericProcesses:TreeLevelAmplitude MadGraph
## Choose a one-loop provider
## GoSam : requires --with-gosam and --with-gosam-contrib
# set GenericProcesses:OneLoopAmplitude GoSam
# Note: If you want to calculate NLO corrections in the
# Higgs Effective Model (smehc) with GoSam virtual
# Amplitudes and MadGraph TreeLevelAmplitude:
# set GoSam:HiggsEff On
# set MadGraph:Model heft
## NJet : requires --with-njet
# set GenericProcesses:OneLoopAmplitude NJet
## OpenLoops : requires --with-openloops
# set GenericProcesses:OneLoopAmplitude OpenLoops
##################################################
## Specialized packages
##################################################
## enable HJets++ : requires installation of HJets++
# clear /Herwig/MatrixElements/Matchbox/PPFactory:Amplitudes
# library HJets.so
# read HJetsProcesses.in
## enable VBFNLO : requires --with-vbfnlo
# clear /Herwig/MatrixElements/Matchbox/PPFactory:Amplitudes
# insert /Herwig/MatrixElements/Matchbox/PPFactory:Amplitudes 0 VBFNLOProcesses
## need to restrict topologies according to VBF approximation,
## see the manual for details; here we only consider VBF Higgs production,
## allowing for only spacelike (t-channel) EW boson propagators
# cd /Herwig/MatrixElements/Matchbox
# insert PPFactory:DiagramGenerator:RestrictLines /Herwig/Particles/Z0
# insert PPFactory:DiagramGenerator:RestrictLines /Herwig/Particles/Wplus
# insert PPFactory:DiagramGenerator:RestrictLines /Herwig/Particles/Wminus
# do PPFactory:DiagramGenerator:TimeLikeRange 0 0
##################################################
## LO or parts of NLO Calculations
##################################################
# cd /Herwig/MatrixElements/Matchbox
# set PPFactory:VirtualContributions Off
# set PPFactory:RealContributions Off
##################################################
## Matching
##################################################
cd /Herwig/MatrixElements/Matchbox
## MC@NLO-type next-to-leading order for use with default shower
set PPFactory:ShowerApproximation QTildeMatching
set /Herwig/Shower/Evolver:HardVetoScaleSource Read
set /Herwig/Shower/Evolver:MECorrMode No
## MC@NLO-type next-to-leading order for use with dipole shower
# set PPFactory:ShowerApproximation DipoleMatching
# cd /Herwig/EventHandlers
# set LHCHandler:CascadeHandler /Herwig/DipoleShower/DipoleShowerHandler
# set /Herwig/DipoleShower/DipoleShowerHandler:MaxPtIsMuF Yes
# read DipoleShowerParameters.in
# cd /Herwig/MatrixElements/Matchbox
## POWHEG-type next-to-leading order
# set PPFactory:ShowerApproximation MEMatching
# set MECorrectionHandler:Factory PPFactory
# cd /Herwig/Generators
# insert LHCGenerator:EventHandler:PostSubProcessHandlers[0] /Herwig/MatrixElements/Matchbox/MECorrectionHandler
# cd /Herwig/MatrixElements/Matchbox
## include truncated angular-ordered shower
# set /Herwig/Shower/PowhegShowerHandler:Factory PPFactory
# set /Herwig/EventHandlers/LHCHandler:CascadeHandler /Herwig/Shower/PowhegShowerHandler
# set /Herwig/MatrixElements/Matchbox/MEMatching:TruncatedShower Yes
# set /Herwig/Shower/Evolver:HardEmissionMode MatchboxPOWHEG
##################################################
## Scales variations
##################################################
cd /Herwig/MatrixElements/Matchbox
## Scale choice
set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 91.2*GeV
set PPFactory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale
# set PPFactory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonPtScale
# set PPFactory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/MaxptScale
# set PPFactory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/HTScale
# set PPFactory:ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/LeptonMassScale
## Hard process scale variation
set PPFactory:RenormalizationScaleFactor 1.0
set PPFactory:FactorizationScaleFactor 1.0
## Matching scale variation for MEMatching
## - other scale factors are deduced from the shower handlers
set MEMatching:RenormalizationScaleFactor 1.0
set MEMatching:FactorizationScaleFactor 1.0
## Shower scale variations
set /Herwig/DipoleShower/DipoleShowerHandler:RenormalizationScaleFactor 1.0
set /Herwig/DipoleShower/DipoleShowerHandler:FactorizationScaleFactor 1.0
set /Herwig/DipoleShower/DipoleShowerHandler:HardScaleFactor 1.0
set /Herwig/Shower/ShowerHandler:RenormalizationScaleFactor 1.0
set /Herwig/Shower/ShowerHandler:FactorizationScaleFactor 1.0
set /Herwig/Shower/ShowerHandler:HardScaleFactor 1.0
##################################################
## Analyses
##################################################
## Rivet Analyses:
## requires installation of Rivet and --with-rivet while installing
## ThePEG please use NLORivetAnalysis for plain NLO runs
# cd /Herwig/Analysis
# create ThePEG::RivetAnalysis RivetAnalysis RivetAnalysis.so
# create ThePEG::NLORivetAnalysis RivetAnalysis RivetAnalysis.so
# insert /Herwig/Generators/LHCGenerator:AnalysisHandlers 0 RivetAnalysis
# insert RivetAnalysis:Analyses 0 MC_ZINC
# insert RivetAnalysis:Analyses 0 MC_ZJETS
# insert RivetAnalysis:Analyses 0 MC_ZKTSPLITTINGS
## Z+jets in pp at 7 TeV:
# insert RivetAnalysis:Analyses 0 ATLAS_2011_I945498
## Measurement of the Z pT with electrons and muons at 7 TeV:
# insert RivetAnalysis:Analyses 0 ATLAS_2011_S9131140
##################################################
## Cleanup
##################################################
## Change only if you know what you are doing.
## For the moment, we only deal with massless partons
cd /Herwig/Particles
set d:NominalMass 0*GeV
set dbar:NominalMass 0*GeV
set u:NominalMass 0*GeV
set ubar:NominalMass 0*GeV
set s:NominalMass 0*GeV
set sbar:NominalMass 0*GeV
set c:NominalMass 0*GeV
set cbar:NominalMass 0*GeV
set b:NominalMass 0*GeV
set bbar:NominalMass 0*GeV
set /Herwig/Cuts/JetKtCut:MinKT 0.0*GeV
set /Herwig/Cuts/QCDCuts:MHatMin 0.0*GeV
set /Herwig/Generators/LHCGenerator:EventHandler:CollisionCuts Off
##################################################
## Parallel integration
##################################################
## uncomment if you want parallel integration for the adaption of grids
# cd /Herwig/Samplers
# set Sampler:ParallelIntegration Yes
# set Sampler:IntegratePerJob 10
##################################################
## Save the generator
##################################################
do /Herwig/MatrixElements/Matchbox/PPFactory:ProductionMode
cd /Herwig/Generators
saverun LHC-Matchbox LHCGenerator
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,720 +1,780 @@
################################################################################
#
# 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
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
################################################################################
# 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
################################################################################
# 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
+@DO_MADGRAPH@ MadGraph:Massless 11
+@DO_MADGRAPH@ MadGraph:Massless -11
+@DO_MADGRAPH@ MadGraph:Massless 12
+@DO_MADGRAPH@ MadGraph:Massless -12
+@DO_MADGRAPH@ MadGraph:Massless 13
+@DO_MADGRAPH@ MadGraph:Massless -13
+@DO_MADGRAPH@ MadGraph:Massless 14
+@DO_MADGRAPH@ MadGraph:Massless -14
+@DO_MADGRAPH@ MadGraph:Massless 16
+@DO_MADGRAPH@ MadGraph:Massless -16
+
@LOAD_GOSAM@ HwMatchboxGoSam.so
@CREATE_GOSAM@ Herwig::GoSamAmplitude GoSam
+@DO_GOSAM@ GoSam:Massless 11
+@DO_GOSAM@ GoSam:Massless -11
+@DO_GOSAM@ GoSam:Massless 12
+@DO_GOSAM@ GoSam:Massless -12
+@DO_GOSAM@ GoSam:Massless 13
+@DO_GOSAM@ GoSam:Massless -13
+@DO_GOSAM@ GoSam:Massless 14
+@DO_GOSAM@ GoSam:Massless -14
+@DO_GOSAM@ GoSam:Massless 16
+@DO_GOSAM@ GoSam:Massless -16
+
@LOAD_NJET@ HwMatchboxNJet.so
@CREATE_NJET@ Herwig::NJetsAmplitude NJet
+@DO_NJET@ NJet:Massless 11
+@DO_NJET@ NJet:Massless -11
+@DO_NJET@ NJet:Massless 12
+@DO_NJET@ NJet:Massless -12
+@DO_NJET@ NJet:Massless 13
+@DO_NJET@ NJet:Massless -13
+@DO_NJET@ NJet:Massless 14
+@DO_NJET@ NJet:Massless -14
+@DO_NJET@ NJet:Massless 16
+@DO_NJET@ NJet:Massless -16
+
@LOAD_OPENLOOPS@ HwMatchboxOpenLoops.so
@CREATE_OPENLOOPS@ Herwig::OpenLoopsAmplitude OpenLoops
+@DO_OPENLOOPS@ OpenLoops:Massless 11
+@DO_OPENLOOPS@ OpenLoops:Massless -11
+@DO_OPENLOOPS@ OpenLoops:Massless 12
+@DO_OPENLOOPS@ OpenLoops:Massless -12
+@DO_OPENLOOPS@ OpenLoops:Massless 13
+@DO_OPENLOOPS@ OpenLoops:Massless -13
+@DO_OPENLOOPS@ OpenLoops:Massless 14
+@DO_OPENLOOPS@ OpenLoops:Massless -14
+@DO_OPENLOOPS@ OpenLoops:Massless 16
+@DO_OPENLOOPS@ OpenLoops:Massless -16
+
@LOAD_VBFNLO@ HwMatchboxVBFNLO.so
@CREATE_VBFNLO@ Herwig::VBFNLOAmplitude VBFNLOProcesses
+@DO_VBFNLO@ VBFNLOProcesses:Massless 11
+@DO_VBFNLO@ VBFNLOProcesses:Massless -11
+@DO_VBFNLO@ VBFNLOProcesses:Massless 12
+@DO_VBFNLO@ VBFNLOProcesses:Massless -12
+@DO_VBFNLO@ VBFNLOProcesses:Massless 13
+@DO_VBFNLO@ VBFNLOProcesses:Massless -13
+@DO_VBFNLO@ VBFNLOProcesses:Massless 14
+@DO_VBFNLO@ VBFNLOProcesses:Massless -14
+@DO_VBFNLO@ VBFNLOProcesses:Massless 15
+@DO_VBFNLO@ VBFNLOProcesses:Massless -15
+@DO_VBFNLO@ VBFNLOProcesses:Massless 16
+@DO_VBFNLO@ VBFNLOProcesses:Massless -16
+
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 utilities for matching
################################################################################
cd /Herwig/MatrixElements/Matchbox
create Herwig::MEMatching MEMatching
set MEMatching:RestrictPhasespace On
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:MaxPtIsMuF Yes
set MEMatching:FFPtCut 1.0*GeV
set MEMatching:FIPtCut 1.0*GeV
set MEMatching:IIPtCut 1.0*GeV
create Herwig::ShowerApproximationGenerator MECorrectionHandler
set MECorrectionHandler:ShowerApproximation MEMatching
create Herwig::FlatInvertiblePhasespace InvertiblePhasespace
set MECorrectionHandler:Phasespace InvertiblePhasespace
set MECorrectionHandler:FreezeGrid 100000
create Herwig::DipoleMatching DipoleMatching HwDipoleMatching.so
set DipoleMatching:RestrictPhasespace On
set DipoleMatching:BornScaleInSubtraction BornScale
set DipoleMatching:RealEmissionScaleInSubtraction BornScale
set DipoleMatching:EmissionScaleInSubtraction BornScale
set DipoleMatching:MaxPtIsMuF Yes
set DipoleMatching:FFPtCut 1.014259*GeV
set DipoleMatching:FIPtCut 1.0*GeV
set DipoleMatching:IIPtCut 1.0*GeV
create Herwig::QTildeMatching QTildeMatching HwQTildeMatching.so
set QTildeMatching:ShowerHandler /Herwig/Shower/ShowerHandler
# set this to off, if the shower pt veto is off
set QTildeMatching:RestrictPhasespace On
set QTildeMatching:BornScaleInSubtraction BornScale
set QTildeMatching:RealEmissionScaleInSubtraction BornScale
set QTildeMatching:EmissionScaleInSubtraction BornScale
set QTildeMatching:QTildeFinder /Herwig/Shower/PartnerFinder
set QTildeMatching:MaxPtIsMuF Yes
# 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/FFWDiagonalVertex
set /Herwig/Vertices/FFWDiagonalVertex:Diagonal Yes
insert DiagramGenerator:Vertices 0 /Herwig/Vertices/FFWDiagonalVertex
insert DiagramGenerator:Vertices 0 /Herwig/Vertices/WWHVertex
insert DiagramGenerator:Vertices 0 /Herwig/Vertices/WWWVertex
insert DiagramGenerator:Vertices 0 /Herwig/Vertices/FFHVertex
insert DiagramGenerator:Vertices 0 /Herwig/Vertices/HGGVertex
insert DiagramGenerator:Vertices 0 /Herwig/Vertices/HHHVertex
insert DiagramGenerator:ExcludeInternal 0 /Herwig/Particles/h0
create Herwig::ProcessData ProcessData
set /Herwig/MatrixElements/Matchbox/Factory:DiagramGenerator DiagramGenerator
set /Herwig/MatrixElements/Matchbox/Factory:ProcessData ProcessData
################################################################################
# Setup phasespace generators
################################################################################
cd /Herwig/MatrixElements/Matchbox
mkdir Phasespace
cd Phasespace
create Herwig::MatchboxRambo Rambo
create Herwig::FlatInvertiblePhasespace DetPhasespace
create Herwig::TreePhasespaceChannels TreePhasespaceChannels
create Herwig::TreePhasespace TreePhasespace
set TreePhasespace:ChannelMap TreePhasespaceChannels
set TreePhasespace:M0 0.0001*GeV
set TreePhasespace:MC 0.0000001*GeV
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
set /Herwig/MatrixElements/Matchbox/Factory:Phasespace TreePhasespace
################################################################################
# Setup jet cuts
################################################################################
cd /Herwig/Cuts
+create Herwig::MatchboxFactoryMatcher MatchboxJetMatcher
+set MatchboxJetMatcher:Group j
+
create ThePEG::FastJetFinder JetFinder
-set JetFinder:UnresolvedMatcher /Herwig/Matchers/StandardQCDParton
+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::NJetsCut NJetsCut
-set NJetsCut:UnresolvedMatcher /Herwig/Matchers/StandardQCDParton
+set NJetsCut:UnresolvedMatcher MatchboxJetMatcher
set NJetsCut:NJetsMin 2
create ThePEG::JetCuts JetCuts
-set JetCuts:UnresolvedMatcher /Herwig/Matchers/StandardQCDParton
+set JetCuts:UnresolvedMatcher MatchboxJetMatcher
set JetCuts:Ordering OrderPt
create Herwig::FrixionePhotonSeparationCut FrixionePhotonSeparationCut
create Herwig::IdentifiedParticleCut IdentifiedParticleCut
create Herwig::MatchboxDeltaRCut MatchboxDeltaRCut
create Herwig::MissingPtCut MissingPtCut
################################################################################
# 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 MaxptScale
set MaxptScale:JetFinder /Herwig/Cuts/JetFinder
create Herwig::MatchboxLeptonMassScale LeptonMassScale
create Herwig::MatchboxLeptonPtScale LeptonPtScale
create Herwig::MatchboxHtScale HTScale
create Herwig::MatchboxTopMassScale TopMassScale
create Herwig::MatchboxTopMTScale TopMTScale
create Herwig::MatchboxTopMinMTScale TopMinMTScale
set HTScale:JetFinder /Herwig/Cuts/JetFinder
set HTScale:IncludeMT No
set /Herwig/MatrixElements/Matchbox/Factory:ScaleChoice LeptonMassScale
################################################################################
# AlphaS
################################################################################
cd /Herwig/MatrixElements/Matchbox
mkdir AlphaS
cd AlphaS
create Herwig::O2AlphaS NLOAlphaS
insert NLOAlphaS:QuarkMasses[0] 0.005
insert NLOAlphaS:QuarkMasses[1] 0.0023
insert NLOAlphaS:QuarkMasses[2] 0.095
insert NLOAlphaS:QuarkMasses[3] 1.25
insert NLOAlphaS:QuarkMasses[4] 4.2
insert NLOAlphaS:QuarkMasses[5] 174.2
create ThePEG::O1AlphaS LOAlphaS O1AlphaS.so
insert LOAlphaS:QuarkMasses[0] 0.005
insert LOAlphaS:QuarkMasses[1] 0.0023
insert LOAlphaS:QuarkMasses[2] 0.095
insert LOAlphaS:QuarkMasses[3] 1.25
insert LOAlphaS:QuarkMasses[4] 4.2
insert LOAlphaS:QuarkMasses[5] 174.2
library HwDipoleShowerAlphaS.so
create matchbox::nlo_alpha_s MatchboxNLOAlphaS
set MatchboxNLOAlphaS:exact_evaluation large_scale
set MatchboxNLOAlphaS:freezing_scale 0.0*GeV
set MatchboxNLOAlphaS:min_active_flavours 3
set MatchboxNLOAlphaS:max_active_flavours 6
set MatchboxNLOAlphaS:input_scale 91.188*GeV
set MatchboxNLOAlphaS:input_alpha_s 0.1271103
insert MatchboxNLOAlphaS:QuarkMasses[0] 0.005
insert MatchboxNLOAlphaS:QuarkMasses[1] 0.0023
insert MatchboxNLOAlphaS:QuarkMasses[2] 0.095
insert MatchboxNLOAlphaS:QuarkMasses[3] 1.25
insert MatchboxNLOAlphaS:QuarkMasses[4] 4.2
insert MatchboxNLOAlphaS:QuarkMasses[5] 174.2
create matchbox::lo_alpha_s MatchboxLOAlphaS
set MatchboxLOAlphaS:freezing_scale 0.0*GeV
set MatchboxLOAlphaS:min_active_flavours 3
set MatchboxLOAlphaS:max_active_flavours 6
set MatchboxLOAlphaS:input_scale 91.188*GeV
set MatchboxLOAlphaS:input_alpha_s 0.1283827
insert MatchboxLOAlphaS:QuarkMasses[0] 0.005
insert MatchboxLOAlphaS:QuarkMasses[1] 0.0023
insert MatchboxLOAlphaS:QuarkMasses[2] 0.095
insert MatchboxLOAlphaS:QuarkMasses[3] 1.25
insert MatchboxLOAlphaS:QuarkMasses[4] 4.2
insert MatchboxLOAlphaS:QuarkMasses[5] 174.2
################################################################################
# Factories for different colliders
################################################################################
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 /
diff --git a/src/defaults/Shower.in b/src/defaults/Shower.in
--- a/src/defaults/Shower.in
+++ b/src/defaults/Shower.in
@@ -1,281 +1,282 @@
############################################################
# Setup of default parton shower
#
# Useful switches for users are marked near the top of
# this file.
#
# Don't edit this file directly, but reset the switches
# in your own input files!
############################################################
library HwMPI.so
library HwShower.so
library HwMatching.so
mkdir /Herwig/Shower
cd /Herwig/Shower
create Herwig::ShowerHandler ShowerHandler
newdef ShowerHandler:MPIHandler /Herwig/UnderlyingEvent/MPIHandler
newdef ShowerHandler:RemDecayer /Herwig/Partons/RemnantDecayer
#####################################
# initial setup, don't change these!
#####################################
create Herwig::SplittingGenerator SplittingGenerator
create Herwig::ShowerAlphaQCD AlphaQCD
create Herwig::ShowerAlphaQED AlphaQED
create Herwig::Evolver Evolver
create Herwig::QTildeModel ShowerModel
create Herwig::QTildeFinder PartnerFinder
newdef PartnerFinder:PartnerMethod 1
newdef PartnerFinder:ScaleChoice 1
create Herwig::QTildeReconstructor KinematicsReconstructor
newdef KinematicsReconstructor:ReconstructionOption Colour
newdef KinematicsReconstructor:InitialInitialBoostOption LongTransBoost
newdef /Herwig/Partons/RemnantDecayer:AlphaS AlphaQCD
newdef /Herwig/Partons/RemnantDecayer:AlphaEM AlphaQED
newdef ShowerHandler:Evolver Evolver
newdef ShowerModel:PartnerFinder PartnerFinder
newdef ShowerModel:KinematicsReconstructor KinematicsReconstructor
newdef Evolver:ShowerModel ShowerModel
newdef Evolver:SplittingGenerator SplittingGenerator
newdef Evolver:Interactions BothAtOnce
newdef Evolver:SpinCorrelations Yes
newdef Evolver:SoftCorrelations Singular
##################################################################
# Intrinsic pT
#
# Recommended:
# 1.9 GeV for Tevatron W/Z production.
# 2.1 GeV for LHC W/Z production at 10 TeV
# 2.2 GeV for LHC W/Z production at 14 TeV
#
# Set all parameters to 0 to disable
##################################################################
newdef Evolver:IntrinsicPtGaussian 1.9*GeV
newdef Evolver:IntrinsicPtBeta 0
newdef Evolver:IntrinsicPtGamma 0*GeV
newdef Evolver:IntrinsicPtIptmax 0*GeV
#############################################################
# Main control switches for the parton shower.
#############################################################
newdef SplittingGenerator:ISR Yes
newdef SplittingGenerator:FSR Yes
#############################################################
# Set up truncated shower handler.
#############################################################
create Herwig::PowhegShowerHandler PowhegShowerHandler
set PowhegShowerHandler:MPIHandler /Herwig/UnderlyingEvent/MPIHandler
set PowhegShowerHandler:RemDecayer /Herwig/Partons/RemnantDecayer
set PowhegShowerHandler:Evolver /Herwig/Shower/Evolver
#############################################################
#############################################################
# End of interesting user servicable section.
#
# Anything that follows below should only be touched if you
# know what you're doing.
#
# Really.
#############################################################
#
# a few default values
newdef Evolver:MECorrMode 1
newdef AlphaQCD:ScaleFactor 1.0
newdef AlphaQCD:NPAlphaS 2
newdef AlphaQCD:Qmin 0.935
newdef AlphaQCD:NumberOfLoops 3
newdef AlphaQCD:InputOption 1
newdef AlphaQCD:AlphaMZ 0.120
#
#
# Lets set up all the splittings
create Herwig::HalfHalfOneSplitFn QtoQGammaSplitFn
set QtoQGammaSplitFn:InteractionType QED
set QtoQGammaSplitFn:ColourStructure ChargedChargedNeutral
set QtoQGammaSplitFn:AngularOrdered Yes
create Herwig::HalfHalfOneSplitFn QtoQGSplitFn
newdef QtoQGSplitFn:InteractionType QCD
newdef QtoQGSplitFn:ColourStructure TripletTripletOctet
set QtoQGSplitFn:AngularOrdered Yes
create Herwig::OneOneOneSplitFn GtoGGSplitFn
newdef GtoGGSplitFn:InteractionType QCD
newdef GtoGGSplitFn:ColourStructure OctetOctetOctet
set GtoGGSplitFn:AngularOrdered Yes
create Herwig::OneHalfHalfSplitFn GtoQQbarSplitFn
newdef GtoQQbarSplitFn:InteractionType QCD
newdef GtoQQbarSplitFn:ColourStructure OctetTripletTriplet
#set GtoQQbarSplitFn:AngularOrdered No
set GtoQQbarSplitFn:AngularOrdered Yes
create Herwig::OneHalfHalfSplitFn GammatoQQbarSplitFn
newdef GammatoQQbarSplitFn:InteractionType QED
newdef GammatoQQbarSplitFn:ColourStructure NeutralChargedCharged
#set GammatoQQbarSplitFn:AngularOrdered No
set GammatoQQbarSplitFn:AngularOrdered Yes
create Herwig::HalfOneHalfSplitFn QtoGQSplitFn
newdef QtoGQSplitFn:InteractionType QCD
newdef QtoGQSplitFn:ColourStructure TripletOctetTriplet
set QtoGQSplitFn:AngularOrdered Yes
create Herwig::HalfOneHalfSplitFn QtoGammaQSplitFn
newdef QtoGammaQSplitFn:InteractionType QED
newdef QtoGammaQSplitFn:ColourStructure ChargedNeutralCharged
set QtoGammaQSplitFn:AngularOrdered Yes
#
# Now the Sudakovs
create Herwig::QTildeSudakov SudakovCommon
newdef SudakovCommon:Alpha AlphaQCD
-newdef SudakovCommon:cutoffKinScale 2.650*GeV
+newdef SudakovCommon:cutoffKinScale 0.0*GeV
newdef SudakovCommon:PDFmax 1.0
newdef SudakovCommon:CutOffOption pT
+newdef SudakovCommon:pTmin 1.0*GeV
cp SudakovCommon QtoQGSudakov
newdef QtoQGSudakov:SplittingFunction QtoQGSplitFn
newdef QtoQGSudakov:PDFmax 1.9
cp SudakovCommon QtoQGammaSudakov
set QtoQGammaSudakov:SplittingFunction QtoQGammaSplitFn
set QtoQGammaSudakov:Alpha AlphaQED
set QtoQGammaSudakov:PDFmax 1.9
cp QtoQGammaSudakov LtoLGammaSudakov
cp SudakovCommon GtoGGSudakov
newdef GtoGGSudakov:SplittingFunction GtoGGSplitFn
newdef GtoGGSudakov:PDFmax 2.0
cp SudakovCommon GtoQQbarSudakov
newdef GtoQQbarSudakov:SplittingFunction GtoQQbarSplitFn
newdef GtoQQbarSudakov:PDFmax 120.0
cp SudakovCommon GammatoQQbarSudakov
newdef GammatoQQbarSudakov:SplittingFunction GammatoQQbarSplitFn
newdef GammatoQQbarSudakov:PDFmax 120.0
cp SudakovCommon GtobbbarSudakov
newdef GtobbbarSudakov:SplittingFunction GtoQQbarSplitFn
newdef GtobbbarSudakov:PDFmax 40000.0
cp SudakovCommon GtoccbarSudakov
newdef GtoccbarSudakov:SplittingFunction GtoQQbarSplitFn
newdef GtoccbarSudakov:PDFmax 2000.0
cp SudakovCommon QtoGQSudakov
newdef QtoGQSudakov:SplittingFunction QtoGQSplitFn
cp SudakovCommon QtoGammaQSudakov
newdef QtoGammaQSudakov:SplittingFunction QtoGammaQSplitFn
cp SudakovCommon utoGuSudakov
newdef utoGuSudakov:SplittingFunction QtoGQSplitFn
newdef utoGuSudakov:PDFFactor OverOneMinusZ
newdef utoGuSudakov:PDFmax 5.0
cp SudakovCommon dtoGdSudakov
newdef dtoGdSudakov:SplittingFunction QtoGQSplitFn
newdef dtoGdSudakov:PDFFactor OverOneMinusZ
#
# Now add the final splittings
#
do SplittingGenerator:AddFinalSplitting u->u,g; QtoQGSudakov
do SplittingGenerator:AddFinalSplitting d->d,g; QtoQGSudakov
do SplittingGenerator:AddFinalSplitting s->s,g; QtoQGSudakov
do SplittingGenerator:AddFinalSplitting c->c,g; QtoQGSudakov
do SplittingGenerator:AddFinalSplitting b->b,g; QtoQGSudakov
do SplittingGenerator:AddFinalSplitting t->t,g; QtoQGSudakov
#
do SplittingGenerator:AddFinalSplitting g->g,g; GtoGGSudakov
#
do SplittingGenerator:AddFinalSplitting g->u,ubar; GtoQQbarSudakov
do SplittingGenerator:AddFinalSplitting g->d,dbar; GtoQQbarSudakov
do SplittingGenerator:AddFinalSplitting g->s,sbar; GtoQQbarSudakov
do SplittingGenerator:AddFinalSplitting g->c,cbar; GtoccbarSudakov
do SplittingGenerator:AddFinalSplitting g->b,bbar; GtobbbarSudakov
do SplittingGenerator:AddFinalSplitting g->t,tbar; GtoQQbarSudakov
#
do SplittingGenerator:AddFinalSplitting gamma->u,ubar; GammatoQQbarSudakov
do SplittingGenerator:AddFinalSplitting gamma->d,dbar; GammatoQQbarSudakov
do SplittingGenerator:AddFinalSplitting gamma->s,sbar; GammatoQQbarSudakov
do SplittingGenerator:AddFinalSplitting gamma->c,cbar; GammatoQQbarSudakov
do SplittingGenerator:AddFinalSplitting gamma->b,bbar; GammatoQQbarSudakov
do SplittingGenerator:AddFinalSplitting gamma->t,tbar; GammatoQQbarSudakov
do SplittingGenerator:AddFinalSplitting gamma->e-,e+; GammatoQQbarSudakov
do SplittingGenerator:AddFinalSplitting gamma->mu-,mu+; GammatoQQbarSudakov
do SplittingGenerator:AddFinalSplitting gamma->tau-,tau+; GammatoQQbarSudakov
#
do SplittingGenerator:AddFinalSplitting u->u,gamma; QtoQGammaSudakov
do SplittingGenerator:AddFinalSplitting d->d,gamma; QtoQGammaSudakov
do SplittingGenerator:AddFinalSplitting s->s,gamma; QtoQGammaSudakov
do SplittingGenerator:AddFinalSplitting c->c,gamma; QtoQGammaSudakov
do SplittingGenerator:AddFinalSplitting b->b,gamma; QtoQGammaSudakov
do SplittingGenerator:AddFinalSplitting t->t,gamma; QtoQGammaSudakov
do SplittingGenerator:AddFinalSplitting e-->e-,gamma; LtoLGammaSudakov
do SplittingGenerator:AddFinalSplitting mu-->mu-,gamma; LtoLGammaSudakov
do SplittingGenerator:AddFinalSplitting tau-->tau-,gamma; LtoLGammaSudakov
#
# Now lets add the initial splittings. Remember the form a->b,c; means
# that particle a is the particle given and we backward branch to
# particle b which is initial state and particle c which is final state
#
do SplittingGenerator:AddInitialSplitting u->u,g; QtoQGSudakov
do SplittingGenerator:AddInitialSplitting d->d,g; QtoQGSudakov
do SplittingGenerator:AddInitialSplitting s->s,g; QtoQGSudakov
do SplittingGenerator:AddInitialSplitting c->c,g; QtoQGSudakov
do SplittingGenerator:AddInitialSplitting b->b,g; QtoQGSudakov
do SplittingGenerator:AddInitialSplitting u->u,gamma; QtoQGammaSudakov
do SplittingGenerator:AddInitialSplitting d->d,gamma; QtoQGammaSudakov
do SplittingGenerator:AddInitialSplitting s->s,gamma; QtoQGammaSudakov
do SplittingGenerator:AddInitialSplitting c->c,gamma; QtoQGammaSudakov
do SplittingGenerator:AddInitialSplitting b->b,gamma; QtoQGammaSudakov
do SplittingGenerator:AddInitialSplitting t->t,gamma; QtoQGammaSudakov
do SplittingGenerator:AddInitialSplitting g->g,g; GtoGGSudakov
#
do SplittingGenerator:AddInitialSplitting g->d,dbar; GtoQQbarSudakov
do SplittingGenerator:AddInitialSplitting g->u,ubar; GtoQQbarSudakov
do SplittingGenerator:AddInitialSplitting g->s,sbar; GtoQQbarSudakov
do SplittingGenerator:AddInitialSplitting g->c,cbar; GtoccbarSudakov
do SplittingGenerator:AddInitialSplitting g->b,bbar; GtobbbarSudakov
#
do SplittingGenerator:AddInitialSplitting gamma->d,dbar; GammatoQQbarSudakov
do SplittingGenerator:AddInitialSplitting gamma->u,ubar; GammatoQQbarSudakov
do SplittingGenerator:AddInitialSplitting gamma->s,sbar; GammatoQQbarSudakov
do SplittingGenerator:AddInitialSplitting gamma->c,cbar; GammatoQQbarSudakov
do SplittingGenerator:AddInitialSplitting gamma->b,bbar; GammatoQQbarSudakov
#
do SplittingGenerator:AddInitialSplitting d->g,d; dtoGdSudakov
do SplittingGenerator:AddInitialSplitting u->g,u; utoGuSudakov
do SplittingGenerator:AddInitialSplitting s->g,s; QtoGQSudakov
do SplittingGenerator:AddInitialSplitting c->g,c; QtoGQSudakov
do SplittingGenerator:AddInitialSplitting b->g,b; QtoGQSudakov
do SplittingGenerator:AddInitialSplitting dbar->g,dbar; dtoGdSudakov
do SplittingGenerator:AddInitialSplitting ubar->g,ubar; utoGuSudakov
do SplittingGenerator:AddInitialSplitting sbar->g,sbar; QtoGQSudakov
do SplittingGenerator:AddInitialSplitting cbar->g,cbar; QtoGQSudakov
do SplittingGenerator:AddInitialSplitting bbar->g,bbar; QtoGQSudakov
#
do SplittingGenerator:AddInitialSplitting d->gamma,d; QtoGammaQSudakov
do SplittingGenerator:AddInitialSplitting u->gamma,u; QtoGammaQSudakov
do SplittingGenerator:AddInitialSplitting s->gamma,s; QtoGammaQSudakov
do SplittingGenerator:AddInitialSplitting c->gamma,c; QtoGammaQSudakov
do SplittingGenerator:AddInitialSplitting b->gamma,b; QtoGammaQSudakov
do SplittingGenerator:AddInitialSplitting dbar->gamma,dbar; QtoGammaQSudakov
do SplittingGenerator:AddInitialSplitting ubar->gamma,ubar; QtoGammaQSudakov
do SplittingGenerator:AddInitialSplitting sbar->gamma,sbar; QtoGammaQSudakov
do SplittingGenerator:AddInitialSplitting cbar->gamma,cbar; QtoGammaQSudakov
do SplittingGenerator:AddInitialSplitting bbar->gamma,bbar; QtoGammaQSudakov

File Metadata

Mime Type
text/x-diff
Expires
Tue, Nov 19, 3:15 PM (1 d, 14 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
ed/ff/d29b69ec269981e6e54c76a7b75e
Default Alt Text
(997 KB)

Event Timeline