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