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