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

Source Code for Module madgraph.interface.amcatnlo_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 logging 
 21  import pydoc 
 22  import sys 
 23  import time 
 24  import optparse 
 25  import subprocess 
 26  import shutil 
 27  import copy 
 28  import multiprocessing 
 29  import signal 
 30  import tempfile 
 31  import itertools 
 32  import os 
 33  import cPickle 
 34   
 35   
 36  import madgraph 
 37  from madgraph import MG4DIR, MG5DIR, MadGraph5Error 
 38  import madgraph.interface.extended_cmd as cmd 
 39  import madgraph.interface.madgraph_interface as mg_interface 
 40  import madgraph.interface.madevent_interface as me_interface 
 41  import madgraph.interface.extended_cmd as extended_cmd 
 42  import madgraph.interface.amcatnlo_run_interface as run_interface 
 43  import madgraph.interface.launch_ext_program as launch_ext 
 44  import madgraph.interface.loop_interface as Loop_interface 
 45  import madgraph.fks.fks_common as fks_common 
 46  import madgraph.fks.fks_base as fks_base 
 47  import madgraph.fks.fks_helas_objects as fks_helas 
 48  import madgraph.iolibs.export_fks as export_fks 
 49  import madgraph.iolibs.export_v4 as export_v4 
 50  import madgraph.iolibs.helas_call_writers as helas_call_writers 
 51  import madgraph.loop.loop_base_objects as loop_base_objects 
 52  import madgraph.core.diagram_generation as diagram_generation 
 53  import madgraph.core.helas_objects as helas_objects 
 54   
 55  import madgraph.various.cluster as cluster 
 56  import madgraph.various.misc as misc 
 57  import madgraph.various.banner as banner_mod 
 58   
 59  #usefull shortcut 
 60  pjoin = os.path.join 
 61   
 62   
 63  logger = logging.getLogger('cmdprint') # -> stdout 
 64  logger_stderr = logging.getLogger('fatalerror') # ->stderr 
 65   
 66  # a new function for the improved NLO generation 
 67  glob_directories_map = [] 
