352
381
wanted_couplings = []):
353
382
""" Create a full valid MG4 model from a MG5 model (coming from UFO)"""
384
# Make sure aloha is in quadruple precision if needed
385
old_aloha_mp=aloha.mp_precision
386
aloha.mp_precision=self.opt['mp']
355
388
# create the MODEL
356
389
write_dir=pjoin(self.dir_path, 'Source', 'MODEL')
357
390
model_builder = UFO_model_to_mg4(model, write_dir, self.opt)
358
391
model_builder.build(wanted_couplings)
360
# Create and write ALOHA Routine
361
aloha_model = create_aloha.AbstractALOHAModel(model.get('name'))
393
# Backup the loop mode, because it can be changed in what follows.
394
old_loop_mode = aloha.loop_mode
396
# Create the aloha model or use the existing one (for loop exporters
397
# this is useful as the aloha model will be used again in the
398
# LoopHelasMatrixElements generated). We do not save the model generated
399
# here if it didn't exist already because it would be a waste of
400
# memory for tree level applications since aloha is only needed at the
401
# time of creating the aloha fortran subroutines.
402
if hasattr(self, 'aloha_model'):
403
aloha_model = self.aloha_model
405
aloha_model = create_aloha.AbstractALOHAModel(model.get('name'))
362
406
aloha_model.add_Lorentz_object(model.get('lorentz'))
408
# Compute the subroutines
363
409
if wanted_lorentz:
364
410
aloha_model.compute_subset(wanted_lorentz)
366
412
aloha_model.compute_all(save=False)
367
415
write_dir=pjoin(self.dir_path, 'Source', 'DHELAS')
368
416
aloha_model.write(write_dir, 'Fortran')
418
# Revert the original aloha loop mode
419
aloha.loop_mode = old_loop_mode
370
421
#copy Helas Template
371
422
cp(MG5DIR + '/aloha/template_files/Makefile_F', write_dir+'/makefile')
372
for filename in os.listdir(pjoin(MG5DIR,'aloha','template_files')):
373
if not filename.lower().endswith('.f'):
375
cp((MG5DIR + '/aloha/template_files/' + filename), write_dir)
423
if any([any(['L' in tag for tag in d[1]]) for d in wanted_lorentz]):
424
cp(MG5DIR + '/aloha/template_files/aloha_functions_loop.f', write_dir+'/aloha_functions.f')
425
aloha_model.loop_mode = False
427
cp(MG5DIR + '/aloha/template_files/aloha_functions.f', write_dir+'/aloha_functions.f')
376
428
create_aloha.write_aloha_file_inc(write_dir, '.f', '.o')
378
430
# Make final link in the Process
379
431
self.make_model_symbolic_link()
433
# Re-establish original aloha mode
434
aloha.mp_precision=old_aloha_mp
381
436
#===========================================================================
382
437
# Helper functions
583
def get_JAMP_lines(self, matrix_element):
584
"""Return the JAMP = sum(fermionfactor * AMP(i)) lines"""
638
#===========================================================================
639
# Returns the data statements initializing the coeffictients for the JAMP
640
# decomposition. It is used when the JAMP initialization is decided to be
641
# done through big arrays containing the projection coefficients.
642
#===========================================================================
643
def get_JAMP_coefs(self, color_amplitudes, color_basis=None, tag_letter="",\
645
"""This functions return the lines defining the DATA statement setting
646
the coefficients building the JAMPS out of the AMPS. Split rows in
648
One can specify the color_basis from which the color amplitudes originates
649
so that there are commentaries telling what color structure each JAMP
652
if(not isinstance(color_amplitudes,list) or
653
not (color_amplitudes and isinstance(color_amplitudes[0],list))):
654
raise MadGraph5Error, "Incorrect col_amps argument passed to get_JAMP_coefs"
657
my_cs = color.ColorString()
658
for index, coeff_list in enumerate(color_amplitudes):
659
# Create the list of the complete numerical coefficient.
660
coefs_list=[coefficient[0][0]*coefficient[0][1]*\
661
(fractions.Fraction(Nc_value)**coefficient[0][3]) for \
662
coefficient in coeff_list]
663
# Create the list of the numbers of the contributing amplitudes.
664
# Mutliply by -1 for those which have an imaginary coefficient.
665
ampnumbers_list=[coefficient[1]*(-1 if coefficient[0][2] else 1) \
666
for coefficient in coeff_list]
667
# Find the common denominator.
668
commondenom=abs(reduce(fractions.gcd, coefs_list).denominator)
669
num_list=[(coefficient*commondenom).numerator \
670
for coefficient in coefs_list]
671
res_list.append("DATA NCONTRIBAMPS%s(%i)/%i/"%(tag_letter,\
672
index+1,len(num_list)))
673
res_list.append("DATA DENOMCCOEF%s(%i)/%i/"%(tag_letter,\
674
index+1,commondenom))
676
my_cs.from_immutable(sorted(color_basis.keys())[index])
677
res_list.append("C %s" % repr(my_cs))
678
for k in xrange(0, len(num_list), n):
679
res_list.append("DATA (NUMCCOEF%s(%3r,i),i=%6r,%6r) /%s/" % \
680
(tag_letter,index + 1, k + 1, min(k + n, len(num_list)),
681
','.join(["%6r" % i for i in num_list[k:k + n]])))
682
res_list.append("DATA (AMPNUMBERS%s(%3r,i),i=%6r,%6r) /%s/" % \
683
(tag_letter,index + 1, k + 1, min(k + n, len(num_list)),
684
','.join(["%6r" % i for i in ampnumbers_list[k:k + n]])))
688
def get_JAMP_lines(self, col_amps, basename="JAMP(", basename2="AMP(", split=-1):
689
"""Return the JAMP = sum(fermionfactor * AMP(i)) lines from col_amps
690
defined as a matrix element or directly as a color_amplitudes dictionary"""
692
# Let the user call get_JAMP_lines directly from a MatrixElement or from
693
# the color amplitudes lists.
694
if(isinstance(col_amps,helas_objects.HelasMatrixElement)):
695
color_amplitudes=col_amps.get_color_amplitudes()
696
elif(isinstance(col_amps,list)):
697
if(col_amps and isinstance(col_amps[0],list)):
698
color_amplitudes=col_amps
700
raise MadGraph5Error, "Incorrect col_amps argument passed to get_JAMP_lines"
702
raise MadGraph5Error, "Incorrect col_amps argument passed to get_JAMP_lines"
588
706
for i, coeff_list in \
589
enumerate(matrix_element.get_color_amplitudes()):
591
res = "JAMP(%i)=" % (i + 1)
593
# Optimization: if all contributions to that color basis element have
594
# the same coefficient (up to a sign), put it in front
595
list_fracs = [abs(coefficient[0][1]) for coefficient in coeff_list]
596
common_factor = False
597
diff_fracs = list(set(list_fracs))
598
if len(diff_fracs) == 1 and abs(diff_fracs[0]) != 1:
600
global_factor = diff_fracs[0]
601
res = res + '%s(' % self.coeff(1, global_factor, False, 0)
603
for (coefficient, amp_number) in coeff_list:
707
enumerate(color_amplitudes):
708
# Break the JAMP definition into 'n=split' pieces to avoid having
709
# arbitrarly long lines.
711
n = (len(coeff_list)+1 if split<=0 else split)
712
while coeff_list!=[]:
714
coeff_list=coeff_list[n:]
715
res = ((basename+"%i)=") % (i + 1)) + \
716
(((basename+"%i)") % (i + 1)) if not first and split>0 else '')
718
# Optimization: if all contributions to that color basis element have
719
# the same coefficient (up to a sign), put it in front
720
list_fracs = [abs(coefficient[0][1]) for coefficient in coefs]
721
common_factor = False
722
diff_fracs = list(set(list_fracs))
723
if len(diff_fracs) == 1 and abs(diff_fracs[0]) != 1:
725
global_factor = diff_fracs[0]
726
res = res + '%s(' % self.coeff(1, global_factor, False, 0)
728
for (coefficient, amp_number) in coefs:
730
res = (res + "%s" + basename2 + "%d)") % \
731
(self.coeff(coefficient[0],
732
coefficient[1] / abs(coefficient[1]),
737
res = (res + "%s" + basename2 + "%d)") % (self.coeff(coefficient[0],
604
743
if common_factor:
605
res = res + "%sAMP(%d)" % (self.coeff(coefficient[0],
606
coefficient[1] / abs(coefficient[1]),
611
res = res + "%sAMP(%d)" % (self.coeff(coefficient[0],
727
853
# Remove last line break from the return variables
728
854
return pdf_definition_lines[:-1], pdf_data_lines[:-1], pdf_lines[:-1]
856
#===========================================================================
858
#===========================================================================
859
def write_props_file(self, writer, matrix_element, s_and_t_channels):
860
"""Write the props.inc file for MadEvent. Needs input from
861
write_configs_file."""
865
particle_dict = matrix_element.get('processes')[0].get('model').\
868
for iconf, configs in enumerate(s_and_t_channels):
869
for vertex in configs[0] + configs[1][:-1]:
870
leg = vertex.get('legs')[-1]
871
if leg.get('id') not in particle_dict:
872
# Fake propagator used in multiparticle vertices
877
particle = particle_dict[leg.get('id')]
879
if particle.get('mass').lower() == 'zero':
880
mass = particle.get('mass')
882
mass = "abs(%s)" % particle.get('mass')
884
if particle.get('width').lower() == 'zero':
885
width = particle.get('width')
887
width = "abs(%s)" % particle.get('width')
889
pow_part = 1 + int(particle.is_boson())
891
lines.append("prmass(%d,%d) = %s" % \
892
(leg.get('number'), iconf + 1, mass))
893
lines.append("prwidth(%d,%d) = %s" % \
894
(leg.get('number'), iconf + 1, width))
895
lines.append("pow(%d,%d) = %d" % \
896
(leg.get('number'), iconf + 1, pow_part))
899
writer.writelines(lines)
903
#===========================================================================
905
#===========================================================================
906
def write_configs_file(self, writer, matrix_element):
907
"""Write the configs.inc file for MadEvent"""
909
# Extract number of external particles
910
(nexternal, ninitial) = matrix_element.get_nexternal_ninitial()
912
configs = [(i+1, d) for i,d in enumerate(matrix_element.get('diagrams'))]
913
mapconfigs = [c[0] for c in configs]
914
model = matrix_element.get('processes')[0].get('model')
915
return mapconfigs, self.write_configs_file_from_diagrams(writer,
916
[[c[1]] for c in configs],
921
#===========================================================================
922
# write_configs_file_from_diagrams
923
#===========================================================================
924
def write_configs_file_from_diagrams(self, writer, configs, mapconfigs,
925
nexternal, ninitial, model):
926
"""Write the actual configs.inc file.
928
configs is the diagrams corresponding to configs (each
929
diagrams is a list of corresponding diagrams for all
930
subprocesses, with None if there is no corresponding diagrams
931
for a given process).
932
mapconfigs gives the diagram number for each config.
934
For s-channels, we need to output one PDG for each subprocess in
935
the subprocess group, in order to be able to pick the right
936
one for multiprocesses."""
940
s_and_t_channels = []
942
minvert = min([max([d for d in config if d][0].get_vertex_leg_numbers()) \
943
for config in configs])
945
# Number of subprocesses
946
nsubprocs = len(configs[0])
950
new_pdg = model.get_first_non_pdg()
952
for iconfig, helas_diags in enumerate(configs):
953
if any([vert > minvert for vert in
954
[d for d in helas_diags if d][0].get_vertex_leg_numbers()]):
955
# Only 3-vertices allowed in configs.inc
959
# Need s- and t-channels for all subprocesses, including
960
# those that don't contribute to this config
963
for h in helas_diags:
965
# get_s_and_t_channels gives vertices starting from
966
# final state external particles and working inwards
967
stchannels.append(h.get('amplitudes')[0].\
968
get_s_and_t_channels(ninitial, model, new_pdg))
970
stchannels.append((empty_verts, None))
972
# For t-channels, just need the first non-empty one
973
tchannels = [t for s,t in stchannels if t != None][0]
975
# For s_and_t_channels (to be used later) use only first config
976
s_and_t_channels.append([[s for s,t in stchannels if t != None][0],
979
# Make sure empty_verts is same length as real vertices
980
if any([s for s,t in stchannels]):
981
empty_verts[:] = [None]*max([len(s) for s,t in stchannels])
983
# Reorganize s-channel vertices to get a list of all
984
# subprocesses for each vertex
985
schannels = zip(*[s for s,t in stchannels])
989
allchannels = schannels
990
if len(tchannels) > 1:
991
# Write out tchannels only if there are any non-trivial ones
992
allchannels = schannels + tchannels
994
# Write out propagators for s-channel and t-channel vertices
996
lines.append("# Diagram %d" % (mapconfigs[iconfig]))
997
# Correspondance between the config and the diagram = amp2
998
lines.append("data mapconfig(%d)/%d/" % (nconfigs,
999
mapconfigs[iconfig]))
1001
for verts in allchannels:
1002
if verts in schannels:
1003
vert = [v for v in verts if v][0]
1006
daughters = [leg.get('number') for leg in vert.get('legs')[:-1]]
1007
last_leg = vert.get('legs')[-1]
1008
lines.append("data (iforest(i,%d,%d),i=1,%d)/%s/" % \
1009
(last_leg.get('number'), nconfigs, len(daughters),
1010
",".join([str(d) for d in daughters])))
1011
if verts in schannels:
1015
pdgs.append(v.get('legs')[-1].get('id'))
1018
lines.append("data (sprop(i,%d,%d),i=1,%d)/%s/" % \
1019
(last_leg.get('number'), nconfigs, nsubprocs,
1020
",".join([str(d) for d in pdgs])))
1021
lines.append("data tprid(%d,%d)/0/" % \
1022
(last_leg.get('number'), nconfigs))
1023
elif verts in tchannels[:-1]:
1024
lines.append("data tprid(%d,%d)/%d/" % \
1025
(last_leg.get('number'), nconfigs,
1026
abs(last_leg.get('id'))))
1027
lines.append("data (sprop(i,%d,%d),i=1,%d)/%s/" % \
1028
(last_leg.get('number'), nconfigs, nsubprocs,
1029
",".join(['0'] * nsubprocs)))
1031
# Write out number of configs
1032
lines.append("# Number of configs")
1033
lines.append("data mapconfig(0)/%d/" % nconfigs)
1036
writer.writelines(lines)
1038
return s_and_t_channels
731
1040
#===========================================================================
732
1041
# Global helper methods
857
1173
# Add file in SubProcesses
858
1174
shutil.copy(pjoin(self.mgme_dir, 'madgraph', 'iolibs', 'template_files', 'makefile_sa_f_sp'),
859
1175
pjoin(self.dir_path, 'SubProcesses', 'makefile'))
860
shutil.copy(pjoin(self.mgme_dir, 'madgraph', 'iolibs', 'template_files', 'check_sa.f'),
861
pjoin(self.dir_path, 'SubProcesses', 'check_sa.f'))
1177
if self.format == 'standalone':
1178
shutil.copy(pjoin(self.mgme_dir, 'madgraph', 'iolibs', 'template_files', 'check_sa.f'),
1179
pjoin(self.dir_path, 'SubProcesses', 'check_sa.f'))
1180
elif self.format == 'standalone_rw':
1181
shutil.copy(pjoin(self.mgme_dir, 'madgraph', 'iolibs', 'template_files', 'driver_reweight.f'),
1182
pjoin(self.dir_path, 'SubProcesses', 'check_sa.f'))
863
1184
# Add file in Source
864
1185
shutil.copy(pjoin(temp_dir, 'Source', 'make_opts'),
865
1186
pjoin(self.dir_path, 'Source'))
866
1187
# add the makefile
867
1188
filename = pjoin(self.dir_path,'Source','makefile')
868
self.write_source_makefile(writers.FileWriter(filename))
1189
self.write_source_makefile(writers.FileWriter(filename))
870
1191
#===========================================================================
871
1192
# export model files
1168
1545
self.dir_path+'/bin/internal/me5_logging.conf')
1169
1546
cp(_file_path+'/interface/coloring_logging.py',
1170
1547
self.dir_path+'/bin/internal/coloring_logging.py')
1548
# shower card and FO_analyse_card.
1549
# Although not needed, it is imported by banner.py
1550
cp(_file_path+'/various/shower_card.py',
1551
self.dir_path+'/bin/internal/shower_card.py')
1552
cp(_file_path+'/various/FO_analyse_card.py',
1553
self.dir_path+'/bin/internal/FO_analyse_card.py')
1173
1556
def convert_model_to_mg4(self, model, wanted_lorentz = [],
1174
1557
wanted_couplings = []):
1176
super(ProcessExporterFortranME,self).convert_model_to_mg4(model,
1559
super(ProcessExporterFortranME,self).convert_model_to_mg4(model,
1177
1560
wanted_lorentz, wanted_couplings)
1179
IGNORE_PATTERNS = ('*.pyc','*.dat','*.py~')
1181
shutil.rmtree(pjoin(self.dir_path,'bin','internal','ufomodel'))
1182
except OSError as error:
1184
shutil.copytree(model.get('version_tag').split('##')[0],
1562
IGNORE_PATTERNS = ('*.pyc','*.dat','*.py~')
1564
shutil.rmtree(pjoin(self.dir_path,'bin','internal','ufomodel'))
1565
except OSError as error:
1567
model_path = model.get('modelpath')
1568
# This is not safe if there is a '##' or '-' in the path.
1569
shutil.copytree(model_path,
1185
1570
pjoin(self.dir_path,'bin','internal','ufomodel'),
1186
1571
ignore=shutil.ignore_patterns(*IGNORE_PATTERNS))
1187
if hasattr(model, 'restrict_card'):
1188
out_path = pjoin(self.dir_path, 'bin', 'internal','ufomodel',
1572
if hasattr(model, 'restrict_card'):
1573
out_path = pjoin(self.dir_path, 'bin', 'internal','ufomodel',
1189
1574
'restrict_default.dat')
1190
if isinstance(model.restrict_card, check_param_card.ParamCard):
1191
model.restrict_card.write(out_path)
1193
files.cp(model.restrict_card, out_path)
1575
if isinstance(model.restrict_card, check_param_card.ParamCard):
1576
model.restrict_card.write(out_path)
1578
files.cp(model.restrict_card, out_path)
1196
1581
#===========================================================================
2273
2697
#===========================================================================
2275
#===========================================================================
2276
def write_props_file(self, writer, matrix_element, s_and_t_channels):
2277
"""Write the props.inc file for MadEvent. Needs input from
2278
write_configs_file."""
2282
particle_dict = matrix_element.get('processes')[0].get('model').\
2283
get('particle_dict')
2285
for iconf, configs in enumerate(s_and_t_channels):
2286
for vertex in configs[0] + configs[1][:-1]:
2287
leg = vertex.get('legs')[-1]
2288
if leg.get('id') not in particle_dict:
2289
# Fake propagator used in multiparticle vertices
2294
particle = particle_dict[leg.get('id')]
2296
if particle.get('mass').lower() == 'zero':
2297
mass = particle.get('mass')
2299
mass = "abs(%s)" % particle.get('mass')
2301
if particle.get('width').lower() == 'zero':
2302
width = particle.get('width')
2304
width = "abs(%s)" % particle.get('width')
2306
pow_part = 1 + int(particle.is_boson())
2308
lines.append("prmass(%d,%d) = %s" % \
2309
(leg.get('number'), iconf + 1, mass))
2310
lines.append("prwidth(%d,%d) = %s" % \
2311
(leg.get('number'), iconf + 1, width))
2312
lines.append("pow(%d,%d) = %d" % \
2313
(leg.get('number'), iconf + 1, pow_part))
2316
writer.writelines(lines)
2320
#===========================================================================
2321
2698
# write_processes_file
2322
2699
#===========================================================================
2323
2700
def write_processes_file(self, writer, subproc_group):
3054
3454
#copy the library files
3055
file_to_link = ['formats.inc', 'lha_read.f','printout.f', \
3455
file_to_link = ['formats.inc','printout.f', \
3056
3456
'rw_para.f', 'testprog.f']
3059
3458
for filename in file_to_link:
3060
cp( MG5DIR + '/models/template_files/fortran/' + filename, self.dir_path)
3062
if self.opt['export_format'] == 'madevent':
3459
cp( MG5DIR + '/models/template_files/fortran/' + filename, \
3462
file = open(os.path.join(MG5DIR,\
3463
'models/template_files/fortran/rw_para.f')).read()
3465
includes=["include \'coupl.inc\'","include \'input.inc\'"]
3467
includes.extend(["include \'mp_coupl.inc\'","include \'mp_input.inc\'"])
3468
# In standalone and madloop we do no use the compiled param card but
3469
# still parse the .dat one so we must load it.
3470
if self.opt['export_format'] in ['madloop','madloop_optimized']:
3471
load_card = 'call LHA_loadcard(param_name,npara,param,value)'
3472
lha_read_filename='lha_read_mp.f'
3473
elif self.opt['export_format'].startswith('standalone'):
3474
load_card = 'call LHA_loadcard(param_name,npara,param,value)'
3475
lha_read_filename='lha_read.f'
3478
lha_read_filename='lha_read.f'
3479
cp( MG5DIR + '/models/template_files/fortran/' + lha_read_filename, \
3480
os.path.join(self.dir_path,'lha_read.f'))
3482
file=file%{'includes':'\n '.join(includes),
3483
'load_card':load_card}
3484
writer=open(os.path.join(self.dir_path,'rw_para.f'),'w')
3485
writer.writelines(file)
3488
if self.opt['export_format'] in ['madevent', 'FKS5_default', 'FKS5_optimized']:
3063
3489
cp( MG5DIR + '/models/template_files/fortran/makefile_madevent',
3064
3490
self.dir_path + '/makefile')
3491
if self.opt['export_format'] in ['FKS5_default', 'FKS5_optimized']:
3492
path = pjoin(self.dir_path, 'makefile')
3493
text = open(path).read()
3494
text = text.replace('madevent','aMCatNLO')
3495
open(path, 'w').writelines(text)
3497
elif self.opt['export_format'] in ['standalone', 'standalone_msP','standalone_msF',
3498
'madloop','madloop_optimized', 'standalone_rw']:
3066
3499
cp( MG5DIR + '/models/template_files/fortran/makefile_standalone',
3067
3500
self.dir_path + '/makefile')
3068
text = open(pjoin(self.dir_path, 'rw_para.f')).read()
3069
text = re.sub(r'c\s*call LHA_loadcard',' call LHA_loadcard',text, re.I)
3070
fsock = open(pjoin(self.dir_path, 'rw_para.f'), 'w')
3502
raise MadGraph5Error('Unknown format')
3077
3504
def create_coupl_inc(self):
3078
3505
""" write coupling.inc """
3080
3507
fsock = self.open('coupl.inc', format='fortran')
3509
mp_fsock = self.open('mp_coupl.inc', format='fortran')
3510
mp_fsock_same_name = self.open('mp_coupl_same_name.inc',\
3083
3514
header = """double precision G
3084
3515
common/strong/ G
3107
3567
widths.add(one_width)
3108
3568
if self.opt['complex_mass'] and one_mass.lower() != 'zero':
3109
3569
complex_mass.add('CMASS_%s' % one_mass)
3111
fsock.writelines('double precision '+','.join(masses)+'\n')
3112
fsock.writelines('common/masses/ '+','.join(masses)+'\n\n')
3572
fsock.writelines('double precision '+','.join(masses)+'\n')
3573
fsock.writelines('common/masses/ '+','.join(masses)+'\n\n')
3575
mp_fsock_same_name.writelines(self.mp_real_format+' '+\
3576
','.join(masses)+'\n')
3577
mp_fsock_same_name.writelines('common/MP_masses/ '+\
3578
','.join(masses)+'\n\n')
3579
mp_fsock.writelines(self.mp_real_format+' '+','.join([\
3580
self.mp_prefix+m for m in masses])+'\n')
3581
mp_fsock.writelines('common/MP_masses/ '+\
3582
','.join([self.mp_prefix+m for m in masses])+'\n\n')
3114
3585
fsock.writelines('double precision '+','.join(widths)+'\n')
3115
3586
fsock.writelines('common/widths/ '+','.join(widths)+'\n\n')
3588
mp_fsock_same_name.writelines(self.mp_real_format+' '+\
3589
','.join(widths)+'\n')
3590
mp_fsock_same_name.writelines('common/MP_widths/ '+\
3591
','.join(widths)+'\n\n')
3592
mp_fsock.writelines(self.mp_real_format+' '+','.join([\
3593
self.mp_prefix+w for w in widths])+'\n')
3594
mp_fsock.writelines('common/MP_widths/ '+\
3595
','.join([self.mp_prefix+w for w in widths])+'\n\n')
3117
3597
# Write the Couplings
3118
3598
coupling_list = [coupl.name for coupl in self.coups_dep + self.coups_indep]
3119
3599
fsock.writelines('double complex '+', '.join(coupling_list)+'\n')
3120
3600
fsock.writelines('common/couplings/ '+', '.join(coupling_list)+'\n')
3602
mp_fsock_same_name.writelines(self.mp_complex_format+' '+\
3603
','.join(coupling_list)+'\n')
3604
mp_fsock_same_name.writelines('common/MP_couplings/ '+\
3605
','.join(coupling_list)+'\n\n')
3606
mp_fsock.writelines(self.mp_complex_format+' '+','.join([\
3607
self.mp_prefix+c for c in coupling_list])+'\n')
3608
mp_fsock.writelines('common/MP_couplings/ '+\
3609
','.join([self.mp_prefix+c for c in coupling_list])+'\n\n')
3122
3611
# Write complex mass for complex mass scheme (if activated)
3123
if self.opt['complex_mass']:
3612
if self.opt['complex_mass'] and complex_mass:
3124
3613
fsock.writelines('double complex '+', '.join(complex_mass)+'\n')
3125
fsock.writelines('common/complex_mass/ '+', '.join(complex_mass)+'\n')
3614
fsock.writelines('common/complex_mass/ '+', '.join(complex_mass)+'\n')
3616
mp_fsock_same_name.writelines(self.mp_complex_format+' '+\
3617
','.join(complex_mass)+'\n')
3618
mp_fsock_same_name.writelines('common/MP_complex_mass/ '+\
3619
','.join(complex_mass)+'\n\n')
3620
mp_fsock.writelines(self.mp_complex_format+' '+','.join([\
3621
self.mp_prefix+cm for cm in complex_mass])+'\n')
3622
mp_fsock.writelines('common/MP_complex_mass/ '+\
3623
','.join([self.mp_prefix+cm for cm in complex_mass])+'\n\n')
3127
3625
def create_write_couplings(self):
3128
3626
""" write the file coupl_write.inc """
3166
3666
fsock.writelines('double precision '+','.join(real_parameters)+'\n')
3167
3667
fsock.writelines('common/params_R/ '+','.join(real_parameters)+'\n\n')
3669
mp_fsock.writelines(self.mp_real_format+' '+','.join([\
3670
self.mp_prefix+p for p in real_parameters])+'\n')
3671
mp_fsock.writelines('common/MP_params_R/ '+','.join([\
3672
self.mp_prefix+p for p in real_parameters])+'\n\n')
3169
3674
complex_parameters = [param.name for param in self.params_dep +
3170
3675
self.params_indep if param.type == 'complex' and
3171
3676
is_valid(param.name)]
3174
3678
fsock.writelines('double complex '+','.join(complex_parameters)+'\n')
3175
fsock.writelines('common/params_C/ '+','.join(complex_parameters)+'\n\n')
3179
def create_intparam_def(self):
3180
""" create intparam_definition.inc """
3182
fsock = self.open('intparam_definition.inc', format='fortran')
3679
fsock.writelines('common/params_C/ '+','.join(complex_parameters)+'\n\n')
3681
mp_fsock.writelines(self.mp_complex_format+' '+','.join([\
3682
self.mp_prefix+p for p in complex_parameters])+'\n')
3683
mp_fsock.writelines('common/MP_params_C/ '+','.join([\
3684
self.mp_prefix+p for p in complex_parameters])+'\n\n')
3688
def create_intparam_def(self, dp=True, mp=False):
3689
""" create intparam_definition.inc setting the internal parameters.
3690
Output the double precision and/or the multiple precision parameters
3691
depending on the parameters dp and mp. If mp only, then the file names
3692
get the 'mp_' prefix.
3695
fsock = self.open('%sintparam_definition.inc'%
3696
('mp_' if mp and not dp else ''), format='fortran')
3184
3698
fsock.write_comments(\
3185
3699
"Parameters that should not be recomputed event by event.\n")
3186
3700
fsock.writelines("if(readlha) then\n")
3187
fsock.writelines("G = 2 * DSQRT(AS*PI) ! for the first init\n")
3702
fsock.writelines("G = 2 * DSQRT(AS*PI) ! for the first init\n")
3704
fsock.writelines("MP__G = 2 * SQRT(MP__AS*MP__PI) ! for the first init\n")
3188
3705
for param in self.params_indep:
3189
3706
if param.name == 'ZERO':
3191
fsock.writelines("%s = %s\n" % (param.name,
3709
fsock.writelines("%s = %s\n" % (param.name,
3192
3710
self.p_to_f.parse(param.expr)))
3712
fsock.writelines("%s%s = %s\n" % (self.mp_prefix,param.name,
3713
self.mp_p_to_f.parse(param.expr)))
3194
3715
fsock.writelines('endif')
3196
3717
fsock.write_comments('\nParameters that should be recomputed at an event by even basis.\n')
3197
fsock.writelines("aS = G**2/4/pi\n")
3719
fsock.writelines("aS = G**2/4/pi\n")
3721
fsock.writelines("MP__aS = MP__G**2/4/MP__PI\n")
3198
3722
for param in self.params_dep:
3199
fsock.writelines("%s = %s\n" % (param.name,
3724
fsock.writelines("%s = %s\n" % (param.name,
3200
3725
self.p_to_f.parse(param.expr)))
3727
fsock.writelines("%s%s = %s\n" % (self.mp_prefix,param.name,
3728
self.mp_p_to_f.parse(param.expr)))
3202
3730
fsock.write_comments("\nDefinition of the EW coupling used in the write out of aqed\n")
3203
3731
if ('aEWM1',) in self.model['parameters']:
3204
fsock.writelines(""" gal(1) = 3.5449077018110318 / DSQRT(aEWM1)
3733
fsock.writelines(""" gal(1) = 3.5449077018110318 / DSQRT(aEWM1)
3737
fsock.writelines(""" %(mp_prefix)sgal(1) = 2 * SQRT(MP__PI/MP__aEWM1)
3738
%(mp_prefix)sgal(2) = 1d0
3739
""" %{'mp_prefix':self.mp_prefix})
3208
logger.warning('$RED aEWM1 not define in MODEL. AQED will not be written correcty in LHE FILE')
3209
fsock.writelines(""" gal(1) = 1d0
3743
logger.warning('$RED aEWM1 not define in MODEL. AQED will not be written correcty in LHE FILE')
3744
fsock.writelines(""" gal(1) = 1d0
3748
fsock.writelines(""" %(mp_prefix)sgal(1) = 1e0_16
3749
%(mp_prefix)sgal(2) = 1e0_16
3750
"""%{'mp_prefix':self.mp_prefix})
3214
3753
def create_couplings(self):
3285
3845
for i in range(nb_coup_dep)]))
3286
3846
fsock.writelines('''\n return \n end\n''')
3288
def create_couplings_part(self, nb_file, data):
3289
""" create couplings[nb_file].f containing information coming from data
3849
fsock.writelines("""subroutine mp_update_as_param()
3853
fsock.writelines("""%s MP__PI, MP__ZERO
3854
parameter (MP__PI=3.1415926535897932384626433832795e0_16)
3855
parameter (MP__ZERO=0e0_16)
3856
include \'mp_input.inc\'
3857
include \'mp_coupl.inc\'
3858
"""%self.mp_real_format)
3859
fsock.writelines("""include \'input.inc\'
3860
include \'coupl.inc\'
3861
include \'actualize_mp_ext_params.inc\'
3863
include \'mp_intparam_definition.inc\'\n
3866
nb_coup_indep = 1 + len(self.coups_indep) // nb_def_by_file
3867
nb_coup_dep = 1 + len(self.coups_dep) // nb_def_by_file
3869
fsock.write_comments('\ncouplings needed to be evaluated points by points\n')
3871
fsock.writelines('\n'.join(\
3872
['call mp_coup%s()' % (nb_coup_indep + i + 1) \
3873
for i in range(nb_coup_dep)]))
3874
fsock.writelines('''\n return \n end\n''')
3876
def create_couplings_part(self, nb_file, data, dp=True, mp=False):
3877
""" create couplings[nb_file].f containing information coming from data.
3878
Outputs the computation of the double precision and/or the multiple
3879
precision couplings depending on the parameters dp and mp.
3880
If mp is True and dp is False, then the prefix 'MP_' is appended to the
3881
filename and subroutine name.
3292
fsock = self.open('couplings%s.f' % nb_file, format='fortran')
3293
fsock.writelines("""subroutine coup%s()
3297
parameter (PI=3.141592653589793d0)
3304
for coupling in data:
3305
fsock.writelines('%s = %s' % (coupling.name,
3884
fsock = self.open('%scouplings%s.f' %('mp_' if mp and not dp else '',
3885
nb_file), format='fortran')
3886
fsock.writelines("""subroutine %scoup%s()
3888
implicit none"""%('mp_' if mp and not dp else '',nb_file))
3890
fsock.writelines("""
3892
parameter (PI=3.141592653589793d0)
3894
include 'coupl.inc'""")
3896
fsock.writelines("""%s MP__PI
3897
parameter (MP__PI=3.1415926535897932384626433832795e0_16)
3898
include \'mp_input.inc\'
3899
include \'mp_coupl.inc\'
3900
"""%self.mp_real_format)
3901
fsock.writelines("""
3902
include 'model_functions.inc'""")
3903
for coupling in data:
3905
fsock.writelines('%s = %s' % (coupling.name,
3306
3906
self.p_to_f.parse(coupling.expr)))
3908
fsock.writelines('%s%s = %s' % (self.mp_prefix,coupling.name,
3909
self.mp_p_to_f.parse(coupling.expr)))
3307
3910
fsock.writelines('end')
3912
def create_model_functions_inc(self):
3913
""" Create model_functions.inc which contains the various declarations
3914
of auxiliary functions which might be used in the couplings expressions
3917
fsock = self.open('model_functions.inc', format='fortran')
3918
fsock.writelines("""double complex cond
3919
double complex reglog""")
3921
fsock.writelines("""%(complex_mp_format)s mp_cond
3922
%(complex_mp_format)s mp_reglog"""\
3923
%{'complex_mp_format':self.mp_complex_format})
3925
def create_model_functions_def(self):
3926
""" Create model_functions.f which contains the various definitions
3927
of auxiliary functions which might be used in the couplings expressions
3928
Add the functions.f functions for formfactors support
3931
fsock = self.open('model_functions.f', format='fortran')
3932
fsock.writelines("""double complex function cond(condition,truecase,falsecase)
3934
double complex condition,truecase,falsecase
3935
if(condition.eq.(0.0d0,0.0d0)) then
3942
double complex function reglog(arg)
3945
if(arg.eq.(0.0d0,0.0d0)) then
3946
reglog=(0.0d0,0.0d0)
3952
fsock.writelines("""
3954
%(complex_mp_format)s function mp_cond(condition,truecase,falsecase)
3956
%(complex_mp_format)s condition,truecase,falsecase
3957
if(condition.eq.(0.0e0_16,0.0e0_16)) then
3964
%(complex_mp_format)s function mp_reglog(arg)
3966
%(complex_mp_format)s arg
3967
if(arg.eq.(0.0e0_16,0.0e0_16)) then
3968
mp_reglog=(0.0e0_16,0.0e0_16)
3972
end"""%{'complex_mp_format':self.mp_complex_format})
3974
#check for the file functions.f
3975
model_path = self.model.get('modelpath')
3976
if os.path.exists(pjoin(model_path,'Fortran','functions.f')):
3977
fsock.write_comment_line(' USER DEFINE FUNCTIONS ')
3978
input = pjoin(self.model_path,'Fortran','functions.f')
3979
fsock.writelines(open(input).read())
3980
fsock.write_comment_line(' END USER DEFINE FUNCTIONS ')
3310
3982
def create_makeinc(self):
3311
3983
"""create makeinc.inc containing the file to compile """
3313
3985
fsock = self.open('makeinc.inc', comment='#')
3314
text = 'MODEL = couplings.o lha_read.o printout.o rw_para.o '
3986
text = 'MODEL = couplings.o lha_read.o printout.o rw_para.o'
3987
text += ' model_functions.o '
3316
3989
nb_coup_indep = 1 + len(self.coups_dep) // 25
3317
3990
nb_coup_dep = 1 + len(self.coups_indep) // 25
3318
text += ' '.join(['couplings%s.o' % (i+1) \
3319
for i in range(nb_coup_dep + nb_coup_indep) ])
3991
couplings_files=['couplings%s.o' % (i+1) \
3992
for i in range(nb_coup_dep + nb_coup_indep) ]
3994
couplings_files+=['mp_couplings%s.o' % (i+1) for i in \
3995
range(nb_coup_dep,nb_coup_dep + nb_coup_indep) ]
3996
text += ' '.join(couplings_files)
3320
3997
fsock.writelines(text)
3322
3999
def create_param_write(self):
3366
4043
external_param = [format(param) for param in self.params_ext]
3367
4044
fsock.writelines('\n'.join(external_param))
4046
def create_actualize_mp_ext_param_inc(self):
4047
""" create the actualize_mp_ext_params.inc code """
4049
# In principle one should actualize all external, but for now, it is
4050
# hardcoded that only AS and MU_R can by dynamically changed by the user
4051
# so that we only update those ones.
4052
# Of course, to be on the safe side, one could decide to update all
4053
# external parameters.
4054
update_params_list=[p for p in self.params_ext if p.name in
4055
self.PS_dependent_key]
4057
res_strings = ["%(mp_prefix)s%(name)s=%(name)s"\
4058
%{'mp_prefix':self.mp_prefix,'name':param.name}\
4059
for param in update_params_list]
4060
# When read_lha is false, it is G which is taken in input and not AS, so
4061
# this is what should be reset here too.
4062
if 'aS' in [param.name for param in update_params_list]:
4063
res_strings.append("%(mp_prefix)sG=G"%{'mp_prefix':self.mp_prefix})
4065
fsock = self.open('actualize_mp_ext_params.inc', format='fortran')
4066
fsock.writelines('\n'.join(res_strings))
3370
4068
def create_param_read(self):
3371
4069
"""create param_read"""
3373
if self.opt['export_format'] == 'madevent':
4071
if self.opt['export_format'] in ['madevent', 'FKS5_default', 'FKS5_optimized']:
3374
4072
fsock = self.open('param_read.inc', format='fortran')
3375
4073
fsock.writelines(' include \'../param_card.inc\'')
3420
4127
translator.make_valid_param_card(out_path, out_path2)
3421
4128
translator.convert_to_slha1(out_path)
3423
def ExportV4Factory(cmd, noclean):
4130
def ExportV4Factory(cmd, noclean, output_type='default'):
3424
4131
""" Determine which Export_v4 class is required. cmd is the command
3425
interface containing all potential usefull information."""
4132
interface containing all potential usefull information.
4133
The output_type argument specifies from which context the output
4134
is called. It is 'madloop' for MadLoop5, 'amcatnlo' for FKS5 output
4135
and 'default' for tree-level outputs."""
3427
4137
group_subprocesses = cmd.options['group_subprocesses']
3428
#check if we need to group processes
3429
if cmd.options['group_subprocesses'] == 'Auto':
3430
if cmd._curr_amps[0].get_ninitial() == 2:
3431
group_subprocesses = True
3433
group_subprocesses = False
3435
assert group_subprocesses in [True, False]
3438
opt = {'clean': not noclean,
3439
'complex_mass': cmd.options['complex_mass_scheme'],
3440
'export_format':cmd._export_format,
3441
'model': cmd._curr_model.get('name')}
3443
if cmd._export_format in ['standalone', 'matrix']:
3444
return ProcessExporterFortranSA(cmd._mgme_dir, cmd._export_dir, opt)
3445
elif cmd._export_format in ['madevent'] and group_subprocesses:
3446
return ProcessExporterFortranMEGroup(cmd._mgme_dir, cmd._export_dir,
3448
elif cmd._export_format in ['madevent']:
3449
return ProcessExporterFortranME(cmd._mgme_dir, cmd._export_dir,opt)
4139
# First treat the MadLoop5 standalone case
4140
if output_type=='madloop':
4141
import madgraph.loop.loop_exporters as loop_exporters
4142
if os.path.isdir(os.path.join(cmd._mgme_dir, 'Template/loop_material')):
4144
options = {'clean': not noclean,
4145
'complex_mass':cmd.options['complex_mass_scheme'],
4146
'export_format':'madloop',
4148
'loop_dir': os.path.join(cmd._mgme_dir, 'Template/loop_material'),
4149
'cuttools_dir': cmd._cuttools_dir,
4150
'fortran_compiler':cmd.options['fortran_compiler']}
4152
if not cmd.options['loop_optimized_output']:
4153
ExporterClass=loop_exporters.LoopProcessExporterFortranSA
4155
if all([amp['process']['has_born'] for amp in cmd._curr_amps]):
4156
ExporterClass=loop_exporters.LoopProcessOptimizedExporterFortranSA
4157
options['export_format'] = 'madloop_optimized'
4159
logger.warning('ML5 can only exploit the optimized output for '+\
4160
' processes with born diagrams. The optimization '+\
4161
' option is therefore turned off for this process.')
4162
ExporterClass=loop_exporters.LoopProcessExporterFortranSA
4163
options['export_format'] = 'madloop_default'
4164
return ExporterClass(cmd._mgme_dir, cmd._export_dir, options)
4166
raise MadGraph5Error('MG5_aMC cannot find the \'loop_material\' directory'+\
4167
' in %s'%str(cmd._mgme_dir))
4169
# Then treat the aMC@NLO output
4170
elif output_type=='amcatnlo':
4171
import madgraph.iolibs.export_fks as export_fks
4173
options = {'clean': not noclean,
4174
'complex_mass':cmd.options['complex_mass_scheme'],
4175
'export_format':'madloop',
4176
#use MP for HELAS only if there are virtual amps
4177
'mp':len(cmd._fks_multi_proc.get_virt_amplitudes()) > 0,
4178
'loop_dir': os.path.join(cmd._mgme_dir,'Template','loop_material'),
4179
'cuttools_dir': cmd._cuttools_dir,
4180
'fortran_compiler':cmd.options['fortran_compiler']}
4181
if not cmd.options['loop_optimized_output']:
4182
logger.info("Writing out the aMC@NLO code")
4183
ExporterClass = export_fks.ProcessExporterFortranFKS
4184
options['export_format']='FKS5_default'
4186
logger.info("Writing out the aMC@NLO code, using optimized Loops")
4187
ExporterClass = export_fks.ProcessOptimizedExporterFortranFKS
4188
options['export_format']='FKS5_optimized'
4189
return ExporterClass(cmd._mgme_dir, cmd._export_dir, options)
4191
# Then the default tree-level output
4192
elif output_type=='default':
4193
#check if we need to group processes
4194
if cmd.options['group_subprocesses'] == 'Auto':
4195
if cmd._curr_amps[0].get_ninitial() == 2:
4196
group_subprocesses = True
4198
group_subprocesses = False
4200
assert group_subprocesses in [True, False]
4202
opt = {'clean': not noclean,
4203
'complex_mass': cmd.options['complex_mass_scheme'],
4204
'export_format':cmd._export_format,
4206
'sa_symmetry':False,
4207
'model': cmd._curr_model.get('name') }
4209
format = cmd._export_format #shortcut
4211
if format in ['standalone_msP', 'standalone_msF', 'standalone_rw']:
4212
opt['sa_symmetry'] = True
4214
if format == 'matrix' or format.startswith('standalone'):
4215
return ProcessExporterFortranSA(cmd._mgme_dir, cmd._export_dir, opt,
4218
elif format in ['madevent'] and group_subprocesses:
4219
return ProcessExporterFortranMEGroup(cmd._mgme_dir, cmd._export_dir,
4221
elif format in ['madevent']:
4222
return ProcessExporterFortranME(cmd._mgme_dir, cmd._export_dir,opt)
4225
raise Exception, 'Wrong export_v4 format'
3452
raise Exception, 'Wrong export_v4 format'
4227
raise MadGraph5Error, 'Output type %s not reckognized in ExportV4Factory.'