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