68 -def generate_directories_fks_async(i):
69 70 arglist = glob_directories_map[i] 71 72 curr_exporter = arglist[0] 73 mefile = arglist[1] 74 curr_fortran_model = arglist[2] 75 ime = arglist[3] 76 nme = arglist[4] 77 path = arglist[5] 78 olpopts = arglist[6] 79 80 infile = open(mefile,'rb') 81 me = cPickle.load(infile) 82 infile.close() 83 84 calls = curr_exporter.generate_directories_fks(me, curr_fortran_model, ime, nme, path, olpopts) 85 processes = me.born_me.get('processes') 86 87 #only available after export has been done, so has to be returned from here 88 max_loop_vertex_rank = -99 89 if me.virt_matrix_element: 90 max_loop_vertex_rank = me.virt_matrix_element.get_max_loop_vertex_rank() 91 92 return [calls, curr_exporter.fksdirs, max_loop_vertex_rank, curr_exporter.proc_characteristic, processes]
93 94
95 -class CheckFKS(mg_interface.CheckValidForCmd):
96 97
98 - def check_display(self, args):
99 """ Check the arguments of the display diagrams command in the context 100 of the Loop interface.""" 101 102 mg_interface.MadGraphCmd.check_display(self,args) 103 104 if args[0] in ['diagrams', 'processes'] and len(args)>=3 \ 105 and args[1] not in ['born','loop','virt','real']: 106 raise self.InvalidCmd("Can only display born, loop (virt) or real diagrams, not %s."%args[1]) 107 # rename args[1] if it is 'virt' 108 if len(args) > 1: 109 if args[1] == 'virt': 110 args[1] = 'loop'
111
112 - def check_add(self, args):
113 114 super(CheckFKS, self).check_add(args) 115 if '$' in args: 116 raise self.InvalidCmd('$ syntax not valid for aMC@NLO. $$ syntax is on the other hand a valid syntax.')
117
118 - def check_tutorial(self, args):
119 """check the validity of the line""" 120 if len(args) == 0: 121 #this means mg5 tutorial 122 args.append('aMCatNLO') 123 else: 124 return mg_interface.CheckValidForCmd.check_tutorial(self,args)
125
126 - def check_output(self, args):
127 """ check the validity of the line""" 128 129 self._export_format = 'NLO' 130 forbidden_formats = ['madevent', 'standalone'] 131 132 133 if not hasattr(self, '_fks_multi_proc') or not self._fks_multi_proc: 134 text = 'No processes generated. Please generate a process first.' 135 raise self.InvalidCmd(text) 136 137 if not self._curr_model: 138 text = 'No model found. Please import a model first and then retry.' 139 raise self.InvalidCmd(text) 140 141 if args and args[0][0] != '-': 142 if args[0] in forbidden_formats: 143 text = 'You generated a NLO process, which cannot be exported in %s mode.\n' % args[0] 144 text+= 'Please use the command "output DIR_NAME".\n' 145 raise self.InvalidCmd(text) 146 147 # This is a path 148 path = args.pop(0) 149 # Check for special directory treatment 150 if path == 'auto': 151 self.get_default_path() 152 elif path != 'auto': 153 self._export_dir = path 154 else: 155 # No valid path 156 self.get_default_path() 157 158 self._export_dir = os.path.realpath(self._export_dir)
159 160
161 - def check_launch(self, args, options):
162 """check the validity of the line. args are DIR and MODE 163 MODE being LO, NLO, aMC@NLO or aMC@LO. If no mode is passed, aMC@NLO is used""" 164 # modify args in order to be DIR 165 # mode being either standalone or madevent 166 167 if not args: 168 if self._done_export: 169 args.append(self._done_export[0]) 170 args.append('auto') 171 172 return 173 else: 174 self.help_launch() 175 raise self.InvalidCmd, \ 176 'No default location available, please specify location.' 177 178 if len(args) > 2: 179 self.help_launch() 180 return self.InvalidCmd, 'Invalid Syntax: Too many argument' 181 182 elif len(args) == 2: 183 if not args[1] in ['LO', 'NLO', 'aMC@NLO', 'aMC@LO', 'auto']: 184 raise self.InvalidCmd, '%s is not a valid mode, please use "LO", "NLO", "aMC@NLO" or "aMC@LO"' % args[1] 185 else: 186 #check if args[0] is path or mode 187 if args[0] in ['LO', 'NLO', 'aMC@NLO', 'aMC@LO', 'auto'] and self._done_export: 188 args.insert(0, self._done_export[0]) 189 elif os.path.isdir(args[0]) or os.path.isdir(pjoin(MG5DIR, args[0]))\ 190 or os.path.isdir(pjoin(MG4DIR, args[0])): 191 args.append('auto') 192 else: 193 self.help_launch() 194 raise self.InvalidCmd, '%s is not a valid process directory nor run mode' % args[0] 195 196 mode = args[1] 197 198 # search for a valid path 199 if os.path.isdir(args[0]): 200 path = os.path.realpath(args[0]) 201 elif os.path.isdir(pjoin(MG5DIR,args[0])): 202 path = pjoin(MG5DIR,args[0]) 203 elif MG4DIR and os.path.isdir(pjoin(MG4DIR,args[0])): 204 path = pjoin(MG4DIR,args[0]) 205 else: 206 raise self.InvalidCmd, '%s is not a valid directory' % args[0] 207 args[0] = path 208 209 # inform where we are for future command 210 self._done_export = [path, mode] 211 212 # check for incompatible options/modes 213 if options['multicore'] and options['cluster']: 214 raise self.InvalidCmd, 'options -m (--multicore) and -c (--cluster)' + \ 215 ' are not compatible. Please choose one.' 216 if mode == 'NLO' and options['reweightonly']: 217 raise self.InvalidCmd, 'option -r (--reweightonly) needs mode "aMC@NLO" or "aMC@LO"'
218 219
220 -class CheckFKSWeb(mg_interface.CheckValidForCmdWeb, CheckFKS):
221 pass
222
223 -class CompleteFKS(mg_interface.CompleteForCmd):
224
225 - def complete_display(self, text, line, begidx, endidx):
226 """Complete the display command in the context of the FKS interface""" 227 228 args = self.split_arg(line[0:begidx]) 229 230 if len(args) == 2 and args[1] in ['diagrams', 'processes']: 231 return self.list_completion(text, ['born', 'loop', 'virt', 'real']) 232 else: 233 return mg_interface.MadGraphCmd.complete_display(self, text, line, 234 begidx, endidx)
235 236
237 - def complete_output(self, text, line, begidx, endidx):
238 """Complete the output command in the context of the FKS interface""" 239 #don't propose directory use by MG_ME 240 forbidden_names = ['MadGraphII', 'Template', 'pythia-pgs', 'CVS', 241 'Calculators', 'MadAnalysis', 'SimpleAnalysis', 242 'mg5', 'DECAY', 'EventConverter', 'Models', 243 'ExRootAnalysis', 'HELAS', 'Transfer_Fct', 'aloha', 244 'madgraph', 'bin', 'tests', 'input', 'vendor', 'models'] 245 246 #name of the run =>proposes old run name 247 args = self.split_arg(line[0:begidx]) 248 if len(args) >= 1: 249 if len(args) > 1 and args[1] == 'aloha': 250 try: 251 return self.aloha_complete_output(text, line, begidx, endidx) 252 except Exception, error: 253 print error 254 # Directory continuation 255 if args[-1].endswith(os.path.sep): 256 return [name for name in self.path_completion(text, 257 pjoin(*[a for a in args if a.endswith(os.path.sep)]), 258 only_dirs = True) if name not in forbidden_names] 259 260 # directory names 261 content = [name for name in self.path_completion(text, '.', only_dirs = True) \ 262 if name not in forbidden_names] 263 return self.list_completion(text, content)
264 265
266 - def complete_launch(self, text, line, begidx, endidx, formatting=True):
267 """ complete the launch command""" 268 args = self.split_arg(line[0:begidx]) 269 270 # Directory continuation 271 if args[-1].endswith(os.path.sep): 272 return self.path_completion(text, 273 pjoin(*[a for a in args if a.endswith(os.path.sep)]), 274 only_dirs = True) 275 # Format 276 if len(args) == 1: 277 out = {'Path from ./': self.path_completion(text, '.', only_dirs = True)} 278 if MG5DIR != os.path.realpath('.'): 279 out['Path from %s' % MG5DIR] = self.path_completion(text, 280 MG5DIR, only_dirs = True, relative=False) 281 if MG4DIR and MG4DIR != os.path.realpath('.') and MG4DIR != MG5DIR: 282 out['Path from %s' % MG4DIR] = self.path_completion(text, 283 MG4DIR, only_dirs = True, relative=False) 284 285 if len(args) == 2: 286 modes = ['aMC@NLO', 'NLO', 'aMC@LO', 'LO'] 287 return self.list_completion(text, modes, line) 288 289 #option 290 if len(args) >= 3: 291 out={} 292 293 if line[0:begidx].endswith('--laststep='): 294 opt = ['parton', 'pythia', 'pgs','delphes','auto'] 295 out['Options'] = self.list_completion(text, opt, line) 296 else: 297 298 opt = ['-f', '-c', '-m', '-i', '-x', '-r', '-p', '-o', '-n', 'a', 299 '--force', '--cluster', '--multicore', '--interactive', 300 '--nocompile', '--reweightonly', '--parton', '--only_generation', '--name', '--appl_start_grid'] 301 out['Options'] = self.list_completion(text, opt, line) 302 303 304 return self.deal_multiple_categories(out, formatting)
305
306 -class HelpFKS(mg_interface.HelpToCmd):
307
308 - def help_display(self):
309 mg_interface.MadGraphCmd.help_display(self) 310 logger.info(" In aMC@NLO5, after display diagrams, the user can add the option") 311 logger.info(" \"born\", \"virt\" or \"real\" to display only the corresponding diagrams.")
312
313 - def help_launch(self):
314 """help for launch command""" 315 _launch_parser.print_help()
316
317 -class aMCatNLOInterface(CheckFKS, CompleteFKS, HelpFKS, Loop_interface.CommonLoopInterface):
318 319 _fks_display_opts = ['real_diagrams', 'born_diagrams', 'virt_diagrams', 320 'real_processes', 'born_processes', 'virt_processes'] 321 322 _nlo_modes_for_completion = ['all','real'] 323
324 - def __init__(self, mgme_dir = '', *completekey, **stdin):
325 """ Special init tasks for the Loop Interface """ 326 mg_interface.MadGraphCmd.__init__(self, mgme_dir = '', *completekey, **stdin) 327 self.setup()
328
329 - def setup(self):
330 """ Special tasks when switching to this interface """ 331 332 # Refresh all the interface stored value as things like generated 333 # processes and amplitudes are not to be reused in between different 334 # interfaces 335 # Clear history, amplitudes and matrix elements when a model is imported 336 # Remove previous imports, generations and outputs from history 337 self.history.clean(remove_bef_last='import', 338 to_keep=['set','load','import', 'define']) 339 # Reset amplitudes and matrix elements 340 self._done_export=False 341 self._curr_amps = diagram_generation.AmplitudeList() 342 self._curr_matrix_elements = helas_objects.HelasMultiProcess() 343 self._v4_export_formats = [] 344 self._nlo_modes_for_completion = ['all','real'] 345 self._export_formats = [ 'madevent', 'aloha' ] 346 # Do not force NLO model as the user might have asked for reals only. 347 # It will anyway be forced later if he attempts virt= or all=. 348 self.validate_model(loop_type='real_init', stop=False) 349 # Set where to look for CutTools installation. 350 # In further versions, it will be set in the same manner as _mgme_dir so that 351 # the user can chose its own CutTools distribution. 352 self._cuttools_dir=str(pjoin(self._mgme_dir,'vendor','CutTools')) 353 if not os.path.isdir(pjoin(self._cuttools_dir, 'src','cts')): 354 logger.warning(('Warning: Directory %s is not a valid CutTools directory.'+\ 355 'Using default CutTools instead.') % \ 356 self._cuttools_dir) 357 self._cuttools_dir=str(pjoin(self._mgme_dir,'vendor','CutTools')) 358 # Set where to look for IREGI installation 359 self._iregi_dir=str(os.path.join(self._mgme_dir,'vendor','IREGI','src')) 360 if not os.path.isdir(self._iregi_dir): 361 logger.warning(('Warning: Directory %s is not a valid IREGI directory.'+\ 362 'Using default IREGI instead.')%\ 363 self._iregi_dir) 364 self._iregi_dir=str(os.path.join(self._mgme_dir,'vendor','IREGI','src'))
365
366 - def do_display(self, line, output=sys.stdout):
367 # if we arrive here it means that a _fks_display_opts has been chosen 368 args = self.split_arg(line) 369 #check the validity of the arguments 370 self.check_display(args) 371 372 if args[0] in ['diagrams', 'processes', 'diagrams_text']: 373 get_amps_dict = {'real': self._fks_multi_proc.get_real_amplitudes, 374 'born': self._fks_multi_proc.get_born_amplitudes, 375 'loop': self._fks_multi_proc.get_virt_amplitudes} 376 if args[0] == 'diagrams': 377 if len(args)>=2 and args[1] in get_amps_dict.keys(): 378 get_amps = get_amps_dict[args[1]] 379 self._curr_amps = get_amps() 380 #check that if one requests the virt diagrams, there are virt_amplitudes 381 if args[1] == 'loop' and len(self._curr_amps) == 0: 382 raise self.InvalidCmd('No virtuals have been generated') 383 self.draw(' '.join(args[2:]),type = args[1]) 384 else: 385 for diag_type, get_amps in get_amps_dict.items(): 386 self._curr_amps = get_amps() 387 if self._curr_amps: 388 self.draw(' '.join(args[1:]), Dtype=diag_type) 389 390 # set _curr_amps back to empty 391 self._curr_amps = diagram_generation.AmplitudeList() 392 393 if args[0] == 'diagrams_text': 394 if len(args)>=2 and args[1] in get_amps_dict.keys(): 395 get_amps = get_amps_dict[args[1]] 396 self._curr_amps = get_amps() 397 #check that if one requests the virt diagrams, there are virt_amplitudes 398 if args[1] in ['virt', 'loop'] and len(self._curr_amps) == 0: 399 raise self.InvalidCmd('No virtuals have been generated') 400 text = "\n".join([amp.nice_string() for amp in self._curr_amps]) 401 else: 402 text = 'Born diagrams:\n' 403 text += '\n'.join(amp.nice_string() for amp in get_amps_dict['born']()) 404 text += '\n\nReal diagrams:' 405 text += '\n'.join(amp.nice_string() for amp in get_amps_dict['real']()) 406 text += '\n\nLoop diagrams:\n' 407 text += '\n'.join(amp.nice_string() for amp in get_amps_dict['loop']()) 408 pydoc.pager(text) 409 410 # set _curr_amps back to empty 411 self._curr_amps = diagram_generation.AmplitudeList() 412 413 elif args[0] == 'processes': 414 if len(args)>=2 and args[1] in get_amps_dict.keys(): 415 get_amps = get_amps_dict[args[1]] 416 self._curr_amps = get_amps() 417 #check that if one requests the virt diagrams, there are virt_amplitudes 418 if args[1] in ['virt', 'loop'] and len(self._curr_amps) == 0: 419 raise self.InvalidCmd('No virtuals have been generated') 420 print '\n'.join(amp.nice_string_processes() for amp in self._curr_amps) 421 else: 422 print 'Born processes:' 423 print '\n'.join(amp.nice_string_processes() for amp in get_amps_dict['born']()) 424 print 'Real processes:' 425 print '\n'.join(amp.nice_string_processes() for amp in get_amps_dict['real']()) 426 print 'Loop processes:' 427 print '\n'.join(amp.nice_string_processes() for amp in get_amps_dict['loop']()) 428 # set _curr_amps back to empty 429 self._curr_amps = diagram_generation.AmplitudeList() 430 431 else: 432 mg_interface.MadGraphCmd.do_display(self,line,output)
433
434 - def do_add(self, line, *args,**opt):
435 436 args = self.split_arg(line) 437 # Check the validity of the arguments 438 self.check_add(args) 439 440 if args[0] == 'model': 441 return self.add_model(args[1:]) 442 elif args[0] != 'process': 443 raise self.InvalidCmd("The add command can only be used with process or model") 444 else: 445 line = ' '.join(args[1:]) 446 447 proc_type=self.extract_process_type(line) 448 if proc_type[1] not in ['real', 'LOonly']: 449 run_interface.check_compiler(self.options, block=False) 450 #validate_model will reset self._generate_info; to avoid 451 #this store it 452 geninfo = self._generate_info 453 self.validate_model(proc_type[1], coupling_type=proc_type[2]) 454 self._generate_info = geninfo 455 456 #now generate the amplitudes as usual 457 #self.options['group_subprocesses'] = 'False' 458 collect_mirror_procs = False 459 ignore_six_quark_processes = self.options['ignore_six_quark_processes'] 460 if ',' in line: 461 myprocdef, line = mg_interface.MadGraphCmd.extract_decay_chain_process(self,line) 462 if myprocdef.are_decays_perturbed(): 463 raise MadGraph5Error("Decay processes cannot be perturbed") 464 else: 465 myprocdef = mg_interface.MadGraphCmd.extract_process(self,line) 466 467 self.proc_validity(myprocdef,'aMCatNLO_%s'%proc_type[1]) 468 469 # set the orders 470 # if some orders have been set by the user, 471 # check that all the orders of the model have been specified 472 # set to zero those which have not been specified and warn the user 473 if myprocdef['orders'] and not all([o in myprocdef['orders'].keys() for o in myprocdef['model'].get_coupling_orders()]): 474 for o in myprocdef['model'].get_coupling_orders(): 475 if o not in myprocdef['orders'].keys(): 476 myprocdef['orders'][o] = 0 477 logger.warning(('%s order is missing in the process definition. It will be set to 0.\n' + \ 478 'If this is not what you need, please regenerate with the correct orders.') % o) 479 480 # this is in case no orders have been passed 481 if not myprocdef['orders']: 482 # find the minimum weighted order, then extract the values for the varius 483 # couplings in the model 484 weighted = diagram_generation.MultiProcess.find_optimal_process_orders(myprocdef) 485 if not weighted: 486 raise MadGraph5Error,'\nProcess orders cannot be determined automatically. \n' + \ 487 'Please specify them from the command line.' 488 489 # this is a very rough attempt, and works only to guess QED/QCD 490 qed, qcd = fks_common.get_qed_qcd_orders_from_weighted(len(myprocdef['legs']), weighted['WEIGHTED']) 491 if qed < 0 or qcd < 0: 492 raise MadGraph5Error,'\nAutomatic process-order determination lead to negative constraints:\n' + \ 493 ('QED: %d, QCD: %d\n' % (qed, qcd)) + \ 494 'Please specify the coupling orders from the command line.' 495 orders = {'QED': qed, 'QCD': qcd} 496 # set all the other coupling to zero 497 for o in myprocdef['model'].get_coupling_orders(): 498 if o not in ['QED', 'QCD']: 499 orders[o] = 0 500 501 myprocdef.set('orders', orders) 502 # warn the user of what happened 503 logger.info(('Setting the born orders automatically in the process definition to %s.\n' + \ 504 'If this is not what you need, please regenerate with the correct orders.'), 505 ' '.join(['%s<=%s' %(k,v) if v else '%s=%s' % (k,v) for k,v in myprocdef['orders'].items()]), 506 '$MG:BOLD') 507 508 myprocdef['born_orders'] = copy.copy(myprocdef['orders']) 509 # split all orders in the model, for the moment it's the simplest solution 510 # mz02/2014 511 myprocdef['split_orders'] += [o for o in myprocdef['model'].get('coupling_orders') \ 512 if o not in myprocdef['split_orders']] 513 514 # now set the squared orders 515 if not myprocdef['squared_orders']: 516 for ord, val in myprocdef['orders'].items(): 517 myprocdef['squared_orders'][ord] = 2 * val 518 519 # then increase the orders which are perturbed 520 for pert in myprocdef['perturbation_couplings']: 521 # if orders have been specified increase them 522 if myprocdef['orders'].keys() != ['WEIGHTED']: 523 try: 524 myprocdef['orders'][pert] += 2 525 except KeyError: 526 # if the order is not specified 527 # then MG does not put any bound on it 528 myprocdef['orders'][pert] = 99 529 try: 530 myprocdef['squared_orders'][pert] += 2 531 except KeyError: 532 myprocdef['squared_orders'][pert] = 200 533 534 # update also the WEIGHTED entry 535 if 'WEIGHTED' in myprocdef['orders'].keys(): 536 myprocdef['orders']['WEIGHTED'] += 1 * \ 537 max([myprocdef.get('model').get('order_hierarchy')[ord] for \ 538 ord in myprocdef['perturbation_couplings']]) 539 540 myprocdef['squared_orders']['WEIGHTED'] += 2 * \ 541 max([myprocdef.get('model').get('order_hierarchy')[ord] for \ 542 ord in myprocdef['perturbation_couplings']]) 543 # finally set perturbation_couplings to **all** the coupling orders 544 # avaliable in the model 545 myprocdef['perturbation_couplings'] = list(myprocdef['model']['coupling_orders']) 546 547 548 myprocdef['orders'] = {} 549 self._curr_proc_defs.append(myprocdef) 550 551 # if myprocdef['perturbation_couplings']!=['QCD']: 552 # message = ""FKS for reals only available in QCD for now, you asked %s" \ 553 # % ', '.join(myprocdef['perturbation_couplings'])" 554 # logger.info("%s. Checking for loop induced") 555 # new_line = ln 556 # 557 # 558 # raise self.InvalidCmd("FKS for reals only available in QCD for now, you asked %s" \ 559 # % ', '.join(myprocdef['perturbation_couplings'])) 560 ## 561 562 # if the new nlo process generation mode is enabled, the number of cores to be 563 # used has to be passed 564 # ncores_for_proc_gen has the following meaning 565 # 0 : do things the old way 566 # > 0 use ncores_for_proc_gen 567 # -1 : use all cores 568 if self.options['low_mem_multicore_nlo_generation']: 569 if self.options['nb_core']: 570 self.ncores_for_proc_gen = int(self.options['nb_core']) 571 else: 572 self.ncores_for_proc_gen = -1 573 else: 574 self.ncores_for_proc_gen = 0 575 576 # this is the options dictionary to pass to the FKSMultiProcess 577 fks_options = {'OLP': self.options['OLP'], 578 'ignore_six_quark_processes': self.options['ignore_six_quark_processes'], 579 'init_lep_split': self.options['include_lepton_initiated_processes'], 580 'ncores_for_proc_gen': self.ncores_for_proc_gen} 581 try: 582 self._fks_multi_proc.add(fks_base.FKSMultiProcess(myprocdef,fks_options)) 583 except AttributeError: 584 self._fks_multi_proc = fks_base.FKSMultiProcess(myprocdef,fks_options)
585 586
587 - def do_output(self, line):
588 """Main commands: Initialize a new Template or reinitialize one""" 589 590 args = self.split_arg(line) 591 # Check Argument validity 592 self.check_output(args) 593 594 noclean = '-noclean' in args 595 force = '-f' in args 596 nojpeg = '-nojpeg' in args 597 main_file_name = "" 598 try: 599 main_file_name = args[args.index('-name') + 1] 600 except Exception: 601 pass 602 603 # For NLO, the group_subprocesses is automatically set to false 604 group_processes = False 605 # initialize the writer 606 if self._export_format in ['NLO']: 607 self._curr_exporter = export_v4.ExportV4Factory(self, noclean, 608 output_type='amcatnlo',group_subprocesses=group_processes) 609 610 self._curr_exporter.pass_information_from_cmd(self) 611 612 # check if a dir with the same name already exists 613 if not force and not noclean and os.path.isdir(self._export_dir)\ 614 and self._export_format in ['NLO']: 615 # Don't ask if user already specified force or noclean 616 logger.info('INFO: directory %s already exists.' % self._export_dir) 617 logger.info('If you continue this directory will be deleted and replaced.') 618 answer = self.ask('Do you want to continue?', 'y', ['y','n'], 619 timeout=self.options['timeout']) 620 if answer != 'y': 621 raise self.InvalidCmd('Stopped by user request') 622 623 # if one gets here either used -f or answered yes to the question about 624 # removing the dir 625 if os.path.exists(self._export_dir): 626 shutil.rmtree(self._export_dir) 627 628 # Make a Template Copy 629 if self._export_format in ['NLO']: 630 self._curr_exporter.copy_fkstemplate() 631 632 # Reset _done_export, since we have new directory 633 self._done_export = False 634 635 # Perform export and finalize right away 636 self.export(nojpeg, main_file_name, group_processes=group_processes) 637 638 # Pass potential new information generated during the export. 639 self._curr_exporter.pass_information_from_cmd(self) 640 641 # Automatically run finalize 642 self.finalize(nojpeg) 643 644 # Generate the virtuals if from OLP 645 if self.options['OLP']!='MadLoop': 646 self._curr_exporter.generate_virtuals_from_OLP( 647 self.born_processes_for_olp,self._export_dir,self.options['OLP']) 648 649 # Remember that we have done export 650 self._done_export = (self._export_dir, self._export_format) 651 652 # Reset _export_dir, so we don't overwrite by mistake later 653 self._export_dir = None
654 655 # Export a matrix element
656 - def export(self, nojpeg = False, main_file_name = "", group_processes=False):
657 """Export a generated amplitude to file""" 658 659 self._curr_helas_model = helas_call_writers.FortranUFOHelasCallWriter(self._curr_model) 660 def generate_matrix_elements(self, group=False): 661 """Helper function to generate the matrix elements before 662 exporting""" 663 664 # Sort amplitudes according to number of diagrams, 665 # to get most efficient multichannel output 666 self._curr_amps.sort(lambda a1, a2: a2.get_number_of_diagrams() - \ 667 a1.get_number_of_diagrams()) 668 669 cpu_time1 = time.time() 670 ndiags = 0 671 if not self._curr_matrix_elements.get_matrix_elements(): 672 if group: 673 raise MadGraph5Error, "Cannot group subprocesses when "+\ 674 "exporting to NLO" 675 else: 676 self._curr_matrix_elements = \ 677 fks_helas.FKSHelasMultiProcess(\ 678 self._fks_multi_proc, 679 loop_optimized= self.options['loop_optimized_output']) 680 681 if not self.options['low_mem_multicore_nlo_generation']: 682 # generate the code the old way 683 ndiags = sum([len(me.get('diagrams')) for \ 684 me in self._curr_matrix_elements.\ 685 get_matrix_elements()]) 686 # assign a unique id number to all process and 687 # generate a list of possible PDF combinations 688 uid = 0 689 initial_states=[] 690 for me in self._curr_matrix_elements.get_matrix_elements(): 691 uid += 1 # update the identification number 692 me.get('processes')[0].set('uid', uid) 693 try: 694 initial_states.append(sorted(list(set((p.get_initial_pdg(1),p.get_initial_pdg(2)) for \ 695 p in me.born_me.get('processes'))))) 696 except IndexError: 697 initial_states.append(sorted(list(set((p.get_initial_pdg(1)) for \ 698 p in me.born_me.get('processes'))))) 699 700 for fksreal in me.real_processes: 701 # Pick out all initial state particles for the two beams 702 try: 703 initial_states.append(sorted(list(set((p.get_initial_pdg(1),p.get_initial_pdg(2)) for \ 704 p in fksreal.matrix_element.get('processes'))))) 705 except IndexError: 706 initial_states.append(sorted(list(set((p.get_initial_pdg(1)) for \ 707 p in fksreal.matrix_element.get('processes'))))) 708 709 710 # remove doubles from the list 711 checked = [] 712 for e in initial_states: 713 if e not in checked: 714 checked.append(e) 715 initial_states=checked 716 717 self._curr_matrix_elements.set('initial_states',initial_states) 718 719 else: 720 #new NLO generation 721 if self._curr_matrix_elements['has_loops']: 722 self._curr_exporter.opt['mp'] = True 723 self._curr_exporter.model = self._curr_model 724 ndiags = 0 725 726 cpu_time2 = time.time() 727 return ndiags, cpu_time2 - cpu_time1
728 729 # Start of the actual routine 730 731 ndiags, cpu_time = generate_matrix_elements(self, group=group_processes) 732 calls = 0 733 734 path = self._export_dir 735 736 if self._export_format in ['NLO']: 737 path = os.path.join(path, 'SubProcesses') 738 739 #_curr_matrix_element is a FKSHelasMultiProcess Object 740 self._fks_directories = [] 741 proc_charac = self._curr_exporter.proc_characteristic 742 for charac in ['has_isr', 'has_fsr', 'has_loops']: 743 proc_charac[charac] = self._curr_matrix_elements[charac] 744 745 # prepare for the generation 746 # glob_directories_map is for the new NLO generation 747 global glob_directories_map 748 glob_directories_map = [] 749 750 # Save processes instances generated 751 self.born_processes_for_olp = [] 752 self.born_processes = [] 753 for ime, me in \ 754 enumerate(self._curr_matrix_elements.get('matrix_elements')): 755 if not self.options['low_mem_multicore_nlo_generation']: 756 #me is a FKSHelasProcessFromReals 757 calls = calls + \ 758 self._curr_exporter.generate_directories_fks(me, 759 self._curr_helas_model, 760 ime, len(self._curr_matrix_elements.get('matrix_elements')), 761 path,self.options['OLP']) 762 self._fks_directories.extend(self._curr_exporter.fksdirs) 763 self.born_processes_for_olp.append(me.born_me.get('processes')[0]) 764 self.born_processes.append(me.born_me.get('processes')) 765 else: 766 glob_directories_map.append(\ 767 [self._curr_exporter, me, self._curr_helas_model, 768 ime, len(self._curr_matrix_elements.get('matrix_elements')), 769 path, self.options['OLP']]) 770 771 if self.options['low_mem_multicore_nlo_generation']: 772 # start the pool instance with a signal instance to catch ctr+c 773 logger.info('Writing directories...') 774 original_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN) 775 if self.ncores_for_proc_gen < 0: # use all cores 776 pool = multiprocessing.Pool(maxtasksperchild=1) 777 else: 778 pool = multiprocessing.Pool(processes=self.ncores_for_proc_gen,maxtasksperchild=1) 779 signal.signal(signal.SIGINT, original_sigint_handler) 780 try: 781 # the very large timeout passed to get is to be able to catch 782 # KeyboardInterrupts 783 diroutputmap = pool.map_async(generate_directories_fks_async, 784 range(len(glob_directories_map))).get(9999999) 785 except KeyboardInterrupt: 786 pool.terminate() 787 raise KeyboardInterrupt 788 789 pool.close() 790 pool.join() 791 792 #clean up tmp files containing final matrix elements 793 for mefile in self._curr_matrix_elements.get('matrix_elements'): 794 os.remove(mefile) 795 796 for charac in ['nexternal', 'ninitial', 'splitting_types']: 797 proc_charac[charac] = self._curr_exporter.proc_characteristic[charac] 798 # ninitial and nexternal 799 proc_charac['nexternal'] = max([diroutput[3]['nexternal'] for diroutput in diroutputmap]) 800 ninitial_set = set([diroutput[3]['ninitial'] for diroutput in diroutputmap]) 801 if len(ninitial_set) != 1: 802 raise MadGraph5Error, ("Invalid ninitial values: %s" % ' ,'.join(list(ninitial_set))) 803 proc_charac['ninitial'] = list(ninitial_set)[0] 804 805 self.born_processes = [] 806 self.born_processes_for_olp = [] 807 max_loop_vertex_ranks = [] 808 809 # transform proc_charac['splitting_types'] into a set 810 splitting_types = set(proc_charac['splitting_types']) 811 for diroutput in diroutputmap: 812 splitting_types = splitting_types.union(set(diroutput[3]['splitting_types'])) 813 calls = calls + diroutput[0] 814 self._fks_directories.extend(diroutput[1]) 815 max_loop_vertex_ranks.append(diroutput[2]) 816 self.born_processes.extend(diroutput[4]) 817 self.born_processes_for_olp.append(diroutput[4][0]) 818 819 # transform proc_charac['splitting_types'] back to a list 820 proc_charac['splitting_types'] = list(splitting_types) 821 822 else: 823 max_loop_vertex_ranks = [me.get_max_loop_vertex_rank() for \ 824 me in self._curr_matrix_elements.get_virt_matrix_elements()] 825 826 card_path = os.path.join(path, os.path.pardir, 'SubProcesses', \ 827 'procdef_mg5.dat') 828 829 if self.options['loop_optimized_output'] and \ 830 len(max_loop_vertex_ranks) > 0: 831 self._curr_exporter.write_coef_specs_file(max_loop_vertex_ranks) 832 if self._generate_info: 833 self._curr_exporter.write_procdef_mg5(card_path, # 834 self._curr_model['name'], 835 self._generate_info) 836 try: 837 cmd.Cmd.onecmd(self, 'history .') 838 except Exception: 839 logger.debug('fail to run command \"history cmd\"') 840 pass 841 subproc_path = os.path.join(path, os.path.pardir, 'SubProcesses', \ 842 'initial_states_map.dat') 843 self._curr_exporter.write_init_map(subproc_path, 844 self._curr_matrix_elements.get('initial_states')) 845 846 cpu_time1 = time.time()
847 848
849 - def do_launch(self, line):
850 """Main commands: Ask for editing the parameters and then execute the code (NLO or aMC@(N)LO) 851 """ 852 old_cwd = os.getcwd() 853 argss = self.split_arg(line) 854 # check argument validity and normalise argument 855 (options, argss) = _launch_parser.parse_args(argss) 856 options = options.__dict__ 857 self.check_launch(argss, options) 858 if not os.path.isdir(os.path.join(os.getcwd(), argss[0], 'Events')): 859 self.do_switch('ML5') 860 return mg_interface.MadGraphCmd.do_launch(self,line) 861 # if self.options['automatic_html_opening']: 862 # misc.open_file(os.path.join(os.getcwd(), argss[0], 'crossx.html')) 863 # self.options['automatic_html_opening'] = False 864 865 if options['interactive']: 866 if isinstance(self, extended_cmd.CmdShell): 867 ME = run_interface.aMCatNLOCmdShell(me_dir=argss[0], options=self.options) 868 else: 869 ME = run_interface.aMCatNLOCmd(me_dir=argss[0],options=self.options) 870 ME.pass_in_web_mode() 871 # transfer interactive configuration 872 config_line = [l for l in self.history if l.strip().startswith('set')] 873 for line in config_line: 874 ME.exec_cmd(line) 875 stop = self.define_child_cmd_interface(ME) 876 return stop 877 878 ext_program = launch_ext.aMCatNLOLauncher(argss[0], self, run_mode=argss[1], 879 shell = isinstance(self, extended_cmd.CmdShell), 880 **options) 881 ext_program.run()
882 883 884
885 -class aMCatNLOInterfaceWeb(mg_interface.CheckValidForCmdWeb, aMCatNLOInterface):
886 pass
887 888 _launch_usage = "launch [DIRPATH] [MODE] [options]\n" + \ 889 "-- execute the aMC@NLO output present in DIRPATH\n" + \ 890 " By default DIRPATH is the latest created directory\n" + \ 891 " MODE can be either LO, NLO, aMC@NLO or aMC@LO (if omitted, it is asked in a separate question)\n" + \ 892 " If mode is set to LO/NLO, no event generation will be performed, but only the \n" + \ 893 " computation of the total cross-section and the filling of parton-level histograms \n" + \ 894 " specified in the DIRPATH/SubProcesses/madfks_plot.f file.\n" + \ 895 " If mode is set to aMC@LO/aMC@NLO, after the cross-section computation, a .lhe \n" + \ 896 " event file is generated which will be showered with the MonteCarlo specified \n" + \ 897 " in the run_card.dat\n" 898 899 _launch_parser = misc.OptionParser(usage=_launch_usage) 900 _launch_parser.add_option("-f", "--force", default=False, action='store_true', 901 help="Use the card present in the directory for the launch, without editing them") 902 _launch_parser.add_option("-c", "--cluster", default=False, action='store_true', 903 help="Submit the jobs on the cluster") 904 _launch_parser.add_option("-i", "--interactive", default=False, action='store_true', 905 help="Use interactive consol") 906 _launch_parser.add_option("-m", "--multicore", default=False, action='store_true', 907 help="Submit the jobs on multicore mode") 908 _launch_parser.add_option("-x", "--nocompile", default=False, action='store_true', 909 help="Skip compilation. Ignored if no executable is found") 910 _launch_parser.add_option("-r", "--reweightonly", default=False, action='store_true', 911 help="Skip integration and event generation, just run reweight on the" + \ 912 " latest generated event files (see list in SubProcesses/nevents_unweighted)") 913 _launch_parser.add_option("-p", "--parton", default=False, action='store_true', 914 help="Stop the run after the parton level file generation (you need " + \ 915 "to shower the file in order to get physical results)") 916 _launch_parser.add_option("-o", "--only_generation", default=False, action='store_true', 917 help="Skip grid set up, just generate events starting from " + \ 918 "the last available results") 919 # the last option is different from the corresponding in amcatnlo_run_interface as it stores the 920 # 'name' entry of the options, not the run_name one 921 _launch_parser.add_option("-n", "--name", default=False, dest='name', 922 help="Provide a name to the run") 923 _launch_parser.add_option("-a", "--appl_start_grid", default=False, dest='appl_start_grid', 924 help="For use with APPLgrid only: start from existing grids") 925 _launch_parser.add_option("-R", "--reweight", default=False, action='store_true', 926 help="Run the reweight module (reweighting by different model parameter") 927 _launch_parser.add_option("-M", "--madspin", default=False, action='store_true', 928 help="Run the madspin package") 929