Merge lp:~maddevelopers/mg5amcnlo/reduce_aloha_call into lp:~maddevelopers/mg5amcnlo/version_1_0_1

Proposed by Olivier Mattelaer
Status: Merged
Merged at revision: 135
Proposed branch: lp:~maddevelopers/mg5amcnlo/reduce_aloha_call
Merge into: lp:~maddevelopers/mg5amcnlo/version_1_0_1
Diff against target: 3370 lines (+1463/-564) (has conflicts)
21 files modified
aloha/aloha_writers.py (+465/-106)
aloha/bin/aloha (+1/-1)
aloha/create_aloha.py (+94/-17)
madgraph/core/helas_objects.py (+122/-77)
madgraph/interface/cmd_interface.py (+0/-1)
madgraph/iolibs/export_cpp.py (+39/-29)
madgraph/iolibs/export_python.py (+5/-3)
madgraph/iolibs/export_v4.py (+0/-9)
madgraph/iolibs/helas_call_writers.py (+142/-129)
madgraph/iolibs/template_files/matrix_madevent_v4.inc (+2/-0)
madgraph/iolibs/template_files/matrix_standalone_v4.inc (+2/-0)
tests/acceptance_tests/test_cmd.py (+6/-6)
tests/parallel_tests/me_comparator.py (+3/-2)
tests/parallel_tests/sample_script.py (+18/-1)
tests/unit_tests/core/test_helas_objects.py (+8/-6)
tests/unit_tests/iolibs/test_export_cpp.py (+132/-10)
tests/unit_tests/iolibs/test_export_python.py (+15/-24)
tests/unit_tests/iolibs/test_export_v4.py (+77/-117)
tests/unit_tests/iolibs/test_helas_call_writers.py (+2/-2)
tests/unit_tests/various/test_4fermion_models.py (+0/-1)
tests/unit_tests/various/test_aloha.py (+330/-23)
Text conflict in tests/parallel_tests/sample_script.py
Text conflict in tests/unit_tests/iolibs/test_export_cpp.py
Text conflict in tests/unit_tests/iolibs/test_export_v4.py
To merge this branch: bzr merge lp:~maddevelopers/mg5amcnlo/reduce_aloha_call
Reviewer Review Type Date Requested Status
Johan Alwall (community) Approve
Review via email: mp+58534@code.launchpad.net

Description of the change

- Merge multiple aloha call in a single one. (for same order/color)
- Add open command in cmd_interface
- Enlarge the symmetry possibility for aloha.
- small debug/improvment

Please check carefully the CPP output. (read at least one formated output)

To post a comment you must log in.
Revision history for this message
Johan Alwall (johan-alwall) wrote :

Hello Olivier,

This is really cool! I do have a couple of questions about the code:
1) Did you add the check in the ALOHA routines if COUP == 0 (in that case exit with zero wf/amp)?
   This check should not be in the combined routines of course, only in the basic routines.

2) In aloha_writers, you do
        # Define which part of the routine should be called
        if 'C' in self.namestring:
            addon = 'C' +self.namestring.split('C',1)[1]
        else:
            addon = '_%s' % self.offshell
   What if a used calls the Lorentz something with a 'C' in the name?
   (this might apply in other places too)
Update: " alohafile_pattern = re.compile(r'''^[STFV\d_]*[_C\d]*_\d%s''' % file_ext)"
   So in fact you are not allowing the user freedom to select lorentz names outside of the
   FR defined ones? This of course solves the problem.

3) + # Two possible scheme FFV1C1_2_X or FFV1__FFV2C1_X
   Why use double "_" for the combined name instead of the slightly better FFV1_FFV2C1_X?

That's the first pass, I'll continue after lunch :-)

Johan

review: Needs Information
Revision history for this message
Olivier Mattelaer (olivier-mattelaer) wrote :

>Hello Olivier,
>
>This is really cool! I do have a couple of questions about the code:
>1) Did you add the check in the ALOHA routines if COUP == 0 (in that case exit with zero wf/amp)?
> This check should not be in the combined routines of course, only in the basic routines.

Indeed, this is not done yet.
In fact, I'm still quite puzzled about this point.
A much better way would be to have a python script which evaluates the couplings
and simplify the matrix.f when a COUP is equal to zero(by commenting line and defining amp to zero) --off course in a reversal way--

They are many advantages to do like this:
1) you can bypass the computation of the full amplitude. (and not only on the interactions with zero couplings
2) This is done once and for all. (compare to a point by point if statement)

The disadvantages are
1) request python on the node. (We are moving for more python so this should be fine)
2) request a new compilation for each param_card (since matrix.f is modified)
3) This is much more work...

I think the advantages (speed) are enough relevant in order to pass to this method.
I would just propose to have a tag in matrix.f in order to forbid such simplification.
This will help for some test.

Note that with such method, I would need a check for the coupling be equal to zero but only in the combined routine... so exactly the opposite

>2) In aloha_writers, you do
> # Define which part of the routine should be called
> if 'C' in self.namestring:
> addon = 'C' +self.namestring.split('C',1)[1]
> else:
> addon = '_%s' % self.offshell
> What if a used calls the Lorentz something with a 'C' in the name?
> (this might apply in other places too)
>Update: " alohafile_pattern = re.compile(r'''^[STFV\d_]*[_C\d]*_\d%s''' % file_ext)"
> So in fact you are not allowing the user freedom to select lorentz names outside of the
> FR defined ones? This of course solves the problem.

Indeed not FR pattern are allowed, and indeed, name with "C" might creates trouble.
I will think about that problem, but I don't think I can find a way working in 100% of the case.
(But I can reduce the problem to routines ending by C\d)

>3) + # Two possible scheme FFV1C1_2_X or FFV1__FFV2C1_X
> Why use double "_" for the combined name instead of the slightly better FFV1_FFV2C1_X?

Ok I can change it.

Revision history for this message
Olivier Mattelaer (olivier-mattelaer) wrote :
Download full text (6.6 KiB)

Hi valentin,all,

I propose that we discuss this not on launchpad and on the ticket but
rather directly by email.
I've already send my comment on this point.

Cheers,

Olivier

On 21-avr.-11, at 11:27, Valentin Hirschi wrote:

>
>
> On Thu, Apr 21, 2011 at 11:20 AM, Valentin Hirschi <<email address hidden>
> > wrote:
>
> On Thu, Apr 21, 2011 at 10:50 AM, Olivier Mattelaer <<email address hidden>
> > wrote:
> >Hello Olivier,
> >
> >This is really cool! I do have a couple of questions about the code:
> >1) Did you add the check in the ALOHA routines if COUP == 0 (in
> that case exit with zero wf/amp)?
> > This check should not be in the combined routines of course,
> only in the basic routines.
>
> Indeed, this is not done yet.
> In fact, I'm still quite puzzled about this point.
> A much better way would be to have a python script which evaluates
> the couplings
> and simplify the matrix.f when a COUP is equal to zero(by commenting
> line and defining amp to zero) --off course in a reversal way--
>
> They are many advantages to do like this:
> 1) you can bypass the computation of the full amplitude. (and not
> only on the interactions with zero couplings
> 2) This is done once and for all. (compare to a point by point if
> statement)
>
> Wait... I did not read this correctly the first time! Do you
> actually consider some if statement (with a condition being directly
> a true/false variable) an actual computing time cost to consider???
> (for the amplitude it's the same, you can have one general if
> statement englobing the whole thing).
> I'm no expert, but I believe that this cannot possibly slow the
> code! I hardly see this if statement taking more than 1/1000
> thousand of the time used to compute a HELAS amplitude call (which
> would be the only one here at the very least).
> For NLO this is for sure totally irrelevant, and I think it's still
> negligible for LO, but if this is indeed something to consider, then
> all what I said is void and this script is indeed the way to go.
>
> The disadvantages are
> 1) request python on the node. (We are moving for more python so
> this should be fine)
> 2) request a new compilation for each param_card (since matrix.f is
> modified)
> 3) This is much more work...
>
> I think the advantages (speed) are enough relevant in order to pass
> to this method.
> I would just propose to have a tag in matrix.f in order to forbid
> such simplification.
> This will help for some test.
>
> Note that with such method, I would need a check for the coupling be
> equal to zero but only in the combined routine... so exactly the
> opposite
>
> Hi all!
>
> I'm of course not very into what you guys are doing, so all what
> follows might be completely out of context and irrelevant, so sorry
> in advance for that.
>
> I just wanted to understand why you really insist on having matrix.f
> with hardcoded elimination of amplitudes being zero because of the
> coupling constants?
> Wouldn't be nice to have a subroutine in matrix.f like the one I
> have in MadLoop which is something like InitMatrixElement()?
>
> This subroutine reads the parameters intended ...

Read more...

Revision history for this message
Johan Alwall (johan-alwall) wrote :

Hello Olivier,

Awesome job!

Some comments on the new version:
1) when I write open <TAB> (without any generation) it only gives me
MG5_debug, so gives no hint that ./ is possible. I would prefer
MG5_debug and ./ as completions. Fixed.
2) mg5>open ./PROC_sm_1/index.html
"Unable to find application named 'None'" - I fixed this too .

For the open and launch commands:
3) We should definitely not have the same code twice, so I put all the
open code in launch. Feel free to change this.
4) On Mac, you can't use the "open" command for text files, since
there's no way to make it wait for the return. So I only allow inline
editors (emacs is always defined). So I changed this.

3) In the code:
+ short_name, addon = name.split('C',1)
+ try:
+ addon = 'C' + str(int(addon))
+ except:
+ addon = ''
+ else:
+ name = short_name
I don't understand how this solves or improves the issue.
All we need is to ensure that the user doesn't use non-FR characters,
which is what they would assume anyway. Also not nice that this comes
multiple times - it's sufficiently complicated to warrant its own
routine (which also allows to modify it easily). But I would prefer to
go back to the previous case.

But I guess it doesn't matter at this point - just to keep in mind for
the future.

Cheers,
Johan

Revision history for this message
Johan Alwall (johan-alwall) wrote :

Hello Olivier,

Please don't do any more edits in this branch, but work directly in the version_1_0_1 branch from now on.

