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 not isinstance(self._curr_model,loop_base_objects.LoopModel) or \ 291 self._curr_model['perturbation_couplings']==[] or \ 292 any((coupl not in self._curr_model['perturbation_couplings']) \ 293 for coupl in coupling_type): 294 if loop_type.startswith('real') or loop_type == 'LOonly': 295 if loop_type == 'real': 296 logger.info(\ 297 "Beware that real corrections are generated from a tree-level model.") 298 if loop_type == 'real_init' and \ 299 self._curr_model.get('name').split('-')[0]!='sm': 300 logger.info(\ 301 "You are entering aMC@NLO with a model which does not "+\ 302 " support loop corrections.") 303 else: 304 logger.info(\ 305 "The current model %s does not allow to generate"%self._curr_model.get('name')+ 306 " loop corrections of type %s."%str(coupling_type)) 307 model_path = self._curr_model.get('modelpath') 308 model_name = self._curr_model.get('name') 309 if model_name.split('-')[0]=='loop_sm': 310 model_name = model_name[5:] 311 if model_name.split('-')[0]=='sm': 312 # So that we don't load the model twice 313 if not self.options['gauge']=='Feynman' and 'QED' in coupling_type: 314 logger.info('Switch to Feynman gauge because '+\ 315 'model loop_qcd_qed_sm is restricted only to Feynman gauge.') 316 self._curr_model = None 317 mg_interface.MadGraphCmd.do_set(self,'gauge Feynman') 318 if coupling_type == ['QCD',]: 319 add_on = '' 320 elif coupling_type in [['QED'],['QCD','QED']]: 321 add_on = 'qcd_qed_' 322 else: 323 raise MadGraph5Error( 324 "The pertubation coupling cannot be '%s'"\ 325 %str(coupling_type)+" in SM loop processes") 326 327 logger.info("MG5_aMC now loads 'loop_%s%s'."%(add_on,model_name)) 328 329 #import model with correct treatment of the history 330 self.history.move_to_last('generate') 331 last_command = self.history[-1] 332 self.exec_cmd(" import model loop_%s%s" % (add_on,model_name), precmd=True) 333 self.history.append(last_command) 334 elif stop: 335 raise self.InvalidCmd( 336 "The model %s cannot handle loop processes"%model_name) 337 338 if loop_type and not loop_type.startswith('real') and \ 339 not self.options['gauge']=='Feynman' and \ 340 not self._curr_model['perturbation_couplings'] in [[],['QCD']]: 341 if 1 in self._curr_model.get('gauge'): 342 logger.info("Setting gauge to Feynman in order to process all"+\ 343 " possible loop computations available in the model.") 344 mg_interface.MadGraphCmd.do_set(self,'gauge Feynman') 345 else: 346 logger.warning("You will only be able to do tree level and QCD"+\ 347 " corrections with this model because it does not support Feynman gauge.")
348
349 -class LoopInterface(CheckLoop, CompleteLoop, HelpLoop, CommonLoopInterface):
350 351 supported_ML_format = ['standalone', 'standalone_rw', 'matchbox'] 352
353 - def __init__(self, mgme_dir = '', *completekey, **stdin):
354 """ Special init tasks for the Loop Interface """ 355 356 mg_interface.MadGraphCmd.__init__(self, mgme_dir = '', *completekey, **stdin) 357 self.setup()
358
359 - def setup(self):
360 """ Special tasks when switching to this interface """ 361 362 # Refresh all the interface stored value as things like generated 363 # processes and amplitudes are not to be reused in between different 364 # interfaces 365 # Clear history, amplitudes and matrix elements when a model is imported 366 # Remove previous imports, generations and outputs from history 367 self.history.clean(remove_bef_last='import', 368 to_keep=['set','load','import', 'define']) 369 # Reset amplitudes and matrix elements 370 self._done_export=False 371 self._curr_amps = diagram_generation.AmplitudeList() 372 self._curr_matrix_elements = helas_objects.HelasMultiProcess() 373 self._v4_export_formats = [] 374 self._export_formats = [ 'matrix', 'standalone' ] 375 self._nlo_modes_for_completion = ['virt'] 376 self.validate_model() 377 # Set where to look for CutTools installation. 378 # In further versions, it will be set in the same manner as _mgme_dir so that 379 # the user can chose its own CutTools distribution. 380 self._cuttools_dir=str(os.path.join(self._mgme_dir,'vendor','CutTools')) 381 if not os.path.isdir(os.path.join(self._cuttools_dir, 'src','cts')): 382 logger.warning(('Warning: Directory %s is not a valid CutTools directory.'+\ 383 'Using default CutTools instead.') % \ 384 self._cuttools_dir) 385 self._cuttools_dir=str(os.path.join(self._mgme_dir,'vendor','CutTools')) 386 # Set where to look for IREGI installation 387 self._iregi_dir=str(os.path.join(self._mgme_dir,'vendor','IREGI','src')) 388 if not os.path.isdir(self._iregi_dir): 389 logger.warning(('Warning: Directory %s is not a valid IREGI directory.'+\ 390 'Using default IREGI instead.')%\ 391 self._iregi_dir) 392 self._iregi_dir=str(os.path.join(self._mgme_dir,'vendor','IREGI','src'))
393
394 - def do_display(self,line, *argss, **opt):
395 """ Display born or loop diagrams, otherwise refer to the default display 396 command """ 397 398 args = self.split_arg(line) 399 #check the validity of the arguments 400 self.check_display(args) 401 402 if args[0]=='diagrams': 403 if len(args)>=2 and args[1] in ['loop','born']: 404 self.draw(' '.join(args[2:]),args[1]) 405 else: 406 self.draw(' '.join(args[1:]),'all') 407 else: 408 mg_interface.MadGraphCmd.do_display(self,line,*argss,**opt)
409
410 - def do_output(self, line):
411 """Main commands:Initialize a new Template or reinitialize one""" 412 413 args = self.split_arg(line) 414 # Check Argument validity 415 self.check_output(args) 416 417 noclean = '-noclean' in args 418 force = '-f' in args 419 nojpeg = '-nojpeg' in args 420 main_file_name = "" 421 try: 422 main_file_name = args[args.index('-name') + 1] 423 except Exception: 424 pass 425 426 # Whatever the format we always output the quadruple precision routines 427 # to allow for curing possible unstable points. 428 aloha_original_quad_mode = aloha.mp_precision 429 aloha.mp_precision = True 430 431 if self._export_format not in self.supported_ML_format: 432 raise self.InvalidCmd('ML5 only support "%s" as export format.' % \ 433 ''.join(self.supported_ML_format)) 434 435 if not os.path.isdir(self._export_dir) and self._export_format in ['matrix']: 436 raise self.InvalidCmd('Specified export directory %s does not exist.'\ 437 %str(self._export_dir)) 438 439 if not force and not noclean and os.path.isdir(self._export_dir)\ 440 and self._export_format.startswith('standalone'): 441 # Don't ask if user already specified force or noclean 442 logger.info('INFO: directory %s already exists.' % self._export_dir) 443 logger.info('If you continue this directory will be cleaned') 444 answer = self.ask('Do you want to continue?', 'y', ['y','n']) 445 if answer != 'y': 446 raise self.InvalidCmd('Stopped by user request') 447 else: 448 try: 449 shutil.rmtree(self._export_dir) 450 except OSError: 451 raise self.InvalidCmd('Could not remove directory %s.'\ 452 %str(self._export_dir)) 453 454 if self._export_format.startswith('standalone'): 455 output_type = 'madloop' 456 elif self._export_format == 'matchbox': 457 output_type = 'madloop_matchbox' 458 459 self._curr_exporter = export_v4.ExportV4Factory(self, \ 460 noclean, output_type=output_type, group_subprocesses=False) 461 462 if self._export_format in ['standalone', 'matchbox']: 463 self._curr_exporter.copy_v4template(modelname=self._curr_model.get('name')) 464 465 if self._export_format == "standalone_rw": 466 self._export_format = "standalone" 467 self._curr_exporter.copy_v4template(modelname=self._curr_model.get('name')) 468 self._export_format = "standalone_rw" 469 470 # Reset _done_export, since we have new directory 471 self._done_export = False 472 473 # Perform export and finalize right away 474 self.ML5export(nojpeg, main_file_name) 475 476 # Automatically run finalize 477 self.ML5finalize(nojpeg) 478 479 # Remember that we have done export 480 self._done_export = (self._export_dir, self._export_format) 481 482 # Reset _export_dir, so we don't overwrite by mistake later 483 self._export_dir = None 484 485 # Put aloha back in its original mode. 486 aloha.mp_precision = aloha_original_quad_mode
487 488 # Export a matrix element 489
490 - def ML5export(self, nojpeg = False, main_file_name = ""):
491 """Export a generated amplitude to file""" 492 493 def generate_matrix_elements(self): 494 """Helper function to generate the matrix elements before exporting""" 495 496 # Sort amplitudes according to number of diagrams, 497 # to get most efficient multichannel output 498 self._curr_amps.sort(lambda a1, a2: a2.get_number_of_diagrams() - \ 499 a1.get_number_of_diagrams()) 500 501 cpu_time1 = time.time() 502 ndiags = 0 503 if not self._curr_matrix_elements.get_matrix_elements(): 504 self._curr_matrix_elements = \ 505 loop_helas_objects.LoopHelasProcess(self._curr_amps, 506 optimized_output = self.options['loop_optimized_output']) 507 ndiags = sum([len(me.get('diagrams')) for \ 508 me in self._curr_matrix_elements.\ 509 get_matrix_elements()]) 510 # assign a unique id number to all process 511 uid = 0 512 for me in self._curr_matrix_elements.get_matrix_elements(): 513 uid += 1 # update the identification number 514 me.get('processes')[0].set('uid', uid) 515 516 cpu_time2 = time.time() 517 return ndiags, cpu_time2 - cpu_time1
518 519 # Start of the actual routine 520 ndiags, cpu_time = generate_matrix_elements(self) 521 522 calls = 0 523 524 path = self._export_dir 525 if self._export_format in self.supported_ML_format: 526 path = pjoin(path, 'SubProcesses') 527 528 cpu_time1 = time.time() 529 530 # Pick out the matrix elements in a list 531 matrix_elements = \ 532 self._curr_matrix_elements.get_matrix_elements() 533 534 # Fortran MadGraph5_aMC@NLO Standalone 535 if self._export_format in self.supported_ML_format: 536 for me in matrix_elements: 537 calls = calls + \ 538 self._curr_exporter.generate_subprocess_directory_v4(\ 539 me, self._curr_fortran_model) 540 # If all ME's do not share the same maximum loop vertex rank and the 541 # same loop maximum wavefunction size, we need to set the maximum 542 # in coef_specs.inc of the HELAS Source. The SubProcesses/P* directory 543 # all link this file, so it should be properly propagated 544 if self.options['loop_optimized_output'] and len(matrix_elements)>1: 545 max_lwfspins = [m.get_max_loop_particle_spin() for m in \ 546 matrix_elements] 547 max_loop_vert_ranks = [me.get_max_loop_vertex_rank() for me in \ 548 matrix_elements] 549 if len(set(max_lwfspins))>1 or len(set(max_loop_vert_ranks))>1: 550 self._curr_exporter.fix_coef_specs(max(max_lwfspins),\ 551 max(max_loop_vert_ranks)) 552 553 # Just the matrix.f files 554 if self._export_format == 'matrix': 555 for me in matrix_elements: 556 filename = pjoin(path, 'matrix_' + \ 557 me.get('processes')[0].shell_string() + ".f") 558 if os.path.isfile(filename): 559 logger.warning("Overwriting existing file %s" % filename) 560 else: 561 logger.info("Creating new file %s" % filename) 562 calls = calls + self._curr_exporter.write_matrix_element_v4(\ 563 writers.FortranWriter(filename),\ 564 me, self._curr_fortran_model) 565 566 cpu_time2 = time.time() - cpu_time1 567 568 logger.info(("Generated helas calls for %d subprocesses " + \ 569 "(%d diagrams) in %0.3f s") % \ 570 (len(matrix_elements), 571 ndiags, cpu_time)) 572 573 if calls: 574 if "cpu_time2" in locals(): 575 logger.info("Wrote files for %d OPP calls in %0.3f s" % \ 576 (calls, cpu_time2)) 577 else: 578 logger.info("Wrote files for %d OPP calls" % \ 579 (calls)) 580 581 # Replace the amplitudes with the actual amplitudes from the 582 # matrix elements, which allows proper diagram drawing also of 583 # decay chain processes 584 self._curr_amps = diagram_generation.AmplitudeList(\ 585 [me.get('base_amplitude') for me in \ 586 matrix_elements])
587
588 - def ML5finalize(self, nojpeg, online = False):
589 """Copy necessary sources and output the ps representation of 590 the diagrams, if needed""" 591 592 if self._export_format in self.supported_ML_format: 593 logger.info('Export UFO model to MG4 format') 594 # wanted_lorentz are the lorentz structures which are 595 # actually used in the wavefunctions and amplitudes in 596 # these processes 597 wanted_lorentz = self._curr_matrix_elements.get_used_lorentz() 598 wanted_couplings = self._curr_matrix_elements.get_used_couplings() 599 # For a unique output of multiple type of exporter model information 600 # are save in memory 601 if hasattr(self, 'previous_lorentz'): 602 wanted_lorentz = list(set(self.previous_lorentz + wanted_lorentz)) 603 wanted_couplings = list(set(self.previous_couplings + wanted_couplings)) 604 del self.previous_lorentz 605 del self.previous_couplings 606 607 self._curr_exporter.convert_model_to_mg4(self._curr_model, 608 wanted_lorentz, 609 wanted_couplings) 610 611 compiler = {'fortran': self.options['fortran_compiler'], 612 'f2py': self.options['f2py_compiler'], 613 'cpp': self.options['cpp_compiler']} 614 615 if self._export_format in self.supported_ML_format: 616 self._curr_exporter.finalize_v4_directory( \ 617 self._curr_matrix_elements, 618 self.history, 619 not nojpeg, 620 online, 621 compiler) 622 623 if self._export_format in self.supported_ML_format: 624 logger.info('Output to directory ' + self._export_dir + ' done.')
625
626 - def do_launch(self, line, *args,**opt):
627 """Main commands: Check that the type of launch is fine before proceeding with the 628 mother function. """ 629 630 args = self.split_arg(line) 631 # check argument validity and normalise argument 632 (options, args) = mg_interface._launch_parser.parse_args(args) 633 634 self.check_launch(args, options) 635 636 if not args[0].startswith('standalone'): 637 raise self.InvalidCmd('ML5 can only launch standalone runs.') 638 639 start_cwd = os.getcwd() 640 options = options.__dict__ 641 # args is now MODE PATH 642 643 ext_program = launch_ext.MadLoopLauncher(self, args[1], \ 644 options=self.options, **options) 645 ext_program.run() 646 os.chdir(start_cwd) #ensure to go to the initial path
647
648 - def do_check(self, line, *args,**opt):
649 """Check a given process or set of processes""" 650 651 argss = self.split_arg(line, *args,**opt) 652 # Check args validity 653 perturbation_couplings_pattern = \ 654 re.compile("^(?P<proc>.+)\s*\[\s*((?P<option>\w+)\s*\=)?\s*(?P<pertOrders>(\w+\s*)*)\s*\]\s*(?P<rest>.*)$") 655 perturbation_couplings_re = perturbation_couplings_pattern.match(line) 656 perturbation_couplings="" 657 if perturbation_couplings_re: 658 perturbation_couplings = perturbation_couplings_re.group("pertOrders") 659 QED_found=re.search("QED",perturbation_couplings) 660 if QED_found: 661 self.validate_model(coupling_type='QED') 662 else: 663 self.validate_model() 664 665 param_card = self.check_check(argss) 666 reuse = argss[1]=="-reuse" 667 argss = argss[:1]+argss[2:] 668 # For the stability check the user can specify the statistics (i.e 669 # number of trial PS points) as a second argument 670 if argss[0] in ['stability', 'profile']: 671 stab_statistics = int(argss[1]) 672 argss = argss[:1]+argss[2:] 673 # Remove the extra options 674 i=-1 675 while argss[i].startswith('--'): 676 i=i-1 677 # Now make sure the process is acceptable 678 proc = " ".join(argss[1:i+1]) 679 myprocdef = self.extract_process(proc) 680 self.proc_validity(myprocdef,'ML5_check_cms' if argss[0]=='cms' else \ 681 'ML5_check') 682 683 return mg_interface.MadGraphCmd.do_check(self, line, *args,**opt)
684
685 - def do_add(self, line, *args,**opt):
686 """Generate an amplitude for a given process and add to 687 existing amplitudes 688 """ 689 args = self.split_arg(line) 690 # Check the validity of the arguments 691 self.check_add(args) 692 perturbation_couplings_pattern = \ 693 re.compile("^(?P<proc>.+)\s*\[\s*((?P<option>\w+)\s*\=)?\s*(?P<pertOrders>(\w+\s*)*)\s*\]\s*(?P<rest>.*)$") 694 perturbation_couplings_re = perturbation_couplings_pattern.match(line) 695 perturbation_couplings="" 696 if perturbation_couplings_re: 697 perturbation_couplings = perturbation_couplings_re.group("pertOrders") 698 QED_found=re.search('QED',perturbation_couplings) 699 if QED_found: 700 self.validate_model(coupling_type='QED') 701 else: 702 self.validate_model() 703 704 loop_filter=None 705 if args[0] == 'process': 706 707 # Extract potential loop_filter 708 for arg in args: 709 if arg.startswith('--loop_filter='): 710 loop_filter = arg[14:] 711 if not isinstance(self, extended_cmd.CmdShell): 712 raise InvalidCmd, "loop_filter is not allowed in web mode" 713 args = [a for a in args if not a.startswith('--loop_filter=')] 714 715 # Rejoin line 716 line = ' '.join(args[1:]) 717 718 # store the first process (for the perl script) 719 if not self._generate_info: 720 self._generate_info = line 721 722 # Reset Helas matrix elements 723 self._curr_matrix_elements = helas_objects.HelasMultiProcess() 724 725 # Extract process from process definition 726 myprocdef = self.extract_process(line) 727 # hack for multiprocess: 728 if myprocdef.has_multiparticle_label(): 729 # split it in a loop 730 succes, failed = 0, 0 731 for base_proc in myprocdef: 732 try: 733 self.exec_cmd("add process %s" % base_proc.nice_string(prefix=False, print_weighted=True)) 734 succes += 1 735 except Exception: 736 failed +=1 737 logger.info("%s/%s processes succeeded" % (succes, failed+succes)) 738 if succes == 0: 739 raise 740 else: 741 return 742 743 744 # If it is a process for MadLoop standalone, make sure it has a 745 # unique ID. It is important for building a BLHA library which 746 # contains unique entry point for each process generated. 747 all_ids = [amp.get('process').get('id') for amp in self._curr_amps] 748 if myprocdef.get('id') in all_ids: 749 myprocdef.set('id',max(all_ids)+1) 750 751 self.proc_validity(myprocdef,'ML5') 752 753 cpu_time1 = time.time() 754 755 # Decide here wether one needs a LoopMultiProcess or a MultiProcess 756 multiprocessclass=None 757 if myprocdef['perturbation_couplings']!=[]: 758 multiprocessclass=loop_diagram_generation.LoopMultiProcess 759 else: 760 multiprocessclass=diagram_generation.MultiProcess 761 762 myproc = multiprocessclass(myprocdef, collect_mirror_procs = False, 763 ignore_six_quark_processes = False, 764 loop_filter = loop_filter) 765 766 for amp in myproc.get('amplitudes'): 767 if amp not in self._curr_amps: 768 self._curr_amps.append(amp) 769 else: 770 warning = "Warning: Already in processes:\n%s" % \ 771 amp.nice_string_processes() 772 logger.warning(warning) 773 774 # Reset _done_export, since we have new process 775 self._done_export = False 776 777 cpu_time2 = time.time() 778 779 ndiags = sum([len(amp.get('loop_diagrams')) for \ 780 amp in myproc.get('amplitudes')]) 781 logger.info("Process generated in %0.3f s" % \ 782 (cpu_time2 - cpu_time1))
783
784 -class LoopInterfaceWeb(mg_interface.CheckValidForCmdWeb, LoopInterface):
785 pass
786