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