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