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(' REAL ( KIND = 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 if name.startswith(aloha.aloha_prefix):
677 return name
678 return '%s%s' % (aloha.aloha_prefix, name)
679
680 if '_' in name:
681 vtype = name.type
682 decla = name.split('_',1)[0]
683 self.declaration.add(('list_%s' % vtype, decla))
684 else:
685 self.declaration.add((name.type, name))
686 name = re.sub('(?P<var>\w*)_(?P<num>\d+)$', self.shift_indices , name)
687 return name
688
697
698 if isinteger(number):
699 out = '%s%s' % (str(int(number)),self.format)
700 elif isinstance(number, complex):
701 if number.imag:
702 if number.real:
703 out = '(%s + %s*CI)' % (self.change_number_format(number.real), \
704 self.change_number_format(number.imag))
705 else:
706 if number.imag == 1:
707 out = 'CI'
708 elif number.imag == -1:
709 out = '-CI'
710 else:
711 out = '%s * CI' % self.change_number_format(number.imag)
712 else:
713 out = '%s' % (self.change_number_format(number.real))
714 else:
715 tmp = Fraction(str(number))
716 tmp = tmp.limit_denominator(100)
717 if not abs(tmp - number) / abs(tmp + number) < 1e-8:
718 out = '%s%s' % (number, self.format)
719 else:
720 out = '%s%s/%s%s' % (tmp.numerator, self.format, tmp.denominator, self.format)
721 return out
722
724 """Define the functions in a 100% way """
725
726 out = StringIO()
727
728 if self.routine.contracted:
729 for name,obj in self.routine.contracted.items():
730 out.write(' %s = %s\n' % (name, self.write_obj(obj)))
731 self.declaration.add(('complex', name))
732
733
734 def sort_fct(a, b):
735 if len(a) < len(b):
736 return -1
737 elif len(a) > len(b):
738 return 1
739 elif a < b:
740 return -1
741 else:
742 return +1
743
744 keys = self.routine.fct.keys()
745 keys.sort(sort_fct)
746 for name in keys:
747 fct, objs = self.routine.fct[name]
748
749 format = ' %s = %s\n' % (name, self.get_fct_format(fct))
750 try:
751 text = format % ','.join([self.write_obj(obj) for obj in objs])
752 except TypeError:
753 text = format % tuple([self.write_obj(obj) for obj in objs])
754 finally:
755 out.write(text)
756
757
758 numerator = self.routine.expr
759 if not 'Coup(1)' in self.routine.infostr:
760 coup_name = 'COUP'
761 else:
762 coup_name = '%s' % self.change_number_format(1)
763
764
765 if not self.offshell:
766 if coup_name == 'COUP':
767 formatted = self.write_obj(numerator.get_rep([0]))
768 if formatted.startswith(('+','-')):
769 out.write(' vertex = COUP*(%s)\n' % formatted)
770 else:
771 out.write(' vertex = COUP*%s\n' % formatted)
772 else:
773 out.write(' vertex = %s\n' % self.write_obj(numerator.get_rep([0])))
774 else:
775 OffShellParticle = '%s%d' % (self.particles[self.offshell-1],\
776 self.offshell)
777 if 'L' not in self.tag:
778 coeff = 'denom*'
779 if not aloha.complex_mass:
780 if self.routine.denominator:
781 out.write(' denom = %(COUP)s/(%(denom)s)\n' % {'COUP': coup_name,\
782 'denom':self.write_obj(self.routine.denominator)})
783 else:
784 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' % \
785 {'i': self.outgoing, 'COUP': coup_name})
786 else:
787 if self.routine.denominator:
788 raise Exception, 'modify denominator are not compatible with complex mass scheme'
789
790 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' % \
791 {'i': self.outgoing, 'COUP': coup_name})
792 self.declaration.add(('complex','denom'))
793 if aloha.loop_mode:
794 ptype = 'list_complex'
795 else:
796 ptype = 'list_double'
797 self.declaration.add((ptype,'P%s' % self.outgoing))
798 else:
799 if coup_name == 'COUP':
800 coeff = 'COUP*'
801 else:
802 coeff = ''
803 to_order = {}
804 for ind in numerator.listindices():
805 formatted = self.write_obj(numerator.get_rep(ind))
806 if formatted.startswith(('+','-')):
807 if '*' in formatted:
808 formatted = '(%s)*%s' % tuple(formatted.split('*',1))
809 else:
810 if formatted.startswith('+'):
811 formatted = formatted[1:]
812 else:
813 formatted = '(-1)*%s' % formatted[1:]
814 to_order[self.pass_to_HELAS(ind)] = \
815 ' %s(%d)= %s%s\n' % (self.outname, self.pass_to_HELAS(ind)+1,
816 coeff, formatted)
817 key = to_order.keys()
818 key.sort()
819 for i in key:
820 out.write(to_order[i])
821 return out.getvalue()
822
825
826
827
828
829
830
833
835 """Write routine for combine ALOHA call (more than one coupling)"""
836
837
838 if offshell is None:
839 sym = 1
840 offshell = self.offshell
841 else:
842 sym = None
843 name = combine_name(self.routine.name, lor_names, offshell, self.tag)
844 self.name = name
845
846 text = StringIO()
847 routine = StringIO()
848 data = {}
849
850
851 new_couplings = ['COUP%s' % (i+1) for i in range(len(lor_names)+1)]
852 text.write(self.get_header_txt(name=name, couplings=new_couplings))
853
854
855 data['addon'] = ''.join(self.tag) + '_%s' % self.offshell
856
857
858 argument = [name for format, name in self.define_argument_list(new_couplings)]
859 index= argument.index('COUP1')
860 data['before_coup'] = ','.join(argument[:index])
861 data['after_coup'] = ','.join(argument[index+len(lor_names)+1:])
862 if data['after_coup']:
863 data['after_coup'] = ',' + data['after_coup']
864
865 lor_list = (self.routine.name,) + lor_names
866 line = " call %(name)s%(addon)s(%(before_coup)s,%(coup)s%(after_coup)s,%(out)s)\n"
867 main = '%(spin)s%(id)d' % {'spin': self.particles[self.outgoing -1],
868 'id': self.outgoing}
869 for i, name in enumerate(lor_list):
870 data['name'] = name
871 data['coup'] = 'COUP%d' % (i+1)
872 if i == 0:
873 if not offshell:
874 data['out'] = 'vertex'
875 else:
876 data['out'] = main
877 elif i==1:
878 if self.offshell:
879 type = self.particles[self.outgoing-1]
880 self.declaration.add(('list_complex','%stmp' % type))
881 else:
882 type = ''
883 self.declaration.add(('complex','%stmp' % type))
884 data['out'] = '%stmp' % type
885 routine.write(line % data)
886 if i:
887 if not offshell:
888 routine.write( ' vertex = vertex + tmp\n')
889 else:
890 size = self.type_to_size[self.particles[self.outgoing -1]] -2
891 routine.write(" do i = %s, %s\n" % (self.momentum_size+1, self.momentum_size+size))
892 routine.write(" %(main)s(i) = %(main)s(i) + %(tmp)s(i)\n" %\
893 {'main': main, 'tmp': data['out']})
894 routine.write(' enddo\n')
895 self.declaration.add(('int','i'))
896
897 self.declaration.discard(('complex','COUP'))
898 for name in aloha_lib.KERNEL.reduced_expr2:
899 self.declaration.discard(('complex', name))
900
901
902
903
904
905 text.write(self.get_declaration_txt())
906 text.write(routine.getvalue())
907 text.write(self.get_foot_txt())
908
909
910 text = text.getvalue()
911 if self.out_path:
912 writer = self.writer(self.out_path,'a')
913 commentstring = 'This File is Automatically generated by ALOHA \n'
914 commentstring += 'The process calculated in this file is: \n'
915 commentstring += self.routine.infostr + '\n'
916 writer.write_comments(commentstring)
917 writer.writelines(text)
918 return text
919
921 """routines for writing out Fortran"""
922
923 type2def = {}
924 type2def['int'] = 'integer*4'
925 type2def['double'] = 'real*16'
926 type2def['complex'] = 'complex*32'
927 format = 'q0'
928
933
935 """routines for writing out Fortran"""
936
937 - def __init__(self, abstract_routine, dirpath):
938
939 ALOHAWriterForFortran.__init__(self, abstract_routine, dirpath)
940
941 self.l_id = [int(c[1:]) for c in abstract_routine.tag if c[0] == 'L'][0]
942 self.l_helas_id = self.l_id
943 if 'C%s' %((self.l_id + 1) // 2) in abstract_routine.tag:
944
945 self.l_helas_id += self.l_id % 2 - (self.l_id +1) % 2
946
947
949 """Define the functions in a 100% way """
950
951 out = StringIO()
952
953 if self.routine.contracted:
954 for name,obj in self.routine.contracted.items():
955 out.write(' %s = %s\n' % (name, self.write_obj(obj)))
956 self.declaration.add(('complex', name))
957
958 if not 'Coup(1)' in self.routine.infostr:
959 coup = True
960 else:
961 coup = False
962
963 rank = self.routine.expr.get_max_rank()
964 poly_object = q_polynomial.Polynomial(rank)
965 nb_coeff = q_polynomial.get_number_of_coefs_for_rank(rank)
966 size = self.type_to_size[self.particles[self.l_id-1]] - 2
967 for K in range(size):
968 for J in range(nb_coeff):
969 data = poly_object.get_coef_at_position(J)
970 arg = [data.count(i) for i in range(4)]
971 arg += [0] * (K) + [1] + [0] * (size-1-K)
972 try:
973 expr = self.routine.expr[tuple(arg)]
974 except KeyError:
975 expr = None
976 for ind in self.routine.expr.values()[0].listindices():
977 if expr:
978 data = expr.get_rep(ind)
979 else:
980 data = 0
981 if data and coup:
982 out.write(' COEFF(%s,%s,%s)= coup*%s\n' % (
983 self.pass_to_HELAS(ind)+1-self.momentum_size,
984 J, K+1, self.write_obj(data)))
985 else:
986 out.write(' COEFF(%s,%s,%s)= %s\n' % (
987 self.pass_to_HELAS(ind)+1-self.momentum_size,
988 J, K+1, self.write_obj(data)))
989
990
991 return out.getvalue()
992
994 """ Prototype for how to write the declaration of variable"""
995
996 out = StringIO()
997 out.write('implicit none\n')
998
999 if 'MP' in self.tag:
1000 out.write(' complex*32 CI\n')
1001 else:
1002 out.write(' complex*16 CI\n')
1003 out.write(' parameter (CI=(%s,%s))\n' %
1004 (self.change_number_format(0),self.change_number_format(1)))
1005 argument_var = [name for type,name in self.call_arg]
1006 for type, name in self.declaration:
1007 if type.startswith('list'):
1008 type = type[5:]
1009
1010 if name.startswith('P'):
1011 size='0:3'
1012 elif name in argument_var:
1013 size ='*'
1014 elif name[0] in ['F','V']:
1015 if aloha.loop_mode:
1016 size = 8
1017 else:
1018 size = 6
1019 elif name[0] == 'S':
1020 if aloha.loop_mode:
1021 size = 5
1022 else:
1023 size = 3
1024 elif name[0] in ['R','T']:
1025 if aloha.loop_mode:
1026 size = 20
1027 else:
1028 size = 18
1029 elif name == 'coeff':
1030 out.write("include 'coef_specs.inc'\n")
1031 size = 'MAXLWFSIZE,0:VERTEXMAXCOEFS-1,MAXLWFSIZE'
1032
1033 out.write(' %s %s(%s)\n' % (self.type2def[type], name, size))
1034 elif type == 'fct':
1035 if name.upper() in ['EXP','LOG','SIN','COS','ASIN','ACOS']:
1036 continue
1037 out.write(' %s %s\n' % (self.type2def['complex'], name))
1038 out.write(' external %s\n' % (name))
1039 else:
1040 out.write(' %s %s\n' % (self.type2def[type], name))
1041
1042 return out.getvalue()
1043
1044
1046 """define a list with the string of object required as incoming argument"""
1047
1048 conjugate = [2*(int(c[1:])-1) for c in self.tag if c[0] == 'C']
1049 call_arg = []
1050
1051 call_arg.append( ('list_complex', 'P%s'% self.l_helas_id) )
1052
1053 self.declaration.add(call_arg[0])
1054
1055 for index,spin in enumerate(self.particles):
1056 if self.outgoing == index + 1:
1057 continue
1058 if self.l_helas_id == index + 1:
1059 continue
1060 call_arg.append(('complex','%s%d' % (spin, index +1)))
1061 self.declaration.add(('list_complex', call_arg[-1][-1]))
1062
1063
1064 if couplings is None:
1065 detected_couplings = [name for type, name in self.declaration if name.startswith('COUP')]
1066 coup_sort = lambda x,y: int(x[4:])-int(y[4:])
1067 detected_couplings.sort(coup_sort)
1068 if detected_couplings:
1069 couplings = detected_couplings
1070 else:
1071 couplings = ['COUP']
1072
1073 for coup in couplings:
1074 call_arg.append(('complex', coup))
1075 self.declaration.add(('complex',coup))
1076
1077 if self.offshell:
1078 if aloha.complex_mass:
1079 call_arg.append(('complex','M%s' % self.outgoing))
1080 self.declaration.add(('complex','M%s' % self.outgoing))
1081 else:
1082 call_arg.append(('double','M%s' % self.outgoing))
1083 self.declaration.add(('double','M%s' % self.outgoing))
1084 call_arg.append(('double','W%s' % self.outgoing))
1085 self.declaration.add(('double','W%s' % self.outgoing))
1086
1087 self.call_arg = call_arg
1088
1089 return call_arg
1090
1092 """Define the Header of the ortran file. This include
1093 - momentum conservation
1094 - definition of the impulsion"""
1095
1096 out = StringIO()
1097
1098
1099 p = []
1100 size = []
1101
1102 signs = self.get_momentum_conservation_sign()
1103
1104 for i,type in enumerate(self.particles):
1105 if self.declaration.is_used('OM%s' % (i+1)):
1106 out.write(" OM{0} = {1}\n if (M{0}.ne.{1}) OM{0}={2}/M{0}**2\n".format(
1107 i+1, self.change_number_format(0), self.change_number_format(1)))
1108
1109 if i+1 == self.outgoing:
1110 out_type = 'P'
1111 continue
1112 elif i+1 == self.l_helas_id:
1113 p.append('%sP%s({%s})' % (signs[i],i+1,len(size)))
1114 size.append(0)
1115 continue
1116 elif self.offshell:
1117 p.append('%s%s%s({%s})' % (signs[i],type,i+1,len(size)))
1118 size.append(1)
1119
1120 if self.declaration.is_used('P%s' % (i+1)):
1121 self.get_one_momenta_def(i+1, out)
1122
1123
1124 if self.offshell:
1125 if aloha.loop_mode:
1126 size_p = 4
1127 else:
1128 size_p = 2
1129 for i in range(size_p):
1130 out.write(' P%s(%s) = %s\n' % (self.outgoing, i,
1131 ''.join(p).format(*[s+i for s in size])))
1132
1133
1134
1135 return out.getvalue()
1136
1137
1139 """return the position for the argument in the HELAS convention"""
1140
1141 loop_momentum = key[:4]
1142 basis = key[4:]
1143
1144 loop_pos = sum([loop_momentum[i] * (i+1) for i in range(4)])
1145 basis_pos = sum([basis[i] * (i+1) for i in range(len(basis))])
1146 return (str(loop_pos), str(basis_pos))
1147
1148
1149
1150
1151
1152
1154 """Define the Header of the fortran file. This include
1155 - function tag
1156 - definition of variable
1157 """
1158 if name is None:
1159 name = self.name
1160
1161 out = StringIO()
1162
1163
1164 arguments = [arg for format, arg in self.define_argument_list(couplings)]
1165 self.declaration.add(('list_complex', 'P%s'% self.outgoing))
1166 self.declaration.add(('list_complex', 'P%s'% self.l_helas_id))
1167 self.declaration.add(('list_complex', 'coeff'))
1168 out.write('subroutine %(name)s(%(args)s, P%(out)s, COEFF)\n' % \
1169 {'name': name, 'args': ', '.join(arguments),
1170 'out':self.outgoing})
1171
1172 return out.getvalue()
1173
1175 """routines for writing out Fortran"""
1176
1179
1181 """ build the name of the aloha function """
1182
1183 assert (name and outgoing is not None) or abstract
1184
1185 if tag is None:
1186 tag = list(abstract.tag)
1187 else:
1188 tag=list(tag)
1189
1190 if name is None:
1191 prefix=''
1192 if 'MP' in tag:
1193 prefix = 'MP_'
1194 tag.remove('MP')
1195 if any(t.startswith('P') for t in tag):
1196
1197 propa = [t for t in tag if t.startswith('P')][0]
1198 tag.remove(propa)
1199 tag.append(propa)
1200 name = prefix + abstract.name + ''.join(tag)
1201
1202 if outgoing is None:
1203 outgoing = abstract.outgoing
1204
1205 return '%s_%s' % (name, outgoing)
1206
1207 -def combine_name(name, other_names, outgoing, tag=None, unknown_propa=False):
1208 """ build the name for combined aloha function """
1209
1210 def myHash(target_string):
1211 if len(target_string)<50:
1212 return target_string
1213 if '%(propa)s' in target_string:
1214 return 'ALOHA_'+(str(hash(target_string.lower()))).replace('-','m')+'%(propa)s'
1215 else:
1216 return 'ALOHA_'+(str(hash(target_string.lower()))).replace('-','m')
1217
1218 if tag and any(t.startswith('P') for t in tag[:-1]):
1219
1220 for i,t in enumerate(tag):
1221 if t.startswith('P'):
1222 tag.pop(i)
1223 tag.append(t)
1224 break
1225
1226
1227
1228 p=re.compile('^(?P<type>[RFSVT]{2,})(?P<id>\d+)$')
1229 routine = ''
1230 if p.search(name):
1231 base, id = p.search(name).groups()
1232 routine = name
1233 for s in other_names:
1234 try:
1235 base2,id2 = p.search(s).groups()
1236 except Exception:
1237 routine = ''
1238 break
1239 if base != base2:
1240 routine = ''
1241 break
1242 else:
1243 routine += '_%s' % id2
1244
1245 if routine:
1246 if tag is not None:
1247 routine += ''.join(tag)
1248 if unknown_propa and outgoing:
1249 routine += '%(propa)s'
1250 if outgoing is not None:
1251 return myHash(routine)+'_%s' % outgoing
1252
1253 else:
1254 return myHash(routine)
1255
1256
1257 if tag is not None:
1258 addon = ''.join(tag)
1259 else:
1260 addon = ''
1261 if 'C' in name:
1262 short_name, addon = name.split('C',1)
1263 try:
1264 addon = 'C' + str(int(addon))
1265 except Exception:
1266 addon = ''
1267 else:
1268 name = short_name
1269 if unknown_propa:
1270 addon += '%(propa)s'
1271
1272
1273
1274
1275
1276
1277 if outgoing is not None:
1278 return myHash('_'.join((name,) + tuple(other_names))) + addon + '_%s' % outgoing
1279 else:
1280 return myHash('_'.join((name,) + tuple(other_names))) + addon
1281
1283 """Routines for writing out helicity amplitudes as C++ .h and .cc files."""
1284
1285 extension = '.c'
1286 writer = writers.CPPWriter
1287
1288 type2def = {}
1289 type2def['int'] = 'int '
1290 type2def['double'] = 'double '
1291 type2def['complex'] = 'std::complex<double> '
1292
1293
1294 realoperator = '.real()'
1295 imagoperator = '.imag()'
1296 ci_definition = 'static std::complex<double> cI = std::complex<double>(0.,1.);\n'
1297
1298
1307
1308 if isinteger(number):
1309 out = '%s.' % (str(int(number)))
1310 elif isinstance(number, complex):
1311 if number.imag:
1312 if number.real:
1313 out = '(%s + %s*cI)' % (self.change_number_format(number.real), \
1314 self.change_number_format(number.imag))
1315 else:
1316 if number.imag == 1:
1317 out = 'cI'
1318 elif number.imag == -1:
1319 out = '-cI'
1320 else:
1321 out = '%s * cI' % self.change_number_format(number.imag)
1322 else:
1323 out = '%s' % (self.change_number_format(number.real))
1324 else:
1325 tmp = Fraction(str(number))
1326 tmp = tmp.limit_denominator(100)
1327 if not abs(tmp - number) / abs(tmp + number) < 1e-8:
1328 out = '%.9f' % (number)
1329 else:
1330 out = '%s./%s.' % (tmp.numerator, tmp.denominator)
1331 return out
1332
1333
1335 """shift the indices for non impulsion object"""
1336 if match.group('var').startswith('P'):
1337 shift = 0
1338 else:
1339 shift = self.momentum_size - 1
1340 return '%s[%s]' % (match.group('var'), int(match.group('num')) + shift)
1341
1342
1344 """Format the variable name to C++ format"""
1345
1346 if '_' in name:
1347 type = name.type
1348 decla = name.split('_',1)[0]
1349 self.declaration.add(('list_%s' % type, decla))
1350 else:
1351 self.declaration.add((name.type, name.split('_',1)[0]))
1352 name = re.sub('(?P<var>\w*)_(?P<num>\d+)$', self.shift_indices , name)
1353 return name
1354
1377
1378
1379
1380
1382 """Define the Header of the fortran file. This include
1383 - function tag
1384 - definition of variable
1385 """
1386 if name is None:
1387 name = self.name
1388
1389 if mode=='':
1390 mode = self.mode
1391
1392
1393
1394 out = StringIO()
1395
1396 if not 'no_include' in mode:
1397 out.write('#include \"%s.h\"\n\n' % self.name)
1398 args = []
1399 for format, argname in self.define_argument_list(couplings):
1400 if format.startswith('list'):
1401 type = self.type2def[format[5:]]
1402 list_arg = '[]'
1403 else:
1404 type = self.type2def[format]
1405 list_arg = ''
1406 args.append('%s%s%s'% (type, argname, list_arg))
1407
1408 if not self.offshell:
1409 output = 'std::complex<double> & vertex'
1410
1411 else:
1412 output = 'std::complex<double> %(spin)s%(id)d[]' % {
1413 'spin': self.particles[self.outgoing -1],
1414 'id': self.outgoing}
1415 self.declaration.add(('list_complex', output))
1416
1417 out.write('void %(name)s(%(args)s,%(output)s)' % \
1418 {'output':output, 'name': name, 'args': ', '.join(args)})
1419 if 'is_h' in mode:
1420 out.write(';\n')
1421 else:
1422 out.write('\n{\n')
1423
1424 return out.getvalue()
1425
1427 """ Prototype for how to write the declaration of variable
1428 Include the symmetry line (entry FFV_2)
1429 """
1430
1431 out = StringIO()
1432 argument_var = [name for type,name in self.call_arg]
1433
1434 if add_i:
1435 out.write(self.ci_definition)
1436
1437 for type, name in self.declaration:
1438 if type.startswith('list'):
1439 type = type[5:]
1440 if name.startswith('P'):
1441 size = 4
1442 elif not 'tmp' in name:
1443 continue
1444
1445 elif name[0] in ['F','V']:
1446 if aloha.loop_mode:
1447 size = 8
1448 else:
1449 size = 6
1450 elif name[0] == 'S':
1451 if aloha.loop_mode:
1452 size = 5
1453 else:
1454 size = 3
1455 elif name[0] in ['R','T']:
1456 if aloha.loop_mode:
1457 size = 20
1458 else:
1459 size = 18
1460
1461 out.write(' %s %s[%s];\n' % (self.type2def[type], name, size))
1462 elif (type, name) not in self.call_arg:
1463 out.write(' %s %s;\n' % (self.type2def[type], name))
1464
1465 return out.getvalue()
1466
1470
1472 """Define the Header of the fortran file. This include
1473 - momentum conservation
1474 - definition of the impulsion"""
1475
1476 out = StringIO()
1477
1478
1479 p = []
1480
1481 signs = self.get_momentum_conservation_sign()
1482
1483 for i,type in enumerate(self.particles):
1484 if self.declaration.is_used('OM%s' % (i+1)):
1485 out.write(" OM{0} = {1};\n if (M{0} != {1})\n OM{0}={2}/(M{0}*M{0});\n".format(
1486 i+1, self.change_number_format(0), self.change_number_format(1)))
1487
1488 if i+1 == self.outgoing:
1489 out_type = type
1490 out_size = self.type_to_size[type]
1491 continue
1492 elif self.offshell:
1493 p.append('{0}{1}{2}[%(i)s]'.format(signs[i],type,i+1,type))
1494
1495 if self.declaration.is_used('P%s' % (i+1)):
1496 self.get_one_momenta_def(i+1, out)
1497
1498
1499 if self.offshell:
1500 energy_pos = out_size -2
1501 type = self.particles[self.outgoing-1]
1502 if aloha.loop_mode:
1503 size_p = 4
1504 else:
1505 size_p = 2
1506
1507 for i in range(size_p):
1508 dict_energy = {'i':i}
1509 out.write(' %s%s[%s] = %s;\n' % (type,self.outgoing, i,
1510 ''.join(p) % dict_energy))
1511 if self.declaration.is_used('P%s' % self.outgoing):
1512 self.get_one_momenta_def(self.outgoing, out)
1513
1514
1515
1516 return out.getvalue()
1517
1519
1520 type = self.particles[i-1]
1521
1522 if aloha.loop_mode:
1523 template ='P%(i)d[%(j)d] = %(sign)s%(type)s%(i)d[%(nb)d];\n'
1524 else:
1525 template ='P%(i)d[%(j)d] = %(sign)s%(type)s%(i)d[%(nb2)d]%(operator)s;\n'
1526
1527 nb2 = 0
1528 for j in range(4):
1529 if not aloha.loop_mode:
1530 nb = j
1531 if j == 0:
1532 assert not aloha.mp_precision
1533 operator = self.realoperator
1534 elif j == 1:
1535 nb2 += 1
1536 elif j == 2:
1537 assert not aloha.mp_precision
1538 operator = self.imagoperator
1539 elif j ==3:
1540 nb2 -= 1
1541 else:
1542 operator =''
1543 nb = j
1544 nb2 = j
1545 strfile.write(template % {'j':j,'type': type, 'i': i,
1546 'nb': nb, 'nb2': nb2, 'operator':operator,
1547 'sign': self.get_P_sign(i)})
1548
1549
1551 """Write the helicity amplitude in C++ format"""
1552
1553 out = StringIO()
1554
1555 if self.routine.contracted:
1556 for name,obj in self.routine.contracted.items():
1557 out.write(' %s = %s;\n' % (name, self.write_obj(obj)))
1558 self.declaration.add(('complex', name))
1559
1560 for name, (fct, objs) in self.routine.fct.items():
1561 format = ' %s = %s;\n' % (name, self.get_fct_format(fct))
1562 out.write(format % ','.join([self.write_obj(obj) for obj in objs]))
1563
1564
1565
1566 numerator = self.routine.expr
1567 if not 'Coup(1)' in self.routine.infostr:
1568 coup_name = 'COUP'
1569 else:
1570 coup_name = '%s' % self.change_number_format(1)
1571 if not self.offshell:
1572 if coup_name == 'COUP':
1573 out.write(' vertex = COUP*%s;\n' % self.write_obj(numerator.get_rep([0])))
1574 else:
1575 out.write(' vertex = %s;\n' % self.write_obj(numerator.get_rep([0])))
1576 else:
1577 OffShellParticle = '%s%d' % (self.particles[self.offshell-1],\
1578 self.offshell)
1579 if 'L' not in self.tag:
1580 coeff = 'denom'
1581 if not aloha.complex_mass:
1582 if self.routine.denominator:
1583 out.write(' denom = %(COUP)s/(%(denom)s)\n' % {'COUP': coup_name,\
1584 'denom':self.write_obj(self.routine.denominator)})
1585 else:
1586 out.write(' denom = %(coup)s/((P%(i)s[0]*P%(i)s[0])-(P%(i)s[1]*P%(i)s[1])-(P%(i)s[2]*P%(i)s[2])-(P%(i)s[3]*P%(i)s[3]) - M%(i)s * (M%(i)s -cI* W%(i)s));\n' % \
1587 {'i': self.outgoing, 'coup': coup_name})
1588 else:
1589 if self.routine.denominator:
1590 raise Exception, 'modify denominator are not compatible with complex mass scheme'
1591
1592 out.write(' denom = %(coup)s/((P%(i)s[0]*P%(i)s[0])-(P%(i)s[1]*P%(i)s[1])-(P%(i)s[2]*P%(i)s[2])-(P%(i)s[3]*P%(i)s[3]) - (M%(i)s*M%(i)s));\n' % \
1593 {'i': self.outgoing, 'coup': coup_name})
1594 self.declaration.add(('complex','denom'))
1595 if aloha.loop_mode:
1596 ptype = 'list_complex'
1597 else:
1598 ptype = 'list_double'
1599 self.declaration.add((ptype,'P%s' % self.outgoing))
1600 else:
1601 coeff = 'COUP'
1602
1603 for ind in numerator.listindices():
1604 out.write(' %s[%d]= %s*%s;\n' % (self.outname,
1605 self.pass_to_HELAS(ind), coeff,
1606 self.write_obj(numerator.get_rep(ind))))
1607 return out.getvalue()
1608
1609 remove_double = re.compile('std::complex<double> (?P<name>[\w]+)\[\]')
1611 """Write the call for symmetric routines"""
1612 number = self.offshell
1613 arguments = [name for format, name in self.define_argument_list()]
1614 new_name = self.name.rsplit('_')[0] + '_%s' % new_nb
1615 output = '%(spin)s%(id)d' % {
1616 'spin': self.particles[self.offshell -1],
1617 'id': self.outgoing}
1618 return '%s\n %s(%s,%s);\n}' % \
1619 (self.get_header_txt(new_name, couplings, mode='no_include'),
1620 self.name, ','.join(arguments), output)
1621
1622 - def get_h_text(self,couplings=None):
1623 """Return the full contents of the .h file"""
1624
1625 h_string = StringIO()
1626 if not self.mode == 'no_include':
1627 h_string.write('#ifndef '+ self.name + '_guard\n')
1628 h_string.write('#define ' + self.name + '_guard\n')
1629 h_string.write('#include <complex>\n\n')
1630
1631 h_header = self.get_header_txt(mode='no_include__is_h', couplings=couplings)
1632 h_string.write(h_header)
1633
1634 for elem in self.routine.symmetries:
1635 symmetryhead = h_header.replace( \
1636 self.name,self.name[0:-1]+'%s' %(elem))
1637 h_string.write(symmetryhead)
1638
1639 if not self.mode == 'no_include':
1640 h_string.write('#endif\n\n')
1641
1642 return h_string.getvalue()
1643
1644
1646 "Return the content of the .cc file linked to multiple lorentz call."
1647
1648
1649 if offshell is None:
1650 offshell = self.offshell
1651
1652 name = combine_name(self.routine.name, lor_names, offshell, self.tag)
1653 self.name = name
1654
1655 text = StringIO()
1656 routine = StringIO()
1657 data = {}
1658
1659
1660 new_couplings = ['COUP%s' % (i+1) for i in range(len(lor_names)+1)]
1661 text.write(self.get_header_txt(name=name, couplings=new_couplings, mode=mode))
1662
1663
1664 data['addon'] = ''.join(self.tag) + '_%s' % self.offshell
1665
1666
1667 argument = [name for format, name in self.define_argument_list(new_couplings)]
1668 index= argument.index('COUP1')
1669 data['before_coup'] = ','.join(argument[:index])
1670 data['after_coup'] = ','.join(argument[index+len(lor_names)+1:])
1671 if data['after_coup']:
1672 data['after_coup'] = ',' + data['after_coup']
1673
1674 lor_list = (self.routine.name,) + lor_names
1675 line = " %(name)s%(addon)s(%(before_coup)s,%(coup)s%(after_coup)s,%(out)s);\n"
1676 main = '%(spin)s%(id)d' % {'spin': self.particles[self.offshell -1],
1677 'id': self.outgoing}
1678 for i, name in enumerate(lor_list):
1679 data['name'] = name
1680 data['coup'] = 'COUP%d' % (i+1)
1681 if i == 0:
1682 if not offshell:
1683 data['out'] = 'vertex'
1684 else:
1685 data['out'] = main
1686 elif i==1:
1687 if self.offshell:
1688 type = self.particles[self.offshell-1]
1689 self.declaration.add(('list_complex','%stmp' % type))
1690 else:
1691 type = ''
1692 self.declaration.add(('complex','%stmp' % type))
1693 data['out'] = '%stmp' % type
1694 routine.write(line % data)
1695 if i:
1696 if not offshell:
1697 routine.write( ' vertex = vertex + tmp;\n')
1698 else:
1699 size = self.type_to_size[self.particles[offshell -1]] -2
1700 routine.write(""" i= %s;\nwhile (i < %s)\n{\n""" % (self.momentum_size, self.momentum_size+size))
1701 routine.write(" %(main)s[i] = %(main)s[i] + %(tmp)s[i];\n i++;\n" %\
1702 {'main': main, 'tmp': data['out']})
1703 routine.write('}\n')
1704 self.declaration.add(('int','i'))
1705 self.declaration.discard(('complex','COUP'))
1706 self.declaration.discard(('complex', 'denom'))
1707 if self.outgoing:
1708 self.declaration.discard(('list_double', 'P%s' % self.outgoing))
1709 self.declaration.discard(('double', 'OM%s' % self.outgoing))
1710 for name in aloha_lib.KERNEL.reduced_expr2:
1711 self.declaration.discard(('complex', name))
1712
1713
1714
1715 text.write(self.get_declaration_txt(add_i=False))
1716 text.write(routine.getvalue())
1717 text.write(self.get_foot_txt())
1718
1719 text = text.getvalue()
1720 return text
1721
1722
1723 - def write(self, **opt):
1724 """Write the .h and .cc files"""
1725
1726 cc_text = WriteALOHA.write(self, **opt)
1727 h_text = self.get_h_text()
1728
1729
1730 if self.out_path:
1731 writer_h = writers.CPPWriter(self.out_path[:-len(self.extension)] + ".h")
1732 commentstring = 'This File is Automatically generated by ALOHA \n'
1733 commentstring += 'The process calculated in this file is: \n'
1734 commentstring += self.routine.infostr + '\n'
1735 writer_h.write_comments(commentstring)
1736 writer_h.writelines(h_text)
1737
1738 return h_text, cc_text
1739
1740
1741
1743 """Write the .h and .cc files associated to the combined file"""
1744
1745
1746 if offshell is None:
1747 sym = 1
1748 offshell = self.offshell
1749 else:
1750 sym = None
1751
1752 if mode == 'self':
1753
1754 self.mode = 'no_include'
1755
1756
1757
1758
1759 cc_text, h_text = StringIO() , StringIO()
1760 cc_text.write(self.write_combined_cc(lor_names, offshell, mode=mode,**opt))
1761 couplings = ['COUP%d' % (i+1) for i in range(len(lor_names)+1)]
1762
1763 if mode == 'self':
1764 self.mode = 'self'
1765 h_text.write(self.get_h_text(couplings=couplings))
1766
1767
1768 if sym:
1769 for elem in self.routine.symmetries:
1770 self.mode = 'no_include'
1771 cc_text.write( self.write_combined_cc(lor_names, elem))
1772
1773
1774 if self.out_path:
1775
1776 path = os.path.join(os.path.dirname(self.out_path), self.name)
1777 commentstring = 'This File is Automatically generated by ALOHA \n'
1778
1779 writer_h = writers.CPPWriter(path + ".h")
1780 writer_h.write_comments(commentstring)
1781 writer_h.writelines(h_text.getvalue())
1782
1783 writer_cc = writers.CPPWriter(path + ".cc")
1784 writer_cc.write_comments(commentstring)
1785 writer_cc.writelines(cc_text.getvalue())
1786
1787 return h_text.getvalue(), cc_text.getvalue()
1788
1791
1792 extension = '.cu'
1793 realoperator = '.re'
1794 imagoperator = '.im'
1795 ci_definition = 'complex<double> cI = mkcmplx(0., 1.);\n'
1796
1798 """Define the Header of the fortran file. This include
1799 - function tag
1800 - definition of variable
1801 """
1802 text = StringIO()
1803 if not 'is_h' in mode:
1804 text.write('__device__=__forceinclude__\n')
1805 text.write(ALOHAWriterForCPP.get_header_txt(self, name, couplings, mode))
1806 return text.getvalue()
1807
1808 - def get_h_text(self,couplings=None):
1809 """Return the full contents of the .h file"""
1810
1811 h_string = StringIO()
1812 if not self.mode == 'no_include':
1813 h_string.write('#ifndef '+ self.name + '_guard\n')
1814 h_string.write('#define ' + self.name + '_guard\n')
1815 h_string.write('#include "cmplx.h"\n')
1816 h_string.write('using namespace std;\n\n')
1817
1818 h_header = self.get_header_txt(mode='no_include__is_h', couplings=couplings)
1819 h_string.write(h_header)
1820
1821 for elem in self.routine.symmetries:
1822 symmetryhead = h_header.replace( \
1823 self.name,self.name[0:-1]+'%s' %(elem))
1824 h_string.write(symmetryhead)
1825
1826 if not self.mode == 'no_include':
1827 h_string.write('#endif\n\n')
1828
1829 return h_string.getvalue()
1830
1833 """ A class for returning a file/a string for python evaluation """
1834
1835 extension = '.py'
1836 writer = writers.PythonWriter
1837
1838 @staticmethod
1862
1863
1865 """shift the indices for non impulsion object"""
1866 if match.group('var').startswith('P'):
1867 shift = 0
1868 else:
1869 shift = -1 + self.momentum_size
1870
1871 return '%s[%s]' % (match.group('var'), int(match.group('num')) + shift)
1872
1874 """Formatting the variable name to Python format
1875 start to count at zero.
1876 No neeed to define the variable in python -> no need to keep track of
1877 the various variable
1878 """
1879
1880 if '_' not in name:
1881 self.declaration.add((name.type, name))
1882 else:
1883 self.declaration.add(('', name.split('_',1)[0]))
1884 name = re.sub('(?P<var>\w*)_(?P<num>\d+)$', self.shift_indices , name)
1885
1886 return name
1887
1913
1915 """Define the functions in a 100% way """
1916
1917 out = StringIO()
1918
1919 if self.routine.contracted:
1920 for name,obj in self.routine.contracted.items():
1921 out.write(' %s = %s\n' % (name, self.write_obj(obj)))
1922
1923 def sort_fct(a, b):
1924 if len(a) < len(b):
1925 return -1
1926 elif len(a) > len(b):
1927 return 1
1928 elif a < b:
1929 return -1
1930 else:
1931 return +1
1932
1933 keys = self.routine.fct.keys()
1934 keys.sort(sort_fct)
1935 for name in keys:
1936 fct, objs = self.routine.fct[name]
1937 format = ' %s = %s\n' % (name, self.get_fct_format(fct))
1938 try:
1939 text = format % ','.join([self.write_obj(obj) for obj in objs])
1940 except TypeError:
1941 text = format % tuple([self.write_obj(obj) for obj in objs])
1942 finally:
1943 out.write(text)
1944
1945
1946
1947 numerator = self.routine.expr
1948 if not 'Coup(1)' in self.routine.infostr:
1949 coup_name = 'COUP'
1950 else:
1951 coup_name = '%s' % self.change_number_format(1)
1952
1953 if not self.offshell:
1954 if coup_name == 'COUP':
1955 out.write(' vertex = COUP*%s\n' % self.write_obj(numerator.get_rep([0])))
1956 else:
1957 out.write(' vertex = %s\n' % self.write_obj(numerator.get_rep([0])))
1958 else:
1959 OffShellParticle = '%s%d' % (self.particles[self.offshell-1],\
1960 self.offshell)
1961
1962 if not 'L' in self.tag:
1963 coeff = 'denom'
1964 if not aloha.complex_mass:
1965 if self.routine.denominator:
1966 out.write(' denom = %(COUP)s/(%(denom)s)\n' % {'COUP': coup_name,\
1967 'denom':self.write_obj(self.routine.denominator)})
1968 else:
1969 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' %
1970 {'i': self.outgoing,'coup':coup_name})
1971 else:
1972 if self.routine.denominator:
1973 raise Exception, 'modify denominator are not compatible with complex mass scheme'
1974
1975 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' %
1976 {'i': self.outgoing,'coup':coup_name})
1977 else:
1978 coeff = 'COUP'
1979
1980 for ind in numerator.listindices():
1981 out.write(' %s[%d]= %s*%s\n' % (self.outname,
1982 self.pass_to_HELAS(ind), coeff,
1983 self.write_obj(numerator.get_rep(ind))))
1984 return out.getvalue()
1985
1991
1992
1994 """Define the Header of the fortran file. This include
1995 - function tag
1996 - definition of variable
1997 """
1998 if name is None:
1999 name = self.name
2000
2001 out = StringIO()
2002 out.write("import cmath\n")
2003 if self.mode == 'mg5':
2004 out.write('import aloha.template_files.wavefunctions as wavefunctions\n')
2005 else:
2006 out.write('import wavefunctions\n')
2007
2008
2009
2010
2011 arguments = [arg for format, arg in self.define_argument_list(couplings)]
2012 out.write('def %(name)s(%(args)s):\n' % \
2013 {'name': name, 'args': ','.join(arguments)})
2014
2015 return out.getvalue()
2016
2018 """Define the Header of the fortran file. This include
2019 - momentum conservation
2020 - definition of the impulsion"""
2021
2022 out = StringIO()
2023
2024
2025 p = []
2026
2027 signs = self.get_momentum_conservation_sign()
2028
2029 for i,type in enumerate(self.particles):
2030 if self.declaration.is_used('OM%s' % (i+1)):
2031 out.write(" OM{0} = 0.0\n if (M{0}): OM{0}=1.0/M{0}**2\n".format( (i+1) ))
2032 if i+1 == self.outgoing:
2033 out_type = type
2034 out_size = self.type_to_size[type]
2035 continue
2036 elif self.offshell:
2037 p.append('{0}{1}{2}[%(i)s]'.format(signs[i],type,i+1))
2038
2039 if self.declaration.is_used('P%s' % (i+1)):
2040 self.get_one_momenta_def(i+1, out)
2041
2042
2043 if self.offshell:
2044 type = self.particles[self.outgoing-1]
2045 out.write(' %s%s = wavefunctions.WaveFunction(size=%s)\n' % (type, self.outgoing, out_size))
2046 if aloha.loop_mode:
2047 size_p = 4
2048 else:
2049 size_p = 2
2050 for i in range(size_p):
2051 dict_energy = {'i':i}
2052
2053 out.write(' %s%s[%s] = %s\n' % (type,self.outgoing, i,
2054 ''.join(p) % dict_energy))
2055
2056 self.get_one_momenta_def(self.outgoing, out)
2057
2058
2059
2060 return out.getvalue()
2061
2063 """return the string defining the momentum"""
2064
2065 type = self.particles[i-1]
2066
2067 main = ' P%d = [' % i
2068 if aloha.loop_mode:
2069 template ='%(sign)s%(type)s%(i)d[%(nb)d]'
2070 else:
2071 template ='%(sign)scomplex(%(type)s%(i)d[%(nb2)d])%(operator)s'
2072
2073 nb2 = 0
2074 strfile.write(main)
2075 data = []
2076 for j in range(4):
2077 if not aloha.loop_mode:
2078 nb = j
2079 if j == 0:
2080 assert not aloha.mp_precision
2081 operator = '.real'
2082 elif j == 1:
2083 nb2 += 1
2084 elif j == 2:
2085 assert not aloha.mp_precision
2086 operator = '.imag'
2087 elif j ==3:
2088 nb2 -= 1
2089 else:
2090 operator =''
2091 nb = j
2092 nb2 = j
2093 data.append(template % {'j':j,'type': type, 'i': i,
2094 'nb': nb, 'nb2': nb2, 'operator':operator,
2095 'sign': self.get_P_sign(i)})
2096
2097 strfile.write(', '.join(data))
2098 strfile.write(']\n')
2099
2100
2107
2109 """Write routine for combine ALOHA call (more than one coupling)"""
2110
2111
2112 if offshell is None:
2113 sym = 1
2114 offshell = self.offshell
2115 else:
2116 sym = None
2117 name = combine_name(self.routine.name, lor_names, offshell, self.tag)
2118
2119 text = StringIO()
2120 data = {}
2121
2122
2123 new_couplings = ['COUP%s' % (i+1) for i in range(len(lor_names)+1)]
2124 text.write(self.get_header_txt(name=name, couplings=new_couplings))
2125
2126
2127 data['addon'] = ''.join(self.tag) + '_%s' % self.offshell
2128
2129
2130 argument = [name for format, name in self.define_argument_list(new_couplings)]
2131 index= argument.index('COUP1')
2132 data['before_coup'] = ','.join(argument[:index])
2133 data['after_coup'] = ','.join(argument[index+len(lor_names)+1:])
2134 if data['after_coup']:
2135 data['after_coup'] = ',' + data['after_coup']
2136
2137 lor_list = (self.routine.name,) + lor_names
2138 line = " %(out)s = %(name)s%(addon)s(%(before_coup)s,%(coup)s%(after_coup)s)\n"
2139 main = '%(spin)s%(id)d' % {'spin': self.particles[self.offshell -1],
2140 'id': self.outgoing}
2141 for i, name in enumerate(lor_list):
2142 data['name'] = name
2143 data['coup'] = 'COUP%d' % (i+1)
2144 if i == 0:
2145 if not offshell:
2146 data['out'] = 'vertex'
2147 else:
2148 data['out'] = main
2149 elif i==1:
2150 data['out'] = 'tmp'
2151 text.write(line % data)
2152 if i:
2153 if not offshell:
2154 text.write( ' vertex += tmp\n')
2155 else:
2156 size = self.type_to_size[self.particles[offshell -1]] -2
2157 text.write(" for i in range(%s,%s):\n" % (self.momentum_size, self.momentum_size+size))
2158 text.write(" %(main)s[i] += tmp[i]\n" %{'main': main})
2159
2160 text.write(self.get_foot_txt())
2161
2162
2163 if sym:
2164 for elem in self.routine.symmetries:
2165 text.write(self.write_combined(lor_names, mode, elem))
2166
2167 text = text.getvalue()
2168 if self.out_path:
2169 writer = self.writer(self.out_path)
2170 commentstring = 'This File is Automatically generated by ALOHA \n'
2171 commentstring += 'The process calculated in this file is: \n'
2172 commentstring += self.routine.infostr + '\n'
2173 writer.write_comments(commentstring)
2174 writer.writelines(text)
2175
2176
2177 return text
2178
2181
2183 if hasattr(self, 'var_name'):
2184 return var in self.var_name
2185 self.var_name = [name for type,name in self]
2186 return var in self.var_name
2187
2188 - def add(self,obj):
2189 if __debug__:
2190 type, name = obj
2191 samename = [t for t,n in self if n ==name]
2192 for type2 in samename:
2193 assert type2 == type, '%s is defined with two different type "%s" and "%s"' % \
2194 (name, type2, type)
2195
2196 set.add(self,obj)
2197
2200
2201 - def __new__(cls, data, language, outputdir, tags):
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255