1 try:
2 import madgraph.iolibs.file_writers as writers
3 import madgraph.various.q_polynomial as q_polynomial
4 import madgraph.various.misc as misc
5 except Exception:
6 import aloha.file_writers as writers
7 import aloha.q_polynomial as q_polynomial
8 import aloha.misc as misc
9
10 import aloha
11 import aloha.aloha_lib as aloha_lib
12 import cmath
13 import os
14 import re
15 from numbers import Number
16 from collections import defaultdict
17 from fractions import Fraction
18
19 from cStringIO import StringIO
20
21
22 import itertools
23
24 KERNEL = aloha_lib.KERNEL
25 pjoin = os.path.join
28 """ Generic writing functions """
29
30 power_symbol = '**'
31 change_number_format = str
32 extension = ''
33 type_to_variable = {2:'F',3:'V',5:'T',1:'S',4:'R', -1:'S'}
34 type_to_size = {'S':3, 'T':18, 'V':6, 'F':6,'R':18}
35
36
37 - def __init__(self, abstract_routine, dirpath):
38 if aloha.loop_mode:
39 self.momentum_size = 4
40 else:
41 self.momentum_size = 2
42
43 self.has_model_parameter = False
44
45 name = get_routine_name(abstract = abstract_routine)
46
47 if dirpath:
48 self.dir_out = dirpath
49 self.out_path = os.path.join(dirpath, name + self.extension)
50 else:
51 self.out_path = None
52 self.dir_out = None
53
54 self.routine = abstract_routine
55 self.tag = self.routine.tag
56 self.name = name
57
58 self.particles = [self.type_to_variable[spin] for spin in \
59 abstract_routine.spins]
60
61 self.offshell = abstract_routine.outgoing
62 self.outgoing = self.offshell
63 if 'C%s' %((self.outgoing + 1) // 2) in self.tag:
64
65 self.outgoing = self.outgoing + self.outgoing % 2 - (self.outgoing +1) % 2
66 self.outname = '%s%s' % (self.particles[self.outgoing -1], \
67 self.outgoing)
68
69 self.declaration = Declaration_list()
70
71
73 """find the Fortran HELAS position for the list of index"""
74
75
76 if len(indices) == 1:
77 return indices[0] + start + self.momentum_size
78
79 try:
80
81 ind_name = self.routine.expr.lorentz_ind
82 except:
83
84 if len(set([tuple(expr.lorentz_ind) for expr in self.routine.expr.values()]))!=1:
85 raise Exception('All SplitCoefficients do not share the same indices names.')
86 for expr in self.routine.expr.values():
87 ind_name = expr.lorentz_ind
88 break
89
90 if ind_name == ['I3', 'I2']:
91 return 4 * indices[1] + indices[0] + start + self.momentum_size
92 elif len(indices) == 2:
93 return 4 * indices[0] + indices[1] + start + self.momentum_size
94 else:
95 raise Exception, 'WRONG CONTRACTION OF LORENTZ OBJECT for routine %s: %s' \
96 % (self.name, ind_name)
97
99 """ Prototype for language specific header"""
100 raise Exception, 'THis function should be overwritten'
101 return ''
102
104 """ Prototype for how to write the declaration of variable"""
105 return ''
106
107 - def define_content(self):
108 """Prototype for language specific body"""
109 pass
110
112 """ Prototype for the definition of the momenta"""
113 raise Exception, 'THis function should be overwritten'
114
116 """find the sign associated to the momentum conservation"""
117
118
119 signs = []
120 nb_fermion =0
121
122
123
124 global_sign = -1
125
126 flipped = [2*(int(c[1:])-1) for c in self.tag if c.startswith('C')]
127 for index, spin in enumerate(self.particles):
128 assert(spin in ['S','F','V','T', 'R'])
129
130
131 if 1:
132 sign = -1 * global_sign
133 elif nb_fermion % 2 == 0:
134 sign = global_sign
135 nb_fermion += 1
136 if index in flipped:
137 sign *= -1
138 else:
139 sign = -1 * global_sign
140 nb_fermion += 1
141 if index-1 in flipped:
142 sign *= -1
143
144
145 if index == self.outgoing -1:
146 signs.append('0*')
147 continue
148
149 if sign == 1:
150 signs.append('+')
151 else:
152 signs.append('-')
153 return signs
154
155
157
158 type = self.particles[index - 1]
159 energy_pos = self.type_to_size[type] -1
160 sign = 1
161 if self.outgoing == index:
162 sign = -1
163
164
165
166
167
168
169
170
171
172
173 if sign == -1 :
174 return '-'
175 else:
176 return ''
177
178
179
180
181
185
187 """define a list with the string of object required as incoming argument"""
188
189 call_arg = []
190
191 conjugate = [2*(int(c[1:])-1) for c in self.tag if c[0] == 'C']
192
193
194 for index,spin in enumerate(self.particles):
195 if self.offshell == index + 1:
196 continue
197
198 if index in conjugate:
199 index2, spin2 = index+1, self.particles[index+1]
200 call_arg.append(('list_complex','%s%d' % (spin2, index2 +1)))
201
202 elif index-1 in conjugate:
203 index2, spin2 = index-1, self.particles[index-1]
204 call_arg.append(('list_complex','%s%d' % (spin2, index2 +1)))
205 else:
206 call_arg.append(('list_complex','%s%d' % (spin, index +1)))
207
208
209 if couplings is None:
210 detected_couplings = [name for type, name in self.declaration if name.startswith('COUP')]
211 coup_sort = lambda x,y: int(x[4:])-int(y[4:])
212 detected_couplings.sort(coup_sort)
213 if detected_couplings:
214 couplings = detected_couplings
215 else:
216 couplings = ['COUP']
217
218 for coup in couplings:
219 call_arg.append(('complex', coup))
220 self.declaration.add(('complex',coup))
221
222 if self.offshell:
223 if aloha.complex_mass:
224 call_arg.append(('complex','M%s' % self.outgoing))
225 self.declaration.add(('complex','M%s' % self.outgoing))
226 else:
227 call_arg.append(('double','M%s' % self.outgoing))
228 self.declaration.add(('double','M%s' % self.outgoing))
229 call_arg.append(('double','W%s' % self.outgoing))
230 self.declaration.add(('double','W%s' % self.outgoing))
231
232 assert len(call_arg) == len(set([a[1] for a in call_arg]))
233 assert len(self.declaration) == len(set([a[1] for a in self.declaration])), self.declaration
234 self.call_arg = call_arg
235 return call_arg
236
237 - def write(self, mode=None):
265
266
268 """Routine for making a string out of indices objects"""
269
270 text = 'output(%s)' % indices
271 return text
272
292
294 """Turn a multvariable into a string"""
295
296 mult_list = [self.write_variable_id(id) for id in obj]
297 data = {'factors': '*'.join(mult_list)}
298 if prefactor and obj.prefactor != 1:
299 if obj.prefactor != -1:
300 text = '%(prefactor)s * %(factors)s'
301 data['prefactor'] = self.change_number_format(obj.prefactor)
302 else:
303 text = '-%(factors)s'
304 else:
305 text = '%(factors)s'
306 return text % data
307
309 """Turn a multvariable into a string"""
310
311 mult_list = [self.write_obj(id) for id in obj]
312 data = {'factors': '*'.join(mult_list)}
313 if prefactor and obj.prefactor != 1:
314 if obj.prefactor != -1:
315 text = '%(prefactor)s * %(factors)s'
316 data['prefactor'] = self.change_number_format(obj.prefactor)
317 else:
318 text = '-%(factors)s'
319 else:
320 text = '%(factors)s'
321 return text % data
322
323
325 """Turns addvariable into a string"""
326
327 data = defaultdict(list)
328 number = []
329 [data[p.prefactor].append(p) if hasattr(p, 'prefactor') else number.append(p)
330 for p in obj]
331
332 file_str = StringIO()
333
334 if prefactor and obj.prefactor != 1:
335 formatted = self.change_number_format(obj.prefactor)
336 if formatted.startswith(('+','-')):
337 file_str.write('(%s)' % formatted)
338 else:
339 file_str.write(formatted)
340 file_str.write('*(')
341 else:
342 file_str.write('(')
343 first=True
344 for value, obj_list in data.items():
345 add= '+'
346 if value not in [-1,1]:
347 nb_str = self.change_number_format(value)
348 if nb_str[0] in ['+','-']:
349 file_str.write(nb_str)
350 else:
351 file_str.write('+')
352 file_str.write(nb_str)
353 file_str.write('*(')
354 elif value == -1:
355 add = '-'
356 file_str.write('-')
357 elif not first:
358 file_str.write('+')
359 else:
360 file_str.write('')
361 first = False
362 file_str.write(add.join([self.write_obj(obj, prefactor=False)
363 for obj in obj_list]))
364 if value not in [1,-1]:
365 file_str.write(')')
366 if number:
367 total = sum(number)
368 file_str.write('+ %s' % self.change_number_format(total))
369
370 file_str.write(')')
371 return file_str.getvalue()
372
375
380
388
389
390
392 """find the way to write the call of the functions"""
393
394 if outgoing is None:
395 outgoing = self.offshell
396
397 call_arg = []
398
399 conjugate = [2*(int(c[1:])-1) for c in self.tag if c[0] == 'C']
400
401 for index,spin in enumerate(self.particles):
402 if self.offshell == index + 1:
403 continue
404
405 if index in conjugate:
406 index2, spin2 = index+1, self.particles[index+1]
407 call_arg.append('%s%d' % (spin2, index2 +1))
408
409 elif index-1 in conjugate:
410 index2, spin2 = index-1, self.particles[index-1]
411 call_arg.append('%s%d' % (spin2, index2 +1))
412 else:
413 call_arg.append('%s%d' % (spin, index +1))
414
415
416 return call_arg
417
418
420 """ make the list of declaration nedded by the header """
421
422 declare_list = []
423
424
425 for index, spin in enumerate(self.particles):
426
427 declare_list.append(self.declare_dict[spin] % (index + 1) )
428
429 return declare_list
430
436 """routines for writing out Fortran"""
437
438 extension = '.f'
439 writer = writers.FortranWriter
440
441 type2def = {}
442 type2def['int'] = 'integer*4'
443 if aloha.mp_precision:
444 type2def['double'] = 'real*16'
445 type2def['complex'] = 'complex*32'
446 format = 'q0'
447 else:
448 type2def['double'] = 'real*8'
449 type2def['complex'] = 'complex*16'
450
451 format = 'd0'
452
483
484
485
487 """Define the Header of the fortran file.
488 """
489 if name is None:
490 name = self.name
491
492 out = StringIO()
493
494
495 arguments = [arg for format, arg in self.define_argument_list(couplings)]
496 if not self.offshell:
497 output = 'vertex'
498 self.declaration.add(('complex','vertex'))
499 else:
500 output = '%(spin)s%(id)d' % {
501 'spin': self.particles[self.outgoing -1],
502 'id': self.outgoing}
503 self.declaration.add(('list_complex', output))
504
505 out.write('subroutine %(name)s(%(args)s,%(output)s)\n' % \
506 {'output':output, 'name': name, 'args': ', '.join(arguments)})
507
508 return out.getvalue()
509
511 """ Prototype for how to write the declaration of variable
512 Include the symmetry line (entry FFV_2)
513 """
514
515 out = StringIO()
516 out.write('implicit none\n')
517
518 if self.has_model_parameter:
519 out.write(' include "../MODEL/input.inc"\n')
520 out.write(' include "../MODEL/coupl.inc"\n')
521 argument_var = [name for type,name in self.call_arg]
522
523 if 'MP' in self.tag:
524 out.write(' complex*32 CI\n')
525 if KERNEL.has_pi:
526 out.write(' double*16 PI\n')
527 else:
528 out.write(' complex*16 CI\n')
529 if KERNEL.has_pi:
530 out.write(' double precision PI\n')
531 out.write(' parameter (CI=(%s,%s))\n' %
532 (self.change_number_format(0),self.change_number_format(1)))
533 if KERNEL.has_pi:
534 out.write(' parameter (PI=%s)\n' % self.change_number_format(cmath.pi))
535 for type, name in self.declaration:
536 if type.startswith('list'):
537 type = type[5:]
538
539 if name in argument_var:
540 size ='*'
541 elif name.startswith('P'):
542 size='0:3'
543 elif name[0] in ['F','V']:
544 if aloha.loop_mode:
545 size = 8
546 else:
547 size = 6
548 elif name[0] == 'S':
549 if aloha.loop_mode:
550 size = 5
551 else:
552 size = 3
553 elif name[0] in ['R','T']:
554 if aloha.loop_mode:
555 size = 20
556 else:
557 size = 18
558 else:
559 size = '*'
560
561 out.write(' %s %s(%s)\n' % (self.type2def[type], name, size))
562 elif type == 'fct':
563 if name.upper() in ['EXP','LOG','SIN','COS','ASIN','ACOS']:
564 continue
565 out.write(' %s %s\n' % (self.type2def['complex'], name))
566 out.write(' external %s\n' % (name))
567 else:
568 out.write(' %s %s\n' % (self.type2def[type], name))
569
570
571
572
573
574
575
576
577 couplings = [name for type, name in self.declaration if name.startswith('COUP') ]
578 couplings.sort()
579 for elem in self.routine.symmetries:
580 new_name = self.name.rsplit('_',1)[0] + '_%s' % elem
581 out.write('%s\n' % self.get_header_txt(new_name, couplings).replace('subroutine','entry'))
582
583
584 return out.getvalue()
585
587 """Define the Header of the fortran file. This include
588 - momentum conservation
589 - definition of the impulsion"""
590
591 out = StringIO()
592
593
594 p = []
595
596 signs = self.get_momentum_conservation_sign()
597
598 for i,type in enumerate(self.particles):
599 if self.declaration.is_used('OM%s' % (i+1)):
600 out.write(" OM{0} = {1}\n if (M{0}.ne.{1}) OM{0}={2}/M{0}**2\n".format(
601 i+1, self.change_number_format(0), self.change_number_format(1)))
602
603 if i+1 == self.outgoing:
604 out_type = type
605 out_size = self.type_to_size[type]
606 continue
607 elif self.offshell:
608 p.append('{0}{1}{2}(%(i)s)'.format(signs[i],type,i+1,type))
609
610 if self.declaration.is_used('P%s' % (i+1)):
611 self.get_one_momenta_def(i+1, out)
612
613
614 if self.offshell:
615 energy_pos = out_size -2
616 type = self.particles[self.outgoing-1]
617
618 for i in range(self.momentum_size):
619 dict_energy = {'i':1+i}
620 out.write(' %s%s(%s) = %s\n' % (type,self.outgoing, 1+i,
621 ''.join(p) % dict_energy))
622 if self.declaration.is_used('P%s' % self.outgoing):
623 self.get_one_momenta_def(self.outgoing, out)
624
625
626
627 return out.getvalue()
628
630
631 type = self.particles[i-1]
632
633 if aloha.loop_mode:
634 template ='P%(i)d(%(j)d) = %(sign)s%(type)s%(i)d(%(nb)d)\n'
635 else:
636 template ='P%(i)d(%(j)d) = %(sign)s%(operator)s(%(type)s%(i)d(%(nb2)d))\n'
637
638 nb2 = 1
639 for j in range(4):
640 if not aloha.loop_mode:
641 nb = j + 1
642 if j == 0:
643 assert not aloha.mp_precision
644 operator = 'dble'
645 elif j == 1:
646 nb2 += 1
647 elif j == 2:
648 assert not aloha.mp_precision
649 operator = 'dimag'
650 elif j ==3:
651 nb2 -= 1
652 else:
653 operator =''
654 nb = 1+ j
655 nb2 = 1 + j
656 strfile.write(template % {'j':j,'type': type, 'i': i,
657 'nb': nb, 'nb2': nb2, 'operator':operator,
658 'sign': self.get_P_sign(i)})
659
661 """shift the indices for non impulsion object"""
662 if match.group('var').startswith('P'):
663 shift = 0
664 else:
665 shift = self.momentum_size
666 return '%s(%s)' % (match.group('var'), int(match.group('num')) + shift)
667
669 """Formatting the variable name to Fortran format"""
670
671 if isinstance(name, aloha_lib.ExtVariable):
672
673 self.has_model_parameter = True
674 if name.lower() in ['pi', 'as', 'mu_r', 'aewm1','g']:
675 return name
676 return '%s%s' % (aloha.aloha_prefix, name)
677
678 if '_' in name:
679 vtype = name.type
680 decla = name.split('_',1)[0]
681 self.declaration.add(('list_%s' % vtype, decla))
682 else:
683 self.declaration.add((name.type, name))
684 name = re.sub('(?P<var>\w*)_(?P<num>\d+)$', self.shift_indices , name)
685 return name
686
695
696 if isinteger(number):
697 out = '%s%s' % (str(int(number)),self.format)
698 elif isinstance(number, complex):
699 if number.imag:
700 if number.real:
701 out = '(%s + %s*CI)' % (self.change_number_format(number.real), \
702 self.change_number_format(number.imag))
703 else:
704 if number.imag == 1:
705 out = 'CI'
706 elif number.imag == -1:
707 out = '-CI'
708 else:
709 out = '%s * CI' % self.change_number_format(number.imag)
710 else:
711 out = '%s' % (self.change_number_format(number.real))
712 else:
713 tmp = Fraction(str(number))
714 tmp = tmp.limit_denominator(100)
715 if not abs(tmp - number) / abs(tmp + number) < 1e-8:
716 out = '%s%s' % (number, self.format)
717 else:
718 out = '%s%s/%s%s' % (tmp.numerator, self.format, tmp.denominator, self.format)
719 return out
720
722 """Define the functions in a 100% way """
723
724 out = StringIO()
725
726 if self.routine.contracted:
727 for name,obj in self.routine.contracted.items():
728 out.write(' %s = %s\n' % (name, self.write_obj(obj)))
729 self.declaration.add(('complex', name))
730
731
732 def sort_fct(a, b):
733 if len(a) < len(b):
734 return -1
735 elif len(a) > len(b):
736 return 1
737 elif a < b:
738 return -1
739 else:
740 return +1
741
742 keys = self.routine.fct.keys()
743 keys.sort(sort_fct)
744 for name in keys:
745 fct, objs = self.routine.fct[name]
746
747 format = ' %s = %s\n' % (name, self.get_fct_format(fct))
748 try:
749 text = format % ','.join([self.write_obj(obj) for obj in objs])
750 except TypeError:
751 text = format % tuple([self.write_obj(obj) for obj in objs])
752 finally:
753 out.write(text)
754
755
756 numerator = self.routine.expr
757 if not 'Coup(1)' in self.routine.infostr:
758 coup_name = 'COUP'
759 else:
760 coup_name = '%s' % self.change_number_format(1)
761
762
763 if not self.offshell:
764 if coup_name == 'COUP':
765 formatted = self.write_obj(numerator.get_rep([0]))
766 if formatted.startswith(('+','-')):
767 out.write(' vertex = COUP*(%s)\n' % formatted)
768 else:
769 out.write(' vertex = COUP*%s\n' % formatted)
770 else:
771 out.write(' vertex = %s\n' % self.write_obj(numerator.get_rep([0])))
772 else:
773 OffShellParticle = '%s%d' % (self.particles[self.offshell-1],\
774 self.offshell)
775 if 'L' not in self.tag:
776 coeff = 'denom*'
777 if not aloha.complex_mass:
778 if self.routine.denominator:
779 out.write(' denom = %(COUP)s/(%(denom)s)\n' % {'COUP': coup_name,\
780 'denom':self.write_obj(self.routine.denominator)})
781 else:
782 out.write(' denom = %(COUP)s/(P%(i)s(0)**2-P%(i)s(1)**2-P%(i)s(2)**2-P%(i)s(3)**2 - M%(i)s * (M%(i)s -CI* W%(i)s))\n' % \
783 {'i': self.outgoing, 'COUP': coup_name})
784 else:
785 if self.routine.denominator:
786 raise Exception, 'modify denominator are not compatible with complex mass scheme'
787
788 out.write(' denom = %(COUP)s/(P%(i)s(0)**2-P%(i)s(1)**2-P%(i)s(2)**2-P%(i)s(3)**2 - M%(i)s**2)\n' % \
789 {'i': self.outgoing, 'COUP': coup_name})
790 self.declaration.add(('complex','denom'))
791 if aloha.loop_mode:
792 ptype = 'list_complex'
793 else:
794 ptype = 'list_double'
795 self.declaration.add((ptype,'P%s' % self.outgoing))
796 else:
797 if coup_name == 'COUP':
798 coeff = 'COUP*'
799 else:
800 coeff = ''
801 to_order = {}
802 for ind in numerator.listindices():
803 formatted = self.write_obj(numerator.get_rep(ind))
804 if formatted.startswith(('+','-')):
805 formatted = '(%s)*%s' % tuple(formatted.split('*',1))
806 to_order[self.pass_to_HELAS(ind)] = \
807 ' %s(%d)= %s%s\n' % (self.outname, self.pass_to_HELAS(ind)+1,
808 coeff, formatted)
809 key = to_order.keys()
810 key.sort()
811 for i in key:
812 out.write(to_order[i])
813 return out.getvalue()
814
817
818
819
820
821
822
825
827 """Write routine for combine ALOHA call (more than one coupling)"""
828
829
830 if offshell is None:
831 sym = 1
832 offshell = self.offshell
833 else:
834 sym = None
835 name = combine_name(self.routine.name, lor_names, offshell, self.tag)
836 self.name = name
837
838 text = StringIO()
839 routine = StringIO()
840 data = {}
841
842
843 new_couplings = ['COUP%s' % (i+1) for i in range(len(lor_names)+1)]
844 text.write(self.get_header_txt(name=name, couplings=new_couplings))
845
846
847 data['addon'] = ''.join(self.tag) + '_%s' % self.offshell
848
849
850 argument = [name for format, name in self.define_argument_list(new_couplings)]
851 index= argument.index('COUP1')
852 data['before_coup'] = ','.join(argument[:index])
853 data['after_coup'] = ','.join(argument[index+len(lor_names)+1:])
854 if data['after_coup']:
855 data['after_coup'] = ',' + data['after_coup']
856
857 lor_list = (self.routine.name,) + lor_names
858 line = " call %(name)s%(addon)s(%(before_coup)s,%(coup)s%(after_coup)s,%(out)s)\n"
859 main = '%(spin)s%(id)d' % {'spin': self.particles[self.offshell -1],
860 'id': self.outgoing}
861 for i, name in enumerate(lor_list):
862 data['name'] = name
863 data['coup'] = 'COUP%d' % (i+1)
864 if i == 0:
865 if not offshell:
866 data['out'] = 'vertex'
867 else:
868 data['out'] = main
869 elif i==1:
870 if self.offshell:
871 type = self.particles[self.offshell-1]
872 self.declaration.add(('list_complex','%stmp' % type))
873 else:
874 type = ''
875 self.declaration.add(('complex','%stmp' % type))
876 data['out'] = '%stmp' % type
877 routine.write(line % data)
878 if i:
879 if not offshell:
880 routine.write( ' vertex = vertex + tmp\n')
881 else:
882 size = self.type_to_size[self.particles[offshell -1]] -2
883 routine.write(" do i = %s, %s\n" % (self.momentum_size+1, self.momentum_size+size))
884 routine.write(" %(main)s(i) = %(main)s(i) + %(tmp)s(i)\n" %\
885 {'main': main, 'tmp': data['out']})
886 routine.write(' enddo\n')
887 self.declaration.add(('int','i'))
888
889 self.declaration.discard(('complex','COUP'))
890 for name in aloha_lib.KERNEL.reduced_expr2:
891 self.declaration.discard(('complex', name))
892
893
894
895
896
897 text.write(self.get_declaration_txt())
898 text.write(routine.getvalue())
899 text.write(self.get_foot_txt())
900
901
902 text = text.getvalue()
903 if self.out_path:
904 writer = self.writer(self.out_path,'a')
905 commentstring = 'This File is Automatically generated by ALOHA \n'
906 commentstring += 'The process calculated in this file is: \n'
907 commentstring += self.routine.infostr + '\n'
908 writer.write_comments(commentstring)
909 writer.writelines(text)
910 return text
911
913 """routines for writing out Fortran"""
914
915 type2def = {}
916 type2def['int'] = 'integer*4'
917 type2def['double'] = 'real*16'
918 type2def['complex'] = 'complex*32'
919 format = 'q0'
920
925
927 """routines for writing out Fortran"""
928
929 - def __init__(self, abstract_routine, dirpath):
930
931 ALOHAWriterForFortran.__init__(self, abstract_routine, dirpath)
932
933 self.l_id = [int(c[1:]) for c in abstract_routine.tag if c[0] == 'L'][0]
934 self.l_helas_id = self.l_id
935 if 'C%s' %((self.l_id + 1) // 2) in abstract_routine.tag:
936
937 self.l_helas_id += self.l_id % 2 - (self.l_id +1) % 2
938
939
941 """Define the functions in a 100% way """
942
943 out = StringIO()
944
945 if self.routine.contracted:
946 for name,obj in self.routine.contracted.items():
947 out.write(' %s = %s\n' % (name, self.write_obj(obj)))
948 self.declaration.add(('complex', name))
949
950 if not 'Coup(1)' in self.routine.infostr:
951 coup = True
952 else:
953 coup = False
954
955 rank = self.routine.expr.get_max_rank()
956 poly_object = q_polynomial.Polynomial(rank)
957 nb_coeff = q_polynomial.get_number_of_coefs_for_rank(rank)
958 size = self.type_to_size[self.particles[self.l_id-1]] - 2
959 for K in range(size):
960 for J in range(nb_coeff):
961 data = poly_object.get_coef_at_position(J)
962 arg = [data.count(i) for i in range(4)]
963 arg += [0] * (K) + [1] + [0] * (size-1-K)
964 try:
965 expr = self.routine.expr[tuple(arg)]
966 except KeyError:
967 expr = None
968 for ind in self.routine.expr.values()[0].listindices():
969 if expr:
970 data = expr.get_rep(ind)
971 else:
972 data = 0
973 if data and coup:
974 out.write(' COEFF(%s,%s,%s)= coup*%s\n' % (
975 self.pass_to_HELAS(ind)+1-self.momentum_size,
976 J, K+1, self.write_obj(data)))
977 else:
978 out.write(' COEFF(%s,%s,%s)= %s\n' % (
979 self.pass_to_HELAS(ind)+1-self.momentum_size,
980 J, K+1, self.write_obj(data)))
981
982
983 return out.getvalue()
984
986 """ Prototype for how to write the declaration of variable"""
987
988 out = StringIO()
989 out.write('implicit none\n')
990
991 if 'MP' in self.tag:
992 out.write(' complex*32 CI\n')
993 else:
994 out.write(' complex*16 CI\n')
995 out.write(' parameter (CI=(%s,%s))\n' %
996 (self.change_number_format(0),self.change_number_format(1)))
997 argument_var = [name for type,name in self.call_arg]
998 for type, name in self.declaration:
999 if type.startswith('list'):
1000 type = type[5:]
1001
1002 if name.startswith('P'):
1003 size='0:3'
1004 elif name in argument_var:
1005 size ='*'
1006 elif name[0] in ['F','V']:
1007 if aloha.loop_mode:
1008 size = 8
1009 else:
1010 size = 6
1011 elif name[0] == 'S':
1012 if aloha.loop_mode:
1013 size = 5
1014 else:
1015 size = 3
1016 elif name[0] in ['R','T']:
1017 if aloha.loop_mode:
1018 size = 20
1019 else:
1020 size = 18
1021 elif name == 'coeff':
1022 out.write("include 'coef_specs.inc'\n")
1023 size = 'MAXLWFSIZE,0:VERTEXMAXCOEFS-1,MAXLWFSIZE'
1024
1025 out.write(' %s %s(%s)\n' % (self.type2def[type], name, size))
1026 elif type == 'fct':
1027 if name.upper() in ['EXP','LOG','SIN','COS','ASIN','ACOS']:
1028 continue
1029 out.write(' %s %s\n' % (self.type2def['complex'], name))
1030 out.write(' external %s\n' % (name))
1031 else:
1032 out.write(' %s %s\n' % (self.type2def[type], name))
1033
1034 return out.getvalue()
1035
1036
1038 """define a list with the string of object required as incoming argument"""
1039
1040 conjugate = [2*(int(c[1:])-1) for c in self.tag if c[0] == 'C']
1041 call_arg = []
1042
1043 call_arg.append( ('list_complex', 'P%s'% self.l_helas_id) )
1044
1045 self.declaration.add(call_arg[0])
1046
1047 for index,spin in enumerate(self.particles):
1048 if self.outgoing == index + 1:
1049 continue
1050 if self.l_helas_id == index + 1:
1051 continue
1052 call_arg.append(('complex','%s%d' % (spin, index +1)))
1053 self.declaration.add(('list_complex', call_arg[-1][-1]))
1054
1055
1056 if couplings is None:
1057 detected_couplings = [name for type, name in self.declaration if name.startswith('COUP')]
1058 coup_sort = lambda x,y: int(x[4:])-int(y[4:])
1059 detected_couplings.sort(coup_sort)
1060 if detected_couplings:
1061 couplings = detected_couplings
1062 else:
1063 couplings = ['COUP']
1064
1065 for coup in couplings:
1066 call_arg.append(('complex', coup))
1067 self.declaration.add(('complex',coup))
1068
1069 if self.offshell:
1070 if aloha.complex_mass:
1071 call_arg.append(('complex','M%s' % self.outgoing))
1072 self.declaration.add(('complex','M%s' % self.outgoing))
1073 else:
1074 call_arg.append(('double','M%s' % self.outgoing))
1075 self.declaration.add(('double','M%s' % self.outgoing))
1076 call_arg.append(('double','W%s' % self.outgoing))
1077 self.declaration.add(('double','W%s' % self.outgoing))
1078
1079 self.call_arg = call_arg
1080
1081 return call_arg
1082
1084 """Define the Header of the ortran file. This include
1085 - momentum conservation
1086 - definition of the impulsion"""
1087
1088 out = StringIO()
1089
1090
1091 p = []
1092 size = []
1093
1094 signs = self.get_momentum_conservation_sign()
1095
1096 for i,type in enumerate(self.particles):
1097 if self.declaration.is_used('OM%s' % (i+1)):
1098 out.write(" OM{0} = {1}\n if (M{0}.ne.{1}) OM{0}={2}/M{0}**2\n".format(
1099 i+1, self.change_number_format(0), self.change_number_format(1)))
1100
1101 if i+1 == self.outgoing:
1102 out_type = 'P'
1103 continue
1104 elif i+1 == self.l_helas_id:
1105 p.append('%sP%s({%s})' % (signs[i],i+1,len(size)))
1106 size.append(0)
1107 continue
1108 elif self.offshell:
1109 p.append('%s%s%s({%s})' % (signs[i],type,i+1,len(size)))
1110 size.append(1)
1111
1112 if self.declaration.is_used('P%s' % (i+1)):
1113 self.get_one_momenta_def(i+1, out)
1114
1115
1116 if self.offshell:
1117 if aloha.loop_mode:
1118 size_p = 4
1119 else:
1120 size_p = 2
1121 for i in range(size_p):
1122 out.write(' P%s(%s) = %s\n' % (self.outgoing, i,
1123 ''.join(p).format(*[s+i for s in size])))
1124
1125
1126
1127 return out.getvalue()
1128
1129
1131 """return the position for the argument in the HELAS convention"""
1132
1133 loop_momentum = key[:4]
1134 basis = key[4:]
1135
1136 loop_pos = sum([loop_momentum[i] * (i+1) for i in range(4)])
1137 basis_pos = sum([basis[i] * (i+1) for i in range(len(basis))])
1138 return (str(loop_pos), str(basis_pos))
1139
1140
1141
1142
1143
1144
1146 """Define the Header of the fortran file. This include
1147 - function tag
1148 - definition of variable
1149 """
1150 if name is None:
1151 name = self.name
1152
1153 out = StringIO()
1154
1155
1156 arguments = [arg for format, arg in self.define_argument_list(couplings)]
1157 self.declaration.add(('list_complex', 'P%s'% self.outgoing))
1158 self.declaration.add(('list_complex', 'P%s'% self.l_helas_id))
1159 self.declaration.add(('list_complex', 'coeff'))
1160 out.write('subroutine %(name)s(%(args)s, P%(out)s, COEFF)\n' % \
1161 {'name': name, 'args': ', '.join(arguments),
1162 'out':self.outgoing})
1163
1164 return out.getvalue()
1165
1167 """routines for writing out Fortran"""
1168
1171
1173 """ build the name of the aloha function """
1174
1175 assert (name and outgoing is not None) or abstract
1176
1177 if tag is None:
1178 tag = list(abstract.tag)
1179 else:
1180 tag=list(tag)
1181
1182 if name is None:
1183 prefix=''
1184 if 'MP' in tag:
1185 prefix = 'MP_'
1186 tag.remove('MP')
1187 if any(t.startswith('P') for t in tag):
1188
1189 propa = [t for t in tag if t.startswith('P')][0]
1190 tag.remove(propa)
1191 tag.append(propa)
1192 name = prefix + abstract.name + ''.join(tag)
1193
1194 if outgoing is None:
1195 outgoing = abstract.outgoing
1196
1197 return '%s_%s' % (name, outgoing)
1198
1199 -def combine_name(name, other_names, outgoing, tag=None, unknown_propa=False):
1200 """ build the name for combined aloha function """
1201
1202
1203
1204 p=re.compile('^(?P<type>[RFSVT]{2,})(?P<id>\d+)$')
1205 routine = ''
1206 if p.search(name):
1207 base, id = p.search(name).groups()
1208 routine = name
1209 for s in other_names:
1210 try:
1211 base2,id2 = p.search(s).groups()
1212 except Exception:
1213 routine = ''
1214 break
1215 if base != base2:
1216 routine = ''
1217 break
1218 else:
1219 routine += '_%s' % id2
1220
1221 if routine:
1222 if tag is not None:
1223 routine += ''.join(tag)
1224 if unknown_propa and outgoing:
1225 routine += '%(propa)s'
1226 if outgoing is not None:
1227 return routine +'_%s' % outgoing
1228 else:
1229 return routine
1230
1231 if tag is not None:
1232 addon = ''.join(tag)
1233 else:
1234 addon = ''
1235 if 'C' in name:
1236 short_name, addon = name.split('C',1)
1237 try:
1238 addon = 'C' + str(int(addon))
1239 except Exception:
1240 addon = ''
1241 else:
1242 name = short_name
1243 if unknown_propa:
1244 addon += '%(propa)s'
1245
1246 if outgoing is not None:
1247 return '_'.join((name,) + tuple(other_names)) + addon + '_%s' % outgoing
1248 else:
1249 return '_'.join((name,) + tuple(other_names)) + addon
1250
1252 """Routines for writing out helicity amplitudes as C++ .h and .cc files."""
1253
1254 extension = '.c'
1255 writer = writers.CPPWriter
1256
1257 type2def = {}
1258 type2def['int'] = 'int'
1259 type2def['double'] = 'double '
1260 type2def['complex'] = 'complex<double> '
1261
1262
1263 realoperator = '.real()'
1264 imagoperator = '.imag()'
1265 ci_definition = ' complex<double> cI = complex<double>(0.,1.);\n'
1266
1267
1276
1277 if isinteger(number):
1278 out = '%s.' % (str(int(number)))
1279 elif isinstance(number, complex):
1280 if number.imag:
1281 if number.real:
1282 out = '(%s + %s*cI)' % (self.change_number_format(number.real), \
1283 self.change_number_format(number.imag))
1284 else:
1285 if number.imag == 1:
1286 out = 'cI'
1287 elif number.imag == -1:
1288 out = '-cI'
1289 else:
1290 out = '%s * cI' % self.change_number_format(number.imag)
1291 else:
1292 out = '%s' % (self.change_number_format(number.real))
1293 else:
1294 tmp = Fraction(str(number))
1295 tmp = tmp.limit_denominator(100)
1296 if not abs(tmp - number) / abs(tmp + number) < 1e-8:
1297 out = '%.9f' % (number)
1298 else:
1299 out = '%s./%s.' % (tmp.numerator, tmp.denominator)
1300 return out
1301
1302
1304 """shift the indices for non impulsion object"""
1305 if match.group('var').startswith('P'):
1306 shift = 0
1307 else:
1308 shift = self.momentum_size - 1
1309 return '%s[%s]' % (match.group('var'), int(match.group('num')) + shift)
1310
1311
1313 """Format the variable name to C++ format"""
1314
1315 if '_' in name:
1316 type = name.type
1317 decla = name.split('_',1)[0]
1318 self.declaration.add(('list_%s' % type, decla))
1319 else:
1320 self.declaration.add((name.type, name.split('_',1)[0]))
1321 name = re.sub('(?P<var>\w*)_(?P<num>\d+)$', self.shift_indices , name)
1322 return name
1323
1346
1347
1348
1349
1351 """Define the Header of the fortran file. This include
1352 - function tag
1353 - definition of variable
1354 """
1355 if name is None:
1356 name = self.name
1357
1358 if mode=='':
1359 mode = self.mode
1360
1361
1362
1363 out = StringIO()
1364
1365 if not 'no_include' in mode:
1366 out.write('#include \"%s.h\"\n\n' % self.name)
1367 args = []
1368 for format, argname in self.define_argument_list(couplings):
1369 if format.startswith('list'):
1370 type = self.type2def[format[5:]]
1371 list_arg = '[]'
1372 else:
1373 type = self.type2def[format]
1374 list_arg = ''
1375 args.append('%s%s%s'% (type, argname, list_arg))
1376
1377 if not self.offshell:
1378 output = 'complex<double> & vertex'
1379
1380 else:
1381 output = 'complex<double> %(spin)s%(id)d[]' % {
1382 'spin': self.particles[self.outgoing -1],
1383 'id': self.outgoing}
1384 self.declaration.add(('list_complex', output))
1385
1386 out.write('void %(name)s(%(args)s,%(output)s)' % \
1387 {'output':output, 'name': name, 'args': ', '.join(args)})
1388 if 'is_h' in mode:
1389 out.write(';\n')
1390 else:
1391 out.write('\n{\n')
1392
1393 return out.getvalue()
1394
1396 """ Prototype for how to write the declaration of variable
1397 Include the symmetry line (entry FFV_2)
1398 """
1399
1400 out = StringIO()
1401 argument_var = [name for type,name in self.call_arg]
1402
1403 out.write(self.ci_definition)
1404
1405 for type, name in self.declaration:
1406 if type.startswith('list'):
1407 type = type[5:]
1408 if name.startswith('P'):
1409 size = 4
1410 elif not 'tmp' in name:
1411 continue
1412
1413 elif name[0] in ['F','V']:
1414 if aloha.loop_mode:
1415 size = 8
1416 else:
1417 size = 6
1418 elif name[0] == 'S':
1419 if aloha.loop_mode:
1420 size = 5
1421 else:
1422 size = 3
1423 elif name[0] in ['R','T']:
1424 if aloha.loop_mode:
1425 size = 20
1426 else:
1427 size = 18
1428
1429 out.write(' %s %s[%s];\n' % (self.type2def[type], name, size))
1430 elif (type, name) not in self.call_arg:
1431 out.write(' %s %s;\n' % (self.type2def[type], name))
1432
1433 return out.getvalue()
1434
1438
1440 """Define the Header of the fortran file. This include
1441 - momentum conservation
1442 - definition of the impulsion"""
1443
1444 out = StringIO()
1445
1446
1447 p = []
1448
1449 signs = self.get_momentum_conservation_sign()
1450
1451 for i,type in enumerate(self.particles):
1452 if self.declaration.is_used('OM%s' % (i+1)):
1453 out.write(" OM{0} = {1};\n if (M{0} != {1})\n OM{0}={2}/pow(M{0},2);\n".format(
1454 i+1, self.change_number_format(0), self.change_number_format(1)))
1455
1456 if i+1 == self.outgoing:
1457 out_type = type
1458 out_size = self.type_to_size[type]
1459 continue
1460 elif self.offshell:
1461 p.append('{0}{1}{2}[%(i)s]'.format(signs[i],type,i+1,type))
1462
1463 if self.declaration.is_used('P%s' % (i+1)):
1464 self.get_one_momenta_def(i+1, out)
1465
1466
1467 if self.offshell:
1468 energy_pos = out_size -2
1469 type = self.particles[self.outgoing-1]
1470 if aloha.loop_mode:
1471 size_p = 4
1472 else:
1473 size_p = 2
1474
1475 for i in range(size_p):
1476 dict_energy = {'i':i}
1477 out.write(' %s%s[%s] = %s;\n' % (type,self.outgoing, i,
1478 ''.join(p) % dict_energy))
1479 if self.declaration.is_used('P%s' % self.outgoing):
1480 self.get_one_momenta_def(self.outgoing, out)
1481
1482
1483
1484 return out.getvalue()
1485
1487
1488 type = self.particles[i-1]
1489
1490 if aloha.loop_mode:
1491 template ='P%(i)d[%(j)d] = %(sign)s%(type)s%(i)d[%(nb)d];\n'
1492 else:
1493 template ='P%(i)d[%(j)d] = %(sign)s%(type)s%(i)d[%(nb2)d]%(operator)s;\n'
1494
1495 nb2 = 0
1496 for j in range(4):
1497 if not aloha.loop_mode:
1498 nb = j
1499 if j == 0:
1500 assert not aloha.mp_precision
1501 operator = self.realoperator
1502 elif j == 1:
1503 nb2 += 1
1504 elif j == 2:
1505 assert not aloha.mp_precision
1506 operator = self.imagoperator
1507 elif j ==3:
1508 nb2 -= 1
1509 else:
1510 operator =''
1511 nb = j
1512 nb2 = j
1513 strfile.write(template % {'j':j,'type': type, 'i': i,
1514 'nb': nb, 'nb2': nb2, 'operator':operator,
1515 'sign': self.get_P_sign(i)})
1516
1517
1519 """Write the helicity amplitude in C++ format"""
1520
1521 out = StringIO()
1522
1523 if self.routine.contracted:
1524 for name,obj in self.routine.contracted.items():
1525 out.write(' %s = %s;\n' % (name, self.write_obj(obj)))
1526 self.declaration.add(('complex', name))
1527
1528 for name, (fct, objs) in self.routine.fct.items():
1529 format = ' %s = %s;\n' % (name, self.get_fct_format(fct))
1530 out.write(format % ','.join([self.write_obj(obj) for obj in objs]))
1531
1532
1533
1534 numerator = self.routine.expr
1535 if not 'Coup(1)' in self.routine.infostr:
1536 coup_name = 'COUP'
1537 else:
1538 coup_name = '%s' % self.change_number_format(1)
1539 if not self.offshell:
1540 if coup_name == 'COUP':
1541 out.write(' vertex = COUP*%s;\n' % self.write_obj(numerator.get_rep([0])))
1542 else:
1543 out.write(' vertex = %s;\n' % self.write_obj(numerator.get_rep([0])))
1544 else:
1545 OffShellParticle = '%s%d' % (self.particles[self.offshell-1],\
1546 self.offshell)
1547 if 'L' not in self.tag:
1548 coeff = 'denom'
1549 if not aloha.complex_mass:
1550 if self.routine.denominator:
1551 out.write(' denom = %(COUP)s/(%(denom)s)\n' % {'COUP': coup_name,\
1552 'denom':self.write_obj(self.routine.denominator)})
1553 else:
1554 out.write(' denom = %(coup)s/(pow(P%(i)s[0],2)-pow(P%(i)s[1],2)-pow(P%(i)s[2],2)-pow(P%(i)s[3],2) - M%(i)s * (M%(i)s -cI* W%(i)s));\n' % \
1555 {'i': self.outgoing, 'coup': coup_name})
1556 else:
1557 if self.routine.denominator:
1558 raise Exception, 'modify denominator are not compatible with complex mass scheme'
1559
1560 out.write(' denom = %(coup)s/(pow(P%(i)s[0],2)-pow(P%(i)s[1],2)-pow(P%(i)s[2],2)-pow(P%(i)s[3],2) - pow(M%(i)s,2));\n' % \
1561 {'i': self.outgoing, 'coup': coup_name})
1562 self.declaration.add(('complex','denom'))
1563 if aloha.loop_mode:
1564 ptype = 'list_complex'
1565 else:
1566 ptype = 'list_double'
1567 self.declaration.add((ptype,'P%s' % self.outgoing))
1568 else:
1569 coeff = 'COUP'
1570
1571 for ind in numerator.listindices():
1572 out.write(' %s[%d]= %s*%s;\n' % (self.outname,
1573 self.pass_to_HELAS(ind), coeff,
1574 self.write_obj(numerator.get_rep(ind))))
1575 return out.getvalue()
1576
1577 remove_double = re.compile('complex<double> (?P<name>[\w]+)\[\]')
1579 """Write the call for symmetric routines"""
1580 number = self.offshell
1581 arguments = [name for format, name in self.define_argument_list()]
1582 new_name = self.name.rsplit('_')[0] + '_%s' % new_nb
1583 output = '%(spin)s%(id)d' % {
1584 'spin': self.particles[self.offshell -1],
1585 'id': self.outgoing}
1586 return '%s\n %s(%s,%s);\n}' % \
1587 (self.get_header_txt(new_name, couplings, mode='no_include'),
1588 self.name, ','.join(arguments), output)
1589
1590 - def get_h_text(self,couplings=None):
1591 """Return the full contents of the .h file"""
1592
1593 h_string = StringIO()
1594 if not self.mode == 'no_include':
1595 h_string.write('#ifndef '+ self.name + '_guard\n')
1596 h_string.write('#define ' + self.name + '_guard\n')
1597 h_string.write('#include <complex>\n')
1598 h_string.write('using namespace std;\n\n')
1599
1600 h_header = self.get_header_txt(mode='no_include__is_h', couplings=couplings)
1601 h_string.write(h_header)
1602
1603 for elem in self.routine.symmetries:
1604 symmetryhead = h_header.replace( \
1605 self.name,self.name[0:-1]+'%s' %(elem))
1606 h_string.write(symmetryhead)
1607
1608 if not self.mode == 'no_include':
1609 h_string.write('#endif\n\n')
1610
1611 return h_string.getvalue()
1612
1613
1615 "Return the content of the .cc file linked to multiple lorentz call."
1616
1617
1618 if offshell is None:
1619 offshell = self.offshell
1620
1621 name = combine_name(self.routine.name, lor_names, offshell, self.tag)
1622 self.name = name
1623
1624 text = StringIO()
1625 routine = StringIO()
1626 data = {}
1627
1628
1629 new_couplings = ['COUP%s' % (i+1) for i in range(len(lor_names)+1)]
1630 text.write(self.get_header_txt(name=name, couplings=new_couplings, mode=mode))
1631
1632
1633 data['addon'] = ''.join(self.tag) + '_%s' % self.offshell
1634
1635
1636 argument = [name for format, name in self.define_argument_list(new_couplings)]
1637 index= argument.index('COUP1')
1638 data['before_coup'] = ','.join(argument[:index])
1639 data['after_coup'] = ','.join(argument[index+len(lor_names)+1:])
1640 if data['after_coup']:
1641 data['after_coup'] = ',' + data['after_coup']
1642
1643 lor_list = (self.routine.name,) + lor_names
1644 line = " %(name)s%(addon)s(%(before_coup)s,%(coup)s%(after_coup)s,%(out)s);\n"
1645 main = '%(spin)s%(id)d' % {'spin': self.particles[self.offshell -1],
1646 'id': self.outgoing}
1647 for i, name in enumerate(lor_list):
1648 data['name'] = name
1649 data['coup'] = 'COUP%d' % (i+1)
1650 if i == 0:
1651 if not offshell:
1652 data['out'] = 'vertex'
1653 else:
1654 data['out'] = main
1655 elif i==1:
1656 if self.offshell:
1657 type = self.particles[self.offshell-1]
1658 self.declaration.add(('list_complex','%stmp' % type))
1659 else:
1660 type = ''
1661 self.declaration.add(('complex','%stmp' % type))
1662 data['out'] = '%stmp' % type
1663 routine.write(line % data)
1664 if i:
1665 if not offshell:
1666 routine.write( ' vertex = vertex + tmp;\n')
1667 else:
1668 size = self.type_to_size[self.particles[offshell -1]] -2
1669 routine.write(""" i= %s;\nwhile (i < %s)\n{\n""" % (self.momentum_size, self.momentum_size+size))
1670 routine.write(" %(main)s[i] = %(main)s[i] + %(tmp)s[i];\n i++;\n" %\
1671 {'main': main, 'tmp': data['out']})
1672 routine.write('}\n')
1673 self.declaration.add(('int','i'))
1674 self.declaration.discard(('complex','COUP'))
1675 for name in aloha_lib.KERNEL.reduced_expr2:
1676 self.declaration.discard(('complex', name))
1677
1678
1679
1680
1681 text.write(self.get_declaration_txt())
1682 text.write(routine.getvalue())
1683 text.write(self.get_foot_txt())
1684
1685 text = text.getvalue()
1686
1687 return text
1688
1689
1690 - def write(self, **opt):
1691 """Write the .h and .cc files"""
1692
1693 cc_text = WriteALOHA.write(self, **opt)
1694 h_text = self.get_h_text()
1695
1696
1697 if self.out_path:
1698 writer_h = writers.CPPWriter(self.out_path[:-len(self.extension)] + ".h")
1699 commentstring = 'This File is Automatically generated by ALOHA \n'
1700 commentstring += 'The process calculated in this file is: \n'
1701 commentstring += self.routine.infostr + '\n'
1702 writer_h.write_comments(commentstring)
1703 writer_h.writelines(h_text)
1704
1705 return h_text, cc_text
1706
1707
1708
1710 """Write the .h and .cc files associated to the combined file"""
1711
1712
1713 if offshell is None:
1714 sym = 1
1715 offshell = self.offshell
1716 else:
1717 sym = None
1718
1719 if mode == 'self':
1720
1721 self.mode = 'no_include'
1722
1723
1724
1725
1726 cc_text, h_text = StringIO() , StringIO()
1727 cc_text.write(self.write_combined_cc(lor_names, offshell, mode=mode,**opt))
1728 couplings = ['COUP%d' % (i+1) for i in range(len(lor_names)+1)]
1729
1730 if mode == 'self':
1731 self.mode = 'self'
1732 h_text.write(self.get_h_text(couplings=couplings))
1733
1734
1735 if sym:
1736 for elem in self.routine.symmetries:
1737 self.mode = 'no_include'
1738 cc_text.write( self.write_combined_cc(lor_names, elem))
1739
1740
1741 if self.out_path:
1742
1743 path = os.path.join(os.path.dirname(self.out_path), self.name)
1744 commentstring = 'This File is Automatically generated by ALOHA \n'
1745
1746 writer_h = writers.CPPWriter(path + ".h")
1747 writer_h.write_comments(commentstring)
1748 writer_h.writelines(h_text)
1749
1750 writer_cc = writers.CPPWriter(path + ".cc")
1751 writer_cc.write_comments(commentstring)
1752 writer_cc.writelines(cc_text)
1753
1754 return h_text.getvalue(), cc_text.getvalue()
1755
1758
1759 extension = '.cu'
1760 realoperator = '.re'
1761 imagoperator = '.im'
1762 ci_definition = 'complex<double> cI = mkcmplx(0., 1.);\n'
1763
1765 """Define the Header of the fortran file. This include
1766 - function tag
1767 - definition of variable
1768 """
1769 text = StringIO()
1770 if not 'is_h' in mode:
1771 text.write('__device__=__forceinclude__\n')
1772 text.write(ALOHAWriterForCPP.get_header_txt(self, name, couplings, mode))
1773 return text.getvalue()
1774
1775 - def get_h_text(self,couplings=None):
1776 """Return the full contents of the .h file"""
1777
1778 h_string = StringIO()
1779 if not self.mode == 'no_include':
1780 h_string.write('#ifndef '+ self.name + '_guard\n')
1781 h_string.write('#define ' + self.name + '_guard\n')
1782 h_string.write('#include "cmplx.h"\n')
1783 h_string.write('using namespace std;\n\n')
1784
1785 h_header = self.get_header_txt(mode='no_include__is_h', couplings=couplings)
1786 h_string.write(h_header)
1787
1788 for elem in self.routine.symmetries:
1789 symmetryhead = h_header.replace( \
1790 self.name,self.name[0:-1]+'%s' %(elem))
1791 h_string.write(symmetryhead)
1792
1793 if not self.mode == 'no_include':
1794 h_string.write('#endif\n\n')
1795
1796 return h_string.getvalue()
1797
1800 """ A class for returning a file/a string for python evaluation """
1801
1802 extension = '.py'
1803 writer = writers.PythonWriter
1804
1805 @staticmethod
1829
1830
1832 """shift the indices for non impulsion object"""
1833 if match.group('var').startswith('P'):
1834 shift = 0
1835 else:
1836 shift = -1 + self.momentum_size
1837
1838 return '%s[%s]' % (match.group('var'), int(match.group('num')) + shift)
1839
1841 """Formatting the variable name to Python format
1842 start to count at zero.
1843 No neeed to define the variable in python -> no need to keep track of
1844 the various variable
1845 """
1846
1847 if '_' not in name:
1848 self.declaration.add((name.type, name))
1849 else:
1850 self.declaration.add(('', name.split('_',1)[0]))
1851 name = re.sub('(?P<var>\w*)_(?P<num>\d+)$', self.shift_indices , name)
1852
1853 return name
1854
1880
1882 """Define the functions in a 100% way """
1883
1884 out = StringIO()
1885
1886 if self.routine.contracted:
1887 for name,obj in self.routine.contracted.items():
1888 out.write(' %s = %s\n' % (name, self.write_obj(obj)))
1889
1890 def sort_fct(a, b):
1891 if len(a) < len(b):
1892 return -1
1893 elif len(a) > len(b):
1894 return 1
1895 elif a < b:
1896 return -1
1897 else:
1898 return +1
1899
1900 keys = self.routine.fct.keys()
1901 keys.sort(sort_fct)
1902 for name in keys:
1903 fct, objs = self.routine.fct[name]
1904 format = ' %s = %s\n' % (name, self.get_fct_format(fct))
1905 try:
1906 text = format % ','.join([self.write_obj(obj) for obj in objs])
1907 except TypeError:
1908 text = format % tuple([self.write_obj(obj) for obj in objs])
1909 finally:
1910 out.write(text)
1911
1912
1913
1914 numerator = self.routine.expr
1915 if not 'Coup(1)' in self.routine.infostr:
1916 coup_name = 'COUP'
1917 else:
1918 coup_name = '%s' % self.change_number_format(1)
1919
1920 if not self.offshell:
1921 if coup_name == 'COUP':
1922 out.write(' vertex = COUP*%s\n' % self.write_obj(numerator.get_rep([0])))
1923 else:
1924 out.write(' vertex = %s\n' % self.write_obj(numerator.get_rep([0])))
1925 else:
1926 OffShellParticle = '%s%d' % (self.particles[self.offshell-1],\
1927 self.offshell)
1928
1929 if not 'L' in self.tag:
1930 coeff = 'denom'
1931 if not aloha.complex_mass:
1932 if self.routine.denominator:
1933 out.write(' denom = %(COUP)s/(%(denom)s)\n' % {'COUP': coup_name,\
1934 'denom':self.write_obj(self.routine.denominator)})
1935 else:
1936 out.write(' denom = %(coup)s/(P%(i)s[0]**2-P%(i)s[1]**2-P%(i)s[2]**2-P%(i)s[3]**2 - M%(i)s * (M%(i)s -1j* W%(i)s))\n' %
1937 {'i': self.outgoing,'coup':coup_name})
1938 else:
1939 if self.routine.denominator:
1940 raise Exception, 'modify denominator are not compatible with complex mass scheme'
1941
1942 out.write(' denom = %(coup)s/(P%(i)s[0]**2-P%(i)s[1]**2-P%(i)s[2]**2-P%(i)s[3]**2 - M%(i)s**2)\n' %
1943 {'i': self.outgoing,'coup':coup_name})
1944 else:
1945 coeff = 'COUP'
1946
1947 for ind in numerator.listindices():
1948 out.write(' %s[%d]= %s*%s\n' % (self.outname,
1949 self.pass_to_HELAS(ind), coeff,
1950 self.write_obj(numerator.get_rep(ind))))
1951 return out.getvalue()
1952
1958
1959
1961 """Define the Header of the fortran file. This include
1962 - function tag
1963 - definition of variable
1964 """
1965 if name is None:
1966 name = self.name
1967
1968 out = StringIO()
1969 out.write("import cmath\n")
1970 if self.mode == 'mg5':
1971 out.write('import aloha.template_files.wavefunctions as wavefunctions\n')
1972 else:
1973 out.write('import wavefunctions\n')
1974
1975
1976
1977
1978 arguments = [arg for format, arg in self.define_argument_list(couplings)]
1979 out.write('def %(name)s(%(args)s):\n' % \
1980 {'name': name, 'args': ','.join(arguments)})
1981
1982 return out.getvalue()
1983
1985 """Define the Header of the fortran file. This include
1986 - momentum conservation
1987 - definition of the impulsion"""
1988
1989 out = StringIO()
1990
1991
1992 p = []
1993
1994 signs = self.get_momentum_conservation_sign()
1995
1996 for i,type in enumerate(self.particles):
1997 if self.declaration.is_used('OM%s' % (i+1)):
1998 out.write(" OM{0} = 0.0\n if (M{0}): OM{0}=1.0/M{0}**2\n".format( (i+1) ))
1999 if i+1 == self.outgoing:
2000 out_type = type
2001 out_size = self.type_to_size[type]
2002 continue
2003 elif self.offshell:
2004 p.append('{0}{1}{2}[%(i)s]'.format(signs[i],type,i+1))
2005
2006 if self.declaration.is_used('P%s' % (i+1)):
2007 self.get_one_momenta_def(i+1, out)
2008
2009
2010 if self.offshell:
2011 type = self.particles[self.outgoing-1]
2012 out.write(' %s%s = wavefunctions.WaveFunction(size=%s)\n' % (type, self.outgoing, out_size))
2013 if aloha.loop_mode:
2014 size_p = 4
2015 else:
2016 size_p = 2
2017 for i in range(size_p):
2018 dict_energy = {'i':i}
2019
2020 out.write(' %s%s[%s] = %s\n' % (type,self.outgoing, i,
2021 ''.join(p) % dict_energy))
2022
2023 self.get_one_momenta_def(self.outgoing, out)
2024
2025
2026
2027 return out.getvalue()
2028
2030 """return the string defining the momentum"""
2031
2032 type = self.particles[i-1]
2033
2034 main = ' P%d = [' % i
2035 if aloha.loop_mode:
2036 template ='%(sign)s%(type)s%(i)d[%(nb)d]'
2037 else:
2038 template ='%(sign)scomplex(%(type)s%(i)d[%(nb2)d])%(operator)s'
2039
2040 nb2 = 0
2041 strfile.write(main)
2042 data = []
2043 for j in range(4):
2044 if not aloha.loop_mode:
2045 nb = j
2046 if j == 0:
2047 assert not aloha.mp_precision
2048 operator = '.real'
2049 elif j == 1:
2050 nb2 += 1
2051 elif j == 2:
2052 assert not aloha.mp_precision
2053 operator = '.imag'
2054 elif j ==3:
2055 nb2 -= 1
2056 else:
2057 operator =''
2058 nb = j
2059 nb2 = j
2060 data.append(template % {'j':j,'type': type, 'i': i,
2061 'nb': nb, 'nb2': nb2, 'operator':operator,
2062 'sign': self.get_P_sign(i)})
2063
2064 strfile.write(', '.join(data))
2065 strfile.write(']\n')
2066
2067
2074
2076 """Write routine for combine ALOHA call (more than one coupling)"""
2077
2078
2079 if offshell is None:
2080 sym = 1
2081 offshell = self.offshell
2082 else:
2083 sym = None
2084 name = combine_name(self.routine.name, lor_names, offshell, self.tag)
2085
2086 text = StringIO()
2087 data = {}
2088
2089
2090 new_couplings = ['COUP%s' % (i+1) for i in range(len(lor_names)+1)]
2091 text.write(self.get_header_txt(name=name, couplings=new_couplings))
2092
2093
2094 data['addon'] = ''.join(self.tag) + '_%s' % self.offshell
2095
2096
2097 argument = [name for format, name in self.define_argument_list(new_couplings)]
2098 index= argument.index('COUP1')
2099 data['before_coup'] = ','.join(argument[:index])
2100 data['after_coup'] = ','.join(argument[index+len(lor_names)+1:])
2101 if data['after_coup']:
2102 data['after_coup'] = ',' + data['after_coup']
2103
2104 lor_list = (self.routine.name,) + lor_names
2105 line = " %(out)s = %(name)s%(addon)s(%(before_coup)s,%(coup)s%(after_coup)s)\n"
2106 main = '%(spin)s%(id)d' % {'spin': self.particles[self.offshell -1],
2107 'id': self.outgoing}
2108 for i, name in enumerate(lor_list):
2109 data['name'] = name
2110 data['coup'] = 'COUP%d' % (i+1)
2111 if i == 0:
2112 if not offshell:
2113 data['out'] = 'vertex'
2114 else:
2115 data['out'] = main
2116 elif i==1:
2117 data['out'] = 'tmp'
2118 text.write(line % data)
2119 if i:
2120 if not offshell:
2121 text.write( ' vertex += tmp\n')
2122 else:
2123 size = self.type_to_size[self.particles[offshell -1]] -2
2124 text.write(" for i in range(%s,%s):\n" % (self.momentum_size, self.momentum_size+size))
2125 text.write(" %(main)s[i] += tmp[i]\n" %{'main': main})
2126
2127 text.write(self.get_foot_txt())
2128
2129
2130 if sym:
2131 for elem in self.routine.symmetries:
2132 text.write(self.write_combined(lor_names, mode, elem))
2133
2134 text = text.getvalue()
2135 if self.out_path:
2136 writer = self.writer(self.out_path)
2137 commentstring = 'This File is Automatically generated by ALOHA \n'
2138 commentstring += 'The process calculated in this file is: \n'
2139 commentstring += self.routine.infostr + '\n'
2140 writer.write_comments(commentstring)
2141 writer.writelines(text)
2142
2143
2144 return text
2145
2148
2150 if hasattr(self, 'var_name'):
2151 return var in self.var_name
2152 self.var_name = [name for type,name in self]
2153 return var in self.var_name
2154
2155 - def add(self,obj):
2156 if __debug__:
2157 type, name = obj
2158 samename = [t for t,n in self if n ==name]
2159 for type2 in samename:
2160 assert type2 == type, '%s is defined with two different type "%s" and "%s"' % \
2161 (name, type2, type)
2162
2163 set.add(self,obj)
2164
2167
2168 - def __new__(cls, data, language, outputdir, tags):
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222