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 six.PY3: 286 ctx = multiprocessing.get_context('fork') 287 else: 288 ctx = multiprocessing 289 if fksmulti['ncores_for_proc_gen'] < 0: # use all cores 290 pool = ctx.Pool(maxtasksperchild=1) 291 else: 292 pool = ctx.Pool(processes=fksmulti['ncores_for_proc_gen'],maxtasksperchild=1) 293 signal.signal(signal.SIGINT, original_sigint_handler) 294 295 logger.info('Generating real matrix elements...') 296 import time 297 try: 298 # the very large timeout passed to get is to be able to catch 299 # KeyboardInterrupts 300 modelpath = born_procs[0].born_proc['model'].get('modelpath') 301 #model = self.get('processes')[0].get('model') 302 with misc.TMP_variable(sys, 'path', sys.path + [pjoin(MG5DIR, 'models'), modelpath]): 303 realmapout = pool.map_async(async_generate_real,realmapin).get(9999999) 304 except KeyboardInterrupt: 305 pool.terminate() 306 raise KeyboardInterrupt 307 308 realmapfiles = [] 309 for realout in realmapout: 310 realmapfiles.append(realout[0]) 311 312 logger.info('Generating born and virtual matrix elements...') 313 #now loop over born and consume reals, generate virtuals 314 bornmapin = [] 315 OLP=fksmulti['OLP'] 316 for i,born in enumerate(born_procs): 317 bornmapin.append([i,born,born_pdg_list,loop_orders,pdg_list,loop_optimized,OLP,realmapfiles]) 318 319 try: 320 bornmapout = pool.map_async(async_generate_born,bornmapin).get(9999999) 321 except KeyboardInterrupt: 322 pool.terminate() 323 raise KeyboardInterrupt 324 325 #remove real temp files 326 for realtmp in realmapout: 327 os.remove(realtmp[0]) 328 329 logger.info('Collecting infos and finalizing matrix elements...') 330 unique_me_list = [] 331 duplicate_me_lists = [] 332 for bornout in bornmapout: 333 mefile = bornout[0] 334 metag = bornout[1] 335 has_loops = bornout[2] 336 self['has_loops'] = self['has_loops'] or has_loops 337 processes = bornout[3] 338 self['processes'].extend(processes) 339 self['max_particles'] = max([self['max_configs']] + [len(p['legs']) + 1 for p in bornout[3]]) 340 self['max_configs'] = max(self['max_configs'], bornout[4]) 341 unique = True 342 for ime2,bornout2 in enumerate(unique_me_list): 343 mefile2 = bornout2[0] 344 metag2 = bornout2[1] 345 if metag==metag2: 346 duplicate_me_lists[ime2].append(mefile) 347 unique = False 348 break; 349 if unique: 350 unique_me_list.append(bornout) 351 duplicate_me_lists.append([]) 352 353 memapin = [] 354 for i,bornout in enumerate(unique_me_list): 355 mefile = bornout[0] 356 memapin.append([i,mefile, duplicate_me_lists[i]]) 357 358 try: 359 memapout = pool.map_async(async_finalize_matrix_elements,memapin).get(9999999) 360 except KeyboardInterrupt: 361 pool.terminate() 362 raise KeyboardInterrupt 363 364 #remove born+virtual temp files 365 for bornout in bornmapout: 366 mefile = bornout[0] 367 os.remove(mefile) 368 369 pool.close() 370 pool.join() 371 372 #set final list of matrix elements (paths to temp files) 373 matrix_elements = [] 374 for meout in memapout: 375 matrix_elements.append(meout[0]) 376 377 self['matrix_elements']=matrix_elements 378 379 #cache information needed for output which will not be available from 380 #the matrix elements later 381 initial_states = [] 382 for meout in memapout: 383 me_initial_states = meout[1] 384 for state in me_initial_states: 385 initial_states.append(state) 386 387 # remove doubles from the list 388 checked = [] 389 for e in initial_states: 390 if e not in checked: 391 checked.append(e) 392 initial_states=checked 393 394 self['initial_states']=initial_states 395 396 helas_list = [] 397 for meout in memapout: 398 helas_list.extend(meout[2]) 399 self['used_lorentz']=list(set(helas_list)) 400 401 coupling_list = [] 402 for meout in memapout: 403 coupling_list.extend([c for l in meout[3] for c in l]) 404 self['used_couplings'] = list(set(coupling_list)) 405 406 has_virtuals = False 407 for meout in memapout: 408 if meout[4]: 409 has_virtuals = True 410 break 411 self['has_virtuals'] = has_virtuals 412 413 configs_list = [self['max_configs']] 414 for meout in realmapout: 415 configs_list.append(meout[1]) 416 self['max_configs'] = max(configs_list) 417 418 nparticles_list = [self['max_particles']] 419 for meout in realmapout: 420 nparticles_list.append(meout[2]) 421 self['max_particles'] = max(nparticles_list) 422 423 self['has_isr'] = fksmulti['has_isr'] 424 self['has_fsr'] = fksmulti['has_fsr'] 425 426 logger.info('... Done') 427 428 for i, logg in enumerate(loggers_off): 429 logg.setLevel(old_levels[i])
430 431
432 - def get_used_lorentz(self):
433 """Return a list of (lorentz_name, conjugate, outgoing) with 434 all lorentz structures used by this HelasMultiProcess.""" 435 436 if not self['used_lorentz']: 437 helas_list = [] 438 for me in self.get('matrix_elements'): 439 helas_list.extend(me.get_used_lorentz()) 440 self['used_lorentz'] = list(set(helas_list)) 441 442 return self['used_lorentz']
443 444
445 - def get_used_couplings(self):
446 """Return a list with all couplings used by this 447 HelasMatrixElement.""" 448 449 if not self['used_couplings']: 450 coupling_list = [] 451 for me in self.get('matrix_elements'): 452 coupling_list.extend([c for l in me.get_used_couplings() for c in l]) 453 self['used_couplings'] = list(set(coupling_list)) 454 455 return self['used_couplings']
456 457
458 - def get_processes(self):
459 """Return a list with all couplings used by this 460 HelasMatrixElement.""" 461 462 if not self['processes']: 463 process_list = [] 464 for me in self.get('matrix_elements'): 465 process_list.extend(me.born_matrix_element.get('processes')) 466 self['processes'] = process_list 467 468 return self['processes']
469 470
471 - def get_max_configs(self):
472 """Return max_configs""" 473 474 if self['max_configs'] < 0: 475 try: 476 self['max_configs'] = max([me.get_num_configs() \ 477 for me in self['real_matrix_elements']]) 478 except ValueError: 479 pass 480 self['max_configs'] = max(self['max_configs'],\ 481 max([me.born_matrix_element.get_num_configs() \ 482 for me in self['matrix_elements']])) 483 484 return self['max_configs']
485 486
487 - def get_max_particles(self):
488 """Return max_paricles""" 489 490 if self['max_particles'] < 0: 491 self['max_particles'] = max([me.get_nexternal_ninitial()[0] \ 492 for me in self['matrix_elements']]) 493 494 return self['max_particles']
495 496
497 - def get_matrix_elements(self):
498 """Extract the list of matrix elements""" 499 return self.get('matrix_elements')
500 501
502 - def get_virt_matrix_elements(self):
503 """Extract the list of virtuals matrix elements""" 504 return [me.virt_matrix_element for me in self.get('matrix_elements') \ 505 if me.virt_matrix_element]
506 507
508 - def generate_matrix_elements_fks(self, fksmulti, gen_color = True, 509 decay_ids = []):
510 """Generate the HelasMatrixElements for the amplitudes, 511 identifying processes with identical matrix elements, as 512 defined by HelasMatrixElement.__eq__. Returns a 513 HelasMatrixElementList and an amplitude map (used by the 514 SubprocessGroup functionality). decay_ids is a list of decayed 515 particle ids, since those should not be combined even if 516 matrix element is identical.""" 517 518 fksprocs = fksmulti['born_processes'] 519 assert isinstance(fksprocs, fks_base.FKSProcessList), \ 520 "%s is not valid FKSProcessList" % \ 521 repr(fksprocs) 522 523 # Keep track of already generated color objects, to reuse as 524 # much as possible 525 list_colorize = [] 526 list_color_links =[] 527 list_color_basis = [] 528 list_color_matrices = [] 529 real_me_list = [] 530 me_id_list = [] 531 532 matrix_elements = FKSHelasProcessList() 533 534 for i, proc in enumerate(fksprocs): 535 logger.info("Generating Helas calls for FKS %s (%d / %d)" % \ 536 (proc.born_amp.get('process').nice_string(print_weighted = False).\ 537 replace('Process', 'process'), 538 i + 1, len(fksprocs))) 539 matrix_element_list = [FKSHelasProcess(proc, self['real_matrix_elements'], 540 fksmulti['real_amplitudes'], 541 loop_optimized = self.loop_optimized, 542 decay_ids=decay_ids, 543 gen_color=False)] 544 for matrix_element in matrix_element_list: 545 assert isinstance(matrix_element, FKSHelasProcess), \ 546 "Not a FKSHelasProcess: %s" % matrix_element 547 548 try: 549 # If an identical matrix element is already in the list, 550 # then simply add this process to the list of 551 # processes for that matrix element 552 other = \ 553 matrix_elements[matrix_elements.index(matrix_element)] 554 except ValueError: 555 # Otherwise, if the matrix element has any diagrams, 556 # add this matrix element. 557 if matrix_element.born_matrix_element.get('processes') and \ 558 matrix_element.born_matrix_element.get('diagrams'): 559 matrix_elements.append(matrix_element) 560 561 if not gen_color: 562 continue 563 564 # Always create an empty color basis, and the 565 # list of raw colorize objects (before 566 # simplification) associated with amplitude 567 col_basis = color_amp.ColorBasis() 568 new_amp = matrix_element.born_matrix_element.get_base_amplitude() 569 matrix_element.born_matrix_element.set('base_amplitude', new_amp) 570 colorize_obj = col_basis.create_color_dict_list(new_amp) 571 572 try: 573 # If the color configuration of the ME has 574 # already been considered before, recycle 575 # the information 576 col_index = list_colorize.index(colorize_obj) 577 logger.info(\ 578 "Reusing existing color information for %s" % \ 579 matrix_element.born_matrix_element.get('processes')\ 580 [0].nice_string(print_weighted=False).\ 581 replace('Process', 'process')) 582 except ValueError: 583 # If not, create color basis and color 584 # matrix accordingly 585 list_colorize.append(colorize_obj) 586 col_basis.build() 587 list_color_basis.append(col_basis) 588 col_matrix = color_amp.ColorMatrix(col_basis) 589 list_color_matrices.append(col_matrix) 590 col_index = -1 591 592 logger.info(\ 593 "Processing color information for %s" % \ 594 matrix_element.born_matrix_element.\ 595 get('processes')[0].nice_string(print_weighted=False).\ 596 replace('Process', 'process')) 597 matrix_element.born_matrix_element.set('color_basis', 598 list_color_basis[col_index]) 599 matrix_element.born_matrix_element.set('color_matrix', 600 list_color_matrices[col_index]) 601 else: 602 # this is in order not to handle valueErrors coming from other plaeces, 603 # e.g. from the add_process function 604 other.add_process(matrix_element) 605 606 for me in matrix_elements: 607 me.set_color_links() 608 return matrix_elements
609 610
611 -class FKSHelasProcessList(MG.PhysicsObjectList):
612 """class to handle lists of FKSHelasProcesses""" 613
614 - def is_valid_element(self, obj):
615 """Test if object obj is a valid FKSProcess for the list.""" 616 return isinstance(obj, FKSHelasProcess)
617 618
619 -class FKSHelasProcess(object):
620 """class to generate the Helas calls for a FKSProcess. Contains: 621 -- born ME 622 -- list of FKSHelasRealProcesses 623 -- color links""" 624
625 - def __init__(self, fksproc=None, real_me_list =[], real_amp_list=[], 626 loop_optimized = False, **opts):#test written
627 """ constructor, starts from a FKSProcess, 628 sets reals and color links. Real_me_list and real_amp_list are the lists of pre-genrated 629 matrix elements in 1-1 correspondence with the amplitudes""" 630 631 if fksproc != None: 632 self.born_matrix_element = helas_objects.HelasMatrixElement( 633 fksproc.born_amp, **opts) 634 self.real_processes = [] 635 self.orders = fksproc.born_proc.get('orders') 636 self.perturbation = fksproc.perturbation 637 real_amps_new = [] 638 # combine for example u u~ > t t~ and d d~ > t t~ 639 if fksproc.ncores_for_proc_gen: 640 # new NLO (multicore) generation mode 641 for real_me, proc in zip(real_me_list,fksproc.real_amps): 642 fksreal_me = FKSHelasRealProcess(proc, real_me, **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 else: 653 #old mode 654 for proc in fksproc.real_amps: 655 fksreal_me = FKSHelasRealProcess(proc, real_me_list, real_amp_list, **opts) 656 try: 657 other = self.real_processes[self.real_processes.index(fksreal_me)] 658 other.matrix_element.get('processes').extend(\ 659 fksreal_me.matrix_element.get('processes') ) 660 except ValueError: 661 if fksreal_me.matrix_element.get('processes') and \ 662 fksreal_me.matrix_element.get('diagrams'): 663 self.real_processes.append(fksreal_me) 664 real_amps_new.append(proc) 665 fksproc.real_amps = real_amps_new 666 if fksproc.virt_amp: 667 self.virt_matrix_element = \ 668 loop_helas_objects.LoopHelasMatrixElement(fksproc.virt_amp, 669 optimized_output = loop_optimized) 670 else: 671 self.virt_matrix_element = None 672 # self.color_links_info = fksproc.find_color_links() 673 self.color_links = []
674 688
689 - def get_fks_info_list(self):
690 """Returns the list of the fks infos for all processes in the format 691 {n_me, pdgs, fks_info}, where n_me is the number of real_matrix_element the configuration 692 belongs to""" 693 info_list = [] 694 for n, real in enumerate(self.real_processes): 695 pdgs = [l['id'] for l in real.matrix_element.get_base_amplitude()['process']['legs']] 696 for info in real.fks_infos: 697 info_list.append({'n_me' : n + 1,'pdgs' : pdgs, 'fks_info' : info}) 698 return info_list
699 700
701 - def get_lh_pdg_string(self):
702 """Returns the pdgs of the legs in the form "i1 i2 -> f1 f2 ...", which may 703 be useful (eg. to be written in a B-LH order file)""" 704 705 initial = '' 706 final = '' 707 for leg in self.born_matrix_element.get('processes')[0].get('legs'): 708 if leg.get('state'): 709 final += '%d ' % leg.get('id') 710 else: 711 initial += '%d ' % leg.get('id') 712 return initial + '-> ' + final
713 714
715 - def get(self, key):
716 """the get function references to born_matrix_element""" 717 return self.born_matrix_element.get(key)
718
719 - def get_used_lorentz(self):
720 """the get_used_lorentz function references to born, reals 721 and virtual matrix elements""" 722 lorentz_list = self.born_matrix_element.get_used_lorentz() 723 for real in self.real_processes: 724 lorentz_list.extend(real.matrix_element.get_used_lorentz()) 725 if self.virt_matrix_element: 726 lorentz_list.extend(self.virt_matrix_element.get_used_lorentz()) 727 728 return list(set(lorentz_list))
729
730 - def get_used_couplings(self):
731 """the get_used_couplings function references to born, reals 732 and virtual matrix elements""" 733 coupl_list = self.born_matrix_element.get_used_couplings() 734 for real in self.real_processes: 735 coupl_list.extend([c for c in\ 736 real.matrix_element.get_used_couplings()]) 737 if self.virt_matrix_element: 738 coupl_list.extend(self.virt_matrix_element.get_used_couplings()) 739 return coupl_list
740
741 - def get_nexternal_ninitial(self):
742 """the nexternal_ninitial function references to the real emissions if they have been 743 generated, otherwise to the born""" 744 if self.real_processes: 745 (nexternal, ninitial) = self.real_processes[0].matrix_element.get_nexternal_ninitial() 746 else: 747 (nexternal, ninitial) = self.born_matrix_element.get_nexternal_ninitial() 748 nexternal += 1 749 return (nexternal, ninitial)
750
751 - def __eq__(self, other):
752 """the equality between two FKSHelasProcesses is defined up to the 753 color links""" 754 selftag = helas_objects.IdentifyMETag.create_tag(self.born_matrix_element.get('base_amplitude')) 755 othertag = helas_objects.IdentifyMETag.create_tag(other.born_matrix_element.get('base_amplitude')) 756 757 if self.born_matrix_element != other.born_matrix_element or \ 758 selftag != othertag: 759 return False 760 761 reals2 = copy.copy(other.real_processes) 762 for real in self.real_processes: 763 try: 764 reals2.remove(real) 765 except ValueError: 766 return False 767 if not reals2: 768 return True 769 else: 770 return False
771
772 - def add_process(self, other): #test written, ppwj
773 """adds processes from born and reals of other to itself. Note that 774 corresponding real processes may not be in the same order. This is 775 taken care of by constructing the list of self_reals.""" 776 self.born_matrix_element.get('processes').extend( 777 other.born_matrix_element.get('processes')) 778 if self.virt_matrix_element and other.virt_matrix_element: 779 self.virt_matrix_element.get('processes').extend( 780 other.virt_matrix_element.get('processes')) 781 self_reals = [real.matrix_element for real in self.real_processes] 782 for oth_real in other.real_processes: 783 this_real = self.real_processes[self_reals.index(oth_real.matrix_element)] 784 #need to store pdg lists rather than processes in order to keep mirror processes different 785 this_pdgs = [[leg['id'] for leg in proc['legs']] \ 786 for proc in this_real.matrix_element['processes']] 787 for oth_proc in oth_real.matrix_element['processes']: 788 oth_pdgs = [leg['id'] for leg in oth_proc['legs']] 789 if oth_pdgs not in this_pdgs: 790 this_real.matrix_element['processes'].append(oth_proc) 791 this_pdgs.append(oth_pdgs) 792 793 # if p not in self.real_processes[\ 794 # self_reals.index(oth_real.matrix_element)].matrix_element['processes']]) 795 796
797 -class FKSHelasRealProcess(object): #test written
798 """class to generate the Helas calls for a FKSRealProcess 799 contains: 800 -- colors 801 -- charges 802 -- i/j/ij fks, ij refers to the born leglist 803 -- ijglu 804 -- need_color_links 805 -- fks_j_from_i 806 -- matrix element 807 -- is_to_integrate 808 -- leg permutation<<REMOVED""" 809
810 - def __init__(self, fksrealproc=None, real_me_list = [], real_amp_list =[], **opts):
811 """constructor, starts from a fksrealproc and then calls the 812 initialization for HelasMatrixElement. 813 Sets i/j fks and the permutation. 814 real_me_list and real_amp_list are the lists of pre-generated matrix elements in 1-1 815 correspondance with the amplitudes""" 816 817 if fksrealproc != None: 818 self.isfinite = False 819 self.colors = fksrealproc.colors 820 self.charges = fksrealproc.charges 821 self.fks_infos = fksrealproc.fks_infos 822 self.is_to_integrate = fksrealproc.is_to_integrate 823 824 # real_me_list is a list in the old NLO generation mode; 825 # in the new one it is a matrix element 826 if type(real_me_list) == list and len(real_me_list) != len(real_amp_list): 827 raise fks_common.FKSProcessError( 828 'not same number of amplitudes and matrix elements: %d, %d' % \ 829 (len(real_amp_list), len(real_me_list))) 830 if type(real_me_list) == list and real_me_list and real_amp_list: 831 self.matrix_element = copy.deepcopy(real_me_list[real_amp_list.index(fksrealproc.amplitude)]) 832 self.matrix_element['processes'] = copy.deepcopy(self.matrix_element['processes']) 833 834 elif type(real_me_list) == helas_objects.HelasMatrixElement: 835 #new NLO generation mode 836 self.matrix_element = real_me_list 837 838 else: 839 840 if real_me_list and real_amp_list: 841 self.matrix_element = copy.deepcopy(real_me_list[real_amp_list.index(fksrealproc.amplitude)]) 842 self.matrix_element['processes'] = copy.deepcopy(self.matrix_element['processes']) 843 else: 844 logger.info('generating matrix element...') 845 self.matrix_element = helas_objects.HelasMatrixElement( 846 fksrealproc.amplitude, **opts) 847 #generate the color for the real 848 self.matrix_element.get('color_basis').build( 849 self.matrix_element.get('base_amplitude')) 850 self.matrix_element.set('color_matrix', 851 color_amp.ColorMatrix( 852 self.matrix_element.get('color_basis'))) 853 #self.fks_j_from_i = fksrealproc.find_fks_j_from_i() 854 self.fks_j_from_i = fksrealproc.fks_j_from_i
855
856 - def get_nexternal_ninitial(self):
857 """Refers to the matrix_element function""" 858 return self.matrix_element.get_nexternal_ninitial()
859
860 - def __eq__(self, other):
861 """Equality operator: 862 compare two FKSHelasRealProcesses by comparing their dictionaries""" 863 864 if self.__dict__ == other.__dict__: 865 return True 866 else: 867 # failed = [] 868 # for key in self.__dict__: 869 # if self.__dict__[key] != other.__dict__[key]: 870 # failed.append(key) 871 # import madgraph.various.misc as misc 872 873 return False 874 875 876 return self.__dict__ == other.__dict__
877
878 - def __ne__(self, other):
879 """Inequality operator: 880 compare two FKSHelasRealProcesses by comparing their dictionaries""" 881 return not self.__eq__(other)
882