1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 """Methods and classes to export matrix elements to v4 format."""
16
17 import copy
18 from cStringIO import StringIO
19 from distutils import dir_util
20 import itertools
21 import fractions
22 import glob
23 import logging
24 import math
25 import os
26 import re
27 import shutil
28 import subprocess
29 import sys
30
31
32 import aloha
33
34 import madgraph.core.base_objects as base_objects
35 import madgraph.core.color_algebra as color
36 import madgraph.core.helas_objects as helas_objects
37 import madgraph.iolibs.drawing_eps as draw
38 import madgraph.iolibs.files as files
39 import madgraph.iolibs.group_subprocs as group_subprocs
40 import madgraph.iolibs.file_writers as writers
41 import madgraph.iolibs.gen_infohtml as gen_infohtml
42 import madgraph.iolibs.template_files as template_files
43 import madgraph.iolibs.ufo_expression_parsers as parsers
44 import madgraph.iolibs.helas_call_writers as helas_call_writers
45 import madgraph.various.diagram_symmetry as diagram_symmetry
46 import madgraph.various.misc as misc
47 import madgraph.various.process_checks as process_checks
48 import aloha.create_aloha as create_aloha
49 import models.import_ufo as import_ufo
50 import models.write_param_card as param_writer
51 import models.check_param_card as check_param_card
52
53 from madgraph import MadGraph5Error, MG5DIR, ReadWrite
54 from madgraph.iolibs.files import cp, ln, mv
55
56 pjoin = os.path.join
57
58 _file_path = os.path.split(os.path.dirname(os.path.realpath(__file__)))[0] + '/'
59 logger = logging.getLogger('madgraph.export_v4')
60
61
62
63
65 """Class to take care of exporting a set of matrix elements to
66 Fortran (v4) format."""
67
68 - def __init__(self, mgme_dir = "", dir_path = "", opt=None):
69 """Initiate the ProcessExporterFortran with directory information"""
70 self.mgme_dir = mgme_dir
71 self.dir_path = dir_path
72 self.model = None
73
74 if opt:
75 self.opt = opt
76 else:
77 self.opt = {'clean': False, 'complex_mass':False,
78 'export_format':'madevent', 'mp': False}
79
80
81
82
84 """create the directory run_name as a copy of the MadEvent
85 Template, and clean the directory
86 """
87
88
89 if not os.path.isdir(self.dir_path):
90 assert self.mgme_dir, \
91 "No valid MG_ME path given for MG4 run directory creation."
92 logger.info('initialize a new directory: %s' % \
93 os.path.basename(self.dir_path))
94 shutil.copytree(pjoin(self.mgme_dir, 'Template/LO'),
95 self.dir_path, True)
96
97 dir_util.copy_tree(pjoin(self.mgme_dir, 'Template/Common'),
98 self.dir_path)
99
100 for card in ['run_card', 'plot_card']:
101 try:
102 shutil.copy(pjoin(self.dir_path, 'Cards',
103 card + '.dat'),
104 pjoin(self.dir_path, 'Cards',
105 card + '_default.dat'))
106 except IOError:
107 logger.warning("Failed to copy " + card + ".dat to default")
108 elif os.getcwd() == os.path.realpath(self.dir_path):
109 logger.info('working in local directory: %s' % \
110 os.path.realpath(self.dir_path))
111
112 dir_util.copy_tree(pjoin(self.mgme_dir, 'Template/LO'),
113 self.dir_path)
114
115
116
117
118
119
120
121
122 dir_util.copy_tree(pjoin(self.mgme_dir, 'Template/Common'),
123 self.dir_path)
124
125 for card in ['run_card', 'plot_card']:
126 try:
127 shutil.copy(pjoin(self.dir_path, 'Cards',
128 card + '.dat'),
129 pjoin(self.dir_path, 'Cards',
130 card + '_default.dat'))
131 except IOError:
132 logger.warning("Failed to copy " + card + ".dat to default")
133 elif not os.path.isfile(pjoin(self.dir_path, 'TemplateVersion.txt')):
134 assert self.mgme_dir, \
135 "No valid MG_ME path given for MG4 run directory creation."
136 try:
137 shutil.copy(pjoin(self.mgme_dir, 'MGMEVersion.txt'), self.dir_path)
138 except IOError:
139 MG5_version = misc.get_pkg_info()
140 open(pjoin(self.dir_path, 'MGMEVersion.txt'), 'w').write( \
141 "5." + MG5_version['version'])
142
143
144 if self.opt['clean']:
145 logger.info('remove old information in %s' % \
146 os.path.basename(self.dir_path))
147 if os.environ.has_key('MADGRAPH_BASE'):
148 misc.call([pjoin('bin', 'internal', 'clean_template'),
149 '--web'], cwd=self.dir_path)
150 else:
151 try:
152 misc.call([pjoin('bin', 'internal', 'clean_template')], \
153 cwd=self.dir_path)
154 except Exception, why:
155 raise MadGraph5Error('Failed to clean correctly %s: \n %s' \
156 % (os.path.basename(self.dir_path),why))
157
158
159 MG_version = misc.get_pkg_info()
160 open(pjoin(self.dir_path, 'SubProcesses', 'MGVersion.txt'), 'w').write(
161 MG_version['version'])
162
163
164
165 filename = pjoin(self.dir_path,'Source','makefile')
166 self.write_source_makefile(writers.FileWriter(filename))
167
168
169
170
172 """ write an equivalent of the MG4 proc_card in order that all the Madevent
173 Perl script of MadEvent4 are still working properly for pure MG5 run."""
174
175 proc_card_template = template_files.mg4_proc_card.mg4_template
176 process_template = template_files.mg4_proc_card.process_template
177 process_text = ''
178 coupling = ''
179 new_process_content = []
180
181
182
183
184 process_str = process_str.replace(' =', '=')
185 process_str = process_str.replace('= ', '=')
186 process_str = process_str.replace(',',' , ')
187
188 for info in process_str.split():
189 if '=' in info:
190 coupling += info + '\n'
191 else:
192 new_process_content.append(info)
193
194
195 process_str = ' '.join(new_process_content)
196
197
198 process_text += process_template.substitute({'process': process_str, \
199 'coupling': coupling})
200
201 text = proc_card_template.substitute({'process': process_text,
202 'model': modelname,
203 'multiparticle':''})
204 ff = open(file_pos, 'w')
205 ff.write(text)
206 ff.close()
207
208
209
210
211 - def finalize_v4_directory(self, matrix_elements, history = "", makejpg = False,
212 online = False, compiler='g77'):
213 """Function to finalize v4 directory, for inheritance.
214 """
215 pass
216
217
218
219
221 """Function to write a matrix.f file, for inheritance.
222 """
223 pass
224
225
226
227
228 - def write_maxparticles_file(self, writer, matrix_elements):
229 """Write the maxparticles.inc file for MadEvent"""
230
231 if isinstance(matrix_elements, helas_objects.HelasMultiProcess):
232 maxparticles = max([me.get_nexternal_ninitial()[0] for me in \
233 matrix_elements.get('matrix_elements')])
234 else:
235 maxparticles = max([me.get_nexternal_ninitial()[0] \
236 for me in matrix_elements])
237
238 lines = "integer max_particles\n"
239 lines += "parameter(max_particles=%d)" % maxparticles
240
241
242 writer.writelines(lines)
243
244 return True
245
246
247
248
249
251 """Configure the files/link of the process according to the model"""
252
253
254 for file in os.listdir(model_path):
255 if os.path.isfile(pjoin(model_path, file)):
256 shutil.copy2(pjoin(model_path, file), \
257 pjoin(self.dir_path, 'Source', 'MODEL'))
258
259
261 """Make the copy/symbolic links"""
262 model_path = self.dir_path + '/Source/MODEL/'
263 if os.path.exists(pjoin(model_path, 'ident_card.dat')):
264 mv(model_path + '/ident_card.dat', self.dir_path + '/Cards')
265 if os.path.exists(pjoin(model_path, 'particles.dat')):
266 ln(model_path + '/particles.dat', self.dir_path + '/SubProcesses')
267 ln(model_path + '/interactions.dat', self.dir_path + '/SubProcesses')
268 cp(model_path + '/param_card.dat', self.dir_path + '/Cards')
269 mv(model_path + '/param_card.dat', self.dir_path + '/Cards/param_card_default.dat')
270 ln(model_path + '/coupl.inc', self.dir_path + '/Source')
271 ln(model_path + '/coupl.inc', self.dir_path + '/SubProcesses')
272 self.make_source_links()
273
275 """ Create the links from the files in sources """
276 ln(self.dir_path + '/Source/run.inc', self.dir_path + '/SubProcesses', log=False)
277 ln(self.dir_path + '/Source/maxparticles.inc', self.dir_path + '/SubProcesses', log=False)
278 ln(self.dir_path + '/Source/run_config.inc', self.dir_path + '/SubProcesses', log=False)
279
280
281
282
284 """Configure the files/link of the process according to the model"""
285
286
287 for filename in os.listdir(helas_path):
288 filepos = pjoin(helas_path, filename)
289 if os.path.isfile(filepos):
290 if filepos.endswith('Makefile.template'):
291 cp(filepos, self.dir_path + '/Source/DHELAS/Makefile')
292 elif filepos.endswith('Makefile'):
293 pass
294 else:
295 cp(filepos, self.dir_path + '/Source/DHELAS')
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
316 """Routine to generate a subprocess directory (for inheritance)"""
317
318 pass
319
320
321
322
324 """Write the nexternal.inc file for MG4"""
325
326
327 path = pjoin(_file_path,'iolibs','template_files','madevent_makefile_source')
328 set_of_lib = '$(LIBRARIES) $(LIBDIR)libdhelas.$(libext) $(LIBDIR)libpdf.$(libext) $(LIBDIR)libmodel.$(libext) $(LIBDIR)libcernlib.$(libext)'
329 if self.opt['model'] == 'mssm' or self.opt['model'].startswith('mssm-'):
330 model_line='''$(LIBDIR)libmodel.$(libext): MODEL param_card.inc\n\tcd MODEL; make
331 MODEL/MG5_param.dat: ../Cards/param_card.dat\n\t../bin/madevent treatcards param
332 param_card.inc: MODEL/MG5_param.dat\n\t../bin/madevent treatcards param\n'''
333 else:
334 model_line='''$(LIBDIR)libmodel.$(libext): MODEL param_card.inc\n\tcd MODEL; make
335 param_card.inc: ../Cards/param_card.dat\n\t../bin/madevent treatcards param\n'''
336 text = open(path).read() % {'libraries': set_of_lib, 'model':model_line}
337 writer.write(text)
338
339 return True
340
341
342
343
345 """Write the nexternal_prod.inc file for madspin"""
346
347 replace_dict = {}
348
349 replace_dict['nexternal'] = nexternal
350 replace_dict['ninitial'] = ninitial
351
352 file = """ \
353 integer nexternal_prod
354 parameter (nexternal_prod=%(nexternal)d)
355 integer nincoming_prod
356 parameter (nincoming_prod=%(ninitial)d)""" % replace_dict
357
358
359 writer.writelines(file)
360
361 return True
362
363
364
365
367 """Write the helamp.inc file for madspin"""
368
369 replace_dict = {}
370
371 replace_dict['ncomb'] = ncomb
372
373 file = """ \
374 integer ncomb1
375 parameter (ncomb1=%(ncomb)d)
376 double precision helamp(ncomb1)
377 common /to_helamp/helamp """ % replace_dict
378
379
380 writer.writelines(file)
381
382 return True
383
384
385
386
387
389 """Write the nexternal.inc file for MG4"""
390
391 replace_dict = {}
392
393 replace_dict['nexternal'] = nexternal
394 replace_dict['ninitial'] = ninitial
395
396 file = """ \
397 integer nexternal
398 parameter (nexternal=%(nexternal)d)
399 integer nincoming
400 parameter (nincoming=%(ninitial)d)""" % replace_dict
401
402
403 writer.writelines(file)
404
405 return True
406
407
408
409
411 """Write the pmass.inc file for MG4"""
412
413 model = matrix_element.get('processes')[0].get('model')
414
415 lines = []
416 for wf in matrix_element.get_external_wavefunctions():
417 mass = model.get('particle_dict')[wf.get('pdg_code')].get('mass')
418 if mass.lower() != "zero":
419 mass = "abs(%s)" % mass
420
421 lines.append("pmass(%d)=%s" % \
422 (wf.get('number_external'), mass))
423
424
425 writer.writelines(lines)
426
427 return True
428
429
430
431
433 """Write the ngraphs.inc file for MG4. Needs input from
434 write_configs_file."""
435
436 file = " integer n_max_cg\n"
437 file = file + "parameter (n_max_cg=%d)" % nconfigs
438
439
440 writer.writelines(file)
441
442 return True
443
444
445
446
454
455
456
457
459 """Write the leshouche.inc file for MG4"""
460
461
462 (nexternal, ninitial) = matrix_element.get_nexternal_ninitial()
463
464 lines = []
465 for iproc, proc in enumerate(matrix_element.get('processes')):
466 legs = proc.get_legs_with_decays()
467 lines.append("DATA (IDUP(i,%d,%d),i=1,%d)/%s/" % \
468 (iproc + 1, numproc+1, nexternal,
469 ",".join([str(l.get('id')) for l in legs])))
470 if iproc == 0 and numproc == 0:
471 for i in [1, 2]:
472 lines.append("DATA (MOTHUP(%d,i),i=1,%2r)/%s/" % \
473 (i, nexternal,
474 ",".join([ "%3r" % 0 ] * ninitial + \
475 [ "%3r" % i ] * (nexternal - ninitial))))
476
477
478
479 if iproc == 0:
480
481 if not matrix_element.get('color_basis'):
482 for i in [1, 2]:
483 lines.append("DATA (ICOLUP(%d,i,1,%d),i=1,%2r)/%s/" % \
484 (i, numproc+1,nexternal,
485 ",".join([ "%3r" % 0 ] * nexternal)))
486
487 else:
488
489 repr_dict = {}
490 for l in legs:
491 repr_dict[l.get('number')] = \
492 proc.get('model').get_particle(l.get('id')).get_color()\
493 * (-1)**(1+l.get('state'))
494
495 color_flow_list = \
496 matrix_element.get('color_basis').color_flow_decomposition(repr_dict,
497 ninitial)
498
499 for cf_i, color_flow_dict in enumerate(color_flow_list):
500 for i in [0, 1]:
501 lines.append("DATA (ICOLUP(%d,i,%d,%d),i=1,%2r)/%s/" % \
502 (i + 1, cf_i + 1, numproc+1, nexternal,
503 ",".join(["%3r" % color_flow_dict[l.get('number')][i] \
504 for l in legs])))
505
506 return lines
507
508
509
510
511
512
513
516 """Write the maxamps.inc file for MG4."""
517
518 file = " integer maxamps, maxflow, maxproc, maxsproc\n"
519 file = file + "parameter (maxamps=%d, maxflow=%d)\n" % \
520 (maxamps, maxflows)
521 file = file + "parameter (maxproc=%d, maxsproc=%d)" % \
522 (maxproc, maxsproc)
523
524
525 writer.writelines(file)
526
527 return True
528
529
530
531
533 """Write the props.inc file for MadEvent. Needs input from
534 write_configs_file."""
535
536 lines = []
537
538 particle_dict = matrix_element.get('processes')[0].get('model').\
539 get('particle_dict')
540
541 for iconf, configs in enumerate(s_and_t_channels):
542 for vertex in configs[0] + configs[1][:-1]:
543 leg = vertex.get('legs')[-1]
544 if leg.get('id') not in particle_dict:
545
546 mass = 'zero'
547 width = 'zero'
548 pow_part = 0
549 else:
550 particle = particle_dict[leg.get('id')]
551
552 if particle.get('mass').lower() == 'zero':
553 mass = particle.get('mass')
554 else:
555 mass = "abs(%s)" % particle.get('mass')
556
557 if particle.get('width').lower() == 'zero':
558 width = particle.get('width')
559 else:
560 width = "abs(%s)" % particle.get('width')
561
562 pow_part = 1 + int(particle.is_boson())
563
564 lines.append("prmass(%d,%d) = %s" % \
565 (leg.get('number'), iconf + 1, mass))
566 lines.append("prwidth(%d,%d) = %s" % \
567 (leg.get('number'), iconf + 1, width))
568 lines.append("pow(%d,%d) = %d" % \
569 (leg.get('number'), iconf + 1, pow_part))
570
571
572 writer.writelines(lines)
573
574 return True
575
576
577
578
579
582 """ Create a full valid MG4 model from a MG5 model (coming from UFO)"""
583
584
585 old_aloha_mp=aloha.mp_precision
586 aloha.mp_precision=self.opt['mp']
587
588
589 write_dir=pjoin(self.dir_path, 'Source', 'MODEL')
590 model_builder = UFO_model_to_mg4(model, write_dir, self.opt)
591 model_builder.build(wanted_couplings)
592
593
594 old_loop_mode = aloha.loop_mode
595
596
597
598
599
600
601
602 if hasattr(self, 'aloha_model'):
603 aloha_model = self.aloha_model
604 else:
605 aloha_model = create_aloha.AbstractALOHAModel(model.get('name'))
606 aloha_model.add_Lorentz_object(model.get('lorentz'))
607
608
609 if wanted_lorentz:
610 aloha_model.compute_subset(wanted_lorentz)
611 else:
612 aloha_model.compute_all(save=False)
613
614
615 write_dir=pjoin(self.dir_path, 'Source', 'DHELAS')
616 aloha_model.write(write_dir, 'Fortran')
617
618
619 aloha.loop_mode = old_loop_mode
620
621
622 cp(MG5DIR + '/aloha/template_files/Makefile_F', write_dir+'/makefile')
623 if any([any(['L' in tag for tag in d[1]]) for d in wanted_lorentz]):
624 cp(MG5DIR + '/aloha/template_files/aloha_functions_loop.f', write_dir+'/aloha_functions.f')
625 aloha_model.loop_mode = False
626 else:
627 cp(MG5DIR + '/aloha/template_files/aloha_functions.f', write_dir+'/aloha_functions.f')
628 create_aloha.write_aloha_file_inc(write_dir, '.f', '.o')
629
630
631 self.make_model_symbolic_link()
632
633
634 aloha.mp_precision=old_aloha_mp
635
636
637
638
640 """Return info lines for MG5, suitable to place at beginning of
641 Fortran files"""
642
643 info = misc.get_pkg_info()
644 info_lines = ""
645 if info and info.has_key('version') and info.has_key('date'):
646 info_lines = "# Generated by MadGraph5_aMC@NLO v. %s, %s\n" % \
647 (info['version'], info['date'])
648 info_lines = info_lines + \
649 "# By the MadGraph5_aMC@NLO Development Team\n" + \
650 "# Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch"
651 else:
652 info_lines = "# Generated by MadGraph5_aMC@NLO\n" + \
653 "# By the MadGraph5_aMC@NLO Development Team\n" + \
654 "# Visit launchpad.net/madgraph5 and amcatnlo.web.cern.ch"
655
656 return info_lines
657
659 """Return info lines describing the processes for this matrix element"""
660
661 return"\n".join([ "C " + process.nice_string().replace('\n', '\nC * ') \
662 for process in matrix_element.get('processes')])
663
664
666 """Return the Helicity matrix definition lines for this matrix element"""
667
668 helicity_line_list = []
669 i = 0
670 for helicities in matrix_element.get_helicity_matrix():
671 i = i + 1
672 int_list = [i, len(helicities)]
673 int_list.extend(helicities)
674 helicity_line_list.append(\
675 ("DATA ("+array_name+"(I,%4r),I=1,%d) /" + \
676 ",".join(['%2r'] * len(helicities)) + "/") % tuple(int_list))
677
678 return "\n".join(helicity_line_list)
679
681 """Return the IC definition line coming after helicities, required by
682 switchmom in madevent"""
683
684 nexternal = matrix_element.get_nexternal_ninitial()[0]
685 int_list = range(1, nexternal + 1)
686
687 return "DATA (IC(I,1),I=1,%i) /%s/" % (nexternal,
688 ",".join([str(i) for \
689 i in int_list]))
690
692 """ From the squared order constraints set by the user, this function
693 finds what indices of the squared_orders list the user intends to pick.
694 It returns this as a string of comma-separated successive '.true.' or
695 '.false.' for each index."""
696
697 user_squared_orders = process.get('squared_orders')
698 split_orders = process.get('split_orders')
699
700 if len(user_squared_orders)==0:
701 return ','.join(['.true.']*len(squared_orders))
702
703 res = []
704 for sqsos in squared_orders:
705 is_a_match = True
706 for user_sqso, value in user_squared_orders.items():
707 if (process.get_squared_order_type(user_sqso) =='==' and \
708 value!=sqsos[split_orders.index(user_sqso)]) or \
709 (process.get_squared_order_type(user_sqso) in ['<=','='] and \
710 value<sqsos[split_orders.index(user_sqso)]) or \
711 (process.get_squared_order_type(user_sqso) == '>' and \
712 value>=sqsos[split_orders.index(user_sqso)]):
713 is_a_match = False
714 break
715 res.append('.true.' if is_a_match else '.false.')
716
717 return ','.join(res)
718
720 """ Return the split orders definition as defined in the list orders and
721 for the name of the array 'array_name'. Split rows in chunks of size n."""
722
723 ret_list = []
724 for index, order in enumerate(orders):
725 for k in xrange(0, len(order), n):
726 ret_list.append("DATA (%s(%3r,i),i=%3r,%3r) /%s/" % \
727 (array_name,index + 1, k + 1, min(k + n, len(order)),
728 ','.join(["%5r" % i for i in order[k:k + n]])))
729 return ret_list
730
742
744 """Return the color matrix definition lines for this matrix element. Split
745 rows in chunks of size n."""
746
747 if not matrix_element.get('color_matrix'):
748 return ["DATA Denom(1)/1/", "DATA (CF(i,1),i=1,1) /1/"]
749 else:
750 ret_list = []
751 my_cs = color.ColorString()
752 for index, denominator in \
753 enumerate(matrix_element.get('color_matrix').\
754 get_line_denominators()):
755
756 ret_list.append("DATA Denom(%i)/%i/" % (index + 1, denominator))
757
758 num_list = matrix_element.get('color_matrix').\
759 get_line_numerators(index, denominator)
760
761 for k in xrange(0, len(num_list), n):
762 ret_list.append("DATA (CF(i,%3r),i=%3r,%3r) /%s/" % \
763 (index + 1, k + 1, min(k + n, len(num_list)),
764 ','.join(["%5r" % i for i in num_list[k:k + n]])))
765 my_cs.from_immutable(sorted(matrix_element.get('color_basis').keys())[index])
766 ret_list.append("C %s" % repr(my_cs))
767 return ret_list
768
769
771 """Return the denominator factor line for this matrix element"""
772
773 return "DATA IDEN/%2r/" % \
774 matrix_element.get_denominator_factor()
775
777 """Return the ICOLAMP matrix, showing which JAMPs contribute to
778 which configs (diagrams)."""
779
780 ret_list = []
781
782 booldict = {False: ".false.", True: ".true."}
783
784 if not matrix_element.get('color_basis'):
785
786
787
788 configs = len(mapconfigs)
789 ret_list.append("DATA(icolamp(1,i,%d),i=1,%d)/%s/" % \
790 (num_matrix_element, configs,
791 ','.join([".true." for i in range(configs)])))
792 return ret_list
793
794
795
796
797
798 color_basis = matrix_element.get('color_basis')
799 max_Nc = max(sum([[v[4] for v in val] for val in color_basis.values()],
800 []))
801
802
803 diag_jamp = {}
804 for ijamp, col_basis_elem in \
805 enumerate(sorted(matrix_element.get('color_basis').keys())):
806 for diag_tuple in matrix_element.get('color_basis')[col_basis_elem]:
807
808 if diag_tuple[4] == max_Nc:
809 diag_num = diag_tuple[0] + 1
810
811 diag_jamp[diag_num] = diag_jamp.setdefault(diag_num, []) + \
812 [ijamp+1]
813
814 colamps = ijamp + 1
815
816 for iconfig, num_diag in enumerate(mapconfigs):
817 if num_diag == 0:
818 continue
819
820
821 bool_list = [(i + 1 in diag_jamp[num_diag]) for i in \
822 range(colamps)]
823
824 ret_list.append("DATA(icolamp(i,%d,%d),i=1,%d)/%s/" % \
825 (iconfig+1, num_matrix_element, colamps,
826 ','.join(["%s" % booldict[b] for b in \
827 bool_list])))
828
829 return ret_list
830
832 """Return the amp2(i) = sum(amp for diag(i))^2 lines"""
833
834 nexternal, ninitial = matrix_element.get_nexternal_ninitial()
835
836 minvert = min([max(diag.get_vertex_leg_numbers()) for diag in \
837 matrix_element.get('diagrams')])
838
839 ret_lines = []
840 if config_map:
841
842
843
844 diagrams = matrix_element.get('diagrams')
845
846 config_to_diag_dict = {}
847 for idiag, diag in enumerate(matrix_element.get('diagrams')):
848 if config_map[idiag] == 0:
849 continue
850 try:
851 config_to_diag_dict[config_map[idiag]].append(idiag)
852 except KeyError:
853 config_to_diag_dict[config_map[idiag]] = [idiag]
854
855
856
857
858
859 for config in sorted(config_to_diag_dict.keys()):
860
861 line = "AMP2(%(num)d)=AMP2(%(num)d)+" % \
862 {"num": (config_to_diag_dict[config][0] + 1)}
863
864 amp = "+".join(["AMP(%(num)d)" % {"num": a.get('number')} for a in \
865 sum([diagrams[idiag].get('amplitudes') for \
866 idiag in config_to_diag_dict[config]], [])])
867
868
869
870 if '+' in amp:
871 line += "(%s)*dconjg(%s)" % (amp, amp)
872 else:
873 line += "%s*dconjg(%s)" % (amp, amp)
874 ret_lines.append(line)
875 else:
876 for idiag, diag in enumerate(matrix_element.get('diagrams')):
877
878 if max(diag.get_vertex_leg_numbers()) > minvert:
879 continue
880
881
882 line = "AMP2(%(num)d)=AMP2(%(num)d)+" % {"num": (idiag + 1)}
883 line += "+".join(["AMP(%(num)d)*dconjg(AMP(%(num)d))" % \
884 {"num": a.get('number')} for a in \
885 diag.get('amplitudes')])
886 ret_lines.append(line)
887
888 return ret_lines
889
890
891
892
893
894
895 - def get_JAMP_coefs(self, color_amplitudes, color_basis=None, tag_letter="",\
896 n=50, Nc_value=3):
897 """This functions return the lines defining the DATA statement setting
898 the coefficients building the JAMPS out of the AMPS. Split rows in
899 bunches of size n.
900 One can specify the color_basis from which the color amplitudes originates
901 so that there are commentaries telling what color structure each JAMP
902 corresponds to."""
903
904 if(not isinstance(color_amplitudes,list) or
905 not (color_amplitudes and isinstance(color_amplitudes[0],list))):
906 raise MadGraph5Error, "Incorrect col_amps argument passed to get_JAMP_coefs"
907
908 res_list = []
909 my_cs = color.ColorString()
910 for index, coeff_list in enumerate(color_amplitudes):
911
912 coefs_list=[coefficient[0][0]*coefficient[0][1]*\
913 (fractions.Fraction(Nc_value)**coefficient[0][3]) for \
914 coefficient in coeff_list]
915
916
917 ampnumbers_list=[coefficient[1]*(-1 if coefficient[0][2] else 1) \
918 for coefficient in coeff_list]
919
920 commondenom=abs(reduce(fractions.gcd, coefs_list).denominator)
921 num_list=[(coefficient*commondenom).numerator \
922 for coefficient in coefs_list]
923 res_list.append("DATA NCONTRIBAMPS%s(%i)/%i/"%(tag_letter,\
924 index+1,len(num_list)))
925 res_list.append("DATA DENOMCCOEF%s(%i)/%i/"%(tag_letter,\
926 index+1,commondenom))
927 if color_basis:
928 my_cs.from_immutable(sorted(color_basis.keys())[index])
929 res_list.append("C %s" % repr(my_cs))
930 for k in xrange(0, len(num_list), n):
931 res_list.append("DATA (NUMCCOEF%s(%3r,i),i=%6r,%6r) /%s/" % \
932 (tag_letter,index + 1, k + 1, min(k + n, len(num_list)),
933 ','.join(["%6r" % i for i in num_list[k:k + n]])))
934 res_list.append("DATA (AMPNUMBERS%s(%3r,i),i=%6r,%6r) /%s/" % \
935 (tag_letter,index + 1, k + 1, min(k + n, len(num_list)),
936 ','.join(["%6r" % i for i in ampnumbers_list[k:k + n]])))
937 pass
938 return res_list
939
940 - def get_JAMP_lines_split_order(self, col_amps, split_order_amps,
941 split_order_names=None, JAMP_format="JAMP(%s)", AMP_format="AMP(%s)"):
942 """Return the JAMP = sum(fermionfactor * AMP(i)) lines from col_amps
943 defined as a matrix element or directly as a color_amplitudes dictionary.
944 The split_order_amps specifies the group of amplitudes sharing the same
945 amplitude orders which should be put in together in a given set of JAMPS.
946 The split_order_amps is supposed to have the format of the second output
947 of the function get_split_orders_mapping function in helas_objects.py.
948 The split_order_names is optional (it should correspond to the process
949 'split_orders' attribute) and only present to provide comments in the
950 JAMP definitions in the code."""
951
952
953 error_msg="Malformed '%s' argument passed to the "+\
954 "get_JAMP_lines_split_order function: %s"%str(split_order_amps)
955 if(isinstance(col_amps,helas_objects.HelasMatrixElement)):
956 color_amplitudes=col_amps.get_color_amplitudes()
957 elif(isinstance(col_amps,list)):
958 if(col_amps and isinstance(col_amps[0],list)):
959 color_amplitudes=col_amps
960 else:
961 raise MadGraph5Error, error_msg%'col_amps'
962 else:
963 raise MadGraph5Error, error_msg%'col_amps'
964
965
966 if isinstance(split_order_amps,list):
967 for elem in split_order_amps:
968 if len(elem)!=2:
969 raise MadGraph5Error, error_msg%'split_order_amps'
970
971
972 if not isinstance(elem[0],tuple) or \
973 not isinstance(elem[1],tuple) or \
974 not isinstance(elem[0][0],int) or \
975 not isinstance(elem[1][0],int):
976 raise MadGraph5Error, error_msg%'split_order_amps'
977 else:
978 raise MadGraph5Error, error_msg%'split_order_amps'
979
980 if not split_order_names is None:
981 if isinstance(split_order_names,list):
982
983
984 if len(split_order_names)!=len(split_order_amps[0][0]):
985 raise MadGraph5Error, error_msg%'split_order_names'
986
987 if not isinstance(split_order_names[0],str):
988 raise MadGraph5Error, error_msg%'split_order_names'
989 else:
990 raise MadGraph5Error, error_msg%'split_order_names'
991
992
993
994
995 res_list=[]
996 for i, amp_order in enumerate(split_order_amps):
997 col_amps_order = []
998 for jamp in color_amplitudes:
999 col_amps_order.append(filter(lambda col_amp:
1000 col_amp[1] in amp_order[1],jamp))
1001 if split_order_names:
1002 res_list.append('C JAMPs contributing to orders '+' '.join(
1003 ['%s=%i'%order for order in zip(split_order_names,
1004 amp_order[0])]))
1005 res_list.extend(self.get_JAMP_lines(col_amps_order,
1006 JAMP_format="JAMP(%s,{0})".format(str(i+1))))
1007
1008 return res_list
1009
1010 - def get_JAMP_lines(self, col_amps, JAMP_format="JAMP(%s)",
1011 AMP_format="AMP(%s)", split=-1):
1012 """Return the JAMP = sum(fermionfactor * AMP(i)) lines from col_amps
1013 defined as a matrix element or directly as a color_amplitudes dictionary.
1014 The split argument defines how the JAMP lines should be split in order
1015 not to be too long."""
1016
1017
1018
1019 if(isinstance(col_amps,helas_objects.HelasMatrixElement)):
1020 color_amplitudes=col_amps.get_color_amplitudes()
1021 elif(isinstance(col_amps,list)):
1022 if(col_amps and isinstance(col_amps[0],list)):
1023 color_amplitudes=col_amps
1024 else:
1025 raise MadGraph5Error, "Incorrect col_amps argument passed to get_JAMP_lines"
1026 else:
1027 raise MadGraph5Error, "Incorrect col_amps argument passed to get_JAMP_lines"
1028
1029
1030 res_list = []
1031 for i, coeff_list in enumerate(color_amplitudes):
1032
1033
1034
1035
1036 if coeff_list==[]:
1037 res_list.append(((JAMP_format+"=0D0") % str(i + 1)))
1038 continue
1039
1040
1041 first=True
1042 n = (len(coeff_list)+1 if split<=0 else split)
1043 while coeff_list!=[]:
1044 coefs=coeff_list[:n]
1045 coeff_list=coeff_list[n:]
1046 res = ((JAMP_format+"=") % str(i + 1)) + \
1047 ((JAMP_format % str(i + 1)) if not first and split>0 else '')
1048 first=False
1049
1050
1051 list_fracs = [abs(coefficient[0][1]) for coefficient in coefs]
1052 common_factor = False
1053 diff_fracs = list(set(list_fracs))
1054 if len(diff_fracs) == 1 and abs(diff_fracs[0]) != 1:
1055 common_factor = True
1056 global_factor = diff_fracs[0]
1057 res = res + '%s(' % self.coeff(1, global_factor, False, 0)
1058
1059 for (coefficient, amp_number) in coefs:
1060 if common_factor:
1061 res = (res + "%s" + AMP_format) % \
1062 (self.coeff(coefficient[0],
1063 coefficient[1] / abs(coefficient[1]),
1064 coefficient[2],
1065 coefficient[3]),
1066 str(amp_number))
1067 else:
1068 res = (res + "%s" + AMP_format) % (self.coeff(coefficient[0],
1069 coefficient[1],
1070 coefficient[2],
1071 coefficient[3]),
1072 str(amp_number))
1073
1074 if common_factor:
1075 res = res + ')'
1076
1077 res_list.append(res)
1078
1079 return res_list
1080
1081 - def get_pdf_lines(self, matrix_element, ninitial, subproc_group = False):
1082 """Generate the PDF lines for the auto_dsig.f file"""
1083
1084 processes = matrix_element.get('processes')
1085 model = processes[0].get('model')
1086
1087 pdf_definition_lines = ""
1088 pdf_data_lines = ""
1089 pdf_lines = ""
1090
1091 if ninitial == 1:
1092 pdf_lines = "PD(0) = 0d0\nIPROC = 0\n"
1093 for i, proc in enumerate(processes):
1094 process_line = proc.base_string()
1095 pdf_lines = pdf_lines + "IPROC=IPROC+1 ! " + process_line
1096 pdf_lines = pdf_lines + "\nPD(IPROC)=1d0\n"
1097 pdf_lines = pdf_lines + "\nPD(0)=PD(0)+PD(IPROC)\n"
1098 else:
1099
1100 initial_states = [sorted(list(set([p.get_initial_pdg(1) for \
1101 p in processes]))),
1102 sorted(list(set([p.get_initial_pdg(2) for \
1103 p in processes])))]
1104
1105
1106 pdf_codes = dict([(p, model.get_particle(p).get_name()) for p in \
1107 sum(initial_states,[])])
1108 for key,val in pdf_codes.items():
1109 pdf_codes[key] = val.replace('~','x').replace('+','p').replace('-','m')
1110
1111
1112 pdgtopdf = {21: 0, 22: 7}
1113
1114
1115 for pdg in sum(initial_states,[]):
1116 if not pdg in pdgtopdf and not pdg in pdgtopdf.values():
1117 pdgtopdf[pdg] = pdg
1118 elif pdg not in pdgtopdf and pdg in pdgtopdf.values():
1119
1120 pdgtopdf[pdg] = 6000000 + pdg
1121
1122
1123 for i in [0,1]:
1124 pdf_definition_lines += "DOUBLE PRECISION " + \
1125 ",".join(["%s%d" % (pdf_codes[pdg],i+1) \
1126 for pdg in \
1127 initial_states[i]]) + \
1128 "\n"
1129
1130
1131 for i in [0,1]:
1132 pdf_data_lines += "DATA " + \
1133 ",".join(["%s%d" % (pdf_codes[pdg],i+1) \
1134 for pdg in initial_states[i]]) + \
1135 "/%d*1D0/" % len(initial_states[i]) + \
1136 "\n"
1137
1138
1139 for i, init_states in enumerate(initial_states):
1140 if subproc_group:
1141 pdf_lines = pdf_lines + \
1142 "IF (ABS(LPP(IB(%d))).GE.1) THEN\nLP=SIGN(1,LPP(IB(%d)))\n" \
1143 % (i + 1, i + 1)
1144 else:
1145 pdf_lines = pdf_lines + \
1146 "IF (ABS(LPP(%d)) .GE. 1) THEN\nLP=SIGN(1,LPP(%d))\n" \
1147 % (i + 1, i + 1)
1148
1149 for initial_state in init_states:
1150 if initial_state in pdf_codes.keys():
1151 if subproc_group:
1152 pdf_lines = pdf_lines + \
1153 ("%s%d=PDG2PDF(ABS(LPP(IB(%d))),%d*LP," + \
1154 "XBK(IB(%d)),DSQRT(Q2FACT(%d)))\n") % \
1155 (pdf_codes[initial_state],
1156 i + 1, i + 1, pdgtopdf[initial_state],
1157 i + 1, i + 1)
1158 else:
1159 pdf_lines = pdf_lines + \
1160 ("%s%d=PDG2PDF(ABS(LPP(%d)),%d*LP," + \
1161 "XBK(%d),DSQRT(Q2FACT(%d)))\n") % \
1162 (pdf_codes[initial_state],
1163 i + 1, i + 1, pdgtopdf[initial_state],
1164 i + 1, i + 1)
1165 pdf_lines = pdf_lines + "ENDIF\n"
1166
1167
1168 pdf_lines = pdf_lines + "PD(0) = 0d0\nIPROC = 0\n"
1169 for proc in processes:
1170 process_line = proc.base_string()
1171 pdf_lines = pdf_lines + "IPROC=IPROC+1 ! " + process_line
1172 pdf_lines = pdf_lines + "\nPD(IPROC)="
1173 for ibeam in [1, 2]:
1174 initial_state = proc.get_initial_pdg(ibeam)
1175 if initial_state in pdf_codes.keys():
1176 pdf_lines = pdf_lines + "%s%d*" % \
1177 (pdf_codes[initial_state], ibeam)
1178 else:
1179 pdf_lines = pdf_lines + "1d0*"
1180
1181 pdf_lines = pdf_lines[:-1] + "\n"
1182 pdf_lines = pdf_lines + "PD(0)=PD(0)+DABS(PD(IPROC))\n"
1183
1184
1185 return pdf_definition_lines[:-1], pdf_data_lines[:-1], pdf_lines[:-1]
1186
1187
1188
1189
1191 """Write the props.inc file for MadEvent. Needs input from
1192 write_configs_file."""
1193
1194 lines = []
1195
1196 particle_dict = matrix_element.get('processes')[0].get('model').\
1197 get('particle_dict')
1198
1199 for iconf, configs in enumerate(s_and_t_channels):
1200 for vertex in configs[0] + configs[1][:-1]:
1201 leg = vertex.get('legs')[-1]
1202 if leg.get('id') not in particle_dict:
1203
1204 mass = 'zero'
1205 width = 'zero'
1206 pow_part = 0
1207 else:
1208 particle = particle_dict[leg.get('id')]
1209
1210 if particle.get('mass').lower() == 'zero':
1211 mass = particle.get('mass')
1212 else:
1213 mass = "abs(%s)" % particle.get('mass')
1214
1215 if particle.get('width').lower() == 'zero':
1216 width = particle.get('width')
1217 else:
1218 width = "abs(%s)" % particle.get('width')
1219
1220 pow_part = 1 + int(particle.is_boson())
1221
1222 lines.append("prmass(%d,%d) = %s" % \
1223 (leg.get('number'), iconf + 1, mass))
1224 lines.append("prwidth(%d,%d) = %s" % \
1225 (leg.get('number'), iconf + 1, width))
1226 lines.append("pow(%d,%d) = %d" % \
1227 (leg.get('number'), iconf + 1, pow_part))
1228
1229
1230 writer.writelines(lines)
1231
1232 return True
1233
1234
1235
1236
1238 """Write the configs.inc file for MadEvent"""
1239
1240
1241 (nexternal, ninitial) = matrix_element.get_nexternal_ninitial()
1242
1243 configs = [(i+1, d) for i,d in enumerate(matrix_element.get('diagrams'))]
1244 mapconfigs = [c[0] for c in configs]
1245 model = matrix_element.get('processes')[0].get('model')
1246 return mapconfigs, self.write_configs_file_from_diagrams(writer,
1247 [[c[1]] for c in configs],
1248 mapconfigs,
1249 nexternal, ninitial,
1250 model)
1251
1252
1253
1254
1257 """Write the actual configs.inc file.
1258
1259 configs is the diagrams corresponding to configs (each
1260 diagrams is a list of corresponding diagrams for all
1261 subprocesses, with None if there is no corresponding diagrams
1262 for a given process).
1263 mapconfigs gives the diagram number for each config.
1264
1265 For s-channels, we need to output one PDG for each subprocess in
1266 the subprocess group, in order to be able to pick the right
1267 one for multiprocesses."""
1268
1269 lines = []
1270
1271 s_and_t_channels = []
1272
1273 minvert = min([max([d for d in config if d][0].get_vertex_leg_numbers()) \
1274 for config in configs])
1275
1276
1277 nsubprocs = len(configs[0])
1278
1279 nconfigs = 0
1280
1281 new_pdg = model.get_first_non_pdg()
1282
1283 for iconfig, helas_diags in enumerate(configs):
1284 if any([vert > minvert for vert in
1285 [d for d in helas_diags if d][0].get_vertex_leg_numbers()]):
1286
1287 continue
1288 nconfigs += 1
1289
1290
1291
1292 empty_verts = []
1293 stchannels = []
1294 for h in helas_diags:
1295 if h:
1296
1297
1298 stchannels.append(h.get('amplitudes')[0].\
1299 get_s_and_t_channels(ninitial, model, new_pdg))
1300 else:
1301 stchannels.append((empty_verts, None))
1302
1303
1304 tchannels = [t for s,t in stchannels if t != None][0]
1305
1306
1307 s_and_t_channels.append([[s for s,t in stchannels if t != None][0],
1308 tchannels])
1309
1310
1311 if any([s for s,t in stchannels]):
1312 empty_verts[:] = [None]*max([len(s) for s,t in stchannels])
1313
1314
1315
1316 schannels = zip(*[s for s,t in stchannels])
1317 else:
1318 schannels = []
1319
1320 allchannels = schannels
1321 if len(tchannels) > 1:
1322
1323 allchannels = schannels + tchannels
1324
1325
1326
1327 lines.append("# Diagram %d" % (mapconfigs[iconfig]))
1328
1329 lines.append("data mapconfig(%d)/%d/" % (nconfigs,
1330 mapconfigs[iconfig]))
1331
1332 for verts in allchannels:
1333 if verts in schannels:
1334 vert = [v for v in verts if v][0]
1335 else:
1336 vert = verts
1337 daughters = [leg.get('number') for leg in vert.get('legs')[:-1]]
1338 last_leg = vert.get('legs')[-1]
1339 lines.append("data (iforest(i,%d,%d),i=1,%d)/%s/" % \
1340 (last_leg.get('number'), nconfigs, len(daughters),
1341 ",".join([str(d) for d in daughters])))
1342 if verts in schannels:
1343 pdgs = []
1344 for v in verts:
1345 if v:
1346 pdgs.append(v.get('legs')[-1].get('id'))
1347 else:
1348 pdgs.append(0)
1349 lines.append("data (sprop(i,%d,%d),i=1,%d)/%s/" % \
1350 (last_leg.get('number'), nconfigs, nsubprocs,
1351 ",".join([str(d) for d in pdgs])))
1352 lines.append("data tprid(%d,%d)/0/" % \
1353 (last_leg.get('number'), nconfigs))
1354 elif verts in tchannels[:-1]:
1355 lines.append("data tprid(%d,%d)/%d/" % \
1356 (last_leg.get('number'), nconfigs,
1357 abs(last_leg.get('id'))))
1358 lines.append("data (sprop(i,%d,%d),i=1,%d)/%s/" % \
1359 (last_leg.get('number'), nconfigs, nsubprocs,
1360 ",".join(['0'] * nsubprocs)))
1361
1362
1363 lines.append("# Number of configs")
1364 lines.append("data mapconfig(0)/%d/" % nconfigs)
1365
1366
1367 writer.writelines(lines)
1368
1369 return s_and_t_channels
1370
1371
1372
1373
1374
1375 - def coeff(self, ff_number, frac, is_imaginary, Nc_power, Nc_value=3):
1376 """Returns a nicely formatted string for the coefficients in JAMP lines"""
1377
1378 total_coeff = ff_number * frac * fractions.Fraction(Nc_value) ** Nc_power
1379
1380 if total_coeff == 1:
1381 if is_imaginary:
1382 return '+imag1*'
1383 else:
1384 return '+'
1385 elif total_coeff == -1:
1386 if is_imaginary:
1387 return '-imag1*'
1388 else:
1389 return '-'
1390
1391 res_str = '%+iD0' % total_coeff.numerator
1392
1393 if total_coeff.denominator != 1:
1394
1395 res_str = res_str + '/%iD0' % total_coeff.denominator
1396
1397 if is_imaginary:
1398 res_str = res_str + '*imag1'
1399
1400 return res_str + '*'
1401
1402
1404 """Set compiler based on what's available on the system"""
1405
1406
1407 if default_compiler and misc.which(default_compiler):
1408 compiler = default_compiler
1409 elif misc.which('gfortran'):
1410 compiler = 'gfortran'
1411 elif misc.which('g77'):
1412 compiler = 'g77'
1413 elif misc.which('f77'):
1414 compiler = 'f77'
1415 elif default_compiler:
1416 logger.warning('No Fortran Compiler detected! Please install one')
1417 compiler = default_compiler
1418 else:
1419 raise MadGraph5Error, 'No Fortran Compiler detected! Please install one'
1420 logger.info('Use Fortran compiler ' + compiler)
1421 self.replace_make_opt_f_compiler(compiler)
1422
1423 if not os.environ.has_key('MADGRAPH_DATA') and ReadWrite:
1424 self.replace_make_opt_f_compiler(compiler, pjoin(MG5DIR, 'Template', 'LO'))
1425
1426 return compiler
1427
1428
1429 set_compiler = set_fortran_compiler
1430
1431
1433 """Set compiler based on what's available on the system"""
1434
1435
1436 if default_compiler and misc.which(default_compiler):
1437 compiler = default_compiler
1438 elif misc.which('g++'):
1439 compiler = 'g++'
1440 elif misc.which('c++'):
1441 compiler = 'c++'
1442 elif misc.which('clang'):
1443 compiler = 'clang'
1444 elif default_compiler:
1445 logger.warning('No c++ Compiler detected! Please install one')
1446 compiler = default_compiler
1447 else:
1448 raise MadGraph5Error, 'No c++ Compiler detected! Please install one'
1449 logger.info('Use c++ compiler ' + compiler)
1450 self.replace_make_opt_c_compiler(compiler)
1451
1452 if not os.environ.has_key('MADGRAPH_DATA') and ReadWrite:
1453 self.replace_make_opt_c_compiler(compiler, pjoin(MG5DIR, 'Template', 'LO'))
1454
1455 return compiler
1456
1457
1459 """Set FC=compiler in Source/make_opts"""
1460
1461 mod = False
1462 if not root_dir:
1463 root_dir = self.dir_path
1464
1465 make_opts = pjoin(root_dir, 'Source', 'make_opts')
1466 lines = open(make_opts).read().split('\n')
1467 FC_re = re.compile('^(\s*)FC\s*=\s*(.+)\s*$')
1468 for iline, line in enumerate(lines):
1469 FC_result = FC_re.match(line)
1470 if FC_result:
1471 if compiler != FC_result.group(2):
1472 mod = True
1473 lines[iline] = FC_result.group(1) + "FC=" + compiler
1474 if not mod:
1475 return
1476 try:
1477 outfile = open(make_opts, 'w')
1478 except IOError:
1479 if root_dir == self.dir_path:
1480 logger.info('Fail to set compiler. Trying to continue anyway.')
1481 return
1482 outfile.write('\n'.join(lines))
1483
1484
1486 """Set CXX=compiler in Source/make_opts.
1487 The version is also checked, in order to set some extra flags
1488 if the compiler is clang (on MACOS)"""
1489
1490
1491 p = misc.Popen([compiler, '--version'], stdout=subprocess.PIPE,
1492 stderr=subprocess.PIPE)
1493 output, error = p.communicate()
1494 is_clang = 'LLVM' in output
1495
1496 mod = False
1497 if not root_dir:
1498 root_dir = self.dir_path
1499 make_opts = pjoin(root_dir, 'Source', 'make_opts')
1500 lines = open(make_opts).read().split('\n')
1501 CC_re = re.compile('^(\s*)CXX\s*=\s*(.+)\s*$')
1502 for iline, line in enumerate(lines):
1503 CC_result = CC_re.match(line)
1504 if CC_result:
1505 if compiler != CC_result.group(2):
1506 mod = True
1507 lines[iline] = CC_result.group(1) + "CXX=" + compiler
1508
1509 if is_clang:
1510 CFLAGS_re=re.compile('^(\s*)CFLAGS\s*=\s*(.+)\s*$')
1511 CXXFLAGS_re=re.compile('^(\s*)CXXFLAGS\s*=\s*(.+)\s*$')
1512 flags= '-O -stdlib=libstdc++ -mmacosx-version-min=10.6'
1513 for iline, line in enumerate(lines):
1514 CF_result = CFLAGS_re.match(line)
1515 CXXF_result = CXXFLAGS_re.match(line)
1516 if CF_result:
1517 lines[iline] = CF_result.group(1) + "CFLAGS= " + flags
1518 if CXXF_result:
1519 lines[iline] = CXXF_result.group(1) + "CXXFLAGS= " + flags
1520 if not mod:
1521 return
1522 try:
1523 outfile = open(make_opts, 'w')
1524 except IOError:
1525 if root_dir == self.dir_path:
1526 logger.info('Fail to set compiler. Trying to continue anyway.')
1527 return
1528 outfile.write('\n'.join(lines))
1529
1530
1531
1532
1534 """Class to take care of exporting a set of matrix elements to
1535 MadGraph v4 StandAlone format."""
1536
1538 """add the format information compare to standard init"""
1539
1540 if 'format' in opts:
1541 self.format = opts['format']
1542 del opts['format']
1543 else:
1544 self.format = 'standalone'
1545 ProcessExporterFortran.__init__(self, *args, **opts)
1546
1548 """Additional actions needed for setup of Template
1549 """
1550
1551
1552 if os.path.isdir(self.dir_path):
1553 return
1554
1555 logger.info('initialize a new standalone directory: %s' % \
1556 os.path.basename(self.dir_path))
1557 temp_dir = pjoin(self.mgme_dir, 'Template/LO')
1558
1559
1560 os.mkdir(self.dir_path)
1561 os.mkdir(pjoin(self.dir_path, 'Source'))
1562 os.mkdir(pjoin(self.dir_path, 'Source', 'MODEL'))
1563 os.mkdir(pjoin(self.dir_path, 'Source', 'DHELAS'))
1564 os.mkdir(pjoin(self.dir_path, 'SubProcesses'))
1565 os.mkdir(pjoin(self.dir_path, 'bin'))
1566 os.mkdir(pjoin(self.dir_path, 'bin', 'internal'))
1567 os.mkdir(pjoin(self.dir_path, 'lib'))
1568 os.mkdir(pjoin(self.dir_path, 'Cards'))
1569
1570
1571
1572 shutil.copy(pjoin(temp_dir, 'TemplateVersion.txt'), self.dir_path)
1573 try:
1574 shutil.copy(pjoin(self.mgme_dir, 'MGMEVersion.txt'), self.dir_path)
1575 except IOError:
1576 MG5_version = misc.get_pkg_info()
1577 open(pjoin(self.dir_path, 'MGMEVersion.txt'), 'w').write( \
1578 "5." + MG5_version['version'])
1579
1580
1581
1582
1583
1584
1585 shutil.copy(pjoin(self.mgme_dir, 'madgraph', 'iolibs', 'template_files', 'makefile_sa_f_sp'),
1586 pjoin(self.dir_path, 'SubProcesses', 'makefile'))
1587
1588 if self.format == 'standalone':
1589 shutil.copy(pjoin(self.mgme_dir, 'madgraph', 'iolibs', 'template_files', 'check_sa.f'),
1590 pjoin(self.dir_path, 'SubProcesses', 'check_sa.f'))
1591 elif self.format == 'standalone_rw':
1592 shutil.copy(pjoin(self.mgme_dir, 'madgraph', 'iolibs', 'template_files', 'driver_reweight.f'),
1593 pjoin(self.dir_path, 'SubProcesses', 'check_sa.f'))
1594
1595
1596 shutil.copy(pjoin(temp_dir, 'Source', 'make_opts'),
1597 pjoin(self.dir_path, 'Source'))
1598
1599 filename = pjoin(self.dir_path,'Source','makefile')
1600 self.write_source_makefile(writers.FileWriter(filename))
1601
1602
1603
1604
1606 """export the model dependent files for V4 model"""
1607
1608 super(ProcessExporterFortranSA,self).export_model_files(model_path)
1609
1610
1611
1612
1613 text = open(pjoin(self.dir_path,'SubProcesses','check_sa.f')).read()
1614 text = text.replace('call setpara(\'param_card.dat\')', 'call setpara(\'param_card.dat\', .true.)')
1615 fsock = open(pjoin(self.dir_path,'SubProcesses','check_sa.f'), 'w')
1616 fsock.write(text)
1617 fsock.close()
1618
1619 self.make_model_symbolic_link()
1620
1621
1622
1623
1625 """Run make in the DHELAS and MODEL directories, to set up
1626 everything for running standalone
1627 """
1628
1629 source_dir = pjoin(self.dir_path, "Source")
1630 logger.info("Running make for Helas")
1631 misc.compile(arg=['../lib/libdhelas.a'], cwd=source_dir, mode='fortran')
1632 logger.info("Running make for Model")
1633 misc.compile(arg=['../lib/libmodel.a'], cwd=source_dir, mode='fortran')
1634
1635
1636
1637
1638 - def finalize_v4_directory(self, matrix_elements, history, makejpg = False,
1639 online = False, compiler='gfortran'):
1640 """Finalize Standalone MG4 directory by generation proc_card_mg5.dat"""
1641
1642 self.compiler_choice(compiler)
1643 self.make()
1644
1645
1646 if history and os.path.isdir(pjoin(self.dir_path, 'Cards')):
1647 output_file = pjoin(self.dir_path, 'Cards', 'proc_card_mg5.dat')
1648 history.write(output_file)
1649
1651 """ Different daughter classes might want different compilers.
1652 So this function is meant to be overloaded if desired."""
1653
1654 self.set_compiler(compiler)
1655
1656
1657
1658
1661 """Generate the Pxxxxx directory for a subprocess in MG4 standalone,
1662 including the necessary matrix.f and nexternal.inc files"""
1663
1664 cwd = os.getcwd()
1665
1666
1667 dirpath = pjoin(self.dir_path, 'SubProcesses', \
1668 "P%s" % matrix_element.get('processes')[0].shell_string())
1669
1670 if self.opt['sa_symmetry']:
1671
1672 for i,proc in enumerate(matrix_element.get('processes')):
1673
1674 initial = []
1675 final = [l.get('id') for l in proc.get('legs')\
1676 if l.get('state') or initial.append(l.get('id'))]
1677 decay_finals = proc.get_final_ids_after_decay()
1678 decay_finals.sort()
1679 tag = (tuple(initial), tuple(decay_finals))
1680 legs = proc.get('legs')[:]
1681 leg0 = proc.get('legs')[0]
1682 leg1 = proc.get('legs')[1]
1683 if not leg1.get('state'):
1684 proc.get('legs')[0] = leg1
1685 proc.get('legs')[1] = leg0
1686 flegs = proc.get('legs')[2:]
1687 for perm in itertools.permutations(flegs):
1688 for i,p in enumerate(perm):
1689 proc.get('legs')[i+2] = p
1690 dirpath2 = pjoin(self.dir_path, 'SubProcesses', \
1691 "P%s" % proc.shell_string())
1692
1693 proc.get('legs')[2:] = legs[2:]
1694 if os.path.exists(dirpath2):
1695 proc.get('legs')[:] = legs
1696 return 0
1697 proc.get('legs')[:] = legs
1698
1699 try:
1700 os.mkdir(dirpath)
1701 except os.error as error:
1702 logger.warning(error.strerror + " " + dirpath)
1703
1704
1705
1706
1707
1708
1709
1710 logger.info('Creating files in directory %s' % dirpath)
1711
1712
1713 (nexternal, ninitial) = matrix_element.get_nexternal_ninitial()
1714
1715
1716 if self.opt['export_format']=='standalone_msP':
1717 filename = pjoin(dirpath, 'matrix_prod.f')
1718 else:
1719 filename = pjoin(dirpath, 'matrix.f')
1720 calls = self.write_matrix_element_v4(
1721 writers.FortranWriter(filename),
1722 matrix_element,
1723 fortran_model)
1724
1725 if self.opt['export_format'] == 'standalone_msP':
1726 filename = pjoin(dirpath,'configs_production.inc')
1727 mapconfigs, s_and_t_channels = self.write_configs_file(\
1728 writers.FortranWriter(filename),
1729 matrix_element)
1730
1731 filename = pjoin(dirpath,'props_production.inc')
1732 self.write_props_file(writers.FortranWriter(filename),
1733 matrix_element,
1734 s_and_t_channels)
1735
1736 filename = pjoin(dirpath,'nexternal_prod.inc')
1737 self.write_nexternal_madspin(writers.FortranWriter(filename),
1738 nexternal, ninitial)
1739
1740 if self.opt['export_format']=='standalone_msF':
1741 filename = pjoin(dirpath, 'helamp.inc')
1742 ncomb=matrix_element.get_helicity_combinations()
1743 self.write_helamp_madspin(writers.FortranWriter(filename),
1744 ncomb)
1745
1746 filename = pjoin(dirpath, 'nexternal.inc')
1747 self.write_nexternal_file(writers.FortranWriter(filename),
1748 nexternal, ninitial)
1749
1750 filename = pjoin(dirpath, 'pmass.inc')
1751 self.write_pmass_file(writers.FortranWriter(filename),
1752 matrix_element)
1753
1754 filename = pjoin(dirpath, 'ngraphs.inc')
1755 self.write_ngraphs_file(writers.FortranWriter(filename),
1756 len(matrix_element.get_all_amplitudes()))
1757
1758
1759 filename = pjoin(dirpath, "matrix.ps")
1760 plot = draw.MultiEpsDiagramDrawer(matrix_element.get('base_amplitude').\
1761 get('diagrams'),
1762 filename,
1763 model=matrix_element.get('processes')[0].\
1764 get('model'),
1765 amplitude=True)
1766 logger.info("Generating Feynman diagrams for " + \
1767 matrix_element.get('processes')[0].nice_string())
1768 plot.draw()
1769
1770 linkfiles = ['check_sa.f', 'coupl.inc', 'makefile']
1771
1772 for file in linkfiles:
1773 ln('../%s' % file, cwd=dirpath)
1774
1775
1776
1777
1778 if not calls:
1779 calls = 0
1780 return calls
1781
1782
1783
1784
1785
1787 """Write the nexternal.inc file for MG4"""
1788
1789
1790 path = pjoin(_file_path,'iolibs','template_files','madevent_makefile_source')
1791 set_of_lib = '$(LIBDIR)libdhelas.$(libext) $(LIBDIR)libmodel.$(libext)'
1792 model_line='''$(LIBDIR)libmodel.$(libext): MODEL\n\t cd MODEL; make\n'''
1793 text = open(path).read() % {'libraries': set_of_lib, 'model':model_line}
1794 writer.write(text)
1795
1796 return True
1797
1798
1799
1800
1803 """Export a matrix element to a matrix.f file in MG4 standalone format"""
1804
1805 if not matrix_element.get('processes') or \
1806 not matrix_element.get('diagrams'):
1807 return 0
1808
1809 if not isinstance(writer, writers.FortranWriter):
1810 raise writers.FortranWriter.FortranWriterError(\
1811 "writer not FortranWriter")
1812
1813 if not self.opt.has_key('sa_symmetry'):
1814 self.opt['sa_symmetry']=False
1815
1816
1817 writers.FortranWriter.downcase = False
1818
1819
1820 replace_dict = {'global_variable':'', 'amp2_lines':'',
1821 'proc_prefix':proc_prefix, 'proc_id':''}
1822
1823
1824 helas_calls = fortran_model.get_matrix_element_calls(\
1825 matrix_element)
1826
1827 replace_dict['helas_calls'] = "\n".join(helas_calls)
1828
1829
1830 info_lines = self.get_mg5_info_lines()
1831 replace_dict['info_lines'] = info_lines
1832
1833
1834 process_lines = self.get_process_info_lines(matrix_element)
1835 replace_dict['process_lines'] = process_lines
1836
1837
1838 (nexternal, ninitial) = matrix_element.get_nexternal_ninitial()
1839 replace_dict['nexternal'] = nexternal
1840
1841
1842 ncomb = matrix_element.get_helicity_combinations()
1843 replace_dict['ncomb'] = ncomb
1844
1845
1846 helicity_lines = self.get_helicity_lines(matrix_element)
1847 replace_dict['helicity_lines'] = helicity_lines
1848
1849
1850
1851 replace_dict['den_factor_line'] = self.get_den_factor_line(matrix_element)
1852
1853
1854 ngraphs = matrix_element.get_number_of_amplitudes()
1855 replace_dict['ngraphs'] = ngraphs
1856
1857
1858 nwavefuncs = matrix_element.get_number_of_wavefunctions()
1859 replace_dict['nwavefuncs'] = nwavefuncs
1860
1861
1862 ncolor = max(1, len(matrix_element.get('color_basis')))
1863 replace_dict['ncolor'] = ncolor
1864
1865 replace_dict['hel_avg_factor'] = matrix_element.get_hel_avg_factor()
1866
1867
1868 color_data_lines = self.get_color_data_lines(matrix_element)
1869 replace_dict['color_data_lines'] = "\n".join(color_data_lines)
1870
1871 if self.opt['export_format']=='standalone_msP':
1872
1873 amp2_lines = self.get_amp2_lines(matrix_element, [] )
1874 replace_dict['amp2_lines'] = '\n'.join(amp2_lines)
1875 replace_dict['global_variable'] = \
1876 " Double Precision amp2(NGRAPHS)\n common/to_amps/ amp2\n"
1877
1878
1879 split_orders=matrix_element.get('processes')[0].get('split_orders')
1880
1881 if len(split_orders)==0:
1882 replace_dict['nSplitOrders']=''
1883
1884 jamp_lines = self.get_JAMP_lines(matrix_element)
1885
1886
1887
1888 squared_orders = [(2,),]
1889 amp_orders = [((1,),tuple(range(1,ngraphs+1)))]
1890 replace_dict['chosen_so_configs'] = '.TRUE.'
1891 replace_dict['nSqAmpSplitOrders']=1
1892 replace_dict['split_order_str_list']=''
1893 else:
1894 squared_orders, amp_orders = matrix_element.get_split_orders_mapping()
1895 replace_dict['nAmpSplitOrders']=len(amp_orders)
1896 replace_dict['nSqAmpSplitOrders']=len(squared_orders)
1897 replace_dict['nSplitOrders']=len(split_orders)
1898 replace_dict['split_order_str_list']=str(split_orders)
1899 amp_so = self.get_split_orders_lines(
1900 [amp_order[0] for amp_order in amp_orders],'AMPSPLITORDERS')
1901 sqamp_so = self.get_split_orders_lines(squared_orders,'SQSPLITORDERS')
1902 replace_dict['ampsplitorders']='\n'.join(amp_so)
1903 replace_dict['sqsplitorders']='\n'.join(sqamp_so)
1904 jamp_lines = self.get_JAMP_lines_split_order(\
1905 matrix_element,amp_orders,split_order_names=split_orders)
1906
1907
1908 replace_dict['chosen_so_configs']=self.set_chosen_SO_index(
1909 matrix_element.get('processes')[0],squared_orders)
1910
1911
1912
1913
1914
1915 check_sa_writer=writers.FortranWriter('check_sa_born_splitOrders.f')
1916 self.write_check_sa_splitOrders(\
1917 squared_orders,split_orders,check_sa_writer)
1918
1919 writers.FortranWriter('nsqso_born.inc').writelines(
1920 """INTEGER NSQSO_BORN
1921 PARAMETER (NSQSO_BORN=%d)"""%replace_dict['nSqAmpSplitOrders'])
1922
1923 replace_dict['jamp_lines'] = '\n'.join(jamp_lines)
1924 if len(split_orders)>0:
1925 if self.opt['export_format']=='standalone_msP' :
1926 logger.debug("Warning: The export format standalone_msP is not "+\
1927 " available for individual ME evaluation of given coupl. orders."+\
1928 " Only the total ME will be computed.")
1929 file = open(pjoin(_file_path, \
1930 'iolibs/template_files/matrix_standalone_msP_v4.inc')).read()
1931
1932 elif self.opt['export_format']=='standalone_msF':
1933 logger.debug("Warning: The export format standalone_msF is not "+\
1934 " available for individual ME evaluation of given coupl. orders."+\
1935 " Only the total ME will be computed.")
1936 file = open(pjoin(_file_path, \
1937 'iolibs/template_files/matrix_standalone_msF_v4.inc')).read()
1938 else:
1939 file = open(pjoin(_file_path, \
1940 'iolibs/template_files/matrix_standalone_splitOrders_v4.inc')).read()
1941 else:
1942 if self.opt['export_format']=='standalone_msP' :
1943 file = open(pjoin(_file_path, \
1944 'iolibs/template_files/matrix_standalone_msP_v4.inc')).read()
1945
1946 elif self.opt['export_format']=='standalone_msF':
1947 file = open(pjoin(_file_path, \
1948 'iolibs/template_files/matrix_standalone_msF_v4.inc')).read()
1949 else:
1950 file = open(pjoin(_file_path, \
1951 'iolibs/template_files/matrix_standalone_v4.inc')).read()
1952
1953 file = file % replace_dict
1954
1955
1956 if len(split_orders)>0:
1957 file = file + '\n' + open(pjoin(_file_path, \
1958 'iolibs/template_files/split_orders_helping_functions.inc'))\
1959 .read()%replace_dict
1960
1961
1962 writer.writelines(file)
1963
1964 return len(filter(lambda call: call.find('#') != 0, helas_calls))
1965
1967 """ Write out a more advanced version of the check_sa drivers that
1968 individually returns the matrix element for each contributing squared
1969 order."""
1970
1971 check_sa_content = open(pjoin(self.mgme_dir, 'madgraph', 'iolibs', \
1972 'template_files', 'check_sa_splitOrders.f')).read()
1973 printout_sq_orders=[]
1974 for i, squared_order in enumerate(squared_orders):
1975 sq_orders=[]
1976 for j, sqo in enumerate(squared_order):
1977 sq_orders.append('%s=%d'%(split_orders[j],sqo))
1978 printout_sq_orders.append(\
1979 "write(*,*) '%d) Matrix element for (%s) = ',MATELEMS(%d)"\
1980 %(i+1,' '.join(sq_orders),i+1))
1981 printout_sq_orders='\n'.join(printout_sq_orders)
1982 writer.writelines(check_sa_content%{\
1983 'printout_sqorders':printout_sq_orders,
1984 'nSplitOrders':len(squared_orders)})
1985
1986
1987
1988
1990 """Class to take care of exporting a set of matrix elements to
1991 MadGraph v4 - MadWeight format."""
1992
1993 matrix_file="matrix_standalone_v4.inc"
1994
1996 """Additional actions needed for setup of Template
1997 """
1998
1999 super(ProcessExporterFortranMW, self).copy_v4template(modelname)
2000
2001
2002 shutil.copytree(pjoin(MG5DIR,'Template','MadWeight'),
2003 pjoin(self.dir_path, 'Source','MadWeight'), True)
2004 shutil.copytree(pjoin(MG5DIR,'madgraph','madweight'),
2005 pjoin(self.dir_path, 'bin','internal','madweight'), True)
2006 files.mv(pjoin(self.dir_path, 'Source','MadWeight','src','setrun.f'),
2007 pjoin(self.dir_path, 'Source','setrun.f'))
2008 files.mv(pjoin(self.dir_path, 'Source','MadWeight','src','run.inc'),
2009 pjoin(self.dir_path, 'Source','run.inc'))
2010
2011 filename = os.path.join(self.dir_path,'Source','run_config.inc')
2012 self.write_run_config_file(writers.FortranWriter(filename))
2013
2014 try:
2015 subprocess.call([os.path.join(self.dir_path, 'Source','MadWeight','bin','internal','pass_to_madweight')],
2016 stdout = os.open(os.devnull, os.O_RDWR),
2017 stderr = os.open(os.devnull, os.O_RDWR),
2018 cwd=self.dir_path)
2019 except OSError:
2020
2021 pass
2022
2023
2024 self.copy_python_file()
2025
2026 self.get_mw_cuts_version()
2027
2028
2029 filename = os.path.join(self.dir_path,'Source','makefile')
2030 self.write_source_makefile(writers.FortranWriter(filename))
2031
2032
2033
2034
2037
2038 super(ProcessExporterFortranMW,self).convert_model_to_mg4(model,
2039 wanted_lorentz, wanted_couplings)
2040
2041 IGNORE_PATTERNS = ('*.pyc','*.dat','*.py~')
2042 try:
2043 shutil.rmtree(pjoin(self.dir_path,'bin','internal','ufomodel'))
2044 except OSError as error:
2045 pass
2046 model_path = model.get('modelpath')
2047
2048 shutil.copytree(model_path,
2049 pjoin(self.dir_path,'bin','internal','ufomodel'),
2050 ignore=shutil.ignore_patterns(*IGNORE_PATTERNS))
2051 if hasattr(model, 'restrict_card'):
2052 out_path = pjoin(self.dir_path, 'bin', 'internal','ufomodel',
2053 'restrict_default.dat')
2054 if isinstance(model.restrict_card, check_param_card.ParamCard):
2055 model.restrict_card.write(out_path)
2056 else:
2057 files.cp(model.restrict_card, out_path)
2058
2059
2060
2061
2063 """copy the python file require for the Template"""
2064
2065
2066 cp(_file_path+'/interface/madweight_interface.py',
2067 self.dir_path+'/bin/internal/madweight_interface.py')
2068 cp(_file_path+'/interface/extended_cmd.py',
2069 self.dir_path+'/bin/internal/extended_cmd.py')
2070 cp(_file_path+'/interface/common_run_interface.py',
2071 self.dir_path+'/bin/internal/common_run_interface.py')
2072 cp(_file_path+'/various/misc.py', self.dir_path+'/bin/internal/misc.py')
2073 cp(_file_path+'/iolibs/files.py', self.dir_path+'/bin/internal/files.py')
2074
2075
2076 cp(_file_path+'/iolibs/file_writers.py',
2077 self.dir_path+'/bin/internal/file_writers.py')
2078
2079 cp(_file_path+'../models/check_param_card.py',
2080 self.dir_path+'/bin/internal/check_param_card.py')
2081
2082
2083 cp(_file_path+'/__init__.py', self.dir_path+'/bin/internal/__init__.py')
2084 cp(_file_path+'/various/lhe_parser.py',
2085 self.dir_path+'/bin/internal/lhe_parser.py')
2086
2087
2088 cp(_file_path+'/various/banner.py',
2089 self.dir_path+'/bin/internal/banner.py')
2090 cp(_file_path+'/various/cluster.py',
2091 self.dir_path+'/bin/internal/cluster.py')
2092
2093
2094
2095
2096
2097
2098 cp(_file_path+'/interface/.mg5_logging.conf',
2099 self.dir_path+'/bin/internal/me5_logging.conf')
2100 cp(_file_path+'/interface/coloring_logging.py',
2101 self.dir_path+'/bin/internal/coloring_logging.py')
2102
2103
2104
2105
2106
2108 """create the appropriate cuts.f
2109 This is based on the one associated to ME output but:
2110 1) No clustering (=> remove initcluster/setclscales)
2111 2) Adding the definition of cut_bw at the file.
2112 """
2113
2114 template = open(pjoin(MG5DIR,'Template','LO','SubProcesses','cuts.f'))
2115
2116 text = StringIO()
2117
2118 nb_if = 0
2119 for line in template:
2120 if 'if(xqcut.gt.0d0' in line:
2121 nb_if = 1
2122 if nb_if == 0:
2123 text.write(line)
2124 continue
2125 if re.search(r'if\(.*\)\s*then', line):
2126 nb_if += 1
2127 elif 'endif' in line:
2128 nb_if -= 1
2129
2130
2131 text.write("""
2132 logical function cut_bw(p)
2133 include 'madweight_param.inc'
2134 double precision p(*)
2135 if (bw_cut) then
2136 cut_bw = .true.
2137 else
2138 stop 1
2139 endif
2140 return
2141 end
2142 """)
2143
2144 final = text.getvalue()
2145
2146 template = final.replace('call initcluster', '! Remove for MW!call initcluster')
2147 template = template.replace('genps.inc', 'maxparticles.inc')
2148
2149 if not outpath:
2150 fsock = open(pjoin(self.dir_path, 'SubProcesses', 'cuts.f'), 'w')
2151 elif isinstance(outpath, str):
2152 fsock = open(outpath, 'w')
2153 else:
2154 fsock = outpath
2155 fsock.write(template)
2156
2157
2158
2159
2160
2161
2163 """Run make in the DHELAS, MODEL, PDF and CERNLIB directories, to set up
2164 everything for running madweight
2165 """
2166
2167 source_dir = os.path.join(self.dir_path, "Source")
2168 logger.info("Running make for Helas")
2169 misc.compile(arg=['../lib/libdhelas.a'], cwd=source_dir, mode='fortran')
2170 logger.info("Running make for Model")
2171 misc.compile(arg=['../lib/libmodel.a'], cwd=source_dir, mode='fortran')
2172 logger.info("Running make for PDF")
2173 misc.compile(arg=['../lib/libpdf.a'], cwd=source_dir, mode='fortran')
2174 logger.info("Running make for CERNLIB")
2175 misc.compile(arg=['../lib/libcernlib.a'], cwd=source_dir, mode='fortran')
2176 logger.info("Running make for GENERIC")
2177 misc.compile(arg=['../lib/libgeneric.a'], cwd=source_dir, mode='fortran')
2178 logger.info("Running make for blocks")
2179 misc.compile(arg=['../lib/libblocks.a'], cwd=source_dir, mode='fortran')
2180 logger.info("Running make for tools")
2181 misc.compile(arg=['../lib/libtools.a'], cwd=source_dir, mode='fortran')
2182
2183
2184
2185
2186 - def finalize_v4_directory(self, matrix_elements, history, makejpg = False,
2187 online = False, compiler='g77'):
2188 """Finalize Standalone MG4 directory by generation proc_card_mg5.dat"""
2189
2190
2191 filename = pjoin(self.dir_path,'Source','maxparticles.inc')
2192 self.write_maxparticles_file(writers.FortranWriter(filename),
2193 matrix_elements)
2194 ln(pjoin(self.dir_path, 'Source', 'maxparticles.inc'),
2195 pjoin(self.dir_path, 'Source','MadWeight','blocks'))
2196 ln(pjoin(self.dir_path, 'Source', 'maxparticles.inc'),
2197 pjoin(self.dir_path, 'Source','MadWeight','tools'))
2198
2199 self.set_compiler(compiler)
2200 self.make()
2201
2202
2203 if os.path.isdir(os.path.join(self.dir_path, 'Cards')):
2204 output_file = os.path.join(self.dir_path, 'Cards', 'proc_card_mg5.dat')
2205 history.write(output_file)
2206
2207
2208
2209
2211 """export the model dependent files for V4 model"""
2212
2213 super(ProcessExporterFortranMW,self).export_model_files(model_path)
2214
2215
2216 text="""
2217 subroutine update_as_param()
2218 call setpara('param_card.dat',.false.)
2219 return
2220 end
2221 """
2222 ff = open(os.path.join(self.dir_path, 'Source', 'MODEL', 'couplings.f'),'a')
2223 ff.write(text)
2224 ff.close()
2225
2226
2227 text = open(os.path.join(self.dir_path,'Source','setrun.f')).read()
2228 text = text.replace('call setpara(param_card_name)', 'call setpara(param_card_name, .true.)')
2229 fsock = open(os.path.join(self.dir_path,'Source','setrun.f'), 'w')
2230 fsock.write(text)
2231 fsock.close()
2232
2233
2234 text = open(os.path.join(self.dir_path,'SubProcesses','initialization.f')).read()
2235 text = text.replace('call setpara(param_name)', 'call setpara(param_name, .true.)')
2236 fsock = open(os.path.join(self.dir_path,'SubProcesses','initialization.f'), 'w')
2237 fsock.write(text)
2238 fsock.close()
2239
2240
2241 self.make_model_symbolic_link()
2242
2243
2244
2245
2248 """Generate the Pxxxxx directory for a subprocess in MG4 MadWeight format,
2249 including the necessary matrix.f and nexternal.inc files"""
2250
2251 cwd = os.getcwd()
2252
2253
2254 dirpath = os.path.join(self.dir_path, 'SubProcesses', \
2255 "P%s" % matrix_element.get('processes')[0].shell_string())
2256
2257 try:
2258 os.mkdir(dirpath)
2259 except os.error as error:
2260 logger.warning(error.strerror + " " + dirpath)
2261
2262
2263
2264
2265
2266
2267
2268 logger.info('Creating files in directory %s' % dirpath)
2269
2270
2271 (nexternal, ninitial) = matrix_element.get_nexternal_ninitial()
2272
2273
2274 filename = pjoin(dirpath,'matrix.f')
2275 calls,ncolor = self.write_matrix_element_v4(
2276 writers.FortranWriter(filename),
2277 matrix_element,
2278 fortran_model)
2279
2280 filename = pjoin(dirpath, 'auto_dsig.f')
2281 self.write_auto_dsig_file(writers.FortranWriter(filename),
2282 matrix_element)
2283
2284 filename = pjoin(dirpath, 'configs.inc')
2285 mapconfigs, s_and_t_channels = self.write_configs_file(\
2286 writers.FortranWriter(filename),
2287 matrix_element)
2288
2289 filename = pjoin(dirpath, 'nexternal.inc')
2290 self.write_nexternal_file(writers.FortranWriter(filename),
2291 nexternal, ninitial)
2292
2293 filename = pjoin(dirpath, 'leshouche.inc')
2294 self.write_leshouche_file(writers.FortranWriter(filename),
2295 matrix_element)
2296
2297 filename = pjoin(dirpath, 'props.inc')
2298 self.write_props_file(writers.FortranWriter(filename),
2299 matrix_element,
2300 s_and_t_channels)
2301
2302 filename = pjoin(dirpath, 'pmass.inc')
2303 self.write_pmass_file(writers.FortranWriter(filename),
2304 matrix_element)
2305
2306 filename = pjoin(dirpath, 'ngraphs.inc')
2307 self.write_ngraphs_file(writers.FortranWriter(filename),
2308 len(matrix_element.get_all_amplitudes()))
2309
2310 filename = pjoin(dirpath, 'maxamps.inc')
2311 self.write_maxamps_file(writers.FortranWriter(filename),
2312 len(matrix_element.get('diagrams')),
2313 ncolor,
2314 len(matrix_element.get('processes')),
2315 1)
2316
2317 filename = pjoin(dirpath, 'phasespace.inc')
2318 self.write_phasespace_file(writers.FortranWriter(filename),
2319 len(matrix_element.get('diagrams')),
2320 )
2321
2322
2323 filename = pjoin(dirpath, "matrix.ps")
2324 plot = draw.MultiEpsDiagramDrawer(matrix_element.get('base_amplitude').\
2325 get('diagrams'),
2326 filename,
2327 model=matrix_element.get('processes')[0].\
2328 get('model'),
2329 amplitude='')
2330 logger.info("Generating Feynman diagrams for " + \
2331 matrix_element.get('processes')[0].nice_string())
2332 plot.draw()
2333
2334
2335 ln(self.dir_path + '/Source/genps.inc', self.dir_path + '/SubProcesses', log=False)
2336
2337
2338 linkfiles = ['driver.f', 'cuts.f', 'initialization.f','gen_ps.f', 'makefile', 'coupl.inc','madweight_param.inc', 'run.inc', 'setscales.f', 'genps.inc']
2339
2340 for file in linkfiles:
2341 ln('../%s' % file, starting_dir=cwd)
2342
2343 ln('nexternal.inc', '../../Source', log=False, cwd=dirpath)
2344 ln('leshouche.inc', '../../Source', log=False, cwd=dirpath)
2345 ln('maxamps.inc', '../../Source', log=False, cwd=dirpath)
2346 ln('phasespace.inc', '../', log=True, cwd=dirpath)
2347
2348
2349
2350 if not calls:
2351 calls = 0
2352 return calls
2353
2354
2355
2356
2358 """Export a matrix element to a matrix.f file in MG4 MadWeight format"""
2359
2360 if not matrix_element.get('processes') or \
2361 not matrix_element.get('diagrams'):
2362 return 0
2363
2364 if not isinstance(writer, writers.FortranWriter):
2365 raise writers.FortranWriter.FortranWriterError(\
2366 "writer not FortranWriter")
2367
2368
2369 writers.FortranWriter.downcase = False
2370
2371 replace_dict = {}
2372
2373
2374 info_lines = self.get_mg5_info_lines()
2375 replace_dict['info_lines'] = info_lines
2376
2377
2378 process_lines = self.get_process_info_lines(matrix_element)
2379 replace_dict['process_lines'] = process_lines
2380
2381
2382 replace_dict['proc_id'] = proc_id
2383
2384
2385 (nexternal, ninitial) = matrix_element.get_nexternal_ninitial()
2386 replace_dict['nexternal'] = nexternal
2387
2388
2389 ncomb = matrix_element.get_helicity_combinations()
2390 replace_dict['ncomb'] = ncomb
2391
2392
2393 helicity_lines = self.get_helicity_lines(matrix_element)
2394 replace_dict['helicity_lines'] = helicity_lines
2395
2396
2397
2398 den_factor_line = self.get_den_factor_line(matrix_element)
2399 replace_dict['den_factor_line'] = den_factor_line
2400
2401
2402 ngraphs = matrix_element.get_number_of_amplitudes()
2403 replace_dict['ngraphs'] = ngraphs
2404
2405
2406 nwavefuncs = matrix_element.get_number_of_wavefunctions()
2407 replace_dict['nwavefuncs'] = nwavefuncs
2408
2409
2410 ncolor = max(1, len(matrix_element.get('color_basis')))
2411 replace_dict['ncolor'] = ncolor
2412
2413
2414 color_data_lines = self.get_color_data_lines(matrix_element)
2415 replace_dict['color_data_lines'] = "\n".join(color_data_lines)
2416
2417
2418 helas_calls = fortran_model.get_matrix_element_calls(\
2419 matrix_element)
2420
2421 replace_dict['helas_calls'] = "\n".join(helas_calls)
2422
2423
2424 jamp_lines = self.get_JAMP_lines(matrix_element)
2425 replace_dict['jamp_lines'] = '\n'.join(jamp_lines)
2426
2427 file = open(os.path.join(_file_path, \
2428 'iolibs/template_files/%s' % self.matrix_file)).read()
2429 file = file % replace_dict
2430
2431
2432
2433 writer.writelines(file)
2434
2435 return len(filter(lambda call: call.find('#') != 0, helas_calls)),ncolor
2436
2437
2438
2439
2441 """Write the nexternal.inc file for madweight"""
2442
2443
2444 path = os.path.join(_file_path,'iolibs','template_files','madweight_makefile_source')
2445 set_of_lib = '$(LIBRARIES) $(LIBDIR)libdhelas.$(libext) $(LIBDIR)libpdf.$(libext) $(LIBDIR)libmodel.$(libext) $(LIBDIR)libcernlib.$(libext) $(LIBDIR)libtf.$(libext)'
2446 text = open(path).read() % {'libraries': set_of_lib}
2447 writer.write(text)
2448
2449 return True
2450
2452 """ """
2453
2454 template = """ include 'maxparticles.inc'
2455 integer max_branches
2456 parameter (max_branches=max_particles-1)
2457 integer max_configs
2458 parameter (max_configs=%(nb_diag)s)
2459
2460 c channel position
2461 integer config_pos,perm_pos
2462 common /to_config/config_pos,perm_pos
2463
2464 """
2465
2466 writer.write(template % {'nb_diag': nb_diag})
2467
2468
2469
2470
2471
2473 """Write the auto_dsig.f file for the differential cross section
2474 calculation, includes pdf call information (MadWeight format)"""
2475
2476 if not matrix_element.get('processes') or \
2477 not matrix_element.get('diagrams'):
2478 return 0
2479
2480 nexternal, ninitial = matrix_element.get_nexternal_ninitial()
2481
2482 if ninitial < 1 or ninitial > 2:
2483 raise writers.FortranWriter.FortranWriterError, \
2484 """Need ninitial = 1 or 2 to write auto_dsig file"""
2485
2486 replace_dict = {}
2487
2488
2489 info_lines = self.get_mg5_info_lines()
2490 replace_dict['info_lines'] = info_lines
2491
2492
2493 process_lines = self.get_process_info_lines(matrix_element)
2494 replace_dict['process_lines'] = process_lines
2495
2496
2497 replace_dict['proc_id'] = proc_id
2498 replace_dict['numproc'] = 1
2499
2500
2501 if ninitial == 1:
2502
2503 dsig_line = "pd(0)*dsiguu"
2504 else:
2505
2506 dsig_line = "pd(0)*conv*dsiguu"
2507
2508 replace_dict['dsig_line'] = dsig_line
2509
2510
2511 pdf_vars, pdf_data, pdf_lines = \
2512 self.get_pdf_lines(matrix_element, ninitial, proc_id != "")
2513 replace_dict['pdf_vars'] = pdf_vars
2514 replace_dict['pdf_data'] = pdf_data
2515 replace_dict['pdf_lines'] = pdf_lines
2516
2517
2518 if proc_id:
2519 replace_dict['numproc'] = int(proc_id)
2520 replace_dict['passcuts_begin'] = ""
2521 replace_dict['passcuts_end'] = ""
2522
2523
2524 replace_dict['define_subdiag_lines'] = \
2525 """\nINTEGER SUBDIAG(MAXSPROC),IB(2)
2526 COMMON/TO_SUB_DIAG/SUBDIAG,IB"""
2527 else:
2528 replace_dict['passcuts_begin'] = "IF (PASSCUTS(PP)) THEN"
2529 replace_dict['passcuts_end'] = "ENDIF"
2530 replace_dict['define_subdiag_lines'] = ""
2531
2532 file = open(os.path.join(_file_path, \
2533 'iolibs/template_files/auto_dsig_mw.inc')).read()
2534
2535 file = file % replace_dict
2536
2537
2538
2539 writer.writelines(file)
2540
2541
2542
2543
2545 """Write the configs.inc file for MadEvent"""
2546
2547
2548 (nexternal, ninitial) = matrix_element.get_nexternal_ninitial()
2549
2550 configs = [(i+1, d) for i,d in enumerate(matrix_element.get('diagrams'))]
2551 mapconfigs = [c[0] for c in configs]
2552 model = matrix_element.get('processes')[0].get('model')
2553 return mapconfigs, self.write_configs_file_from_diagrams(writer,
2554 [[c[1]] for c in configs],
2555 mapconfigs,
2556 nexternal, ninitial,matrix_element, model)
2557
2558
2559
2560
2562 """Write the run_configs.inc file for MadWeight"""
2563
2564 path = os.path.join(_file_path,'iolibs','template_files','madweight_run_config.inc')
2565 text = open(path).read() % {'chanperjob':'5'}
2566 writer.write(text)
2567 return True
2568
2569
2570
2571
2574 """Write the actual configs.inc file.
2575
2576 configs is the diagrams corresponding to configs (each
2577 diagrams is a list of corresponding diagrams for all
2578 subprocesses, with None if there is no corresponding diagrams
2579 for a given process).
2580 mapconfigs gives the diagram number for each config.
2581
2582 For s-channels, we need to output one PDG for each subprocess in
2583 the subprocess group, in order to be able to pick the right
2584 one for multiprocesses."""
2585
2586 lines = []
2587
2588 particle_dict = matrix_element.get('processes')[0].get('model').\
2589 get('particle_dict')
2590
2591 s_and_t_channels = []
2592
2593 minvert = min([max([d for d in config if d][0].get_vertex_leg_numbers()) \
2594 for config in configs])
2595
2596
2597 nsubprocs = len(configs[0])
2598
2599 nconfigs = 0
2600
2601 new_pdg = model.get_first_non_pdg()
2602
2603 for iconfig, helas_diags in enumerate(configs):
2604 if any([vert > minvert for vert in
2605 [d for d in helas_diags if d][0].get_vertex_leg_numbers()]):
2606
2607 continue
2608 nconfigs += 1
2609
2610
2611
2612 empty_verts = []
2613 stchannels = []
2614 for h in helas_diags:
2615 if h:
2616
2617
2618 stchannels.append(h.get('amplitudes')[0].\
2619 get_s_and_t_channels(ninitial,model,new_pdg))
2620 else:
2621 stchannels.append((empty_verts, None))
2622
2623
2624 tchannels = [t for s,t in stchannels if t != None][0]
2625
2626
2627 s_and_t_channels.append([[s for s,t in stchannels if t != None][0],
2628 tchannels])
2629
2630
2631 if any([s for s,t in stchannels]):
2632 empty_verts[:] = [None]*max([len(s) for s,t in stchannels])
2633
2634
2635
2636 schannels = zip(*[s for s,t in stchannels])
2637 else:
2638 schannels = []
2639
2640 allchannels = schannels
2641 if len(tchannels) > 1:
2642
2643 allchannels = schannels + tchannels
2644
2645
2646
2647
2648
2649 lines.append("* %d %d " % (nconfigs,
2650 mapconfigs[iconfig]))
2651
2652 for verts in allchannels:
2653 if verts in schannels:
2654 vert = [v for v in verts if v][0]
2655 else:
2656 vert = verts
2657 daughters = [leg.get('number') for leg in vert.get('legs')[:-1]]
2658 last_leg = vert.get('legs')[-1]
2659 line=str(last_leg.get('number'))+" "+str(daughters[0])+" "+str(daughters[1])
2660
2661
2662
2663
2664 if last_leg.get('id') == 21 and 21 not in particle_dict:
2665
2666 mass = 'zero'
2667 width = 'zero'
2668 pow_part = 0
2669 else:
2670 if (last_leg.get('id')!=7):
2671 particle = particle_dict[last_leg.get('id')]
2672
2673 mass = particle.get('mass')
2674
2675 width = particle.get('width')
2676 else :
2677 mass= 'zero'
2678 width= 'zero'
2679
2680 line=line+" "+mass+" "+width+" "
2681
2682 if verts in schannels:
2683 pdgs = []
2684 for v in verts:
2685 if v:
2686 pdgs.append(v.get('legs')[-1].get('id'))
2687 else:
2688 pdgs.append(0)
2689 lines.append(line+" S "+str(last_leg.get('id')))
2690
2691
2692
2693
2694
2695 elif verts in tchannels[:-1]:
2696 lines.append(line+" T "+str(last_leg.get('id')))
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707 lines.append(" * ")
2708
2709 writer.writelines(lines)
2710
2711 return s_and_t_channels
2712
2713
2714
2715
2716
2718 """Class to take care of exporting a set of matrix elements to
2719 MadEvent format."""
2720
2721 matrix_file = "matrix_madevent_v4.inc"
2722
2746
2747
2748
2749
2750
2751
2752
2753
2755 """copy the python file require for the Template"""
2756
2757
2758 cp(_file_path+'/interface/madevent_interface.py',
2759 self.dir_path+'/bin/internal/madevent_interface.py')
2760 cp(_file_path+'/interface/extended_cmd.py',
2761 self.dir_path+'/bin/internal/extended_cmd.py')
2762 cp(_file_path+'/interface/common_run_interface.py',
2763 self.dir_path+'/bin/internal/common_run_interface.py')
2764 cp(_file_path+'/various/misc.py', self.dir_path+'/bin/internal/misc.py')
2765 cp(_file_path+'/iolibs/files.py', self.dir_path+'/bin/internal/files.py')
2766 cp(_file_path+'/iolibs/save_load_object.py',
2767 self.dir_path+'/bin/internal/save_load_object.py')
2768 cp(_file_path+'/iolibs/file_writers.py',
2769 self.dir_path+'/bin/internal/file_writers.py')
2770
2771 cp(_file_path+'../models/check_param_card.py',
2772 self.dir_path+'/bin/internal/check_param_card.py')
2773
2774
2775 cp(_file_path+'/__init__.py', self.dir_path+'/bin/internal/__init__.py')
2776 cp(_file_path+'/various/lhe_parser.py',
2777 self.dir_path+'/bin/internal/lhe_parser.py')
2778 cp(_file_path+'/various/gen_crossxhtml.py',
2779 self.dir_path+'/bin/internal/gen_crossxhtml.py')
2780 cp(_file_path+'/various/banner.py',
2781 self.dir_path+'/bin/internal/banner.py')
2782 cp(_file_path+'/various/cluster.py',
2783 self.dir_path+'/bin/internal/cluster.py')
2784 cp(_file_path+'/various/sum_html.py',
2785 self.dir_path+'/bin/internal/sum_html.py')
2786 cp(_file_path+'/various/combine_runs.py',
2787 self.dir_path+'/bin/internal/combine_runs.py')
2788
2789 cp(_file_path+'/interface/.mg5_logging.conf',
2790 self.dir_path+'/bin/internal/me5_logging.conf')
2791 cp(_file_path+'/interface/coloring_logging.py',
2792 self.dir_path+'/bin/internal/coloring_logging.py')
2793
2794
2795 cp(_file_path+'/various/shower_card.py',
2796 self.dir_path+'/bin/internal/shower_card.py')
2797 cp(_file_path+'/various/FO_analyse_card.py',
2798 self.dir_path+'/bin/internal/FO_analyse_card.py')
2799
2800
2803
2804 super(ProcessExporterFortranME,self).convert_model_to_mg4(model,
2805 wanted_lorentz, wanted_couplings)
2806
2807 IGNORE_PATTERNS = ('*.pyc','*.dat','*.py~')
2808 try:
2809 shutil.rmtree(pjoin(self.dir_path,'bin','internal','ufomodel'))
2810 except OSError as error:
2811 pass
2812 model_path = model.get('modelpath')
2813
2814 shutil.copytree(model_path,
2815 pjoin(self.dir_path,'bin','internal','ufomodel'),
2816 ignore=shutil.ignore_patterns(*IGNORE_PATTERNS))
2817 if hasattr(model, 'restrict_card'):
2818 out_path = pjoin(self.dir_path, 'bin', 'internal','ufomodel',
2819 'restrict_default.dat')
2820 if isinstance(model.restrict_card, check_param_card.ParamCard):
2821 model.restrict_card.write(out_path)
2822 else:
2823 files.cp(model.restrict_card, out_path)
2824
2825
2826
2827
2829 """export the model dependent files"""
2830
2831 super(ProcessExporterFortranME,self).export_model_files(model_path)
2832
2833
2834
2835 text="""
2836 subroutine update_as_param()
2837 call setpara('param_card.dat',.false.)
2838 return
2839 end
2840 """
2841 ff = open(pjoin(self.dir_path, 'Source', 'MODEL', 'couplings.f'),'a')
2842 ff.write(text)
2843 ff.close()
2844
2845
2846 filename = pjoin(self.dir_path,'SubProcesses','symmetry.f')
2847 self.write_symmetry(writers.FortranWriter(filename), v5=False)
2848
2849
2850 filename = pjoin(self.dir_path,'SubProcesses','driver.f')
2851 self.write_driver(writers.FortranWriter(filename), v5=False)
2852
2853
2854 text = open(pjoin(self.dir_path,'Source','setrun.f')).read()
2855 text = text.replace('call setpara(param_card_name)', 'call setpara(param_card_name, .true.)')
2856 fsock = open(pjoin(self.dir_path,'Source','setrun.f'), 'w')
2857 fsock.write(text)
2858 fsock.close()
2859
2860 self.make_model_symbolic_link()
2861
2862
2863
2864
2865
2869 """Generate the Pxxxxx directory for a subprocess in MG4 madevent,
2870 including the necessary matrix.f and various helper files"""
2871
2872 cwd = os.getcwd()
2873 path = pjoin(self.dir_path, 'SubProcesses')
2874
2875
2876 if not self.model:
2877 self.model = matrix_element.get('processes')[0].get('model')
2878
2879
2880
2881
2882
2883 subprocdir = "P%s" % matrix_element.get('processes')[0].shell_string()
2884 try:
2885 os.mkdir(pjoin(path,subprocdir))
2886 except os.error as error:
2887 logger.warning(error.strerror + " " + subprocdir)
2888
2889
2890
2891
2892
2893
2894
2895 logger.info('Creating files in directory %s' % subprocdir)
2896 Ppath = pjoin(path, subprocdir)
2897
2898
2899 (nexternal, ninitial) = matrix_element.get_nexternal_ninitial()
2900
2901
2902 filename = pjoin(Ppath, 'matrix.f')
2903 calls, ncolor = \
2904 self.write_matrix_element_v4(writers.FortranWriter(filename),
2905 matrix_element,
2906 fortran_model)
2907
2908 filename = pjoin(Ppath, 'auto_dsig.f')
2909 self.write_auto_dsig_file(writers.FortranWriter(filename),
2910 matrix_element)
2911
2912 filename = pjoin(Ppath, 'configs.inc')
2913 mapconfigs, (s_and_t_channels, nqcd_list) = self.write_configs_file(\
2914 writers.FortranWriter(filename),
2915 matrix_element)
2916
2917 filename = pjoin(Ppath, 'config_nqcd.inc')
2918 self.write_config_nqcd_file(writers.FortranWriter(filename),
2919 nqcd_list)
2920
2921 filename = pjoin(Ppath, 'config_subproc_map.inc')
2922 self.write_config_subproc_map_file(writers.FortranWriter(filename),
2923 s_and_t_channels)
2924
2925 filename = pjoin(Ppath, 'coloramps.inc')
2926 self.write_coloramps_file(writers.FortranWriter(filename),
2927 mapconfigs,
2928 matrix_element)
2929
2930 filename = pjoin(Ppath, 'get_color.f')
2931 self.write_colors_file(writers.FortranWriter(filename),
2932 matrix_element)
2933
2934 filename = pjoin(Ppath, 'decayBW.inc')
2935 self.write_decayBW_file(writers.FortranWriter(filename),
2936 s_and_t_channels)
2937
2938 filename = pjoin(Ppath, 'dname.mg')
2939 self.write_dname_file(writers.FileWriter(filename),
2940 "P"+matrix_element.get('processes')[0].shell_string())
2941
2942 filename = pjoin(Ppath, 'iproc.dat')
2943 self.write_iproc_file(writers.FortranWriter(filename),
2944 me_number)
2945
2946 filename = pjoin(Ppath, 'leshouche.inc')
2947 self.write_leshouche_file(writers.FortranWriter(filename),
2948 matrix_element)
2949
2950 filename = pjoin(Ppath, 'maxamps.inc')
2951 self.write_maxamps_file(writers.FortranWriter(filename),
2952 len(matrix_element.get('diagrams')),
2953 ncolor,
2954 len(matrix_element.get('processes')),
2955 1)
2956
2957 filename = pjoin(Ppath, 'mg.sym')
2958 self.write_mg_sym_file(writers.FortranWriter(filename),
2959 matrix_element)
2960
2961 filename = pjoin(Ppath, 'ncombs.inc')
2962 self.write_ncombs_file(writers.FortranWriter(filename),
2963 nexternal)
2964
2965 filename = pjoin(Ppath, 'nexternal.inc')
2966 self.write_nexternal_file(writers.FortranWriter(filename),
2967 nexternal, ninitial)
2968
2969 filename = pjoin(Ppath, 'ngraphs.inc')
2970 self.write_ngraphs_file(writers.FortranWriter(filename),
2971 len(mapconfigs))
2972
2973
2974 filename = pjoin(Ppath, 'pmass.inc')
2975 self.write_pmass_file(writers.FortranWriter(filename),
2976 matrix_element)
2977
2978 filename = pjoin(Ppath, 'props.inc')
2979 self.write_props_file(writers.FortranWriter(filename),
2980 matrix_element,
2981 s_and_t_channels)
2982
2983
2984 symmetry, perms, ident_perms = \
2985 diagram_symmetry.find_symmetry(matrix_element)
2986
2987 filename = pjoin(Ppath, 'symswap.inc')
2988 self.write_symswap_file(writers.FortranWriter(filename),
2989 ident_perms)
2990
2991 filename = pjoin(Ppath, 'symfact_orig.dat')
2992 self.write_symfact_file(open(filename, 'w'), symmetry)
2993
2994
2995 filename = pjoin(Ppath, "matrix.ps")
2996 plot = draw.MultiEpsDiagramDrawer(matrix_element.get('base_amplitude').\
2997 get('diagrams'),
2998 filename,
2999 model=matrix_element.get('processes')[0].\
3000 get('model'),
3001 amplitude=True)
3002 logger.info("Generating Feynman diagrams for " + \
3003 matrix_element.get('processes')[0].nice_string())
3004 plot.draw()
3005
3006
3007 ln(self.dir_path + '/Source/genps.inc', self.dir_path + '/SubProcesses', log=False)
3008 ln(self.dir_path + '/Source/maxconfigs.inc', self.dir_path + '/SubProcesses', log=False)
3009
3010 linkfiles = ['addmothers.f',
3011 'cluster.f',
3012 'cluster.inc',
3013 'coupl.inc',
3014 'cuts.f',
3015 'cuts.inc',
3016 'driver.f',
3017 'genps.f',
3018 'genps.inc',
3019 'idenparts.f',
3020 'initcluster.f',
3021 'makefile',
3022 'message.inc',
3023 'myamp.f',
3024 'reweight.f',
3025 'run.inc',
3026 'maxconfigs.inc',
3027 'maxparticles.inc',
3028 'run_config.inc',
3029 'setcuts.f',
3030 'setscales.f',
3031 'sudakov.inc',
3032 'symmetry.f',
3033 'unwgt.f']
3034
3035 for file in linkfiles:
3036 ln('../' + file , cwd=Ppath)
3037
3038
3039 ln(pjoin(Ppath,'nexternal.inc'), pjoin(self.dir_path,'Source'), log=False)
3040 ln(pjoin(Ppath,'leshouche.inc'), pjoin(self.dir_path,'Source'), log=False)
3041 ln(pjoin(Ppath,'maxamps.inc'), pjoin(self.dir_path,'Source'), log=False)
3042
3043
3044
3045
3046 filename = pjoin(path, 'subproc.mg')
3047 files.append_to_file(filename,
3048 self.write_subproc,
3049 subprocdir)
3050
3051
3052
3053
3054
3055 gen_infohtml.make_info_html(self.dir_path)
3056
3057
3058 if not calls:
3059 calls = 0
3060 return calls
3061
3062 - def finalize_v4_directory(self, matrix_elements, history, makejpg = False,
3063 online = False, compiler='gfortran'):
3064 """Finalize ME v4 directory by creating jpeg diagrams, html
3065 pages,proc_card_mg5.dat and madevent.tar.gz."""
3066
3067 modelname = self.opt['model']
3068 if modelname == 'mssm' or modelname.startswith('mssm-'):
3069 param_card = pjoin(self.dir_path, 'Cards','param_card.dat')
3070 mg5_param = pjoin(self.dir_path, 'Source', 'MODEL', 'MG5_param.dat')
3071 check_param_card.convert_to_mg5card(param_card, mg5_param)
3072 check_param_card.check_valid_param_card(mg5_param)
3073
3074
3075 filename = pjoin(self.dir_path,'Source','combine_events.f')
3076 try:
3077 nb_proc =[p.get('id') for me in matrix_elements for m in me.get('matrix_elements') for p in m.get('processes')]
3078 except AttributeError:
3079 nb_proc =[p.get('id') for m in matrix_elements.get('matrix_elements') for p in m.get('processes')]
3080 nb_proc = len(set(nb_proc))
3081 self.write_combine_events(writers.FortranWriter(filename), nb_proc)
3082
3083 filename = pjoin(self.dir_path,'Source','maxconfigs.inc')
3084 self.write_maxconfigs_file(writers.FortranWriter(filename),
3085 matrix_elements)
3086
3087
3088 filename = pjoin(self.dir_path,'Source','maxparticles.inc')
3089 self.write_maxparticles_file(writers.FortranWriter(filename),
3090 matrix_elements)
3091
3092
3093 os.system('touch %s/done' % pjoin(self.dir_path,'SubProcesses'))
3094
3095
3096 self.set_compiler(compiler)
3097
3098 old_pos = os.getcwd()
3099 subpath = pjoin(self.dir_path, 'SubProcesses')
3100
3101 P_dir_list = [proc for proc in os.listdir(subpath)
3102 if os.path.isdir(pjoin(subpath,proc)) and proc[0] == 'P']
3103
3104 devnull = os.open(os.devnull, os.O_RDWR)
3105
3106 if makejpg:
3107 try:
3108 os.remove(pjoin(self.dir_path,'HTML','card.jpg'))
3109 except Exception, error:
3110 pass
3111 logger.info("Generate jpeg diagrams")
3112 for Pdir in P_dir_list:
3113 misc.call([pjoin(self.dir_path, 'bin', 'internal', 'gen_jpeg-pl')],
3114 stdout = devnull, cwd=pjoin(subpath, Pdir))
3115
3116 logger.info("Generate web pages")
3117
3118
3119 misc.call([pjoin(self.dir_path, 'bin', 'internal', 'gen_cardhtml-pl')], \
3120 stdout = devnull,cwd=pjoin(self.dir_path))
3121
3122
3123
3124 obj = gen_infohtml.make_info_html(self.dir_path)
3125
3126 if online:
3127 nb_channel = obj.rep_rule['nb_gen_diag']
3128 open(pjoin(self.dir_path, 'Online'),'w').write(str(nb_channel))
3129
3130
3131 if os.path.isdir(pjoin(self.dir_path,'Cards')):
3132 output_file = pjoin(self.dir_path,'Cards', 'proc_card_mg5.dat')
3133 history.write(output_file)
3134
3135 misc.call([pjoin(self.dir_path, 'bin', 'internal', 'gen_cardhtml-pl')],
3136 stdout = devnull)
3137
3138
3139 if os.path.exists(pjoin(self.dir_path,'SubProcesses', 'subproc.mg')):
3140 if os.path.exists(pjoin(self.dir_path,'madevent.tar.gz')):
3141 os.remove(pjoin(self.dir_path,'madevent.tar.gz'))
3142 misc.call([os.path.join(self.dir_path, 'bin', 'internal', 'make_madevent_tar')],
3143 stdout = devnull, cwd=self.dir_path)
3144
3145 misc.call([pjoin(self.dir_path, 'bin', 'internal', 'gen_cardhtml-pl')],
3146 stdout = devnull)
3147
3148
3149
3150
3151
3152
3153
3156 """Export a matrix element to a matrix.f file in MG4 madevent format"""
3157
3158 if not matrix_element.get('processes') or \
3159 not matrix_element.get('diagrams'):
3160 return 0
3161
3162 if not isinstance(writer, writers.FortranWriter):
3163 raise writers.FortranWriter.FortranWriterError(\
3164 "writer not FortranWriter")
3165
3166
3167
3168 writers.FortranWriter.downcase = False
3169
3170
3171
3172 replace_dict = {'proc_prefix':''}
3173
3174
3175 helas_calls = fortran_model.get_matrix_element_calls(\
3176 matrix_element)
3177
3178 replace_dict['helas_calls'] = "\n".join(helas_calls)
3179
3180
3181
3182 info_lines = self.get_mg5_info_lines()
3183 replace_dict['info_lines'] = info_lines
3184
3185
3186 process_lines = self.get_process_info_lines(matrix_element)
3187 replace_dict['process_lines'] = process_lines
3188
3189
3190 replace_dict['proc_id'] = proc_id
3191
3192
3193 ncomb = matrix_element.get_helicity_combinations()
3194 replace_dict['ncomb'] = ncomb
3195
3196
3197 helicity_lines = self.get_helicity_lines(matrix_element)
3198 replace_dict['helicity_lines'] = helicity_lines
3199
3200
3201 ic_line = self.get_ic_line(matrix_element)
3202 replace_dict['ic_line'] = ic_line
3203
3204
3205
3206 den_factor_line = self.get_den_factor_line(matrix_element)
3207 replace_dict['den_factor_line'] = den_factor_line
3208
3209
3210 ngraphs = matrix_element.get_number_of_amplitudes()
3211 replace_dict['ngraphs'] = ngraphs
3212
3213
3214 ndiags = len(matrix_element.get('diagrams'))
3215 replace_dict['ndiags'] = ndiags
3216
3217
3218 replace_dict['define_iconfigs_lines'] = \
3219 """INTEGER MAPCONFIG(0:LMAXCONFIGS), ICONFIG
3220 COMMON/TO_MCONFIGS/MAPCONFIG, ICONFIG"""
3221
3222 if proc_id:
3223
3224
3225 replace_dict['define_iconfigs_lines'] += \
3226 """\nINTEGER SUBDIAG(MAXSPROC),IB(2)
3227 COMMON/TO_SUB_DIAG/SUBDIAG,IB"""
3228
3229 replace_dict['set_amp2_line'] = "ANS=ANS*AMP2(SUBDIAG(%s))/XTOT" % \
3230 proc_id
3231 else:
3232
3233
3234 replace_dict['set_amp2_line'] = "ANS=ANS*AMP2(MAPCONFIG(ICONFIG))/XTOT"
3235
3236
3237 nwavefuncs = matrix_element.get_number_of_wavefunctions()
3238 replace_dict['nwavefuncs'] = nwavefuncs
3239
3240
3241 ncolor = max(1, len(matrix_element.get('color_basis')))
3242 replace_dict['ncolor'] = ncolor
3243
3244
3245 color_data_lines = self.get_color_data_lines(matrix_element)
3246 replace_dict['color_data_lines'] = "\n".join(color_data_lines)
3247
3248
3249
3250 if not self.model or any([p.get('spin') in [4,5] for p in self.model.get('particles') if p]):
3251 replace_dict['wavefunctionsize'] = 18
3252 else:
3253 replace_dict['wavefunctionsize'] = 6
3254
3255
3256 amp2_lines = self.get_amp2_lines(matrix_element, config_map)
3257 replace_dict['amp2_lines'] = '\n'.join(amp2_lines)
3258
3259
3260 split_orders=matrix_element.get('processes')[0].get('split_orders')
3261 if len(split_orders)>0:
3262 squared_orders, amp_orders = matrix_element.get_split_orders_mapping()
3263 replace_dict['chosen_so_configs']=self.set_chosen_SO_index(
3264 matrix_element.get('processes')[0],squared_orders)
3265 else:
3266
3267
3268
3269 squared_orders = [(2,),]
3270 amp_orders = [((1,),tuple(range(1,ngraphs+1)))]
3271 replace_dict['chosen_so_configs'] = '.TRUE.'
3272
3273 replace_dict['nAmpSplitOrders']=len(amp_orders)
3274 replace_dict['nSqAmpSplitOrders']=len(squared_orders)
3275 replace_dict['split_order_str_list']=str(split_orders)
3276 replace_dict['nSplitOrders']=max(len(split_orders),1)
3277 amp_so = self.get_split_orders_lines(
3278 [amp_order[0] for amp_order in amp_orders],'AMPSPLITORDERS')
3279 sqamp_so = self.get_split_orders_lines(squared_orders,'SQSPLITORDERS')
3280 replace_dict['ampsplitorders']='\n'.join(amp_so)
3281 replace_dict['sqsplitorders']='\n'.join(sqamp_so)
3282
3283
3284 jamp_lines = self.get_JAMP_lines_split_order(\
3285 matrix_element,amp_orders,split_order_names=
3286 split_orders if len(split_orders)>0 else ['ALL_ORDERS'])
3287 replace_dict['jamp_lines'] = '\n'.join(jamp_lines)
3288
3289 file = open(pjoin(_file_path, \
3290 'iolibs/template_files/%s' % self.matrix_file)).read()
3291 file = file % replace_dict
3292
3293
3294 file = file + '\n' + open(pjoin(_file_path, \
3295 'iolibs/template_files/split_orders_helping_functions.inc'))\
3296 .read()%replace_dict
3297
3298 writer.writelines(file)
3299
3300 return len(filter(lambda call: call.find('#') != 0, helas_calls)), ncolor
3301
3302
3303
3304
3306 """Write the auto_dsig.f file for the differential cross section
3307 calculation, includes pdf call information"""
3308
3309 if not matrix_element.get('processes') or \
3310 not matrix_element.get('diagrams'):
3311 return 0
3312
3313 nexternal, ninitial = matrix_element.get_nexternal_ninitial()
3314
3315 if ninitial < 1 or ninitial > 2:
3316 raise writers.FortranWriter.FortranWriterError, \
3317 """Need ninitial = 1 or 2 to write auto_dsig file"""
3318
3319 replace_dict = {}
3320
3321
3322 info_lines = self.get_mg5_info_lines()
3323 replace_dict['info_lines'] = info_lines
3324
3325
3326 process_lines = self.get_process_info_lines(matrix_element)
3327 replace_dict['process_lines'] = process_lines
3328
3329
3330 replace_dict['proc_id'] = proc_id
3331 replace_dict['numproc'] = 1
3332
3333
3334 if ninitial == 1:
3335
3336 dsig_line = "pd(0)*dsiguu"
3337 else:
3338
3339 dsig_line = "pd(0)*conv*dsiguu"
3340
3341 replace_dict['dsig_line'] = dsig_line
3342
3343
3344 pdf_vars, pdf_data, pdf_lines = \
3345 self.get_pdf_lines(matrix_element, ninitial, proc_id != "")
3346 replace_dict['pdf_vars'] = pdf_vars
3347 replace_dict['pdf_data'] = pdf_data
3348 replace_dict['pdf_lines'] = pdf_lines
3349
3350
3351 if proc_id:
3352 replace_dict['numproc'] = int(proc_id)
3353 replace_dict['passcuts_begin'] = ""
3354 replace_dict['passcuts_end'] = ""
3355
3356
3357 replace_dict['define_subdiag_lines'] = \
3358 """\nINTEGER SUBDIAG(MAXSPROC),IB(2)
3359 COMMON/TO_SUB_DIAG/SUBDIAG,IB"""
3360 replace_dict['cutsdone'] = ""
3361 else:
3362 replace_dict['passcuts_begin'] = "IF (PASSCUTS(PP)) THEN"
3363 replace_dict['passcuts_end'] = "ENDIF"
3364 replace_dict['define_subdiag_lines'] = ""
3365 replace_dict['cutsdone'] = " cutsdone=.false.\n cutspassed=.false."
3366
3367 file = open(pjoin(_file_path, \
3368 'iolibs/template_files/auto_dsig_v4.inc')).read()
3369 file = file % replace_dict
3370
3371
3372 writer.writelines(file)
3373
3374
3375
3376
3378 """Write the coloramps.inc file for MadEvent"""
3379
3380 lines = self.get_icolamp_lines(mapconfigs, matrix_element, 1)
3381 lines.insert(0, "logical icolamp(%d,%d,1)" % \
3382 (max(len(matrix_element.get('color_basis').keys()), 1),
3383 len(mapconfigs)))
3384
3385
3386
3387 writer.writelines(lines)
3388
3389 return True
3390
3391
3392
3393
3395 """Write the get_color.f file for MadEvent, which returns color
3396 for all particles used in the matrix element."""
3397
3398 if isinstance(matrix_elements, helas_objects.HelasMatrixElement):
3399 matrix_elements = [matrix_elements]
3400
3401 model = matrix_elements[0].get('processes')[0].get('model')
3402
3403
3404
3405 wf_ids = set(sum([sum([sum([[wf.get_pdg_code(),wf.get_anti_pdg_code()] \
3406 for wf in d.get('wavefunctions')],[]) \
3407 for d in me.get('diagrams')], []) \
3408 for me in matrix_elements], []))
3409
3410 leg_ids = set(sum([sum([sum([[l.get('id'),
3411 model.get_particle(l.get('id')).get_anti_pdg_code()] \
3412 for l in p.get_legs_with_decays()], []) \
3413 for p in me.get('processes')], []) \
3414 for me in matrix_elements], []))
3415 particle_ids = sorted(list(wf_ids.union(leg_ids)))
3416
3417 lines = """function get_color(ipdg)
3418 implicit none
3419 integer get_color, ipdg
3420
3421 if(ipdg.eq.%d)then
3422 get_color=%d
3423 return
3424 """ % (particle_ids[0], model.get_particle(particle_ids[0]).get_color())
3425
3426 for part_id in particle_ids[1:]:
3427 lines += """else if(ipdg.eq.%d)then
3428 get_color=%d
3429 return
3430 """ % (part_id, model.get_particle(part_id).get_color())
3431
3432
3433 lines += """else if(ipdg.eq.%d)then
3434 c This is dummy particle used in multiparticle vertices
3435 get_color=2
3436 return
3437 """ % model.get_first_non_pdg()
3438 lines += """else
3439 write(*,*)'Error: No color given for pdg ',ipdg
3440 get_color=0
3441 return
3442 endif
3443 end
3444 """
3445
3446
3447 writer.writelines(lines)
3448
3449 return True
3450
3451
3452
3453
3455 """Write the config_nqcd.inc with the number of QCD couplings
3456 for each config"""
3457
3458 lines = []
3459 for iconf, n in enumerate(nqcd_list):
3460 lines.append("data nqcd(%d)/%d/" % (iconf+1, n))
3461
3462
3463 writer.writelines(lines)
3464
3465 return True
3466
3467
3468
3469
3471 """Write the maxconfigs.inc file for MadEvent"""
3472
3473 if isinstance(matrix_elements, helas_objects.HelasMultiProcess):
3474 maxconfigs = max([me.get_num_configs() for me in \
3475 matrix_elements.get('matrix_elements')])
3476 else:
3477 maxconfigs = max([me.get_num_configs() for me in matrix_elements])
3478
3479 lines = "integer lmaxconfigs\n"
3480 lines += "parameter(lmaxconfigs=%d)" % maxconfigs
3481
3482
3483 writer.writelines(lines)
3484
3485 return True
3486
3487
3488
3489
3490
3491
3493 """Write a dummy config_subproc.inc file for MadEvent"""
3494
3495 lines = []
3496
3497 for iconfig in range(len(s_and_t_channels)):
3498 lines.append("DATA CONFSUB(1,%d)/1/" % \
3499 (iconfig + 1))
3500
3501
3502 writer.writelines(lines)
3503
3504 return True
3505
3506
3507
3508
3510 """Write the configs.inc file for MadEvent"""
3511
3512
3513 (nexternal, ninitial) = matrix_element.get_nexternal_ninitial()
3514
3515 model = matrix_element.get('processes')[0].get('model')
3516 configs = [(i+1, d) for (i, d) in \
3517 enumerate(matrix_element.get('diagrams'))]
3518 mapconfigs = [c[0] for c in configs]
3519 return mapconfigs, self.write_configs_file_from_diagrams(writer,
3520 [[c[1]] for c in configs],
3521 mapconfigs,
3522 nexternal, ninitial,
3523 model)
3524
3525
3526
3527
3529 """Write the run_configs.inc file for MadEvent"""
3530
3531 path = pjoin(_file_path,'iolibs','template_files','madevent_run_config.inc')
3532 text = open(path).read() % {'chanperjob':'5'}
3533 writer.write(text)
3534 return True
3535
3536
3537
3538
3539
3542 """Write the actual configs.inc file.
3543
3544 configs is the diagrams corresponding to configs (each
3545 diagrams is a list of corresponding diagrams for all
3546 subprocesses, with None if there is no corresponding diagrams
3547 for a given process).
3548 mapconfigs gives the diagram number for each config.
3549
3550 For s-channels, we need to output one PDG for each subprocess in
3551 the subprocess group, in order to be able to pick the right
3552 one for multiprocesses."""
3553
3554 lines = []
3555
3556 s_and_t_channels = []
3557
3558 nqcd_list = []
3559
3560 minvert = min([max([d for d in config if d][0].get_vertex_leg_numbers()) \
3561 for config in configs])
3562
3563
3564 nsubprocs = len(configs[0])
3565
3566 nconfigs = 0
3567
3568 new_pdg = model.get_first_non_pdg()
3569
3570 for iconfig, helas_diags in enumerate(configs):
3571 if any([vert > minvert for vert in
3572 [d for d in helas_diags if d][0].get_vertex_leg_numbers()]):
3573
3574 continue
3575 nconfigs += 1
3576
3577
3578
3579 empty_verts = []
3580 stchannels = []
3581 for h in helas_diags:
3582 if h:
3583
3584
3585 stchannels.append(h.get('amplitudes')[0].\
3586 get_s_and_t_channels(ninitial, model,
3587 new_pdg))
3588 else:
3589 stchannels.append((empty_verts, None))
3590
3591
3592 tchannels = [t for s,t in stchannels if t != None][0]
3593
3594
3595 s_and_t_channels.append([[s for s,t in stchannels if t != None][0],
3596 tchannels])
3597
3598
3599 if any([s for s,t in stchannels]):
3600 empty_verts[:] = [None]*max([len(s) for s,t in stchannels])
3601
3602
3603
3604 schannels = zip(*[s for s,t in stchannels])
3605 else:
3606 schannels = []
3607
3608 allchannels = schannels
3609 if len(tchannels) > 1:
3610
3611 allchannels = schannels + tchannels
3612
3613
3614
3615 lines.append("# Diagram %d" % (mapconfigs[iconfig]))
3616
3617 lines.append("data mapconfig(%d)/%d/" % (nconfigs,
3618 mapconfigs[iconfig]))
3619
3620 nqcd = 0
3621 for h in helas_diags:
3622 if h:
3623 try:
3624 nqcd = h.calculate_orders()['QCD']
3625 except KeyError:
3626 pass
3627 break
3628 else:
3629 continue
3630
3631 nqcd_list.append(nqcd)
3632
3633 for verts in allchannels:
3634 if verts in schannels:
3635 vert = [v for v in verts if v][0]
3636 else:
3637 vert = verts
3638 daughters = [leg.get('number') for leg in vert.get('legs')[:-1]]
3639 last_leg = vert.get('legs')[-1]
3640 lines.append("data (iforest(i,%d,%d),i=1,%d)/%s/" % \
3641 (last_leg.get('number'), nconfigs, len(daughters),
3642 ",".join([str(d) for d in daughters])))
3643 if verts in schannels:
3644 pdgs = []
3645 for v in verts:
3646 if v:
3647 pdgs.append(v.get('legs')[-1].get('id'))
3648 else:
3649 pdgs.append(0)
3650 lines.append("data (sprop(i,%d,%d),i=1,%d)/%s/" % \
3651 (last_leg.get('number'), nconfigs, nsubprocs,
3652 ",".join([str(d) for d in pdgs])))
3653 lines.append("data tprid(%d,%d)/0/" % \
3654 (last_leg.get('number'), nconfigs))
3655 elif verts in tchannels[:-1]:
3656 lines.append("data tprid(%d,%d)/%d/" % \
3657 (last_leg.get('number'), nconfigs,
3658 abs(last_leg.get('id'))))
3659 lines.append("data (sprop(i,%d,%d),i=1,%d)/%s/" % \
3660 (last_leg.get('number'), nconfigs, nsubprocs,
3661 ",".join(['0'] * nsubprocs)))
3662
3663
3664 lines.append("# Number of configs")
3665 lines.append("data mapconfig(0)/%d/" % nconfigs)
3666
3667
3668 writer.writelines(lines)
3669
3670 return s_and_t_channels, nqcd_list
3671
3672
3673
3674
3676 """Write the decayBW.inc file for MadEvent"""
3677
3678 lines = []
3679
3680 booldict = {None: "0", True: "1", False: "2"}
3681
3682 for iconf, config in enumerate(s_and_t_channels):
3683 schannels = config[0]
3684 for vertex in schannels:
3685
3686
3687 leg = vertex.get('legs')[-1]
3688 lines.append("data gForceBW(%d,%d)/%s/" % \
3689 (leg.get('number'), iconf + 1,
3690 booldict[leg.get('onshell')]))
3691
3692
3693 writer.writelines(lines)
3694
3695 return True
3696
3697
3698
3699
3701 """Write the dname.mg file for MG4"""
3702
3703 line = "DIRNAME=%s" % dir_name
3704
3705
3706 writer.write(line + "\n")
3707
3708 return True
3709
3710
3711
3712
3714 """Write the SubProcess/driver.f file for MG4"""
3715
3716 path = pjoin(_file_path,'iolibs','template_files','madevent_driver.f')
3717
3718 if self.model_name == 'mssm' or self.model_name.startswith('mssm-'):
3719 card = 'Source/MODEL/MG5_param.dat'
3720 else:
3721 card = 'param_card.dat'
3722 if v5:
3723 text = open(path).read() % {'param_card_name':card, 'secondparam':''}
3724 else:
3725 text = open(path).read() % {'param_card_name':card,
3726 'secondparam': ',.true.'}
3727 writer.write(text)
3728
3729 return True
3730
3731
3732
3733
3735 """Write the SubProcess/addmothers.f"""
3736
3737 path = pjoin(_file_path,'iolibs','template_files','addmothers.f')
3738
3739 text = open(path).read() % {'iconfig': 'diag_number'}
3740 writer.write(text)
3741
3742 return True
3743
3744
3745
3746
3747
3749 """Write the SubProcess/driver.f file for MG4"""
3750
3751 path = pjoin(_file_path,'iolibs','template_files','madevent_combine_events.f')
3752
3753 if self.model_name == 'mssm' or self.model_name.startswith('mssm-'):
3754 card = 'Source/MODEL/MG5_param.dat'
3755 else:
3756 card = 'param_card.dat'
3757
3758
3759
3760 text = open(path).read() % {'param_card_name':card, 'maxpup':nb_proc+1}
3761
3762 writer.write(text)
3763
3764 return True
3765
3766
3767
3768
3769
3771 """Write the SubProcess/driver.f file for ME"""
3772
3773 path = pjoin(_file_path,'iolibs','template_files','madevent_symmetry.f')
3774
3775 if self.model_name == 'mssm' or self.model_name.startswith('mssm-'):
3776 card = 'Source/MODEL/MG5_param.dat'
3777 else:
3778 card = 'param_card.dat'
3779 text = open(path).read()
3780
3781 if v5:
3782 text = text % {'param_card_name':card, 'setparasecondarg':''}
3783 else:
3784 text = text % {'param_card_name':card, 'setparasecondarg':',.true.'}
3785 writer.write(text)
3786
3787 return True
3788
3789
3790
3791
3792
3793
3794
3796 """Write the iproc.dat file for MG4"""
3797 line = "%d" % (me_number + 1)
3798
3799
3800 for line_to_write in writer.write_line(line):
3801 writer.write(line_to_write)
3802 return True
3803
3804
3805
3806
3808 """Write the mg.sym file for MadEvent."""
3809
3810 lines = []
3811
3812
3813 final_legs = filter(lambda leg: leg.get('state') == True,
3814 matrix_element.get('processes')[0].get_legs_with_decays())
3815
3816 ninitial = len(filter(lambda leg: leg.get('state') == False,
3817 matrix_element.get('processes')[0].get('legs')))
3818
3819 identical_indices = {}
3820
3821
3822 for i, leg in enumerate(final_legs):
3823 if leg.get('id') in identical_indices:
3824 identical_indices[leg.get('id')].append(\
3825 i + ninitial + 1)
3826 else:
3827 identical_indices[leg.get('id')] = [i + ninitial + 1]
3828
3829
3830 for key in identical_indices.keys():
3831 if len(identical_indices[key]) < 2:
3832 del identical_indices[key]
3833
3834
3835 lines.append(str(len(identical_indices.keys())))
3836 for key in identical_indices.keys():
3837 lines.append(str(len(identical_indices[key])))
3838 for number in identical_indices[key]:
3839 lines.append(str(number))
3840
3841
3842 writer.writelines(lines)
3843
3844 return True
3845
3846
3847
3848
3850 """Write the mg.sym file for MadEvent."""
3851
3852 lines = "0"
3853
3854
3855 writer.writelines(lines)
3856
3857 return True
3858
3859
3860
3861
3863 """Write the ncombs.inc file for MadEvent."""
3864
3865
3866 file = " integer n_max_cl\n"
3867 file = file + "parameter (n_max_cl=%d)" % (2 ** nexternal)
3868
3869
3870 writer.writelines(file)
3871
3872 return True
3873
3874
3875
3876
3878 """Write the processes.dat file with info about the subprocesses
3879 in this group."""
3880
3881 lines = []
3882
3883 for ime, me in \
3884 enumerate(subproc_group.get('matrix_elements')):
3885 lines.append("%s %s" % (str(ime+1) + " " * (7-len(str(ime+1))),
3886 ",".join(p.base_string() for p in \
3887 me.get('processes'))))
3888 if me.get('has_mirror_process'):
3889 mirror_procs = [copy.copy(p) for p in me.get('processes')]
3890 for proc in mirror_procs:
3891 legs = copy.copy(proc.get('legs_with_decays'))
3892 legs.insert(0, legs.pop(1))
3893 proc.set("legs_with_decays", legs)
3894 lines.append("mirror %s" % ",".join(p.base_string() for p in \
3895 mirror_procs))
3896 else:
3897 lines.append("mirror none")
3898
3899
3900 writer.write("\n".join(lines))
3901
3902 return True
3903
3904
3905
3906
3908 """Write the file symswap.inc for MG4 by comparing diagrams using
3909 the internal matrix element value functionality."""
3910
3911 lines = []
3912
3913
3914
3915 for iperm, perm in enumerate(ident_perms):
3916 lines.append("data (isym(i,%d),i=1,nexternal)/%s/" % \
3917 (iperm+1, ",".join([str(i+1) for i in perm])))
3918 lines.append("data nsym/%d/" % len(ident_perms))
3919
3920
3921 writer.writelines(lines)
3922
3923 return True
3924
3925
3926
3927
3929 """Write the files symfact.dat for MG4 by comparing diagrams using
3930 the internal matrix element value functionality."""
3931
3932 pos = max(2, int(math.ceil(math.log10(len(symmetry)))))
3933 form = "%"+str(pos)+"r %"+str(pos+1)+"r"
3934
3935
3936 lines = [ form %(i+1, s) for i,s in enumerate(symmetry) if s != 0]
3937
3938 writer.write('\n'.join(lines))
3939 writer.write('\n')
3940
3941 return True
3942
3943
3944
3945
3947 """Write the symperms.inc file for subprocess group, used for
3948 symmetric configurations"""
3949
3950 lines = []
3951 for iperm, perm in enumerate(perms):
3952 lines.append("data (perms(i,%d),i=1,nexternal)/%s/" % \
3953 (iperm+1, ",".join([str(i+1) for i in perm])))
3954
3955
3956 writer.writelines(lines)
3957
3958 return True
3959
3960
3961
3962
3964 """Append this subprocess to the subproc.mg file for MG4"""
3965
3966
3967 writer.write(subprocdir + "\n")
3968
3969 return True
3970
3971
3972
3973
3975 """Class to take care of exporting a set of matrix elements to
3976 MadEvent subprocess group format."""
3977
3978 matrix_file = "matrix_madevent_group_v4.inc"
3979
3980
3981
3982
3986 """Generate the Pn directory for a subprocess group in MadEvent,
3987 including the necessary matrix_N.f files, configs.inc and various
3988 other helper files"""
3989
3990 assert isinstance(subproc_group, group_subprocs.SubProcessGroup), \
3991 "subproc_group object not SubProcessGroup"
3992
3993 if not self.model:
3994 self.model = subproc_group.get('matrix_elements')[0].\
3995 get('processes')[0].get('model')
3996
3997 cwd = os.getcwd()
3998 path = pjoin(self.dir_path, 'SubProcesses')
3999
4000 os.chdir(path)
4001 pathdir = os.getcwd()
4002
4003
4004 subprocdir = "P%d_%s" % (subproc_group.get('number'),
4005 subproc_group.get('name'))
4006 try:
4007 os.mkdir(subprocdir)
4008 except os.error as error:
4009 logger.warning(error.strerror + " " + subprocdir)
4010
4011 try:
4012 os.chdir(subprocdir)
4013 except os.error:
4014 logger.error('Could not cd to directory %s' % subprocdir)
4015 return 0
4016
4017 logger.info('Creating files in directory %s' % subprocdir)
4018
4019
4020
4021
4022 maxamps = 0
4023 maxflows = 0
4024 tot_calls = 0
4025
4026 matrix_elements = subproc_group.get('matrix_elements')
4027
4028 for ime, matrix_element in \
4029 enumerate(matrix_elements):
4030 filename = 'matrix%d.f' % (ime+1)
4031 calls, ncolor = \
4032 self.write_matrix_element_v4(writers.FortranWriter(filename),
4033 matrix_element,
4034 fortran_model,
4035 str(ime+1),
4036 subproc_group.get('diagram_maps')[\
4037 ime])
4038
4039 filename = 'auto_dsig%d.f' % (ime+1)
4040 self.write_auto_dsig_file(writers.FortranWriter(filename),
4041 matrix_element,
4042 str(ime+1))
4043
4044
4045 tot_calls += int(calls)
4046 maxflows = max(maxflows, ncolor)
4047 maxamps = max(maxamps, len(matrix_element.get('diagrams')))
4048
4049
4050 filename = "matrix%d.ps" % (ime+1)
4051 plot = draw.MultiEpsDiagramDrawer(matrix_element.get('base_amplitude').\
4052 get('diagrams'),
4053 filename,
4054 model = \
4055 matrix_element.get('processes')[0].\
4056 get('model'),
4057 amplitude=True)
4058 logger.info("Generating Feynman diagrams for " + \
4059 matrix_element.get('processes')[0].nice_string())
4060 plot.draw()
4061
4062
4063 (nexternal, ninitial) = matrix_element.get_nexternal_ninitial()
4064
4065
4066
4067
4068
4069 subproc_diagrams_for_config = subproc_group.get('diagrams_for_configs')
4070
4071 filename = 'auto_dsig.f'
4072 self.write_super_auto_dsig_file(writers.FortranWriter(filename),
4073 subproc_group)
4074
4075 filename = 'coloramps.inc'
4076 self.write_coloramps_file(writers.FortranWriter(filename),
4077 subproc_diagrams_for_config,
4078 maxflows,
4079 matrix_elements)
4080
4081 filename = 'get_color.f'
4082 self.write_colors_file(writers.FortranWriter(filename),
4083 matrix_elements)
4084
4085 filename = 'config_subproc_map.inc'
4086 self.write_config_subproc_map_file(writers.FortranWriter(filename),
4087 subproc_diagrams_for_config)
4088
4089 filename = 'configs.inc'
4090 nconfigs, (s_and_t_channels, nqcd_list) = self.write_configs_file(\
4091 writers.FortranWriter(filename),
4092 subproc_group,
4093 subproc_diagrams_for_config)
4094
4095 filename = 'config_nqcd.inc'
4096 self.write_config_nqcd_file(writers.FortranWriter(filename),
4097 nqcd_list)
4098
4099 filename = 'decayBW.inc'
4100 self.write_decayBW_file(writers.FortranWriter(filename),
4101 s_and_t_channels)
4102
4103 filename = 'dname.mg'
4104 self.write_dname_file(writers.FortranWriter(filename),
4105 subprocdir)
4106
4107 filename = 'iproc.dat'
4108 self.write_iproc_file(writers.FortranWriter(filename),
4109 group_number)
4110
4111 filename = 'leshouche.inc'
4112 self.write_leshouche_file(writers.FortranWriter(filename),
4113 subproc_group)
4114
4115 filename = 'maxamps.inc'
4116 self.write_maxamps_file(writers.FortranWriter(filename),
4117 maxamps,
4118 maxflows,
4119 max([len(me.get('processes')) for me in \
4120 matrix_elements]),
4121 len(matrix_elements))
4122
4123
4124 filename = 'mg.sym'
4125 self.write_default_mg_sym_file(writers.FortranWriter(filename))
4126
4127 filename = 'mirrorprocs.inc'
4128 self.write_mirrorprocs(writers.FortranWriter(filename),
4129 subproc_group)
4130
4131 filename = 'ncombs.inc'
4132 self.write_ncombs_file(writers.FortranWriter(filename),
4133 nexternal)
4134
4135 filename = 'nexternal.inc'
4136 self.write_nexternal_file(writers.FortranWriter(filename),
4137 nexternal, ninitial)
4138
4139 filename = 'ngraphs.inc'
4140 self.write_ngraphs_file(writers.FortranWriter(filename),
4141 nconfigs)
4142
4143 filename = 'pmass.inc'
4144 self.write_pmass_file(writers.FortranWriter(filename),
4145 matrix_element)
4146
4147 filename = 'props.inc'
4148 self.write_props_file(writers.FortranWriter(filename),
4149 matrix_element,
4150 s_and_t_channels)
4151
4152 filename = 'processes.dat'
4153 files.write_to_file(filename,
4154 self.write_processes_file,
4155 subproc_group)
4156
4157
4158 symmetry, perms, ident_perms = \
4159 diagram_symmetry.find_symmetry(subproc_group)
4160
4161 filename = 'symswap.inc'
4162 self.write_symswap_file(writers.FortranWriter(filename),
4163 ident_perms)
4164
4165 filename = 'symfact_orig.dat'
4166 self.write_symfact_file(open(filename, 'w'), symmetry)
4167
4168 filename = 'symperms.inc'
4169 self.write_symperms_file(writers.FortranWriter(filename),
4170 perms)
4171
4172
4173
4174
4175
4176 ln(self.dir_path + '/Source/genps.inc', self.dir_path + '/SubProcesses', log=False)
4177 ln(self.dir_path + '/Source/maxconfigs.inc', self.dir_path + '/SubProcesses', log=False)
4178
4179 linkfiles = ['addmothers.f',
4180 'cluster.f',
4181 'cluster.inc',
4182 'coupl.inc',
4183 'cuts.f',
4184 'cuts.inc',
4185 'driver.f',
4186 'genps.f',
4187 'genps.inc',
4188 'idenparts.f',
4189 'initcluster.f',
4190 'makefile',
4191 'message.inc',
4192 'myamp.f',
4193 'reweight.f',
4194 'run.inc',
4195 'maxconfigs.inc',
4196 'maxparticles.inc',
4197 'run_config.inc',
4198 'setcuts.f',
4199 'setscales.f',
4200 'sudakov.inc',
4201 'symmetry.f',
4202 'unwgt.f']
4203
4204 for file in linkfiles:
4205 ln('../' + file , '.')
4206
4207
4208 ln('nexternal.inc', '../../Source', log=False)
4209 ln('leshouche.inc', '../../Source', log=False)
4210 ln('maxamps.inc', '../../Source', log=False)
4211
4212
4213 os.chdir(pathdir)
4214
4215
4216 filename = 'subproc.mg'
4217 files.append_to_file(filename,
4218 self.write_subproc,
4219 subprocdir)
4220
4221
4222 gen_infohtml.make_info_html(os.path.pardir)
4223
4224
4225 os.chdir(cwd)
4226
4227 if not tot_calls:
4228 tot_calls = 0
4229 return tot_calls
4230
4231
4232
4233
4235 """Write the auto_dsig.f file selecting between the subprocesses
4236 in subprocess group mode"""
4237
4238 replace_dict = {}
4239
4240
4241 info_lines = self.get_mg5_info_lines()
4242 replace_dict['info_lines'] = info_lines
4243
4244 matrix_elements = subproc_group.get('matrix_elements')
4245
4246
4247 process_lines = '\n'.join([self.get_process_info_lines(me) for me in \
4248 matrix_elements])
4249 replace_dict['process_lines'] = process_lines
4250
4251 nexternal, ninitial = matrix_elements[0].get_nexternal_ninitial()
4252 replace_dict['nexternal'] = nexternal
4253
4254 replace_dict['nsprocs'] = 2*len(matrix_elements)
4255
4256
4257 dsig_def_line = "DOUBLE PRECISION " + \
4258 ",".join(["DSIG%d" % (iproc + 1) for iproc in \
4259 range(len(matrix_elements))])
4260 replace_dict["dsig_def_line"] = dsig_def_line
4261
4262
4263 call_dsig_proc_lines = []
4264 for iproc in range(len(matrix_elements)):
4265 call_dsig_proc_lines.append(\
4266 "IF(IPROC.EQ.%(num)d) DSIGPROC=DSIG%(num)d(P1,WGT,IMODE) ! %(proc)s" % \
4267 {"num": iproc + 1,
4268 "proc": matrix_elements[iproc].get('processes')[0].base_string()})
4269 replace_dict['call_dsig_proc_lines'] = "\n".join(call_dsig_proc_lines)
4270
4271 file = open(pjoin(_file_path, \
4272 'iolibs/template_files/super_auto_dsig_group_v4.inc')).read()
4273 file = file % replace_dict
4274
4275
4276 writer.writelines(file)
4277
4278
4279
4280
4282 """Write the mirrorprocs.inc file determining which processes have
4283 IS mirror process in subprocess group mode."""
4284
4285 lines = []
4286 bool_dict = {True: '.true.', False: '.false.'}
4287 matrix_elements = subproc_group.get('matrix_elements')
4288 lines.append("DATA (MIRRORPROCS(I),I=1,%d)/%s/" % \
4289 (len(matrix_elements),
4290 ",".join([bool_dict[me.get('has_mirror_process')] for \
4291 me in matrix_elements])))
4292
4293 writer.writelines(lines)
4294
4295
4296
4297
4299 """Write the SubProcess/addmothers.f"""
4300
4301 path = pjoin(_file_path,'iolibs','template_files','addmothers.f')
4302
4303 text = open(path).read() % {'iconfig': 'lconfig'}
4304 writer.write(text)
4305
4306 return True
4307
4308
4309
4310
4311
4314 """Write the coloramps.inc file for MadEvent in Subprocess group mode"""
4315
4316
4317
4318
4319 lines = []
4320
4321 subproc_to_confdiag = {}
4322 for config in diagrams_for_config:
4323 for subproc, diag in enumerate(config):
4324 try:
4325 subproc_to_confdiag[subproc].append(diag)
4326 except KeyError:
4327 subproc_to_confdiag[subproc] = [diag]
4328
4329 for subproc in sorted(subproc_to_confdiag.keys()):
4330 lines.extend(self.get_icolamp_lines(subproc_to_confdiag[subproc],
4331 matrix_elements[subproc],
4332 subproc + 1))
4333
4334 lines.insert(0, "logical icolamp(%d,%d,%d)" % \
4335 (maxflows,
4336 len(diagrams_for_config),
4337 len(matrix_elements)))
4338
4339
4340 writer.writelines(lines)
4341
4342 return True
4343
4344
4345
4346
4348 """Write the config_subproc_map.inc file for subprocess groups"""
4349
4350 lines = []
4351
4352 iconfig = 0
4353 for config in config_subproc_map:
4354 if set(config) == set([0]):
4355 continue
4356 lines.append("DATA (CONFSUB(i,%d),i=1,%d)/%s/" % \
4357 (iconfig + 1, len(config),
4358 ",".join([str(i) for i in config])))
4359 iconfig += 1
4360
4361 writer.writelines(lines)
4362
4363 return True
4364
4365
4366
4367
4369 """Write the configs.inc file with topology information for a
4370 subprocess group. Use the first subprocess with a diagram for each
4371 configuration."""
4372
4373 matrix_elements = subproc_group.get('matrix_elements')
4374 model = matrix_elements[0].get('processes')[0].get('model')
4375
4376 diagrams = []
4377 config_numbers = []
4378 for iconfig, config in enumerate(diagrams_for_config):
4379
4380 if set(config) == set([0]):
4381 continue
4382 subproc_diags = []
4383 for s,d in enumerate(config):
4384 if d:
4385 subproc_diags.append(matrix_elements[s].\
4386 get('diagrams')[d-1])
4387 else:
4388 subproc_diags.append(None)
4389 diagrams.append(subproc_diags)
4390 config_numbers.append(iconfig + 1)
4391
4392
4393 (nexternal, ninitial) = subproc_group.get_nexternal_ninitial()
4394
4395 return len(diagrams), \
4396 self.write_configs_file_from_diagrams(writer, diagrams,
4397 config_numbers,
4398 nexternal, ninitial,
4399 model)
4400
4401
4402
4403
4405 """Write the run_configs.inc file for MadEvent"""
4406
4407 path = pjoin(_file_path,'iolibs','template_files','madevent_run_config.inc')
4408 text = open(path).read() % {'chanperjob':'2'}
4409 writer.write(text)
4410 return True
4411
4412
4413
4414
4415
4417 """Write the leshouche.inc file for MG4"""
4418
4419 all_lines = []
4420
4421 for iproc, matrix_element in \
4422 enumerate(subproc_group.get('matrix_elements')):
4423 all_lines.extend(self.get_leshouche_lines(matrix_element,
4424 iproc))
4425
4426
4427 writer.writelines(all_lines)
4428
4429 return True
4430
4431
4432
4433
4434 python_to_fortran = lambda x: parsers.UFOExpressionParserFortran().parse(x)
4435
4437 """ A converter of the UFO-MG5 Model to the MG4 format """
4438
4439
4440
4441
4442
4443 PS_dependent_key = ['aS','MU_R']
4444 mp_complex_format = 'complex*32'
4445 mp_real_format = 'real*16'
4446
4447
4448
4449 mp_prefix = check_param_card.ParamCard.mp_prefix
4450
4451 - def __init__(self, model, output_path, opt=None):
4452 """ initialization of the objects """
4453
4454 self.model = model
4455 self.model_name = model['name']
4456 self.dir_path = output_path
4457 if opt:
4458 self.opt = opt
4459 else:
4460 self.opt = {'complex_mass': False, 'export_format': 'madevent', 'mp':True}
4461
4462 self.coups_dep = []
4463 self.coups_indep = []
4464 self.params_dep = []
4465 self.params_indep = []
4466 self.params_ext = []
4467 self.p_to_f = parsers.UFOExpressionParserFortran()
4468 self.mp_p_to_f = parsers.UFOExpressionParserMPFortran()
4469
4471 """modify the parameter if some of them are identical up to the case"""
4472
4473 lower_dict={}
4474 duplicate = set()
4475 keys = self.model['parameters'].keys()
4476 for key in keys:
4477 for param in self.model['parameters'][key]:
4478 lower_name = param.name.lower()
4479 if not lower_name:
4480 continue
4481 try:
4482 lower_dict[lower_name].append(param)
4483 except KeyError,error:
4484 lower_dict[lower_name] = [param]
4485 else:
4486 duplicate.add(lower_name)
4487 logger.debug('%s is define both as lower case and upper case.'
4488 % lower_name)
4489 if not duplicate:
4490 return
4491
4492 re_expr = r'''\b(%s)\b'''
4493 to_change = []
4494 change={}
4495 for value in duplicate:
4496 for i, var in enumerate(lower_dict[value][1:]):
4497 to_change.append(var.name)
4498 change[var.name] = '%s__%s' %( var.name.lower(), i+2)
4499 var.name = '%s__%s' %( var.name.lower(), i+2)
4500
4501 replace = lambda match_pattern: change[match_pattern.groups()[0]]
4502 rep_pattern = re.compile(re_expr % '|'.join(to_change))
4503
4504
4505 for key in keys:
4506 if key == ('external',):
4507 continue
4508 for param in self.model['parameters'][key]:
4509 param.expr = rep_pattern.sub(replace, param.expr)
4510
4511
4512 for key in self.model['couplings'].keys():
4513 for coup in self.model['couplings'][key]:
4514 coup.expr = rep_pattern.sub(replace, coup.expr)
4515
4516
4517 for part in self.model['particles']:
4518 if str(part.get('mass')) in to_change:
4519 part.set('mass', rep_pattern.sub(replace, str(part.get('mass'))))
4520 if str(part.get('width')) in to_change:
4521 part.set('width', rep_pattern.sub(replace, str(part.get('width'))))
4522
4524 """modify the couplings to fit with MG4 convention """
4525
4526
4527 keys = self.model['parameters'].keys()
4528 keys.sort(key=len)
4529 for key in keys:
4530 to_add = [o for o in self.model['parameters'][key] if o.name]
4531
4532 if key == ('external',):
4533 self.params_ext += to_add
4534 elif any([(k in key) for k in self.PS_dependent_key]):
4535 self.params_dep += to_add
4536 else:
4537 self.params_indep += to_add
4538
4539 keys = self.model['couplings'].keys()
4540 keys.sort(key=len)
4541 for key, coup_list in self.model['couplings'].items():
4542 if any([(k in key) for k in self.PS_dependent_key]):
4543 self.coups_dep += [c for c in coup_list if
4544 (not wanted_couplings or c.name in \
4545 wanted_couplings)]
4546 else:
4547 self.coups_indep += [c for c in coup_list if
4548 (not wanted_couplings or c.name in \
4549 wanted_couplings)]
4550
4551
4552
4553 if 'G' in self.params_dep:
4554 index = self.params_dep.index('G')
4555 G = self.params_dep.pop(index)
4556
4557
4558
4559
4560 if 'aS' not in self.params_ext:
4561 logger.critical('aS not define as external parameter adding it!')
4562
4563 self.params_indep.append( base_objects. ModelVariable('aS', '0.138','real'))
4564 self.params_indep.append( base_objects. ModelVariable('G', '4.1643','real'))
4565 - def build(self, wanted_couplings = [], full=True):
4575
4576
4577 - def open(self, name, comment='c', format='default'):
4578 """ Open the file name in the correct directory and with a valid
4579 header."""
4580
4581 file_path = pjoin(self.dir_path, name)
4582
4583 if format == 'fortran':
4584 fsock = writers.FortranWriter(file_path, 'w')
4585 else:
4586 fsock = open(file_path, 'w')
4587
4588 file.writelines(fsock, comment * 77 + '\n')
4589 file.writelines(fsock,'%(comment)s written by the UFO converter\n' % \
4590 {'comment': comment + (6 - len(comment)) * ' '})
4591 file.writelines(fsock, comment * 77 + '\n\n')
4592 return fsock
4593
4594
4628
4629
4630
4631
4632
4634 """Copy the standard files for the fortran model."""
4635
4636
4637
4638 file_to_link = ['formats.inc','printout.f', \
4639 'rw_para.f', 'testprog.f']
4640
4641 for filename in file_to_link:
4642 cp( MG5DIR + '/models/template_files/fortran/' + filename, \
4643 self.dir_path)
4644
4645 file = open(os.path.join(MG5DIR,\
4646 'models/template_files/fortran/rw_para.f')).read()
4647
4648 includes=["include \'coupl.inc\'","include \'input.inc\'"]
4649 if self.opt['mp']:
4650 includes.extend(["include \'mp_coupl.inc\'","include \'mp_input.inc\'"])
4651
4652
4653 if self.opt['export_format'] in ['madloop','madloop_optimized']:
4654 load_card = 'call LHA_loadcard(param_name,npara,param,value)'
4655 lha_read_filename='lha_read_mp.f'
4656 elif self.opt['export_format'].startswith('standalone') or self.opt['export_format'] in ['madweight']:
4657 load_card = 'call LHA_loadcard(param_name,npara,param,value)'
4658 lha_read_filename='lha_read.f'
4659 else:
4660 load_card = ''
4661 lha_read_filename='lha_read.f'
4662 cp( MG5DIR + '/models/template_files/fortran/' + lha_read_filename, \
4663 os.path.join(self.dir_path,'lha_read.f'))
4664
4665 file=file%{'includes':'\n '.join(includes),
4666 'load_card':load_card}
4667 writer=open(os.path.join(self.dir_path,'rw_para.f'),'w')
4668 writer.writelines(file)
4669 writer.close()
4670
4671 if self.opt['export_format'] in ['madevent', 'FKS5_default', 'FKS5_optimized']:
4672 cp( MG5DIR + '/models/template_files/fortran/makefile_madevent',
4673 self.dir_path + '/makefile')
4674 if self.opt['export_format'] in ['FKS5_default', 'FKS5_optimized']:
4675 path = pjoin(self.dir_path, 'makefile')
4676 text = open(path).read()
4677 text = text.replace('madevent','aMCatNLO')
4678 open(path, 'w').writelines(text)
4679 elif self.opt['export_format'] in ['standalone', 'standalone_msP','standalone_msF',
4680 'madloop','madloop_optimized', 'standalone_rw', 'madweight']:
4681 cp( MG5DIR + '/models/template_files/fortran/makefile_standalone',
4682 self.dir_path + '/makefile')
4683 else:
4684 raise MadGraph5Error('Unknown format')
4685
4687 """ write coupling.inc """
4688
4689 fsock = self.open('coupl.inc', format='fortran')
4690 if self.opt['mp']:
4691 mp_fsock = self.open('mp_coupl.inc', format='fortran')
4692 mp_fsock_same_name = self.open('mp_coupl_same_name.inc',\
4693 format='fortran')
4694
4695
4696 header = """double precision G
4697 common/strong/ G
4698
4699 double complex gal(2)
4700 common/weak/ gal
4701
4702 double precision MU_R
4703 common/rscale/ MU_R
4704
4705 """
4706
4707 header = header+"""double precision Nf
4708 parameter(Nf=%d)
4709 """ % self.model.get_nflav()
4710
4711 fsock.writelines(header)
4712
4713 if self.opt['mp']:
4714 header = """%(real_mp_format)s %(mp_prefix)sG
4715 common/MP_strong/ %(mp_prefix)sG
4716
4717 %(complex_mp_format)s %(mp_prefix)sgal(2)
4718 common/MP_weak/ %(mp_prefix)sgal
4719
4720 %(complex_mp_format)s %(mp_prefix)sMU_R
4721 common/MP_rscale/ %(mp_prefix)sMU_R
4722 """
4723
4724 mp_fsock.writelines(header%{'real_mp_format':self.mp_real_format,
4725 'complex_mp_format':self.mp_complex_format,
4726 'mp_prefix':self.mp_prefix})
4727 mp_fsock_same_name.writelines(header%{'real_mp_format':self.mp_real_format,
4728 'complex_mp_format':self.mp_complex_format,
4729 'mp_prefix':''})
4730
4731
4732 masses = set()
4733 widths = set()
4734 if self.opt['complex_mass']:
4735 complex_mass = set()
4736
4737 for particle in self.model.get('particles'):
4738
4739 one_mass = particle.get('mass')
4740 if one_mass.lower() != 'zero':
4741 masses.add(one_mass)
4742
4743
4744 one_width = particle.get('width')
4745 if one_width.lower() != 'zero':
4746 widths.add(one_width)
4747 if self.opt['complex_mass'] and one_mass.lower() != 'zero':
4748 complex_mass.add('CMASS_%s' % one_mass)
4749
4750 if masses:
4751 fsock.writelines('double precision '+','.join(masses)+'\n')
4752 fsock.writelines('common/masses/ '+','.join(masses)+'\n\n')
4753 if self.opt['mp']:
4754 mp_fsock_same_name.writelines(self.mp_real_format+' '+\
4755 ','.join(masses)+'\n')
4756 mp_fsock_same_name.writelines('common/MP_masses/ '+\
4757 ','.join(masses)+'\n\n')
4758 mp_fsock.writelines(self.mp_real_format+' '+','.join([\
4759 self.mp_prefix+m for m in masses])+'\n')
4760 mp_fsock.writelines('common/MP_masses/ '+\
4761 ','.join([self.mp_prefix+m for m in masses])+'\n\n')
4762
4763 if widths:
4764 fsock.writelines('double precision '+','.join(widths)+'\n')
4765 fsock.writelines('common/widths/ '+','.join(widths)+'\n\n')
4766 if self.opt['mp']:
4767 mp_fsock_same_name.writelines(self.mp_real_format+' '+\
4768 ','.join(widths)+'\n')
4769 mp_fsock_same_name.writelines('common/MP_widths/ '+\
4770 ','.join(widths)+'\n\n')
4771 mp_fsock.writelines(self.mp_real_format+' '+','.join([\
4772 self.mp_prefix+w for w in widths])+'\n')
4773 mp_fsock.writelines('common/MP_widths/ '+\
4774 ','.join([self.mp_prefix+w for w in widths])+'\n\n')
4775
4776
4777 coupling_list = [coupl.name for coupl in self.coups_dep + self.coups_indep]
4778 fsock.writelines('double complex '+', '.join(coupling_list)+'\n')
4779 fsock.writelines('common/couplings/ '+', '.join(coupling_list)+'\n')
4780 if self.opt['mp']:
4781 mp_fsock_same_name.writelines(self.mp_complex_format+' '+\
4782 ','.join(coupling_list)+'\n')
4783 mp_fsock_same_name.writelines('common/MP_couplings/ '+\
4784 ','.join(coupling_list)+'\n\n')
4785 mp_fsock.writelines(self.mp_complex_format+' '+','.join([\
4786 self.mp_prefix+c for c in coupling_list])+'\n')
4787 mp_fsock.writelines('common/MP_couplings/ '+\
4788 ','.join([self.mp_prefix+c for c in coupling_list])+'\n\n')
4789
4790
4791 if self.opt['complex_mass'] and complex_mass:
4792 fsock.writelines('double complex '+', '.join(complex_mass)+'\n')
4793 fsock.writelines('common/complex_mass/ '+', '.join(complex_mass)+'\n')
4794 if self.opt['mp']:
4795 mp_fsock_same_name.writelines(self.mp_complex_format+' '+\
4796 ','.join(complex_mass)+'\n')
4797 mp_fsock_same_name.writelines('common/MP_complex_mass/ '+\
4798 ','.join(complex_mass)+'\n\n')
4799 mp_fsock.writelines(self.mp_complex_format+' '+','.join([\
4800 self.mp_prefix+cm for cm in complex_mass])+'\n')
4801 mp_fsock.writelines('common/MP_complex_mass/ '+\
4802 ','.join([self.mp_prefix+cm for cm in complex_mass])+'\n\n')
4803
4805 """ write the file coupl_write.inc """
4806
4807 fsock = self.open('coupl_write.inc', format='fortran')
4808
4809 fsock.writelines("""write(*,*) ' Couplings of %s'
4810 write(*,*) ' ---------------------------------'
4811 write(*,*) ' '""" % self.model_name)
4812 def format(coupl):
4813 return 'write(*,2) \'%(name)s = \', %(name)s' % {'name': coupl.name}
4814
4815
4816 lines = [format(coupl) for coupl in self.coups_dep + self.coups_indep]
4817 fsock.writelines('\n'.join(lines))
4818
4819
4866
4868 """ create intparam_definition.inc setting the internal parameters.
4869 Output the double precision and/or the multiple precision parameters
4870 depending on the parameters dp and mp. If mp only, then the file names
4871 get the 'mp_' prefix.
4872 """
4873
4874 fsock = self.open('%sintparam_definition.inc'%
4875 ('mp_' if mp and not dp else ''), format='fortran')
4876
4877 fsock.write_comments(\
4878 "Parameters that should not be recomputed event by event.\n")
4879 fsock.writelines("if(readlha) then\n")
4880 if dp:
4881 fsock.writelines("G = 2 * DSQRT(AS*PI) ! for the first init\n")
4882 if mp:
4883 fsock.writelines("MP__G = 2 * SQRT(MP__AS*MP__PI) ! for the first init\n")
4884 for param in self.params_indep:
4885 if param.name == 'ZERO':
4886 continue
4887 if dp:
4888 fsock.writelines("%s = %s\n" % (param.name,
4889 self.p_to_f.parse(param.expr)))
4890 if mp:
4891 fsock.writelines("%s%s = %s\n" % (self.mp_prefix,param.name,
4892 self.mp_p_to_f.parse(param.expr)))
4893
4894 fsock.writelines('endif')
4895
4896 fsock.write_comments('\nParameters that should be recomputed at an event by even basis.\n')
4897 if dp:
4898 fsock.writelines("aS = G**2/4/pi\n")
4899 if mp:
4900 fsock.writelines("MP__aS = MP__G**2/4/MP__PI\n")
4901 for param in self.params_dep:
4902 if dp:
4903 fsock.writelines("%s = %s\n" % (param.name,
4904 self.p_to_f.parse(param.expr)))
4905 elif mp:
4906 fsock.writelines("%s%s = %s\n" % (self.mp_prefix,param.name,
4907 self.mp_p_to_f.parse(param.expr)))
4908
4909 fsock.write_comments("\nDefinition of the EW coupling used in the write out of aqed\n")
4910 if ('aEWM1',) in self.model['parameters']:
4911 if dp:
4912 fsock.writelines(""" gal(1) = 3.5449077018110318 / DSQRT(aEWM1)
4913 gal(2) = 1d0
4914 """)
4915 elif mp:
4916 fsock.writelines(""" %(mp_prefix)sgal(1) = 2 * SQRT(MP__PI/MP__aEWM1)
4917 %(mp_prefix)sgal(2) = 1d0
4918 """ %{'mp_prefix':self.mp_prefix})
4919 pass
4920
4921 elif ('Gf',) in self.model['parameters']:
4922 if dp:
4923 fsock.writelines(""" gal(1) = 2.3784142300054421*MDL_MW*MDL_SW*DSQRT(MDL_Gf)
4924 gal(2) = 1d0
4925 """)
4926 elif mp:
4927 fsock.writelines(""" %(mp_prefix)sgal(1) = 2*MP__MDL_MW*MP__MDL_SW*SQRT(SQRT(2e0_16)*MP__MDL_Gf)
4928 %(mp_prefix)sgal(2) = 1d0
4929 """ %{'mp_prefix':self.mp_prefix})
4930 pass
4931 else:
4932 if dp:
4933 logger.warning('$RED aEWM1 and Gf not define in MODEL. AQED will not be written correcty in LHE FILE')
4934 fsock.writelines(""" gal(1) = 1d0
4935 gal(2) = 1d0
4936 """)
4937 elif mp:
4938 fsock.writelines(""" %(mp_prefix)sgal(1) = 1e0_16
4939 %(mp_prefix)sgal(2) = 1e0_16
4940 """%{'mp_prefix':self.mp_prefix})
4941
4942
4944 """ create couplings.f and all couplingsX.f """
4945
4946 nb_def_by_file = 25
4947
4948 self.create_couplings_main(nb_def_by_file)
4949 nb_coup_indep = 1 + len(self.coups_indep) // nb_def_by_file
4950 nb_coup_dep = 1 + len(self.coups_dep) // nb_def_by_file
4951
4952 for i in range(nb_coup_indep):
4953
4954
4955 data = self.coups_indep[nb_def_by_file * i:
4956 min(len(self.coups_indep), nb_def_by_file * (i+1))]
4957 self.create_couplings_part(i + 1, data, dp=True, mp=self.opt['mp'])
4958
4959 for i in range(nb_coup_dep):
4960
4961
4962 data = self.coups_dep[nb_def_by_file * i:
4963 min(len(self.coups_dep), nb_def_by_file * (i+1))]
4964 self.create_couplings_part( i + 1 + nb_coup_indep , data,
4965 dp=True,mp=False)
4966 if self.opt['mp']:
4967 self.create_couplings_part( i + 1 + nb_coup_indep , data,
4968 dp=False,mp=True)
4969
4970
4971 - def create_couplings_main(self, nb_def_by_file=25):
4972 """ create couplings.f """
4973
4974 fsock = self.open('couplings.f', format='fortran')
4975
4976 fsock.writelines("""subroutine coup()
4977
4978 implicit none
4979 double precision PI, ZERO
4980 logical READLHA
4981 parameter (PI=3.141592653589793d0)
4982 parameter (ZERO=0d0)""")
4983 if self.opt['mp']:
4984 fsock.writelines("""%s MP__PI, MP__ZERO
4985 parameter (MP__PI=3.1415926535897932384626433832795e0_16)
4986 parameter (MP__ZERO=0e0_16)
4987 include \'mp_input.inc\'
4988 include \'mp_coupl.inc\'
4989 """%self.mp_real_format)
4990 fsock.writelines("""include \'input.inc\'
4991 include \'coupl.inc\'
4992 READLHA = .true.
4993 include \'intparam_definition.inc\'""")
4994 if self.opt['mp']:
4995 fsock.writelines("""include \'mp_intparam_definition.inc\'\n""")
4996
4997 nb_coup_indep = 1 + len(self.coups_indep) // nb_def_by_file
4998 nb_coup_dep = 1 + len(self.coups_dep) // nb_def_by_file
4999
5000 fsock.writelines('\n'.join(\
5001 ['call coup%s()' % (i + 1) for i in range(nb_coup_indep)]))
5002
5003 fsock.write_comments('\ncouplings needed to be evaluated points by points\n')
5004
5005 fsock.writelines('\n'.join(\
5006 ['call coup%s()' % (nb_coup_indep + i + 1) \
5007 for i in range(nb_coup_dep)]))
5008 if self.opt['mp']:
5009 fsock.writelines('\n'.join(\
5010 ['call mp_coup%s()' % (nb_coup_indep + i + 1) \
5011 for i in range(nb_coup_dep)]))
5012 fsock.writelines('''\n return \n end\n''')
5013
5014 fsock.writelines("""subroutine update_as_param()
5015
5016 implicit none
5017 double precision PI, ZERO
5018 logical READLHA
5019 parameter (PI=3.141592653589793d0)
5020 parameter (ZERO=0d0)""")
5021 fsock.writelines("""include \'input.inc\'
5022 include \'coupl.inc\'
5023 READLHA = .false.""")
5024 fsock.writelines("""
5025 include \'intparam_definition.inc\'\n
5026 """)
5027
5028 nb_coup_indep = 1 + len(self.coups_indep) // nb_def_by_file
5029 nb_coup_dep = 1 + len(self.coups_dep) // nb_def_by_file
5030
5031 fsock.write_comments('\ncouplings needed to be evaluated points by points\n')
5032
5033 fsock.writelines('\n'.join(\
5034 ['call coup%s()' % (nb_coup_indep + i + 1) \
5035 for i in range(nb_coup_dep)]))
5036 fsock.writelines('''\n return \n end\n''')
5037
5038 fsock.writelines("""subroutine update_as_param2(mu_r2,as2)
5039
5040 implicit none
5041 double precision PI
5042 parameter (PI=3.141592653589793d0)
5043 double precision mu_r2, as2""")
5044 fsock.writelines("""include \'input.inc\'
5045 include \'coupl.inc\'""")
5046 fsock.writelines("""
5047 MU_R = mu_r2
5048 G = SQRT(4.0d0*PI*AS2)
5049 AS = as2
5050
5051 CALL UPDATE_AS_PARAM()
5052 """)
5053 fsock.writelines('''\n return \n end\n''')
5054
5055 if self.opt['mp']:
5056 fsock.writelines("""subroutine mp_update_as_param()
5057
5058 implicit none
5059 logical READLHA""")
5060 fsock.writelines("""%s MP__PI, MP__ZERO
5061 parameter (MP__PI=3.1415926535897932384626433832795e0_16)
5062 parameter (MP__ZERO=0e0_16)
5063 include \'mp_input.inc\'
5064 include \'mp_coupl.inc\'
5065 """%self.mp_real_format)
5066 fsock.writelines("""include \'input.inc\'
5067 include \'coupl.inc\'
5068 include \'actualize_mp_ext_params.inc\'
5069 READLHA = .false.
5070 include \'mp_intparam_definition.inc\'\n
5071 """)
5072
5073 nb_coup_indep = 1 + len(self.coups_indep) // nb_def_by_file
5074 nb_coup_dep = 1 + len(self.coups_dep) // nb_def_by_file
5075
5076 fsock.write_comments('\ncouplings needed to be evaluated points by points\n')
5077
5078 fsock.writelines('\n'.join(\
5079 ['call mp_coup%s()' % (nb_coup_indep + i + 1) \
5080 for i in range(nb_coup_dep)]))
5081 fsock.writelines('''\n return \n end\n''')
5082
5084 """ create couplings[nb_file].f containing information coming from data.
5085 Outputs the computation of the double precision and/or the multiple
5086 precision couplings depending on the parameters dp and mp.
5087 If mp is True and dp is False, then the prefix 'MP_' is appended to the
5088 filename and subroutine name.
5089 """
5090
5091 fsock = self.open('%scouplings%s.f' %('mp_' if mp and not dp else '',
5092 nb_file), format='fortran')
5093 fsock.writelines("""subroutine %scoup%s()
5094
5095 implicit none"""%('mp_' if mp and not dp else '',nb_file))
5096 if dp:
5097 fsock.writelines("""
5098 double precision PI, ZERO
5099 parameter (PI=3.141592653589793d0)
5100 parameter (ZERO=0d0)
5101 include 'input.inc'
5102 include 'coupl.inc'""")
5103 if mp:
5104 fsock.writelines("""%s MP__PI, MP__ZERO
5105 parameter (MP__PI=3.1415926535897932384626433832795e0_16)
5106 parameter (MP__ZERO=0e0_16)
5107 include \'mp_input.inc\'
5108 include \'mp_coupl.inc\'
5109 """%self.mp_real_format)
5110 fsock.writelines("""
5111 include 'model_functions.inc'""")
5112 for coupling in data:
5113 if dp:
5114 fsock.writelines('%s = %s' % (coupling.name,
5115 self.p_to_f.parse(coupling.expr)))
5116 if mp:
5117 fsock.writelines('%s%s = %s' % (self.mp_prefix,coupling.name,
5118 self.mp_p_to_f.parse(coupling.expr)))
5119 fsock.writelines('end')
5120
5122 """ Create model_functions.inc which contains the various declarations
5123 of auxiliary functions which might be used in the couplings expressions
5124 """
5125
5126 fsock = self.open('model_functions.inc', format='fortran')
5127 fsock.writelines("""double complex cond
5128 double complex condif
5129 double complex reglog
5130 double complex arg""")
5131 if self.opt['mp']:
5132 fsock.writelines("""%(complex_mp_format)s mp_cond
5133 %(complex_mp_format)s mp_condif
5134 %(complex_mp_format)s mp_reglog
5135 %(complex_mp_format)s mp_arg"""\
5136 %{'complex_mp_format':self.mp_complex_format})
5137
5139 """ Create model_functions.f which contains the various definitions
5140 of auxiliary functions which might be used in the couplings expressions
5141 Add the functions.f functions for formfactors support
5142 """
5143
5144 fsock = self.open('model_functions.f', format='fortran')
5145 fsock.writelines("""double complex function cond(condition,truecase,falsecase)
5146 implicit none
5147 double complex condition,truecase,falsecase
5148 if(condition.eq.(0.0d0,0.0d0)) then
5149 cond=truecase
5150 else
5151 cond=falsecase
5152 endif
5153 end
5154
5155 double complex function condif(condition,truecase,falsecase)
5156 implicit none
5157 logical condition
5158 double complex truecase,falsecase
5159 if(condition) then
5160 condif=truecase
5161 else
5162 condif=falsecase
5163 endif
5164 end
5165
5166 double complex function reglog(arg)
5167 implicit none
5168 double complex arg
5169 if(arg.eq.(0.0d0,0.0d0)) then
5170 reglog=(0.0d0,0.0d0)
5171 else
5172 reglog=log(arg)
5173 endif
5174 end
5175
5176 double complex function arg(comnum)
5177 implicit none
5178 double complex comnum
5179 double complex iim
5180 iim = (0.0d0,1.0d0)
5181 if(comnum.eq.(0.0d0,0.0d0)) then
5182 arg=(0.0d0,0.0d0)
5183 else
5184 arg=log(comnum/abs(comnum))/iim
5185 endif
5186 end""")
5187 if self.opt['mp']:
5188 fsock.writelines("""
5189
5190 %(complex_mp_format)s function mp_cond(condition,truecase,falsecase)
5191 implicit none
5192 %(complex_mp_format)s condition,truecase,falsecase
5193 if(condition.eq.(0.0e0_16,0.0e0_16)) then
5194 mp_cond=truecase
5195 else
5196 mp_cond=falsecase
5197 endif
5198 end
5199
5200 %(complex_mp_format)s function mp_condif(condition,truecase,falsecase)
5201 implicit none
5202 logical condition
5203 %(complex_mp_format)s truecase,falsecase
5204 if(condition) then
5205 mp_condif=truecase
5206 else
5207 mp_condif=falsecase
5208 endif
5209 end
5210
5211 %(complex_mp_format)s function mp_reglog(arg)
5212 implicit none
5213 %(complex_mp_format)s arg
5214 if(arg.eq.(0.0e0_16,0.0e0_16)) then
5215 mp_reglog=(0.0e0_16,0.0e0_16)
5216 else
5217 mp_reglog=log(arg)
5218 endif
5219 end
5220
5221 %(complex_mp_format)s function mp_arg(comnum)
5222 implicit none
5223 %(complex_mp_format)s comnum
5224 %(complex_mp_format)s imm
5225 imm = (0.0e0_16,1.0e0_16)
5226 if(comnum.eq.(0.0e0_16,0.0e0_16)) then
5227 mp_arg=(0.0e0_16,0.0e0_16)
5228 else
5229 mp_arg=log(comnum/abs(comnum))/imm
5230 endif
5231 end"""%{'complex_mp_format':self.mp_complex_format})
5232
5233
5234 model_path = self.model.get('modelpath')
5235 if os.path.exists(pjoin(model_path,'Fortran','functions.f')):
5236 fsock.write_comment_line(' USER DEFINE FUNCTIONS ')
5237 input = pjoin(model_path,'Fortran','functions.f')
5238 file.writelines(fsock, open(input).read())
5239 fsock.write_comment_line(' END USER DEFINE FUNCTIONS ')
5240
5241
5242 ufo_fct = self.model.get('functions')
5243 if ufo_fct:
5244 fsock.write_comment_line(' START UFO DEFINE FUNCTIONS ')
5245 for fct in ufo_fct:
5246
5247 if fct.name not in ["complexconjugate", "re", "im", "sec", "csc", "asec", "acsc",
5248 "theta_function", "cond", "reglog", "arg"]:
5249 ufo_fct_template = """
5250 double complex function %(name)s(%(args)s)
5251 implicit none
5252 double complex %(args)s
5253 %(name)s = %(fct)s
5254
5255 return
5256 end
5257 """
5258 text = ufo_fct_template % {
5259 'name': fct.name,
5260 'args': ", ".join(fct.arguments),
5261 'fct': self.p_to_f.parse(fct.expr)
5262 }
5263 fsock.writelines(text)
5264 if self.opt['mp']:
5265 fsock.write_comment_line(' START UFO DEFINE FUNCTIONS FOR MP')
5266 for fct in ufo_fct:
5267
5268 if fct.name not in ["complexconjugate", "re", "im", "sec", "csc", "asec", "acsc",
5269 "theta_function", "cond", "reglog", "arg"]:
5270 ufo_fct_template = """
5271 %(complex_mp_format)s function mp__%(name)s(mp__%(args)s)
5272 implicit none
5273 %(complex_mp_format)s mp__%(args)s
5274 mp__%(name)s = %(fct)s
5275
5276 return
5277 end
5278 """
5279 text = ufo_fct_template % {
5280 'name': fct.name,
5281 'args': ", mp__".join(fct.arguments),
5282 'fct': self.mp_p_to_f.parse(fct.expr),
5283 'complex_mp_format': self.mp_complex_format
5284 }
5285 fsock.writelines(text)
5286
5287
5288
5289 fsock.write_comment_line(' STOP UFO DEFINE FUNCTIONS ')
5290
5291
5292
5294 """create makeinc.inc containing the file to compile """
5295
5296 fsock = self.open('makeinc.inc', comment='#')
5297 text = 'MODEL = couplings.o lha_read.o printout.o rw_para.o'
5298 text += ' model_functions.o '
5299
5300 nb_coup_indep = 1 + len(self.coups_dep) // 25
5301 nb_coup_dep = 1 + len(self.coups_indep) // 25
5302 couplings_files=['couplings%s.o' % (i+1) \
5303 for i in range(nb_coup_dep + nb_coup_indep) ]
5304 if self.opt['mp']:
5305 couplings_files+=['mp_couplings%s.o' % (i+1) for i in \
5306 range(nb_coup_dep,nb_coup_dep + nb_coup_indep) ]
5307 text += ' '.join(couplings_files)
5308 fsock.writelines(text)
5309
5311 """ create param_write """
5312
5313 fsock = self.open('param_write.inc', format='fortran')
5314
5315 fsock.writelines("""write(*,*) ' External Params'
5316 write(*,*) ' ---------------------------------'
5317 write(*,*) ' '""")
5318 def format(name):
5319 return 'write(*,*) \'%(name)s = \', %(name)s' % {'name': name}
5320
5321
5322 lines = [format(param.name) for param in self.params_ext]
5323 fsock.writelines('\n'.join(lines))
5324
5325 fsock.writelines("""write(*,*) ' Internal Params'
5326 write(*,*) ' ---------------------------------'
5327 write(*,*) ' '""")
5328 lines = [format(data.name) for data in self.params_indep
5329 if data.name != 'ZERO']
5330 fsock.writelines('\n'.join(lines))
5331 fsock.writelines("""write(*,*) ' Internal Params evaluated point by point'
5332 write(*,*) ' ----------------------------------------'
5333 write(*,*) ' '""")
5334 lines = [format(data.name) for data in self.params_dep]
5335
5336 fsock.writelines('\n'.join(lines))
5337
5338
5339
5341 """ create the ident_card.dat """
5342
5343 def format(parameter):
5344 """return the line for the ident_card corresponding to this parameter"""
5345 colum = [parameter.lhablock.lower()] + \
5346 [str(value) for value in parameter.lhacode] + \
5347 [parameter.name]
5348 if not parameter.name:
5349 return ''
5350 return ' '.join(colum)+'\n'
5351
5352 fsock = self.open('ident_card.dat')
5353
5354 external_param = [format(param) for param in self.params_ext]
5355 fsock.writelines('\n'.join(external_param))
5356
5358 """ create the actualize_mp_ext_params.inc code """
5359
5360
5361
5362
5363
5364
5365 update_params_list=[p for p in self.params_ext if p.name in
5366 self.PS_dependent_key]
5367
5368 res_strings = ["%(mp_prefix)s%(name)s=%(name)s"\
5369 %{'mp_prefix':self.mp_prefix,'name':param.name}\
5370 for param in update_params_list]
5371
5372
5373 if 'aS' in [param.name for param in update_params_list]:
5374 res_strings.append("%(mp_prefix)sG=G"%{'mp_prefix':self.mp_prefix})
5375
5376 fsock = self.open('actualize_mp_ext_params.inc', format='fortran')
5377 fsock.writelines('\n'.join(res_strings))
5378
5380 """create param_read"""
5381
5382 if self.opt['export_format'] in ['madevent', 'FKS5_default', 'FKS5_optimized']:
5383 fsock = self.open('param_read.inc', format='fortran')
5384 fsock.writelines(' include \'../param_card.inc\'')
5385 return
5386
5387 def format_line(parameter):
5388 """return the line for the ident_card corresponding to this
5389 parameter"""
5390 template = \
5391 """ call LHA_get_real(npara,param,value,'%(name)s',%(name)s,%(value)s)""" \
5392 % {'name': parameter.name,
5393 'value': self.p_to_f.parse(str(parameter.value.real))}
5394 if self.opt['mp']:
5395 template = template+ \
5396 ("\n call MP_LHA_get_real(npara,param,value,'%(name)s',"+
5397 "%(mp_prefix)s%(name)s,%(value)s)") \
5398 % {'name': parameter.name,'mp_prefix': self.mp_prefix,
5399 'value': self.mp_p_to_f.parse(str(parameter.value.real))}
5400 return template
5401
5402 fsock = self.open('param_read.inc', format='fortran')
5403 res_strings = [format_line(param) \
5404 for param in self.params_ext]
5405
5406
5407
5408 for particle in self.model.get('particles'):
5409 if particle.is_fermion() and particle.get('self_antipart') and \
5410 particle.get('width').lower() != 'zero':
5411
5412 res_strings.append('%(width)s = sign(%(width)s,%(mass)s)' % \
5413 {'width': particle.get('width'), 'mass': particle.get('mass')})
5414 if self.opt['mp']:
5415 res_strings.append(\
5416 ('%(mp_pref)s%(width)s = sign(%(mp_pref)s%(width)s,'+\
5417 '%(mp_pref)s%(mass)s)')%{'width': particle.get('width'),\
5418 'mass': particle.get('mass'),'mp_pref':self.mp_prefix})
5419
5420 fsock.writelines('\n'.join(res_strings))
5421
5423 """ create the param_card.dat """
5424
5425
5426 done = False
5427 if hasattr(self.model, 'restrict_card') and isinstance(self.model.restrict_card, str):
5428 restrict_name = os.path.basename(self.model.restrict_card)[9:-4]
5429 model_path = self.model.get('modelpath')
5430 if os.path.exists(pjoin(model_path,'paramcard_%s.dat' % restrict_name)):
5431 done = True
5432 files.cp(pjoin(model_path,'paramcard_%s.dat' % restrict_name),
5433 pjoin(self.dir_path, 'param_card.dat'))
5434 if not done:
5435 out_path = pjoin(self.dir_path, 'param_card.dat')
5436 param_writer.ParamCardWriter(self.model, out_path)
5437
5438 out_path2 = None
5439 if hasattr(self.model, 'rule_card'):
5440 out_path2 = pjoin(self.dir_path, 'param_card_rule.dat')
5441 self.model.rule_card.write_file(out_path2)
5442
5443
5444 if self.model_name == 'mssm' or self.model_name.startswith('mssm-'):
5445 import models.check_param_card as translator
5446
5447
5448 if out_path2:
5449 translator.make_valid_param_card(out_path, out_path2)
5450 translator.convert_to_slha1(out_path)
5451
5453 """ Determine which Export_v4 class is required. cmd is the command
5454 interface containing all potential usefull information.
5455 The output_type argument specifies from which context the output
5456 is called. It is 'madloop' for MadLoop5, 'amcatnlo' for FKS5 output
5457 and 'default' for tree-level outputs."""
5458
5459 group_subprocesses = cmd.options['group_subprocesses']
5460
5461
5462 if output_type=='madloop':
5463 import madgraph.loop.loop_exporters as loop_exporters
5464 if os.path.isdir(os.path.join(cmd._mgme_dir, 'Template/loop_material')):
5465 ExporterClass=None
5466 options = {'clean': not noclean,
5467 'complex_mass':cmd.options['complex_mass_scheme'],
5468 'export_format':'madloop',
5469 'mp':True,
5470 'loop_dir': os.path.join(cmd._mgme_dir, 'Template/loop_material'),
5471 'cuttools_dir': cmd._cuttools_dir,
5472 'iregi_dir':cmd._iregi_dir,
5473 'pjfry_dir':cmd.options["pjfry"],
5474 'golem_dir':cmd.options["golem"],
5475 'fortran_compiler':cmd.options['fortran_compiler'],
5476 'output_dependencies':cmd.options['output_dependencies']}
5477
5478 if not cmd.options['loop_optimized_output']:
5479 ExporterClass=loop_exporters.LoopProcessExporterFortranSA
5480 else:
5481 if all([amp['process']['has_born'] for amp in cmd._curr_amps]):
5482 ExporterClass=loop_exporters.LoopProcessOptimizedExporterFortranSA
5483 options['export_format'] = 'madloop_optimized'
5484 else:
5485 logger.warning('ML5 can only exploit the optimized output for '+\
5486 ' processes with born diagrams. The optimization '+\
5487 ' option is therefore turned off for this process.')
5488 ExporterClass=loop_exporters.LoopProcessExporterFortranSA
5489 options['export_format'] = 'madloop_default'
5490 return ExporterClass(cmd._mgme_dir, cmd._export_dir, options)
5491 else:
5492 raise MadGraph5Error('MG5_aMC cannot find the \'loop_material\' directory'+\
5493 ' in %s'%str(cmd._mgme_dir))
5494
5495
5496 elif output_type=='amcatnlo':
5497 import madgraph.iolibs.export_fks as export_fks
5498 ExporterClass=None
5499 options = {'clean': not noclean,
5500 'complex_mass':cmd.options['complex_mass_scheme'],
5501 'export_format':'madloop',
5502
5503 'mp':len(cmd._fks_multi_proc.get_virt_amplitudes()) > 0,
5504 'loop_dir': os.path.join(cmd._mgme_dir,'Template','loop_material'),
5505 'cuttools_dir': cmd._cuttools_dir,
5506 'iregi_dir':cmd._iregi_dir,
5507 'pjfry_dir':cmd.options["pjfry"],
5508 'golem_dir':cmd.options["golem"],
5509 'fortran_compiler':cmd.options['fortran_compiler'],
5510 'output_dependencies':cmd.options['output_dependencies']}
5511 if not cmd.options['loop_optimized_output']:
5512 logger.info("Writing out the aMC@NLO code")
5513 ExporterClass = export_fks.ProcessExporterFortranFKS
5514 options['export_format']='FKS5_default'
5515 else:
5516 logger.info("Writing out the aMC@NLO code, using optimized Loops")
5517 ExporterClass = export_fks.ProcessOptimizedExporterFortranFKS
5518 options['export_format']='FKS5_optimized'
5519 return ExporterClass(cmd._mgme_dir, cmd._export_dir, options)
5520
5521
5522 elif output_type=='default':
5523
5524 if cmd.options['group_subprocesses'] == 'Auto':
5525 if cmd._curr_amps[0].get_ninitial() == 2:
5526 group_subprocesses = True
5527 else:
5528 group_subprocesses = False
5529
5530 assert group_subprocesses in [True, False]
5531
5532 opt = {'clean': not noclean,
5533 'complex_mass': cmd.options['complex_mass_scheme'],
5534 'export_format':cmd._export_format,
5535 'mp': False,
5536 'sa_symmetry':False,
5537 'model': cmd._curr_model.get('name') }
5538
5539 format = cmd._export_format
5540
5541 if format in ['standalone_msP', 'standalone_msF', 'standalone_rw']:
5542 opt['sa_symmetry'] = True
5543
5544 if format == 'matrix' or format.startswith('standalone'):
5545 return ProcessExporterFortranSA(cmd._mgme_dir, cmd._export_dir, opt,
5546 format=format)
5547
5548 elif format in ['madevent'] and group_subprocesses:
5549 return ProcessExporterFortranMEGroup(cmd._mgme_dir, cmd._export_dir,
5550 opt)
5551 elif format in ['madevent']:
5552 return ProcessExporterFortranME(cmd._mgme_dir, cmd._export_dir,opt)
5553 elif cmd._export_format in ['madweight'] and group_subprocesses:
5554
5555 return ProcessExporterFortranMWGroup(cmd._mgme_dir, cmd._export_dir,
5556 opt)
5557 elif cmd._export_format in ['madweight']:
5558 return ProcessExporterFortranMW(cmd._mgme_dir, cmd._export_dir, opt)
5559 else:
5560 raise Exception, 'Wrong export_v4 format'
5561 else:
5562 raise MadGraph5Error, 'Output type %s not reckognized in ExportV4Factory.'
5563
5564
5565
5566
5567
5568
5569
5571 """Class to take care of exporting a set of matrix elements to
5572 MadEvent subprocess group format."""
5573
5574 matrix_file = "matrix_madweight_group_v4.inc"
5575
5576
5577
5578
5582 """Generate the Pn directory for a subprocess group in MadEvent,
5583 including the necessary matrix_N.f files, configs.inc and various
5584 other helper files"""
5585
5586 if not isinstance(subproc_group, group_subprocs.SubProcessGroup):
5587 raise base_objects.PhysicsObject.PhysicsObjectError,\
5588 "subproc_group object not SubProcessGroup"
5589
5590 if not self.model:
5591 self.model = subproc_group.get('matrix_elements')[0].\
5592 get('processes')[0].get('model')
5593
5594 pathdir = os.path.join(self.dir_path, 'SubProcesses')
5595
5596
5597 subprocdir = "P%d_%s" % (subproc_group.get('number'),
5598 subproc_group.get('name'))
5599 try:
5600 os.mkdir(pjoin(pathdir, subprocdir))
5601 except os.error as error:
5602 logger.warning(error.strerror + " " + subprocdir)
5603
5604
5605 logger.info('Creating files in directory %s' % subprocdir)
5606 Ppath = pjoin(pathdir, subprocdir)
5607
5608
5609
5610
5611 maxamps = 0
5612 maxflows = 0
5613 tot_calls = 0
5614
5615 matrix_elements = subproc_group.get('matrix_elements')
5616
5617 for ime, matrix_element in \
5618 enumerate(matrix_elements):
5619 filename = pjoin(Ppath, 'matrix%d.f' % (ime+1))
5620 calls, ncolor = \
5621 self.write_matrix_element_v4(writers.FortranWriter(filename),
5622 matrix_element,
5623 fortran_model,
5624 str(ime+1),
5625 subproc_group.get('diagram_maps')[\
5626 ime])
5627
5628 filename = pjoin(Ppath, 'auto_dsig%d.f' % (ime+1))
5629 self.write_auto_dsig_file(writers.FortranWriter(filename),
5630 matrix_element,
5631 str(ime+1))
5632
5633
5634 tot_calls += int(calls)
5635 maxflows = max(maxflows, ncolor)
5636 maxamps = max(maxamps, len(matrix_element.get('diagrams')))
5637
5638
5639 filename = pjoin(Ppath, "matrix%d.ps" % (ime+1))
5640 plot = draw.MultiEpsDiagramDrawer(matrix_element.get('base_amplitude').\
5641 get('diagrams'),
5642 filename,
5643 model = \
5644 matrix_element.get('processes')[0].\
5645 get('model'),
5646 amplitude=True)
5647 logger.info("Generating Feynman diagrams for " + \
5648 matrix_element.get('processes')[0].nice_string())
5649 plot.draw()
5650
5651
5652 (nexternal, ninitial) = matrix_element.get_nexternal_ninitial()
5653
5654
5655
5656
5657
5658 subproc_diagrams_for_config = subproc_group.get('diagrams_for_configs')
5659
5660 filename = pjoin(Ppath, 'auto_dsig.f')
5661 self.write_super_auto_dsig_file(writers.FortranWriter(filename),
5662 subproc_group)
5663
5664 filename = pjoin(Ppath,'configs.inc')
5665 nconfigs, s_and_t_channels = self.write_configs_file(\
5666 writers.FortranWriter(filename),
5667 subproc_group,
5668 subproc_diagrams_for_config)
5669
5670 filename = pjoin(Ppath, 'leshouche.inc')
5671 self.write_leshouche_file(writers.FortranWriter(filename),
5672 subproc_group)
5673
5674 filename = pjoin(Ppath, 'phasespace.inc')
5675 self.write_phasespace_file(writers.FortranWriter(filename),
5676 nconfigs)
5677
5678
5679 filename = pjoin(Ppath, 'maxamps.inc')
5680 self.write_maxamps_file(writers.FortranWriter(filename),
5681 maxamps,
5682 maxflows,
5683 max([len(me.get('processes')) for me in \
5684 matrix_elements]),
5685 len(matrix_elements))
5686
5687 filename = pjoin(Ppath, 'mirrorprocs.inc')
5688 self.write_mirrorprocs(writers.FortranWriter(filename),
5689 subproc_group)
5690
5691 filename = pjoin(Ppath, 'nexternal.inc')
5692 self.write_nexternal_file(writers.FortranWriter(filename),
5693 nexternal, ninitial)
5694
5695 filename = pjoin(Ppath, 'pmass.inc')
5696 self.write_pmass_file(writers.FortranWriter(filename),
5697 matrix_element)
5698
5699 filename = pjoin(Ppath, 'props.inc')
5700 self.write_props_file(writers.FortranWriter(filename),
5701 matrix_element,
5702 s_and_t_channels)
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712 linkfiles = ['driver.f', 'cuts.f', 'initialization.f','gen_ps.f', 'makefile', 'coupl.inc','madweight_param.inc', 'run.inc', 'setscales.f']
5713
5714 for file in linkfiles:
5715 ln('../%s' % file, cwd=Ppath)
5716
5717 ln('nexternal.inc', '../../Source', cwd=Ppath, log=False)
5718 ln('leshouche.inc', '../../Source', cwd=Ppath, log=False)
5719 ln('maxamps.inc', '../../Source', cwd=Ppath, log=False)
5720 ln('../../Source/maxparticles.inc', '.', log=True, cwd=Ppath)
5721 ln('../../Source/maxparticles.inc', '.', name='genps.inc', log=True, cwd=Ppath)
5722 ln('phasespace.inc', '../', log=True, cwd=Ppath)
5723 if not tot_calls:
5724 tot_calls = 0
5725 return tot_calls
5726
5727
5728
5729
5731 """Write the auto_dsig.f file selecting between the subprocesses
5732 in subprocess group mode"""
5733
5734 replace_dict = {}
5735
5736
5737 info_lines = self.get_mg5_info_lines()
5738 replace_dict['info_lines'] = info_lines
5739
5740 matrix_elements = subproc_group.get('matrix_elements')
5741
5742
5743 process_lines = '\n'.join([self.get_process_info_lines(me) for me in \
5744 matrix_elements])
5745 replace_dict['process_lines'] = process_lines
5746
5747 nexternal, ninitial = matrix_elements[0].get_nexternal_ninitial()
5748 replace_dict['nexternal'] = nexternal
5749
5750 replace_dict['nsprocs'] = 2*len(matrix_elements)
5751
5752
5753 dsig_def_line = "DOUBLE PRECISION " + \
5754 ",".join(["DSIG%d" % (iproc + 1) for iproc in \
5755 range(len(matrix_elements))])
5756 replace_dict["dsig_def_line"] = dsig_def_line
5757
5758
5759 call_dsig_proc_lines = []
5760 for iproc in range(len(matrix_elements)):
5761 call_dsig_proc_lines.append(\
5762 "IF(IPROC.EQ.%(num)d) DSIGPROC=DSIG%(num)d(P1,WGT,IMODE) ! %(proc)s" % \
5763 {"num": iproc + 1,
5764 "proc": matrix_elements[iproc].get('processes')[0].base_string()})
5765 replace_dict['call_dsig_proc_lines'] = "\n".join(call_dsig_proc_lines)
5766
5767 file = open(os.path.join(_file_path, \
5768 'iolibs/template_files/super_auto_dsig_mw_group_v4.inc')).read()
5769 file = file % replace_dict
5770
5771
5772 writer.writelines(file)
5773
5774
5775
5776
5778 """Write the mirrorprocs.inc file determining which processes have
5779 IS mirror process in subprocess group mode."""
5780
5781 lines = []
5782 bool_dict = {True: '.true.', False: '.false.'}
5783 matrix_elements = subproc_group.get('matrix_elements')
5784 lines.append("DATA (MIRRORPROCS(I),I=1,%d)/%s/" % \
5785 (len(matrix_elements),
5786 ",".join([bool_dict[me.get('has_mirror_process')] for \
5787 me in matrix_elements])))
5788
5789 writer.writelines(lines)
5790
5791
5792
5793
5795 """Write the configs.inc file with topology information for a
5796 subprocess group. Use the first subprocess with a diagram for each
5797 configuration."""
5798
5799 matrix_elements = subproc_group.get('matrix_elements')
5800 model = matrix_elements[0].get('processes')[0].get('model')
5801
5802 diagrams = []
5803 config_numbers = []
5804 for iconfig, config in enumerate(diagrams_for_config):
5805
5806 if set(config) == set([0]):
5807 continue
5808 subproc_diags = []
5809 for s,d in enumerate(config):
5810 if d:
5811 subproc_diags.append(matrix_elements[s].\
5812 get('diagrams')[d-1])
5813 else:
5814 subproc_diags.append(None)
5815 diagrams.append(subproc_diags)
5816 config_numbers.append(iconfig + 1)
5817
5818
5819 (nexternal, ninitial) = subproc_group.get_nexternal_ninitial()
5820
5821 return len(diagrams), \
5822 self.write_configs_file_from_diagrams(writer, diagrams,
5823 config_numbers,
5824 nexternal, ninitial,
5825 matrix_elements[0],model)
5826
5827
5828
5829
5831 """Write the run_configs.inc file for MadEvent"""
5832
5833 path = os.path.join(_file_path,'iolibs','template_files','madweight_run_config.inc')
5834 text = open(path).read() % {'chanperjob':'2'}
5835 writer.write(text)
5836 return True
5837
5838
5839
5840
5841
5843 """Write the leshouche.inc file for MG4"""
5844
5845 all_lines = []
5846
5847 for iproc, matrix_element in \
5848 enumerate(subproc_group.get('matrix_elements')):
5849 all_lines.extend(self.get_leshouche_lines(matrix_element,
5850 iproc))
5851
5852
5853 writer.writelines(all_lines)
5854
5855 return True
5856