Package madgraph :: Package fks :: Module fks_helas_objects
[hide private]
[frames] | no frames]

Source Code for Module madgraph.fks.fks_helas_objects

  1  ################################################################################ 
  2  # 
  3  # Copyright (c) 2009 The MadGraph5_aMC@NLO Development team and Contributors 
  4  # 
  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. 
  8  # 
  9  # It is subject to the MadGraph5_aMC@NLO license which should accompany this  
 10  # distribution. 
 11  # 
 12  # For more information, visit madgraph.phys.ucl.ac.be and amcatnlo.web.cern.ch 
 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  import madgraph.various.misc as misc 
 31  import copy 
 32  import logging 
 33  import array 
 34  import multiprocessing 
 35  import signal 
 36  import tempfile 
 37  import six.moves.cPickle 
 38  import itertools 
 39  import os 
 40  import sys 
 41  from six.moves import zip 
 42  from madgraph import MG5DIR 
 43  pjoin = os.path.join 
 44  logger = logging.getLogger('madgraph.fks_helas_objects') 
 45   
 46   
 47  #functions to be used in the ncores_for_proc_gen mode 
48 -def async_generate_real(args):
49 i = args[0] 50 real_amp = args[1] 51 #amplitude generation 52 amplitude = real_amp.generate_real_amplitude() 53 helasreal = helas_objects.HelasMatrixElement(amplitude) 54 logger.info('Generating real %s' % \ 55 real_amp.process.nice_string(print_weighted=False).replace('Process', 'process')) 56 57 # Keep track of already generated color objects, to reuse as 58 # much as possible 59 list_colorize = [] 60 list_color_basis = [] 61 list_color_matrices = [] 62 63 # Now this keeps track of the color matrices created from the loop-born 64 # color basis. Keys are 2-tuple with the index of the loop and born basis 65 # in the list above and the value is the resulting matrix. 66 dict_loopborn_matrices = {} 67 # The dictionary below is simply a container for convenience to be 68 # passed to the function process_color. 69 color_information = { 'list_colorize' : list_colorize, 70 'list_color_basis' : list_color_basis, 71 'list_color_matrices' : list_color_matrices, 72 'dict_loopborn_matrices' : dict_loopborn_matrices} 73 74 helas_objects.HelasMultiProcess.process_color(helasreal,color_information) 75 76 outdata = [amplitude,helasreal] 77 78 output = tempfile.NamedTemporaryFile(delete = False) 79 80 six.moves.cPickle.dump(outdata,output,protocol=2) 81 output.close() 82 83 return [output.name,helasreal.get_num_configs(),helasreal.get_nexternal_ninitial()[0]]
84 85
86 -def async_generate_born(args):
87 i = args[0] 88 born = args[1] 89 born_pdg_list = args[2] 90 loop_orders = args[3] 91 pdg_list = args[4] 92 loop_optimized = args[5] 93 OLP = args[6] 94 realmapout = args[7] 95 96 logger.info('Generating born %s' % \ 97 born.born_proc.nice_string(print_weighted=False).replace('Process', 'process')) 98 99 #load informations on reals from temp files 100 helasreal_list = [] 101 for amp in born.real_amps: 102 idx = pdg_list.index(amp.pdgs) 103 infilename = realmapout[idx] 104 infile = open(infilename,'rb') 105 realdata = six.moves.cPickle.load(infile) 106 infile.close() 107 amp.amplitude = realdata[0] 108 helasreal_list.append(realdata[1]) 109 110 born.link_born_reals() 111 112 for amp in born.real_amps: 113 amp.find_fks_j_from_i(born_pdg_list) 114 115 # generate the virtuals if needed 116 has_loops = False 117 if born.born_proc.get('NLO_mode') == 'all' and OLP == 'MadLoop': 118 myproc = copy.copy(born.born_proc) 119 # take the orders that are actually used by the matrix element 120 myproc['orders'] = loop_orders 121 myproc['legs'] = fks_common.to_legs(copy.copy(myproc['legs'])) 122 myamp = loop_diagram_generation.LoopAmplitude(myproc) 123 if myamp.get('diagrams'): 124 has_loops = True 125 born.virt_amp = myamp 126 127 helasfull = FKSHelasProcess(born, helasreal_list, 128 loop_optimized = loop_optimized, 129 decay_ids=[], 130 gen_color=False) 131 132 processes = helasfull.born_matrix_element.get('processes') 133 134 max_configs = helasfull.born_matrix_element.get_num_configs() 135 136 metag = helas_objects.IdentifyMETag.create_tag(helasfull.born_matrix_element.get('base_amplitude')) 137 138 outdata = helasfull 139 140 output = tempfile.NamedTemporaryFile(delete = False) 141 six.moves.cPickle.dump(outdata,output,protocol=2) 142 output.close() 143 144 return [output.name,metag,has_loops,processes,max_configs]
145 146
147 -def async_finalize_matrix_elements(args):
148 149 i = args[0] 150 mefile = args[1] 151 duplist = args[2] 152 153 infile = open(mefile,'rb') 154 me = six.moves.cPickle.load(infile) 155 infile.close() 156 157 #set unique id based on position in unique me list 158 me.get('processes')[0].set('uid', i) 159 160 # Always create an empty color basis, and the 161 # list of raw colorize objects (before 162 # simplification) associated with amplitude 163 col_basis = color_amp.ColorBasis() 164 new_amp = me.born_matrix_element.get_base_amplitude() 165 me.born_matrix_element.set('base_amplitude', new_amp) 166 colorize_obj = col_basis.create_color_dict_list(new_amp) 167 168 col_basis.build() 169 col_matrix = color_amp.ColorMatrix(col_basis) 170 171 me.born_matrix_element.set('color_basis',col_basis) 172 me.born_matrix_element.set('color_matrix',col_matrix) 173 174 for iother,othermefile in enumerate(duplist): 175 infileother = open(othermefile,'rb') 176 otherme = six.moves.cPickle.load(infileother) 177 infileother.close() 178 me.add_process(otherme) 179 180 me.set_color_links() 181 182 initial_states=[] 183 for fksreal in me.real_processes: 184 # Pick out all initial state particles for the two beams 185 initial_states.append(sorted(list(set((p.get_initial_pdg(1),p.get_initial_pdg(2)) for \ 186 p in fksreal.matrix_element.get('processes'))))) 187 188 if me.virt_matrix_element: 189 has_virtual = True 190 else: 191 has_virtual = False 192 193 #data to write to file 194 outdata = me 195 196 output = tempfile.NamedTemporaryFile(delete = False) 197 six.moves.cPickle.dump(outdata,output,protocol=2) 198 output.close() 199 200 #data to be returned to parent process (filename plus small objects only) 201 return [output.name,initial_states,me.get_used_lorentz(),me.get_used_couplings(),has_virtual]
202 203
204 -class FKSHelasMultiProcess(helas_objects.HelasMultiProcess):
205 """class to generate the helas calls for a FKSMultiProcess""" 206
207 - def get_sorted_keys(self):
208 """Return particle property names as a nicely sorted list.""" 209 keys = super(FKSHelasMultiProcess, self).get_sorted_keys() 210 keys += ['real_matrix_elements', ['has_isr'], ['has_fsr'], 211 'used_lorentz', 'used_couplings', 'max_configs', 'max_particles', 'processes'] 212 return keys
213
214 - def filter(self, name, value):
215 """Filter for valid leg property values.""" 216 217 if name == 'real_matrix_elements': 218 if not isinstance(value, helas_objects.HelasMultiProcess): 219 raise self.PhysicsObjectError("%s is not a valid list for real_matrix_element " % str(value))
220
221 - def __init__(self, fksmulti, loop_optimized = False, gen_color =True, decay_ids =[]):
222 """Initialization from a FKSMultiProcess""" 223 224 #swhich the other loggers off 225 loggers_off = [logging.getLogger('madgraph.diagram_generation'), 226 logging.getLogger('madgraph.helas_objects')] 227 old_levels = [logg.level for logg in loggers_off] 228 for logg in loggers_off: 229 logg.setLevel(logging.WARNING) 230 231 self.loop_optimized = loop_optimized 232 233 self['used_lorentz'] = [] 234 self['used_couplings'] = [] 235 self['processes'] = [] 236 237 self['max_particles'] = -1 238 self['max_configs'] = -1 239 240 if not fksmulti['ncores_for_proc_gen']: 241 # generate the real ME's if they are needed. 242 # note that it may not be always the case, e.g. it the NLO_mode is LOonly 243 if fksmulti['real_amplitudes']: 244 logger.info('Generating real emission matrix-elements...') 245 self['real_matrix_elements'] = self.generate_matrix_elements( 246 copy.copy(fksmulti['real_amplitudes']), combine_matrix_elements = False) 247 else: 248 self['real_matrix_elements'] = helas_objects.HelasMatrixElementList() 249 250 self['matrix_elements'] = self.generate_matrix_elements_fks( 251 fksmulti, 252 gen_color, decay_ids) 253 self['initial_states']=[] 254 self['has_loops'] = len(self.get_virt_matrix_elements()) > 0 255 256 else: 257 self['has_loops'] = False 258 #more efficient generation 259 born_procs = fksmulti.get('born_processes') 260 born_pdg_list = [[l['id'] for l in born.born_proc['legs']] \ 261 for born in born_procs ] 262 loop_orders = {} 263 for born in born_procs: 264 for coup, val in fks_common.find_orders(born.born_amp).items(): 265 try: 266 loop_orders[coup] = max([loop_orders[coup], val]) 267 except KeyError: 268 loop_orders[coup] = val 269 pdg_list = [] 270 real_amp_list = [] 271 for born in born_procs: 272 for amp in born.real_amps: 273 if not pdg_list.count(amp.pdgs): 274 pdg_list.append(amp.pdgs) 275 real_amp_list.append(amp) 276 277 #generating and store in tmp files all output corresponding to each real_amplitude 278 real_out_list = [] 279 realmapin = [] 280 for i,real_amp in enumerate(real_amp_list): 281 realmapin.append([i,real_amp]) 282 283 # start the pool instance with a signal instance to catch ctr+c 284 original_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN) 285 if fksmulti['ncores_for_proc_gen'] < 0: # use all cores 286 pool = multiprocessing.Pool(maxtasksperchild=1) 287 else: 288 pool = multiprocessing.Pool(processes=fksmulti['ncores_for_proc_gen'],maxtasksperchild=1) 289 signal.signal(signal.SIGINT, original_sigint_handler) 290 291 logger.info('Generating real matrix elements...') 292 import time 293 try: 294 # the very large timeout passed to get is to be able to catch 295 # KeyboardInterrupts 296 modelpath = born_procs[0].born_proc['model'].get('modelpath') 297 #model = self.get('processes')[0].get('model') 298 with misc.TMP_variable(sys, 'path', sys.path + [pjoin(MG5DIR, 'models'), modelpath]): 299 realmapout = pool.map_async(async_generate_real,realmapin).get(9999999) 300 except KeyboardInterrupt: 301 pool.terminate() 302 raise KeyboardInterrupt 303 304 realmapfiles = [] 305 for realout in realmapout: 306 realmapfiles.append(realout[0]) 307 308 logger.info('Generating born and virtual matrix elements...') 309 #now loop over born and consume reals, generate virtuals 310 bornmapin = [] 311 OLP=fksmulti['OLP'] 312 for i,born in enumerate(born_procs): 313 bornmapin.append([i,born,born_pdg_list,loop_orders,pdg_list,loop_optimized,OLP,realmapfiles]) 314 315 try: 316 bornmapout = pool.map_async(async_generate_born,bornmapin).get(9999999) 317 except KeyboardInterrupt: 318 pool.terminate() 319 raise KeyboardInterrupt 320 321 #remove real temp files 322 for realtmp in realmapout: 323 os.remove(realtmp[0]) 324 325 logger.info('Collecting infos and finalizing matrix elements...') 326 unique_me_list = [] 327 duplicate_me_lists = [] 328 for bornout in bornmapout: 329 mefile = bornout[0] 330 metag = bornout[1] 331 has_loops = bornout[2] 332 self['has_loops'] = self['has_loops'] or has_loops 333 processes = bornout[3] 334 self['processes'].extend(processes) 335 self['max_particles'] = max([self['max_configs']] + [len(p['legs']) + 1 for p in bornout[3]]) 336 self['max_configs'] = max(self['max_configs'], bornout[4]) 337 unique = True 338 for ime2,bornout2 in enumerate(unique_me_list): 339 mefile2 = bornout2[0] 340 metag2 = bornout2[1] 341 if metag==metag2: 342 duplicate_me_lists[ime2].append(mefile) 343 unique = False 344 break; 345 if unique: 346 unique_me_list.append(bornout) 347 duplicate_me_lists.append([]) 348 349 memapin = [] 350 for i,bornout in enumerate(unique_me_list): 351 mefile = bornout[0] 352 memapin.append([i,mefile, duplicate_me_lists[i]]) 353 354 try: 355 memapout = pool.map_async(async_finalize_matrix_elements,memapin).get(9999999) 356 except KeyboardInterrupt: 357 pool.terminate() 358 raise KeyboardInterrupt 359 360 #remove born+virtual temp files 361 for bornout in bornmapout: 362 mefile = bornout[0] 363 os.remove(mefile) 364 365 pool.close() 366 pool.join() 367 368 #set final list of matrix elements (paths to temp files) 369 matrix_elements = [] 370 for meout in memapout: 371 matrix_elements.append(meout[0]) 372 373 self['matrix_elements']=matrix_elements 374 375 #cache information needed for output which will not be available from 376 #the matrix elements later 377 initial_states = [] 378 for meout in memapout: 379 me_initial_states = meout[1] 380 for state in me_initial_states: 381 initial_states.append(state) 382 383 # remove doubles from the list 384 checked = [] 385 for e in initial_states: 386 if e not in checked: 387 checked.append(e) 388 initial_states=checked 389 390 self['initial_states']=initial_states 391 392 helas_list = [] 393 for meout in memapout: 394 helas_list.extend(meout[2]) 395 self['used_lorentz']=list(set(helas_list)) 396 397 coupling_list = [] 398 for meout in memapout: 399 coupling_list.extend([c for l in meout[3] for c in l]) 400 self['used_couplings'] = list(set(coupling_list)) 401 402 has_virtuals = False 403 for meout in memapout: 404 if meout[4]: 405 has_virtuals = True 406 break 407 self['has_virtuals'] = has_virtuals 408 409 configs_list = [self['max_configs']] 410 for meout in realmapout: 411 configs_list.append(meout[1]) 412 self['max_configs'] = max(configs_list) 413 414 nparticles_list = [self['max_particles']] 415 for meout in realmapout: 416 nparticles_list.append(meout[2]) 417 self['max_particles'] = max(nparticles_list) 418 419 self['has_isr'] = fksmulti['has_isr'] 420 self['has_fsr'] = fksmulti['has_fsr'] 421 422 logger.info('... Done') 423 424 for i, logg in enumerate(loggers_off): 425 logg.setLevel(old_levels[i])
426 427
428 - def get_used_lorentz(self):
429 """Return a list of (lorentz_name, conjugate, outgoing) with 430 all lorentz structures used by this HelasMultiProcess.""" 431 432 if not self['used_lorentz']: 433 helas_list = [] 434 for me in self.get('matrix_elements'): 435 helas_list.extend(me.get_used_lorentz()) 436 self['used_lorentz'] = list(set(helas_list)) 437 438 return self['used_lorentz']
439 440
441 - def get_used_couplings(self):
442 """Return a list with all couplings used by this 443 HelasMatrixElement.""" 444 445 if not self['used_couplings']: 446 coupling_list = [] 447 for me in self.get('matrix_elements'): 448 coupling_list.extend([c for l in me.get_used_couplings() for c in l]) 449 self['used_couplings'] = list(set(coupling_list)) 450 451 return self['used_couplings']
452 453
454 - def get_processes(self):
455 """Return a list with all couplings used by this 456 HelasMatrixElement.""" 457 458 if not self['processes']: 459 process_list = [] 460 for me in self.get('matrix_elements'): 461 process_list.extend(me.born_matrix_element.get('processes')) 462 self['processes'] = process_list 463 464 return self['processes']
465 466
467 - def get_max_configs(self):
468 """Return max_configs""" 469 470 if self['max_configs'] < 0: 471 try: 472 self['max_configs'] = max([me.get_num_configs() \ 473 for me in self['real_matrix_elements']]) 474 except ValueError: 475 pass 476 self['max_configs'] = max(self['max_configs'],\ 477 max([me.born_matrix_element.get_num_configs() \ 478 for me in self['matrix_elements']])) 479 480 return self['max_configs']
481 482
483 - def get_max_particles(self):
484 """Return max_paricles""" 485 486 if self['max_particles'] < 0: 487 self['max_particles'] = max([me.get_nexternal_ninitial()[0] \ 488 for me in self['matrix_elements']]) 489 490 return self['max_particles']
491 492
493 - def get_matrix_elements(self):
494 """Extract the list of matrix elements""" 495 return self.get('matrix_elements')
496 497
498 - def get_virt_matrix_elements(self):
499 """Extract the list of virtuals matrix elements""" 500 return [me.virt_matrix_element for me in self.get('matrix_elements') \ 501 if me.virt_matrix_element]
502 503
504 - def generate_matrix_elements_fks(self, fksmulti, gen_color = True, 505 decay_ids = []):
506 """Generate the HelasMatrixElements for the amplitudes, 507 identifying processes with identical matrix elements, as 508 defined by HelasMatrixElement.__eq__. Returns a 509 HelasMatrixElementList and an amplitude map (used by the 510 SubprocessGroup functionality). decay_ids is a list of decayed 511 particle ids, since those should not be combined even if 512 matrix element is identical.""" 513 514 fksprocs = fksmulti['born_processes'] 515 assert isinstance(fksprocs, fks_base.FKSProcessList), \ 516 "%s is not valid FKSProcessList" % \ 517 repr(fksprocs) 518 519 # Keep track of already generated color objects, to reuse as 520 # much as possible 521 list_colorize = [] 522 list_color_links =[] 523 list_color_basis = [] 524 list_color_matrices = [] 525 real_me_list = [] 526 me_id_list = [] 527 528 matrix_elements = FKSHelasProcessList() 529 530 for i, proc in enumerate(fksprocs): 531 logger.info("Generating Helas calls for FKS %s (%d / %d)" % \ 532 (proc.born_amp.get('process').nice_string(print_weighted = False).\ 533 replace('Process', 'process'), 534 i + 1, len(fksprocs))) 535 matrix_element_list = [FKSHelasProcess(proc, self['real_matrix_elements'], 536 fksmulti['real_amplitudes'], 537 loop_optimized = self.loop_optimized, 538 decay_ids=decay_ids, 539 gen_color=False)] 540 for matrix_element in matrix_element_list: 541 assert isinstance(matrix_element, FKSHelasProcess), \ 542 "Not a FKSHelasProcess: %s" % matrix_element 543 544 try: 545 # If an identical matrix element is already in the list, 546 # then simply add this process to the list of 547 # processes for that matrix element 548 other = \ 549 matrix_elements[matrix_elements.index(matrix_element)] 550 except ValueError: 551 # Otherwise, if the matrix element has any diagrams, 552 # add this matrix element. 553 if matrix_element.born_matrix_element.get('processes') and \ 554 matrix_element.born_matrix_element.get('diagrams'): 555 matrix_elements.append(matrix_element) 556 557 if not gen_color: 558 continue 559 560 # Always create an empty color basis, and the 561 # list of raw colorize objects (before 562 # simplification) associated with amplitude 563 col_basis = color_amp.ColorBasis() 564 new_amp = matrix_element.born_matrix_element.get_base_amplitude() 565 matrix_element.born_matrix_element.set('base_amplitude', new_amp) 566 colorize_obj = col_basis.create_color_dict_list(new_amp) 567 568 try: 569 # If the color configuration of the ME has 570 # already been considered before, recycle 571 # the information 572 col_index = list_colorize.index(colorize_obj) 573 logger.info(\ 574 "Reusing existing color information for %s" % \ 575 matrix_element.born_matrix_element.get('processes')\ 576 [0].nice_string(print_weighted=False).\ 577 replace('Process', 'process')) 578 except ValueError: 579 # If not, create color basis and color 580 # matrix accordingly 581 list_colorize.append(colorize_obj) 582 col_basis.build() 583 list_color_basis.append(col_basis) 584 col_matrix = color_amp.ColorMatrix(col_basis) 585 list_color_matrices.append(col_matrix) 586 col_index = -1 587 588 logger.info(\ 589 "Processing color information for %s" % \ 590 matrix_element.born_matrix_element.\ 591 get('processes')[0].nice_string(print_weighted=False).\ 592 replace('Process', 'process')) 593 matrix_element.born_matrix_element.set('color_basis', 594 list_color_basis[col_index]) 595 matrix_element.born_matrix_element.set('color_matrix', 596 list_color_matrices[col_index]) 597 else: 598 # this is in order not to handle valueErrors coming from other plaeces, 599 # e.g. from the add_process function 600 other.add_process(matrix_element) 601 602 for me in matrix_elements: 603 me.set_color_links() 604 return matrix_elements
605 606
607 -class FKSHelasProcessList(MG.PhysicsObjectList):
608 """class to handle lists of FKSHelasProcesses""" 609
610 - def is_valid_element(self, obj):
611 """Test if object obj is a valid FKSProcess for the list.""" 612 return isinstance(obj, FKSHelasProcess)
613 614
615 -class FKSHelasProcess(object):
616 """class to generate the Helas calls for a FKSProcess. Contains: 617 -- born ME 618 -- list of FKSHelasRealProcesses 619 -- color links""" 620
621 - def __init__(self, fksproc=None, real_me_list =[], real_amp_list=[], 622 loop_optimized = False, **opts):#test written
623 """ constructor, starts from a FKSProcess, 624 sets reals and color links. Real_me_list and real_amp_list are the lists of pre-genrated 625 matrix elements in 1-1 correspondence with the amplitudes""" 626 627 if fksproc != None: 628 self.born_matrix_element = helas_objects.HelasMatrixElement( 629 fksproc.born_amp, **opts) 630 self.real_processes = [] 631 self.orders = fksproc.born_proc.get('orders') 632 self.perturbation = fksproc.perturbation 633 real_amps_new = [] 634 # combine for example u u~ > t t~ and d d~ > t t~ 635 if fksproc.ncores_for_proc_gen: 636 # new NLO (multicore) generation mode 637 for real_me, proc in zip(real_me_list,fksproc.real_amps): 638 fksreal_me = FKSHelasRealProcess(proc, real_me, **opts) 639 try: 640 other = self.real_processes[self.real_processes.index(fksreal_me)] 641 other.matrix_element.get('processes').extend(\ 642 fksreal_me.matrix_element.get('processes') ) 643 except ValueError: 644 if fksreal_me.matrix_element.get('processes') and \ 645 fksreal_me.matrix_element.get('diagrams'): 646 self.real_processes.append(fksreal_me) 647 real_amps_new.append(proc) 648 else: 649 #old mode 650 for proc in fksproc.real_amps: 651 fksreal_me = FKSHelasRealProcess(proc, real_me_list, real_amp_list, **opts) 652 try: 653 other = self.real_processes[self.real_processes.index(fksreal_me)] 654 other.matrix_element.get('processes').extend(\ 655 fksreal_me.matrix_element.get('processes') ) 656 except ValueError: 657 if fksreal_me.matrix_element.get('processes') and \ 658 fksreal_me.matrix_element.get('diagrams'): 659 self.real_processes.append(fksreal_me) 660 real_amps_new.append(proc) 661 fksproc.real_amps = real_amps_new 662 if fksproc.virt_amp: 663 self.virt_matrix_element = \ 664 loop_helas_objects.LoopHelasMatrixElement(fksproc.virt_amp, 665 optimized_output = loop_optimized) 666 else: 667 self.virt_matrix_element = None 668 # self.color_links_info = fksproc.find_color_links() 669 self.color_links = []
670 684
685 - def get_fks_info_list(self):
686 """Returns the list of the fks infos for all processes in the format 687 {n_me, pdgs, fks_info}, where n_me is the number of real_matrix_element the configuration 688 belongs to""" 689 info_list = [] 690 for n, real in enumerate(self.real_processes): 691 pdgs = [l['id'] for l in real.matrix_element.get_base_amplitude()['process']['legs']] 692 for info in real.fks_infos: 693 info_list.append({'n_me' : n + 1,'pdgs' : pdgs, 'fks_info' : info}) 694 return info_list
695 696
697 - def get_lh_pdg_string(self):
698 """Returns the pdgs of the legs in the form "i1 i2 -> f1 f2 ...", which may 699 be useful (eg. to be written in a B-LH order file)""" 700 701 initial = '' 702 final = '' 703 for leg in self.born_matrix_element.get('processes')[0].get('legs'): 704 if leg.get('state'): 705 final += '%d ' % leg.get('id') 706 else: 707 initial += '%d ' % leg.get('id') 708 return initial + '-> ' + final
709 710
711 - def get(self, key):
712 """the get function references to born_matrix_element""" 713 return self.born_matrix_element.get(key)
714
715 - def get_used_lorentz(self):
716 """the get_used_lorentz function references to born, reals 717 and virtual matrix elements""" 718 lorentz_list = self.born_matrix_element.get_used_lorentz() 719 for real in self.real_processes: 720 lorentz_list.extend(real.matrix_element.get_used_lorentz()) 721 if self.virt_matrix_element: 722 lorentz_list.extend(self.virt_matrix_element.get_used_lorentz()) 723 724 return list(set(lorentz_list))
725
726 - def get_used_couplings(self):
727 """the get_used_couplings function references to born, reals 728 and virtual matrix elements""" 729 coupl_list = self.born_matrix_element.get_used_couplings() 730 for real in self.real_processes: 731 coupl_list.extend([c for c in\ 732 real.matrix_element.get_used_couplings()]) 733 if self.virt_matrix_element: 734 coupl_list.extend(self.virt_matrix_element.get_used_couplings()) 735 return coupl_list
736
737 - def get_nexternal_ninitial(self):
738 """the nexternal_ninitial function references to the real emissions if they have been 739 generated, otherwise to the born""" 740 if self.real_processes: 741 (nexternal, ninitial) = self.real_processes[0].matrix_element.get_nexternal_ninitial() 742 else: 743 (nexternal, ninitial) = self.born_matrix_element.get_nexternal_ninitial() 744 nexternal += 1 745 return (nexternal, ninitial)
746
747 - def __eq__(self, other):
748 """the equality between two FKSHelasProcesses is defined up to the 749 color links""" 750 selftag = helas_objects.IdentifyMETag.create_tag(self.born_matrix_element.get('base_amplitude')) 751 othertag = helas_objects.IdentifyMETag.create_tag(other.born_matrix_element.get('base_amplitude')) 752 753 if self.born_matrix_element != other.born_matrix_element or \ 754 selftag != othertag: 755 return False 756 757 reals2 = copy.copy(other.real_processes) 758 for real in self.real_processes: 759 try: 760 reals2.remove(real) 761 except ValueError: 762 return False 763 if not reals2: 764 return True 765 else: 766 return False
767
768 - def add_process(self, other): #test written, ppwj
769 """adds processes from born and reals of other to itself. Note that 770 corresponding real processes may not be in the same order. This is 771 taken care of by constructing the list of self_reals.""" 772 self.born_matrix_element.get('processes').extend( 773 other.born_matrix_element.get('processes')) 774 if self.virt_matrix_element and other.virt_matrix_element: 775 self.virt_matrix_element.get('processes').extend( 776 other.virt_matrix_element.get('processes')) 777 self_reals = [real.matrix_element for real in self.real_processes] 778 for oth_real in other.real_processes: 779 this_real = self.real_processes[self_reals.index(oth_real.matrix_element)] 780 #need to store pdg lists rather than processes in order to keep mirror processes different 781 this_pdgs = [[leg['id'] for leg in proc['legs']] \ 782 for proc in this_real.matrix_element['processes']] 783 for oth_proc in oth_real.matrix_element['processes']: 784 oth_pdgs = [leg['id'] for leg in oth_proc['legs']] 785 if oth_pdgs not in this_pdgs: 786 this_real.matrix_element['processes'].append(oth_proc) 787 this_pdgs.append(oth_pdgs) 788 789 # if p not in self.real_processes[\ 790 # self_reals.index(oth_real.matrix_element)].matrix_element['processes']]) 791 792
793 -class FKSHelasRealProcess(object): #test written
794 """class to generate the Helas calls for a FKSRealProcess 795 contains: 796 -- colors 797 -- charges 798 -- i/j/ij fks, ij refers to the born leglist 799 -- ijglu 800 -- need_color_links 801 -- fks_j_from_i 802 -- matrix element 803 -- is_to_integrate 804 -- leg permutation<<REMOVED""" 805
806 - def __init__(self, fksrealproc=None, real_me_list = [], real_amp_list =[], **opts):
807 """constructor, starts from a fksrealproc and then calls the 808 initialization for HelasMatrixElement. 809 Sets i/j fks and the permutation. 810 real_me_list and real_amp_list are the lists of pre-generated matrix elements in 1-1 811 correspondance with the amplitudes""" 812 813 if fksrealproc != None: 814 self.isfinite = False 815 self.colors = fksrealproc.colors 816 self.charges = fksrealproc.charges 817 self.fks_infos = fksrealproc.fks_infos 818 self.is_to_integrate = fksrealproc.is_to_integrate 819 820 # real_me_list is a list in the old NLO generation mode; 821 # in the new one it is a matrix element 822 if type(real_me_list) == list and len(real_me_list) != len(real_amp_list): 823 raise fks_common.FKSProcessError( 824 'not same number of amplitudes and matrix elements: %d, %d' % \ 825 (len(real_amp_list), len(real_me_list))) 826 if type(real_me_list) == list and real_me_list and real_amp_list: 827 self.matrix_element = copy.deepcopy(real_me_list[real_amp_list.index(fksrealproc.amplitude)]) 828 self.matrix_element['processes'] = copy.deepcopy(self.matrix_element['processes']) 829 830 elif type(real_me_list) == helas_objects.HelasMatrixElement: 831 #new NLO generation mode 832 self.matrix_element = real_me_list 833 834 else: 835 836 if real_me_list and real_amp_list: 837 self.matrix_element = copy.deepcopy(real_me_list[real_amp_list.index(fksrealproc.amplitude)]) 838 self.matrix_element['processes'] = copy.deepcopy(self.matrix_element['processes']) 839 else: 840 logger.info('generating matrix element...') 841 self.matrix_element = helas_objects.HelasMatrixElement( 842 fksrealproc.amplitude, **opts) 843 #generate the color for the real 844 self.matrix_element.get('color_basis').build( 845 self.matrix_element.get('base_amplitude')) 846 self.matrix_element.set('color_matrix', 847 color_amp.ColorMatrix( 848 self.matrix_element.get('color_basis'))) 849 #self.fks_j_from_i = fksrealproc.find_fks_j_from_i() 850 self.fks_j_from_i = fksrealproc.fks_j_from_i
851
852 - def get_nexternal_ninitial(self):
853 """Refers to the matrix_element function""" 854 return self.matrix_element.get_nexternal_ninitial()
855
856 - def __eq__(self, other):
857 """Equality operator: 858 compare two FKSHelasRealProcesses by comparing their dictionaries""" 859 860 if self.__dict__ == other.__dict__: 861 return True 862 else: 863 # failed = [] 864 # for key in self.__dict__: 865 # if self.__dict__[key] != other.__dict__[key]: 866 # failed.append(key) 867 # import madgraph.various.misc as misc 868 869 return False 870 871 872 return self.__dict__ == other.__dict__
873
874 - def __ne__(self, other):
875 """Inequality operator: 876 compare two FKSHelasRealProcesses by comparing their dictionaries""" 877 return not self.__eq__(other)
878