1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 """Definitions of the Helas objects needed for the implementation of MadFKS
17 from born"""
18
19
20 import madgraph.core.base_objects as MG
21 import madgraph.core.helas_objects as helas_objects
22 import madgraph.core.diagram_generation as diagram_generation
23 import madgraph.core.color_amp as color_amp
24 import madgraph.core.color_algebra as color_algebra
25 import madgraph.fks.fks_base as fks_base
26 import madgraph.fks.fks_common as fks_common
27 import madgraph.loop.loop_helas_objects as loop_helas_objects
28 import copy
29 import logging
30 import array
31
32 logger = logging.getLogger('madgraph.fks_helas_objects')
33
34
36 """class to generate the helas calls for a FKSMultiProcess"""
37
43
44 - def filter(self, name, value):
51
52 - def __init__(self, fksmulti, loop_optimized = False, gen_color =True, decay_ids =[]):
53 """Initialization from a FKSMultiProcess"""
54
55
56 loggers_off = [logging.getLogger('madgraph.diagram_generation'),
57 logging.getLogger('madgraph.helas_objects')]
58 old_levels = [logg.level for logg in loggers_off]
59 for logg in loggers_off:
60 logg.setLevel(logging.WARNING)
61
62 self.loop_optimized = loop_optimized
63
64 logger.info('Generating real emission matrix-elements...')
65 self['real_matrix_elements'] = self.generate_matrix_elements(
66 copy.copy(fksmulti['real_amplitudes']), combine_matrix_elements = False)
67
68 self['matrix_elements'] = self.generate_matrix_elements_fks(
69 fksmulti,
70 gen_color, decay_ids)
71 self['initial_states']=[]
72
73 self['has_isr'] = fksmulti['has_isr']
74 self['has_fsr'] = fksmulti['has_fsr']
75 self['has_loops'] = len(self.get_virt_matrix_elements()) > 0
76
77 for i, logg in enumerate(loggers_off):
78 logg.setLevel(old_levels[i])
79
81 """Return a list of (lorentz_name, conjugate, outgoing) with
82 all lorentz structures used by this HelasMultiProcess."""
83 helas_list = []
84 for me in self.get('matrix_elements'):
85 helas_list.extend(me.get_used_lorentz())
86 return list(set(helas_list))
87
89 """Return a list with all couplings used by this
90 HelasMatrixElement."""
91 coupling_list = []
92 for me in self.get('matrix_elements'):
93 coupling_list.extend([c for l in me.get_used_couplings() for c in l])
94 return list(set(coupling_list))
95
97 """Extract the list of matrix elements"""
98 return self.get('matrix_elements')
99
100
102 """Extract the list of virtuals matrix elements"""
103 return [me.virt_matrix_element for me in self.get('matrix_elements') \
104 if me.virt_matrix_element]
105
106
109 """Generate the HelasMatrixElements for the amplitudes,
110 identifying processes with identical matrix elements, as
111 defined by HelasMatrixElement.__eq__. Returns a
112 HelasMatrixElementList and an amplitude map (used by the
113 SubprocessGroup functionality). decay_ids is a list of decayed
114 particle ids, since those should not be combined even if
115 matrix element is identical."""
116
117 fksprocs = fksmulti['born_processes']
118 assert isinstance(fksprocs, fks_base.FKSProcessList), \
119 "%s is not valid FKSProcessList" % \
120 repr(fksprocs)
121
122
123
124 list_colorize = []
125 list_color_links =[]
126 list_color_basis = []
127 list_color_matrices = []
128 real_me_list = []
129 me_id_list = []
130
131 matrix_elements = FKSHelasProcessList()
132
133 for i, proc in enumerate(fksprocs):
134 logger.info("Generating Helas calls for FKS %s (%d / %d)" % \
135 (proc.born_amp.get('process').nice_string(print_weighted = False).\
136 replace('Process', 'process'),
137 i + 1, len(fksprocs)))
138 matrix_element_list = [FKSHelasProcess(proc, self['real_matrix_elements'],
139 fksmulti['real_amplitudes'],
140 loop_optimized = self.loop_optimized,
141 decay_ids=decay_ids,
142 gen_color=False)]
143 for matrix_element in matrix_element_list:
144 assert isinstance(matrix_element, FKSHelasProcess), \
145 "Not a FKSHelasProcess: %s" % matrix_element
146
147 try:
148
149
150
151 other = \
152 matrix_elements[matrix_elements.index(matrix_element)]
153 except ValueError:
154
155
156 if matrix_element.born_matrix_element.get('processes') and \
157 matrix_element.born_matrix_element.get('diagrams'):
158 matrix_elements.append(matrix_element)
159
160 if not gen_color:
161 continue
162
163
164
165
166 col_basis = color_amp.ColorBasis()
167 new_amp = matrix_element.born_matrix_element.get_base_amplitude()
168 matrix_element.born_matrix_element.set('base_amplitude', new_amp)
169 colorize_obj = col_basis.create_color_dict_list(new_amp)
170
171 try:
172
173
174
175 col_index = list_colorize.index(colorize_obj)
176 logger.info(\
177 "Reusing existing color information for %s" % \
178 matrix_element.born_matrix_element.get('processes')\
179 [0].nice_string(print_weighted=False).\
180 replace('Process', 'process'))
181 except ValueError:
182
183
184 list_colorize.append(colorize_obj)
185 col_basis.build()
186 list_color_basis.append(col_basis)
187 col_matrix = color_amp.ColorMatrix(col_basis)
188 list_color_matrices.append(col_matrix)
189 col_index = -1
190
191 logger.info(\
192 "Processing color information for %s" % \
193 matrix_element.born_matrix_element.\
194 get('processes')[0].nice_string(print_weighted=False).\
195 replace('Process', 'process'))
196 matrix_element.born_matrix_element.set('color_basis',
197 list_color_basis[col_index])
198 matrix_element.born_matrix_element.set('color_matrix',
199 list_color_matrices[col_index])
200 else:
201
202
203 other.add_process(matrix_element)
204
205 for me in matrix_elements:
206 me.set_color_links()
207 return matrix_elements
208
209
211 """class to handle lists of FKSHelasProcesses"""
212
214 """Test if object obj is a valid FKSProcess for the list."""
215 return isinstance(obj, FKSHelasProcess)
216
217
219 """class to generate the Helas calls for a FKSProcess. Contains:
220 -- born ME
221 -- list of FKSHelasRealProcesses
222 -- color links"""
223
224 - def __init__(self, fksproc=None, real_me_list =[], real_amp_list=[],
225 loop_optimized = False, **opts):
226 """ constructor, starts from a FKSProcess,
227 sets reals and color links. Real_me_list and real_amp_list are the lists of pre-genrated
228 matrix elements in 1-1 correspondence with the amplitudes"""
229
230 if fksproc != None:
231 self.born_matrix_element = helas_objects.HelasMatrixElement(
232 fksproc.born_amp, **opts)
233 self.real_processes = []
234 self.orders = fksproc.born_proc.get('orders')
235 self.perturbation = fksproc.perturbation
236 real_amps_new = []
237
238 for proc in fksproc.real_amps:
239 fksreal_me = FKSHelasRealProcess(proc, real_me_list, real_amp_list, **opts)
240 try:
241 other = self.real_processes[self.real_processes.index(fksreal_me)]
242 other.matrix_element.get('processes').extend(\
243 fksreal_me.matrix_element.get('processes') )
244 except ValueError:
245 if fksreal_me.matrix_element.get('processes') and \
246 fksreal_me.matrix_element.get('diagrams'):
247 self.real_processes.append(fksreal_me)
248 real_amps_new.append(proc)
249 fksproc.real_amps = real_amps_new
250 if fksproc.virt_amp:
251 self.virt_matrix_element = \
252 loop_helas_objects.LoopHelasMatrixElement(fksproc.virt_amp,
253 optimized_output = loop_optimized)
254 else:
255 self.virt_matrix_element = None
256
257 self.color_links = []
258
260 """this function computes and returns the color links, it should be called
261 after the initialization and the setting of the color basis"""
262 if not self.color_links:
263 legs = self.born_matrix_element.get('base_amplitude').get('process').get('legs')
264 model = self.born_matrix_element.get('base_amplitude').get('process').get('model')
265 color_links_info = fks_common.find_color_links(fks_common.to_fks_legs(legs, model),
266 symm = True,pert = self.perturbation)
267 col_basis = self.born_matrix_element.get('color_basis')
268 self.color_links = fks_common.insert_color_links(col_basis,
269 col_basis.create_color_dict_list(
270 self.born_matrix_element.get('base_amplitude')),
271 color_links_info)
272
274 """Returns the list of the fks infos for all processes in the format
275 {n_me, pdgs, fks_info}, where n_me is the number of real_matrix_element the configuration
276 belongs to"""
277 info_list = []
278 for n, real in enumerate(self.real_processes):
279 pdgs = [l['id'] for l in real.matrix_element.get_base_amplitude()['process']['legs']]
280 for info in real.fks_infos:
281 info_list.append({'n_me' : n + 1,'pdgs' : pdgs, 'fks_info' : info})
282 return info_list
283
284
286 """Returns the pdgs of the legs in the form "i1 i2 -> f1 f2 ...", which may
287 be useful (eg. to be written in a B-LH order file)"""
288
289 initial = ''
290 final = ''
291 for leg in self.born_matrix_element.get('processes')[0].get('legs'):
292 if leg.get('state'):
293 final += '%d ' % leg.get('id')
294 else:
295 initial += '%d ' % leg.get('id')
296 return initial + '-> ' + final
297
298
299 - def get(self, key):
300 """the get function references to born_matrix_element"""
301 return self.born_matrix_element.get(key)
302
304 """the get_used_lorentz function references to born, reals
305 and virtual matrix elements"""
306 lorentz_list = self.born_matrix_element.get_used_lorentz()
307 for real in self.real_processes:
308 lorentz_list.extend(real.matrix_element.get_used_lorentz())
309 if self.virt_matrix_element:
310 lorentz_list.extend(self.virt_matrix_element.get_used_lorentz())
311
312 return list(set(lorentz_list))
313
315 """the get_used_couplings function references to born, reals
316 and virtual matrix elements"""
317 coupl_list = self.born_matrix_element.get_used_couplings()
318 for real in self.real_processes:
319 coupl_list.extend([c for c in\
320 real.matrix_element.get_used_couplings()])
321 if self.virt_matrix_element:
322 coupl_list.extend(self.virt_matrix_element.get_used_couplings())
323 return coupl_list
324
326 """the equality between two FKSHelasProcesses is defined up to the
327 color links"""
328 selftag = helas_objects.IdentifyMETag.create_tag(self.born_matrix_element.get('base_amplitude'))
329 othertag = helas_objects.IdentifyMETag.create_tag(other.born_matrix_element.get('base_amplitude'))
330
331 if self.born_matrix_element != other.born_matrix_element or \
332 selftag != othertag:
333 return False
334
335 reals2 = copy.copy(other.real_processes)
336 for real in self.real_processes:
337 try:
338 reals2.remove(real)
339 except ValueError:
340 return False
341 if not reals2:
342 return True
343 else:
344 return False
345
347 """adds processes from born and reals of other to itself. Note that
348 corresponding real processes may not be in the same order. This is
349 taken care of by constructing the list of self_reals."""
350 self.born_matrix_element.get('processes').extend(
351 other.born_matrix_element.get('processes'))
352 if self.virt_matrix_element and other.virt_matrix_element:
353 self.virt_matrix_element.get('processes').extend(
354 other.virt_matrix_element.get('processes'))
355 self_reals = [real.matrix_element for real in self.real_processes]
356 for oth_real in other.real_processes:
357 this_real = self.real_processes[self_reals.index(oth_real.matrix_element)]
358
359 this_pdgs = [[leg['id'] for leg in proc['legs']] \
360 for proc in this_real.matrix_element['processes']]
361 for oth_proc in oth_real.matrix_element['processes']:
362 oth_pdgs = [leg['id'] for leg in oth_proc['legs']]
363 if oth_pdgs not in this_pdgs:
364 this_real.matrix_element['processes'].append(oth_proc)
365 this_pdgs.append(oth_pdgs)
366
367
368
369
370
372 """class to generate the Helas calls for a FKSRealProcess
373 contains:
374 -- colors
375 -- charges
376 -- i/j/ij fks, ij refers to the born leglist
377 -- ijglu
378 -- need_color_links
379 -- fks_j_from_i
380 -- matrix element
381 -- is_to_integrate
382 -- leg permutation<<REMOVED"""
383
384 - def __init__(self, fksrealproc=None, real_me_list = [], real_amp_list =[], **opts):
385 """constructor, starts from a fksrealproc and then calls the
386 initialization for HelasMatrixElement.
387 Sets i/j fks and the permutation.
388 real_me_list and real_amp_list are the lists of pre-generated matrix elements in 1-1
389 correspondance with the amplitudes"""
390
391 if fksrealproc != None:
392 self.isfinite = False
393 self.colors = fksrealproc.colors
394 self.charges = fksrealproc.charges
395 self.fks_infos = fksrealproc.fks_infos
396 self.is_to_integrate = fksrealproc.is_to_integrate
397
398 if len(real_me_list) != len(real_amp_list):
399 raise fks_common.FKSProcessError(
400 'not same number of amplitudes and matrix elements: %d, %d' % \
401 (len(real_amp_list), len(real_me_list)))
402 if real_me_list and real_amp_list:
403 self.matrix_element = copy.deepcopy(real_me_list[real_amp_list.index(fksrealproc.amplitude)])
404 self.matrix_element['processes'] = copy.deepcopy(self.matrix_element['processes'])
405 else:
406 logger.info('generating matrix element...')
407 self.matrix_element = helas_objects.HelasMatrixElement(
408 fksrealproc.amplitude, **opts)
409
410 self.matrix_element.get('color_basis').build(
411 self.matrix_element.get('base_amplitude'))
412 self.matrix_element.set('color_matrix',
413 color_amp.ColorMatrix(
414 self.matrix_element.get('color_basis')))
415
416 self.fks_j_from_i = fksrealproc.fks_j_from_i
417
421
423 """Equality operator:
424 compare two FKSHelasRealProcesses by comparing their dictionaries"""
425 return self.__dict__ == other.__dict__
426
428 """Inequality operator:
429 compare two FKSHelasRealProcesses by comparing their dictionaries"""
430 return not self.__eq__(other)
431