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 from __future__ import absolute_import
21 import madgraph.core.base_objects as MG
22 import madgraph.core.helas_objects as helas_objects
23 import madgraph.core.diagram_generation as diagram_generation
24 import madgraph.core.color_amp as color_amp
25 import madgraph.core.color_algebra as color_algebra
26 import madgraph.fks.fks_base as fks_base
27 import madgraph.fks.fks_common as fks_common
28 import madgraph.loop.loop_helas_objects as loop_helas_objects
29 import madgraph.loop.loop_diagram_generation as loop_diagram_generation
30 from madgraph import InvalidCmd
31 import madgraph.various.misc as misc
32 import copy
33 import logging
34 import array
35 import multiprocessing
36 import signal
37 import tempfile
38 import six
39 import six.moves.cPickle as cPickle
40 import itertools
41 import os
42 import sys
43 from six.moves import zip
44 from madgraph import MG5DIR
45 pjoin = os.path.join
46 logger = logging.getLogger('madgraph.fks_helas_objects')
47
48
49
51 i = args[0]
52 real_amp = args[1]
53
54 amplitude = real_amp.generate_real_amplitude()
55
56
57 if not amplitude['diagrams']:
58 msg = "Discarding amplitude with no diagrams%s" % \
59 (amplitude['process'].nice_string(print_weighted=False).replace('Process ', ''))
60 logger.debug(msg)
61 return []
62
63 helasreal = helas_objects.HelasMatrixElement(amplitude)
64 logger.info('Generating real %s' % \
65 real_amp.process.nice_string(print_weighted=False).replace('Process', 'process'))
66
67
68
69 list_colorize = []
70 list_color_basis = []
71 list_color_matrices = []
72
73
74
75
76 dict_loopborn_matrices = {}
77
78
79 color_information = { 'list_colorize' : list_colorize,
80 'list_color_basis' : list_color_basis,
81 'list_color_matrices' : list_color_matrices,
82 'dict_loopborn_matrices' : dict_loopborn_matrices}
83
84 helas_objects.HelasMultiProcess.process_color(helasreal,color_information)
85
86 outdata = [amplitude,helasreal]
87
88 output = tempfile.NamedTemporaryFile(delete = False)
89
90 six.moves.cPickle.dump(outdata,output,protocol=2)
91 output.close()
92
93 return [output.name,helasreal.get_num_configs(),helasreal.get_nexternal_ninitial()[0]]
94
95
97 i = args[0]
98 born = args[1]
99 born_pdg_list = args[2]
100 loop_orders = args[3]
101 pdg_list = args[4]
102 loop_optimized = args[5]
103 OLP = args[6]
104 realmapout = args[7]
105
106 logger.info('Generating born %s' % \
107 born.born_amp['process'].nice_string(print_weighted=False).replace('Process', 'process'))
108
109 helasreal_list = []
110 amp_to_remove = []
111 for amp in born.real_amps:
112
113
114 try:
115 idx = pdg_list.index(amp.pdgs)
116 infilename = realmapout[idx]
117 infile = open(infilename,'rb')
118 realdata = cPickle.load(infile)
119 infile.close()
120 amp.amplitude = realdata[0]
121 helasreal_list.append(realdata[1])
122
123 except ValueError:
124 logger.debug('Removing amplitude: %s' % amp.process.nice_string())
125 amp_to_remove.append(amp)
126
127 for amp in amp_to_remove:
128 born.real_amps.remove(amp)
129
130 born.link_born_reals()
131
132 for amp in born.real_amps:
133 amp.find_fks_j_from_i(born_pdg_list)
134
135
136 has_loops = False
137 if born.born_amp['process'].get('NLO_mode') == 'all' and OLP == 'MadLoop':
138 myproc = copy.copy(born.born_amp['process'])
139
140
141 myproc['perturbation_couplings'] = myproc['model']['coupling_orders']
142 myproc['legs'] = fks_common.to_legs(copy.copy(myproc['legs']))
143
144 try:
145 myamp = loop_diagram_generation.LoopAmplitude(myproc)
146 has_loops = True
147 born.virt_amp = myamp
148 except InvalidCmd:
149 has_loops = False
150
151 helasfull = FKSHelasProcess(born, helasreal_list,
152 loop_optimized = loop_optimized,
153 decay_ids=[],
154 gen_color=False)
155
156 processes = helasfull.born_me.get('processes')
157
158 max_configs = helasfull.born_me.get_num_configs()
159
160 metag = helas_objects.IdentifyMETag.create_tag(helasfull.born_me.get('base_amplitude'))
161
162 outdata = helasfull
163
164 output = tempfile.NamedTemporaryFile(delete = False)
165 six.moves.cPickle.dump(outdata,output,protocol=2)
166 output.close()
167
168 return [output.name,metag,has_loops,processes,helasfull.born_me.get_num_configs(),helasfull.get_nexternal_ninitial()[0]]
169
170
172
173 i = args[0]
174 mefile = args[1]
175 duplist = args[2]
176
177 infile = open(mefile,'rb')
178 me = six.moves.cPickle.load(infile)
179 infile.close()
180
181
182 me.get('processes')[0].set('uid', i)
183
184
185
186
187 col_basis = color_amp.ColorBasis()
188 new_amp = me.born_me.get_base_amplitude()
189 me.born_me.set('base_amplitude', new_amp)
190 colorize_obj = col_basis.create_color_dict_list(new_amp)
191
192 col_basis.build()
193 col_matrix = color_amp.ColorMatrix(col_basis)
194
195 me.born_me.set('color_basis',col_basis)
196 me.born_me.set('color_matrix',col_matrix)
197
198 cannot_combine = []
199
200 for iother,othermefile in enumerate(duplist):
201 infileother = open(othermefile,'rb')
202 otherme = six.moves.cPickle.load(infileother)
203 infileother.close()
204
205
206
207 if otherme == me:
208 me.add_process(otherme)
209 else:
210 cannot_combine.append(othermefile)
211
212 me.set_color_links()
213
214 initial_states=[]
215 for fksreal in me.real_processes:
216
217 initial_states.append(sorted(list(set((p.get_initial_pdg(1),p.get_initial_pdg(2)) for \
218 p in fksreal.matrix_element.get('processes')))))
219
220 if me.virt_matrix_element:
221 has_virtual = True
222 else:
223 has_virtual = False
224
225
226 outdata = me
227
228 output = tempfile.NamedTemporaryFile(delete = False)
229 six.moves.cPickle.dump(outdata,output,protocol=2)
230 output.close()
231
232
233 return [output.name,initial_states,me.get_used_lorentz(),me.get_used_couplings(),has_virtual,cannot_combine]
234
235
237 """class to generate the helas calls for a FKSMultiProcess"""
238
240 """Return particle property names as a nicely sorted list."""
241 keys = super(FKSHelasMultiProcess, self).get_sorted_keys()
242 keys += ['real_matrix_elements', ['has_isr'], ['has_fsr'],
243 'used_lorentz', 'used_couplings', 'max_configs', 'max_particles', 'processes']
244 return keys
245
246 - def filter(self, name, value):
252
253 - def __init__(self, fksmulti, loop_optimized = False, gen_color =True, decay_ids =[]):
254 """Initialization from a FKSMultiProcess"""
255
256
257 loggers_off = [logging.getLogger('madgraph.diagram_generation'),
258 logging.getLogger('madgraph.helas_objects')]
259 old_levels = [logg.level for logg in loggers_off]
260 for logg in loggers_off:
261 logg.setLevel(logging.WARNING)
262
263 self.loop_optimized = loop_optimized
264
265 self['used_lorentz'] = []
266 self['used_couplings'] = []
267 self['processes'] = []
268
269 self['max_particles'] = -1
270 self['max_configs'] = -1
271
272 if not fksmulti['ncores_for_proc_gen']:
273
274
275 if fksmulti['real_amplitudes']:
276 logger.info('Generating real emission matrix-elements...')
277 self['real_matrix_elements'] = self.generate_matrix_elements(
278 copy.copy(fksmulti['real_amplitudes']), combine_matrix_elements = False)
279 else:
280 self['real_matrix_elements'] = helas_objects.HelasMatrixElementList()
281
282 self['matrix_elements'] = self.generate_matrix_elements_fks(
283 fksmulti,
284 gen_color, decay_ids)
285 self['initial_states']=[]
286 self['has_loops'] = len(self.get_virt_matrix_elements()) > 0
287
288 else:
289 self['has_loops'] = False
290
291 born_procs = fksmulti.get('born_processes')
292 born_pdg_list = [[l['id'] for l in born.born_amp['process']['legs']] \
293 for born in born_procs ]
294 loop_orders = {}
295 for born in born_procs:
296 for coup, val in fks_common.find_orders(born.born_amp).items():
297 try:
298 loop_orders[coup] = max([loop_orders[coup], val])
299 except KeyError:
300 loop_orders[coup] = val
301 pdg_list = []
302 real_amp_list = []
303 for born in born_procs:
304 for amp in born.real_amps:
305 if not pdg_list.count(amp.pdgs):
306 pdg_list.append(amp.pdgs)
307 real_amp_list.append(amp)
308
309
310 real_out_list = []
311 realmapin = []
312 for i,real_amp in enumerate(real_amp_list):
313 realmapin.append([i,real_amp])
314
315
316 original_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN)
317 if six.PY3:
318 ctx = multiprocessing.get_context('fork')
319 else:
320 ctx = multiprocessing
321 if fksmulti['ncores_for_proc_gen'] < 0:
322 pool = ctx.Pool(maxtasksperchild=1)
323 else:
324 pool = ctx.Pool(processes=fksmulti['ncores_for_proc_gen'],maxtasksperchild=1)
325 signal.signal(signal.SIGINT, original_sigint_handler)
326
327 logger.info('Generating real matrix elements...')
328 import time
329 try:
330
331
332 modelpath = born_procs[0].born_amp['process']['model'].get('modelpath')
333
334 with misc.TMP_variable(sys, 'path', sys.path + [pjoin(MG5DIR, 'models'), modelpath]):
335 realmapout = pool.map_async(async_generate_real,realmapin).get(9999999)
336 except KeyboardInterrupt:
337 pool.terminate()
338 raise KeyboardInterrupt
339
340
341
342 for rout, ramp, rpdg in zip(list(realmapout), list(real_amp_list), list(pdg_list)):
343 if not rout:
344 realmapout.remove(rout)
345 real_amp_list.remove(ramp)
346 pdg_list.remove(rpdg)
347 realmapout = [r for r in realmapout if r]
348
349 realmapfiles = []
350 for realout in realmapout:
351 realmapfiles.append(realout[0])
352
353 logger.info('Generating born and virtual matrix elements...')
354
355 bornmapin = []
356 OLP=fksmulti['OLP']
357 for i,born in enumerate(born_procs):
358 bornmapin.append([i,born,born_pdg_list,loop_orders,pdg_list,loop_optimized,OLP,realmapfiles])
359
360 try:
361 bornmapout = pool.map_async(async_generate_born,bornmapin).get(9999999)
362 except KeyboardInterrupt:
363 pool.terminate()
364 raise KeyboardInterrupt
365
366 configs_list = [bout[4] for bout in bornmapout]
367 nparticles_list = [bout[5] for bout in bornmapout]
368
369
370 for realtmp in realmapout:
371 os.remove(realtmp[0])
372
373 memapout = []
374 while bornmapout:
375 logger.info('Collecting infos and finalizing matrix elements, %d left...' \
376 % (len(bornmapout)))
377 unique_me_list = []
378 duplicate_me_lists = []
379 for bornout in bornmapout:
380 mefile = bornout[0]
381 metag = bornout[1]
382 has_loops = bornout[2]
383 self['has_loops'] = self['has_loops'] or has_loops
384 processes = bornout[3]
385 self['processes'].extend(processes)
386 unique = True
387 for ime2,bornout2 in enumerate(unique_me_list):
388 mefile2 = bornout2[0]
389 metag2 = bornout2[1]
390 if metag==metag2:
391 duplicate_me_lists[ime2].append(mefile)
392 unique = False
393 break;
394 if unique:
395 unique_me_list.append(bornout)
396 duplicate_me_lists.append([])
397
398 memapin = []
399 not_combined = []
400 for i,bornout in enumerate(unique_me_list):
401 mefile = bornout[0]
402 memapin.append([i,mefile, duplicate_me_lists[i]])
403
404 try:
405 memapout.append(pool.map_async(async_finalize_matrix_elements,memapin).get(9999999))
406 except KeyboardInterrupt:
407 pool.terminate()
408 raise KeyboardInterrupt
409
410
411
412 for meout in memapout[-1]:
413 not_combined += meout[5]
414
415
416 for bornout in bornmapout[:]:
417 mefile = bornout[0]
418 if not mefile in not_combined:
419 os.remove(mefile)
420 bornmapout.remove(bornout)
421
422 pool.close()
423 pool.join()
424
425
426 memapout = sum(memapout, [])
427
428
429 matrix_elements = []
430 for meout in memapout:
431 matrix_elements.append(meout[0])
432
433 self['matrix_elements']=matrix_elements
434
435
436
437 initial_states = []
438 for meout in memapout:
439 me_initial_states = meout[1]
440 for state in me_initial_states:
441 initial_states.append(state)
442
443
444 checked = []
445 for e in initial_states:
446 if e not in checked:
447 checked.append(e)
448 initial_states=checked
449
450 self['initial_states']=initial_states
451
452 helas_list = []
453 for meout in memapout:
454 helas_list.extend(meout[2])
455 self['used_lorentz']=list(set(helas_list))
456
457 coupling_list = []
458 for meout in memapout:
459 coupling_list.extend([c for l in meout[3] for c in l])
460 self['used_couplings'] = list(set(coupling_list))
461
462 has_virtuals = False
463 for meout in memapout:
464 if meout[4]:
465 has_virtuals = True
466 break
467 self['has_virtuals'] = has_virtuals
468
469
470
471
472 for meout in realmapout:
473 configs_list.append(meout[1])
474 self['max_configs'] = max(configs_list)
475
476 for meout in realmapout:
477 nparticles_list.append(meout[2])
478 self['max_particles'] = max(nparticles_list)
479
480 self['has_isr'] = fksmulti['has_isr']
481 self['has_fsr'] = fksmulti['has_fsr']
482
483 logger.info('... Done')
484
485 for i, logg in enumerate(loggers_off):
486 logg.setLevel(old_levels[i])
487
488
490 """Return a list of (lorentz_name, conjugate, outgoing) with
491 all lorentz structures used by this HelasMultiProcess."""
492
493 if not self['used_lorentz']:
494 helas_list = []
495 for me in self.get('matrix_elements'):
496 helas_list.extend(me.get_used_lorentz())
497 self['used_lorentz'] = list(set(helas_list))
498
499 return self['used_lorentz']
500
501
503 """Return a list with all couplings used by this
504 HelasMatrixElement."""
505
506 if not self['used_couplings']:
507 coupling_list = []
508 for me in self.get('matrix_elements'):
509 coupling_list.extend([c for l in me.get_used_couplings() for c in l])
510 self['used_couplings'] = list(set(coupling_list))
511
512 return self['used_couplings']
513
514
516 """Return a list with all couplings used by this
517 HelasMatrixElement."""
518
519 if not self['processes']:
520 process_list = []
521 for me in self.get('matrix_elements'):
522 process_list.extend(me.born_me.get('processes'))
523 self['processes'] = process_list
524
525 return self['processes']
526
527
529 """Return max_configs"""
530
531 if self['max_configs'] < 0:
532 try:
533 self['max_configs'] = max([me.get_num_configs() \
534 for me in self['real_matrix_elements']])
535 except (ValueError, MG.PhysicsObject.PhysicsObjectError):
536 pass
537 self['max_configs'] = max(self['max_configs'],\
538 max([me.born_me.get_num_configs() \
539 for me in self['matrix_elements']]))
540 return self['max_configs']
541
542
544 """Return max_paricles"""
545
546 if self['max_particles'] < 0:
547 self['max_particles'] = max([me.get_nexternal_ninitial()[0] \
548 for me in self['matrix_elements']])
549
550 return self['max_particles']
551
552
554 """Extract the list of matrix elements"""
555 return self.get('matrix_elements')
556
557
559 """Extract the list of virtuals matrix elements"""
560 return [me.virt_matrix_element for me in self.get('matrix_elements') \
561 if me.virt_matrix_element]
562
563
566 """Generate the HelasMatrixElements for the amplitudes,
567 identifying processes with identical matrix elements, as
568 defined by HelasMatrixElement.__eq__. Returns a
569 HelasMatrixElementList and an amplitude map (used by the
570 SubprocessGroup functionality). decay_ids is a list of decayed
571 particle ids, since those should not be combined even if
572 matrix element is identical."""
573
574 fksprocs = fksmulti['born_processes']
575 assert isinstance(fksprocs, fks_base.FKSProcessList), \
576 "%s is not valid FKSProcessList" % \
577 repr(fksprocs)
578
579
580
581 list_colorize = []
582 list_color_links = []
583 list_color_basis = []
584 list_color_matrices = []
585 real_me_list = []
586 me_id_list = []
587
588 matrix_elements = FKSHelasProcessList()
589
590 for i, proc in enumerate(fksprocs):
591 logger.info("Generating Helas calls for FKS %s (%d / %d)" % \
592 (proc.get_born_nice_string().\
593 replace('Process', 'process'),
594 i + 1, len(fksprocs)))
595 matrix_element_list = [\
596 FKSHelasProcess(proc, self['real_matrix_elements'],
597 [amp for amp in fksmulti['real_amplitudes'] if amp['diagrams']],
598 loop_optimized = self.loop_optimized,
599 decay_ids=decay_ids,
600 gen_color=False)]
601
602 for matrix_element in matrix_element_list:
603 assert isinstance(matrix_element, FKSHelasProcess), \
604 "Not a FKSHelasProcess: %s" % matrix_element
605
606 try:
607
608
609
610 other = \
611 matrix_elements[matrix_elements.index(matrix_element)]
612 except ValueError:
613
614
615 if matrix_element.born_me.get('processes') and \
616 matrix_element.born_me.get('diagrams'):
617 matrix_elements.append(matrix_element)
618
619 if not gen_color:
620 continue
621
622
623
624
625 col_basis = color_amp.ColorBasis()
626 new_amp = matrix_element.born_me.get_base_amplitude()
627 matrix_element.born_me.set('base_amplitude', new_amp)
628 colorize_obj = col_basis.create_color_dict_list(new_amp)
629
630 try:
631
632
633
634 col_index = list_colorize.index(colorize_obj)
635 logger.info(\
636 "Reusing existing color information for %s" % \
637 matrix_element.born_me.get('processes')\
638 [0].nice_string(print_weighted=False).\
639 replace('Process', 'process'))
640 except ValueError:
641
642
643 list_colorize.append(colorize_obj)
644 col_basis.build()
645 list_color_basis.append(col_basis)
646 col_matrix = color_amp.ColorMatrix(col_basis)
647 list_color_matrices.append(col_matrix)
648 col_index = -1
649
650 logger.info(\
651 "Processing color information for %s" % \
652 matrix_element.born_me.get('processes')[0].\
653 nice_string(print_weighted=False).\
654 replace('Process', 'process'))
655 matrix_element.born_me.set('color_basis', list_color_basis[col_index])
656 matrix_element.born_me.set('color_matrix', list_color_matrices[col_index])
657 else:
658
659
660 other.add_process(matrix_element)
661
662 for me in matrix_elements:
663 me.set_color_links()
664 return matrix_elements
665
666
668 """class to handle lists of FKSHelasProcesses"""
669
671 """Test if object obj is a valid FKSProcess for the list."""
672 return isinstance(obj, FKSHelasProcess)
673
674
676 """class to generate the Helas calls for a FKSProcess. Contains:
677 -- born ME
678 -- list of FKSHelasRealProcesses
679 -- color links
680 -- charges
681 -- extra MEs used as counterterms
682 """
683
684 - def __init__(self, fksproc=None, real_me_list =[], real_amp_list=[],
685 loop_optimized = False, **opts):
686 """ constructor, starts from a FKSProcess,
687 sets reals and color links. Real_me_list and real_amp_list are the lists of pre-genrated
688 matrix elements in 1-1 correspondence with the amplitudes"""
689
690 if fksproc != None:
691 self.born_me = helas_objects.HelasMatrixElement(fksproc.born_amp, **opts)
692
693 self.real_processes = []
694 self.extra_cnt_me_list = []
695 self.perturbation = fksproc.perturbation
696 self.charges_born = fksproc.get_charges()
697 real_amps_new = []
698
699 for extra_cnt in fksproc.extra_cnt_amp_list:
700 self.extra_cnt_me_list.append(helas_objects.HelasMatrixElement(extra_cnt,gen_color=True))
701
702
703 if fksproc.ncores_for_proc_gen:
704
705 for real_me, proc in zip(real_me_list,fksproc.real_amps):
706 fksreal_me = FKSHelasRealProcess(proc, real_me, **opts)
707 try:
708 other = self.real_processes[self.real_processes.index(fksreal_me)]
709 other.matrix_element.get('processes').extend(\
710 fksreal_me.matrix_element.get('processes') )
711 except ValueError:
712 if fksreal_me.matrix_element.get('processes') and \
713 fksreal_me.matrix_element.get('diagrams'):
714 self.real_processes.append(fksreal_me)
715 real_amps_new.append(proc)
716 else:
717
718 for proc in fksproc.real_amps:
719 if proc.amplitude['diagrams']:
720 fksreal_me = FKSHelasRealProcess(proc, real_me_list, real_amp_list, **opts)
721 try:
722 other = self.real_processes[self.real_processes.index(fksreal_me)]
723 other.matrix_element.get('processes').extend(\
724 fksreal_me.matrix_element.get('processes') )
725 except ValueError:
726 if fksreal_me.matrix_element.get('processes') and \
727 fksreal_me.matrix_element.get('diagrams'):
728 self.real_processes.append(fksreal_me)
729 real_amps_new.append(proc)
730
731 fksproc.real_amps = real_amps_new
732 if fksproc.virt_amp:
733 self.virt_matrix_element = \
734 loop_helas_objects.LoopHelasMatrixElement(fksproc.virt_amp,
735 optimized_output = loop_optimized)
736 else:
737 self.virt_matrix_element = None
738 self.color_links = []
739
740
742 """this function computes and returns the color links, it should be called
743 after the initialization and the setting of the color basis"""
744 if not self.color_links:
745 legs = self.born_me.get('base_amplitude').get('process').get('legs')
746 model = self.born_me.get('base_amplitude').get('process').get('model')
747 color_links_info = fks_common.find_color_links(fks_common.to_fks_legs(legs, model),
748 symm = True, pert = self.perturbation)
749 col_basis = self.born_me.get('color_basis')
750 self.color_links = fks_common.insert_color_links(col_basis,
751 col_basis.create_color_dict_list(
752 self.born_me.get('base_amplitude')),
753 color_links_info)
754
756 """Returns the list of the fks infos for all processes in the format
757 {n_me, pdgs, fks_info}, where n_me is the number of real_matrix_element the configuration
758 belongs to"""
759 info_list = []
760 for n, real in enumerate(self.real_processes):
761 pdgs = [l['id'] for l in real.matrix_element.get_base_amplitude()['process']['legs']]
762 for info in real.fks_infos:
763 info_list.append({'n_me' : n + 1,'pdgs' : pdgs, 'fks_info' : info})
764 return info_list
765
766
768 """Returns the pdgs of the legs in the form "i1 i2 -> f1 f2 ...", which may
769 be useful (eg. to be written in a B-LH order file)"""
770
771 initial = ''
772 final = ''
773 for leg in self.born_me.get('processes')[0].get('legs'):
774 if leg.get('state'):
775 final += '%d ' % leg.get('id')
776 else:
777 initial += '%d ' % leg.get('id')
778 return initial + '-> ' + final
779
780
781 - def get(self, key):
782 """the get function references to the born
783 matrix element
784 """
785 return self.born_me.get(key)
786
787
789 """the get_used_lorentz function references to born, reals
790 and virtual matrix elements"""
791 lorentz_list = self.born_me.get_used_lorentz()
792 for real in self.real_processes:
793 lorentz_list.extend(real.matrix_element.get_used_lorentz())
794 if self.virt_matrix_element:
795 lorentz_list.extend(self.virt_matrix_element.get_used_lorentz())
796
797 return list(set(lorentz_list))
798
799
801 """the get_used_couplings function references to born, reals
802 and virtual matrix elements"""
803 coupl_list = self.born_me.get_used_couplings()
804 for real in self.real_processes:
805 coupl_list.extend([c for c in\
806 real.matrix_element.get_used_couplings()])
807 if self.virt_matrix_element:
808 coupl_list.extend(self.virt_matrix_element.get_used_couplings())
809 return coupl_list
810
812 """the nexternal_ninitial function references to the real emissions if they have been
813 generated, otherwise to the born"""
814 if self.real_processes:
815 (nexternal, ninitial) = self.real_processes[0].matrix_element.get_nexternal_ninitial()
816 else:
817 (nexternal, ninitial) = self.born_me.get_nexternal_ninitial()
818 nexternal += 1
819 return (nexternal, ninitial)
820
822 """the equality between two FKSHelasProcesses is defined up to the
823 color links"""
824
825 selftag = helas_objects.IdentifyMETag.\
826 create_tag(self.born_me.get('base_amplitude'))
827 othertag = helas_objects.IdentifyMETag.\
828 create_tag(other.born_me.get('base_amplitude'))
829
830 if selftag != othertag:
831 return False
832
833
834 if self.virt_matrix_element != other.virt_matrix_element:
835 return False
836
837
838 reals2 = copy.copy(other.real_processes)
839
840 for real in self.real_processes:
841 try:
842 reals2.remove(real)
843 except ValueError:
844 return False
845
846 if not reals2:
847 return True
848 else:
849 return False
850
851
853 """Inequality operator
854 """
855 return not self.__eq__(other)
856
857
859 """adds processes from born and reals of other to itself. Note that
860 corresponding real processes may not be in the same order. This is
861 taken care of by constructing the list of self_reals.
862 """
863
864
865 this_pdgs = [[leg['id'] for leg in proc['legs']] \
866 for proc in self.born_me['processes']]
867 for oth_proc in other.born_me['processes']:
868 oth_pdgs = [leg['id'] for leg in oth_proc['legs']]
869 if oth_pdgs not in this_pdgs:
870 self.born_me['processes'].append(oth_proc)
871 this_pdgs.append(oth_pdgs)
872
873
874 if self.virt_matrix_element and other.virt_matrix_element:
875 self.virt_matrix_element.get('processes').extend(
876 other.virt_matrix_element.get('processes'))
877
878
879 self_reals = [real.matrix_element for real in self.real_processes]
880 for oth_real in other.real_processes:
881
882 try:
883
884
885 this_real = self.real_processes[self.real_processes.index(oth_real)]
886 except ValueError:
887 raise fks_common.FKSProcessError('add_process: error in combination of real MEs')
888
889 this_pdgs = [[leg['id'] for leg in proc['legs']] \
890 for proc in this_real.matrix_element['processes']]
891 for oth_proc in oth_real.matrix_element['processes']:
892 oth_pdgs = [leg['id'] for leg in oth_proc['legs']]
893 if oth_pdgs not in this_pdgs:
894 this_real.matrix_element['processes'].append(oth_proc)
895 this_pdgs.append(oth_pdgs)
896
897
898
900 """class to generate the Helas calls for a FKSRealProcess
901 contains:
902 -- colors
903 -- charges
904 -- i/j/ij fks, ij refers to the born leglist
905 -- ijglu
906 -- need_color_links
907 -- fks_j_from_i
908 -- matrix element
909 -- is_to_integrate
910 -- leg permutation<<REMOVED"""
911
912 - def __init__(self, fksrealproc=None, real_me_list = [], real_amp_list =[], **opts):
913 """constructor, starts from a fksrealproc and then calls the
914 initialization for HelasMatrixElement.
915 Sets i/j fks and the permutation.
916 real_me_list and real_amp_list are the lists of pre-generated matrix elements in 1-1
917 correspondance with the amplitudes"""
918
919 if fksrealproc != None:
920 self.isfinite = False
921 self.colors = fksrealproc.colors
922 self.charges = fksrealproc.charges
923 self.fks_infos = fksrealproc.fks_infos
924 self.is_to_integrate = fksrealproc.is_to_integrate
925
926
927
928 if type(real_me_list) == list and len(real_me_list) != len(real_amp_list):
929 raise fks_common.FKSProcessError(
930 'not same number of amplitudes and matrix elements: %d, %d' % \
931 (len(real_amp_list), len(real_me_list)))
932 if type(real_me_list) == list and real_me_list and real_amp_list:
933 self.matrix_element = copy.deepcopy(real_me_list[real_amp_list.index(fksrealproc.amplitude)])
934 self.matrix_element['processes'] = copy.deepcopy(self.matrix_element['processes'])
935
936 elif type(real_me_list) == helas_objects.HelasMatrixElement:
937
938 assert fksrealproc.process in real_me_list['processes'], \
939 "Inconsistent input in FKSHelasRealProcess\nfksrealproc: %s\nME: %s" % \
940 (fksrealproc.process.nice_string(),
941 ' - '.join([p.nice_string() for p in real_me_list['processes']]))
942 self.matrix_element = real_me_list
943
944 else:
945
946 if real_me_list and real_amp_list:
947 self.matrix_element = copy.deepcopy(real_me_list[real_amp_list.index(fksrealproc.amplitude)])
948 self.matrix_element['processes'] = copy.deepcopy(self.matrix_element['processes'])
949 else:
950 logger.info('generating matrix element...')
951 self.matrix_element = helas_objects.HelasMatrixElement(
952 fksrealproc.amplitude, **opts)
953
954 self.matrix_element.get('color_basis').build(
955 self.matrix_element.get('base_amplitude'))
956 self.matrix_element.set('color_matrix',
957 color_amp.ColorMatrix(
958 self.matrix_element.get('color_basis')))
959
960 self.fks_j_from_i = fksrealproc.fks_j_from_i
961
965
967 """Equality operator:
968 compare two FKSHelasRealProcesses by comparing their dictionaries"""
969
970 for key in [k for k in self.__dict__.keys() if k not in ['fks_infos', 'charges']]:
971 if self.__dict__[key] != other.__dict__[key]:
972 return False
973
974
975 if (len(self.fks_infos) != len(other.fks_infos)):
976 return False
977
978 tocheck_info = [k for k in self.fks_infos[0].keys() if k not in ['ij_id', 'underlying_born']]
979 for selfinfo, otherinfo in zip(self.fks_infos, other.fks_infos):
980 if len(selfinfo['underlying_born']) != len(otherinfo['underlying_born']):
981 return False
982 for key in tocheck_info:
983 if selfinfo[key] != otherinfo [key]:
984 return False
985
986 return True
987
988
990 """Inequality operator:
991 compare two FKSHelasRealProcesses by comparing their dictionaries"""
992 return not self.__eq__(other)
993