Package madgraph :: Package interface :: Module loop_interface
[hide private]
[frames] | no frames]

Source Code for Module madgraph.interface.loop_interface

  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  """A user friendly command line interface to access all MadGraph5_aMC@NLO features. 
 16     Uses the cmd package for command interpretation and tab completion. 
 17  """ 
 18   
 19  import os 
 20  import shutil 
 21  import time 
 22  import logging 
 23  import re 
 24   
 25  import madgraph 
 26  from madgraph import MG4DIR, MG5DIR, MadGraph5Error 
 27  import madgraph.interface.madgraph_interface as mg_interface 
 28  import madgraph.interface.launch_ext_program as launch_ext 
 29  import madgraph.interface.extended_cmd as extended_cmd 
 30  import madgraph.core.base_objects as base_objects 
 31  import madgraph.core.diagram_generation as diagram_generation 
 32  import madgraph.loop.loop_diagram_generation as loop_diagram_generation 
 33  import madgraph.loop.loop_base_objects as loop_base_objects 
 34  import madgraph.loop.loop_helas_objects as loop_helas_objects 
 35  import madgraph.core.helas_objects as helas_objects 
 36  import madgraph.iolibs.export_v4 as export_v4 
 37  import madgraph.iolibs.helas_call_writers as helas_call_writers 
 38  import madgraph.iolibs.file_writers as writers 
 39  import madgraph.interface.launch_ext_program as launch_ext 
 40  import madgraph.various.misc as misc 
 41  import madgraph.fks.fks_base as fks_base 
 42  import aloha 
 43   
 44  # Special logger for the Cmd Interface 
 45  logger = logging.getLogger('cmdprint') 
 46   
 47  #useful shortcut 
 48  pjoin = os.path.join 
 49   
