1
################################################################################
3
# Copyright (c) 2009 The MadGraph5_aMC@NLO Development team and Contributors
5
# This file is a part of the MadGraph5_aMC@NLO project, an application which
6
# automatically generates Feynman diagrams and matrix elements for arbitrary
7
# high-energy processes in the Standard Model and beyond.
9
# It is subject to the MadGraph5_aMC@NLO license which should accompany this
12
# For more information, visit madgraph.phys.ucl.ac.be and amcatnlo.web.cern.ch
14
################################################################################
16
"""Classes, methods and functions required to write QCD color information
17
for a loop diagram and build a color basis, and to square a QCD color string for
18
squared diagrams and interference terms."""
24
import madgraph.various.misc as misc
26
import madgraph.core.color_amp as color_amp
27
import madgraph.core.color_algebra as color_algebra
28
import madgraph.core.diagram_generation as diagram_generation
29
import madgraph.loop.loop_diagram_generation as loop_diagram_generation
30
import madgraph.core.base_objects as base_objects
33
#===============================================================================
35
#===============================================================================
36
class LoopColorBasis(color_amp.ColorBasis):
37
""" Same class as its mother ColorBasis except that it can also handle
40
def __init__(self, compute_loop_nc = False):
41
""" Defines the instance attribute compute_loop_nc.
42
The compute_loop_nc sets wheter independent tracking of Nc power coming
43
from the color loop trace is necessary or not (it is time consuming)."""
45
self.compute_loop_nc = compute_loop_nc
47
def closeColorLoop(self, colorize_dict, lcut_charge, lcut_numbers):
48
""" Add a color delta in the right representation (depending on the
49
color charge carried by the L-cut particle whose number are given in
50
the loop_numbers argument) to close the loop color trace."""
52
# But for T3 and T6 for example, we must make sure to add a delta with
53
# the first index in the fundamental representation.
55
lcut_numbers.reverse()
56
if abs(lcut_charge)==1:
57
# No color carried by the lcut particle, there is nothing to do.
59
elif abs(lcut_charge)==3:
60
closingCS=color_algebra.ColorString(\
61
[color_algebra.T(lcut_numbers[1],lcut_numbers[0])])
62
elif abs(lcut_charge)==6:
63
closingCS=color_algebra.ColorString(\
64
[color_algebra.T6(lcut_numbers[1],lcut_numbers[0])])
65
elif abs(lcut_charge)==8:
66
closingCS=color_algebra.ColorString(\
67
[color_algebra.Tr(lcut_numbers[1],lcut_numbers[0])],
68
fractions.Fraction(2, 1))
70
raise color_amp.ColorBasis.ColorBasisError, \
71
"L-cut particle has an unsupported color representation %s" % lcut_charge
73
# Append it to all color strings for this diagram.
74
for CS in colorize_dict.values():
75
# The double full_simplify() below brings significantly slowdown
76
# so that it should be used only when loop_Nc_power is actuall used.
77
if self.compute_loop_nc:
78
# We first compute the NcPower of this ColorString before
79
# *before* the loop color flow is sewed together.
80
max_CS_lcut_diag_Nc_power = max(cs.Nc_power \
81
for cs in color_algebra.ColorFactor([CS]).full_simplify())
82
# We add here the closing color structure.
84
if self.compute_loop_nc:
85
# Now compute the Nc power *after* the loop color flow is sewed
86
# together and again compute the overall maximum power of Nc
87
# appearing in this simplified sewed structure.
88
simplified_cs = color_algebra.ColorFactor([CS]).full_simplify()
90
# It can be that the color structure simplifies to zero.
94
max_CS_loop_diag_Nc_power = max(cs.Nc_power \
95
for cs in simplified_cs)
96
# We can now set the power of Nc brought by the potential loop
97
# color trace to the corresponding attribute of this ColorStructure
98
CS.loop_Nc_power = max_CS_loop_diag_Nc_power - \
99
max_CS_lcut_diag_Nc_power
101
# When not computing loop_nc (whcih is typically used for now
102
# only when doing LoopInduced + Madevent, we set the
103
# CS.loop_Nc_power to None so that it will cause problems if used.
104
CS.loop_Nc_power = None
106
def create_loop_color_dict_list(self, amplitude):
107
"""Returns a list of colorize dict for all loop diagrams in amplitude.
108
Also update the _list_color_dict object accordingly."""
112
if not isinstance(amplitude,loop_diagram_generation.LoopAmplitude):
113
raise color_amp.ColorBasis.ColorBasisError, \
114
'LoopColorBasis is used with an amplitude which is not a LoopAmplitude'
115
for diagram in amplitude.get('loop_diagrams'):
117
colorize_dict = self.colorize(diagram,
118
amplitude.get('process').get('model'))
119
if diagram['type']>0:
120
# We close here the color loop for loop diagrams (R2 have
121
# negative 'type') by adding a delta in the two color indices of
123
starting_leg=diagram.get_starting_loop_line()
124
finishing_leg=diagram.get_finishing_loop_line()
125
lcut_charge=amplitude['process']['model'].get_particle(\
126
starting_leg.get('id')).get_color()
127
lcut_numbers=[starting_leg.get('number'),\
128
finishing_leg.get('number')]
129
self.closeColorLoop(colorize_dict,lcut_charge,lcut_numbers)
131
list_color_dict.append(colorize_dict)
133
# Now let's treat the UVCT diagrams as well
134
for diagram in amplitude.get('loop_UVCT_diagrams'):
135
colorize_dict = self.colorize(diagram,
136
amplitude.get('process').get('model'))
137
list_color_dict.append(colorize_dict)
139
self._list_color_dict = list_color_dict
141
return list_color_dict
143
def create_born_color_dict_list(self, amplitude):
144
"""Returns a list of colorize dict for all born diagrams in amplitude.
145
Also update the _list_color_dict object accordingly """
149
if not isinstance(amplitude,loop_diagram_generation.LoopAmplitude):
150
raise color_amp.ColorBasis.ColorBasisError, \
151
'LoopColorBasis is used with an amplitude which is not a LoopAmplitude'
153
for diagram in amplitude.get('born_diagrams'):
154
colorize_dict = self.colorize(diagram,
155
amplitude.get('process').get('model'))
156
list_color_dict.append(colorize_dict)
158
self._list_color_dict = list_color_dict
160
return list_color_dict
162
def build_born(self, amplitude):
163
"""Build the a color basis object using information contained in
164
amplitude (otherwise use info from _list_color_dict).
165
Returns a list of color """
167
self.create_born_color_dict_list(amplitude)
168
for index, color_dict in enumerate(self._list_color_dict):
169
self.update_color_basis(color_dict, index)
171
def build_loop(self, amplitude):
172
"""Build the loop color basis object using information contained in
173
amplitude (otherwise use info from _list_color_dict).
174
Returns a list of color."""
176
self.create_loop_color_dict_list(amplitude)
177
for index, color_dict in enumerate(self._list_color_dict):
178
self.update_color_basis(color_dict, index)