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 def myHash(target_string):
1209 if len(target_string)<50:
1210 return target_string
1211 if '%(propa)s' in target_string:
1212 return 'ALOHA_'+(str(hash(target_string.lower()))).replace('-','m')+'%(propa)s'
1213 else:
1214 return 'ALOHA_'+(str(hash(target_string.lower()))).replace('-','m')
1215
1216 if tag and any(t.startswith('P') for t in tag[:-1]):
1217
1218 for i,t in enumerate(tag):
1219 if t.startswith('P'):
1220 tag.pop(i)
1221 tag.append(t)
1222 break
1223
1224
1225
1226 p=re.compile('^(?P<type>[RFSVT]{2,})(?P<id>\d+)$')
1227 routine = ''
1228 if p.search(name):
1229 base, id = p.search(name).groups()
1230 routine = name
1231 for s in other_names:
1232 try:
1233 base2,id2 = p.search(s).groups()
1234 except Exception:
1235 routine = ''
1236 break
1237 if base != base2:
1238 routine = ''
1239 break
1240 else:
1241 routine += '_%s' % id2
1242
1243 if routine:
1244 if tag is not None:
1245 routine += ''.join(tag)
1246 if unknown_propa and outgoing:
1247 routine += '%(propa)s'
1248 if outgoing is not None:
1249 return myHash(routine)+'_%s' % outgoing
1250
1251 else:
1252 return myHash(routine)
1253
1254
1255 if tag is not None:
1256 addon = ''.join(tag)
1257 else:
1258 addon = ''
1259 if 'C' in name:
1260 short_name, addon = name.split('C',1)
1261 try:
1262 addon = 'C' + str(int(addon))
1263 except Exception:
1264 addon = ''
1265 else:
1266 name = short_name
1267 if unknown_propa:
1268 addon += '%(propa)s'
1269
1270
1271
1272
1273
1274
1275 if outgoing is not None:
1276 return myHash('_'.join((name,) + tuple(other_names))) + addon + '_%s' % outgoing
1277 else:
1278 return myHash('_'.join((name,) + tuple(other_names))) + addon
1279
1281 """Routines for writing out helicity amplitudes as C++ .h and .cc files."""
1282
1283 extension = '.c'
1284 writer = writers.CPPWriter
1285
1286 type2def = {}
1287 type2def['int'] = 'int '
1288 type2def['double'] = 'double '
1289 type2def['complex'] = 'std::complex<double> '
1290
1291
1292 realoperator = '.real()'
1293 imagoperator = '.imag()'
1294 ci_definition = 'static std::complex<double> cI = std::complex<double>(0.,1.);\n'
1295
1296
1305
1306 if isinteger(number):
1307 out = '%s.' % (str(int(number)))
1308 elif isinstance(number, complex):
1309 if number.imag:
1310 if number.real:
1311 out = '(%s + %s*cI)' % (self.change_number_format(number.real), \
1312 self.change_number_format(number.imag))
1313 else:
1314 if number.imag == 1:
1315 out = 'cI'
1316 elif number.imag == -1:
1317 out = '-cI'
1318 else:
1319 out = '%s * cI' % self.change_number_format(number.imag)
1320 else:
1321 out = '%s' % (self.change_number_format(number.real))
1322 else:
1323 tmp = Fraction(str(number))
1324 tmp = tmp.limit_denominator(100)
1325 if not abs(tmp - number) / abs(tmp + number) < 1e-8:
1326 out = '%.9f' % (number)
1327 else:
1328 out = '%s./%s.' % (tmp.numerator, tmp.denominator)
1329 return out
1330
1331
1333 """shift the indices for non impulsion object"""
1334 if match.group('var').startswith('P'):
1335 shift = 0
1336 else:
1337 shift = self.momentum_size - 1
1338 return '%s[%s]' % (match.group('var'), int(match.group('num')) + shift)
1339
1340
1342 """Format the variable name to C++ format"""
1343
1344 if '_' in name:
1345 type = name.type
1346 decla = name.split('_',1)[0]
1347 self.declaration.add(('list_%s' % type, decla))
1348 else:
1349 self.declaration.add((name.type, name.split('_',1)[0]))
1350 name = re.sub('(?P<var>\w*)_(?P<num>\d+)$', self.shift_indices , name)
1351 return name
1352
1375
1376
1377
1378
1380 """Define the Header of the fortran file. This include
1381 - function tag
1382 - definition of variable
1383 """
1384 if name is None:
1385 name = self.name
1386
1387 if mode=='':
1388 mode = self.mode
1389
1390
1391
1392 out = StringIO()
1393
1394 if not 'no_include' in mode:
1395 out.write('#include \"%s.h\"\n\n' % self.name)
1396 args = []
1397 for format, argname in self.define_argument_list(couplings):
1398 if format.startswith('list'):
1399 type = self.type2def[format[5:]]
1400 list_arg = '[]'
1401 else:
1402 type = self.type2def[format]
1403 list_arg = ''
1404 args.append('%s%s%s'% (type, argname, list_arg))
1405
1406 if not self.offshell:
1407 output = 'std::complex<double> & vertex'
1408
1409 else:
1410 output = 'std::complex<double> %(spin)s%(id)d[]' % {
1411 'spin': self.particles[self.outgoing -1],
1412 'id': self.outgoing}
1413 self.declaration.add(('list_complex', output))
1414
1415 out.write('void %(name)s(%(args)s,%(output)s)' % \
1416 {'output':output, 'name': name, 'args': ', '.join(args)})
1417 if 'is_h' in mode:
1418 out.write(';\n')
1419 else:
1420 out.write('\n{\n')
1421
1422 return out.getvalue()
1423
1425 """ Prototype for how to write the declaration of variable
1426 Include the symmetry line (entry FFV_2)
1427 """
1428
1429 out = StringIO()
1430 argument_var = [name for type,name in self.call_arg]
1431
1432 if add_i:
1433 out.write(self.ci_definition)
1434
1435 for type, name in self.declaration:
1436 if type.startswith('list'):
1437 type = type[5:]
1438 if name.startswith('P'):
1439 size = 4
1440 elif not 'tmp' in name:
1441 continue
1442
1443 elif name[0] in ['F','V']:
1444 if aloha.loop_mode:
1445 size = 8
1446 else:
1447 size = 6
1448 elif name[0] == 'S':
1449 if aloha.loop_mode:
1450 size = 5
1451 else:
1452 size = 3
1453 elif name[0] in ['R','T']:
1454 if aloha.loop_mode:
1455 size = 20
1456 else:
1457 size = 18
1458
1459 out.write(' %s %s[%s];\n' % (self.type2def[type], name, size))
1460 elif (type, name) not in self.call_arg:
1461 out.write(' %s %s;\n' % (self.type2def[type], name))
1462
1463 return out.getvalue()
1464
1468
1470 """Define the Header of the fortran file. This include
1471 - momentum conservation
1472 - definition of the impulsion"""
1473
1474 out = StringIO()
1475
1476
1477 p = []
1478
1479 signs = self.get_momentum_conservation_sign()
1480
1481 for i,type in enumerate(self.particles):
1482 if self.declaration.is_used('OM%s' % (i+1)):
1483 out.write(" OM{0} = {1};\n if (M{0} != {1})\n OM{0}={2}/(M{0}*M{0});\n".format(
1484 i+1, self.change_number_format(0), self.change_number_format(1)))
1485
1486 if i+1 == self.outgoing:
1487 out_type = type
1488 out_size = self.type_to_size[type]
1489 continue
1490 elif self.offshell:
1491 p.append('{0}{1}{2}[%(i)s]'.format(signs[i],type,i+1,type))
1492
1493 if self.declaration.is_used('P%s' % (i+1)):
1494 self.get_one_momenta_def(i+1, out)
1495
1496
1497 if self.offshell:
1498 energy_pos = out_size -2
1499 type = self.particles[self.outgoing-1]
1500 if aloha.loop_mode:
1501 size_p = 4
1502 else:
1503 size_p = 2
1504
1505 for i in range(size_p):
1506 dict_energy = {'i':i}
1507 out.write(' %s%s[%s] = %s;\n' % (type,self.outgoing, i,
1508 ''.join(p) % dict_energy))
1509 if self.declaration.is_used('P%s' % self.outgoing):
1510 self.get_one_momenta_def(self.outgoing, out)
1511
1512
1513
1514 return out.getvalue()
1515
1517
1518 type = self.particles[i-1]
1519
1520 if aloha.loop_mode:
1521 template ='P%(i)d[%(j)d] = %(sign)s%(type)s%(i)d[%(nb)d];\n'
1522 else:
1523 template ='P%(i)d[%(j)d] = %(sign)s%(type)s%(i)d[%(nb2)d]%(operator)s;\n'
1524
1525 nb2 = 0
1526 for j in range(4):
1527 if not aloha.loop_mode:
1528 nb = j
1529 if j == 0:
1530 assert not aloha.mp_precision
1531 operator = self.realoperator
1532 elif j == 1:
1533 nb2 += 1
1534 elif j == 2:
1535 assert not aloha.mp_precision
1536 operator = self.imagoperator
1537 elif j ==3:
1538 nb2 -= 1
1539 else:
1540 operator =''
1541 nb = j
1542 nb2 = j
1543 strfile.write(template % {'j':j,'type': type, 'i': i,
1544 'nb': nb, 'nb2': nb2, 'operator':operator,
1545 'sign': self.get_P_sign(i)})
1546
1547
1549 """Write the helicity amplitude in C++ format"""
1550
1551 out = StringIO()
1552
1553 if self.routine.contracted:
1554 for name,obj in self.routine.contracted.items():
1555 out.write(' %s = %s;\n' % (name, self.write_obj(obj)))
1556 self.declaration.add(('complex', name))
1557
1558 for name, (fct, objs) in self.routine.fct.items():
1559 format = ' %s = %s;\n' % (name, self.get_fct_format(fct))
1560 out.write(format % ','.join([self.write_obj(obj) for obj in objs]))
1561
1562
1563
1564 numerator = self.routine.expr
1565 if not 'Coup(1)' in self.routine.infostr:
1566 coup_name = 'COUP'
1567 else:
1568 coup_name = '%s' % self.change_number_format(1)
1569 if not self.offshell:
1570 if coup_name == 'COUP':
1571 out.write(' vertex = COUP*%s;\n' % self.write_obj(numerator.get_rep([0])))
1572 else:
1573 out.write(' vertex = %s;\n' % self.write_obj(numerator.get_rep([0])))
1574 else:
1575 OffShellParticle = '%s%d' % (self.particles[self.offshell-1],\
1576 self.offshell)
1577 if 'L' not in self.tag:
1578 coeff = 'denom'
1579 if not aloha.complex_mass:
1580 if self.routine.denominator:
1581 out.write(' denom = %(COUP)s/(%(denom)s)\n' % {'COUP': coup_name,\
1582 'denom':self.write_obj(self.routine.denominator)})
1583 else:
1584 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' % \
1585 {'i': self.outgoing, 'coup': coup_name})
1586 else:
1587 if self.routine.denominator:
1588 raise Exception, 'modify denominator are not compatible with complex mass scheme'
1589
1590 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' % \
1591 {'i': self.outgoing, 'coup': coup_name})
1592 self.declaration.add(('complex','denom'))
1593 if aloha.loop_mode:
1594 ptype = 'list_complex'
1595 else:
1596 ptype = 'list_double'
1597 self.declaration.add((ptype,'P%s' % self.outgoing))
1598 else:
1599 coeff = 'COUP'
1600
1601 for ind in numerator.listindices():
1602 out.write(' %s[%d]= %s*%s;\n' % (self.outname,
1603 self.pass_to_HELAS(ind), coeff,
1604 self.write_obj(numerator.get_rep(ind))))
1605 return out.getvalue()
1606
1607 remove_double = re.compile('std::complex<double> (?P<name>[\w]+)\[\]')
1609 """Write the call for symmetric routines"""
1610 number = self.offshell
1611 arguments = [name for format, name in self.define_argument_list()]
1612 new_name = self.name.rsplit('_')[0] + '_%s' % new_nb
1613 output = '%(spin)s%(id)d' % {
1614 'spin': self.particles[self.offshell -1],
1615 'id': self.outgoing}
1616 return '%s\n %s(%s,%s);\n}' % \
1617 (self.get_header_txt(new_name, couplings, mode='no_include'),
1618 self.name, ','.join(arguments), output)
1619
1620 - def get_h_text(self,couplings=None):
1621 """Return the full contents of the .h file"""
1622
1623 h_string = StringIO()
1624 if not self.mode == 'no_include':
1625 h_string.write('#ifndef '+ self.name + '_guard\n')
1626 h_string.write('#define ' + self.name + '_guard\n')
1627 h_string.write('#include <complex>\n\n')
1628
1629 h_header = self.get_header_txt(mode='no_include__is_h', couplings=couplings)
1630 h_string.write(h_header)
1631
1632 for elem in self.routine.symmetries:
1633 symmetryhead = h_header.replace( \
1634 self.name,self.name[0:-1]+'%s' %(elem))
1635 h_string.write(symmetryhead)
1636
1637 if not self.mode == 'no_include':
1638 h_string.write('#endif\n\n')
1639
1640 return h_string.getvalue()
1641
1642
1644 "Return the content of the .cc file linked to multiple lorentz call."
1645
1646
1647 if offshell is None:
1648 offshell = self.offshell
1649
1650 name = combine_name(self.routine.name, lor_names, offshell, self.tag)
1651 self.name = name
1652
1653 text = StringIO()
1654 routine = StringIO()
1655 data = {}
1656
1657
1658 new_couplings = ['COUP%s' % (i+1) for i in range(len(lor_names)+1)]
1659 text.write(self.get_header_txt(name=name, couplings=new_couplings, mode=mode))
1660
1661
1662 data['addon'] = ''.join(self.tag) + '_%s' % self.offshell
1663
1664
1665 argument = [name for format, name in self.define_argument_list(new_couplings)]
1666 index= argument.index('COUP1')
1667 data['before_coup'] = ','.join(argument[:index])
1668 data['after_coup'] = ','.join(argument[index+len(lor_names)+1:])
1669 if data['after_coup']:
1670 data['after_coup'] = ',' + data['after_coup']
1671
1672 lor_list = (self.routine.name,) + lor_names
1673 line = " %(name)s%(addon)s(%(before_coup)s,%(coup)s%(after_coup)s,%(out)s);\n"
1674 main = '%(spin)s%(id)d' % {'spin': self.particles[self.offshell -1],
1675 'id': self.outgoing}
1676 for i, name in enumerate(lor_list):
1677 data['name'] = name
1678 data['coup'] = 'COUP%d' % (i+1)
1679 if i == 0:
1680 if not offshell:
1681 data['out'] = 'vertex'
1682 else:
1683 data['out'] = main
1684 elif i==1:
1685 if self.offshell:
1686 type = self.particles[self.offshell-1]
1687 self.declaration.add(('list_complex','%stmp' % type))
1688 else:
1689 type = ''
1690 self.declaration.add(('complex','%stmp' % type))
1691 data['out'] = '%stmp' % type
1692 routine.write(line % data)
1693 if i:
1694 if not offshell:
1695 routine.write( ' vertex = vertex + tmp;\n')
1696 else:
1697 size = self.type_to_size[self.particles[offshell -1]] -2
1698 routine.write(""" i= %s;\nwhile (i < %s)\n{\n""" % (self.momentum_size, self.momentum_size+size))
1699 routine.write(" %(main)s[i] = %(main)s[i] + %(tmp)s[i];\n i++;\n" %\
1700 {'main': main, 'tmp': data['out']})
1701 routine.write('}\n')
1702 self.declaration.add(('int','i'))
1703 self.declaration.discard(('complex','COUP'))
1704 self.declaration.discard(('complex', 'denom'))
1705 if self.outgoing:
1706 self.declaration.discard(('list_double', 'P%s' % self.outgoing))
1707 self.declaration.discard(('double', 'OM%s' % self.outgoing))
1708 for name in aloha_lib.KERNEL.reduced_expr2:
1709 self.declaration.discard(('complex', name))
1710
1711
1712
1713 text.write(self.get_declaration_txt(add_i=False))
1714 text.write(routine.getvalue())
1715 text.write(self.get_foot_txt())
1716
1717 text = text.getvalue()
1718 return text
1719
1720
1721 - def write(self, **opt):
1722 """Write the .h and .cc files"""
1723
1724 cc_text = WriteALOHA.write(self, **opt)
1725 h_text = self.get_h_text()
1726
1727
1728 if self.out_path:
1729 writer_h = writers.CPPWriter(self.out_path[:-len(self.extension)] + ".h")
1730 commentstring = 'This File is Automatically generated by ALOHA \n'
1731 commentstring += 'The process calculated in this file is: \n'
1732 commentstring += self.routine.infostr + '\n'
1733 writer_h.write_comments(commentstring)
1734 writer_h.writelines(h_text)
1735
1736 return h_text, cc_text
1737
1738
1739
1741 """Write the .h and .cc files associated to the combined file"""
1742
1743
1744 if offshell is None:
1745 sym = 1
1746 offshell = self.offshell
1747 else:
1748 sym = None
1749
1750 if mode == 'self':
1751
1752 self.mode = 'no_include'
1753
1754
1755
1756
1757 cc_text, h_text = StringIO() , StringIO()
1758 cc_text.write(self.write_combined_cc(lor_names, offshell, mode=mode,**opt))
1759 couplings = ['COUP%d' % (i+1) for i in range(len(lor_names)+1)]
1760
1761 if mode == 'self':
1762 self.mode = 'self'
1763 h_text.write(self.get_h_text(couplings=couplings))
1764
1765
1766 if sym:
1767 for elem in self.routine.symmetries:
1768 self.mode = 'no_include'
1769 cc_text.write( self.write_combined_cc(lor_names, elem))
1770
1771
1772 if self.out_path:
1773
1774 path = os.path.join(os.path.dirname(self.out_path), self.name)
1775 commentstring = 'This File is Automatically generated by ALOHA \n'
1776
1777 writer_h = writers.CPPWriter(path + ".h")
1778 writer_h.write_comments(commentstring)
1779 writer_h.writelines(h_text.getvalue())
1780
1781 writer_cc = writers.CPPWriter(path + ".cc")
1782 writer_cc.write_comments(commentstring)
1783 writer_cc.writelines(cc_text.getvalue())
1784
1785 return h_text.getvalue(), cc_text.getvalue()
1786
1789
1790 extension = '.cu'
1791 realoperator = '.re'
1792 imagoperator = '.im'
1793 ci_definition = 'complex<double> cI = mkcmplx(0., 1.);\n'
1794
1796 """Define the Header of the fortran file. This include
1797 - function tag
1798 - definition of variable
1799 """
1800 text = StringIO()
1801 if not 'is_h' in mode:
1802 text.write('__device__=__forceinclude__\n')
1803 text.write(ALOHAWriterForCPP.get_header_txt(self, name, couplings, mode))
1804 return text.getvalue()
1805
1806 - def get_h_text(self,couplings=None):
1807 """Return the full contents of the .h file"""
1808
1809 h_string = StringIO()
1810 if not self.mode == 'no_include':
1811 h_string.write('#ifndef '+ self.name + '_guard\n')
1812 h_string.write('#define ' + self.name + '_guard\n')
1813 h_string.write('#include "cmplx.h"\n')
1814 h_string.write('using namespace std;\n\n')
1815
1816 h_header = self.get_header_txt(mode='no_include__is_h', couplings=couplings)
1817 h_string.write(h_header)
1818
1819 for elem in self.routine.symmetries:
1820 symmetryhead = h_header.replace( \
1821 self.name,self.name[0:-1]+'%s' %(elem))
1822 h_string.write(symmetryhead)
1823
1824 if not self.mode == 'no_include':
1825 h_string.write('#endif\n\n')
1826
1827 return h_string.getvalue()
1828
1831 """ A class for returning a file/a string for python evaluation """
1832
1833 extension = '.py'
1834 writer = writers.PythonWriter
1835
1836 @staticmethod
1860
1861
1863 """shift the indices for non impulsion object"""
1864 if match.group('var').startswith('P'):
1865 shift = 0
1866 else:
1867 shift = -1 + self.momentum_size
1868
1869 return '%s[%s]' % (match.group('var'), int(match.group('num')) + shift)
1870
1872 """Formatting the variable name to Python format
1873 start to count at zero.
1874 No neeed to define the variable in python -> no need to keep track of
1875 the various variable
1876 """
1877
1878 if '_' not in name:
1879 self.declaration.add((name.type, name))
1880 else:
1881 self.declaration.add(('', name.split('_',1)[0]))
1882 name = re.sub('(?P<var>\w*)_(?P<num>\d+)$', self.shift_indices , name)
1883
1884 return name
1885
1911
1913 """Define the functions in a 100% way """
1914
1915 out = StringIO()
1916
1917 if self.routine.contracted:
1918 for name,obj in self.routine.contracted.items():
1919 out.write(' %s = %s\n' % (name, self.write_obj(obj)))
1920
1921 def sort_fct(a, b):
1922 if len(a) < len(b):
1923 return -1
1924 elif len(a) > len(b):
1925 return 1
1926 elif a < b:
1927 return -1
1928 else:
1929 return +1
1930
1931 keys = self.routine.fct.keys()
1932 keys.sort(sort_fct)
1933 for name in keys:
1934 fct, objs = self.routine.fct[name]
1935 format = ' %s = %s\n' % (name, self.get_fct_format(fct))
1936 try:
1937 text = format % ','.join([self.write_obj(obj) for obj in objs])
1938 except TypeError:
1939 text = format % tuple([self.write_obj(obj) for obj in objs])
1940 finally:
1941 out.write(text)
1942
1943
1944
1945 numerator = self.routine.expr
1946 if not 'Coup(1)' in self.routine.infostr:
1947 coup_name = 'COUP'
1948 else:
1949 coup_name = '%s' % self.change_number_format(1)
1950
1951 if not self.offshell:
1952 if coup_name == 'COUP':
1953 out.write(' vertex = COUP*%s\n' % self.write_obj(numerator.get_rep([0])))
1954 else:
1955 out.write(' vertex = %s\n' % self.write_obj(numerator.get_rep([0])))
1956 else:
1957 OffShellParticle = '%s%d' % (self.particles[self.offshell-1],\
1958 self.offshell)
1959
1960 if not 'L' in self.tag:
1961 coeff = 'denom'
1962 if not aloha.complex_mass:
1963 if self.routine.denominator:
1964 out.write(' denom = %(COUP)s/(%(denom)s)\n' % {'COUP': coup_name,\
1965 'denom':self.write_obj(self.routine.denominator)})
1966 else:
1967 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' %
1968 {'i': self.outgoing,'coup':coup_name})
1969 else:
1970 if self.routine.denominator:
1971 raise Exception, 'modify denominator are not compatible with complex mass scheme'
1972
1973 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' %
1974 {'i': self.outgoing,'coup':coup_name})
1975 else:
1976 coeff = 'COUP'
1977
1978 for ind in numerator.listindices():
1979 out.write(' %s[%d]= %s*%s\n' % (self.outname,
1980 self.pass_to_HELAS(ind), coeff,
1981 self.write_obj(numerator.get_rep(ind))))
1982 return out.getvalue()
1983
1989
1990
1992 """Define the Header of the fortran file. This include
1993 - function tag
1994 - definition of variable
1995 """
1996 if name is None:
1997 name = self.name
1998
1999 out = StringIO()
2000 out.write("import cmath\n")
2001 if self.mode == 'mg5':
2002 out.write('import aloha.template_files.wavefunctions as wavefunctions\n')
2003 else:
2004 out.write('import wavefunctions\n')
2005
2006
2007
2008
2009 arguments = [arg for format, arg in self.define_argument_list(couplings)]
2010 out.write('def %(name)s(%(args)s):\n' % \
2011 {'name': name, 'args': ','.join(arguments)})
2012
2013 return out.getvalue()
2014
2016 """Define the Header of the fortran file. This include
2017 - momentum conservation
2018 - definition of the impulsion"""
2019
2020 out = StringIO()
2021
2022
2023 p = []
2024
2025 signs = self.get_momentum_conservation_sign()
2026
2027 for i,type in enumerate(self.particles):
2028 if self.declaration.is_used('OM%s' % (i+1)):
2029 out.write(" OM{0} = 0.0\n if (M{0}): OM{0}=1.0/M{0}**2\n".format( (i+1) ))
2030 if i+1 == self.outgoing:
2031 out_type = type
2032 out_size = self.type_to_size[type]
2033 continue
2034 elif self.offshell:
2035 p.append('{0}{1}{2}[%(i)s]'.format(signs[i],type,i+1))
2036
2037 if self.declaration.is_used('P%s' % (i+1)):
2038 self.get_one_momenta_def(i+1, out)
2039
2040
2041 if self.offshell:
2042 type = self.particles[self.outgoing-1]
2043 out.write(' %s%s = wavefunctions.WaveFunction(size=%s)\n' % (type, self.outgoing, out_size))
2044 if aloha.loop_mode:
2045 size_p = 4
2046 else:
2047 size_p = 2
2048 for i in range(size_p):
2049 dict_energy = {'i':i}
2050
2051 out.write(' %s%s[%s] = %s\n' % (type,self.outgoing, i,
2052 ''.join(p) % dict_energy))
2053
2054 self.get_one_momenta_def(self.outgoing, out)
2055
2056
2057
2058 return out.getvalue()
2059
2061 """return the string defining the momentum"""
2062
2063 type = self.particles[i-1]
2064
2065 main = ' P%d = [' % i
2066 if aloha.loop_mode:
2067 template ='%(sign)s%(type)s%(i)d[%(nb)d]'
2068 else:
2069 template ='%(sign)scomplex(%(type)s%(i)d[%(nb2)d])%(operator)s'
2070
2071 nb2 = 0
2072 strfile.write(main)
2073 data = []
2074 for j in range(4):
2075 if not aloha.loop_mode:
2076 nb = j
2077 if j == 0:
2078 assert not aloha.mp_precision
2079 operator = '.real'
2080 elif j == 1:
2081 nb2 += 1
2082 elif j == 2:
2083 assert not aloha.mp_precision
2084 operator = '.imag'
2085 elif j ==3:
2086 nb2 -= 1
2087 else:
2088 operator =''
2089 nb = j
2090 nb2 = j
2091 data.append(template % {'j':j,'type': type, 'i': i,
2092 'nb': nb, 'nb2': nb2, 'operator':operator,
2093 'sign': self.get_P_sign(i)})
2094
2095 strfile.write(', '.join(data))
2096 strfile.write(']\n')
2097
2098
2105
2107 """Write routine for combine ALOHA call (more than one coupling)"""
2108
2109
2110 if offshell is None:
2111 sym = 1
2112 offshell = self.offshell
2113 else:
2114 sym = None
2115 name = combine_name(self.routine.name, lor_names, offshell, self.tag)
2116
2117 text = StringIO()
2118 data = {}
2119
2120
2121 new_couplings = ['COUP%s' % (i+1) for i in range(len(lor_names)+1)]
2122 text.write(self.get_header_txt(name=name, couplings=new_couplings))
2123
2124
2125 data['addon'] = ''.join(self.tag) + '_%s' % self.offshell
2126
2127
2128 argument = [name for format, name in self.define_argument_list(new_couplings)]
2129 index= argument.index('COUP1')
2130 data['before_coup'] = ','.join(argument[:index])
2131 data['after_coup'] = ','.join(argument[index+len(lor_names)+1:])
2132 if data['after_coup']:
2133 data['after_coup'] = ',' + data['after_coup']
2134
2135 lor_list = (self.routine.name,) + lor_names
2136 line = " %(out)s = %(name)s%(addon)s(%(before_coup)s,%(coup)s%(after_coup)s)\n"
2137 main = '%(spin)s%(id)d' % {'spin': self.particles[self.offshell -1],
2138 'id': self.outgoing}
2139 for i, name in enumerate(lor_list):
2140 data['name'] = name
2141 data['coup'] = 'COUP%d' % (i+1)
2142 if i == 0:
2143 if not offshell:
2144 data['out'] = 'vertex'
2145 else:
2146 data['out'] = main
2147 elif i==1:
2148 data['out'] = 'tmp'
2149 text.write(line % data)
2150 if i:
2151 if not offshell:
2152 text.write( ' vertex += tmp\n')
2153 else:
2154 size = self.type_to_size[self.particles[offshell -1]] -2
2155 text.write(" for i in range(%s,%s):\n" % (self.momentum_size, self.momentum_size+size))
2156 text.write(" %(main)s[i] += tmp[i]\n" %{'main': main})
2157
2158 text.write(self.get_foot_txt())
2159
2160
2161 if sym:
2162 for elem in self.routine.symmetries:
2163 text.write(self.write_combined(lor_names, mode, elem))
2164
2165 text = text.getvalue()
2166 if self.out_path:
2167 writer = self.writer(self.out_path)
2168 commentstring = 'This File is Automatically generated by ALOHA \n'
2169 commentstring += 'The process calculated in this file is: \n'
2170 commentstring += self.routine.infostr + '\n'
2171 writer.write_comments(commentstring)
2172 writer.writelines(text)
2173
2174
2175 return text
2176
2179
2181 if hasattr(self, 'var_name'):
2182 return var in self.var_name
2183 self.var_name = [name for type,name in self]
2184 return var in self.var_name
2185
2186 - def add(self,obj):
2187 if __debug__:
2188 type, name = obj
2189 samename = [t for t,n in self if n ==name]
2190 for type2 in samename:
2191 assert type2 == type, '%s is defined with two different type "%s" and "%s"' % \
2192 (name, type2, type)
2193
2194 set.add(self,obj)
2195
2198
2199 - def __new__(cls, data, language, outputdir, tags):
2220
2221
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