Cheers,
Johan

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'aloha/aloha_writers.py'
2--- aloha/aloha_writers.py 2011-04-01 22:38:18 +0000
3+++ aloha/aloha_writers.py 2011-04-20 16:57:29 +0000
4@@ -19,10 +19,16 @@
5
6 def __init__(self, abstract_routine, dirpath):
7
8+
9+ name = get_routine_name(abstract_routine.name, abstract_routine.outgoing)
10+ if dirpath:
11+ self.dir_out = dirpath
12+ self.out_path = os.path.join(dirpath, name + self.extension)
13+ else:
14+ self.out_path = None
15+ self.dir_out = None
16+
17 self.obj = abstract_routine.expr
18- name = get_routine_name(abstract_routine.name, abstract_routine.outgoing)
19- self.out_path = os.path.join(dirpath, name + self.extension)
20- self.dir_out = dirpath
21 self.particles = [self.type_to_variable[spin] for spin in \
22 abstract_routine.spins]
23 self.namestring = name
24@@ -36,6 +42,9 @@
25 self.make_all_lists() # Compute the expression for the call ordering
26 #the definition of objects,..
27
28+
29+
30+
31 def pass_to_HELAS(self, indices, start=0):
32 """find the Fortran HELAS position for the list of index"""
33
34@@ -170,18 +179,19 @@
35
36 return call_arg
37
38- def reorder_call_list(self, call_list, old, new):
39- """ restore the correct order for symmetries """
40- spins = self.particles
41- assert(0 < old < new)
42- old, new = old -1, new -1 # pass in real position in particles list
43- assert(spins[old] == spins[new])
44- spin =spins[old]
45-
46- new_call = call_list[:]
47- val = new_call.pop(old)
48- new_call.insert(new - 1, val)
49- return new_call
50+# def reorder_call_list(self, call_list, old, new):
51+# """ restore the correct order for symmetries """
52+# raise
53+# #spins = self.particles
54+# #assert(0 < old < new)
55+# #old, new = old -1, new -1 # pass in real position in particles list
56+# #assert(spins[old] == spins[new])
57+# #spin =spins[old]
58+#
59+# new_call = call_list[:]
60+# #val = new_call.pop(old)
61+# #new_call.insert(new - 1, val)
62+# return new_call
63
64
65 def make_momentum_conservation(self):
66@@ -249,42 +259,45 @@
67 'V':'double complex V%d(6)',
68 'T':'double complex T%s(18)'}
69
70- def define_header(self):
71+ def define_header(self, name=None):
72 """Define the Header of the fortran file. This include
73 - function tag
74 - definition of variable
75 """
76-
77+
78+ if not name:
79+ name = self.namestring
80+
81 Momenta = self.collected['momenta']
82 OverM = self.collected['om']
83
84 CallList = self.calllist['CallList']
85 declare_list = self.calllist['DeclareList']
86- if 'double complex C' in declare_list:
87+ if 'double complex COUP' in declare_list:
88 alredy_update = True
89 else:
90 alredy_update = False
91
92 if not alredy_update:
93- declare_list.append('double complex C')
94+ declare_list.append('double complex COUP')
95
96 # define the type of function and argument
97 if not self.offshell:
98 str_out = 'subroutine %(name)s(%(args)s,vertex)\n' % \
99- {'name': self.namestring,
100- 'args': ','.join(CallList+ ['C']) }
101+ {'name': name,
102+ 'args': ','.join(CallList+ ['COUP']) }
103 if not alredy_update:
104- declare_list.append('double complex vertex\n')
105+ declare_list.append('double complex vertex')
106 else:
107 if not alredy_update:
108 declare_list.append('double complex denom')
109 declare_list.append('double precision M%(id)d, W%(id)d' %
110 {'id': self.offshell})
111- call_arg = '%(args)s, C, M%(id)d, W%(id)d, %(spin)s%(id)d' % \
112+ call_arg = '%(args)s, COUP, M%(id)d, W%(id)d, %(spin)s%(id)d' % \
113 {'args': ', '.join(CallList),
114 'spin': self.particles[self.offshell -1],
115 'id': self.offshell}
116- str_out = ' subroutine %s(%s)\n' % (self.namestring, call_arg)
117+ str_out = ' subroutine %s(%s)\n' % (name, call_arg)
118
119 # Forcing implicit None
120 str_out += 'implicit none \n'
121@@ -402,7 +415,7 @@
122 OutString = ''
123 if not self.offshell:
124 for ind in self.obj.listindices():
125- string = 'Vertex = C*' + self.write_obj(self.obj.get_rep(ind))
126+ string = 'Vertex = COUP*' + self.write_obj(self.obj.get_rep(ind))
127 string = string.replace('+-', '-')
128 string = re.sub('\((?P<num>[+-]*[0-9])(?P<num2>[+-][0-9])[Jj]\)\.', '(\g<num>d0,\g<num2>d0)', string)
129 string = re.sub('(?P<num>[0-9])[Jj]\.', '\g<num>.*(0d0,1d0)', string)
130@@ -420,7 +433,7 @@
131 string = re.sub('(?P<num>[0-9])[Jj]\.', '\g<num>*(0d0,1d0)', string)
132 OutString = OutString + string + '\n'
133 for ind in numerator.listindices():
134- string = '%s(%d)= C*denom*' % (OffShellParticle, self.pass_to_HELAS(ind, start=1))
135+ string = '%s(%d)= COUP*denom*' % (OffShellParticle, self.pass_to_HELAS(ind, start=1))
136 string += self.write_obj(numerator.get_rep(ind))
137 string = string.replace('+-', '-')
138 string = re.sub('\((?P<num>[+-][0-9])\+(?P<num2>[+-][0-9])[Jj]\)\.', '(\g<num>d0,\g<num2>d0)', string)
139@@ -430,45 +443,167 @@
140
141 def define_symmetry(self, new_nb):
142 number = self.offshell
143- calls = self.reorder_call_list(self.calllist['CallList'], self.offshell,
144- new_nb)
145- Outstring = 'call '+self.namestring+'('+','.join(calls)+',C,M%s,W%s,%s%s)' \
146+ calls = self.calllist['CallList']
147+
148+ Outstring = 'call '+self.namestring+'('+','.join(calls)+',COUP,M%s,W%s,%s%s)\n' \
149 %(number,number,self.particles[number-1],number)
150 return Outstring
151
152 def define_foot(self):
153- return 'end'
154+ return 'end\n\n'
155
156 def write(self, mode='self'):
157-
158- writer = writers.FortranWriter(self.out_path)
159- writer.downcase = False
160- commentstring = 'This File is Automatically generated by ALOHA \n'
161- commentstring += 'The process calculated in this file is: \n'
162- commentstring += self.comment + '\n'
163- writer.write_comments(commentstring)
164-
165+
166 # write head - momenta - body - foot
167- writer.writelines(self.define_header())
168- writer.writelines(self.define_momenta())
169- writer.writelines(self.define_expression())
170- writer.writelines(self.define_foot())
171+ text = self.define_header()+'\n'
172+ text += self.define_momenta()+'\n'
173+ text += self.define_expression()
174+ text += self.define_foot()
175
176+ sym_text = []
177 for elem in self.symmetries:
178 symmetryhead = self.define_header().replace( \
179 self.namestring,self.namestring[0:-1]+'%s' %(elem))
180 symmetrybody = self.define_symmetry(elem)
181- writer.write_comments('\n%s\n' % ('#'*65))
182- writer.writelines(symmetryhead)
183- writer.writelines(symmetrybody)
184- writer.writelines(self.define_foot())
185-
186-
187+
188+ sym_text.append(symmetryhead + symmetrybody + self.define_foot())
189+
190+
191+ if self.out_path:
192+ writer = writers.FortranWriter(self.out_path)
193+ writer.downcase = False
194+ commentstring = 'This File is Automatically generated by ALOHA \n'
195+ commentstring += 'The process calculated in this file is: \n'
196+ commentstring += self.comment + '\n'
197+ writer.write_comments(commentstring)
198+ writer.writelines(text)
199+ for text in sym_text:
200+ writer.write_comments('\n%s\n' % ('#'*65))
201+ writer.writelines(text)
202+ else:
203+ for stext in sym_text:
204+ text += '\n\n' + stext
205+
206+ return text + '\n'
207+
208+ def write_combined(self, lor_names, mode='self', offshell=None):
209+ """Write routine for combine ALOHA call (more than one coupling)"""
210+
211+ # Set some usefull command
212+ if offshell is None:
213+ sym = 1
214+ offshell = self.offshell
215+ else:
216+ sym = None # deactivate symetry
217+
218+ name = combine_name(self.abstractname, lor_names, offshell)
219+
220+
221+ # write header
222+ header = self.define_header(name=name)
223+ new_couplings = ['COUP%s' % (i+1) for i in range(len(lor_names)+1)]
224+ text = header.replace('COUP', ','.join(new_couplings))
225+ # define the TMP for storing output
226+ if not offshell:
227+ text += ' double complex TMP\n'
228+ else:
229+ spin = self.particles[offshell -1]
230+ text += ' double complex TMP(%s)\n integer i' % self.type_to_size[spin]
231+
232+ # Define which part of the routine should be called
233+ if 'C' in self.namestring:
234+ addon = 'C' +self.namestring.split('C',1)[1]
235+ else:
236+ addon = '_%s' % self.offshell
237+
238+ # how to call the routine
239+ if not offshell:
240+ main = 'vertex'
241+ call_arg = '%(args)s, %(COUP)s, %(LAST)s' % \
242+ {'args': ', '.join(self.calllist['CallList']),
243+ 'COUP':'COUP%d',
244+ 'spin': self.particles[self.offshell -1],
245+ 'LAST': '%s'}
246+ else:
247+ main = '%(spin)s%(id)d' % \
248+ {'spin': self.particles[offshell -1],
249+ 'id': self.offshell}
250+ call_arg = '%(args)s, %(COUP)s, M%(id)d, W%(id)d, %(LAST)s' % \
251+ {'args': ', '.join(self.calllist['CallList']),
252+ 'COUP':'COUP%d',
253+ 'id': self.offshell,
254+ 'LAST': '%s'}
255+
256+ # make the first call
257+ line = " CALL %s%s("+call_arg+")\n"
258+ text += '\n\n' + line % (self.namestring, '', 1, main)
259+
260+ # make the other call
261+ for i,lor in enumerate(lor_names):
262+ text += line % (lor, addon, i+2, 'TMP')
263+ if not offshell:
264+ text += ' vertex = vertex + tmp\n'
265+ else:
266+ size = self.type_to_size[spin] -2
267+ text += """ do i=1,%(id)d
268+ %(main)s(i) = %(main)s(i) + tmp(i)
269+ enddo\n""" % {'id': size, 'main':main}
270+
271+
272+ text += self.define_foot()
273+
274+ #ADD SYMETRY
275+ if sym:
276+ for elem in self.symmetries:
277+ text += self.write_combined(lor_names, mode, elem)
278+
279+
280+ if self.out_path:
281+ # Prepare a specific file
282+ path = os.path.join(os.path.dirname(self.out_path), name+'.f')
283+ writer = writers.FortranWriter(path)
284+ writer.downcase = False
285+ commentstring = 'This File is Automatically generated by ALOHA \n'
286+ writer.write_comments(commentstring)
287+ writer.writelines(text)
288+
289+ return text
290+
291 def get_routine_name(name,outgoing):
292 """ build the name of the aloha function """
293
294 return '%s_%s' % (name, outgoing)
295
296+def combine_name(name, other_names, outgoing):
297+ """ build the name for combined aloha function """
298+
299+ # Two possible scheme FFV1C1_2_X or FFV1__FFV2C1_X
300+ # If they are all in FFVX scheme then use the first
301+ p=re.compile('^(?P<type>[FSVT]+)(?P<id>\d+)')
302+ routine = ''
303+ if p.search(name):
304+ base, id = p.search(name).groups()
305+ routine = name
306+ for s in other_names:
307+ try:
308+ base2,id2 = p.search(s).groups()
309+ except:
310+ routine = ''
311+ break # one matching not good -> other scheme
312+ if base != base2:
313+ routine = ''
314+ break # one matching not good -> other scheme
315+ else:
316+ routine += '_%s' % id2
317+ if routine:
318+ return routine +'_%s' % outgoing
319+
320+ addon = ''
321+ if 'C' in name:
322+ name, addon = name.split('C',1)
323+ addon = 'C' + addon
324+ return '__'.join((name,) + tuple(other_names)) + addon + '_%s' % outgoing
325+
326 class ALOHAWriterForCPP(WriteALOHA):
327 """Routines for writing out helicity amplitudes as C++ .h and .cc files."""
328
329@@ -477,17 +612,20 @@
330 'V':'double complex V%d[6]',
331 'T':'double complex T%s[18]'}
332
333- def define_header(self):
334+ def define_header(self, name=None):
335 """Define the headers for the C++ .h and .cc files. This include
336 - function tag
337 - definition of variable
338 - momentum conservation
339 """
340+
341+ if name is None:
342+ name = self.namestring
343
344 #Width = self.collected['width']
345 #Mass = self.collected['mass']
346
347- CallList = self.calllist['CallList']
348+ CallList = self.calllist['CallList'][:]
349
350 local_declare = []
351 OffShell = self.offshell
352@@ -503,12 +641,12 @@
353 # define the type of function and argument
354 if not OffShell:
355 str_out = 'void %(name)s(%(args)s, complex<double>& vertex)' % \
356- {'name': self.namestring,
357- 'args': ','.join(CallList + ['complex<double> C'])}
358+ {'name': name,
359+ 'args': ','.join(CallList + ['complex<double> COUP'])}
360 else:
361 str_out = 'void %(name)s(%(args)s, double M%(number)d, double W%(number)d, complex<double>%(out)s%(number)d[])' % \
362- {'name': self.namestring,
363- 'args': ','.join(CallList+ ['complex<double> C']),
364+ {'name': name,
365+ 'args': ','.join(CallList+ ['complex<double> COUP']),
366 'out': self.particles[OffShellParticle],
367 'number': OffShellParticle + 1
368 }
369@@ -613,7 +751,7 @@
370 OutString = ''
371 if not self.offshell:
372 for ind in self.obj.listindices():
373- string = 'vertex = C*' + self.write_obj(self.obj.get_rep(ind))
374+ string = 'vertex = COUP*' + self.write_obj(self.obj.get_rep(ind))
375 string = string.replace('+-', '-')
376 OutString = OutString + string + ';\n'
377 else:
378@@ -626,7 +764,7 @@
379 string = string.replace('+-', '-')
380 OutString = OutString + string + ';\n'
381 for ind in numerator.listindices():
382- string = '%s[%d]= C*denom*' % (OffShellParticle, self.pass_to_HELAS(ind))
383+ string = '%s[%d]= COUP*denom*' % (OffShellParticle, self.pass_to_HELAS(ind))
384 string += self.write_obj(numerator.get_rep(ind))
385 string = string.replace('+-', '-')
386 OutString = OutString + string + ';\n'
387@@ -636,8 +774,7 @@
388 remove_double = re.compile('complex<double> (?P<name>[\w]+)\[\]')
389 def define_symmetry(self, new_nb):
390 """Write the call for symmetric routines"""
391- calls = self.reorder_call_list(self.calllist['CallList'],
392- self.offshell, new_nb)
393+ calls = self.calllist['CallList']
394
395 for i, call in enumerate(calls):
396 if self.remove_double.match(call):
397@@ -647,22 +784,24 @@
398 #calls = [self.remove_double.match(call).group('name') for call in \
399 # calls]
400 number = self.offshell
401- Outstring = self.namestring+'('+','.join(calls)+',C,M%s,W%s,%s%s);' \
402+ Outstring = self.namestring+'('+','.join(calls)+',COUP,M%s,W%s,%s%s);\n' \
403 %(number,number,self.particles[self.offshell-1],number)
404 return Outstring
405
406 def define_foot(self):
407 """Return the end of the function definition"""
408
409- return '}\n'
410+ return '}\n\n'
411
412- def write_h(self, header):
413+ def write_h(self, header, compiler_cmd=True):
414 """Return the full contents of the .h file"""
415
416- h_string = '#ifndef '+ self.namestring + '_guard\n'
417- h_string += '#define ' + self.namestring + '_guard\n'
418- h_string += '#include <complex>\n'
419- h_string += 'using namespace std;\n\n'
420+ h_string = ''
421+ if compiler_cmd:
422+ h_string = '#ifndef '+ self.namestring + '_guard\n'
423+ h_string += '#define ' + self.namestring + '_guard\n'
424+ h_string += '#include <complex>\n'
425+ h_string += 'using namespace std;\n\n'
426
427 h_header = header['h_header']
428
429@@ -672,15 +811,44 @@
430 symmetryhead = h_header.replace( \
431 self.namestring,self.namestring[0:-1]+'%s' %(elem))
432 h_string += symmetryhead
433-
434- h_string += '#endif'
435+
436+ if compiler_cmd:
437+ h_string += '#endif\n\n'
438
439 return h_string
440
441- def write_cc(self, header):
442+ def write_combined_h(self, lor_names, offshell=None, compiler_cmd=True):
443+ """Return the content of the .h file linked to multiple lorentz call."""
444+
445+ name = combine_name(self.abstractname, lor_names, offshell)
446+ text= ''
447+ if compiler_cmd:
448+ text = '#ifndef '+ name + '_guard\n'
449+ text += '#define ' + name + '_guard\n'
450+ text += '#include <complex>\n'
451+ text += 'using namespace std;\n\n'
452+
453+ # write header
454+ header = self.define_header(name=name)
455+ h_header = header['h_header']
456+ new_couplings = ['COUP%s' % (i+1) for i in range(len(lor_names)+1)]
457+ h_string = h_header.replace('COUP', ', complex <double>'.join(new_couplings))
458+ text += h_string
459+
460+ for elem in self.symmetries:
461+ text += h_string.replace(name, name[0:-1]+str(elem))
462+
463+ if compiler_cmd:
464+ text += '#endif'
465+
466+ return text
467+
468+ def write_cc(self, header, compiler_cmd=True):
469 """Return the full contents of the .cc file"""
470
471- cc_string = '#include \"%s.h\"\n\n' % self.namestring
472+ cc_string = ''
473+ if compiler_cmd:
474+ cc_string = '#include \"%s.h\"\n\n' % self.namestring
475 cc_header = header['cc_header']
476 cc_string += cc_header
477 cc_string += self.define_momenta()
478@@ -696,24 +864,149 @@
479 cc_string += self.define_foot()
480
481 return cc_string
482+
483+ def write_combined_cc(self, lor_names, offshell=None, compiler_cmd=True, sym=True):
484+ "Return the content of the .cc file linked to multiple lorentz call."
485+
486+ # Set some usefull command
487+ if offshell is None:
488+ offshell = self.offshell
489+
490+ name = combine_name(self.abstractname, lor_names, offshell)
491+
492+ text = ''
493+ if compiler_cmd:
494+ text += '#include "%s.h"\n\n' % name
495+
496+ # write header
497+ header = self.define_header(name=name)['cc_header']
498+ new_couplings = ['COUP%s' % (i+1) for i in range(len(lor_names)+1)]
499+ text += header.replace('COUP', ', complex<double>'.join(new_couplings))
500+ # define the TMP for storing output
501+ if not offshell:
502+ text += 'complex<double> tmp;\n'
503+ else:
504+ spin = self.particles[offshell -1]
505+ text += 'complex<double> tmp[%s];\n int i = 0;' % self.type_to_size[spin]
506+
507+ # Define which part of the routine should be called
508+ if 'C' in self.namestring:
509+ addon = 'C' +self.namestring.split('C',1)[1]
510+ else:
511+ addon = '_%s' % self.offshell
512+
513+ # how to call the routine
514+ if not offshell:
515+ main = 'vertex'
516+ call_arg = '%(args)s, %(COUP)s, %(LAST)s' % \
517+ {'args': ', '.join(self.calllist['CallList']),
518+ 'COUP':'COUP%d',
519+ 'spin': self.particles[self.offshell -1],
520+ 'LAST': '%s'}
521+ else:
522+ main = '%(spin)s%(id)d' % \
523+ {'spin': self.particles[self.offshell -1],
524+ 'id': self.offshell}
525+ call_arg = '%(args)s, %(COUP)s, M%(id)d, W%(id)d, %(LAST)s' % \
526+ {'args': ', '.join(self.calllist['CallList']),
527+ 'COUP':'COUP%d',
528+ 'id': self.offshell,
529+ 'LAST': '%s'}
530+
531+ # make the first call
532+ line = "%s%s("+call_arg+");\n"
533+ text += '\n\n' + line % (self.namestring, '', 1, main)
534+
535+ # make the other call
536+ for i,lor in enumerate(lor_names):
537+ text += line % (lor, addon, i+2, 'tmp')
538+ if not offshell:
539+ text += ' vertex = vertex + tmp;\n'
540+ else:
541+ size = self.type_to_size[spin] -2
542+ text += """ while (i < %(id)d)
543+ {
544+ %(main)s[i] = %(main)s[i] + tmp[i];
545+ i++;
546+ }\n""" % {'id': size, 'main':main}
547+
548+
549+ text += self.define_foot()
550+
551+ if sym:
552+ for elem in self.symmetries:
553+ text += self.write_combined_cc(lor_names, elem,
554+ compiler_cmd=compiler_cmd,
555+ sym=False)
556+
557+
558+ if self.out_path:
559+ # Prepare a specific file
560+ path = os.path.join(os.path.dirname(self.out_path), name+'.f')
561+ writer = writers.FortranWriter(path)
562+ writer.downcase = False
563+ commentstring = 'This File is Automatically generated by ALOHA \n'
564+ writer.write_comments(commentstring)
565+ writer.writelines(text)
566+
567+ return text
568+
569+
570
571- def write(self, mode='self'):
572+ def write(self, mode='self', **opt):
573 """Write the .h and .cc files"""
574
575- writer_h = writers.CPPWriter(self.out_path + ".h")
576- writer_cc = writers.CPPWriter(self.out_path + ".cc")
577- commentstring = 'This File is Automatically generated by ALOHA \n'
578- commentstring += 'The process calculated in this file is: \n'
579- commentstring += self.comment + '\n'
580- writer_h.write_comments(commentstring)
581- writer_cc.write_comments(commentstring)
582-
583+
584 # write head - momenta - body - foot
585-
586 header = self.define_header()
587- writer_h.writelines(self.write_h(header))
588- writer_cc.writelines(self.write_cc(header))
589-
590+ h_text = self.write_h(header, **opt)
591+ cc_text = self.write_cc(header, **opt)
592+
593+ # write in two file
594+ if self.out_path:
595+ writer_h = writers.CPPWriter(self.out_path + ".h")
596+ writer_cc = writers.CPPWriter(self.out_path + ".cc")
597+ commentstring = 'This File is Automatically generated by ALOHA \n'
598+ commentstring += 'The process calculated in this file is: \n'
599+ commentstring += self.comment + '\n'
600+ writer_h.write_comments(commentstring)
601+ writer_cc.write_comments(commentstring)
602+ writer_h.writelines(h_text)
603+ writer_cc.writelines(cc_text)
604+
605+ return h_text, cc_text
606+
607+
608+
609+ def write_combined(self, lor_names, mode='self', offshell=None, **opt):
610+ """Write the .h and .cc files associated to the combined file"""
611+
612+ # Set some usefull command
613+ if offshell is None:
614+ offshell = self.offshell
615+
616+ name = combine_name(self.abstractname, lor_names, offshell)
617+
618+ h_text = self.write_combined_h(lor_names, offshell, **opt)
619+ cc_text = self.write_combined_cc(lor_names, offshell, sym=True, **opt)
620+
621+ if self.out_path:
622+ # Prepare a specific file
623+ path = os.path.join(os.path.dirname(self.out_path), name)
624+ commentstring = 'This File is Automatically generated by ALOHA \n'
625+
626+ writer_h = writers.CPPWriter(path + ".h")
627+ writer_h.write_comments(commentstring)
628+ writer_h.writelines(h_text)
629+
630+ writer_cc = writers.CPPWriter(path + ".cc")
631+ writer_cc.write_comments(commentstring)
632+ writer_cc.writelines(cc_text)
633+ else:
634+ return h_text, cc_text
635+
636+ return h_text, cc_text
637+
638 class ALOHAWriterForPython(WriteALOHA):
639 """ A class for returning a file/a string for python evaluation """
640
641@@ -723,18 +1016,11 @@
642 """ standard init but if dirpath is None the write routine will
643 return a string (which can be evaluated by an exec"""
644
645- if dirpath:
646- WriteALOHA.__init__(self, abstract_routine, dirpath)
647- else:
648- WriteALOHA.__init__(self, abstract_routine, '')
649- self.out_path = None
650- self.dir_out = None
651+ WriteALOHA.__init__(self, abstract_routine, dirpath)
652 self.outname = '%s%s' % (self.particles[self.offshell -1], \
653 self.offshell)
654
655-
656-
657-
658+
659 def change_var_format(self, name):
660 """Formatting the variable name to Python format
661 start to count at zero"""
662@@ -759,7 +1045,7 @@
663 OutString = ''
664 if not self.offshell:
665 for ind in self.obj.listindices():
666- string = 'vertex = C*' + self.write_obj(self.obj.get_rep(ind))
667+ string = 'vertex = COUP*' + self.write_obj(self.obj.get_rep(ind))
668 string = string.replace('+-', '-')
669 OutString = OutString + string + '\n'
670 else:
671@@ -773,7 +1059,7 @@
672 string = string.replace('+-', '-')
673 OutString += string + '\n'
674 for ind in numerator.listindices():
675- string = '%s[%d]= C*denom*' % (self.outname, self.pass_to_HELAS(ind))
676+ string = '%s[%d]= COUP*denom*' % (self.outname, self.pass_to_HELAS(ind))
677 string += self.write_obj(numerator.get_rep(ind))
678 string = string.replace('+-', '-')
679 OutString += string + '\n'
680@@ -781,17 +1067,19 @@
681
682 def define_foot(self):
683 if not self.offshell:
684- return 'return vertex'
685+ return 'return vertex\n\n'
686 else:
687- return 'return %s' % (self.outname)
688+ return 'return %s\n\n' % (self.outname)
689
690
691- def define_header(self):
692+ def define_header(self, name=None):
693 """Define the Header of the fortran file. This include
694 - function tag
695 - definition of variable
696 """
697-
698+ if name is None:
699+ name = self.namestring
700+
701 Momenta = self.collected['momenta']
702 OverM = self.collected['om']
703
704@@ -801,11 +1089,11 @@
705 # define the type of function and argument
706 if not self.offshell:
707 str_out += 'def %(name)s(%(args)s):\n' % \
708- {'name': self.namestring,
709- 'args': ','.join(CallList+ ['C']) }
710+ {'name': name,
711+ 'args': ','.join(CallList+ ['COUP']) }
712 else:
713- str_out += 'def %(name)s(%(args)s, C, M%(id)d, W%(id)d):\n' % \
714- {'name': self.namestring,
715+ str_out += 'def %(name)s(%(args)s, COUP, M%(id)d, W%(id)d):\n' % \
716+ {'name': name,
717 'args': ', '.join(CallList),
718 'id': self.offshell}
719 return str_out
720@@ -871,9 +1159,8 @@
721
722 def define_symmetry(self, new_nb):
723 number = self.offshell
724- calls = self.reorder_call_list(self.calllist['CallList'], self.offshell,
725- new_nb)
726- Outstring = 'return '+self.namestring+'('+','.join(calls)+',C,M%s,W%s)' \
727+ calls = self.calllist['CallList']
728+ Outstring = 'return '+self.namestring+'('+','.join(calls)+',COUP,M%s,W%s)\n' \
729 %(number,number)
730 return Outstring
731
732@@ -900,5 +1187,77 @@
733
734 if self.out_path:
735 ff = open(self.out_path,'w').write(text)
736- else:
737- return text
738+
739+ return text + '\n'
740+
741+ def write_combined(self, lor_names, mode='self', offshell=None):
742+ """Write routine for combine ALOHA call (more than one coupling)"""
743+
744+ # Set some usefull command
745+ if offshell is None:
746+ sym = 1
747+ offshell = self.offshell
748+ else:
749+ sym = None
750+ name = combine_name(self.abstractname, lor_names, offshell)
751+
752+ # write head - momenta - body - foot
753+ text = ''
754+ #if mode == 'mg5':
755+ # text = 'import aloha.template_files.wavefunctions as wavefunctions\n'
756+ #else:
757+ # text = 'import wavefunctions\n'
758+
759+
760+ # write header
761+ header = self.define_header(name=name)
762+ new_couplings = ['COUP%s' % (i+1) for i in range(len(lor_names)+1)]
763+ header = header.replace('COUP', ','.join(new_couplings))
764+
765+ text += header
766+
767+ # Define which part of the routine should be called
768+ if 'C' in self.namestring:
769+ addon = 'C' +self.namestring.split('C',1)[1]
770+ else:
771+ addon = '_%s' % self.offshell
772+
773+ # how to call the routine
774+ if not offshell:
775+ main = 'vertex'
776+ call_arg = '%(args)s, %(COUP)s' % \
777+ {'args': ', '.join(self.calllist['CallList']),
778+ 'COUP':'COUP%d',
779+ 'spin': self.particles[self.offshell -1]}
780+ else:
781+ main = '%(spin)s%(id)d' % \
782+ {'spin': self.particles[self.offshell -1],
783+ 'id': self.offshell}
784+ call_arg = '%(args)s, %(COUP)s, M%(id)d, W%(id)d' % \
785+ {'args': ', '.join(self.calllist['CallList']),
786+ 'COUP':'COUP%d',
787+ 'id': self.offshell}
788+
789+ # make the first call
790+ line = " %s = %s%s("+call_arg+")\n"
791+ text += '\n\n' + line % (main, self.namestring, '', 1)
792+
793+ # make the other call
794+ for i,name in enumerate(lor_names):
795+ text += line % ('tmp',name, addon, i+2)
796+ if not offshell:
797+ text += ' vertex += tmp\n'
798+ else:
799+ size = self.type_to_size[self.particles[offshell -1]] -2
800+ text += " for i in range(%(id)d):\n" % {'id': size}
801+ text += " %(main)s[i] += tmp[i]\n" %{'main': main}
802+
803+ text += ' '+self.define_foot()
804+
805+ #ADD SYMETRY
806+ if sym:
807+ for elem in self.symmetries:
808+ text += self.write_combined(lor_names, mode, elem)
809+
810+ return text
811+
812\ No newline at end of file
813
814=== modified file 'aloha/bin/aloha'
815--- aloha/bin/aloha 2011-02-03 09:33:24 +0000
816+++ aloha/bin/aloha 2011-04-20 16:57:29 +0000
817@@ -31,7 +31,7 @@
818
819 (options, args) = parser.parse_args()
820 if len(args) != 1:
821- sys.exit('ALOHA requires as arguments the path to UFO directory')
822+ sys.exit('ALOHA requires exactly one argument (the path to UFO directory)')
823
824 # Set logging level according to the logging level given by options
825 logging.basicConfig(level=vars(logging)[options.logging])
826
827=== modified file 'aloha/create_aloha.py'
828--- aloha/create_aloha.py 2011-03-31 18:03:05 +0000
829+++ aloha/create_aloha.py 2011-04-20 16:57:29 +0000
830@@ -56,18 +56,32 @@
831 self.outgoing = outgoing
832 self.infostr = infostr
833 self.symmetries = []
834+ self.combined = []
835
836 def add_symmetry(self, outgoing):
837 """ add an outgoing """
838
839 if not outgoing in self.symmetries:
840 self.symmetries.append(outgoing)
841-
842- def write(self, output_dir, language='Fortran', mode='self'):
843+
844+ def add_combine(self, lor_list):
845+ """add a combine rule """
846+
847+ if lor_list not in self.combined:
848+ self.combined.append(lor_list)
849+
850+ def write(self, output_dir, language='Fortran', mode='self', **opt):
851 """ write the content of the object """
852- return getattr(aloha_writers, 'ALOHAWriterFor%s' % language)(self, output_dir).write(mode=mode)
853-
854-
855+
856+ writer = getattr(aloha_writers, 'ALOHAWriterFor%s' % language)(self, output_dir)
857+ text = writer.write(mode=mode, **opt)
858+ for grouped in self.combined:
859+ if isinstance(text, tuple):
860+ text = tuple([old.__add__(new) for old, new in zip(text,
861+ writer.write_combined(grouped, mode=mode, **opt))])
862+ else:
863+ text += writer.write_combined(grouped, mode=mode, **opt)
864+ return text
865
866 class AbstractRoutineBuilder(object):
867 """ Launch the creation of the Helicity Routine"""
868@@ -346,6 +360,7 @@
869 # init the dictionary
870 dict.__init__(self)
871 self.symmetries = {}
872+ self.multiple_lor = {}
873
874 # check the mass of spin2 (if any)
875 self.massless_spin2 = self.has_massless_spin2()
876@@ -394,6 +409,7 @@
877
878 def load(self, filepos=None):
879 """ reload the pickle file """
880+ return False
881 if not filepos:
882 filepos = os.path.join(self.model_pos,'aloha.pkl')
883 if os.path.exists(filepos):
884@@ -426,6 +442,7 @@
885 #to compute identical contribution
886 self.look_for_symmetries()
887 conjugate_list = self.look_for_conjugate()
888+ self.look_for_multiple_lorentz_interactions()
889 if not wanted_lorentz:
890 wanted_lorentz = [l.name for l in self.model.all_lorentz]
891 for lorentz in self.model.all_lorentz:
892@@ -445,6 +462,13 @@
893 if 5 in lorentz.spins and self.massless_spin2 is not None:
894 builder.spin2_massless = self.massless_spin2
895 self.compute_aloha(builder)
896+
897+ if lorentz.name in self.multiple_lor:
898+ for m in self.multiple_lor[lorentz.name]:
899+ for outgoing in range(len(lorentz.spins)+1):
900+ self[(lorentz.name, outgoing)].add_combine(m)
901+
902+
903 if lorentz.name in conjugate_list:
904 conjg_builder_list= builder.define_all_conjugate_builder(\
905 conjugate_list[lorentz.name])
906@@ -452,6 +476,11 @@
907 # No duplication of conjugation:
908 assert conjg_builder_list.count(conjg_builder) == 1
909 self.compute_aloha(conjg_builder, lorentz.name)
910+ if lorentz.name in self.multiple_lor:
911+ for m in self.multiple_lor[lorentz.name]:
912+ for outgoing in range(len(lorentz.spins)+1):
913+ self[(conjg_builder.name, outgoing)].add_combine(m)
914+
915
916
917 if save:
918@@ -471,14 +500,16 @@
919 # reorganize the data (in order to use optimization for a given lorentz
920 #structure
921 request = {}
922- for l_name, conjugate, outgoing in data:
923- try:
924- request[l_name][conjugate].append(outgoing)
925- except:
926+ for list_l_name, conjugate, outgoing in data:
927+ for l_name in list_l_name:
928 try:
929- request[l_name][conjugate] = [outgoing]
930+ request[l_name][conjugate].append(outgoing)
931 except:
932- request[l_name] = {conjugate: [outgoing]}
933+ try:
934+ request[l_name][conjugate] = [outgoing]
935+ except:
936+ request[l_name] = {conjugate: [outgoing]}
937+
938 # Loop on the structure to build exactly what is request
939 for l_name in request:
940 lorentz = eval('self.model.lorentz.%s' % l_name)
941@@ -503,7 +534,14 @@
942 # Compute routines
943 self.compute_aloha(conjg_builder, symmetry=lorentz.name,
944 routines=routines)
945-
946+
947+ # Build mutiple lorentz call
948+ for list_l_name, conjugate, outgoing in data:
949+ if len(list_l_name) >1:
950+ lorentzname = list_l_name[0]
951+ for c in conjugate:
952+ lorentzname += 'C%s' % c
953+ self[(lorentzname, outgoing)].add_combine(list_l_name[1:])
954
955 def compute_aloha(self, builder, symmetry=None, routines=None):
956 """ define all the AbstractRoutine linked to a given lorentz structure
957@@ -520,7 +558,7 @@
958 for outgoing in routines:
959 symmetric = self.has_symmetries(symmetry, outgoing, valid_output=routines)
960 if symmetric:
961- self.get(symmetry, symmetric).add_symmetry(outgoing)
962+ self.get(name, symmetric).add_symmetry(outgoing)
963 else:
964 wavefunction = builder.compute_routine(outgoing)
965 #Store the information
966@@ -589,9 +627,9 @@
967 for i, part1 in enumerate(vertex.particles):
968 for j in range(i-1,-1,-1):
969 part2 = vertex.particles[j]
970- if part1.name == part2.name and \
971- part1.color == part2.color == 1 and\
972- part1.spin != 2:
973+ if part1.pdg_code == part2.pdg_code:
974+ if part1.spin == 2 and (i % 2 != j % 2 ):
975+ continue
976 for lorentz in vertex.lorentz:
977 if self.symmetries.has_key(lorentz.name):
978 if self.symmetries[lorentz.name].has_key(i+1):
979@@ -601,7 +639,46 @@
980 else:
981 self.symmetries[lorentz.name] = {i+1:j+1}
982 break
983+
984+ def look_for_multiple_lorentz_interactions(self):
985+ """Search the interaction associate with more than one lorentz structure.
986+ If those lorentz structure have the same order and the same color then
987+ associate a multiple lorentz routines to ALOHA """
988+
989+ orders = {}
990+ for coup in self.model.all_couplings:
991+ orders[coup.name] = str(coup.order)
992+
993+ for vertex in self.model.all_vertices:
994+ if len(vertex.lorentz) == 1:
995+ continue
996+ #remove ghost
997+ if -1 in vertex.lorentz[0].spins:
998+ continue
999+
1000+ # assign each order/color to a set of lorentz routine
1001+ combine = {}
1002+ for (id_col, id_lor), coup in vertex.couplings.items():
1003+ order = orders[coup.name]
1004+ key = (id_col, order)
1005+ if key in combine:
1006+ combine[key].append(id_lor)
1007+ else:
1008+ combine[key] = [id_lor]
1009
1010+ # Check if more than one routine are associated
1011+ for list_lor in combine.values():
1012+ if len(list_lor) == 1:
1013+ continue
1014+ list_lor.sort()
1015+ main = vertex.lorentz[list_lor[0]].name
1016+ if main not in self.multiple_lor:
1017+ self.multiple_lor[main] = []
1018+
1019+ info = tuple([vertex.lorentz[id].name for id in list_lor[1:]])
1020+ if info not in self.multiple_lor[main]:
1021+ self.multiple_lor[main].append(info)
1022+
1023 def has_massless_spin2(self):
1024 """Search if the spin2 particles are massless or not"""
1025
1026@@ -690,7 +767,7 @@
1027 aloha_files = []
1028
1029 # Identify the valid files
1030- alohafile_pattern = re.compile(r'''^[STFV]*[_C\d]*_\d%s''' % file_ext)
1031+ alohafile_pattern = re.compile(r'''^[STFV\d_]*[_C\d]*_\d%s''' % file_ext)
1032 for filename in os.listdir(aloha_dir):
1033 if os.path.isfile(os.path.join(aloha_dir, filename)):
1034 if alohafile_pattern.match(filename):
1035
1036=== modified file 'madgraph/core/helas_objects.py'
1037--- madgraph/core/helas_objects.py 2011-04-03 22:06:00 +0000
1038+++ madgraph/core/helas_objects.py 2011-04-20 16:57:29 +0000
1039@@ -72,16 +72,16 @@
1040 # interaction_id = the id of the interaction in the model
1041 # pdg_codes = the pdg_codes property of the interaction, [11, -11, 22]
1042 # inter_color = the 'color' property of the interaction: []
1043- # lorentz = the 'lorentz' property of the interaction: ['']
1044+ # lorentz = the 'lorentz' property of the interaction: ('')
1045 # couplings = the coupling names from the interaction: {(0,0):'MGVX12'}
1046 self['interaction_id'] = 0
1047 self['pdg_codes'] = []
1048 self['orders'] = {}
1049 self['inter_color'] = None
1050- self['lorentz'] = ''
1051- self['coupling'] = 'none'
1052- # The Lorentz and color index used in this wavefunction
1053- self['coupl_key'] = (0, 0)
1054+ self['lorentz'] = []
1055+ self['coupling'] = ['none']
1056+ # The color index used in this wavefunction
1057+ self['color_key'] = 0
1058 # Properties relating to the leg/vertex
1059 # state = initial/final (for external bosons),
1060 # intermediate (for intermediate bosons),
1061@@ -206,28 +206,32 @@
1062 "%s is not a valid Color String" % str(value)
1063
1064 if name == 'lorentz':
1065- #Should be a string
1066- if not isinstance(value, str):
1067- raise self.PhysicsObjectError, \
1068- "%s is not a valid string" % str(value)
1069+ #Should be a list of string
1070+ if not isinstance(value, list):
1071+ raise self.PhysicsObjectError, \
1072+ "%s is not a valid tuple" % str(value)
1073+ for name in value:
1074+ if not isinstance(name, str):
1075+ raise self.PhysicsObjectError, \
1076+ "%s doesn't contain only string" % str(value)
1077
1078 if name == 'coupling':
1079- #Should be a string
1080- if not isinstance(value, str):
1081- raise self.PhysicsObjectError, \
1082- "%s is not a valid coupling string" % \
1083- str(value)
1084+ #Should be a list of string
1085+ if not isinstance(value, list):
1086+ raise self.PhysicsObjectError, \
1087+ "%s is not a valid coupling string" % str(value)
1088+ for name in value:
1089+ if not isinstance(name, str):
1090+ raise self.PhysicsObjectError, \
1091+ "%s doesn't contain only string" % str(value)
1092+ if len(value) == 0:
1093+ raise self.PhysicsObjectError, \
1094+ "%s should have at least one value" % str(value)
1095
1096- if name == 'coupl_key':
1097- if value and not isinstance(value, tuple):
1098- raise self.PhysicsObjectError, \
1099- "%s is not a valid tuple" % str(value)
1100- if len(value) != 2:
1101- raise self.PhysicsObjectError, \
1102- "%s is not a valid tuple with 2 elements" % str(value)
1103- if not isinstance(value[0], int) or not isinstance(value[1], int):
1104- raise self.PhysicsObjectError, \
1105- "%s is not a valid tuple of integer" % str(value)
1106+ if name == 'color_key':
1107+ if value and not isinstance(value, int):
1108+ raise self.PhysicsObjectError, \
1109+ "%s is not a valid integer" % str(value)
1110
1111 if name == 'state':
1112 if not isinstance(value, str):
1113@@ -320,9 +324,9 @@
1114 if inter.get('color'):
1115 self.set('inter_color', inter.get('color')[0])
1116 if inter.get('lorentz'):
1117- self.set('lorentz', inter.get('lorentz')[0])
1118+ self.set('lorentz', [inter.get('lorentz')[0]])
1119 if inter.get('couplings'):
1120- self.set('coupling', inter.get('couplings').values()[0])
1121+ self.set('coupling', [inter.get('couplings').values()[0]])
1122 return True
1123 elif name == 'particle':
1124 self.set('particle', model.get('particle_dict')[value])
1125@@ -343,7 +347,7 @@
1126
1127 return ['particle', 'antiparticle', 'is_part',
1128 'interaction_id', 'pdg_codes', 'orders', 'inter_color',
1129- 'lorentz', 'coupling', 'coupl_key', 'state', 'number_external',
1130+ 'lorentz', 'coupling', 'color_key', 'state', 'number_external',
1131 'number', 'fermionflow', 'mothers']
1132
1133 # Helper functions
1134@@ -369,8 +373,8 @@
1135 array_rep = array.array('i', [self['interaction_id']])
1136 # Need the coupling key, to distinguish between
1137 # wavefunctions from the same interaction but different
1138- # Lorentz or color structures
1139- array_rep.extend(list(self['coupl_key']))
1140+ # color structures
1141+ array_rep.append(self['color_key'])
1142 # Finally, the mother numbers
1143 array_rep.extend([mother['number'] for \
1144 mother in self['mothers']])
1145@@ -406,7 +410,7 @@
1146 particles[1].get_anti_pdg_code()\
1147 and self.get('coupling')[0] != '-':
1148 # We need a minus sign in front of the coupling
1149- self.set('coupling', '-' + self.get('coupling'))
1150+ self.set('coupling', ['-' + c for c in self.get('coupling')])
1151
1152 def set_octet_majorana_coupling_sign(self):
1153 """For octet Majorana fermions, need an extra minus sign in
1154@@ -418,7 +422,7 @@
1155 self.get_spin_state_number() == -2 and \
1156 self.get('self_antipart') and \
1157 [m.get('color') for m in self.get('mothers')] == [8, 8]:
1158- self.set('coupling', '-' + self.get('coupling'))
1159+ self.set('coupling', ['-' + c for c in self.get('coupling')])
1160
1161 def set_state_and_particle(self, model):
1162 """Set incoming/outgoing state according to mother states and
1163@@ -794,7 +798,7 @@
1164 if self.needs_hermitian_conjugate():
1165 res.append(self.get_conjugate_index())
1166
1167- return (tuple(res), self.get('lorentz'))
1168+ return (tuple(res), tuple(self.get('lorentz')))
1169
1170 def get_base_vertices(self, wf_dict = {}, vx_list = [], optimization = 1):
1171 """Recursive method to get a base_objects.VertexList
1172@@ -876,7 +880,7 @@
1173 # This is where recursion happens
1174 color_indices.extend(mother.get_color_indices())
1175 # Add this wf's color index
1176- color_indices.append(self.get('coupl_key')[0])
1177+ color_indices.append(self.get('color_key'))
1178
1179 return color_indices
1180
1181@@ -1058,7 +1062,7 @@
1182 # Check relevant directly defined properties
1183 if self['number_external'] != other['number_external'] or \
1184 self['fermionflow'] != other['fermionflow'] or \
1185- self['coupl_key'] != other['coupl_key'] or \
1186+ self['color_key'] != other['color_key'] or \
1187 self['lorentz'] != other['lorentz'] or \
1188 self['coupling'] != other['coupling'] or \
1189 self['state'] != other['state'] or \
1190@@ -1293,10 +1297,10 @@
1191 self['pdg_codes'] = []
1192 self['orders'] = {}
1193 self['inter_color'] = None
1194- self['lorentz'] = ''
1195- self['coupling'] = 'none'
1196+ self['lorentz'] = []
1197+ self['coupling'] = ['none']
1198 # The Lorentz and color index used in this amplitude
1199- self['coupl_key'] = (0, 0)
1200+ self['color_key'] = 0
1201 # Properties relating to the vertex
1202 self['number'] = 0
1203 self['fermionfactor'] = 0
1204@@ -1359,28 +1363,33 @@
1205 "%s is not a valid Color String" % str(value)
1206
1207 if name == 'lorentz':
1208- #Should be a string
1209- if not isinstance(value, str):
1210- raise self.PhysicsObjectError, \
1211- "%s is not a valid string" % str(value)
1212-
1213+ #Should be a list of string
1214+ if not isinstance(value, list):
1215+ raise self.PhysicsObjectError, \
1216+ "%s is not a valid list of string" % str(value)
1217+ for name in value:
1218+ if not isinstance(name, str):
1219+ raise self.PhysicsObjectError, \
1220+ "%s doesn't contain only string" % str(value)
1221+
1222 if name == 'coupling':
1223- #Should be a string
1224- if not isinstance(value, str):
1225- raise self.PhysicsObjectError, \
1226- "%s is not a valid coupling string" % \
1227- str(value)
1228+ #Should be a list of string
1229+ if not isinstance(value, list):
1230+ raise self.PhysicsObjectError, \
1231+ "%s is not a valid coupling (list of string)" % str(value)
1232+
1233+ for name in value:
1234+ if not isinstance(name, str):
1235+ raise self.PhysicsObjectError, \
1236+ "%s doesn't contain only string" % str(value)
1237+ if not len(value):
1238+ raise self.PhysicsObjectError, \
1239+ 'coupling should have at least one value'
1240
1241- if name == 'coupl_key':
1242- if value and not isinstance(value, tuple):
1243- raise self.PhysicsObjectError, \
1244- "%s is not a valid tuple" % str(value)
1245- if len(value) != 2:
1246- raise self.PhysicsObjectError, \
1247- "%s is not a valid tuple with 2 elements" % str(value)
1248- if not isinstance(value[0], int) or not isinstance(value[1], int):
1249- raise self.PhysicsObjectError, \
1250- "%s is not a valid tuple of integer" % str(value)
1251+ if name == 'color_key':
1252+ if value and not isinstance(value, int):
1253+ raise self.PhysicsObjectError, \
1254+ "%s is not a valid integer" % str(value)
1255
1256 if name == 'number':
1257 if not isinstance(value, int):
1258@@ -1416,6 +1425,30 @@
1259
1260 return True
1261
1262+ def __str__(self):
1263+ """ practicle way to represent an HelasAmplitude"""
1264+
1265+ mystr = '{\n'
1266+ for prop in self.get_sorted_keys():
1267+ if isinstance(self[prop], str):
1268+ mystr = mystr + ' \'' + prop + '\': \'' + \
1269+ self[prop] + '\',\n'
1270+ elif isinstance(self[prop], float):
1271+ mystr = mystr + ' \'' + prop + '\': %.2f,\n' % self[prop]
1272+ elif isinstance(self[prop], int):
1273+ mystr = mystr + ' \'' + prop + '\': %s,\n' % self[prop]
1274+ elif prop != 'mothers':
1275+ mystr = mystr + ' \'' + prop + '\': ' + \
1276+ str(self[prop]) + ',\n'
1277+ else:
1278+ info = [m.get('pdg_code') for m in self['mothers']]
1279+ mystr += ' \'%s\': %s,\n' % (prop, info)
1280+
1281+ mystr = mystr.rstrip(',\n')
1282+ mystr = mystr + '\n}'
1283+
1284+ return mystr
1285+
1286 # Enhanced get function
1287 def get(self, name):
1288 """Get the value of the property name."""
1289@@ -1453,9 +1486,9 @@
1290 if inter.get('color'):
1291 self.set('inter_color', inter.get('color')[0])
1292 if inter.get('lorentz'):
1293- self.set('lorentz', inter.get('lorentz')[0])
1294+ self.set('lorentz', [inter.get('lorentz')[0]])
1295 if inter.get('couplings'):
1296- self.set('coupling', inter.get('couplings').values()[0])
1297+ self.set('coupling', [inter.get('couplings').values()[0]])
1298 return True
1299 else:
1300 raise self.PhysicsObjectError, \
1301@@ -1467,7 +1500,7 @@
1302 """Return particle property names as a nicely sorted list."""
1303
1304 return ['interaction_id', 'pdg_codes', 'orders', 'inter_color',
1305- 'lorentz', 'coupling', 'coupl_key', 'number', 'color_indices',
1306+ 'lorentz', 'coupling', 'color_key', 'number', 'color_indices',
1307 'fermionfactor', 'mothers']
1308
1309
1310@@ -1516,7 +1549,7 @@
1311 if self.needs_hermitian_conjugate():
1312 res.append(self.get_conjugate_index())
1313
1314- return (tuple(res), self.get('lorentz'))
1315+ return (tuple(res), tuple(self.get('lorentz')))
1316
1317 def calculate_fermionfactor(self):
1318 """Calculate the fermion factor for the diagram corresponding
1319@@ -1770,7 +1803,7 @@
1320
1321 # Add this amp's color index
1322 if self.get('interaction_id'):
1323- color_indices.append(self.get('coupl_key')[0])
1324+ color_indices.append(self.get('color_key'))
1325
1326 return color_indices
1327
1328@@ -2218,15 +2251,22 @@
1329
1330 # Now generate new wavefunction for the last leg
1331
1332- # Need one amplitude for each Lorentz/color structure,
1333- # i.e. for each coupling
1334+ # Need one amplitude for each color structure,
1335+ done_color = {} # store link to color
1336 for coupl_key in sorted(inter.get('couplings').keys()):
1337+ color = coupl_key[0]
1338+ if color in done_color:
1339+ wf = done_color[color]
1340+ wf.get('coupling').append(inter.get('couplings')[coupl_key])
1341+ wf.get('lorentz').append(inter.get('lorentz')[coupl_key[1]])
1342+ continue
1343 wf = HelasWavefunction(last_leg, vertex.get('id'), model)
1344- wf.set('coupling', inter.get('couplings')[coupl_key])
1345+ wf.set('coupling', [inter.get('couplings')[coupl_key]])
1346 if inter.get('color'):
1347 wf.set('inter_color', inter.get('color')[coupl_key[0]])
1348- wf.set('lorentz', inter.get('lorentz')[coupl_key[1]])
1349- wf.set('coupl_key', coupl_key)
1350+ done_color[color] = wf
1351+ wf.set('lorentz', [inter.get('lorentz')[coupl_key[1]]])
1352+ wf.set('color_key', color)
1353 wf.set('mothers', mothers)
1354 # Need to set incoming/outgoing and
1355 # particle/antiparticle according to the fermion flow
1356@@ -2312,24 +2352,29 @@
1357 wf_number,
1358 False,
1359 number_to_wavefunctions)
1360-
1361+ done_color = {}
1362 for i, coupl_key in enumerate(keys):
1363+ color = coupl_key[0]
1364+ if inter and color in done_color.keys():
1365+ amp = done_color[color]
1366+ amp.get('coupling').append(inter.get('couplings')[coupl_key])
1367+ amp.get('lorentz').append(inter.get('lorentz')[coupl_key[1]])
1368+ continue
1369 amp = HelasAmplitude(lastvx, model)
1370 if inter:
1371- amp.set('coupling', inter.get('couplings')[coupl_key])
1372- amp.set('lorentz', inter.get('lorentz')[\
1373- coupl_key[1]])
1374+ amp.set('coupling', [inter.get('couplings')[coupl_key]])
1375+ amp.set('lorentz', [inter.get('lorentz')[coupl_key[1]]])
1376 if inter.get('color'):
1377- amp.set('inter_color', inter.get('color')[\
1378- coupl_key[0]])
1379- amp.set('coupl_key', coupl_key)
1380+ amp.set('inter_color', inter.get('color')[color])
1381+ amp.set('color_key', color)
1382+ done_color[color] = amp
1383 amp.set('mothers', mothers)
1384 amplitude_number = amplitude_number + 1
1385 amp.set('number', amplitude_number)
1386 # Add the list with color indices to the amplitude
1387 new_color_list = copy.copy(color_list)
1388 if inter:
1389- new_color_list.append(coupl_key[0])
1390+ new_color_list.append(color)
1391
1392 amp.set('color_indices', new_color_list)
1393
1394@@ -3291,7 +3336,7 @@
1395 """Return a list of (lorentz_name, conjugate, outgoing) with
1396 all lorentz structures used by this HelasMatrixElement."""
1397
1398- return [(wa.get('lorentz'), tuple(wa.get_conjugate_index()),
1399+ return [(tuple(wa.get('lorentz')), tuple(wa.get_conjugate_index()),
1400 wa.find_outgoing_number()) for wa in \
1401 self.get_all_wavefunctions() + self.get_all_amplitudes() \
1402 if wa.get('interaction_id') != 0]
1403@@ -3967,7 +4012,7 @@
1404 coupling_list = []
1405
1406 for me in self.get('matrix_elements'):
1407- coupling_list.extend(me.get_used_couplings())
1408+ coupling_list.extend([c for l in me.get_used_couplings() for c in l])
1409
1410 return list(set(coupling_list))
1411
1412
1413=== modified file 'madgraph/interface/cmd_interface.py'
1414--- madgraph/interface/cmd_interface.py 2011-04-20 13:10:25 +0000
1415+++ madgraph/interface/cmd_interface.py 2011-04-20 16:57:29 +0000
1416@@ -2443,7 +2443,6 @@
1417 raise self.InvalidCmd , '%s cannot be run from MG5 interface' % args[0]
1418
1419
1420-
1421 ext_program.run()
1422
1423
1424
1425=== modified file 'madgraph/iolibs/export_cpp.py'
1426--- madgraph/iolibs/export_cpp.py 2011-04-15 19:21:44 +0000
1427+++ madgraph/iolibs/export_cpp.py 2011-04-20 16:57:29 +0000
1428@@ -232,7 +232,10 @@
1429 else:
1430 self.process_string = self.processes[0].base_string()
1431
1432- self.process_number = process_number
1433+ if process_number:
1434+ self.process_number = process_number
1435+ else:
1436+ self.process_number = self.processes[0].get('id')
1437
1438 self.process_name = self.get_process_name()
1439 self.process_class = "CPPProcess"
1440@@ -1881,14 +1884,21 @@
1441 aloha_model.compute_subset(self.wanted_lorentz)
1442 else:
1443 aloha_model.compute_all(save=False)
1444+
1445 for abstracthelas in dict(aloha_model).values():
1446- aloha_writer = aloha_writers.ALOHAWriterForCPP(abstracthelas,
1447- self.dir_path)
1448- header = aloha_writer.define_header()
1449- template_h_files.append(self.write_function_declaration(\
1450- aloha_writer, header))
1451- template_cc_files.append(self.write_function_definition(\
1452- aloha_writer, header))
1453+ h_rout, cc_rout = abstracthelas.write(output_dir=None, language='CPP',
1454+ compiler_cmd=False)
1455+
1456+ template_h_files.append(h_rout)
1457+ template_cc_files.append(cc_rout)
1458+
1459+ #aloha_writer = aloha_writers.ALOHAWriterForCPP(abstracthelas,
1460+ # self.dir_path)
1461+ #header = aloha_writer.define_header()
1462+ #template_h_files.append(self.write_function_declaration(\
1463+ # aloha_writer, header))
1464+ #template_cc_files.append(self.write_function_definition(\
1465+ # aloha_writer, header))
1466
1467 replace_dict['function_declarations'] = '\n'.join(template_h_files)
1468 replace_dict['function_definitions'] = '\n'.join(template_cc_files)
1469@@ -1928,27 +1938,27 @@
1470
1471 return template_files
1472
1473- def write_function_declaration(self, aloha_writer, header):
1474- """Write the function declaration for the ALOHA routine"""
1475-
1476- ret_lines = []
1477- for line in aloha_writer.write_h(header).split('\n'):
1478- if self.compiler_option_re.match(line) or self.namespace_re.match(line):
1479- # Strip out compiler flags and namespaces
1480- continue
1481- ret_lines.append(line)
1482- return "\n".join(ret_lines)
1483-
1484- def write_function_definition(self, aloha_writer, header):
1485- """Write the function definition for the ALOHA routine"""
1486-
1487- ret_lines = []
1488- for line in aloha_writer.write_cc(header).split('\n'):
1489- if self.compiler_option_re.match(line) or self.namespace_re.match(line):
1490- # Strip out compiler flags and namespaces
1491- continue
1492- ret_lines.append(line)
1493- return "\n".join(ret_lines)
1494+# def write_function_declaration(self, aloha_writer, header):
1495+# """Write the function declaration for the ALOHA routine"""
1496+#
1497+# ret_lines = []
1498+# for line in aloha_writer.write_h(header).split('\n'):
1499+# if self.compiler_option_re.match(line) or self.namespace_re.match(line):
1500+# # Strip out compiler flags and namespaces
1501+# continue
1502+# ret_lines.append(line)
1503+# return "\n".join(ret_lines)
1504+#
1505+# def write_function_definition(self, aloha_writer, header):
1506+# """Write the function definition for the ALOHA routine"""
1507+#
1508+# ret_lines = []
1509+# for line in aloha_writer.write_cc(header).split('\n'):
1510+# if self.compiler_option_re.match(line) or self.namespace_re.match(line):
1511+# # Strip out compiler flags and namespaces
1512+# continue
1513+# ret_lines.append(line)
1514+# return "\n".join(ret_lines)
1515
1516 def clean_line(self, line):
1517 """Strip a line of compiler options and namespace options."""
1518
1519=== modified file 'madgraph/iolibs/export_python.py'
1520--- madgraph/iolibs/export_python.py 2010-12-01 01:33:28 +0000
1521+++ madgraph/iolibs/export_python.py 2011-04-20 16:57:29 +0000
1522@@ -354,10 +354,12 @@
1523 parameters.remove('ZERO')
1524
1525 # Get all couplings used
1526- couplings = list(set([func.get('coupling').replace('-', '') for func \
1527+
1528+
1529+ couplings = list(set([c.replace('-', '') for func \
1530 in matrix_element.get_all_wavefunctions() + \
1531- matrix_element.get_all_amplitudes()
1532- if func.get('mothers')]))
1533+ matrix_element.get_all_amplitudes() for c in func.get('coupling')
1534+ if func.get('mothers') ]))
1535
1536 return "\n ".join([\
1537 "%(param)s = model.get(\'parameter_dict\')[\"%(param)s\"]"\
1538
1539=== modified file 'madgraph/iolibs/export_v4.py'
1540--- madgraph/iolibs/export_v4.py 2011-04-18 15:25:50 +0000
1541+++ madgraph/iolibs/export_v4.py 2011-04-20 16:57:29 +0000
1542@@ -2477,11 +2477,6 @@
1543 double complex gal(2)
1544 common/weak/ gal
1545
1546- double precision DUM0
1547- common/FRDUM0/ DUM0
1548-
1549- double precision DUM1
1550- common/FRDUM1/ DUM1
1551 """
1552 fsock.writelines(header)
1553
1554@@ -2587,10 +2582,6 @@
1555 gal(2) = 1d0
1556 """)
1557
1558- fsock.write_comments("\nDefinition of DUM symbols\n")
1559- fsock.writelines(""" DUM0 = 0
1560- DUM1 = 1
1561- """)
1562
1563 def create_couplings(self):
1564 """ create couplings.f and all couplingsX.f """
1565
1566=== modified file 'madgraph/iolibs/helas_call_writers.py'
1567--- madgraph/iolibs/helas_call_writers.py 2011-03-31 18:03:05 +0000
1568+++ madgraph/iolibs/helas_call_writers.py 2011-04-20 16:57:29 +0000
1569@@ -16,6 +16,7 @@
1570
1571 import madgraph.core.base_objects as base_objects
1572 import madgraph.core.helas_objects as helas_objects
1573+import aloha.aloha_writers as aloha_writers
1574 from madgraph import MadGraph5Error
1575
1576
1577@@ -224,210 +225,210 @@
1578
1579 # Gluon 4-vertex division tensor calls ggT for the FR sm and mssm
1580
1581- key = ((3, 3, 5, 3), 'A')
1582+ key = ((3, 3, 5, 3), ('A',))
1583 call = lambda wf: \
1584 "CALL UVVAXX(W(1,%d),W(1,%d),%s,zero,zero,zero,W(1,%d))" % \
1585 (FortranHelasCallWriter.sorted_mothers(wf)[0].get('number'),
1586 FortranHelasCallWriter.sorted_mothers(wf)[1].get('number'),
1587- wf.get('coupling'),
1588+ wf.get('coupling')[0],
1589 wf.get('number'))
1590 self.add_wavefunction(key, call)
1591
1592- key = ((3, 5, 3, 1), 'A')
1593+ key = ((3, 5, 3, 1), ('A',))
1594 call = lambda wf: \
1595 "CALL JVTAXX(W(1,%d),W(1,%d),%s,zero,zero,W(1,%d))" % \
1596 (FortranHelasCallWriter.sorted_mothers(wf)[0].get('number'),
1597 FortranHelasCallWriter.sorted_mothers(wf)[1].get('number'),
1598- wf.get('coupling'),
1599+ wf.get('coupling')[0],
1600 wf.get('number'))
1601 self.add_wavefunction(key, call)
1602
1603- key = ((3, 3, 5), 'A')
1604+ key = ((3, 3, 5), ('A',))
1605 call = lambda amp: \
1606 "CALL VVTAXX(W(1,%d),W(1,%d),W(1,%d),%s,zero,AMP(%d))" % \
1607 (FortranHelasCallWriter.sorted_mothers(amp)[0].get('number'),
1608 FortranHelasCallWriter.sorted_mothers(amp)[1].get('number'),
1609 FortranHelasCallWriter.sorted_mothers(amp)[2].get('number'),
1610- amp.get('coupling'),
1611+ amp.get('coupling')[0],
1612 amp.get('number'))
1613 self.add_amplitude(key, call)
1614
1615 # SM gluon 4-vertex components
1616
1617- key = ((3, 3, 3, 3, 1), 'gggg3')
1618+ key = ((3, 3, 3, 3, 1), ('gggg3',))
1619 call = lambda wf: \
1620 "CALL JGGGXX(W(1,%d),W(1,%d),W(1,%d),%s,W(1,%d))" % \
1621 (FortranHelasCallWriter.sorted_mothers(wf)[1].get('number'),
1622 FortranHelasCallWriter.sorted_mothers(wf)[0].get('number'),
1623 FortranHelasCallWriter.sorted_mothers(wf)[2].get('number'),
1624- wf.get('coupling'),
1625+ wf.get('coupling')[0],
1626 wf.get('number'))
1627 self.add_wavefunction(key, call)
1628- key = ((3, 3, 3, 3), 'gggg1')
1629+ key = ((3, 3, 3, 3), ('gggg1',))
1630 call = lambda amp: \
1631 "CALL GGGGXX(W(1,%d),W(1,%d),W(1,%d),W(1,%d),%s,AMP(%d))" % \
1632 (FortranHelasCallWriter.sorted_mothers(amp)[0].get('number'),
1633 FortranHelasCallWriter.sorted_mothers(amp)[1].get('number'),
1634 FortranHelasCallWriter.sorted_mothers(amp)[2].get('number'),
1635 FortranHelasCallWriter.sorted_mothers(amp)[3].get('number'),
1636- amp.get('coupling'),
1637+ amp.get('coupling')[0],
1638 amp.get('number'))
1639 self.add_amplitude(key, call)
1640- key = ((3, 3, 3, 3, 1), 'gggg2')
1641+ key = ((3, 3, 3, 3, 1), ('gggg2',))
1642 call = lambda wf: \
1643 "CALL JGGGXX(W(1,%d),W(1,%d),W(1,%d),%s,W(1,%d))" % \
1644 (FortranHelasCallWriter.sorted_mothers(wf)[0].get('number'),
1645 FortranHelasCallWriter.sorted_mothers(wf)[2].get('number'),
1646 FortranHelasCallWriter.sorted_mothers(wf)[1].get('number'),
1647- wf.get('coupling'),
1648+ wf.get('coupling')[0],
1649 wf.get('number'))
1650 self.add_wavefunction(key, call)
1651- key = ((3, 3, 3, 3), 'gggg2')
1652+ key = ((3, 3, 3, 3), ('gggg2',))
1653 call = lambda amp: \
1654 "CALL GGGGXX(W(1,%d),W(1,%d),W(1,%d),W(1,%d),%s,AMP(%d))" % \
1655 (FortranHelasCallWriter.sorted_mothers(amp)[2].get('number'),
1656 FortranHelasCallWriter.sorted_mothers(amp)[0].get('number'),
1657 FortranHelasCallWriter.sorted_mothers(amp)[1].get('number'),
1658 FortranHelasCallWriter.sorted_mothers(amp)[3].get('number'),
1659- amp.get('coupling'),
1660+ amp.get('coupling')[0],
1661 amp.get('number'))
1662 self.add_amplitude(key, call)
1663- key = ((3, 3, 3, 3, 1), 'gggg1')
1664+ key = ((3, 3, 3, 3, 1), ('gggg1',))
1665 call = lambda wf: \
1666 "CALL JGGGXX(W(1,%d),W(1,%d),W(1,%d),%s,W(1,%d))" % \
1667 (FortranHelasCallWriter.sorted_mothers(wf)[2].get('number'),
1668 FortranHelasCallWriter.sorted_mothers(wf)[1].get('number'),
1669 FortranHelasCallWriter.sorted_mothers(wf)[0].get('number'),
1670- wf.get('coupling'),
1671+ wf.get('coupling')[0],
1672 wf.get('number'))
1673 self.add_wavefunction(key, call)
1674- key = ((3, 3, 3, 3), 'gggg3')
1675+ key = ((3, 3, 3, 3), ('gggg3',))
1676 call = lambda amp: \
1677 "CALL GGGGXX(W(1,%d),W(1,%d),W(1,%d),W(1,%d),%s,AMP(%d))" % \
1678 (FortranHelasCallWriter.sorted_mothers(amp)[1].get('number'),
1679 FortranHelasCallWriter.sorted_mothers(amp)[2].get('number'),
1680 FortranHelasCallWriter.sorted_mothers(amp)[0].get('number'),
1681 FortranHelasCallWriter.sorted_mothers(amp)[3].get('number'),
1682- amp.get('coupling'),
1683- amp.get('number'))
1684- self.add_amplitude(key, call)
1685-
1686- # HEFT VVVS calls
1687-
1688- key = ((1, 3, 3, 3, 3), '')
1689- call = lambda wf: \
1690- "CALL JVVSXX(W(1,%d),W(1,%d),W(1,%d),DUM1,%s,%s,%s,W(1,%d))" % \
1691- (wf.get('mothers')[0].get('number'),
1692- wf.get('mothers')[1].get('number'),
1693- wf.get('mothers')[2].get('number'),
1694- wf.get('coupling'),
1695- wf.get('mass'),
1696- wf.get('width'),
1697- wf.get('number'))
1698- self.add_wavefunction(key, call)
1699-
1700- key = ((3, 3, 3, 1, 4), '')
1701- call = lambda wf: \
1702- "CALL HVVVXX(W(1,%d),W(1,%d),W(1,%d),DUM1,%s,%s,%s,W(1,%d))" % \
1703- (wf.get('mothers')[0].get('number'),
1704- wf.get('mothers')[1].get('number'),
1705- wf.get('mothers')[2].get('number'),
1706- wf.get('coupling'),
1707- wf.get('mass'),
1708- wf.get('width'),
1709- wf.get('number'))
1710- self.add_wavefunction(key, call)
1711-
1712- key = ((1, 3, 3, 3), '')
1713- call = lambda amp: \
1714- "CALL VVVSXX(W(1,%d),W(1,%d),W(1,%d),W(1,%d),DUM1,%s,AMP(%d))" % \
1715- (amp.get('mothers')[0].get('number'),
1716- amp.get('mothers')[1].get('number'),
1717- amp.get('mothers')[2].get('number'),
1718- amp.get('mothers')[3].get('number'),
1719- amp.get('coupling'),
1720- amp.get('number'))
1721- self.add_amplitude(key, call)
1722-
1723- # HEFT VVVS calls
1724-
1725- key = ((1, 3, 3, 3, 1), '')
1726- call = lambda wf: \
1727- "CALL JVVSXX(W(1,%d),W(1,%d),W(1,%d),DUM1,%s,%s,%s,W(1,%d))" % \
1728- (wf.get('mothers')[0].get('number'),
1729- wf.get('mothers')[1].get('number'),
1730- wf.get('mothers')[2].get('number'),
1731- wf.get('coupling'),
1732- wf.get('mass'),
1733- wf.get('width'),
1734- wf.get('number'))
1735- self.add_wavefunction(key, call)
1736-
1737- key = ((3, 3, 3, 1, 4), '')
1738- call = lambda wf: \
1739- "CALL HVVVXX(W(1,%d),W(1,%d),W(1,%d),DUM1,%s,%s,%s,W(1,%d))" % \
1740- (wf.get('mothers')[0].get('number'),
1741- wf.get('mothers')[1].get('number'),
1742- wf.get('mothers')[2].get('number'),
1743- wf.get('coupling'),
1744- wf.get('mass'),
1745- wf.get('width'),
1746- wf.get('number'))
1747- self.add_wavefunction(key, call)
1748-
1749- key = ((1, 3, 3, 3), '')
1750- call = lambda amp: \
1751- "CALL VVVSXX(W(1,%d),W(1,%d),W(1,%d),W(1,%d),DUM1,%s,AMP(%d))" % \
1752- (amp.get('mothers')[0].get('number'),
1753- amp.get('mothers')[1].get('number'),
1754- amp.get('mothers')[2].get('number'),
1755- amp.get('mothers')[3].get('number'),
1756- amp.get('coupling'),
1757+ amp.get('coupling')[0],
1758+ amp.get('number'))
1759+ self.add_amplitude(key, call)
1760+
1761+ # HEFT VVVS calls
1762+
1763+ key = ((1, 3, 3, 3, 3), ('',))
1764+ call = lambda wf: \
1765+ "CALL JVVSXX(W(1,%d),W(1,%d),W(1,%d),DUM1,%s,%s,%s,W(1,%d))" % \
1766+ (wf.get('mothers')[0].get('number'),
1767+ wf.get('mothers')[1].get('number'),
1768+ wf.get('mothers')[2].get('number'),
1769+ wf.get('coupling')[0],
1770+ wf.get('mass'),
1771+ wf.get('width'),
1772+ wf.get('number'))
1773+ self.add_wavefunction(key, call)
1774+
1775+ key = ((3, 3, 3, 1, 4), ('',))
1776+ call = lambda wf: \
1777+ "CALL HVVVXX(W(1,%d),W(1,%d),W(1,%d),DUM1,%s,%s,%s,W(1,%d))" % \
1778+ (wf.get('mothers')[0].get('number'),
1779+ wf.get('mothers')[1].get('number'),
1780+ wf.get('mothers')[2].get('number'),
1781+ wf.get('coupling')[0],
1782+ wf.get('mass'),
1783+ wf.get('width'),
1784+ wf.get('number'))
1785+ self.add_wavefunction(key, call)
1786+
1787+ key = ((1, 3, 3, 3), ('',))
1788+ call = lambda amp: \
1789+ "CALL VVVSXX(W(1,%d),W(1,%d),W(1,%d),W(1,%d),DUM1,%s,AMP(%d))" % \
1790+ (amp.get('mothers')[0].get('number'),
1791+ amp.get('mothers')[1].get('number'),
1792+ amp.get('mothers')[2].get('number'),
1793+ amp.get('mothers')[3].get('number'),
1794+ amp.get('coupling')[0],
1795+ amp.get('number'))
1796+ self.add_amplitude(key, call)
1797+
1798+ # HEFT VVVS calls
1799+
1800+ key = ((1, 3, 3, 3, 1), ('',))
1801+ call = lambda wf: \
1802+ "CALL JVVSXX(W(1,%d),W(1,%d),W(1,%d),DUM1,%s,%s,%s,W(1,%d))" % \
1803+ (wf.get('mothers')[0].get('number'),
1804+ wf.get('mothers')[1].get('number'),
1805+ wf.get('mothers')[2].get('number'),
1806+ wf.get('coupling')[0],
1807+ wf.get('mass'),
1808+ wf.get('width'),
1809+ wf.get('number'))
1810+ self.add_wavefunction(key, call)
1811+
1812+ key = ((3, 3, 3, 1, 4), ('',))
1813+ call = lambda wf: \
1814+ "CALL HVVVXX(W(1,%d),W(1,%d),W(1,%d),DUM1,%s,%s,%s,W(1,%d))" % \
1815+ (wf.get('mothers')[0].get('number'),
1816+ wf.get('mothers')[1].get('number'),
1817+ wf.get('mothers')[2].get('number'),
1818+ wf.get('coupling')[0],
1819+ wf.get('mass'),
1820+ wf.get('width'),
1821+ wf.get('number'))
1822+ self.add_wavefunction(key, call)
1823+
1824+ key = ((1, 3, 3, 3), ('',))
1825+ call = lambda amp: \
1826+ "CALL VVVSXX(W(1,%d),W(1,%d),W(1,%d),W(1,%d),DUM1,%s,AMP(%d))" % \
1827+ (amp.get('mothers')[0].get('number'),
1828+ amp.get('mothers')[1].get('number'),
1829+ amp.get('mothers')[2].get('number'),
1830+ amp.get('mothers')[3].get('number'),
1831+ amp.get('coupling')[0],
1832 amp.get('number'))
1833 self.add_amplitude(key, call)
1834
1835 # Spin2 Helas Routine
1836- key = ((-2, 2, 5), '')
1837+ key = ((-2, 2, 5), ('',))
1838 call = lambda amp: \
1839 "CALL IOTXXX(W(1,%d),W(1,%d),W(1,%d),%s,%s,AMP(%d))" % \
1840 (amp.get('mothers')[0].get('number'),
1841 amp.get('mothers')[1].get('number'),
1842 amp.get('mothers')[2].get('number'),
1843- amp.get('coupling'),
1844+ amp.get('coupling')[0],
1845 amp.get('mothers')[0].get('mass'),
1846 amp.get('number'))
1847 self.add_amplitude(key, call)
1848
1849- key = ((-2, 2, 5, 3), '')
1850+ key = ((-2, 2, 5, 3), ('',))
1851 call = lambda wf: \
1852 "CALL UIOXXX(W(1,%d),W(1,%d),%s,%s,%s,%s,W(1,%d))" % \
1853 (wf.get('mothers')[0].get('number'),
1854 wf.get('mothers')[1].get('number'),
1855- wf.get('coupling'),
1856+ wf.get('coupling')[0],
1857 wf.get('mothers')[0].get('mass'),
1858 wf.get('mass'),
1859 wf.get('width'),
1860 wf.get('number'))
1861 self.add_wavefunction(key, call)
1862
1863- key = ((3,3,3,5),'')
1864+ key = ((3,3,3,5),('',))
1865 call = lambda amp: \
1866 "CALL VVVTXX(W(1,%d),W(1,%d),W(1,%d),W(1,%d),1d0,%s,AMP(%d))" % \
1867 (amp.get('mothers')[0].get('number'),
1868 amp.get('mothers')[1].get('number'),
1869 amp.get('mothers')[2].get('number'),
1870 amp.get('mothers')[3].get('number'),
1871- amp.get('coupling'),
1872+ amp.get('coupling')[0],
1873 amp.get('number'))
1874 self.add_amplitude(key, call)
1875
1876- key = ((3,3,5),'')
1877+ key = ((3,3,5),('',))
1878 call = lambda amp: \
1879 "CALL VVTXXX(W(1,%d),W(1,%d),W(1,%d),%s,%s,AMP(%d))" % \
1880 (amp.get('mothers')[0].get('number'),
1881 amp.get('mothers')[1].get('number'),
1882 amp.get('mothers')[2].get('number'),
1883- amp.get('coupling'),
1884+ amp.get('coupling')[0],
1885 amp.get('mothers')[0].get('mass'),
1886 amp.get('number'))
1887 self.add_amplitude(key, call)
1888@@ -569,19 +570,18 @@
1889
1890 # If Lorentz structure is given, by default add this
1891 # to call name
1892- addition = argument.get('lorentz')
1893+ lor_name = argument.get('lorentz')[0]
1894
1895 # Take care of special case: WWWW or WWVV calls
1896- if len(argument.get('lorentz')) > 3 and \
1897- argument.get('lorentz')[:2] == "WW":
1898- if argument.get('lorentz')[:4] == "WWWW":
1899+ if len(lor_name) > 3 and lor_name[:2] == "WW":
1900+ if lor_name[:4] == "WWWW":
1901 mother_letters = "WWWW"[:len(mother_letters)]
1902- if argument.get('lorentz')[:4] == "WWVV":
1903+ if lor_name[:4] == "WWVV":
1904 mother_letters = "W3W3"[:len(mother_letters)]
1905- addition = argument.get('lorentz')[4:]
1906+ lor_name = lor_name[4:]
1907
1908 call = call + mother_letters
1909- call = call + addition
1910+ call = call + lor_name
1911
1912 # Check if we need to append a charge conjugation flag
1913 if argument.needs_hermitian_conjugate():
1914@@ -641,7 +641,7 @@
1915 get('number'),
1916 FortranHelasCallWriter.sorted_mothers(wf)[1].\
1917 get('number'),
1918- wf.get_with_flow('coupling'),
1919+ ','.join(wf.get_with_flow('coupling')),
1920 wf.get('mass'),
1921 wf.get('width'),
1922 wf.get('number'))
1923@@ -653,7 +653,7 @@
1924 get('number'),
1925 FortranHelasCallWriter.sorted_mothers(wf)[2].\
1926 get('number'),
1927- wf.get_with_flow('coupling'),
1928+ ','.join(wf.get_with_flow('coupling')),
1929 wf.get('mass'),
1930 wf.get('width'),
1931 wf.get('number'))
1932@@ -668,7 +668,7 @@
1933 FortranHelasCallWriter.sorted_mothers(amp)[2].\
1934 get('number'),
1935
1936- amp.get('coupling'),
1937+ ','.join(amp.get('coupling')),
1938 amp.get('number'))
1939 else:
1940 call_function = lambda amp: call % \
1941@@ -680,7 +680,7 @@
1942 get('number'),
1943 FortranHelasCallWriter.sorted_mothers(amp)[3].\
1944 get('number'),
1945- amp.get('coupling'),
1946+ ','.join(amp.get('coupling')),
1947 amp.get('number'))
1948
1949 # Add the constructed function to wavefunction or amplitude dictionary
1950@@ -926,12 +926,14 @@
1951 outgoing = 0
1952
1953 # Check if we need to append a charge conjugation flag
1954+ l = [str(l) for l in argument.get('lorentz')]
1955 c_flag = ''
1956 if argument.needs_hermitian_conjugate():
1957 c_flag = "".join(['C%d' % i for i in \
1958 argument.get_conjugate_index()])
1959-
1960- call = 'CALL %s%s_%s' % (argument.get('lorentz'), c_flag, outgoing)
1961+ routine_name = aloha_writers.combine_name(
1962+ '%s%s' % (l[0], c_flag), l[1:], outgoing)
1963+ call = 'CALL %s' % (routine_name)
1964
1965 # Add the wave function
1966 call = call + '('
1967@@ -946,7 +948,7 @@
1968 #CALL L_4_011(W(1,%d),W(1,%d),%s,%s, %s, W(1,%d))
1969 call_function = lambda wf: call % \
1970 (tuple([mother.get('number') for mother in wf.get('mothers')]) + \
1971- (wf.get_with_flow('coupling'),
1972+ (','.join(wf.get_with_flow('coupling')),
1973 wf.get('mass'),
1974 wf.get('width'),
1975 wf.get('number')))
1976@@ -956,7 +958,7 @@
1977 call_function = lambda amp: call % \
1978 (tuple([mother.get('number')
1979 for mother in amp.get('mothers')]) + \
1980- (amp.get('coupling'),
1981+ (','.join(amp.get('coupling')),
1982 amp.get('number')))
1983
1984 # Add the constructed function to wavefunction or amplitude dictionary
1985@@ -1061,12 +1063,14 @@
1986 outgoing = 0
1987
1988 # Check if we need to append a charge conjugation flag
1989+ l = [str(l) for l in argument.get('lorentz')]
1990 c_flag = ''
1991 if argument.needs_hermitian_conjugate():
1992 c_flag = "".join(['C%d' % i for i in \
1993 argument.get_conjugate_index()])
1994-
1995- call = '%s%s_%s' % (argument.get('lorentz'), c_flag, outgoing)
1996+ routine_name = aloha_writers.combine_name(
1997+ '%s%s' % (l[0], c_flag), l[1:], outgoing)
1998+ call = '%s' % (routine_name)
1999
2000 # Add the wave function
2001 call = call + '('
2002@@ -1081,8 +1085,8 @@
2003 #CALL L_4_011(W(1,%d),W(1,%d),%s,%s, %s, W(1,%d))
2004 call_function = lambda wf: call % \
2005 (tuple([mother.get('number')-1 for mother in wf.get('mothers')]) + \
2006- (CPPUFOHelasCallWriter.format_coupling(\
2007- wf.get_with_flow('coupling')),
2008+ (','.join(CPPUFOHelasCallWriter.format_coupling(\
2009+ wf.get_with_flow('coupling'))),
2010 wf.get('mass'),
2011 wf.get('width'),
2012 wf.get('number')-1))
2013@@ -1092,8 +1096,8 @@
2014 call_function = lambda amp: call % \
2015 (tuple([mother.get('number')-1
2016 for mother in amp.get('mothers')]) + \
2017- (CPPUFOHelasCallWriter.format_coupling(\
2018- amp.get('coupling')),
2019+ (','.join(CPPUFOHelasCallWriter.format_coupling(\
2020+ amp.get('coupling'))),
2021 amp.get('number')-1))
2022
2023 # Add the constructed function to wavefunction or amplitude dictionary
2024@@ -1103,13 +1107,18 @@
2025 self.add_amplitude(argument.get_call_key(), call_function)
2026
2027 @staticmethod
2028- def format_coupling(coupling):
2029+ def format_coupling(couplings):
2030 """Format the coupling so any minus signs are put in front"""
2031
2032- if coupling.startswith('-'):
2033- return "-pars->" + coupling[1:]
2034- else:
2035- return "pars->" + coupling
2036+ output = []
2037+ for coupling in couplings:
2038+ if coupling.startswith('-'):
2039+ output.append("-pars->" + coupling[1:])
2040+ else:
2041+ output.append("pars->" + coupling)
2042+
2043+ return output
2044+
2045
2046 #===============================================================================
2047 # PythonUFOHelasCallWriter
2048@@ -1229,16 +1238,20 @@
2049 outgoing = 0
2050
2051 # Check if we need to append a charge conjugation flag
2052+ l = [str(l) for l in argument.get('lorentz')]
2053 c_flag = ''
2054 if argument.needs_hermitian_conjugate():
2055 c_flag = "".join(['C%d' % i for i in \
2056 argument.get_conjugate_index()])
2057+ routine_name = aloha_writers.combine_name(
2058+ '%s%s' % (l[0], c_flag), l[1:], outgoing)
2059+
2060
2061 if isinstance(argument, helas_objects.HelasWavefunction):
2062 call = 'w[%d] = '
2063 else:
2064 call = 'amp[%d] = '
2065- call += '%s%s_%s' % (argument.get('lorentz'), c_flag, outgoing)
2066+ call += '%s' % routine_name
2067
2068 # Add the wave function
2069 call = call + '('
2070@@ -1255,7 +1268,7 @@
2071 ((wf.get('number')-1,) + \
2072 tuple([mother.get('number')-1 for mother in \
2073 wf.get('mothers')]) + \
2074- (wf.get_with_flow('coupling'),
2075+ (','.join(wf.get_with_flow('coupling')),
2076 wf.get('mass'),
2077 wf.get('width')))
2078 else:
2079@@ -1265,7 +1278,7 @@
2080 ((amp.get('number')-1,) + \
2081 tuple([mother.get('number')-1
2082 for mother in amp.get('mothers')]) + \
2083- (amp.get('coupling'),))
2084+ (','.join(amp.get('coupling')),))
2085
2086 # Add the constructed function to wavefunction or amplitude dictionary
2087 if isinstance(argument, helas_objects.HelasWavefunction):
2088
2089=== modified file 'madgraph/iolibs/template_files/matrix_madevent_v4.inc'
2090--- madgraph/iolibs/template_files/matrix_madevent_v4.inc 2011-04-18 02:53:53 +0000
2091+++ madgraph/iolibs/template_files/matrix_madevent_v4.inc 2011-04-20 16:57:29 +0000
2092@@ -214,6 +214,8 @@
2093 REAL*8 DENOM(NCOLOR), CF(NCOLOR,NCOLOR)
2094 COMPLEX*16 AMP(NGRAPHS), JAMP(NCOLOR)
2095 COMPLEX*16 W(18,NWAVEFUNCS)
2096+ COMPLEX*16 DUM0,DUM1
2097+ DATA DUM0, DUM1/(0d0, 0d0), (1d0, 0d0)/
2098 C
2099 C GLOBAL VARIABLES
2100 C
2101
2102=== modified file 'madgraph/iolibs/template_files/matrix_standalone_v4.inc'
2103--- madgraph/iolibs/template_files/matrix_standalone_v4.inc 2011-02-08 16:27:15 +0000
2104+++ madgraph/iolibs/template_files/matrix_standalone_v4.inc 2011-04-20 16:57:29 +0000
2105@@ -92,6 +92,8 @@
2106 REAL*8 DENOM(NCOLOR), CF(NCOLOR,NCOLOR)
2107 COMPLEX*16 AMP(NGRAPHS), JAMP(NCOLOR)
2108 COMPLEX*16 W(18,NWAVEFUNCS)
2109+ COMPLEX*16 DUM0,DUM1
2110+ DATA DUM0, DUM1/(0d0, 0d0), (1d0, 0d0)/
2111 C
2112 C GLOBAL VARIABLES
2113 C
2114
2115=== modified file 'tests/acceptance_tests/test_cmd.py'
2116--- tests/acceptance_tests/test_cmd.py 2011-04-18 19:06:57 +0000
2117+++ tests/acceptance_tests/test_cmd.py 2011-04-20 16:57:29 +0000
2118@@ -913,7 +913,7 @@
2119 self.do('import model sm')
2120 self.do('define p g u d u~ d~')
2121 self.do('define j g u d u~ d~')
2122- self.do('generate p p > w+ j')
2123+ self.do('generate p p > w+ j @2')
2124 self.do('output pythia8 %s' % self.out_dir)
2125 # Check that the needed files are generated
2126 files = ['Processes_sm/Sigma_sm_gq_wpq.h', 'Processes_sm/Sigma_sm_gq_wpq.cc',
2127@@ -933,7 +933,7 @@
2128 shutil.rmdir(self.out_dir)
2129
2130 self.do('import model sm')
2131- self.do('generate e+ e- > e+ e-')
2132+ self.do('generate e+ e- > e+ e- @2')
2133 self.do('output standalone_cpp %s' % self.out_dir)
2134
2135 # Check that all needed src files are generated
2136@@ -955,21 +955,21 @@
2137 subprocess.call(['make', 'check'],
2138 stdout=devnull, stderr=devnull,
2139 cwd=os.path.join(self.out_dir, 'SubProcesses',
2140- 'P0_Sigma_sm_epem_epem'))
2141+ 'P2_Sigma_sm_epem_epem'))
2142
2143 self.assertTrue(os.path.exists(os.path.join(self.out_dir,
2144 'SubProcesses',
2145- 'P0_Sigma_sm_epem_epem',
2146+ 'P2_Sigma_sm_epem_epem',
2147 'check')))
2148
2149 # Check that the output of check is correct
2150 logfile = os.path.join(self.out_dir, 'SubProcesses',
2151- 'P0_Sigma_sm_epem_epem', 'check.log')
2152+ 'P2_Sigma_sm_epem_epem', 'check.log')
2153
2154 subprocess.call('./check',
2155 stdout=open(logfile, 'w'), stderr=devnull,
2156 cwd=os.path.join(self.out_dir, 'SubProcesses',
2157- 'P0_Sigma_sm_epem_epem'), shell=True)
2158+ 'P2_Sigma_sm_epem_epem'), shell=True)
2159
2160 log_output = open(logfile, 'r').read()
2161 me_re = re.compile('Matrix element\s*=\s*(?P<value>[\d\.e\+-]+)\s*GeV',
2162
2163=== modified file 'tests/parallel_tests/me_comparator.py'
2164--- tests/parallel_tests/me_comparator.py 2011-04-10 15:43:51 +0000
2165+++ tests/parallel_tests/me_comparator.py 2011-04-20 16:57:29 +0000
2166@@ -339,7 +339,7 @@
2167 the specified model, the specified maximal coupling orders and a certain
2168 energy for incoming particles (for decay, incoming particle is at rest).
2169 """
2170-
2171+ self.res_list = [] # ensure that to be void, and avoid pointer problem
2172 self.proc_list = proc_list
2173 self.model = model
2174 self.orders = orders
2175@@ -373,7 +373,8 @@
2176
2177 # Get the ME value
2178 for i, proc in enumerate(proc_list):
2179- self.res_list.append(self.get_me_value(proc, i))
2180+ value = self.get_me_value(proc, i)
2181+ self.res_list.append(value)
2182
2183 return self.res_list
2184
2185
2186=== modified file 'tests/parallel_tests/sample_script.py'
2187--- tests/parallel_tests/sample_script.py 2011-04-12 16:11:45 +0000
2188+++ tests/parallel_tests/sample_script.py 2011-04-20 16:57:29 +0000
2189@@ -46,6 +46,7 @@
2190 logging.getLogger('tutorial').setLevel(logging.ERROR)
2191
2192 logging.basicConfig(level=logging.INFO)
2193+<<<<<<< TREE
2194 #my_proc_list = ['u u~ > g y $ g', 'u~ u > g y $ g ', 'y > u u~','Z > u u~']
2195 #my_proc_list = ['t t > t t', 't t~ > t t~', 't t~ > z z', 't z > t z', 't~ t~ > t~ t~', 't~ z > t~ z', 'g g > y y', 'g y > g y', 'y y > g g', 'y y > z z', 'y y > a a', 'y z > t t~', 'y z > y z', 'a y > a y',' z z > t t~', 'z z > y y', 'a a > y y']
2196 #my_proc_list = ['t t~ > t t~','e+ e- > e+ e-','w+ w- > w+ w-', 't t~ > t t~ / a z h g', 'y > t t~', 'y > t t~ g', 't t~ > t t~ / z h g','t t~ > t t~ / a h g','t t~ > t t~ / z a g', 't t~ > t t~ / h ', 't t~ > t t~ / z','t t~ > z > t t~', 'y t > t z', 't t~ > z > t t~']
2197@@ -74,6 +75,17 @@
2198 #print len(my_proc_list)
2199 #print my_proc_list
2200 #
2201+=======
2202+
2203+ my_proc_list=['z z > z z','w+ w- > w+ w-','g g > g g', 'u u~ > g g g', 'u u~ > e+ e- z', 't t~ > g g'
2204+ 'e+ e- > e+ e- e+ e-', ' g g > t t~ g', 't t~ > h > t t~']
2205+ #my_proc_list1 = me_comparator.create_proc_list(['u', 'u~','t','t~','g','y','z','a'], initial=1,
2206+ # final=2)
2207+ #my_proc_list = me_comparator.create_proc_list_enhanced(
2208+ # fermion, fermion, boson,
2209+ # initial=2, final_1=2, final_2 = 1)
2210+
2211+>>>>>>> MERGE-SOURCE
2212 #my_proc_list += me_comparator.create_proc_list(['w+','w-','z','a','x1+','x1-','n1'], initial=2,
2213 # final=3)
2214 #my_proc_list += me_comparator.create_proc_list(['g','u','u~','go','ul','ul~','ur','ur~'], initial=2,
2215@@ -102,12 +114,17 @@
2216
2217 # Create and setup a comparator
2218 my_comp = me_comparator.MEComparator()
2219- my_comp.set_me_runners(my_mg5_ufo, my_mg4)
2220+ my_comp.set_me_runners(my_mg5, my_mg5_ufo, my_mg5_cpp, my_mg4)
2221
2222 # Run the actual comparison
2223 my_comp.run_comparison(my_proc_list,
2224+<<<<<<< TREE
2225 model=['RS','RS'],
2226 orders={'QED':4, 'QCD':4, 'QTD':4}, energy=2000)
2227+=======
2228+ model='sm',
2229+ orders={'QED':99, 'QCD':99, 'QTD':4}, energy=2000)
2230+>>>>>>> MERGE-SOURCE
2231
2232 # Do some cleanup
2233 #my_comp.cleanup()
2234
2235=== modified file 'tests/unit_tests/core/test_helas_objects.py'
2236--- tests/unit_tests/core/test_helas_objects.py 2010-12-19 03:57:07 +0000
2237+++ tests/unit_tests/core/test_helas_objects.py 2011-04-20 16:57:29 +0000
2238@@ -408,8 +408,8 @@
2239 g,
2240 g]),
2241 'color': [color.ColorString([color.f(0, 1, 2)]),
2242- color.ColorString([color.f(0, 1, 2)]),
2243- color.ColorString([color.f(0, 1, 2)])],
2244+ color.ColorString([color.f(1, 2, 0)]),
2245+ color.ColorString([color.f(2, 0, 1)])],
2246 'lorentz':['gggg1', 'gggg2', 'gggg3'],
2247 'couplings':{(0, 0):'GG',(1, 1):'GG',(2, 2):'GG'},
2248 'orders':{'QCD':2}}))
2249@@ -1137,8 +1137,10 @@
2250 matrix_element = helas_objects.HelasMatrixElement(\
2251 myamplitude,
2252 0)
2253-
2254- self.assertEqual(matrix_element.get('diagrams'), diagrams)
2255+
2256+ self.assertEqual(matrix_element.get('diagrams')[0]['amplitudes'], amplitude1,
2257+ '%s != %s' %(matrix_element.get('diagrams')[0]['amplitudes'], amplitude1))
2258+ #self.assertEqual(matrix_element.get('diagrams'), diagrams)
2259
2260 def test_generate_helas_diagrams_ae_ae(self):
2261 """Testing the helas diagram generation a e- > a e-
2262@@ -1888,9 +1890,9 @@
2263
2264 helas_writer = helas_call_writers.FortranUFOHelasCallWriter(mymodel)
2265
2266- self.assertEqual(len(me.get_all_amplitudes()), 8)
2267+ self.assertEqual(len(me.get_all_amplitudes()), 2)
2268
2269- self.assertEqual(len(me.get_all_wavefunctions()), 8)
2270+ self.assertEqual(len(me.get_all_wavefunctions()), 6)
2271
2272 for i, amp in enumerate(me.get_all_amplitudes()):
2273 self.assertEqual(amp.get('number'), i + 1)
2274
2275=== modified file 'tests/unit_tests/iolibs/test_export_cpp.py'
2276--- tests/unit_tests/iolibs/test_export_cpp.py 2011-04-15 19:21:44 +0000
2277+++ tests/unit_tests/iolibs/test_export_cpp.py 2011-04-20 16:57:29 +0000
2278@@ -665,15 +665,30 @@
2279 oxxxxx(p[perm[2]], mME[2], hel[2], +1, w[2]);
2280 ixxxxx(p[perm[3]], mME[3], hel[3], -1, w[3]);
2281 FFV1_3(w[0], w[1], pars->GC_10, pars->ZERO, pars->ZERO, w[4]);
2282- FFV2_3(w[0], w[1], pars->GC_35, pars->MZ, pars->WZ, w[5]);
2283- FFV5_3(w[0], w[1], pars->GC_47, pars->MZ, pars->WZ, w[6]);
2284- FFV1_3(w[0], w[2], pars->GC_10, pars->ZERO, pars->ZERO, w[7]);
2285- FFV2_3(w[0], w[2], pars->GC_35, pars->MZ, pars->WZ, w[8]);
2286- FFV5_3(w[0], w[2], pars->GC_47, pars->MZ, pars->WZ, w[9]);
2287-
2288+ FFV2_5_3(w[0], w[1], pars->GC_35, pars->GC_47, pars->MZ, pars->WZ, w[5]);
2289+ FFV1_3(w[0], w[2], pars->GC_10, pars->ZERO, pars->ZERO, w[6]);
2290+ FFV2_5_3(w[0], w[2], pars->GC_35, pars->GC_47, pars->MZ, pars->WZ, w[7]);
2291+
2292+<<<<<<< TREE
2293+=======
2294+
2295+}
2296+double Sigma_sm_qqx_qqx::matrix_uux_uux()
2297+{
2298+ int i, j;
2299+ // Local variables
2300+ const int ngraphs = 4;
2301+ const int ncolor = 2;
2302+ std::complex<double> ztemp;
2303+ std::complex<double> amp[ngraphs], jamp[ncolor];
2304+ // The color matrix;
2305+ static const double denom[ncolor] = {1, 1};
2306+ static const double cf[ncolor][ncolor] = {{9, 3}, {3, 9}};
2307+>>>>>>> MERGE-SOURCE
2308 // Calculate all amplitudes
2309 // Amplitude(s) for diagram number 0
2310 FFV1_0(w[3], w[2], w[4], pars->GC_10, amp[0]);
2311+<<<<<<< TREE
2312 FFV2_0(w[3], w[2], w[5], pars->GC_35, amp[1]);
2313 FFV5_0(w[3], w[2], w[5], pars->GC_47, amp[2]);
2314 FFV2_0(w[3], w[2], w[6], pars->GC_35, amp[3]);
2315@@ -683,6 +698,14 @@
2316 FFV5_0(w[3], w[1], w[8], pars->GC_47, amp[7]);
2317 FFV2_0(w[3], w[1], w[9], pars->GC_35, amp[8]);
2318 FFV5_0(w[3], w[1], w[9], pars->GC_47, amp[9]);
2319+=======
2320+ // Amplitude(s) for diagram number 2
2321+ FFV2_5_0(w[3], w[2], w[5], pars->GC_35, pars->GC_47, amp[1]);
2322+ // Amplitude(s) for diagram number 3
2323+ FFV1_0(w[3], w[1], w[6], pars->GC_10, amp[2]);
2324+ // Amplitude(s) for diagram number 4
2325+ FFV2_5_0(w[3], w[1], w[7], pars->GC_35, pars->GC_47, amp[3]);
2326+>>>>>>> MERGE-SOURCE
2327
2328
2329 }
2330@@ -699,10 +722,8 @@
2331 static const double cf[ncolor][ncolor] = {{9, 3}, {3, 9}};
2332
2333 // Calculate color flows
2334- jamp[0] = +1./6. * amp[0] - amp[1] - amp[2] - amp[3] - amp[4] + 1./2. *
2335- amp[5];
2336- jamp[1] = -1./2. * amp[0] - 1./6. * amp[5] + amp[6] + amp[7] + amp[8] +
2337- amp[9];
2338+ jamp[0] = +1./6. * amp[0] - amp[1] + 1./2. * amp[2];
2339+ jamp[1] = -1./2. * amp[0] - 1./6. * amp[2] + amp[3];
2340
2341 // Sum and square the color flows to get the matrix element
2342 double matrix = 0;
2343@@ -1321,6 +1342,107 @@
2344 print "cd /tmp; g++ -c -I $PATH_TO_PYTHIA8/include Sigma_sm_qqx_qqx.cc.cc"
2345
2346
2347+<<<<<<< TREE
2348+=======
2349+ def test_write_process_h_file(self):
2350+ """Test writing the .h Pythia file for a matrix element"""
2351+
2352+ goal_string = \
2353+"""//==========================================================================
2354+// This file has been automatically generated for Pythia 8
2355+// MadGraph 5 v. %(version)s, %(date)s
2356+// By the MadGraph Development Team
2357+// Please visit us at https://launchpad.net/madgraph5
2358+//==========================================================================
2359+
2360+#ifndef Pythia8_Sigma_sm_qqx_qqx_H
2361+#define Pythia8_Sigma_sm_qqx_qqx_H
2362+
2363+#include <complex>
2364+
2365+#include "SigmaProcess.h"
2366+#include "Parameters_sm.h"
2367+
2368+using namespace std;
2369+
2370+namespace Pythia8
2371+{
2372+//==========================================================================
2373+// A class for calculating the matrix elements for
2374+// Process: u u~ > u u~
2375+// Process: c c~ > c c~
2376+//--------------------------------------------------------------------------
2377+
2378+class Sigma_sm_qqx_qqx : public Sigma2Process
2379+{
2380+ public:
2381+
2382+ // Constructor.
2383+ Sigma_sm_qqx_qqx() {}
2384+
2385+ // Initialize process.
2386+ virtual void initProc();
2387+
2388+ // Calculate flavour-independent parts of cross section.
2389+ virtual void sigmaKin();
2390+
2391+ // Evaluate sigmaHat(sHat).
2392+ virtual double sigmaHat();
2393+
2394+ // Select flavour, colour and anticolour.
2395+ virtual void setIdColAcol();
2396+
2397+ // Evaluate weight for decay angles.
2398+ virtual double weightDecay(Event& process, int iResBeg, int iResEnd);
2399+
2400+ // Info on the subprocess.
2401+ virtual string name() const {return "q q~ > q q~ (sm)";}
2402+
2403+ virtual int code() const {return 10000;}
2404+
2405+ virtual string inFlux() const {return "qqbarSame";}
2406+
2407+ virtual int resonanceA() const {return 23;}
2408+ // Tell Pythia that sigmaHat returns the ME^2
2409+ virtual bool convertM2() const {return true;}
2410+
2411+ private:
2412+
2413+ // Private functions to calculate the matrix element for all subprocesses
2414+ // Calculate wavefunctions
2415+ void calculate_wavefunctions(const int perm[], const int hel[]);
2416+ static const int nwavefuncs = 8;
2417+ std::complex<double> w[nwavefuncs][18];
2418+ double matrix_uux_uux();
2419+
2420+ // Constants for array limits
2421+ static const int nexternal = 4;
2422+ static const int nprocesses = 1;
2423+
2424+ // Store the matrix element value from sigmaKin
2425+ double matrix_element[nprocesses];
2426+
2427+ // Color flows, used when selecting color
2428+ double * jamp2[nprocesses];
2429+
2430+ // Pointer to the model parameters
2431+ Parameters_sm * pars;
2432+
2433+};
2434+
2435+} // end namespace Pythia
2436+
2437+#endif // Pythia8_Sigma_sm_qqx_qqx_H
2438+""" % misc.get_pkg_info()
2439+
2440+ self.pythia8_exporter.write_process_h_file(\
2441+ writers.CPPWriter(self.give_pos('test.h')))
2442+
2443+ #print open(self.give_pos('test.h')).read()
2444+
2445+ self.assertFileContains('test.h', goal_string)
2446+
2447+>>>>>>> MERGE-SOURCE
2448 #===============================================================================
2449 # ExportUFOModelPythia8Test
2450 #===============================================================================
2451
2452=== modified file 'tests/unit_tests/iolibs/test_export_python.py'
2453--- tests/unit_tests/iolibs/test_export_python.py 2011-03-24 15:44:58 +0000
2454+++ tests/unit_tests/iolibs/test_export_python.py 2011-04-20 16:57:29 +0000
2455@@ -299,9 +299,9 @@
2456 #
2457 # Process parameters
2458 #
2459- ngraphs = 10
2460+ ngraphs = 4
2461 nexternal = 4
2462- nwavefuncs = 10
2463+ nwavefuncs = 8
2464 ncolor = 2
2465 ZERO = 0.
2466 #
2467@@ -330,32 +330,24 @@
2468 w[4] = FFV1_3(w[0],w[1],GC_10,ZERO, ZERO)
2469 # Amplitude(s) for diagram number 1
2470 amp[0] = FFV1_0(w[3],w[2],w[4],GC_10)
2471- w[5] = FFV2_3(w[0],w[1],GC_35,MZ, WZ)
2472- w[6] = FFV5_3(w[0],w[1],GC_47,MZ, WZ)
2473+ w[5] = FFV2_5_3(w[0],w[1],GC_35,GC_47,MZ, WZ)
2474 # Amplitude(s) for diagram number 2
2475- amp[1] = FFV2_0(w[3],w[2],w[5],GC_35)
2476- amp[2] = FFV5_0(w[3],w[2],w[5],GC_47)
2477- amp[3] = FFV2_0(w[3],w[2],w[6],GC_35)
2478- amp[4] = FFV5_0(w[3],w[2],w[6],GC_47)
2479- w[7] = FFV1_3(w[0],w[2],GC_10,ZERO, ZERO)
2480+ amp[1] = FFV2_5_0(w[3],w[2],w[5],GC_35,GC_47)
2481+ w[6] = FFV1_3(w[0],w[2],GC_10,ZERO, ZERO)
2482 # Amplitude(s) for diagram number 3
2483- amp[5] = FFV1_0(w[3],w[1],w[7],GC_10)
2484- w[8] = FFV2_3(w[0],w[2],GC_35,MZ, WZ)
2485- w[9] = FFV5_3(w[0],w[2],GC_47,MZ, WZ)
2486+ amp[2] = FFV1_0(w[3],w[1],w[6],GC_10)
2487+ w[7] = FFV2_5_3(w[0],w[2],GC_35,GC_47,MZ, WZ)
2488 # Amplitude(s) for diagram number 4
2489- amp[6] = FFV2_0(w[3],w[1],w[8],GC_35)
2490- amp[7] = FFV5_0(w[3],w[1],w[8],GC_47)
2491- amp[8] = FFV2_0(w[3],w[1],w[9],GC_35)
2492- amp[9] = FFV5_0(w[3],w[1],w[9],GC_47)
2493+ amp[3] = FFV2_5_0(w[3],w[1],w[7],GC_35,GC_47)
2494
2495 jamp = [None] * ncolor
2496- jamp[0] = +1./6.*amp[0]-amp[1]-amp[2]-amp[3]-amp[4]+1./2.*amp[5]
2497- jamp[1] = -1./2.*amp[0]-1./6.*amp[5]+amp[6]+amp[7]+amp[8]+amp[9]
2498+ jamp[0] = +1./6.*amp[0]-amp[1]+1./2.*amp[2]
2499+ jamp[1] = -1./2.*amp[0]-1./6.*amp[2]+amp[3]
2500
2501 self.amp2[0]+=abs(amp[0]*amp[0].conjugate())
2502- self.amp2[1]+=abs(amp[1]*amp[1].conjugate())+abs(amp[2]*amp[2].conjugate())+abs(amp[3]*amp[3].conjugate())+abs(amp[4]*amp[4].conjugate())
2503- self.amp2[2]+=abs(amp[5]*amp[5].conjugate())
2504- self.amp2[3]+=abs(amp[6]*amp[6].conjugate())+abs(amp[7]*amp[7].conjugate())+abs(amp[8]*amp[8].conjugate())+abs(amp[9]*amp[9].conjugate())
2505+ self.amp2[1]+=abs(amp[1]*amp[1].conjugate())
2506+ self.amp2[2]+=abs(amp[2]*amp[2].conjugate())
2507+ self.amp2[3]+=abs(amp[3]*amp[3].conjugate())
2508
2509 matrix = 0.
2510 for i in range(ncolor):
2511@@ -373,9 +365,8 @@
2512 matrix_methods = exporter.get_python_matrix_methods()["0_uux_uux"].\
2513 split('\n')
2514
2515- for iline in range(len(goal_method)):
2516- self.assertEqual(matrix_methods[iline],
2517- goal_method[iline])
2518+
2519+ self.assertEqual(matrix_methods, goal_method)
2520
2521
2522 def test_run_python_matrix_element(self):
2523
2524=== modified file 'tests/unit_tests/iolibs/test_export_v4.py'
2525--- tests/unit_tests/iolibs/test_export_v4.py 2011-04-18 02:53:53 +0000
2526+++ tests/unit_tests/iolibs/test_export_v4.py 2011-04-20 16:57:29 +0000
2527@@ -276,6 +276,8 @@
2528 REAL*8 DENOM(NCOLOR), CF(NCOLOR,NCOLOR)
2529 COMPLEX*16 AMP(NGRAPHS), JAMP(NCOLOR)
2530 COMPLEX*16 W(18,NWAVEFUNCS)
2531+ COMPLEX*16 DUM0,DUM1
2532+ DATA DUM0, DUM1/(0D0, 0D0), (1D0, 0D0)/
2533 C
2534 C GLOBAL VARIABLES
2535 C
2536@@ -599,13 +601,21 @@
2537 amp2_lines = \
2538 exporter.get_amp2_lines(matrix_elements[0],
2539 subprocess_group.get('diagram_maps')[0])
2540+
2541 self.assertEqual(amp2_lines,
2542+<<<<<<< TREE
2543 ['AMP2(1)=AMP2(1)+AMP(1)*dconjg(AMP(1))',
2544 'AMP2(2)=AMP2(2)+AMP(2)*dconjg(AMP(2))',
2545 'AMP2(3)=AMP2(3)+AMP(3)*dconjg(AMP(3))+AMP(4)*dconjg(AMP(4))+AMP(5)*dconjg(AMP(5))+AMP(6)*dconjg(AMP(6))',
2546 'AMP2(4)=AMP2(4)+AMP(7)*dconjg(AMP(7))',
2547 'AMP2(5)=AMP2(5)+AMP(8)*dconjg(AMP(8))',
2548 'AMP2(6)=AMP2(6)+AMP(9)*dconjg(AMP(9))+AMP(10)*dconjg(AMP(10))+AMP(11)*dconjg(AMP(11))+AMP(12)*dconjg(AMP(12))'])
2549+=======
2550+ ['AMP2(1)=AMP2(1)+AMP(1)*dconjg(AMP(1))+AMP(2)*dconjg(AMP(2))',
2551+ 'AMP2(3)=AMP2(3)+AMP(3)*dconjg(AMP(3))',
2552+ 'AMP2(4)=AMP2(4)+AMP(4)*dconjg(AMP(4))+AMP(5)*dconjg(AMP(5))',
2553+ 'AMP2(6)=AMP2(6)+AMP(6)*dconjg(AMP(6))'])
2554+>>>>>>> MERGE-SOURCE
2555
2556 # Test configs.inc
2557
2558@@ -1758,14 +1768,14 @@
2559 #print '\n'.join(amp2_lines)
2560
2561 self.assertEqual('\n'.join(amp2_lines),
2562-"""AMP2(5)=AMP2(5)+AMP(9)*dconjg(AMP(9))
2563-AMP2(6)=AMP2(6)+AMP(10)*dconjg(AMP(10))
2564-AMP2(7)=AMP2(7)+AMP(11)*dconjg(AMP(11))
2565-AMP2(8)=AMP2(8)+AMP(12)*dconjg(AMP(12))
2566-AMP2(9)=AMP2(9)+AMP(13)*dconjg(AMP(13))
2567-AMP2(10)=AMP2(10)+AMP(14)*dconjg(AMP(14))
2568-AMP2(11)=AMP2(11)+AMP(15)*dconjg(AMP(15))
2569-AMP2(12)=AMP2(12)+AMP(16)*dconjg(AMP(16))""")
2570+"""AMP2(5)=AMP2(5)+AMP(5)*dconjg(AMP(5))
2571+AMP2(6)=AMP2(6)+AMP(6)*dconjg(AMP(6))
2572+AMP2(7)=AMP2(7)+AMP(7)*dconjg(AMP(7))
2573+AMP2(8)=AMP2(8)+AMP(8)*dconjg(AMP(8))
2574+AMP2(9)=AMP2(9)+AMP(9)*dconjg(AMP(9))
2575+AMP2(10)=AMP2(10)+AMP(10)*dconjg(AMP(10))
2576+AMP2(11)=AMP2(11)+AMP(11)*dconjg(AMP(11))
2577+AMP2(12)=AMP2(12)+AMP(12)*dconjg(AMP(12))""")
2578
2579 # Test configs.inc
2580
2581@@ -3913,13 +3923,13 @@
2582
2583 # Test get_used_lorentz
2584 # Wavefunctions
2585- goal_lorentz_list = [('', (), 1), ('', (), 2), ('', (), 3),
2586- ('', (1,), 2),('', (), 3), ('', (1,), 1),
2587- ('', (), 2), ('', (), 3),('', (1,), 1),
2588- ('', (), 1), ('', (), 3),('', (1,), 2),
2589- ('', (), 3), ('', (), 3)]
2590+ goal_lorentz_list = [(('',), (), 1), (('',), (), 2), (('',), (), 3),
2591+ (('',), (1,), 2),(('',), (), 3), (('',), (1,), 1),
2592+ (('',), (), 2), (('',), (), 3),(('',), (1,), 1),
2593+ (('',), (), 1), (('',), (), 3),(('',), (1,), 2),
2594+ (('',), (), 3), (('',), (), 3)]
2595 # Amplitudes
2596- goal_lorentz_list += [('', (), 0)] * 8
2597+ goal_lorentz_list += [(('',), (), 0)] * 8
2598 self.assertEqual(matrix_element.get_used_lorentz(),
2599 goal_lorentz_list)
2600
2601@@ -4741,34 +4751,21 @@
2602
2603 matrix_element = helas_objects.HelasMatrixElement(myamplitude, gen_color=False)
2604
2605- myfortranmodel = helas_call_writers.FortranHelasCallWriter(mybasemodel)
2606- self.assertEqual("\n".join(myfortranmodel.\
2607- get_matrix_element_calls(matrix_element)),
2608+ myfortranmodel = helas_call_writers.FortranUFOHelasCallWriter(mybasemodel)
2609+ self.assertEqual(myfortranmodel.get_matrix_element_calls(matrix_element),
2610 """CALL VXXXXX(P(0,1),zero,NHEL(1),-1*IC(1),W(1,1))
2611 CALL VXXXXX(P(0,2),zero,NHEL(2),-1*IC(2),W(1,2))
2612 CALL VXXXXX(P(0,3),zero,NHEL(3),+1*IC(3),W(1,3))
2613 CALL VXXXXX(P(0,4),zero,NHEL(4),+1*IC(4),W(1,4))
2614-CALL JVVL1X(W(1,1),W(1,2),G1,zero,zero,W(1,5))
2615-CALL JVVL2X(W(1,1),W(1,2),G2,zero,zero,W(1,6))
2616+CALL L1__L2_1(W(1,1),W(1,2),G1,G2,zero, zero, W(1,5))
2617 # Amplitude(s) for diagram number 1
2618-CALL VVVL1X(W(1,3),W(1,4),W(1,5),G1,AMP(1))
2619-CALL VVVL2X(W(1,3),W(1,4),W(1,5),G2,AMP(2))
2620-CALL VVVL1X(W(1,3),W(1,4),W(1,6),G1,AMP(3))
2621-CALL VVVL2X(W(1,3),W(1,4),W(1,6),G2,AMP(4))
2622-CALL JVVL1X(W(1,1),W(1,3),G1,zero,zero,W(1,7))
2623-CALL JVVL2X(W(1,1),W(1,3),G2,zero,zero,W(1,8))
2624+CALL L1__L2_0(W(1,3),W(1,4),W(1,5),G1,G2,AMP(1))
2625+CALL L1__L2_1(W(1,1),W(1,3),G1,G2,zero, zero, W(1,6))
2626 # Amplitude(s) for diagram number 2
2627-CALL VVVL1X(W(1,2),W(1,4),W(1,7),G1,AMP(5))
2628-CALL VVVL2X(W(1,2),W(1,4),W(1,7),G2,AMP(6))
2629-CALL VVVL1X(W(1,2),W(1,4),W(1,8),G1,AMP(7))
2630-CALL VVVL2X(W(1,2),W(1,4),W(1,8),G2,AMP(8))
2631-CALL JVVL1X(W(1,1),W(1,4),G1,zero,zero,W(1,9))
2632-CALL JVVL2X(W(1,1),W(1,4),G2,zero,zero,W(1,10))
2633+CALL L1__L2_0(W(1,2),W(1,4),W(1,6),G1,G2,AMP(2))
2634+CALL L1__L2_1(W(1,1),W(1,4),G1,G2,zero, zero, W(1,7))
2635 # Amplitude(s) for diagram number 3
2636-CALL VVVL1X(W(1,2),W(1,3),W(1,9),G1,AMP(9))
2637-CALL VVVL2X(W(1,2),W(1,3),W(1,9),G2,AMP(10))
2638-CALL VVVL1X(W(1,2),W(1,3),W(1,10),G1,AMP(11))
2639-CALL VVVL2X(W(1,2),W(1,3),W(1,10),G2,AMP(12))""")
2640+CALL L1__L2_0(W(1,2),W(1,3),W(1,7),G1,G2,AMP(3))""".split('\n'))
2641
2642 exporter = export_v4.ProcessExporterFortranME()
2643
2644@@ -4776,9 +4773,9 @@
2645 amp2_lines = \
2646 exporter.get_amp2_lines(matrix_element)
2647 self.assertEqual(amp2_lines,
2648- ['AMP2(1)=AMP2(1)+AMP(1)*dconjg(AMP(1))+AMP(2)*dconjg(AMP(2))+AMP(3)*dconjg(AMP(3))+AMP(4)*dconjg(AMP(4))',
2649- 'AMP2(2)=AMP2(2)+AMP(5)*dconjg(AMP(5))+AMP(6)*dconjg(AMP(6))+AMP(7)*dconjg(AMP(7))+AMP(8)*dconjg(AMP(8))',
2650- 'AMP2(3)=AMP2(3)+AMP(9)*dconjg(AMP(9))+AMP(10)*dconjg(AMP(10))+AMP(11)*dconjg(AMP(11))+AMP(12)*dconjg(AMP(12))'])
2651+ ['AMP2(1)=AMP2(1)+AMP(1)*dconjg(AMP(1))',
2652+ 'AMP2(2)=AMP2(2)+AMP(2)*dconjg(AMP(2))',
2653+ 'AMP2(3)=AMP2(3)+AMP(3)*dconjg(AMP(3))'])
2654
2655 # Test configs file
2656 writer = writers.FortranWriter(self.give_pos('test'))
2657@@ -4963,45 +4960,23 @@
2658 CALL IXXXXX(P(0,4),Mx1p,NHEL(4),-1*IC(4),W(1,4))
2659 CALL OXXXXX(P(0,5),Mx1p,NHEL(5),+1*IC(5),W(1,5))
2660 CALL VVV1_2(W(1,1),W(1,3),GC_214,MW, WW, W(1,6))
2661-CALL FFV2C1_2(W(1,4),W(1,2),GC_422,Mneu1, Wneu1, W(1,7))
2662-CALL FFV3C1_2(W(1,4),W(1,2),GC_628,Mneu1, Wneu1, W(1,8))
2663+CALL FFV2C1_3_2(W(1,4),W(1,2),GC_422,GC_628,Mneu1, Wneu1, W(1,7))
2664 # Amplitude(s) for diagram number 1
2665-CALL FFV2_0(W(1,7),W(1,5),W(1,6),GC_422,AMP(1))
2666-CALL FFV3_0(W(1,7),W(1,5),W(1,6),GC_628,AMP(2))
2667-CALL FFV2_0(W(1,8),W(1,5),W(1,6),GC_422,AMP(3))
2668-CALL FFV3_0(W(1,8),W(1,5),W(1,6),GC_628,AMP(4))
2669-CALL FFV2_1(W(1,5),W(1,2),GC_422,Mneu1, Wneu1, W(1,9))
2670-CALL FFV3_1(W(1,5),W(1,2),GC_628,Mneu1, Wneu1, W(1,10))
2671+CALL FFV2_3_0(W(1,7),W(1,5),W(1,6),GC_422,GC_628,AMP(1))
2672+CALL FFV2_3_1(W(1,5),W(1,2),GC_422,GC_628,Mneu1, Wneu1, W(1,8))
2673 # Amplitude(s) for diagram number 2
2674-CALL FFV2C1_0(W(1,4),W(1,9),W(1,6),GC_422,AMP(5))
2675-CALL FFV3C1_0(W(1,4),W(1,9),W(1,6),GC_628,AMP(6))
2676-CALL FFV2C1_0(W(1,4),W(1,10),W(1,6),GC_422,AMP(7))
2677-CALL FFV3C1_0(W(1,4),W(1,10),W(1,6),GC_628,AMP(8))
2678-CALL FFV2C1_2(W(1,4),W(1,1),GC_422,Mneu1, Wneu1, W(1,11))
2679-CALL FFV3C1_2(W(1,4),W(1,1),GC_628,Mneu1, Wneu1, W(1,12))
2680-CALL VVV1_2(W(1,2),W(1,3),GC_214,MW, WW, W(1,13))
2681+CALL FFV2C1_3_0(W(1,4),W(1,8),W(1,6),GC_422,GC_628,AMP(2))
2682+CALL FFV2C1_3_2(W(1,4),W(1,1),GC_422,GC_628,Mneu1, Wneu1, W(1,9))
2683+CALL VVV1_2(W(1,2),W(1,3),GC_214,MW, WW, W(1,10))
2684 # Amplitude(s) for diagram number 3
2685-CALL FFV2_0(W(1,11),W(1,5),W(1,13),GC_422,AMP(9))
2686-CALL FFV3_0(W(1,11),W(1,5),W(1,13),GC_628,AMP(10))
2687-CALL FFV2_0(W(1,12),W(1,5),W(1,13),GC_422,AMP(11))
2688-CALL FFV3_0(W(1,12),W(1,5),W(1,13),GC_628,AMP(12))
2689+CALL FFV2_3_0(W(1,9),W(1,5),W(1,10),GC_422,GC_628,AMP(3))
2690 # Amplitude(s) for diagram number 4
2691-CALL FFV5_0(W(1,11),W(1,9),W(1,3),GC_418,AMP(13))
2692-CALL FFV5_0(W(1,11),W(1,10),W(1,3),GC_418,AMP(14))
2693-CALL FFV5_0(W(1,12),W(1,9),W(1,3),GC_418,AMP(15))
2694-CALL FFV5_0(W(1,12),W(1,10),W(1,3),GC_418,AMP(16))
2695-CALL FFV2_1(W(1,5),W(1,1),GC_422,Mneu1, Wneu1, W(1,14))
2696-CALL FFV3_1(W(1,5),W(1,1),GC_628,Mneu1, Wneu1, W(1,15))
2697+CALL FFV5_0(W(1,9),W(1,8),W(1,3),GC_418,AMP(4))
2698+CALL FFV2_3_1(W(1,5),W(1,1),GC_422,GC_628,Mneu1, Wneu1, W(1,11))
2699 # Amplitude(s) for diagram number 5
2700-CALL FFV2C1_0(W(1,4),W(1,14),W(1,13),GC_422,AMP(17))
2701-CALL FFV3C1_0(W(1,4),W(1,14),W(1,13),GC_628,AMP(18))
2702-CALL FFV2C1_0(W(1,4),W(1,15),W(1,13),GC_422,AMP(19))
2703-CALL FFV3C1_0(W(1,4),W(1,15),W(1,13),GC_628,AMP(20))
2704+CALL FFV2C1_3_0(W(1,4),W(1,11),W(1,10),GC_422,GC_628,AMP(5))
2705 # Amplitude(s) for diagram number 6
2706-CALL FFV5_0(W(1,7),W(1,14),W(1,3),GC_418,AMP(21))
2707-CALL FFV5_0(W(1,8),W(1,14),W(1,3),GC_418,AMP(22))
2708-CALL FFV5_0(W(1,7),W(1,15),W(1,3),GC_418,AMP(23))
2709-CALL FFV5_0(W(1,8),W(1,15),W(1,3),GC_418,AMP(24))""".split('\n')
2710+CALL FFV5_0(W(1,7),W(1,11),W(1,3),GC_418,AMP(6))""".split('\n')
2711
2712 for i in range(len(goal)):
2713 self.assertEqual(result[i], goal[i])
2714@@ -5012,12 +4987,12 @@
2715 amp2_lines = \
2716 exporter.get_amp2_lines(matrix_element)
2717 self.assertEqual(amp2_lines,
2718- ['AMP2(1)=AMP2(1)+AMP(1)*dconjg(AMP(1))+AMP(2)*dconjg(AMP(2))+AMP(3)*dconjg(AMP(3))+AMP(4)*dconjg(AMP(4))',
2719- 'AMP2(2)=AMP2(2)+AMP(5)*dconjg(AMP(5))+AMP(6)*dconjg(AMP(6))+AMP(7)*dconjg(AMP(7))+AMP(8)*dconjg(AMP(8))',
2720- 'AMP2(3)=AMP2(3)+AMP(9)*dconjg(AMP(9))+AMP(10)*dconjg(AMP(10))+AMP(11)*dconjg(AMP(11))+AMP(12)*dconjg(AMP(12))',
2721- 'AMP2(4)=AMP2(4)+AMP(13)*dconjg(AMP(13))+AMP(14)*dconjg(AMP(14))+AMP(15)*dconjg(AMP(15))+AMP(16)*dconjg(AMP(16))',
2722- 'AMP2(5)=AMP2(5)+AMP(17)*dconjg(AMP(17))+AMP(18)*dconjg(AMP(18))+AMP(19)*dconjg(AMP(19))+AMP(20)*dconjg(AMP(20))',
2723- 'AMP2(6)=AMP2(6)+AMP(21)*dconjg(AMP(21))+AMP(22)*dconjg(AMP(22))+AMP(23)*dconjg(AMP(23))+AMP(24)*dconjg(AMP(24))'])
2724+ ['AMP2(1)=AMP2(1)+AMP(1)*dconjg(AMP(1))',
2725+ 'AMP2(2)=AMP2(2)+AMP(2)*dconjg(AMP(2))',
2726+ 'AMP2(3)=AMP2(3)+AMP(3)*dconjg(AMP(3))',
2727+ 'AMP2(4)=AMP2(4)+AMP(4)*dconjg(AMP(4))',
2728+ 'AMP2(5)=AMP2(5)+AMP(5)*dconjg(AMP(5))',
2729+ 'AMP2(6)=AMP2(6)+AMP(6)*dconjg(AMP(6))'])
2730
2731 def test_four_fermion_vertex_normal_fermion_flow(self):
2732 """Testing process u u > t t g with fermion flow (u~t)(u~t)
2733@@ -5550,24 +5525,21 @@
2734
2735 result = helas_call_writers.FortranUFOHelasCallWriter(mybasemodel).\
2736 get_matrix_element_calls(matrix_element.get('core_processes')[0])
2737- self.assertEqual("\n".join(result),
2738+ self.assertEqual(result,
2739 """CALL OXXXXX(P(0,1),zero,NHEL(1),-1*IC(1),W(1,1))
2740 CALL IXXXXX(P(0,2),MT,NHEL(2),+1*IC(2),W(1,2))
2741 CALL VXXXXX(P(0,3),Mwp,NHEL(3),+1*IC(3),W(1,3))
2742 # Amplitude(s) for diagram number 1
2743-CALL FFS3_0(W(1,2),W(1,1),W(1,3),GC_108,AMP(1))
2744-CALL FFS4_0(W(1,2),W(1,1),W(1,3),GC_111,AMP(2))""")
2745+CALL FFS3_4_0(W(1,2),W(1,1),W(1,3),GC_108,GC_111,AMP(1))""".split('\n'))
2746 result = helas_call_writers.FortranUFOHelasCallWriter(mybasemodel).\
2747 get_matrix_element_calls(matrix_element.get('decay_chains')[0].get('core_processes')[0])
2748- self.assertEqual("\n".join(result),
2749+ self.assertEqual(result,
2750 """CALL VXXXXX(P(0,1),Mwp,NHEL(1),-1*IC(1),W(1,1))
2751 CALL IXXXXX(P(0,2),zero,NHEL(2),-1*IC(2),W(1,2))
2752 CALL OXXXXX(P(0,3),MT,NHEL(3),+1*IC(3),W(1,3))
2753-CALL FFS3_3(W(1,2),W(1,3),GC_108,Mwp, Wwp, W(1,4))
2754-CALL FFS4_3(W(1,2),W(1,3),GC_111,Mwp, Wwp, W(1,5))
2755+CALL FFS3_4_3(W(1,2),W(1,3),GC_108,GC_111,Mwp, Wwp, W(1,4))
2756 # Amplitude(s) for diagram number 1
2757-#
2758-#""")
2759+#""".split('\n'))
2760
2761 matrix_elements = matrix_element.combine_decay_chain_processes()
2762
2763@@ -5580,13 +5552,9 @@
2764 CALL IXXXXX(P(0,2),MT,NHEL(2),+1*IC(2),W(1,2))
2765 CALL IXXXXX(P(0,3),zero,NHEL(3),-1*IC(3),W(1,3))
2766 CALL OXXXXX(P(0,4),MT,NHEL(4),+1*IC(4),W(1,4))
2767-CALL FFS3_3(W(1,3),W(1,4),GC_108,Mwp, Wwp, W(1,5))
2768-CALL FFS4_3(W(1,3),W(1,4),GC_111,Mwp, Wwp, W(1,6))
2769+CALL FFS3_4_3(W(1,3),W(1,4),GC_108,GC_111,Mwp, Wwp, W(1,5))
2770 # Amplitude(s) for diagram number 1
2771-CALL FFS3_0(W(1,2),W(1,1),W(1,5),GC_108,AMP(1))
2772-CALL FFS3_0(W(1,2),W(1,1),W(1,6),GC_108,AMP(2))
2773-CALL FFS4_0(W(1,2),W(1,1),W(1,5),GC_111,AMP(3))
2774-CALL FFS4_0(W(1,2),W(1,1),W(1,6),GC_111,AMP(4))""".split('\n')
2775+CALL FFS3_4_0(W(1,2),W(1,1),W(1,5),GC_108,GC_111,AMP(1))""".split('\n')
2776
2777 for i in range(len(goal)):
2778 self.assertEqual(result[i], goal[i])
2779@@ -5705,24 +5673,21 @@
2780
2781 result = helas_call_writers.FortranUFOHelasCallWriter(mybasemodel).\
2782 get_matrix_element_calls(matrix_element.get('core_processes')[0])
2783- self.assertEqual("\n".join(result),
2784+ self.assertEqual(result,
2785 """CALL OXXXXX(P(0,1),zero,NHEL(1),-1*IC(1),W(1,1))
2786 CALL IXXXXX(P(0,2),MT,NHEL(2),+1*IC(2),W(1,2))
2787 CALL SXXXXX(P(0,3),+1*IC(3),W(1,3))
2788 # Amplitude(s) for diagram number 1
2789-CALL FFS3C1_0(W(1,2),W(1,1),W(1,3),GC_108,AMP(1))
2790-CALL FFS4C1_0(W(1,2),W(1,1),W(1,3),GC_111,AMP(2))""")
2791+CALL FFS3C1_4_0(W(1,2),W(1,1),W(1,3),GC_108,GC_111,AMP(1))""".split('\n'))
2792 result = helas_call_writers.FortranUFOHelasCallWriter(mybasemodel).\
2793 get_matrix_element_calls(matrix_element.get('decay_chains')[0].get('core_processes')[0])
2794- self.assertEqual("\n".join(result),
2795+ self.assertEqual(result,
2796 """CALL SXXXXX(P(0,1),-1*IC(1),W(1,1))
2797 CALL OXXXXX(P(0,2),zero,NHEL(2),+1*IC(2),W(1,2))
2798 CALL IXXXXX(P(0,3),MT,NHEL(3),-1*IC(3),W(1,3))
2799-CALL FFS3C1_3(W(1,3),W(1,2),GC_108,Msix1, Wsix1, W(1,4))
2800-CALL FFS4C1_3(W(1,3),W(1,2),GC_111,Msix1, Wsix1, W(1,5))
2801+CALL FFS3C1_4_3(W(1,3),W(1,2),GC_108,GC_111,Msix1, Wsix1, W(1,4))
2802 # Amplitude(s) for diagram number 1
2803-#
2804-#""")
2805+#""".split('\n'))
2806
2807 matrix_elements = matrix_element.combine_decay_chain_processes()
2808
2809@@ -5735,16 +5700,12 @@
2810 CALL IXXXXX(P(0,2),MT,NHEL(2),+1*IC(2),W(1,2))
2811 CALL OXXXXX(P(0,3),zero,NHEL(3),+1*IC(3),W(1,3))
2812 CALL IXXXXX(P(0,4),MT,NHEL(4),-1*IC(4),W(1,4))
2813-CALL FFS3C1_3(W(1,4),W(1,3),GC_108,Msix1, Wsix1, W(1,5))
2814-CALL FFS4C1_3(W(1,4),W(1,3),GC_111,Msix1, Wsix1, W(1,6))
2815+CALL FFS3C1_4_3(W(1,4),W(1,3),GC_108,GC_111,Msix1, Wsix1, W(1,5))
2816 # Amplitude(s) for diagram number 1
2817-CALL FFS3C1_0(W(1,2),W(1,1),W(1,5),GC_108,AMP(1))
2818-CALL FFS3C1_0(W(1,2),W(1,1),W(1,6),GC_108,AMP(2))
2819-CALL FFS4C1_0(W(1,2),W(1,1),W(1,5),GC_111,AMP(3))
2820-CALL FFS4C1_0(W(1,2),W(1,1),W(1,6),GC_111,AMP(4))""".split('\n')
2821+CALL FFS3C1_4_0(W(1,2),W(1,1),W(1,5),GC_108,GC_111,AMP(1))""".split('\n')
2822
2823- for i in range(len(goal)):
2824- self.assertEqual(result[i], goal[i])
2825+
2826+ self.assertEqual(result, goal)
2827
2828 def test_matrix_multistage_decay_chain_process(self):
2829 """Test matrix.f for multistage decay chain
2830@@ -6033,8 +5994,8 @@
2831 g,
2832 g]),
2833 'color': [color.ColorString([color.f(0, 1, 2)]),
2834- color.ColorString([color.f(0, 1, 2)]),
2835- color.ColorString([color.f(0, 1, 2)])],
2836+ color.ColorString([color.f(2, 1, 0)]),
2837+ color.ColorString([color.f(1, 0, 2)])],
2838 'lorentz':['gggg1', 'gggg2', 'gggg3'],
2839 'couplings':{(0, 0):'GG', (1, 1):'GG', (2, 2):'GG'},
2840 'orders':{'QCD':2}}))
2841@@ -7760,7 +7721,7 @@
2842 gen_color=True)
2843
2844 self.assertEqual(sum([len(diagram.get('amplitudes')) for diagram in \
2845- me.get('diagrams')]), 8)
2846+ me.get('diagrams')]), 2)
2847
2848 for i, amp in enumerate(me.get_all_amplitudes()):
2849 self.assertEqual(amp.get('number'), i + 1)
2850@@ -7770,8 +7731,8 @@
2851 exporter = export_v4.ProcessExporterFortranME()
2852
2853 self.assertEqual(exporter.get_JAMP_lines(me),
2854- ["JAMP(1)=-AMP(1)-AMP(2)-AMP(3)-AMP(4)",
2855- "JAMP(2)=+AMP(5)+AMP(6)+AMP(7)+AMP(8)"])
2856+ ["JAMP(1)=-AMP(1)",
2857+ "JAMP(2)=+AMP(2)"])
2858
2859 def test_generate_helas_diagrams_gg_gogo(self):
2860 """Testing the v4 helas diagram generation g g > go go,
2861@@ -8631,12 +8592,12 @@
2862 C The process calculated in this file is:
2863 C Gamma(3,2,1)
2864 C
2865- SUBROUTINE FFV1_1(F2, V3, C, M1, W1, F1)
2866+ SUBROUTINE FFV1_1(F2, V3, COUP, M1, W1, F1)
2867 IMPLICIT NONE
2868 DOUBLE COMPLEX F1(6)
2869 DOUBLE COMPLEX F2(6)
2870 DOUBLE COMPLEX V3(6)
2871- DOUBLE COMPLEX C
2872+ DOUBLE COMPLEX COUP
2873 DOUBLE COMPLEX DENOM
2874 DOUBLE PRECISION M1, W1
2875 DOUBLE PRECISION P1(0:3)
2876@@ -8653,10 +8614,9 @@
2877 abstract_M.write('/tmp','Fortran')
2878
2879 self.assertTrue(os.path.exists('/tmp/FFV1_1.f'))
2880- textfile = open('/tmp/FFV1_1.f','r')
2881+ textfile = open('/tmp/FFV1_1.f','r').read()
2882 split_sol = solution.split('\n')
2883- for i in range(len(split_sol)):
2884- self.assertEqual(split_sol[i]+'\n', textfile.readline())
2885+ self.assertEqual(split_sol, textfile.split('\n')[:len(split_sol)])
2886
2887
2888 class UFO_model_to_mg4_Test(unittest.TestCase):
2889
2890=== modified file 'tests/unit_tests/iolibs/test_helas_call_writers.py'
2891--- tests/unit_tests/iolibs/test_helas_call_writers.py 2011-03-22 00:16:20 +0000
2892+++ tests/unit_tests/iolibs/test_helas_call_writers.py 2011-04-20 16:57:29 +0000
2893@@ -493,14 +493,14 @@
2894
2895 wavefunctions = {}
2896 # IXXXXXX.Key: (spin, state)
2897- key1 = ((-2, 0), '')
2898+ key1 = ((-2, 0), ('',))
2899 wavefunctions[key1] = \
2900 lambda wf: 'CALL IXXXXX(P(0,%d),%s,NHEL(%d),%d*IC(%d),W(1,%d))' % \
2901 (wf.get('number_external'), wf.get('mass'),
2902 wf.get('number_external'), -(-1) ** wf.get_with_flow('is_part'),
2903 wf.get('number_external'), wf.get('number'))
2904 # OXXXXXX.Key: (spin, state)
2905- key2 = ((2, 0), '')
2906+ key2 = ((2, 0), ('',))
2907 wavefunctions[key2] = \
2908 lambda wf: 'CALL OXXXXX(P(0,%d),%s,NHEL(%d),%d*IC(%d),W(1,%d))' % \
2909 (wf.get('number_external'), wf.get('mass'),
2910
2911=== modified file 'tests/unit_tests/various/test_4fermion_models.py'
2912--- tests/unit_tests/various/test_4fermion_models.py 2011-04-15 04:15:48 +0000
2913+++ tests/unit_tests/various/test_4fermion_models.py 2011-04-20 16:57:29 +0000
2914@@ -77,7 +77,6 @@
2915 p)[0]
2916
2917
2918-
2919 self.assertAlmostEqual(values['scalar'], values['4ferm'], 3)
2920
2921 #===============================================================================
2922
2923=== modified file 'tests/unit_tests/various/test_aloha.py'
2924--- tests/unit_tests/various/test_aloha.py 2011-03-31 17:39:59 +0000
2925+++ tests/unit_tests/various/test_aloha.py 2011-04-20 16:57:29 +0000
2926@@ -16,6 +16,7 @@
2927 the output of the Feynman Rules."""
2928 from __future__ import division
2929
2930+import os
2931 import time
2932 import aloha.aloha_object as aloha_obj
2933 import aloha.aloha_lib as aloha_lib
2934@@ -2798,7 +2799,7 @@
2935 # Check that full identification symmetry works
2936 helas_suite = create_aloha.AbstractALOHAModel('sm')
2937 helas_suite.look_for_symmetries()
2938- solution = {'VVS1': {2: 1}, 'SSS1': {2: 1, 3: 2}, 'VVSS1': {2: 1, 4: 3}, 'VVVV2': {2: 1, 4: 3}, 'SSSS1': {2: 1, 3: 2, 4: 3}}
2939+ solution = {'SSSS1': {2: 1, 3: 2, 4: 3}, 'VVVV4': {2: 1, 3: 2, 4: 3}, 'VVV1': {2: 1, 3: 2}, 'VVVV1': {2: 1, 3: 2, 4: 3}, 'VVVV3': {2: 1, 3: 2, 4: 3}, 'VVVV2': {2: 1, 4: 3}, 'SSS1': {2: 1, 3: 2}, 'VVSS1': {2: 1, 4: 3}, 'VVS1': {2: 1}}
2940 self.assertEqual(solution, helas_suite.symmetries)
2941
2942 def test_has_symmetries(self):
2943@@ -2824,6 +2825,246 @@
2944
2945 base = helas_suite.has_symmetries('VVS1', 3, valid_output=(1, 2))
2946 self.assertEqual(base, None)
2947+
2948+ def test_aloha_multiple_lorentz(self):
2949+ """ check if the detection of multiple lorentz work """
2950+
2951+ helas_suite = create_aloha.AbstractALOHAModel('sm')
2952+ helas_suite.look_for_multiple_lorentz_interactions()
2953+ solution = {'FFV2': [('FFV3',), ('FFV4',), ('FFV5',)], 'FFS3': [('FFS4',)]}
2954+ self.assertEqual(solution, helas_suite.multiple_lor)
2955+
2956+
2957+ def test_aloha_multiple_lorentz_and_symmetry(self):
2958+ """ check if the detection of multiple lorentz work """
2959+
2960+ VVS1 = self.Lorentz(name = 'VVS1',
2961+ spins = [ 3, 3, 1 ],
2962+ structure = 'Metric(1,2)')
2963+
2964+ #VVS2 = self.Lorentz(name = 'VVS2',
2965+ # spins = [ 3, 3, 1 ],
2966+ # structure = 'Metric(2,1)')
2967+
2968+ abstract = create_aloha.AbstractRoutineBuilder(VVS1).compute_routine(1)
2969+ abstract.add_symmetry(2)
2970+ abstract.add_combine(('VVS2',))
2971+
2972+ text = abstract.write(None, 'Fortran')
2973+
2974+ goal =""" subroutine VVS1_1(V2, S3, COUP, M1, W1, V1)
2975+implicit none
2976+double complex V1(6)
2977+double complex V2(6)
2978+double complex S3(3)
2979+double complex COUP
2980+double complex denom
2981+double precision M1, W1
2982+double complex OM1
2983+double precision P1(0:3)
2984+
2985+V1(5)= V2(5)+S3(2)
2986+V1(6)= V2(6)+S3(3)
2987+P1(0) = - dble(V1(5))
2988+P1(1) = - dble(V1(6))
2989+P1(2) = - dimag(V1(6))
2990+P1(3) = - dimag(V1(5))
2991+OM1 = 0d0
2992+if (M1 .ne. 0d0) OM1=1d0/M1**2
2993+
2994+denom =1d0/(( (M1*( -M1+(0, 1)*W1))+( (P1(0)**2)-(P1(1)**2)-(P1(2)**2)-(P1(3)**2))))
2995+V1(1)= COUP*denom*(S3(1)*( (OM1*( (0, 1)*(V2(1)*P1(0))+(0, -1)*(V2(2)*P1(1))+(0, -1)*(V2(3)*P1(2))+(0, -1)*(V2(4)*P1(3)))*P1(0))+(0, -1)*V2(1)))
2996+V1(2)= COUP*denom*(S3(1)*( (OM1*( (0, 1)*(V2(1)*P1(0))+(0, -1)*(V2(2)*P1(1))+(0, -1)*(V2(3)*P1(2))+(0, -1)*(V2(4)*P1(3)))*P1(1))+(0, -1)*V2(2)))
2997+V1(3)= COUP*denom*(S3(1)*( (OM1*( (0, 1)*(V2(1)*P1(0))+(0, -1)*(V2(2)*P1(1))+(0, -1)*(V2(3)*P1(2))+(0, -1)*(V2(4)*P1(3)))*P1(2))+(0, -1)*V2(3)))
2998+V1(4)= COUP*denom*(S3(1)*( (OM1*( (0, 1)*(V2(1)*P1(0))+(0, -1)*(V2(2)*P1(1))+(0, -1)*(V2(3)*P1(2))+(0, -1)*(V2(4)*P1(3)))*P1(3))+(0, -1)*V2(4)))
2999+end
3000+
3001+
3002+
3003+ subroutine VVS1_2(V2, S3, COUP, M1, W1, V1)
3004+implicit none
3005+double complex V1(6)
3006+double complex V2(6)
3007+double complex S3(3)
3008+double complex COUP
3009+double complex denom
3010+double precision M1, W1
3011+double complex OM1
3012+double precision P1(0:3)
3013+call VVS1_1(V2,S3,COUP,M1,W1,V1)
3014+end
3015+
3016+
3017+ subroutine VVS1_2_1(V2, S3, COUP1,COUP2, M1, W1, V1)
3018+implicit none
3019+double complex V1(6)
3020+double complex V2(6)
3021+double complex S3(3)
3022+double complex COUP1,COUP2
3023+double complex denom
3024+double precision M1, W1
3025+double complex OM1
3026+double precision P1(0:3)
3027+ double complex TMP(6)
3028+ integer i
3029+
3030+ CALL VVS1_1(V2, S3, COUP1, M1, W1, V1)
3031+ CALL VVS2_1(V2, S3, COUP2, M1, W1, TMP)
3032+ do i=1,4
3033+ V1(i) = V1(i) + tmp(i)
3034+ enddo
3035+end
3036+
3037+ subroutine VVS1_2_2(V2, S3, COUP1,COUP2, M1, W1, V1)
3038+implicit none
3039+double complex V1(6)
3040+double complex V2(6)
3041+double complex S3(3)
3042+double complex COUP1,COUP2
3043+double complex denom
3044+double precision M1, W1
3045+double complex OM1
3046+double precision P1(0:3)
3047+ double complex TMP(6)
3048+ integer i
3049+
3050+ CALL VVS1_1(V2, S3, COUP1, M1, W1, V1)
3051+ CALL VVS2_1(V2, S3, COUP2, M1, W1, TMP)
3052+ do i=1,4
3053+ V1(i) = V1(i) + tmp(i)
3054+ enddo
3055+end
3056+
3057+"""
3058+ self.assertEqual(text.split('\n'),goal.split('\n'))
3059+
3060+ text_h, text_cpp = abstract.write(None, 'CPP')
3061+
3062+ goal_h = """#ifndef VVS1_1_guard
3063+#define VVS1_1_guard
3064+#include <complex>
3065+using namespace std;
3066+
3067+void VVS1_1(complex<double> V2[],complex<double> S3[],complex<double> COUP, double M1, double W1, complex<double>V1[]);
3068+
3069+void VVS1_2(complex<double> V2[],complex<double> S3[],complex<double> COUP, double M1, double W1, complex<double>V1[]);
3070+
3071+#endif
3072+
3073+#ifndef VVS1_2_1_guard
3074+#define VVS1_2_1_guard
3075+#include <complex>
3076+using namespace std;
3077+
3078+void VVS1_2_1(complex<double> V2[],complex<double> S3[],complex<double> COUP1, complex <double>COUP2, double M1, double W1, complex<double>V1[]);
3079+
3080+void VVS1_2_2(complex<double> V2[],complex<double> S3[],complex<double> COUP1, complex <double>COUP2, double M1, double W1, complex<double>V1[]);
3081+
3082+#endif"""
3083+ goal_cpp = """#include "VVS1_1.h"
3084+
3085+void VVS1_1(complex<double> V2[],complex<double> S3[],complex<double> COUP, double M1, double W1, complex<double>V1[]){
3086+complex<double> denom;
3087+complex<double> OM1;
3088+double P1[4];
3089+V1[4]= V2[4]+S3[1];
3090+V1[5]= V2[5]+S3[2];
3091+P1[0] = -V1[4].real();
3092+P1[1] = -V1[5].real();
3093+P1[2] = -V1[5].imag();
3094+P1[3] = -V1[4].imag();
3095+OM1 = 0;
3096+if (M1 != 0) OM1= 1./pow(M1,2);
3097+denom =1./(( (M1*( -M1+complex<double>(0., 1.)*W1))+( (pow(P1[0],2))-(pow(P1[1],2))-(pow(P1[2],2))-(pow(P1[3],2)))));
3098+V1[0]= COUP*denom*(S3[0]*( (OM1*( complex<double>(0., 1.)*(V2[0]*P1[0])+complex<double>(0., -1.)*(V2[1]*P1[1])+complex<double>(0., -1.)*(V2[2]*P1[2])+complex<double>(0., -1.)*(V2[3]*P1[3]))*P1[0])+complex<double>(0., -1.)*V2[0]));
3099+V1[1]= COUP*denom*(S3[0]*( (OM1*( complex<double>(0., 1.)*(V2[0]*P1[0])+complex<double>(0., -1.)*(V2[1]*P1[1])+complex<double>(0., -1.)*(V2[2]*P1[2])+complex<double>(0., -1.)*(V2[3]*P1[3]))*P1[1])+complex<double>(0., -1.)*V2[1]));
3100+V1[2]= COUP*denom*(S3[0]*( (OM1*( complex<double>(0., 1.)*(V2[0]*P1[0])+complex<double>(0., -1.)*(V2[1]*P1[1])+complex<double>(0., -1.)*(V2[2]*P1[2])+complex<double>(0., -1.)*(V2[3]*P1[3]))*P1[2])+complex<double>(0., -1.)*V2[2]));
3101+V1[3]= COUP*denom*(S3[0]*( (OM1*( complex<double>(0., 1.)*(V2[0]*P1[0])+complex<double>(0., -1.)*(V2[1]*P1[1])+complex<double>(0., -1.)*(V2[2]*P1[2])+complex<double>(0., -1.)*(V2[3]*P1[3]))*P1[3])+complex<double>(0., -1.)*V2[3]));
3102+}
3103+
3104+void VVS1_2(complex<double> V2[],complex<double> S3[],complex<double> COUP, double M1, double W1, complex<double>V1[]){
3105+VVS1_1(V2,S3,COUP,M1,W1,V1);
3106+}
3107+
3108+#include "VVS1_2_1.h"
3109+
3110+void VVS1_2_1(complex<double> V2[],complex<double> S3[],complex<double> COUP1, complex<double>COUP2, double M1, double W1, complex<double>V1[]){
3111+complex<double> tmp[6];
3112+ int i = 0;
3113+
3114+VVS1_1(V2, S3, COUP1, M1, W1, V1);
3115+VVS2_1(V2, S3, COUP2, M1, W1, tmp);
3116+ while (i < 4)
3117+ {
3118+ V1[i] = V1[i] + tmp[i];
3119+ i++;
3120+ }
3121+}
3122+
3123+#include "VVS1_2_2.h"
3124+
3125+void VVS1_2_2(complex<double> V2[],complex<double> S3[],complex<double> COUP1, complex<double>COUP2, double M1, double W1, complex<double>V1[]){
3126+complex<double> tmp[6];
3127+ int i = 0;
3128+
3129+VVS1_1(V2, S3, COUP1, M1, W1, V1);
3130+VVS2_1(V2, S3, COUP2, M1, W1, tmp);
3131+ while (i < 4)
3132+ {
3133+ V1[i] = V1[i] + tmp[i];
3134+ i++;
3135+ }
3136+}
3137+
3138+"""
3139+
3140+ self.assertEqual(text_h.split('\n'),goal_h.split('\n'))
3141+ self.assertEqual(text_cpp.split('\n'),goal_cpp.split('\n'))
3142+
3143+
3144+ text = abstract.write(None, 'Python')
3145+ goal = """import wavefunctions
3146+def VVS1_1(V2, S3, COUP, M1, W1):
3147+ V1 = wavefunctions.WaveFunction(size=6)
3148+ V1[4] = V2[4]+S3[1]
3149+ V1[5] = V2[5]+S3[2]
3150+ P1 = [-complex(V1[4]).real, \\
3151+ - complex(V1[5]).real, \\
3152+ - complex(V1[5]).imag, \\
3153+ - complex(V1[4]).imag]
3154+ OM1 = 0.0
3155+ if (M1): OM1=1.0/M1**2
3156+ denom =1.0/(( (M1*( -M1+1j*W1))+( (P1[0]**2)-(P1[1]**2)-(P1[2]**2)-(P1[3]**2))))
3157+ V1[0]= COUP*denom*(S3[0]*( (OM1*( 1j*(V2[0]*P1[0])-1j*(V2[1]*P1[1])-1j*(V2[2]*P1[2])-1j*(V2[3]*P1[3]))*P1[0])-1j*V2[0]))
3158+ V1[1]= COUP*denom*(S3[0]*( (OM1*( 1j*(V2[0]*P1[0])-1j*(V2[1]*P1[1])-1j*(V2[2]*P1[2])-1j*(V2[3]*P1[3]))*P1[1])-1j*V2[1]))
3159+ V1[2]= COUP*denom*(S3[0]*( (OM1*( 1j*(V2[0]*P1[0])-1j*(V2[1]*P1[1])-1j*(V2[2]*P1[2])-1j*(V2[3]*P1[3]))*P1[2])-1j*V2[2]))
3160+ V1[3]= COUP*denom*(S3[0]*( (OM1*( 1j*(V2[0]*P1[0])-1j*(V2[1]*P1[1])-1j*(V2[2]*P1[2])-1j*(V2[3]*P1[3]))*P1[3])-1j*V2[3]))
3161+ return V1
3162+
3163+
3164+def VVS1_2(V2, S3, COUP, M1, W1):
3165+ return VVS1_1(V2,S3,COUP,M1,W1)
3166+
3167+def VVS1_2_1(V2, S3, COUP1,COUP2, M1, W1):
3168+
3169+
3170+ V1 = VVS1_1(V2, S3, COUP1, M1, W1)
3171+ tmp = VVS2_1(V2, S3, COUP2, M1, W1)
3172+ for i in range(4):
3173+ V1[i] += tmp[i]
3174+ return V1
3175+
3176+def VVS1_2_2(V2, S3, COUP1,COUP2, M1, W1):
3177+
3178+
3179+ V1 = VVS1_1(V2, S3, COUP1, M1, W1)
3180+ tmp = VVS2_1(V2, S3, COUP2, M1, W1)
3181+ for i in range(4):
3182+ V1[i] += tmp[i]
3183+ return V1
3184+
3185+"""
3186+ self.assertEqual(text.split('\n'),goal.split('\n'))
3187
3188
3189 def test_full_sm_aloha(self):
3190@@ -2852,17 +3093,77 @@
3191 spin_solution = spin_index[helas.spins[output_part -1]]
3192 self.assertEqual(abstract.expr.numerator.nb_spin, spin_solution, \
3193 error % name)
3194+
3195+ def test_multiple_lorentz_subset(self):
3196+ """test if we create the correct set of routine/files for multiple lorentz"""
3197+
3198+ helas_suite = create_aloha.AbstractALOHAModel('sm')
3199+ requested_routines=[(('FFS1','FFS2') , (), 0),
3200+ (('FFV1',) , (), 0),
3201+ (('FFV1','FFV2') , (1,), 0)]
3202+
3203+ helas_suite.compute_subset(requested_routines)
3204+
3205+ # Check that the 5 base routines are created
3206+ # FFS1, FFS2, FFV1, FFV1C1, FFV2C1
3207+ self.assertEqual(len(helas_suite), 5)
3208+
3209+ # Check that FFS1 and FFV1C1 are correctly connected to the associate
3210+ #lorentz
3211+ linked = helas_suite[('FFS1',0)].combined
3212+ self.assertEqual(linked, [('FFS2',)])
3213+ linked = helas_suite[('FFV1C1',0)].combined
3214+ self.assertEqual(linked, [('FFV2',)])
3215+ linked = helas_suite[('FFV1',0)].combined
3216+ self.assertEqual(linked, [])
3217+
3218+ # Check that the file are correctly written
3219+ os.system('rm -r /tmp/mg5 &> /dev/null; mkdir /tmp/mg5 &> /dev/null')
3220+ helas_suite.write('/tmp/mg5', 'Fortran')
3221+
3222+ content = set(os.listdir('/tmp/mg5'))
3223+ self.assertEqual(content, set(['FFS1_0.f', 'FFS2_0.f', 'FFV1_0.f',
3224+ 'FFV1C1_0.f','FFV2C1_0.f', 'FFS1_2_0.f',
3225+ 'FFV1C1_2_0.f']))
3226+
3227+ # Check the content of FFV1__FFV2C1_0.f
3228+ fsock = open('/tmp/mg5/FFV1C1_2_0.f')
3229+ goal = """C This File is Automatically generated by ALOHA
3230+C
3231+ SUBROUTINE FFV1C1_2_0(F1,F2,V3,COUP1,COUP2,VERTEX)
3232+ IMPLICIT NONE
3233+ DOUBLE COMPLEX F1(6)
3234+ DOUBLE COMPLEX F2(6)
3235+ DOUBLE COMPLEX V3(6)
3236+ DOUBLE COMPLEX COUP1,COUP2
3237+ DOUBLE COMPLEX VERTEX
3238+ DOUBLE COMPLEX TMP
3239+
3240+
3241+ CALL FFV1C1_0(F1, F2, V3, COUP1, VERTEX)
3242+ CALL FFV2C1_0(F1, F2, V3, COUP2, TMP)
3243+ VERTEX = VERTEX + TMP
3244+ END
3245+
3246+
3247+"""
3248+ self.assertEqual(fsock.read().split('\n'), goal.split('\n'))
3249+
3250+
3251+
3252+
3253+
3254
3255 def test_mssm_subset_creation(self):
3256 """ test the creation of subpart of ALOHA routines
3257 including clash routines """
3258 helas_suite = create_aloha.AbstractALOHAModel('mssm')
3259
3260- requested_routines=[('FFV1' , (), 0),
3261- ('FFV1', (), 2),
3262- ('FFV1', (1,), 0),
3263- ('FFV2', (1,), 3),
3264- ('VVV1', (), 3)]
3265+ requested_routines=[(('FFV1',) , (), 0),
3266+ (('FFV1',), (), 2),
3267+ (('FFV1',), (1,), 0),
3268+ (('FFV2',), (1,), 3),
3269+ (('VVV1',), (), 3)]
3270
3271 helas_suite.compute_subset(requested_routines)
3272 self.assertEqual(len(helas_suite), 5)
3273@@ -3008,7 +3309,7 @@
3274 and test_export_pythia"""
3275
3276
3277- def test_reorder_call_listFFVV(self):
3278+ def old_test_reorder_call_listFFVV(self):
3279
3280 FFVV = UFOLorentz(name = 'FFVV',
3281 spins = [ 2, 2, 3, 3])
3282@@ -3021,7 +3322,7 @@
3283 new_call = writer.reorder_call_list(call_list, 1, 2)
3284 self.assertEqual(['F2', 'V3', 'V4'], new_call)
3285
3286- def test_reorder_call_listFVVV(self):
3287+ def old_test_reorder_call_listFVVV(self):
3288 FVVV = UFOLorentz(name = 'FVVV',
3289 spins = [ 2, 3, 3, 3])
3290
3291@@ -3041,7 +3342,7 @@
3292 new_call = writer.reorder_call_list(call_list, 2, 4)
3293 self.assertEqual(['F1', 'V4', 'V3'], new_call)
3294
3295- def test_reorder_call_listVVVV(self):
3296+ def old_test_reorder_call_listVVVV(self):
3297 VVVV = UFOLorentz(name = 'VVVV',
3298 spins = [ 3, 3, 3, 3])
3299
3300@@ -3092,7 +3393,7 @@
3301 new_call = writer.reorder_call_list(call_list, 3, 4)
3302 self.assertEqual(['V1', 'V2', 'V4'], new_call)
3303
3304- def test_reorder_call_listUVVS(self):
3305+ def old_test_reorder_call_listUVVS(self):
3306 UVVS = UFOLorentz(name = 'UVVS',
3307 spins = [ 2, 3, 3, 1])
3308
3309@@ -3144,7 +3445,7 @@
3310 """ test that python writer works """
3311
3312 solution ="""import wavefunctions
3313-def SSS1_1(S2, S3, C, M1, W1):
3314+def SSS1_1(S2, S3, COUP, M1, W1):
3315 S1 = wavefunctions.WaveFunction(size=3)
3316 S1[1] = S2[1]+S3[1]
3317 S1[2] = S2[2]+S3[2]
3318@@ -3153,12 +3454,17 @@
3319 - complex(S1[2]).imag, \\
3320 - complex(S1[1]).imag]
3321 denom =1.0/(( (M1*( -M1+1j*W1))+( (P1[0]**2)-(P1[1]**2)-(P1[2]**2)-(P1[3]**2))))
3322- S1[0]= C*denom*1j*(S3[0]*S2[0])
3323+ S1[0]= COUP*denom*1j*(S3[0]*S2[0])
3324 return S1
3325-def SSS1_2(S2, S3, C, M1, W1):
3326- return SSS1_1(S2,S3,C,M1,W1)
3327-def SSS1_3(S2, S3, C, M1, W1):
3328- return SSS1_1(S3,S2,C,M1,W1)"""
3329+
3330+
3331+def SSS1_2(S2, S3, COUP, M1, W1):
3332+ return SSS1_1(S2,S3,COUP,M1,W1)
3333+
3334+def SSS1_3(S2, S3, COUP, M1, W1):
3335+ return SSS1_1(S2,S3,COUP,M1,W1)
3336+
3337+"""
3338
3339 SSS = UFOLorentz(name = 'SSS1',
3340 spins = [ 1, 1, 1 ],
3341@@ -3172,8 +3478,7 @@
3342
3343 split_solution = solution.split('\n')
3344 split_routine = routine.split('\n')
3345- for i,line in enumerate(split_routine):
3346- self.assertEqual(split_solution[i],line)
3347+ self.assertEqual(split_solution, split_routine)
3348 self.assertEqual(len(split_routine), len(split_solution))
3349
3350
3351@@ -3191,14 +3496,16 @@
3352
3353
3354 solution = """import wavefunctions
3355-def FFV2C1_0(F1,F2,V3,C):
3356- vertex = C*( (F1[3]*( (F2[0]*( -1j*V3[1]-V3[2]))+(F2[1]*( 1j*V3[0]+1j*V3[3]))))+(F1[2]*( (F2[0]*( 1j*V3[0]-1j*V3[3]))+(F2[1]*( -1j*V3[1]+V3[2])))))
3357- return vertex"""
3358+def FFV2C1_0(F1,F2,V3,COUP):
3359+ vertex = COUP*( (F1[3]*( (F2[0]*( -1j*V3[1]-V3[2]))+(F2[1]*( 1j*V3[0]+1j*V3[3]))))+(F1[2]*( (F2[0]*( 1j*V3[0]-1j*V3[3]))+(F2[1]*( -1j*V3[1]+V3[2])))))
3360+ return vertex
3361+
3362+
3363+"""
3364
3365 split_solution = solution.split('\n')
3366 split_routine = routine.split('\n')
3367- for i,line in enumerate(split_routine):
3368- self.assertEqual(split_solution[i],line)
3369+ self.assertEqual(split_solution,split_routine)
3370 self.assertEqual(len(split_routine), len(split_solution))
3371
3372

Subscribers

People subscribed via source and target branches