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