1
2
3
4
5
6
7
8
9
10
11
12
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
45 logger = logging.getLogger('cmdprint')
46
47
48 pjoin = os.path.join
49
50 -class CheckLoop(mg_interface.CheckValidForCmd):
51
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
72
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
97
98
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):
124
126
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
139
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
147 """ An additional layer between MadGraphInterface and LoopInterface as well
148 as aMCatNLO interface, to put the common feature of these two here."""
149
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
159
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
175 if len(leg['ids'])>1:
176 score += 1
177 else:
178 score += pdg_difficulty(leg.get('id'))
179
180
181 if proc['NLO_mode']=='virt':
182 score = score - 6
183
184 if proc['NLO_mode']=='real':
185 score = score - 6
186
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
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
216
217 difficulty_threshold = 100
218
219 if not proc:
220 raise self.InvalidCmd("Empty or wrong format process, please try again.")
221
222
223
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
229
230
231
232
233
234
235
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
286
287 if isinstance(coupling_type,str):
288 coupling_type = [coupling_type,]
289
290 if coupling_type!= ['QCD'] and loop_type not in ['virtual','noborn']:
291 c = ' '.join(coupling_type)
292 raise self.InvalidCmd, 'MG5aMC can only handle QCD at NLO accuracy.\n We can however compute loop with [virt=%s].\n We can also compute cross-section for loop-induced processes with [noborn=%s]' % (c,c)
293
294
295 if not isinstance(self._curr_model,loop_base_objects.LoopModel) or \
296 self._curr_model['perturbation_couplings']==[] or \
297 any((coupl not in self._curr_model['perturbation_couplings']) \
298 for coupl in coupling_type):
299 if loop_type.startswith('real') or loop_type == 'LOonly':
300 if loop_type == 'real':
301 logger.info(\
302 "Beware that real corrections are generated from a tree-level model.")
303 if loop_type == 'real_init' and \
304 self._curr_model.get('name').split('-')[0]!='sm':
305 logger.info(\
306 "You are entering aMC@NLO with a model which does not "+\
307 " support loop corrections.")
308 else:
309 logger.info(\
310 "The current model %s does not allow to generate"%self._curr_model.get('name')+
311 " loop corrections of type %s."%str(coupling_type))
312 model_path = self._curr_model.get('modelpath')
313 model_name = self._curr_model.get('name')
314 if model_name.split('-')[0]=='loop_sm':
315 model_name = model_name[5:]
316 if model_name.split('-')[0]=='sm':
317
318 if not self.options['gauge']=='Feynman' and 'QED' in coupling_type:
319 logger.info('Switch to Feynman gauge because '+\
320 'model loop_qcd_qed_sm is restricted only to Feynman gauge.')
321 self._curr_model = None
322 mg_interface.MadGraphCmd.do_set(self,'gauge Feynman')
323 if coupling_type == ['QCD',]:
324 add_on = ''
325 elif coupling_type in [['QED'],['QCD','QED']]:
326 add_on = 'qcd_qed_'
327 else:
328 raise MadGraph5Error(
329 "The pertubation coupling cannot be '%s'"\
330 %str(coupling_type)+" in SM loop processes")
331
332 logger.info("MG5_aMC now loads 'loop_%s%s'."%(add_on,model_name))
333
334
335 self.history.move_to_last('generate')
336 last_command = self.history[-1]
337 self.exec_cmd(" import model loop_%s%s" % (add_on,model_name), precmd=True)
338 self.history.append(last_command)
339 elif stop:
340 raise self.InvalidCmd(
341 "The model %s cannot handle loop processes"%model_name)
342
343 if loop_type and not loop_type.startswith('real') and \
344 not self.options['gauge']=='Feynman' and \
345 not self._curr_model['perturbation_couplings'] in [[],['QCD']]:
346 if 1 in self._curr_model.get('gauge'):
347 logger.info("Setting gauge to Feynman in order to process all"+\
348 " possible loop computations available in the model.")
349 mg_interface.MadGraphCmd.do_set(self,'gauge Feynman')
350 else:
351 logger.warning("You will only be able to do tree level and QCD"+\
352 " corrections with this model because it does not support Feynman gauge.")
353
354 -class LoopInterface(CheckLoop, CompleteLoop, HelpLoop, CommonLoopInterface):
355
356 supported_ML_format = ['standalone', 'standalone_rw', 'matchbox']
357
358 - def __init__(self, mgme_dir = '', *completekey, **stdin):
359 """ Special init tasks for the Loop Interface """
360
361 mg_interface.MadGraphCmd.__init__(self, mgme_dir = '', *completekey, **stdin)
362 self.setup()
363
365 """ Special tasks when switching to this interface """
366
367
368
369
370
371
372 self.history.clean(remove_bef_last='import',
373 to_keep=['set','load','import', 'define'])
374
375 self._done_export=False
376 self._curr_amps = diagram_generation.AmplitudeList()
377 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
378 self._v4_export_formats = []
379 self._export_formats = [ 'matrix', 'standalone' ]
380 self._nlo_modes_for_completion = ['virt']
381 self.validate_model()
382
383
384
385 self._cuttools_dir=str(os.path.join(self._mgme_dir,'vendor','CutTools'))
386 if not os.path.isdir(os.path.join(self._cuttools_dir, 'src','cts')):
387 logger.warning(('Warning: Directory %s is not a valid CutTools directory.'+\
388 'Using default CutTools instead.') % \
389 self._cuttools_dir)
390 self._cuttools_dir=str(os.path.join(self._mgme_dir,'vendor','CutTools'))
391
392 self._iregi_dir=str(os.path.join(self._mgme_dir,'vendor','IREGI','src'))
393 if not os.path.isdir(self._iregi_dir):
394 logger.warning(('Warning: Directory %s is not a valid IREGI directory.'+\
395 'Using default IREGI instead.')%\
396 self._iregi_dir)
397 self._iregi_dir=str(os.path.join(self._mgme_dir,'vendor','IREGI','src'))
398
414
416 """Main commands:Initialize a new Template or reinitialize one"""
417
418 args = self.split_arg(line)
419
420 self.check_output(args)
421
422 noclean = '-noclean' in args
423 force = '-f' in args
424 nojpeg = '-nojpeg' in args
425 main_file_name = ""
426 try:
427 main_file_name = args[args.index('-name') + 1]
428 except Exception:
429 pass
430
431
432
433 aloha_original_quad_mode = aloha.mp_precision
434 aloha.mp_precision = True
435
436 if self._export_format not in self.supported_ML_format:
437 raise self.InvalidCmd('ML5 only support "%s" as export format.' % \
438 ''.join(self.supported_ML_format))
439
440 if not os.path.isdir(self._export_dir) and self._export_format in ['matrix']:
441 raise self.InvalidCmd('Specified export directory %s does not exist.'\
442 %str(self._export_dir))
443
444 if not force and not noclean and os.path.isdir(self._export_dir)\
445 and self._export_format.startswith('standalone'):
446
447 logger.info('INFO: directory %s already exists.' % self._export_dir)
448 logger.info('If you continue this directory will be cleaned')
449 answer = self.ask('Do you want to continue?', 'y', ['y','n'])
450 if answer != 'y':
451 raise self.InvalidCmd('Stopped by user request')
452 else:
453 try:
454 shutil.rmtree(self._export_dir)
455 except OSError:
456 raise self.InvalidCmd('Could not remove directory %s.'\
457 %str(self._export_dir))
458
459 if self._export_format.startswith('standalone'):
460 output_type = 'madloop'
461 elif self._export_format == 'matchbox':
462 output_type = 'madloop_matchbox'
463
464 self._curr_exporter = export_v4.ExportV4Factory(self, \
465 noclean, output_type=output_type, group_subprocesses=False)
466
467 if self._export_format in ['standalone', 'matchbox']:
468 self._curr_exporter.copy_v4template(modelname=self._curr_model.get('name'))
469
470 if self._export_format == "standalone_rw":
471 self._export_format = "standalone"
472 self._curr_exporter.copy_v4template(modelname=self._curr_model.get('name'))
473 self._export_format = "standalone_rw"
474
475
476 self._done_export = False
477
478
479 self.ML5export(nojpeg, main_file_name)
480
481
482 self.ML5finalize(nojpeg)
483
484
485 self._done_export = (self._export_dir, self._export_format)
486
487
488 self._export_dir = None
489
490
491 aloha.mp_precision = aloha_original_quad_mode
492
493
494
495 - def ML5export(self, nojpeg = False, main_file_name = ""):
523
524
525 ndiags, cpu_time = generate_matrix_elements(self)
526
527 calls = 0
528
529 path = self._export_dir
530 if self._export_format in self.supported_ML_format:
531 path = pjoin(path, 'SubProcesses')
532
533 cpu_time1 = time.time()
534
535
536 matrix_elements = \
537 self._curr_matrix_elements.get_matrix_elements()
538
539
540 if self._export_format in self.supported_ML_format:
541 for me in matrix_elements:
542 calls = calls + \
543 self._curr_exporter.generate_subprocess_directory_v4(\
544 me, self._curr_fortran_model)
545
546
547
548
549 if self.options['loop_optimized_output'] and len(matrix_elements)>1:
550 max_lwfspins = [m.get_max_loop_particle_spin() for m in \
551 matrix_elements]
552 max_loop_vert_ranks = [me.get_max_loop_vertex_rank() for me in \
553 matrix_elements]
554 if len(set(max_lwfspins))>1 or len(set(max_loop_vert_ranks))>1:
555 self._curr_exporter.fix_coef_specs(max(max_lwfspins),\
556 max(max_loop_vert_ranks))
557
558
559 if self._export_format == 'matrix':
560 for me in matrix_elements:
561 filename = pjoin(path, 'matrix_' + \
562 me.get('processes')[0].shell_string() + ".f")
563 if os.path.isfile(filename):
564 logger.warning("Overwriting existing file %s" % filename)
565 else:
566 logger.info("Creating new file %s" % filename)
567 calls = calls + self._curr_exporter.write_matrix_element_v4(\
568 writers.FortranWriter(filename),\
569 me, self._curr_fortran_model)
570
571 cpu_time2 = time.time() - cpu_time1
572
573 logger.info(("Generated helas calls for %d subprocesses " + \
574 "(%d diagrams) in %0.3f s") % \
575 (len(matrix_elements),
576 ndiags, cpu_time))
577
578 if calls:
579 if "cpu_time2" in locals():
580 logger.info("Wrote files for %d OPP calls in %0.3f s" % \
581 (calls, cpu_time2))
582 else:
583 logger.info("Wrote files for %d OPP calls" % \
584 (calls))
585
586
587
588
589 self._curr_amps = diagram_generation.AmplitudeList(\
590 [me.get('base_amplitude') for me in \
591 matrix_elements])
592
594 """Copy necessary sources and output the ps representation of
595 the diagrams, if needed"""
596
597 if self._export_format in self.supported_ML_format:
598 logger.info('Export UFO model to MG4 format')
599
600
601
602 wanted_lorentz = self._curr_matrix_elements.get_used_lorentz()
603 wanted_couplings = self._curr_matrix_elements.get_used_couplings()
604
605
606 if hasattr(self, 'previous_lorentz'):
607 wanted_lorentz = list(set(self.previous_lorentz + wanted_lorentz))
608 wanted_couplings = list(set(self.previous_couplings + wanted_couplings))
609 del self.previous_lorentz
610 del self.previous_couplings
611
612 self._curr_exporter.convert_model_to_mg4(self._curr_model,
613 wanted_lorentz,
614 wanted_couplings)
615
616 compiler = {'fortran': self.options['fortran_compiler'],
617 'f2py': self.options['f2py_compiler'],
618 'cpp': self.options['cpp_compiler']}
619
620 if self._export_format in self.supported_ML_format:
621 self._curr_exporter.finalize_v4_directory( \
622 self._curr_matrix_elements,
623 self.history,
624 not nojpeg,
625 online,
626 compiler)
627
628 if self._export_format in self.supported_ML_format:
629 logger.info('Output to directory ' + self._export_dir + ' done.')
630
632 """Main commands: Check that the type of launch is fine before proceeding with the
633 mother function. """
634
635 args = self.split_arg(line)
636
637 (options, args) = mg_interface._launch_parser.parse_args(args)
638
639 self.check_launch(args, options)
640
641 if not args[0].startswith('standalone'):
642 raise self.InvalidCmd('ML5 can only launch standalone runs.')
643
644 start_cwd = os.getcwd()
645 options = options.__dict__
646
647
648 ext_program = launch_ext.MadLoopLauncher(self, args[1], \
649 options=self.options, **options)
650 ext_program.run()
651 os.chdir(start_cwd)
652
654 """Check a given process or set of processes"""
655
656 argss = self.split_arg(line, *args,**opt)
657
658 perturbation_couplings_pattern = \
659 re.compile("^(?P<proc>.+)\s*\[\s*((?P<option>\w+)\s*\=)?\s*(?P<pertOrders>(\w+\s*)*)\s*\]\s*(?P<rest>.*)$")
660 perturbation_couplings_re = perturbation_couplings_pattern.match(line)
661 perturbation_couplings=""
662 if perturbation_couplings_re:
663 perturbation_couplings = perturbation_couplings_re.group("pertOrders")
664 QED_found=re.search("QED",perturbation_couplings)
665 if QED_found:
666 self.validate_model(coupling_type='QED')
667 else:
668 self.validate_model()
669
670 param_card = self.check_check(argss)
671 reuse = argss[1]=="-reuse"
672 argss = argss[:1]+argss[2:]
673
674
675 if argss[0] in ['stability', 'profile']:
676 stab_statistics = int(argss[1])
677 argss = argss[:1]+argss[2:]
678
679 i=-1
680 while argss[i].startswith('--'):
681 i=i-1
682
683 proc = " ".join(argss[1:i+1])
684 myprocdef = self.extract_process(proc)
685 self.proc_validity(myprocdef,'ML5_check_cms' if argss[0]=='cms' else \
686 'ML5_check')
687
688 return mg_interface.MadGraphCmd.do_check(self, line, *args,**opt)
689
690 - def do_add(self, line, *args,**opt):
691 """Generate an amplitude for a given process and add to
692 existing amplitudes
693 """
694 args = self.split_arg(line)
695
696 self.check_add(args)
697 perturbation_couplings_pattern = \
698 re.compile("^(?P<proc>.+)\s*\[\s*((?P<option>\w+)\s*\=)?\s*(?P<pertOrders>(\w+\s*)*)\s*\]\s*(?P<rest>.*)$")
699 perturbation_couplings_re = perturbation_couplings_pattern.match(line)
700 perturbation_couplings=""
701 if perturbation_couplings_re:
702 perturbation_couplings = perturbation_couplings_re.group("pertOrders")
703 QED_found=re.search('QED',perturbation_couplings)
704 if QED_found:
705 self.validate_model(coupling_type='QED')
706 else:
707 self.validate_model()
708
709 loop_filter=None
710 if args[0] == 'process':
711
712
713 for arg in args:
714 if arg.startswith('--loop_filter='):
715 loop_filter = arg[14:]
716 if not isinstance(self, extended_cmd.CmdShell):
717 raise InvalidCmd, "loop_filter is not allowed in web mode"
718 args = [a for a in args if not a.startswith('--loop_filter=')]
719
720
721 line = ' '.join(args[1:])
722
723
724 if not self._generate_info:
725 self._generate_info = line
726
727
728 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
729
730
731 myprocdef = self.extract_process(line)
732
733 if myprocdef.has_multiparticle_label():
734
735 succes, failed = 0, 0
736 for base_proc in myprocdef:
737 try:
738 self.exec_cmd("add process %s" % base_proc.nice_string(prefix=False, print_weighted=True))
739 succes += 1
740 except Exception:
741 failed +=1
742 logger.info("%s/%s processes succeeded" % (succes, failed+succes))
743 if succes == 0:
744 raise
745 else:
746 return
747
748
749
750
751
752 all_ids = [amp.get('process').get('id') for amp in self._curr_amps]
753 if myprocdef.get('id') in all_ids:
754 myprocdef.set('id',max(all_ids)+1)
755
756 self.proc_validity(myprocdef,'ML5')
757
758 cpu_time1 = time.time()
759
760
761 multiprocessclass=None
762 if myprocdef['perturbation_couplings']!=[]:
763 multiprocessclass=loop_diagram_generation.LoopMultiProcess
764 else:
765 multiprocessclass=diagram_generation.MultiProcess
766
767 myproc = multiprocessclass(myprocdef, collect_mirror_procs = False,
768 ignore_six_quark_processes = False,
769 loop_filter = loop_filter)
770
771 for amp in myproc.get('amplitudes'):
772 if amp not in self._curr_amps:
773 self._curr_amps.append(amp)
774 else:
775 warning = "Warning: Already in processes:\n%s" % \
776 amp.nice_string_processes()
777 logger.warning(warning)
778
779
780 self._done_export = False
781
782 cpu_time2 = time.time()
783
784 ndiags = sum([len(amp.get('loop_diagrams')) for \
785 amp in myproc.get('amplitudes')])
786 logger.info("Process generated in %0.3f s" % \
787 (cpu_time2 - cpu_time1))
788
791