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