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