50 -class CheckLoop(mg_interface.CheckValidForCmd):
51
52 - def check_display(self, args):
53 """ Check the arguments of the display diagrams command in the context 54 of the Loop interface.""" 55 56 mg_interface.MadGraphCmd.check_display(self,args) 57 58 if all([not amp['process']['has_born'] for amp in self._curr_amps]): 59 if args[0]=='diagrams' and len(args)>=2 and args[1]=='born': 60 raise self.InvalidCmd("Processes generated do not have born diagrams.") 61 62 if args[0]=='diagrams' and len(args)>=3 and args[1] not in ['born','loop']: 63 raise self.InvalidCmd("Can only display born or loop diagrams, not %s."%args[1])
64
65 - def check_tutorial(self, args):
66 """check the validity of the line""" 67 if len(args) == 0: 68 #this means mg5 tutorial 69 args.append('MadLoop') 70 else: 71 return mg_interface.CheckValidForCmd.check_tutorial(self,args)
72
73 - def check_add(self, args):
74 """ If no model is defined yet, make sure to load the right loop one """ 75 76 if not self._curr_model: 77 pert_coupl_finder = re.compile(r"^(?P<proc>.+)\s*\[\s*((?P<option>\w+)"+ 78 r"\s*\=)?\s*(?P<pertOrders>(\w+\s*)*)\s*\]\s*(?P<rest>.*)$") 79 pert_coupl = pert_coupl_finder.match(' '.join(args)) 80 model_name = 'loop_sm' 81 if pert_coupl: 82 pert_coupls = pert_coupl.group("pertOrders") 83 if "QED" in pert_coupls: 84 model_name = 'loop_qcd_qed_sm' 85 self.do_import('model %s'%model_name) 86 87 mg_interface.MadGraphCmd.check_add(self,args)
88
89 - def check_output(self, args, default='standalone'):
90 """ Check the arguments of the output command in the context 91 of the Loop interface.""" 92 93 mg_interface.MadGraphCmd.check_output(self,args, default=default) 94 95 if self._export_format not in self.supported_ML_format: 96 raise self.InvalidCmd, "not supported format %s" % self._export_format
97 98
99 - def check_launch(self, args, options):
100 """ Further check that only valid options are given to the MadLoop 101 default launcher.""" 102 103 mg_interface.MadGraphCmd.check_launch(self,args,options) 104 if int(options.cluster) != 0 : 105 return self.InvalidCmd, 'MadLoop standalone runs cannot be '+\ 106 'performed on a cluster.' 107 108 if int(options.multicore) != 0 : 109 logger.warning('MadLoop standalone can only run on a single core,'+\ 110 ' so the -m option is ignored.') 111 options.multicore = '0' 112 113 if options.laststep != '' : 114 logger.warning('The -laststep option is only used for Madevent.'+\ 115 'Ignoring this option') 116 options.multicore = '' 117 118 if options.interactive : 119 logger.warning('No interactive mode for MadLoop standalone runs.') 120 options.interactive = False
121
122 -class CheckLoopWeb(mg_interface.CheckValidForCmdWeb, CheckLoop):
123 pass
124
125 -class CompleteLoop(mg_interface.CompleteForCmd):
126
127 - def complete_display(self, text, line, begidx, endidx):
128 "Complete the display command in the context of the Loop interface" 129 130 args = self.split_arg(line[0:begidx]) 131 132 if len(args) == 2 and args[1] == 'diagrams': 133 return self.list_completion(text, ['born', 'loop']) 134 else: 135 return mg_interface.MadGraphCmd.complete_display(self, text, line, 136 begidx, endidx)
137
138 -class HelpLoop(mg_interface.HelpToCmd):
139
140 - def help_display(self):
141 mg_interface.MadGraphCmd.help_display(self) 142 logger.info(" In ML5, after display diagrams, the user can add the option") 143 logger.info(" \"born\" or \"loop\" to display only the corresponding diagrams.")
144 145
146 -class CommonLoopInterface(mg_interface.MadGraphCmd):
147 """ An additional layer between MadGraphInterface and LoopInterface as well 148 as aMCatNLO interface, to put the common feature of these two here.""" 149
150 - def rate_proc_difficulty(self, proc, mode):
151 """ Gives an integer more or less representing the difficulty of the process. 152 For now it is very basic and such that "difficult" processes start at 153 a value of about 35.""" 154 155 def pdg_difficulty(pdg): 156 """ Gives a score from the pdg of a leg to state how it increases the 157 difficulty of the process """ 158 # For now, it is only based on the color charge. One can change that 159 # of course. 160 part=self._curr_model.get_particle(pdg) 161 if abs(part.get_color())==1: 162 return 2 163 elif abs(part.get_color())==3: 164 return 3 165 elif abs(part.get_color())==6: 166 return 4 167 elif abs(part.get_color())==8: 168 return 6
169 170 score = 0 171 for leg in proc.get('legs'): 172 if isinstance(leg,base_objects.MultiLeg): 173 score += max([pdg_difficulty(id) for id in leg['ids']]) 174 # add one if it has more than one particle 175 if len(leg['ids'])>1: 176 score += 1 177 else: 178 score += pdg_difficulty(leg.get('id')) 179 180 # No integration planned right away if only virtual, remove 6 181 if proc['NLO_mode']=='virt': 182 score = score - 6 183 # Only reals, then again remove 6 184 if proc['NLO_mode']=='real': 185 score = score - 6 186 # If tree only then it is easy 187 if proc['NLO_mode']=='tree': 188 return 0 189 return score
190
191 - def do_set(self, line, log=True):
192 """Set the loop optimized output while correctly switching to the 193 Feynman gauge if necessary. 194 """ 195 196 mg_interface.MadGraphCmd.do_set(self,line,log) 197 198 args = self.split_arg(line) 199 self.check_set(args) 200 201 if args[0] == 'gauge' and args[1] == 'unitary' and \ 202 not self.options['gauge']=='unitary' and \ 203 isinstance(self._curr_model,loop_base_objects.LoopModel) and \ 204 not self._curr_model['perturbation_couplings'] in [[],['QCD']]: 205 if log: logger.warning('You will only be able to do tree level and QCD'+\ 206 ' corrections in the unitary gauge.')
207
208 - def proc_validity(self, proc, mode):
209 """ Check that the process or processDefinition describes a process that 210 ML5 can handle. Mode specifies who called the function, 211 typically ML5, ML5_check or aMCatNLO. This allows to relieve some limitation 212 depending on the functionality.""" 213 214 tool = 'MadLoop' if mode.startswith('ML5') else 'aMC@NLO' 215 # The threshold for the triggering of the 'Warning difficult process' 216 # message. 217 difficulty_threshold = 100 218 # Check that we have something 219 if not proc: 220 raise self.InvalidCmd("Empty or wrong format process, please try again.") 221 222 # Check that we have the same number of initial states as 223 # existing processes 224 if self._curr_amps and self._curr_amps[0].get_ninitial() != \ 225 proc.get_ninitial(): 226 raise self.InvalidCmd("Can not mix processes with different number of initial states.") 227 228 # It is partially supported for now if the initial state is not charged 229 # under the gauge group perturbed. 230 # if proc.get_ninitial()==1 and tool=='aMC@NLO': 231 # raise self.InvalidCmd("At this stage %s cannot handle decay process."%tool+\ 232 # "\nIt is however a straight-forward extension which "+\ 233 # "will come out with the next release.") 234 235 # Now all checks should support multi-particle label for loops as well. 236 if isinstance(proc, base_objects.ProcessDefinition) and mode=='ML5': 237 if proc.has_multiparticle_label(): 238 raise self.InvalidCmd( 239 "When running ML5 standalone, multiparticle labels cannot be"+\ 240 " employed.") 241 242 if proc['decay_chains']: 243 raise self.InvalidCmd( 244 "ML5 cannot yet decay a core process including loop corrections.") 245 246 if proc.are_decays_perturbed(): 247 raise self.InvalidCmd( 248 "The processes defining the decay of the core process cannot"+\ 249 " include loop corrections.") 250 251 if not proc['perturbation_couplings'] and mode.startswith('ML5'): 252 raise self.InvalidCmd( 253 "Please perform tree-level generations within default MG5 interface.") 254 if not 'real': 255 if not isinstance(self._curr_model,loop_base_objects.LoopModel) or \ 256 not proc['perturbation_couplings']: 257 raise self.InvalidCmd( 258 "The current model does not allow for loop computations.") 259 260 miss_order = [ p_order for p_order in proc['perturbation_couplings'] \ 261 if p_order not in self._curr_model.get('perturbation_couplings')] 262 if len(miss_order)>0 and not 'real' in mode: 263 raise self.InvalidCmd( 264 "Perturbation orders %s not among"%str(miss_order) + \ 265 " the perturbation orders allowed for by the loop model.") 266 267 if proc['perturbation_couplings'] not in [[],['QCD']]: 268 raise self.InvalidCmd( 269 "The process perturbation coupling orders %s are beyond "+\ 270 "tree level or only QCD corrections. MadLoop can only work"+\ 271 " in the Feynman gauge for these. Please set the gauge to "+\ 272 " Feynman and try again.") 273 274 proc_diff = self.rate_proc_difficulty(proc, mode) 275 logger.debug('Process difficulty estimation: %d'%proc_diff) 276 if proc_diff >= difficulty_threshold: 277 msg = """ 278 The %s you attempt to generate appears to be of challenging difficulty, but it will be tried anyway. If you have successfully studied it with MadGraph5_aMC@NLO, please report it. 279 """ 280 logger.warning(msg%proc.nice_string().replace('Process:','process'))
281
282 - def validate_model(self, loop_type='virtual',coupling_type=['QCD'], stop=True):
283 """ Upgrade the model sm to loop_sm if needed """ 284 285 # Allow to call this function with a string instead of a list of 286 # perturbation orders. 287 if isinstance(coupling_type,str): 288 coupling_type = [coupling_type,] 289 290 if coupling_type!= ['QCD'] and loop_type not in ['virtual','noborn']: 291 c = ' '.join(coupling_type) 292 raise self.InvalidCmd, 'MG5aMC can only handle QCD at NLO accuracy.\n We can however compute loop with [virt=%s].\n We can also compute cross-section for loop-induced processes with [noborn=%s]' % (c,c) 293 294 295 if not isinstance(self._curr_model,loop_base_objects.LoopModel) or \ 296 self._curr_model['perturbation_couplings']==[] or \ 297 any((coupl not in self._curr_model['perturbation_couplings']) \ 298 for coupl in coupling_type): 299 if loop_type.startswith('real') or loop_type == 'LOonly': 300 if loop_type == 'real': 301 logger.info(\ 302 "Beware that real corrections are generated from a tree-level model.") 303 if loop_type == 'real_init' and \ 304 self._curr_model.get('name').split('-')[0]!='sm': 305 logger.info(\ 306 "You are entering aMC@NLO with a model which does not "+\ 307 " support loop corrections.") 308 else: 309 logger.info(\ 310 "The current model %s does not allow to generate"%self._curr_model.get('name')+ 311 " loop corrections of type %s."%str(coupling_type)) 312 model_path = self._curr_model.get('modelpath') 313 model_name = self._curr_model.get('name') 314 if model_name.split('-')[0]=='loop_sm': 315 model_name = model_name[5:] 316 if model_name.split('-')[0]=='sm': 317 # So that we don't load the model twice 318 if not self.options['gauge']=='Feynman' and 'QED' in coupling_type: 319 logger.info('Switch to Feynman gauge because '+\ 320 'model loop_qcd_qed_sm is restricted only to Feynman gauge.') 321 self._curr_model = None 322 mg_interface.MadGraphCmd.do_set(self,'gauge Feynman') 323 if coupling_type == ['QCD',]: 324 add_on = '' 325 elif coupling_type in [['QED'],['QCD','QED']]: 326 add_on = 'qcd_qed_' 327 else: 328 raise MadGraph5Error( 329 "The pertubation coupling cannot be '%s'"\ 330 %str(coupling_type)+" in SM loop processes") 331 332 logger.info("MG5_aMC now loads 'loop_%s%s'."%(add_on,model_name)) 333 334 #import model with correct treatment of the history 335 self.history.move_to_last('generate') 336 last_command = self.history[-1] 337 self.exec_cmd(" import model loop_%s%s" % (add_on,model_name), precmd=True) 338 self.history.append(last_command) 339 elif stop: 340 raise self.InvalidCmd( 341 "The model %s cannot handle loop processes"%model_name) 342 343 if loop_type and not loop_type.startswith('real') and \ 344 not self.options['gauge']=='Feynman' and \ 345 not self._curr_model['perturbation_couplings'] in [[],['QCD']]: 346 if 1 in self._curr_model.get('gauge'): 347 logger.info("Setting gauge to Feynman in order to process all"+\ 348 " possible loop computations available in the model.") 349 mg_interface.MadGraphCmd.do_set(self,'gauge Feynman') 350 else: 351 logger.warning("You will only be able to do tree level and QCD"+\ 352 " corrections with this model because it does not support Feynman gauge.")
353
354 -class LoopInterface(CheckLoop, CompleteLoop, HelpLoop, CommonLoopInterface):
355 356 supported_ML_format = ['standalone', 'standalone_rw', 'matchbox'] 357
358 - def __init__(self, mgme_dir = '', *completekey, **stdin):
359 """ Special init tasks for the Loop Interface """ 360 361 mg_interface.MadGraphCmd.__init__(self, mgme_dir = '', *completekey, **stdin) 362 self.setup()
363
364 - def setup(self):
365 """ Special tasks when switching to this interface """ 366 367 # Refresh all the interface stored value as things like generated 368 # processes and amplitudes are not to be reused in between different 369 # interfaces 370 # Clear history, amplitudes and matrix elements when a model is imported 371 # Remove previous imports, generations and outputs from history 372 self.history.clean(remove_bef_last='import', 373 to_keep=['set','load','import', 'define']) 374 # Reset amplitudes and matrix elements 375 self._done_export=False 376 self._curr_amps = diagram_generation.AmplitudeList() 377 self._curr_matrix_elements = helas_objects.HelasMultiProcess() 378 self._v4_export_formats = [] 379 self._export_formats = [ 'matrix', 'standalone' ] 380 self._nlo_modes_for_completion = ['virt'] 381 self.validate_model() 382 # Set where to look for CutTools installation. 383 # In further versions, it will be set in the same manner as _mgme_dir so that 384 # the user can chose its own CutTools distribution. 385 self._cuttools_dir=str(os.path.join(self._mgme_dir,'vendor','CutTools')) 386 if not os.path.isdir(os.path.join(self._cuttools_dir, 'src','cts')): 387 logger.warning(('Warning: Directory %s is not a valid CutTools directory.'+\ 388 'Using default CutTools instead.') % \ 389 self._cuttools_dir) 390 self._cuttools_dir=str(os.path.join(self._mgme_dir,'vendor','CutTools')) 391 # Set where to look for IREGI installation 392 self._iregi_dir=str(os.path.join(self._mgme_dir,'vendor','IREGI','src')) 393 if not os.path.isdir(self._iregi_dir): 394 logger.warning(('Warning: Directory %s is not a valid IREGI directory.'+\ 395 'Using default IREGI instead.')%\ 396 self._iregi_dir) 397 self._iregi_dir=str(os.path.join(self._mgme_dir,'vendor','IREGI','src'))
398
399 - def do_display(self,line, *argss, **opt):
400 """ Display born or loop diagrams, otherwise refer to the default display 401 command """ 402 403 args = self.split_arg(line) 404 #check the validity of the arguments 405 self.check_display(args) 406 407 if args[0]=='diagrams': 408 if len(args)>=2 and args[1] in ['loop','born']: 409 self.draw(' '.join(args[2:]),args[1]) 410 else: 411 self.draw(' '.join(args[1:]),'all') 412 else: 413 mg_interface.MadGraphCmd.do_display(self,line,*argss,**opt)
414
415 - def do_output(self, line):
416 """Main commands:Initialize a new Template or reinitialize one""" 417 418 args = self.split_arg(line) 419 # Check Argument validity 420 self.check_output(args) 421 422 noclean = '-noclean' in args 423 force = '-f' in args 424 nojpeg = '-nojpeg' in args 425 main_file_name = "" 426 try: 427 main_file_name = args[args.index('-name') + 1] 428 except Exception: 429 pass 430 431 # Whatever the format we always output the quadruple precision routines 432 # to allow for curing possible unstable points. 433 aloha_original_quad_mode = aloha.mp_precision 434 aloha.mp_precision = True 435 436 if self._export_format not in self.supported_ML_format: 437 raise self.InvalidCmd('ML5 only support "%s" as export format.' % \ 438 ''.join(self.supported_ML_format)) 439 440 if not os.path.isdir(self._export_dir) and self._export_format in ['matrix']: 441 raise self.InvalidCmd('Specified export directory %s does not exist.'\ 442 %str(self._export_dir)) 443 444 if not force and not noclean and os.path.isdir(self._export_dir)\ 445 and self._export_format.startswith('standalone'): 446 # Don't ask if user already specified force or noclean 447 logger.info('INFO: directory %s already exists.' % self._export_dir) 448 logger.info('If you continue this directory will be cleaned') 449 answer = self.ask('Do you want to continue?', 'y', ['y','n']) 450 if answer != 'y': 451 raise self.InvalidCmd('Stopped by user request') 452 else: 453 try: 454 shutil.rmtree(self._export_dir) 455 except OSError: 456 raise self.InvalidCmd('Could not remove directory %s.'\ 457 %str(self._export_dir)) 458 459 if self._export_format.startswith('standalone'): 460 output_type = 'madloop' 461 elif self._export_format == 'matchbox': 462 output_type = 'madloop_matchbox' 463 464 self._curr_exporter = export_v4.ExportV4Factory(self, \ 465 noclean, output_type=output_type, group_subprocesses=False) 466 467 if self._export_format in ['standalone', 'matchbox']: 468 self._curr_exporter.copy_v4template(modelname=self._curr_model.get('name')) 469 470 if self._export_format == "standalone_rw": 471 self._export_format = "standalone" 472 self._curr_exporter.copy_v4template(modelname=self._curr_model.get('name')) 473 self._export_format = "standalone_rw" 474 475 # Reset _done_export, since we have new directory 476 self._done_export = False 477 478 # Perform export and finalize right away 479 self.ML5export(nojpeg, main_file_name) 480 481 # Automatically run finalize 482 self.ML5finalize(nojpeg) 483 484 # Remember that we have done export 485 self._done_export = (self._export_dir, self._export_format) 486 487 # Reset _export_dir, so we don't overwrite by mistake later 488 self._export_dir = None 489 490 # Put aloha back in its original mode. 491 aloha.mp_precision = aloha_original_quad_mode
492 493 # Export a matrix element 494
495 - def ML5export(self, nojpeg = False, main_file_name = ""):
496 """Export a generated amplitude to file""" 497 498 def generate_matrix_elements(self): 499 """Helper function to generate the matrix elements before exporting""" 500 501 # Sort amplitudes according to number of diagrams, 502 # to get most efficient multichannel output 503 self._curr_amps.sort(lambda a1, a2: a2.get_number_of_diagrams() - \ 504 a1.get_number_of_diagrams()) 505 506 cpu_time1 = time.time() 507 ndiags = 0 508 if not self._curr_matrix_elements.get_matrix_elements(): 509 self._curr_matrix_elements = \ 510 loop_helas_objects.LoopHelasProcess(self._curr_amps, 511 optimized_output = self.options['loop_optimized_output']) 512 ndiags = sum([len(me.get('diagrams')) for \ 513 me in self._curr_matrix_elements.\ 514 get_matrix_elements()]) 515 # assign a unique id number to all process 516 uid = 0 517 for me in self._curr_matrix_elements.get_matrix_elements(): 518 uid += 1 # update the identification number 519 me.get('processes')[0].set('uid', uid) 520 521 cpu_time2 = time.time() 522 return ndiags, cpu_time2 - cpu_time1
523 524 # Start of the actual routine 525 ndiags, cpu_time = generate_matrix_elements(self) 526 527 calls = 0 528 529 path = self._export_dir 530 if self._export_format in self.supported_ML_format: 531 path = pjoin(path, 'SubProcesses') 532 533 cpu_time1 = time.time() 534 535 # Pick out the matrix elements in a list 536 matrix_elements = \ 537 self._curr_matrix_elements.get_matrix_elements() 538 539 # Fortran MadGraph5_aMC@NLO Standalone 540 if self._export_format in self.supported_ML_format: 541 for me in matrix_elements: 542 calls = calls + \ 543 self._curr_exporter.generate_subprocess_directory_v4(\ 544 me, self._curr_fortran_model) 545 # If all ME's do not share the same maximum loop vertex rank and the 546 # same loop maximum wavefunction size, we need to set the maximum 547 # in coef_specs.inc of the HELAS Source. The SubProcesses/P* directory 548 # all link this file, so it should be properly propagated 549 if self.options['loop_optimized_output'] and len(matrix_elements)>1: 550 max_lwfspins = [m.get_max_loop_particle_spin() for m in \ 551 matrix_elements] 552 max_loop_vert_ranks = [me.get_max_loop_vertex_rank() for me in \ 553 matrix_elements] 554 if len(set(max_lwfspins))>1 or len(set(max_loop_vert_ranks))>1: 555 self._curr_exporter.fix_coef_specs(max(max_lwfspins),\ 556 max(max_loop_vert_ranks)) 557 558 # Just the matrix.f files 559 if self._export_format == 'matrix': 560 for me in matrix_elements: 561 filename = pjoin(path, 'matrix_' + \ 562 me.get('processes')[0].shell_string() + ".f") 563 if os.path.isfile(filename): 564 logger.warning("Overwriting existing file %s" % filename) 565 else: 566 logger.info("Creating new file %s" % filename) 567 calls = calls + self._curr_exporter.write_matrix_element_v4(\ 568 writers.FortranWriter(filename),\ 569 me, self._curr_fortran_model) 570 571 cpu_time2 = time.time() - cpu_time1 572 573 logger.info(("Generated helas calls for %d subprocesses " + \ 574 "(%d diagrams) in %0.3f s") % \ 575 (len(matrix_elements), 576 ndiags, cpu_time)) 577 578 if calls: 579 if "cpu_time2" in locals(): 580 logger.info("Wrote files for %d OPP calls in %0.3f s" % \ 581 (calls, cpu_time2)) 582 else: 583 logger.info("Wrote files for %d OPP calls" % \ 584 (calls)) 585 586 # Replace the amplitudes with the actual amplitudes from the 587 # matrix elements, which allows proper diagram drawing also of 588 # decay chain processes 589 self._curr_amps = diagram_generation.AmplitudeList(\ 590 [me.get('base_amplitude') for me in \ 591 matrix_elements])
592
593 - def ML5finalize(self, nojpeg, online = False):
594 """Copy necessary sources and output the ps representation of 595 the diagrams, if needed""" 596 597 if self._export_format in self.supported_ML_format: 598 logger.info('Export UFO model to MG4 format') 599 # wanted_lorentz are the lorentz structures which are 600 # actually used in the wavefunctions and amplitudes in 601 # these processes 602 wanted_lorentz = self._curr_matrix_elements.get_used_lorentz() 603 wanted_couplings = self._curr_matrix_elements.get_used_couplings() 604 # For a unique output of multiple type of exporter model information 605 # are save in memory 606 if hasattr(self, 'previous_lorentz'): 607 wanted_lorentz = list(set(self.previous_lorentz + wanted_lorentz)) 608 wanted_couplings = list(set(self.previous_couplings + wanted_couplings)) 609 del self.previous_lorentz 610 del self.previous_couplings 611 612 self._curr_exporter.convert_model_to_mg4(self._curr_model, 613 wanted_lorentz, 614 wanted_couplings) 615 616 compiler = {'fortran': self.options['fortran_compiler'], 617 'f2py': self.options['f2py_compiler'], 618 'cpp': self.options['cpp_compiler']} 619 620 if self._export_format in self.supported_ML_format: 621 self._curr_exporter.finalize_v4_directory( \ 622 self._curr_matrix_elements, 623 self.history, 624 not nojpeg, 625 online, 626 compiler) 627 628 if self._export_format in self.supported_ML_format: 629 logger.info('Output to directory ' + self._export_dir + ' done.')
630
631 - def do_launch(self, line, *args,**opt):
632 """Main commands: Check that the type of launch is fine before proceeding with the 633 mother function. """ 634 635 args = self.split_arg(line) 636 # check argument validity and normalise argument 637 (options, args) = mg_interface._launch_parser.parse_args(args) 638 639 self.check_launch(args, options) 640 641 if not args[0].startswith('standalone'): 642 raise self.InvalidCmd('ML5 can only launch standalone runs.') 643 644 start_cwd = os.getcwd() 645 options = options.__dict__ 646 # args is now MODE PATH 647 648 ext_program = launch_ext.MadLoopLauncher(self, args[1], \ 649 options=self.options, **options) 650 ext_program.run() 651 os.chdir(start_cwd) #ensure to go to the initial path
652
653 - def do_check(self, line, *args,**opt):
654 """Check a given process or set of processes""" 655 656 argss = self.split_arg(line, *args,**opt) 657 # Check args validity 658 perturbation_couplings_pattern = \ 659 re.compile("^(?P<proc>.+)\s*\[\s*((?P<option>\w+)\s*\=)?\s*(?P<pertOrders>(\w+\s*)*)\s*\]\s*(?P<rest>.*)$") 660 perturbation_couplings_re = perturbation_couplings_pattern.match(line) 661 perturbation_couplings="" 662 if perturbation_couplings_re: 663 perturbation_couplings = perturbation_couplings_re.group("pertOrders") 664 QED_found=re.search("QED",perturbation_couplings) 665 if QED_found: 666 self.validate_model(coupling_type='QED') 667 else: 668 self.validate_model() 669 670 param_card = self.check_check(argss) 671 reuse = argss[1]=="-reuse" 672 argss = argss[:1]+argss[2:] 673 # For the stability check the user can specify the statistics (i.e 674 # number of trial PS points) as a second argument 675 if argss[0] in ['stability', 'profile']: 676 stab_statistics = int(argss[1]) 677 argss = argss[:1]+argss[2:] 678 # Remove the extra options 679 i=-1 680 while argss[i].startswith('--'): 681 i=i-1 682 # Now make sure the process is acceptable 683 proc = " ".join(argss[1:i+1]) 684 myprocdef = self.extract_process(proc) 685 self.proc_validity(myprocdef,'ML5_check_cms' if argss[0]=='cms' else \ 686 'ML5_check') 687 688 return mg_interface.MadGraphCmd.do_check(self, line, *args,**opt)
689
690 - def do_add(self, line, *args,**opt):
691 """Generate an amplitude for a given process and add to 692 existing amplitudes 693 """ 694 args = self.split_arg(line) 695 # Check the validity of the arguments 696 self.check_add(args) 697 perturbation_couplings_pattern = \ 698 re.compile("^(?P<proc>.+)\s*\[\s*((?P<option>\w+)\s*\=)?\s*(?P<pertOrders>(\w+\s*)*)\s*\]\s*(?P<rest>.*)$") 699 perturbation_couplings_re = perturbation_couplings_pattern.match(line) 700 perturbation_couplings="" 701 if perturbation_couplings_re: 702 perturbation_couplings = perturbation_couplings_re.group("pertOrders") 703 QED_found=re.search('QED',perturbation_couplings) 704 if QED_found: 705 self.validate_model(coupling_type='QED') 706 else: 707 self.validate_model() 708 709 loop_filter=None 710 if args[0] == 'process': 711 712 # Extract potential loop_filter 713 for arg in args: 714 if arg.startswith('--loop_filter='): 715 loop_filter = arg[14:] 716 if not isinstance(self, extended_cmd.CmdShell): 717 raise InvalidCmd, "loop_filter is not allowed in web mode" 718 args = [a for a in args if not a.startswith('--loop_filter=')] 719 720 # Rejoin line 721 line = ' '.join(args[1:]) 722 723 # store the first process (for the perl script) 724 if not self._generate_info: 725 self._generate_info = line 726 727 # Reset Helas matrix elements 728 self._curr_matrix_elements = helas_objects.HelasMultiProcess() 729 730 # Extract process from process definition 731 myprocdef = self.extract_process(line) 732 # hack for multiprocess: 733 if myprocdef.has_multiparticle_label(): 734 # split it in a loop 735 succes, failed = 0, 0 736 for base_proc in myprocdef: 737 try: 738 self.exec_cmd("add process %s" % base_proc.nice_string(prefix=False, print_weighted=True)) 739 succes += 1 740 except Exception: 741 failed +=1 742 logger.info("%s/%s processes succeeded" % (succes, failed+succes)) 743 if succes == 0: 744 raise 745 else: 746 return 747 748 749 # If it is a process for MadLoop standalone, make sure it has a 750 # unique ID. It is important for building a BLHA library which 751 # contains unique entry point for each process generated. 752 all_ids = [amp.get('process').get('id') for amp in self._curr_amps] 753 if myprocdef.get('id') in all_ids: 754 myprocdef.set('id',max(all_ids)+1) 755 756 self.proc_validity(myprocdef,'ML5') 757 758 cpu_time1 = time.time() 759 760 # Decide here wether one needs a LoopMultiProcess or a MultiProcess 761 multiprocessclass=None 762 if myprocdef['perturbation_couplings']!=[]: 763 multiprocessclass=loop_diagram_generation.LoopMultiProcess 764 else: 765 multiprocessclass=diagram_generation.MultiProcess 766 767 myproc = multiprocessclass(myprocdef, collect_mirror_procs = False, 768 ignore_six_quark_processes = False, 769 loop_filter = loop_filter) 770 771 for amp in myproc.get('amplitudes'): 772 if amp not in self._curr_amps: 773 self._curr_amps.append(amp) 774 else: 775 warning = "Warning: Already in processes:\n%s" % \ 776 amp.nice_string_processes() 777 logger.warning(warning) 778 779 # Reset _done_export, since we have new process 780 self._done_export = False 781 782 cpu_time2 = time.time() 783 784 ndiags = sum([len(amp.get('loop_diagrams')) for \ 785 amp in myproc.get('amplitudes')]) 786 logger.info("Process generated in %0.3f s" % \ 787 (cpu_time2 - cpu_time1))
788
789 -class LoopInterfaceWeb(mg_interface.CheckValidForCmdWeb, LoopInterface):
790 pass
791