Merge lp:~maddevelopers/mg5amcnlo/version_1_0_1 into lp:~madteam/mg5amcnlo/trunk

Proposed by Johan Alwall
Status: Merged
Merged at revision: 112
Proposed branch: lp:~maddevelopers/mg5amcnlo/version_1_0_1
Merge into: lp:~madteam/mg5amcnlo/trunk
Diff against target: 24292 lines (+4693/-15598)
79 files modified
Template/Cards/run_card.dat (+5/-0)
Template/Source/combine_events.f (+26/-29)
Template/Source/combine_runs.f (+28/-32)
Template/Source/cuts.inc (+6/-0)
Template/Source/dsample.f (+1/-2)
Template/Source/gen_ximprove.f (+27/-49)
Template/Source/genps.inc (+4/-5)
Template/Source/invarients.f (+2/-1)
Template/Source/makefile (+1/-1)
Template/Source/maxparticles.inc (+2/-0)
Template/Source/run_config.inc (+4/-4)
Template/Source/setrun.f (+6/-0)
Template/Source/sum_html.f (+26/-53)
Template/SubProcesses/cluster.f (+5/-5)
Template/SubProcesses/cuts.f (+12/-8)
Template/SubProcesses/driver.f (+7/-6)
Template/SubProcesses/makefile (+2/-2)
Template/SubProcesses/myamp.f (+50/-31)
Template/SubProcesses/reweight.f (+18/-1)
Template/SubProcesses/setcuts.f (+58/-1)
Template/SubProcesses/symmetry.f (+46/-39)
Template/SubProcesses/symmetry_v4.f (+84/-78)
Template/SubProcesses/unwgt.f (+17/-10)
Template/bin/gen_crossxhtml-pl (+1/-1)
Template/bin/generate_events (+0/-1)
UpdateNotes.txt (+36/-0)
aloha/aloha_writers.py (+486/-106)
aloha/bin/aloha (+1/-1)
aloha/create_aloha.py (+95/-18)
input/mg5_configuration.txt (+18/-0)
madgraph/VERSION (+2/-2)
madgraph/core/helas_objects.py (+122/-77)
madgraph/interface/cmd_interface.py (+291/-99)
madgraph/interface/launch_ext_program.py (+78/-36)
madgraph/interface/tutorial_text.py (+11/-14)
madgraph/iolibs/export_cpp.py (+81/-45)
madgraph/iolibs/export_python.py (+5/-3)
madgraph/iolibs/export_v4.py (+49/-46)
madgraph/iolibs/files.py (+5/-1)
madgraph/iolibs/gen_infohtml.py (+1/-1)
madgraph/iolibs/group_subprocs.py (+6/-0)
madgraph/iolibs/helas_call_writers.py (+142/-129)
madgraph/iolibs/template_files/cpp_process_matrix.inc (+1/-3)
madgraph/iolibs/template_files/cpp_process_wavefunctions.inc (+2/-0)
madgraph/iolibs/template_files/matrix_madevent_group_v4.inc (+57/-32)
madgraph/iolibs/template_files/matrix_madevent_v4.inc (+52/-12)
madgraph/iolibs/template_files/matrix_standalone_v4.inc (+2/-0)
madgraph/iolibs/template_files/pythia8_main_makefile.inc (+1/-1)
madgraph/iolibs/template_files/pythia8_process_wavefunctions.inc (+3/-0)
madgraph/iolibs/template_files/super_auto_dsig_group_v4.inc (+9/-9)
madgraph/various/diagram_symmetry.py (+76/-63)
madgraph/various/process_checks.py (+22/-60)
models/RS/model.pkl (+0/-13743)
models/heft_v4/coupl.inc (+2/-2)
models/heft_v4/couplings.f (+0/-1)
models/import_ufo.py (+1/-4)
models/mssm/restrict_no_b_mass.dat (+525/-0)
models/mssm/restrict_no_masses.dat (+525/-0)
models/mssm/restrict_no_tau_mass.dat (+525/-0)
models/sextet_diquarks/parameters.py (+8/-0)
models/sm/restrict_no_b_mass.dat (+1/-1)
models/sm/restrict_no_tau_mass.dat (+1/-1)
models/template_files/fortran/lha_read.f (+4/-9)
models/triplet_diquarks/parameters.py (+8/-0)
tests/acceptance_tests/test_cmd.py (+69/-59)
tests/acceptance_tests/test_model_equivalence.py (+1/-3)
tests/parallel_tests/me_comparator.py (+3/-2)
tests/parallel_tests/sample_script.py (+11/-31)
tests/unit_tests/core/test_helas_objects.py (+8/-6)
tests/unit_tests/iolibs/test_export_cpp.py (+373/-137)
tests/unit_tests/iolibs/test_export_python.py (+15/-24)
tests/unit_tests/iolibs/test_export_v4.py (+166/-373)
tests/unit_tests/iolibs/test_group_subprocs.py (+2/-2)
tests/unit_tests/iolibs/test_helas_call_writers.py (+2/-2)
tests/unit_tests/various/test_4fermion_models.py (+3/-7)
tests/unit_tests/various/test_aloha.py (+330/-23)
tests/unit_tests/various/test_diagram_symmetry.py (+9/-22)
tests/unit_tests/various/test_diquark_models.py (+5/-18)
tests/unit_tests/various/test_process_checks.py (+4/-11)
To merge this branch: bzr merge lp:~maddevelopers/mg5amcnlo/version_1_0_1
Reviewer Review Type Date Requested Status
Priscila de Aquino Pending
Olivier Mattelaer Pending
Review via email: mp+58201@code.launchpad.net

Description of the change

- Removed hard limit on number of external particles in
MadEvent, allowing for unlimited length decay chains there
(up to 14 final state particles successfully integrated)
- Improved helicity selection and automatic full helicity
sum if needed. Optimization of run parameters.
- Fixed MadEvent bugs for multiparton processes with
conflicting decays and fixed some faulty array limits.
- Suppressed scary but irrelevant warnings for compiling
2->1 and 1->2 processes in MadEvent
- Optimized Pythia 8 output further
- Several minor fixes relating to user interface etc.

To post a comment you must log in.
132. By Johan Alwall

Include possibility to choose in run_card whether or not apply cuts on decay products (pt/E/eta/dr/mij)

133. By Johan Alwall

Added restrict files setting tau and b masses to 0 for mssm

134. By Olivier Mattelaer

      make output of launch to have correct unit when computing width
      correct bug 761743 linked to lha_read.f

135. By Johan Alwall

Merged with reduce_aloha_call branch rev. 141: Combine multiple lorentz with the same color in the same vertex into a single aloha call, speeding up things like SM Z production and decay by a factor 2 or more.

136. By Johan Alwall

Ensure to flip color info etc for mirror processes after addmothers, since this might change there

137. By Johan Alwall

Fixed number of digits for Gxx.xx directories to work for all cases, fixed grid presetting also for forced BW without cuts

138. By Johan Alwall

Woops, forgot symmetry_v4.f

139. By Johan Alwall

Updated version number and UpdateNotes

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

Nice Job,

here is the first part of my review (the diff is too long to be on the web:)

1) At a point you use this:

2749+ start_time = time.time()
2750 for perm in itertools.permutations(range(ninitial, nexternal)):
2751 if [equivalent_process.get('legs')[i].get('id') for i in perm] != \
2752 final_states:
2753 # Non-identical particles permutated
2754 continue
2755+ # Check if we need to cancel the check due to time limit
2756+ if not max_time or time.time() - start_time > max_time:
2757+ logger.warning("Cancel diagram symmetry - time exceeded")
2758+ break

I would suggest to rather use a clock alarm.

for example:
def handle_alarm(signum, frame):
    raise TimeOutError

signal.signal(signal.SIGALRM, handle_alarm)
signal.alarm(timeout)
try:
 WHAT YOU HAVE TO DO
except TimeOutError:
 STOPPED IT NICELY
finally:
 signal.alarm(0) # stop the alarm since the job is done

*********************************************************************

2) models/RS/model.pkl need to be suppresed
It seemed to be include in the repository (this should be my fault. sorry for that)

So I'm at 50% of the review, and so far so good.

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

Hello Olivier,

> I would suggest to rather use a clock alarm.
>
> for example:
> def handle_alarm(signum, frame):
>    raise TimeOutError
>
> signal.signal(signal.SIGALRM, handle_alarm)
> signal.alarm(timeout)
> try:
>        WHAT YOU HAVE TO DO
> except TimeOutError:
>        STOPPED IT NICELY
> finally:
>        signal.alarm(0) # stop the alarm since the job is done

Excellent! This is much, much better! I've made the change.

> 2) models/RS/model.pkl need to be suppresed
> It seemed to be include in the repository (this should be my fault. sorry for that)

Already removed!

Thanks! Looking forward to the other half!

Johan

140. By Johan Alwall

Replaced stupid time.time in diagram symmetry with elegant Python alarm

141. By Johan Alwall

Cutoff when fact scale too low instead of ungraceful exit. Set minimum for grid even if no cuts (at 1/10000 x sqrt(s)). Changed refresh in crossx.html to 10 s instead of 30 s.

142. By Johan Alwall

Added floating point trap to commented line in makefiles

143. By Johan Alwall

Merged with updated reduce_aloha_call branch, including open command for relevant file types, and automatic opening of crossx.html when running launch for MadEvent.

144. By Johan Alwall

Set all applications directly in configuration step, no selection done in open_file

145. By Johan Alwall

Added .ps as valid extention for eps_viewer

146. By Johan Alwall

Updated UpdateNotes.

147. By Johan Alwall

Finally fixed the way default directories are set. Now, always check for present directory if none is given.

148. By Johan Alwall

Finally removed superfluous and confusing check if export has already happened to this directory.

149. By Johan Alwall

Remove scary output about no valid eps viewer or web browser

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Template/Cards/run_card.dat'
2--- Template/Cards/run_card.dat 2011-03-02 18:01:07 +0000
3+++ Template/Cards/run_card.dat 2011-04-22 01:24:30 +0000
4@@ -70,6 +70,11 @@
5 # BW cutoff (M+/-bwcutoff*Gamma)
6 #**********************************
7 15 = bwcutoff
8+#**********************************************************
9+# Apply pt/E/eta/dr/mij cuts on decay products or not
10+# (note that etmiss/ptll/ptheavy/sorted cuts always apply)
11+#**********************************************************
12+ F = cut_decays
13 #*******************
14 # Standard Cuts
15 #*******************
16
17=== modified file 'Template/Source/combine_events.f'
18--- Template/Source/combine_events.f 2011-03-01 07:02:57 +0000
19+++ Template/Source/combine_events.f 2011-04-22 01:24:30 +0000
20@@ -13,15 +13,16 @@
21 parameter (cmax_events=500000)
22 integer sfnum
23 parameter (sfnum=17) !Unit number for scratch file
24+ include 'maxparticles.inc'
25 integer maxexternal
26- parameter (maxexternal=17)
27+ parameter (maxexternal=2*max_particles-3)
28 integer maxpara
29 parameter (maxpara=1000)
30 c
31 c Local
32 c
33- character*100 subname(maxsubprocesses)
34- character*110 pathsubname(maxsubprocesses) !needed for MadWeight
35+ character*300 subname(maxsubprocesses)
36+ character*310 pathsubname(maxsubprocesses) !needed for MadWeight
37 character*80 down_path !needed for MadWeight
38 character*40 filename !needed for MadWeight
39 character*4 card_number !needed for MadWeight
40@@ -442,6 +443,7 @@
41 c
42 character*(*) symfile
43 parameter (symfile='symfact.dat')
44+ include 'maxparticles.inc'
45 c
46 c Arguments
47 c
48@@ -453,37 +455,31 @@
49 c
50 integer i,j, k, ip
51 double precision xi
52- character*150 dirname,dname,channame
53+ character*300 dirname,dname,channame
54+ integer ncode,npos
55+ character*20 formstr
56 c-----
57 c Begin Code
58 c-----
59- i = index(dir," ")
60+ i = index(dir," ")
61+c ncode is number of digits needed for the bw coding
62+ ncode=int(dlog10(3d0)*(max_particles-3))+1
63 dname = dir(1:i-1)// "/" // symfile
64 open(unit=35, file=dname ,status='old',err=59)
65 do while (.true.)
66 read(35,*,err=99,end=99) xi,j
67 if (j .gt. 0) then
68- if ( (xi-int(xi+.01)) .lt. 1d-5) then
69- k = int(xi+.01)
70- if (k .lt. 10) then
71- write(dirname,'(a,i1,a)') 'G',k,'/'
72- else if (k .lt. 100) then
73- write(dirname,'(a,i2,a)') 'G',k,'/'
74- else if (k .lt. 1000) then
75- write(dirname,'(a,i3,a)') 'G',k,'/'
76- else if (k .lt. 10000) then
77- write(dirname,'(a,i4,a)') 'G',k,'/'
78- endif
79+ k = int(xi*(1+10**-ncode))
80+ npos=int(dlog10(dble(k)))+1
81+ if ( (xi-k) .eq. 0) then
82+c Write with correct number of digits
83+ write(formstr,'(a,i1,a)') '(a,i',npos,',a)'
84+ write(dirname, formstr) 'G',k,'/'
85 else !Handle B.W.
86- if (xi .lt. 10) then
87- write(dirname,'(a,f5.3,a,a)') 'G',xi,'/'
88- else if (xi .lt. 100) then
89- write(dirname,'(a,f6.3,a,a)') 'G',xi,'/'
90- else if (xi .lt. 1000) then
91- write(dirname,'(a,f7.3,a,a)') 'G',xi,'/'
92- else if (xi .lt. 10000) then
93- write(dirname,'(a,f8.3,a,a)') 'G',xi,'/'
94- endif
95+c Write with correct number of digits
96+ write(formstr,'(a,i1,a,i1,a)') '(a,f',npos+ncode+1,
97+ $ '.',ncode,',a)'
98+ write(dirname,formstr) 'G',xi,'/'
99 endif
100 ip = index(dirname,'/')
101 channame = dname(1:i-1)// "/" //dirname(1:ip)
102@@ -517,8 +513,9 @@
103 parameter (sfnum=17) !Unit number for scratch file
104 character*(*) scaled_file
105 parameter (scaled_file='events.lhe')
106- integer maxexternal
107- parameter (maxexternal=17)
108+ include 'maxparticles.inc'
109+ integer maxexternal
110+ parameter (maxexternal=2*max_particles-3)
111 include 'run_config.inc'
112 integer max_read
113 parameter (max_read = 2000000)
114@@ -540,7 +537,7 @@
115 integer ievent,iseed
116 logical done,found
117 character*140 buff
118- character*150 fullname
119+ character*300 fullname
120 c
121 c Les Houches init block (for the <init> info)
122 c
123@@ -654,7 +651,7 @@
124 c
125 c Arguments
126 c
127- character*100 subname(maxsubprocesses)
128+ character*300 subname(maxsubprocesses)
129 integer ns
130 c-----
131 c Begin Code
132
133=== modified file 'Template/Source/combine_runs.f'
134--- Template/Source/combine_runs.f 2010-12-20 20:08:13 +0000
135+++ Template/Source/combine_runs.f 2011-04-22 01:24:30 +0000
136@@ -14,9 +14,9 @@
137 c
138 c Local
139 c
140- character*150 procname(maxsubprocesses)
141- character*150 channame(maxsubprocesses)
142- character*150 pathname
143+ character*300 procname(maxsubprocesses)
144+ character*300 channame(maxsubprocesses)
145+ character*300 pathname
146 integer iproc,nproc
147 integer ichan,nchan
148 integer jc
149@@ -88,6 +88,7 @@
150 c
151 character*(*) symfile
152 parameter (symfile='symfact.dat')
153+ include 'maxparticles.inc'
154 integer maxsubprocesses
155 parameter (maxsubprocesses=999)
156 c
157@@ -99,42 +100,36 @@
158 c
159 c Local
160 c
161- character*150 fname
162+ character*300 fname
163 character*50 dirname
164 integer jc,ip
165 double precision xi
166 integer j,k
167+ integer ncode,npos
168+ character*20 formstr
169 c-----
170 c Begin Code
171 c-----
172 jc = index(pathname," ")
173+c ncode is number of digits needed for the bw coding
174+ ncode=int(dlog10(3d0)*(max_particles-3))+1
175 fname = pathname(1:jc-1) // "/" // symfile
176 nchan = 0
177 open(unit=35, file=fname,status='old',err=99)
178 do while (.true.)
179 read(35,*,err=99,end=99) xi,j
180 if (j .gt. 0) then
181- if ( (xi-int(xi+.01)) .lt. 1d-5) then
182- k = int(xi+.01)
183- if (k .lt. 10) then
184- write(dirname,'(a,i1,a)') 'G',k,'/'
185- else if (k .lt. 100) then
186- write(dirname,'(a,i2,a)') 'G',k,'/'
187- else if (k .lt. 1000) then
188- write(dirname,'(a,i3,a)') 'G',k,'/'
189- else if (k .lt. 10000) then
190- write(dirname,'(a,i4,a)') 'G',k,'/'
191- endif
192+ k = int(xi*(1+10**-ncode))
193+ npos=int(dlog10(dble(k)))+1
194+ if ( (xi-k) .eq. 0) then
195+c Write with correct number of digits
196+ write(formstr,'(a,i1,a)') '(a,i',npos,',a)'
197+ write(dirname, formstr) 'G',k,'/'
198 else !Handle B.W.
199- if (xi .lt. 10) then
200- write(dirname,'(a,f5.3,a,a)') 'G',xi,'/'
201- else if (xi .lt. 100) then
202- write(dirname,'(a,f6.3,a,a)') 'G',xi,'/'
203- else if (xi .lt. 1000) then
204- write(dirname,'(a,f7.3,a,a)') 'G',xi,'/'
205- else if (xi .lt. 10000) then
206- write(dirname,'(a,f8.3,a,a)') 'G',xi,'/'
207- endif
208+c Write with correct number of digits
209+ write(formstr,'(a,i1,a,i1,a)') '(a,f',npos+ncode+1,
210+ $ '.',ncode,',a)'
211+ write(dirname,formstr) 'G',xi,'/'
212 endif
213 ip = index(dirname,'/')
214 nchan=nchan+1
215@@ -165,8 +160,8 @@
216 c
217 c Local
218 c
219- character*150 fname
220- character*150 pathname
221+ character*300 fname
222+ character*300 pathname
223 character*26 alphabet
224 integer jc,i
225 integer njobs
226@@ -263,8 +258,9 @@
227 c
228 character*(*) eventfname
229 parameter (eventfname="events.lhe")
230+ include 'maxparticles.inc'
231 integer maxexternal !Max number external momenta
232- parameter (maxexternal=17)
233+ parameter (maxexternal=2*max_particles-3)
234 c
235 c Arguments
236 c
237@@ -274,9 +270,9 @@
238 c
239 c Local
240 c
241- character*150 fname
242+ character*300 fname
243 integer jc
244- double precision P(0:3,maxexternal),xwgt
245+ double precision P(0:4,maxexternal),xwgt
246 integer n,ic(7,maxexternal),ievent
247 double precision scale,aqcd,aqed
248 character*140 buff
249@@ -328,7 +324,7 @@
250 c
251 c Local
252 c
253- character*150 fname
254+ character*300 fname
255 integer jc,i,j
256 double precision x1,x2,x3,x4
257 c-----
258@@ -385,7 +381,7 @@
259 c
260 c Local
261 c
262- character*150 fname
263+ character*300 fname
264 character*26 alphabet
265 integer jc,i,j
266 c-----
267@@ -429,7 +425,7 @@
268 c
269 c Local
270 c
271- character*150 fname
272+ character*300 fname
273 integer jc,i,j
274 double precision x1,x2
275 integer i3,i4
276
277=== modified file 'Template/Source/cuts.inc'
278--- Template/Source/cuts.inc 2010-12-19 17:10:07 +0000
279+++ Template/Source/cuts.inc 2011-04-22 01:24:30 +0000
280@@ -65,3 +65,9 @@
281 real*8 xptj,xptb,xpta,xptl,xmtc
282 real*8 xetamin,xqcut,deltaeta
283 common /to_specxpt/xptj,xptb,xpta,xptl,xmtc,xetamin,xqcut,deltaeta
284+
285+C
286+C FLAG FOR CUTTING DECAY PRODUCTS
287+C
288+ logical cut_decays
289+ common /to_cut_decays/cut_decays
290
291=== modified file 'Template/Source/dsample.f'
292--- Template/Source/dsample.f 2011-04-04 06:18:33 +0000
293+++ Template/Source/dsample.f 2011-04-22 01:24:30 +0000
294@@ -1755,7 +1755,7 @@
295 c
296 c special routines to deal with xmin cutoff
297 c
298- do while(grid(1,k,j) .le. 0d0 .and. k .lt. ng)
299+ do while(grid(1,k,j) .le. 0d0 .and. k+1 .lt. ng)
300 k=k+1
301 enddo
302
303@@ -1940,7 +1940,6 @@
304 tmeant = 0d0
305 tsigmat = 0d0
306 do i=cur_it-3,cur_it-1
307- print *,'mean, sigma: ',i,ymean(i),ysigma(i)
308 tmeant = tmeant+ymean(i)*ymean(i)**2/ysigma(i)**2
309 tsigmat = tsigmat + ymean(i)**2/ ysigma(i)**2
310 enddo
311
312=== modified file 'Template/Source/gen_ximprove.f'
313--- Template/Source/gen_ximprove.f 2011-03-15 23:28:24 +0000
314+++ Template/Source/gen_ximprove.f 2011-04-22 01:24:30 +0000
315@@ -17,6 +17,7 @@
316 parameter (maxpara=1000)
317
318 include 'run_config.inc'
319+ include 'maxparticles.inc'
320 c
321 c global
322 c
323@@ -46,6 +47,8 @@
324 logical Gridpack,gridrun
325 logical split_channels
326 common /to_split/split_channels
327+ integer ncode,npos
328+ character*20 formstr
329
330 c-----
331 c Begin Code
332@@ -106,33 +109,25 @@
333 errtotc=0d0
334 xtot = 0d0
335 i = 0
336+c ncode is number of digits needed for the bw coding
337+ ncode=int(dlog10(3d0)*(max_particles-3))+1
338 do while (.true.)
339 read(15,*,err=99,end=99) xi,j
340 if (j .gt. 0) then
341 i = i+1
342- if ( (xi-int(xi+.01)) .lt. 1d-5) then
343- n = int(xi+.01)
344- if (n .lt. 10) then
345- write(fname,'(a,i1,a,a)') 'G',n,'/',rfile
346- else if (n .lt. 100) then
347- write(fname,'(a,i2,a,a)') 'G',n,'/',rfile
348- else if (n .lt. 1000) then
349- write(fname,'(a,i3,a,a)') 'G',n,'/',rfile
350- else if (n .lt. 10000) then
351- write(fname,'(a,i4,a,a)') 'G',n,'/',rfile
352- endif
353- else
354- if (xi .lt. 10) then
355- write(fname,'(a,f5.3,a,a)') 'G',xi,'/',rfile
356- else if (xi .lt. 100) then
357- write(fname,'(a,f6.3,a,a)') 'G',xi,'/',rfile
358- else if (xi .lt. 1000) then
359- write(fname,'(a,f7.3,a,a)') 'G',xi,'/',rfile
360- else if (xi .lt. 10000) then
361- write(fname,'(a,f8.3,a,a)') 'G',xi,'/',rfile
362- endif
363+ k = int(xi*(1+10**-ncode))
364+ npos=int(dlog10(dble(k)))+1
365+ if ( (xi-k) .eq. 0) then
366+c Write with correct number of digits
367+ write(formstr,'(a,i1,a)') '(a,i',npos,',a,a)'
368+ write(fname, formstr) 'G',k,'/',rfile
369+ else !Handle B.W.
370+c Write with correct number of digits
371+ write(formstr,'(a,i1,a,i1,a)') '(a,f',npos+ncode+1,
372+ $ '.',ncode,',a,a)'
373+ write(fname, formstr) 'G',xi,'/',rfile
374+ endif
375 c write(*,*) 'log name ',fname
376- endif
377 endif
378 if (j .gt. 0) then
379 gname(i)=fname
380@@ -314,17 +309,6 @@
381
382 ip = index(gn(io(i)),'/')
383 write(26,'(2a)') 'j=',gn(io(i))(1:ip-1)
384- if (.false.) then
385- if (io(i) .lt. 10) then
386- write(26,'(a,i1)') 'j=G',io(i)
387- elseif (io(i) .lt. 100) then
388- write(26,'(a,i2)') 'j=G',io(i)
389- elseif (io(i) .lt. 1000) then
390- write(26,'(a,i3)') 'j=G',io(i)
391- elseif (io(i) .lt. 10000) then
392- write(26,'(a,i4)') 'j=G',io(i)
393- endif
394- endif
395 c
396 c Determine estimates for getting the desired accuracy
397 c
398@@ -386,7 +370,8 @@
399 c local
400 c
401 character*30 fname
402- integer ic
403+ integer ic, npos
404+ character*10 formstr
405
406 data ic/0/
407 c-----
408@@ -394,20 +379,12 @@
409 c-----
410 ic=ic+1
411 fname='ajob'
412- if (ic .lt. 10) then
413- write(fname(5:5),'(i1)') ic
414- elseif (ic .lt. 100) then
415- write(fname(5:6),'(i2)') ic
416- elseif (ic .lt. 1000) then
417- write(fname(5:7),'(i3)') ic
418- elseif (ic .lt. 10000) then
419- write(fname(5:8),'(i4)') ic
420- else
421- write(*,*) 'Error too many jobs in gen_ximprove',ic
422- stop
423- endif
424+c Write ic with correct number of digits
425+ npos=int(dlog10(dble(ic)))+1
426+ write(formstr,'(a,i1,a)') '(I',npos,')'
427+ write(fname(5:(5+npos-1)),formstr) ic
428+
429 write(*,*) 'Opening file ',fname
430-
431 open (unit=26, file = fname, status='unknown')
432 write(26,15) '#!/bin/bash'
433 write(26,15) '#PBS -q ' // PBS_QUE
434@@ -559,9 +536,10 @@
435 k=k+1
436 enddo
437 kk=k
438-c Check error for the rest of the channels
439+c Check error for the rest of the channels - rerun if
440+c bigger than channel xsec and bigger than 1% of largest channel
441 do while( kk .le. ng)
442- if (xerr(io(kk)).gt.xsec(io(kk))) then
443+ if (xerr(io(kk)).gt.max(xsec(io(kk)),0.01*xsec(io(1)))) then
444 write(*,*) 'Improving for error ',kk,gn(io(kk)),xt(kk),xsec(io(kk)),xerr(io(kk))
445 io(k)=io(kk)
446 xt(k)=xt(kk)
447
448=== modified file 'Template/Source/genps.inc'
449--- Template/Source/genps.inc 2011-04-03 22:06:00 +0000
450+++ Template/Source/genps.inc 2011-04-22 01:24:30 +0000
451@@ -2,12 +2,11 @@
452 c Parameters used by genps and dsample, you must recompile
453 c dsample if you change anything below
454 c*************************************************************************
455- integer max_particles , max_branch
456- parameter (max_particles=10, max_branch=max_particles-2)
457- integer max_tree , max_dim
458- parameter (max_tree=200, max_dim=max_tree*(max_branch+1))
459+ include 'maxparticles.inc'
460+ integer max_branch
461+ parameter (max_branch=max_particles-1)
462 integer ng , maxdim , maxinvar , maxconfigs
463- parameter (ng = 96, maxdim = 25, maxinvar= 50 , maxconfigs=10)
464+ parameter (ng = 96, maxdim = 3*(max_particles-2)-2, maxinvar= 4*max_particles, maxconfigs=10)
465 c parameter (ng = 43, maxdim = 25, maxinvar= 57 , maxconfigs=20)
466
467 double precision xgmin, xgmax
468
469=== modified file 'Template/Source/invarients.f'
470--- Template/Source/invarients.f 2011-04-03 22:06:00 +0000
471+++ Template/Source/invarients.f 2011-04-22 01:24:30 +0000
472@@ -226,7 +226,8 @@
473 c
474
475 if (nconfigs .eq. 1) then
476- do j=1,3*nbranch-4+2
477+c do j=1,3*nbranch-4+2
478+ do j=1,maxdim
479 minvar(j,mincfig)=j
480 enddo
481 jgrid=j-1
482
483=== modified file 'Template/Source/makefile'
484--- Template/Source/makefile 2010-12-19 04:12:16 +0000
485+++ Template/Source/makefile 2011-04-22 01:24:30 +0000
486@@ -1,6 +1,6 @@
487 g77 = g77
488 FFLAGS= -O -ffixed-line-length-132
489-#FFLAGS= -O
490+#FFLAGS= -g -ffixed-line-length-132 -fbounds-check -ffpe-trap=invalid,zero,overflow,underflow,denormal
491 LIBDIR= ../lib/
492 BINDIR= ../bin/
493 PDFDIR= ./PDF/
494
495=== added file 'Template/Source/maxparticles.inc'
496--- Template/Source/maxparticles.inc 1970-01-01 00:00:00 +0000
497+++ Template/Source/maxparticles.inc 2011-04-22 01:24:30 +0000
498@@ -0,0 +1,2 @@
499+ integer max_particles
500+ parameter (max_particles=10)
501
502=== modified file 'Template/Source/run_config.inc'
503--- Template/Source/run_config.inc 2010-12-19 04:12:16 +0000
504+++ Template/Source/run_config.inc 2011-04-22 01:24:30 +0000
505@@ -9,18 +9,18 @@
506 integer icomp
507 parameter (icomp = 3) !BW + Symmetry compression 0 == none
508 integer min_events_subprocess !Minimum number of events
509- parameter (min_events_subprocess = 2000) !per iteration in each subprocess
510+ parameter (min_events_subprocess = 1000) !per iteration in each subprocess
511 integer min_events_channel !Minimum number of events
512 parameter (min_events_channel = 1000) !per iteration in each channel
513 integer iter_survey !Number of iterations for survey
514- parameter (iter_survey=4)
515+ parameter (iter_survey=3)
516 integer nhel_survey !Number of helicities to sum for each
517 parameter (nhel_survey=1) !phase space point. (0 = sum_all)
518 c
519 c The following parameters are used by gen_ximprove.f in running refine
520 c
521 integer min_events !Minimum number of events/iteration
522- parameter (min_events = 2000) !to refine a channel
523+ parameter (min_events = 1000) !to refine a channel
524 integer max_events !Maximum number of events/iteration
525 parameter (max_events = 2000) !to refine a channel
526 integer max_iter !Maximum number of iterations
527@@ -51,6 +51,6 @@
528 double precision acc_wu
529 parameter (acc_wu = 0.01) !Desired accuracy from warmup run
530 integer npoints_wu, itmax_wu !warmup # points/iterations
531- parameter (npoints_wu = 4000, itmax_wu = 8)
532+ parameter (npoints_wu = 2000, itmax_wu = 8)
533 integer min_gevents_wu
534 parameter (min_gevents_wu=1000) !Minumum # unweighted events to generate from channel
535
536=== modified file 'Template/Source/setrun.f'
537--- Template/Source/setrun.f 2010-12-21 00:56:27 +0000
538+++ Template/Source/setrun.f 2011-04-22 01:24:30 +0000
539@@ -87,6 +87,12 @@
540 call get_integer (npara,param,value,"maxjetflavor",maxjetflavor,4)
541
542 c*********************************************************************
543+c cut on decay products (pt/e/eta/dr/mij) or not
544+c*********************************************************************
545+
546+ call get_logical (npara,param,value,"cut_decays",cut_decays,.true.)
547+
548+c*********************************************************************
549 c Minimum pt's *
550 c*********************************************************************
551
552
553=== modified file 'Template/Source/sum_html.f'
554--- Template/Source/sum_html.f 2011-03-23 21:27:45 +0000
555+++ Template/Source/sum_html.f 2011-04-22 01:24:30 +0000
556@@ -7,6 +7,7 @@
557 c
558 c Constants
559 c
560+ include 'maxparticles.inc'
561 character*(*) subfile
562 parameter (subfile='subproc.mg')
563 character*(*) symfile
564@@ -14,7 +15,7 @@
565 character*(*) rfile
566 parameter (rfile='results.dat')
567 integer max_amps , max_iter
568- parameter (max_amps=9999, max_iter=50)
569+ parameter (max_amps=9999, max_iter=50)
570 c
571 c local
572 c
573@@ -34,8 +35,8 @@
574 integer icor(max_amps)
575 integer nunwgt(max_amps)
576 integer minit
577- character*100 fname, pname
578- character*120 linkname(max_amps)
579+ character*300 fname, pname
580+ character*320 linkname(max_amps)
581 integer i,j,k,l
582 double precision xtot,errtot,err_goal, xi
583 double precision errtotc, errtotu
584@@ -44,6 +45,8 @@
585 integer ntevents, ntw
586 integer ilen
587 logical errex
588+ integer ncode,npos
589+ character*20 formstr
590
591 logical sumproc
592 common/to_sumproc/sumproc
593@@ -70,6 +73,8 @@
594 ntevents = 0
595 ntw = 0
596 i = 0
597+c ncode is number of digits needed for the bw coding
598+ ncode=int(dlog10(3d0)*(max_particles-3))+1
599 do while (.true.)
600 if (sumproc) then
601 j = 1
602@@ -84,38 +89,22 @@
603 read(15,*,err=99,end=99) xi,j
604 if (j .gt. 0) then
605 i=i+1
606- if ( (xi-int(xi+.01)) .lt. 1d-5) then
607- k = int(xi+.01)
608- if (k .lt. 10) then
609- write(fname,'(a,i1,a,a)') 'G',k,'/',rfile
610- write(linkname(i),'(a,i1,a,a)') 'G',k,'/','log.txt'
611- else if (k .lt. 100) then
612- write(fname,'(a,i2,a,a)') 'G',k,'/',rfile
613- write(linkname(i),'(a,i2,a,a)') 'G',k,'/','log.txt'
614- else if (k .lt. 1000) then
615- write(fname,'(a,i3,a,a)') 'G',k,'/',rfile
616- write(linkname(i),'(a,i3,a,a)') 'G',k,'/','log.txt'
617- else if (k .lt. 10000) then
618- write(fname,'(a,i4,a,a)') 'G',k,'/',rfile
619- write(linkname(i),'(a,i4,a,a)') 'G',k,'/','log.txt'
620- endif
621- else
622- if (xi .lt. 10) then
623- write(fname,'(a,f5.3,a,a)') 'G',xi,'/',rfile
624- write(linkname(i),'(a,f5.3,a,a)') 'G',xi,'/','log.txt'
625- else if (xi .lt. 100) then
626- write(fname,'(a,f6.3,a,a)') 'G',xi,'/',rfile
627- write(linkname(i),'(a,f6.3,a,a)') 'G',xi,'/','log.txt'
628- else if (xi .lt. 1000) then
629- write(fname,'(a,f7.3,a,a)') 'G',xi,'/',rfile
630- write(linkname(i),'(a,f7.3,a,a)') 'G',xi,'/','log.txt'
631- else if (xi .lt. 10000) then
632- write(fname,'(a,f8.3,a,a)') 'G',xi,'/',rfile
633- write(linkname(i),'(a,f8.3,a,a)') 'G',xi,'/','log.txt'
634+ k = int(xi*(1+10**-ncode))
635+ npos=int(dlog10(dble(k)))+1
636+ if ( (xi-k) .eq. 0) then
637+c Write with correct number of digits
638+ write(formstr,'(a,i1,a)') '(a,i',npos,',a,a)'
639+ write(fname, formstr) 'G',k,'/',rfile
640+ write(linkname(i),formstr) 'G',k,'/','log.txt'
641+ else !Handle B.W.
642+c Write with correct number of digits
643+ write(formstr,'(a,i1,a,i1,a)') '(a,f',npos+ncode+1,
644+ $ '.',ncode,',a,a)'
645+ write(fname, formstr) 'G',xi,'/',rfile
646+ write(linkname(i),formstr) 'G',xi,'/','log.txt'
647 endif
648 c write(*,*) 'log name ',fname
649 endif
650- endif
651 endif
652
653
654@@ -139,7 +128,7 @@
655 ntw=ntw+nw(i)
656 c maxit = min(maxit,2)
657 if (sumproc) then
658- write(*,'(a20,e15.5)') pname(2:ilen), xsec(i)
659+ write(*,'(a,e15.5)') pname(2:ilen), xsec(i)
660 else
661 write(*,*) fname,i,xsec(i),mfact(i)
662 endif
663@@ -320,7 +309,7 @@
664 integer nsubproc !Number of specific processes requested
665 logical found
666 integer ig
667- character*120 linkname(max_amps)
668+ character*320 linkname(max_amps)
669 integer sname(256)
670 integer gname
671 c
672@@ -328,7 +317,7 @@
673 c
674 integer i,j,k, io(max_amps), ik
675 integer ntot, ip,jp
676- character*100 procname
677+ character*300 procname
678 character*4 cpref
679 character*20 fnamel, fnamee
680 double precision scale,xt(max_amps), teff
681@@ -445,7 +434,7 @@
682 if (sumproc) then
683 nsubproc=0
684 do i=1,ng
685- procname = linkname(io(i))(:100)
686+ procname = linkname(io(i))(:300)
687 gname=0
688 read(procname(2:index(procname,'_')-1),*,err=20) gname
689 20 found = .false.
690@@ -488,22 +477,6 @@
691 c Create directory names using the linkname
692 c
693 c
694- if (.false.) then
695- if (io(i) .lt. 10) then
696- write(fnamel,'(a,i1,a,a)') 'G',io(i),'/',logfile
697- write(fnamee,'(a,i1,a,a)') 'G',io(i),'/',eventfile
698- else if (io(i) .lt. 100) then
699- write(fnamel,'(a,i2,a,a)') 'G',io(i),'/',logfile
700- write(fnamee,'(a,i2,a,a)') 'G',io(i),'/',eventfile
701- else if (io(i) .lt. 1000) then
702- write(fnamel,'(a,i3,a,a)') 'G',io(i),'/',logfile
703- write(fnamee,'(a,i3,a,a)') 'G',io(i),'/',eventfile
704- else if (io(i) .lt. 10000) then
705- write(fnamel,'(a,i4,a,a)') 'G',io(i),'/',logfile
706- write(fnamee,'(a,i4,a,a)') 'G',io(i),'/',eventfile
707- endif
708- endif
709-
710 ik = index(linkname(io(i)),'log.txt')-1
711 fnamel = linkname(io(i))(1:ik) // logfile
712 fnamee = linkname(io(i))(1:ik) // eventfile
713@@ -523,7 +496,7 @@
714 $ xlum(io(i))/scale,'</td></tr>'
715 c write(*,*) io(i),xmax(io(i))
716 else
717- procname = linkname(io(i))(:100)
718+ procname = linkname(io(i))(:300)
719 cxx tjs 3-20-2006 + cfax 12.05.2006
720 c ip = index(procname,'P')+2 !Strip off first P_
721 ip = index(procname,'P')+1 !Strip off first P
722
723=== modified file 'Template/SubProcesses/cluster.f'
724--- Template/SubProcesses/cluster.f 2011-04-03 22:06:00 +0000
725+++ Template/SubProcesses/cluster.f 2011-04-22 01:24:30 +0000
726@@ -376,8 +376,8 @@
727
728 logical OnBW(-nexternal:0) !Set if event is on B.W.
729 common/to_BWEvents/ OnBW
730- integer mincfig, maxcfig
731- common/to_configs/mincfig, maxcfig
732+ integer mapconfig(0:lmaxconfigs), this_config
733+ common/to_mconfigs/mapconfig, this_config
734 C $B$ IFOREST $B$ !this is a tag for MadWeight
735 integer i, iforest(2,-max_branch:-1,lmaxconfigs)
736 common/to_forest/ iforest
737@@ -405,8 +405,8 @@
738 enddo
739 ibw=0
740 do i=-1,-(nexternal-3),-1
741- icl(i)=icl(iforest(1,i,mincfig))+
742- $ icl(iforest(2,i,mincfig))
743+ icl(i)=icl(iforest(1,i,this_config))+
744+ $ icl(iforest(2,i,this_config))
745 isbw(icl(i))=.false.
746 C $B$ ONBW $B$ !this is a tag for MadWeight
747 if(OnBW(i))then
748@@ -414,7 +414,7 @@
749 ibw=ibw+1
750 ibwlist(ibw)=icl(i)
751 isbw(icl(i))=.true.
752-c print *,'Added BW for resonance ',i,icl(i),mincfig
753+c print *,'Added BW for resonance ',i,icl(i),this_config
754 if(ibw.eq.nbw) return
755 endif
756 enddo
757
758=== modified file 'Template/SubProcesses/cuts.f'
759--- Template/SubProcesses/cuts.f 2011-04-13 01:05:26 +0000
760+++ Template/SubProcesses/cuts.f 2011-04-22 01:24:30 +0000
761@@ -54,6 +54,7 @@
762 integer i,j,njets,hardj1,hardj2
763 REAL*8 XVAR,ptmax1,ptmax2,htj,tmp
764 real*8 ptemp(0:3)
765+ character*20 formstr
766 C
767 C PARAMETERS
768 C
769@@ -135,12 +136,16 @@
770 call initcluster()
771 c
772 c
773- write(*,'(a10,10i8)') 'Particle',(i,i=nincoming+1,nexternal)
774- write(*,'(a10,10f8.1)') 'Et >',(etmin(i),i=nincoming+1,nexternal)
775- write(*,'(a10,10f8.1)') 'E >',(emin(i),i=nincoming+1,nexternal)
776- write(*,'(a10,10f8.1)') 'Eta <',(etamax(i),i=nincoming+1,nexternal)
777+ write(formstr,'(a,i2.2,a)')'(a10,',nexternal,'i8)'
778+ write(*,formstr) 'Particle',(i,i=nincoming+1,nexternal)
779+ write(formstr,'(a,i2.2,a)')'(a10,',nexternal,'f8.1)'
780+ write(*,formstr) 'Et >',(etmin(i),i=nincoming+1,nexternal)
781+ write(*,formstr) 'E >',(emin(i),i=nincoming+1,nexternal)
782+ write(*,formstr) 'Eta <',(etamax(i),i=nincoming+1,nexternal)
783+ write(*,formstr) 'xqcut: ',(xqcuti(i),i=nincoming+1,nexternal)
784+ write(formstr,'(a,i2.2,a)')'(a,i2,a,',nexternal,'f8.1)'
785 do j=nincoming+1,nexternal-1
786- write(*,'(a,i2,a,10f8.1)') 'd R #',j,' >',(-0.0,i=nincoming+1,j),
787+ write(*,formstr) 'd R #',j,' >',(-0.0,i=nincoming+1,j),
788 & (r2min(i,j),i=j+1,nexternal)
789 do i=j+1,nexternal
790 r2min(i,j)=r2min(i,j)*dabs(r2min(i,j)) !Since r2 returns distance squared
791@@ -148,12 +153,11 @@
792 enddo
793 enddo
794 do j=nincoming+1,nexternal-1
795- write(*,'(a,i2,a,10f8.1)') 's min #',j,'>',
796+ write(*,formstr) 's min #',j,'>',
797 & (s_min(i,j),i=nincoming+1,nexternal)
798 enddo
799- write(*,'(a10,10f8.1)') 'xqcut: ',(xqcuti(i),i=nincoming+1,nexternal)
800 do j=nincoming+1,nexternal-1
801- write(*,'(a,i2,a,10f8.1)') 'xqcutij #',j,'>',
802+ write(*,formstr) 'xqcutij #',j,'>',
803 & (xqcutij(i,j),i=nincoming+1,nexternal)
804 enddo
805
806
807=== modified file 'Template/SubProcesses/driver.f'
808--- Template/SubProcesses/driver.f 2011-04-03 22:06:00 +0000
809+++ Template/SubProcesses/driver.f 2011-04-22 01:24:30 +0000
810@@ -31,8 +31,6 @@
811 common /sample_status/result_file,where_file,nsteps
812 integer Minvar(maxdim,lmaxconfigs)
813 common /to_invar/ Minvar
814- real*8 dsigtot(10)
815- common/to_dsig/ dsigtot
816 integer ngroup
817 common/to_group/ngroup
818 data ngroup/0/
819@@ -177,14 +175,15 @@
820 c Constants
821 c
822 include 'nexternal.inc'
823+ include 'maxparticles.inc'
824 c
825 c Arguments
826 c
827- integer ncall,itmax,iconfig, jconfig
828+ integer ncall,itmax,iconfig
829 c
830 c Local
831 c
832- integer i, j
833+ integer i, j, jconfig, ncode
834 double precision dconfig
835 c
836 c Global
837@@ -239,7 +238,9 @@
838
839 write(*,10) 'Enter Configuration Number: '
840 read(*,*) dconfig
841- iconfig = int(dconfig)
842+c ncode is number of digits needed for the BW code
843+ ncode=int(dlog10(3d0)*(max_particles-3))+1
844+ iconfig = int(dconfig*(1+10**-ncode))
845 write(*,12) 'Running Configuration Number: ',iconfig
846 c
847 c Here I want to set up with B.W. we map and which we don't
848@@ -250,7 +251,7 @@
849 lbw(0)=0
850 else
851 lbw(0)=1
852- jconfig=dconfig*1000.1
853+ jconfig=dconfig*(10**ncode + 0.1)
854 write(*,*) 'Using dconfig=',jconfig
855 call DeCode(jconfig,lbw(1),3,nexternal)
856 write(*,*) 'BW Setting ', (lbw(j),j=1,nexternal-2)
857
858=== modified file 'Template/SubProcesses/makefile'
859--- Template/SubProcesses/makefile 2010-11-25 00:43:00 +0000
860+++ Template/SubProcesses/makefile 2011-04-22 01:24:30 +0000
861@@ -1,6 +1,6 @@
862 g77 = g77
863-FFLAGS= -O -ffixed-line-length-132
864-#FFLAGS = -g -ffixed-line-length-132
865+FFLAGS= -O -w -ffixed-line-length-132
866+#FFLAGS = -g -ffixed-line-length-132 -fbounds-check -ffpe-trap=invalid,zero,overflow,underflow,denormal
867 LIBDIR = ../../lib/
868 BINDIR = ../../bin/
869 # $B$ obj_for_MW $B$ !this is a tag for MadWeight. Don't edit this line
870
871=== modified file 'Template/SubProcesses/myamp.f'
872--- Template/SubProcesses/myamp.f 2011-04-03 22:06:00 +0000
873+++ Template/SubProcesses/myamp.f 2011-04-22 01:24:30 +0000
874@@ -215,32 +215,38 @@
875 idenpart=0
876 do j=1,2
877 ida(j)=iforest(j,i,iconfig)
878- if((ida(j).lt.0.and.sprop(i,iconfig).eq.sprop(ida(j),iconfig))
879- $ .or.(ida(j).gt.0.and.sprop(i,iconfig).eq.IDUP(ida(j),1,1)))
880- $ idenpart=ida(j)
881+ if(ida(j).lt.0) then
882+ if(sprop(i,iconfig).eq.sprop(ida(j),iconfig))
883+ $ idenpart=ida(j)
884+ elseif (ida(j).gt.0) then
885+ if(sprop(i,iconfig).eq.IDUP(ida(j),1,1))
886+ $ idenpart=ida(j)
887+ endif
888 enddo
889 c Always remove if daughter final-state
890 if(idenpart.gt.0) then
891 OnBW(i)=.false.
892 c Else remove if daughter forced to be onshell
893- elseif(idenpart.lt.0.and.gForceBW(idenpart, iconfig)) then
894- OnBW(i)=.false.
895+ elseif(idenpart.lt.0)then
896+ if(gForceBW(idenpart, iconfig)) then
897+ OnBW(i)=.false.
898 c Else remove daughter if forced to be onshell
899- elseif(idenpart.lt.0.and.gForceBW(i, iconfig)) then
900- OnBW(idenpart)=.false.
901+ elseif(gForceBW(i, iconfig)) then
902+ OnBW(idenpart)=.false.
903 c Else remove either this resonance or daughter, which is closer to mass shell
904- elseif(idenpart.lt.0.and.abs(xmass-pmass(i,iconfig)).gt.
905- $ abs(sqrt(dot(xp(0,idenpart),xp(0,idenpart)))-
906- $ pmass(i,iconfig))) then
907- OnBW(i)=.false.
908+ elseif(abs(xmass-pmass(i,iconfig)).gt.
909+ $ abs(sqrt(dot(xp(0,idenpart),xp(0,idenpart)))-
910+ $ pmass(i,iconfig))) then
911+ OnBW(i)=.false.
912 c Else remove OnBW for daughter
913- else if(idenpart.lt.0) then
914- OnBW(idenpart)=.false.
915+ else
916+ OnBW(idenpart)=.false.
917+ endif
918 endif
919 endif
920 if (onshell .and. (lbw(nbw).eq. 2) ) cut_bw=.true.
921 if (.not. onshell .and. (lbw(nbw).eq. 1)) cut_bw=.true.
922-c write(*,*) nbw,xmass,onshell,lbw(nbw),cut_bw
923+c write(*,*) 'cut_bw: ',nbw,xmass,onshell,lbw(nbw),cut_bw
924 endif
925
926 enddo
927@@ -286,6 +292,9 @@
928
929 logical gForceBW(-max_branch:-1,lmaxconfigs) ! Forced BW
930 include 'decayBW.inc'
931+
932+ double precision forced_mass
933+ data forced_mass/0d0/
934 c
935 c Global
936 c
937@@ -318,7 +327,7 @@
938
939 integer lbw(0:nexternal) !Use of B.W.
940 common /to_BW/ lbw
941-
942+
943 include 'coupl.inc'
944
945 c
946@@ -351,7 +360,7 @@
947 tsgn = +1d0
948 c Reset variables
949 nbw = 0
950- do i=1,nexternal
951+ do i=1,nexternal-2
952 iden_part(-i)=0
953 spole(i)=0
954 swidth(i)=0
955@@ -359,22 +368,28 @@
956 do i=-1,-(nexternal-3),-1 !Find all the propagotors
957 c JA 3/31/11 Keep track of identical particles (i.e., radiation vertices)
958 c by tracing the particle identity from the external particle.
959- if(iforest(1,i,iconfig).gt.0.and.
960- $ sprop(i,iconfig).eq.idup(iforest(1,i,iconfig),1,1).or.
961- $ iforest(2,i,iconfig).gt.0.and.
962- $ sprop(i,iconfig).eq.idup(iforest(2,i,iconfig),1,1).or.
963- $ iforest(1,i,iconfig).lt.0.and.
964- $ (iden_part(iforest(1,i,iconfig)).ne.0.and.
965+ if(iforest(1,i,iconfig).gt.0) then
966+ if (sprop(i,iconfig).eq.idup(iforest(1,i,iconfig),1,1))
967+ $ iden_part(i) = sprop(i,iconfig)
968+ endif
969+ if(iforest(2,i,iconfig).gt.0) then
970+ if(sprop(i,iconfig).eq.idup(iforest(2,i,iconfig),1,1))
971+ $ iden_part(i) = sprop(i,iconfig)
972+ endif
973+ if(iforest(1,i,iconfig).lt.0) then
974+ if((iden_part(iforest(1,i,iconfig)).ne.0.and.
975 $ sprop(i,iconfig).eq.iden_part(iforest(1,i,iconfig)) .or.
976 $ gforcebw(iforest(1,i,iconfig),iconfig).and.
977- $ sprop(i,iconfig).eq.sprop(iforest(1,i,iconfig),iconfig)).or.
978- $ iforest(2,i,iconfig).lt.0.and.
979- $ (iden_part(iforest(2,i,iconfig)).ne.0.and.
980+ $ sprop(i,iconfig).eq.sprop(iforest(1,i,iconfig),iconfig)))
981+ $ iden_part(i) = sprop(i,iconfig)
982+ endif
983+ if(iforest(2,i,iconfig).lt.0) then
984+ if((iden_part(iforest(2,i,iconfig)).ne.0.and.
985 $ sprop(i,iconfig).eq.iden_part(iforest(2,i,iconfig)).or.
986 $ gforcebw(iforest(2,i,iconfig),iconfig).and.
987- $ sprop(i,iconfig).eq.sprop(iforest(2,i,iconfig),iconfig)))then
988- iden_part(i) = sprop(i,iconfig)
989- endif
990+ $ sprop(i,iconfig).eq.sprop(iforest(2,i,iconfig),iconfig)))
991+ $ iden_part(i) = sprop(i,iconfig)
992+ endif
993 if (iforest(1,i,iconfig) .eq. 1) tsgn=-1d0
994 if (tsgn .eq. 1d0) then !s channel
995 xm(i) = xm(iforest(1,i,iconfig))+xm(iforest(2,i,iconfig))
996@@ -418,6 +433,9 @@
997 spole(-i)=pmass(i,iconfig)*pmass(i,iconfig)/stot
998 swidth(-i) = pwidth(i,iconfig)*pmass(i,iconfig)/stot
999 xm(i) = pmass(i,iconfig)
1000+c Remember largest BW mass for better grid setting
1001+ forced_mass = max(forced_mass,
1002+ $ pmass(i,iconfig)-bwcutoff*pwidth(i,iconfig))
1003 c RF & TJS, should start from final state particle masses, not only at resonance.
1004 c Therefore remove the next line.
1005 c xe(i) = max(xe(i),xm(i))
1006@@ -474,7 +492,8 @@
1007
1008 xo = min(x1,x2)
1009
1010- xo = xo*xo/stot
1011+c Use 1/10000 of sqrt(s) as minimum, to always get integration
1012+ xo = max(xo*xo/stot,1e-8)
1013 a=-pmass(i,iconfig)**2/stot
1014 c call setgrid(-i,xo,a,pow(i,iconfig))
1015
1016@@ -485,8 +504,8 @@
1017 endif
1018 enddo
1019 if (abs(lpp(1)) .eq. 1 .or. abs(lpp(2)) .eq. 1) then
1020- write(*,*) 'etot',etot,nexternal
1021- xo = etot**2/stot
1022+c Set minimum based on: 1) required energy 2) resonances 3) 1/10000 of sqrt(s)
1023+ xo = max(max(etot**2, forced_mass**2)/stot,1e-8)
1024 i = 3*(nexternal-2) - 4 + 1
1025 c-----------------------
1026 c tjs 4/29/2008 use analytic transform for s-hat
1027
1028=== modified file 'Template/SubProcesses/reweight.f'
1029--- Template/SubProcesses/reweight.f 2011-04-03 22:06:00 +0000
1030+++ Template/SubProcesses/reweight.f 2011-04-22 01:24:30 +0000
1031@@ -373,10 +373,11 @@
1032 integer idfl, idmap(-nexternal:nexternal)
1033 integer ipart(2,n_max_cl)
1034 double precision xnow(2)
1035- integer jlast(2),jfirst(2)
1036+ integer jlast(2),jfirst(2),nwarning
1037 logical qcdline(2),qcdrad(2)
1038 logical failed,first
1039 data first/.true./
1040+ data nwarning/0/
1041
1042 logical isqcd,isjet,isparton,isjetvx,cluster
1043 double precision alphas
1044@@ -585,6 +586,22 @@
1045 $ q2fact(2)=pt2ijcl(nexternal-2)
1046 endif
1047
1048+c Check that factorization scale is >= 2 GeV
1049+ if(lpp(1).ne.0.and.q2fact(1).lt.4d0.or.
1050+ $ lpp(2).ne.0.and.q2fact(2).lt.4d0)then
1051+ if(nwarning.le.10) then
1052+ nwarning=nwarning+1
1053+ write(*,*) 'Warning: Too low fact scales: ',
1054+ $ sqrt(q2fact(1)), sqrt(q2fact(2))
1055+ endif
1056+ if(nwarning.eq.11) then
1057+ nwarning=nwarning+1
1058+ write(*,*) 'No more warnings written out this run.'
1059+ endif
1060+ setclscales=.false.
1061+ return
1062+ endif
1063+
1064 if (btest(mlevel,3))
1065 $ write(*,*) 'Set fact scales to ',sqrt(q2fact(1)),sqrt(q2fact(2))
1066 return
1067
1068=== modified file 'Template/SubProcesses/setcuts.f'
1069--- Template/SubProcesses/setcuts.f 2011-04-03 22:06:00 +0000
1070+++ Template/SubProcesses/setcuts.f 2011-04-22 01:24:30 +0000
1071@@ -28,6 +28,7 @@
1072 logical do_cuts(nexternal)
1073 integer ncheck
1074 logical done,fopened
1075+ logical from_decay(-(nexternal+3):nexternal)
1076 C
1077 C GLOBAL
1078 C
1079@@ -109,7 +110,7 @@
1080 endif
1081 c
1082 c set ptj and s_min if xqcut and ktscheme = 1, to improve
1083-c integration speed, and set drjj to 0.
1084+c integration speed, and set drjj and drjl to 0.
1085 c
1086 if(xqcut.gt.0.and.ktscheme.eq.1) then
1087 if(ptj.ge.0d0) ptj=max(ptj, xqcut)
1088@@ -120,14 +121,23 @@
1089 write(*,*) 'Warning! drjj > 0 with xqcut > 0, set to 0'
1090 drjj = 0d0
1091 endif
1092+ if(drjl.gt.0d0) then
1093+ write(*,*) 'Warning! drjl > 0 with xqcut > 0, set to 0'
1094+ drjl = 0d0
1095+ endif
1096 endif
1097
1098+c Check which particles come from decays
1099+ if(.not.cut_decays)
1100+ $ call check_decay(from_decay)
1101+
1102 c
1103 c check if I have to apply cuts on the particles
1104 c
1105 do i=nincoming+1,nexternal
1106 do_cuts(i)=.true.
1107 if(nincoming.eq.1) do_cuts(i)=.false.
1108+ if(.not.cut_decays.and.from_decay(i)) do_cuts(i)=.false.
1109 is_a_j(i)=.false.
1110 is_a_l(i)=.false.
1111 is_a_b(i)=.false.
1112@@ -518,3 +528,50 @@
1113
1114 end
1115
1116+
1117+c************************************************************************
1118+c Subroutine to check which external particles are from decays
1119+c************************************************************************
1120+ subroutine check_decay(from_decay)
1121+ implicit none
1122+
1123+ include 'nexternal.inc'
1124+ include 'maxconfigs.inc'
1125+ include 'genps.inc'
1126+c
1127+c Arguments
1128+c
1129+ logical from_decay(-(nexternal+3):nexternal)
1130+c
1131+c Global
1132+c
1133+ integer iforest(2,-max_branch:-1,lmaxconfigs)
1134+ common/to_forest/ iforest
1135+ integer sprop(-max_branch:-1,lmaxconfigs)
1136+ integer tprid(-max_branch:-1,lmaxconfigs)
1137+ common/to_sprop/sprop,tprid
1138+ logical gForceBW(-max_branch:-1,lmaxconfigs) ! Forced BW
1139+ include 'decayBW.inc'
1140+
1141+c
1142+c Local
1143+c
1144+ integer i,j
1145+
1146+ do i=-(nexternal-3),nexternal
1147+ from_decay(i)=.false.
1148+ enddo
1149+
1150+c Set who comes from decay based on forced BW
1151+ do i=-(nexternal-3),-1
1152+ if(tprid(i,1).eq.0.and.gForceBW(i,1).or.
1153+ $ from_decay(i)) then
1154+ do j=i,-1
1155+ from_decay(j)=.true.
1156+ from_decay(iforest(1,j,1))=.true.
1157+ from_decay(iforest(2,j,1))=.true.
1158+ enddo
1159+ endif
1160+ enddo
1161+
1162+ end
1163
1164=== modified file 'Template/SubProcesses/symmetry.f'
1165--- Template/SubProcesses/symmetry.f 2011-04-08 00:33:38 +0000
1166+++ Template/SubProcesses/symmetry.f 2011-04-22 01:24:30 +0000
1167@@ -164,7 +164,8 @@
1168 c Local
1169 c
1170 character*30 fname
1171- integer ic
1172+ integer ic, npos
1173+ character*10 formstr
1174
1175 data ic/0/
1176 c-----
1177@@ -172,13 +173,10 @@
1178 c-----
1179 ic=ic+1
1180 fname='ajob'
1181- if (ic .lt. 10) then
1182- write(fname(5:5),'(i1)') ic
1183- elseif (ic .lt. 100) then
1184- write(fname(5:6),'(i2)') ic
1185- elseif (ic .lt. 1000) then
1186- write(fname(5:7),'(i3)') ic
1187- endif
1188+c Write ic with correct number of digits
1189+ npos=int(dlog10(dble(ic)))+1
1190+ write(formstr,'(a,i1,a)') '(I',npos,')'
1191+ write(fname(5:(5+npos-1)),formstr) ic
1192 open (unit=lun, file = fname, status='unknown')
1193 write(lun,15) '#!/bin/bash'
1194 write(lun,15) '#PBS -q ' // PBS_QUE
1195@@ -226,6 +224,9 @@
1196 c local
1197 c
1198 integer i, j, nbw, ic, icode
1199+ integer ncode, nconf
1200+ double precision dconfig
1201+ character*10 formstr
1202 integer iarray(imax)
1203 logical lconflict(-max_branch:nexternal)
1204 logical done
1205@@ -237,6 +238,8 @@
1206 c-----
1207 call open_bash_file(26)
1208 ic = 0
1209+c ncode is number of digits needed for the code
1210+ ncode=int(dlog10(3d0)*(max_particles-3))+1
1211 do i=1,mapconfig(0)
1212 if (use_config(i) .gt. 0) then
1213 call bw_conflict(i,iforest(1,-max_branch,i),lconflict,
1214@@ -273,26 +276,17 @@
1215 ic = 1
1216 endif
1217 c write(*,*) 'mapping',ic,mapconfig(i)
1218- if (mapconfig(i) .lt. 10) then
1219- write(26,'(i1$)') mapconfig(i)
1220- elseif (mapconfig(i) .lt. 100) then
1221- write(26,'(i2$)') mapconfig(i)
1222- elseif (mapconfig(i) .lt. 1000) then
1223- write(26,'(i3$)') mapconfig(i)
1224- elseif (mapconfig(i) .lt. 10000) then
1225- write(26,'(i4$)') mapconfig(i)
1226- endif
1227+ nconf=int(dlog10(dble(mapconfig(i))))+1
1228 if (icode .eq. 0) then
1229-c write(26,'($a)') '.000'
1230- elseif (icode .lt. 10) then
1231- write(26,'(a,i1$)') '.00', icode
1232- elseif (icode .lt. 100) then
1233- write(26,'(a,i2$)') '.0', icode
1234- elseif (icode .lt. 1000) then
1235- write(26,'(a,i3$)') '.', icode
1236+c Create format string based on number of digits
1237+ write(formstr,'(a,i1,a)') '(I',nconf,'$)'
1238+ write(26,formstr) mapconfig(i)
1239 else
1240- write(*,*) 'Error too many B.W. in symmetry.f',icode
1241- stop
1242+c Create format string based on number of digits
1243+ dconfig=mapconfig(i)+icode*1d0/10**ncode
1244+ write(formstr,'(a,i1,a,i1,a)') '(F',nconf+ncode+1,
1245+ $ '.',ncode,'$)'
1246+ write(26,formstr) dconfig
1247 endif
1248 write(26,'(a$)') ' '
1249 call bw_increment_array(iarray,imax,ibase,gForceBW(-imax,i),done)
1250@@ -300,8 +294,8 @@
1251 endif
1252 enddo
1253 call close_bash_file(26)
1254- if (mapconfig(0) .gt. 9999) then
1255- write(*,*) 'Only writing first 9999 jobs',mapconfig(0)
1256+ if (mapconfig(0) .gt. 99999) then
1257+ write(*,*) 'Only writing first 99999 jobs',mapconfig(0)
1258 endif
1259 c
1260 c Now write out the symmetry factors for each graph
1261@@ -337,8 +331,11 @@
1262 do while (.not. done)
1263 call enCode(icode,iarray,ibase,imax)
1264 if (icode .gt. 0) then
1265- write(26,'(f9.3,i6)') mapconfig(i)+real(icode)/1000.,
1266- $ use_config(i)
1267+ nconf=int(dlog10(dble(mapconfig(i))))+1
1268+ write(formstr,'(a,i1,a,i1,a)') '(F',nconf+ncode+1,
1269+ $ '.',ncode,',i6)'
1270+ dconfig=mapconfig(i)+icode*1d0/10**ncode
1271+ write(26,formstr) dconfig,use_config(i)
1272 else
1273 write(26,'(2i6)') mapconfig(i),use_config(i)
1274 endif
1275@@ -401,6 +398,8 @@
1276 c
1277 do i=1,nexternal
1278 xmass(i) = 0d0
1279+ enddo
1280+ do i=1,nexternal-1
1281 lconflict(-i) = .false.
1282 iden_part(-i)=0
1283 enddo
1284@@ -414,19 +413,27 @@
1285 if (pwidth(-i,iconfig) .gt. 0d0) then
1286 c JA 3/31/11 Keep track of identical particles (i.e., radiation vertices)
1287 c by tracing the particle identity from the external particle.
1288- if(itree(1,-i).gt.0.and.
1289- $ sprop(-i).eq.idup(itree(1,-i),1,1).or.
1290- $ itree(2,-i).gt.0.and.
1291- $ sprop(-i).eq.idup(itree(2,-i),1,1).or.
1292- $ itree(1,-i).lt.0.and.(iden_part(itree(1,-i)).ne.0.and.
1293+ if(itree(1,-i).gt.0) then
1294+ if(sprop(-i).eq.idup(itree(1,-i),1,1))
1295+ $ iden_part(-i) = sprop(-i)
1296+ endif
1297+ if(itree(2,-i).gt.0) then
1298+ if(sprop(-i).eq.idup(itree(2,-i),1,1))
1299+ $ iden_part(-i) = sprop(-i)
1300+ endif
1301+ if(itree(1,-i).lt.0) then
1302+ if(iden_part(itree(1,-i)).ne.0.and.
1303 $ sprop(-i).eq.iden_part(itree(1,-i)) .or.
1304 $ forcebw(itree(1,-i)).and.
1305- $ sprop(-i).eq.sprop(itree(1,-i))).or.
1306- $ itree(2,-i).lt.0.and.(iden_part(itree(2,-i)).ne.0.and.
1307+ $ sprop(-i).eq.sprop(itree(1,-i)))
1308+ $ iden_part(-i) = sprop(-i)
1309+ endif
1310+ if(itree(2,-i).lt.0) then
1311+ if(iden_part(itree(2,-i)).ne.0.and.
1312 $ sprop(-i).eq.iden_part(itree(2,-i)).or.
1313 $ forcebw(itree(2,-i)).and.
1314- $ sprop(-i).eq.sprop(itree(2,-i))))then
1315- iden_part(-i) = sprop(-i)
1316+ $ sprop(-i).eq.sprop(itree(2,-i)))
1317+ $ iden_part(-i) = sprop(-i)
1318 endif
1319 if (xmass(-i) .gt. pmass(-i,iconfig) .and.
1320 $ iden_part(-i).eq.0) then !Can't be on shell, and not radiation
1321
1322=== modified file 'Template/SubProcesses/symmetry_v4.f'
1323--- Template/SubProcesses/symmetry_v4.f 2011-04-03 22:06:00 +0000
1324+++ Template/SubProcesses/symmetry_v4.f 2011-04-22 01:24:30 +0000
1325@@ -15,8 +15,6 @@
1326
1327 double precision ZERO
1328 parameter (ZERO = 0d0)
1329- integer maxswitch
1330- parameter(maxswitch=99)
1331 integer lun
1332 parameter (lun=28)
1333 c
1334@@ -26,7 +24,9 @@
1335 integer mapconfig(0:lmaxconfigs)
1336 integer sprop(-max_branch:-1,lmaxconfigs)
1337 integer itree(2,-max_branch:-1)
1338- integer imatch
1339+ integer imatch, nperm
1340+ integer maxswitch
1341+ parameter (maxswitch=10000000)
1342 integer use_config(0:lmaxconfigs)
1343 integer i,j, k, n, nsym
1344 double precision diff
1345@@ -36,11 +36,11 @@
1346 c
1347 c Local for generating amps
1348 c
1349- double precision p(0:3,99), wgt, x(99), fx
1350- double precision p1(0:3,99)
1351+ double precision p(0:3,nexternal), wgt, x(maxinvar), fx
1352+ double precision p1(0:3,nexternal)
1353 integer ninvar, ndim, iconfig, minconfig, maxconfig
1354 integer ncall,itmax,nconfigs,ntry, ngraphs
1355- integer ic(nexternal,maxswitch), jc(12),nswitch
1356+ integer ic(nexternal), jc(12),nswitch
1357 double precision saveamp(maxamps)
1358 integer nmatch, ibase
1359 logical mtc, even
1360@@ -99,10 +99,10 @@
1361 call printout
1362 call run_printout
1363 c
1364- ndim = 22
1365+ ndim = maxdim
1366 ncall = 10000
1367 itmax = 10
1368- ninvar = 35
1369+ ninvar = maxinvar
1370 nconfigs = 1
1371 iconfig=1
1372 include 'props.inc'
1373@@ -149,46 +149,52 @@
1374 c
1375 nswitch = 1
1376 do k=1,nexternal
1377- ic(k,1)=k
1378+ ic(k)=k
1379 enddo
1380 nmatch = 0
1381 mtc=.false.
1382 nsym = 1
1383 write(lun,'(a,i2,a$)') ' data (isym(i,',nsym,'),i=1,nexternal) /1 '
1384 do i=2,nexternal
1385- write(lun,'(a,i2$)') ",",ic(i,1)
1386-c write(*,'(a,i2$)') ",",ic(i,1)
1387+ write(lun,'(a,i2$)') ",",ic(i)
1388+c write(*,'(a,i2$)') ",",ic(i)
1389 enddo
1390 c write(*,*)
1391 write(lun,'(a)') "/"
1392- call nexper(nexternal-2,ic(3,1),mtc,even)
1393-c write(*,*) 'mtc',mtc, (ic(i,1),i=1,nexternal)
1394+ call nexper(nexternal-2,ic(3),mtc,even)
1395+c write(*,*) 'mtc',mtc, (ic(i),i=1,nexternal)
1396+ nperm=0
1397 do while(mtc)
1398- call nexper(nexternal-2,ic(3,1),mtc,even)
1399-c write(*,*) 'mtc',mtc, (ic(i,1),i=1,nexternal)
1400+ nperm=nperm+1
1401+ if (nperm.gt.maxswitch) goto 10
1402+ call nexper(nexternal-2,ic(3),mtc,even)
1403+c write(*,*) 'mtc',mtc, (ic(i),i=1,nexternal)
1404 do j=3,nexternal
1405- ic(j,1)=ic(j,1)+2
1406+ ic(j)=ic(j)+2
1407 enddo
1408- if (mtc) then
1409- CALL SWITCHMOM(P,P1,IC(1,1),JC,NEXTERNAL)
1410+ if (.not.check_swap(ic(1))) then
1411+ do j=3,nexternal
1412+ ic(j)=ic(j)-2
1413+ enddo
1414+ cycle
1415+ endif
1416+ CALL SWITCHMOM(P,P1,IC(1),JC,NEXTERNAL)
1417 c
1418 c Now check if it is a valid swap to make
1419 c
1420-
1421- if (check_swap(ic(1,1))) then
1422- write(*,*) 'Good swap', (ic(i,1),i=1,nexternal)
1423- nsym=nsym+1
1424- write(lun,'(a,i2,a$)') ' data (isym(i,',nsym,'),i=1,nexternal) /1 '
1425- do i=2,nexternal
1426- write(lun,'(a,i2$)') ",",ic(i,1)
1427- enddo
1428- write(lun,'(a)') "/"
1429-
1430- call smatrix(p1,fx)
1431+ write(*,*) 'Good swap', (ic(i),i=1,nexternal)
1432+ nsym=nsym+1
1433+ write(lun,'(a,i2,a$)') ' data (isym(i,',nsym,'),i=1,nexternal) /1 '
1434+ do i=2,nexternal
1435+ write(lun,'(a,i2$)') ",",ic(i)
1436+ enddo
1437+ write(lun,'(a)') "/"
1438+
1439+ call smatrix(p1,fx)
1440 c write(*,*) 'dsig=',fx
1441-c write(*,'(7i6)') i,(ic(k,i),k=1,nexternal)
1442+c write(*,'(7i6)') i,(ic(k),k=1,nexternal)
1443 c do n = i+1,nswitch
1444-c CALL SWITCHMOM(P,P1,IC(1,n),JC,NEXTERNAL)
1445+c CALL SWITCHMOM(P,P1,IC(1),JC,NEXTERNAL)
1446 c call smatrix(p1,fx)
1447 c
1448 c Look for matches, but only for diagrams < current diagram
1449@@ -213,15 +219,11 @@
1450 endif
1451 enddo
1452 enddo
1453- else
1454- write(*,*) 'Bad swap', (ic(i,1),i=1,nexternal)
1455- endif !Good Swap
1456- endif !Real Swap
1457 do j=3,nexternal
1458- ic(j,1)=ic(j,1)-2
1459+ ic(j)=ic(j)-2
1460 enddo
1461 enddo
1462- write(lun,*) ' data nsym /',nsym,'/'
1463+ 10 write(lun,*) ' data nsym /',nsym,'/'
1464 close(lun)
1465 write(*,*) 'Found ',nmatch, ' matches. ',mapconfig(0)-nmatch,
1466 $ ' channels remain for integration.'
1467@@ -396,7 +398,8 @@
1468 c Local
1469 c
1470 character*30 fname
1471- integer ic
1472+ integer ic, npos
1473+ character*10 formstr
1474
1475 data ic/0/
1476 c-----
1477@@ -404,13 +407,10 @@
1478 c-----
1479 ic=ic+1
1480 fname='ajob'
1481- if (ic .lt. 10) then
1482- write(fname(5:5),'(i1)') ic
1483- elseif (ic .lt. 100) then
1484- write(fname(5:6),'(i2)') ic
1485- elseif (ic .lt. 1000) then
1486- write(fname(5:7),'(i3)') ic
1487- endif
1488+c Write ic with correct number of digits
1489+ npos=int(dlog10(dble(ic)))+1
1490+ write(formstr,'(a,i1,a)') '(I',npos,')'
1491+ write(fname(5:(5+npos-1)),formstr) ic
1492 open (unit=lun, file = fname, status='unknown')
1493 write(lun,15) '#!/bin/bash'
1494 write(lun,15) '#PBS -q ' // PBS_QUE
1495@@ -458,6 +458,9 @@
1496 c local
1497 c
1498 integer i, j, nbw, ic, icode
1499+ integer ncode, nconf
1500+ double precision dconfig
1501+ character*10 formstr
1502 integer iarray(imax)
1503 logical lconflict(-max_branch:nexternal)
1504 logical done
1505@@ -469,6 +472,8 @@
1506 c-----
1507 call open_bash_file(26)
1508 ic = 0
1509+c ncode is number of digits needed for the code
1510+ ncode=int(dlog10(3d0)*(max_particles-3))+1
1511 do i=1,mapconfig(0)
1512 if (use_config(i) .gt. 0) then
1513 call bw_conflict(i,iforest(1,-max_branch,i),lconflict,
1514@@ -505,26 +510,17 @@
1515 ic = 1
1516 endif
1517 c write(*,*) 'mapping',ic,mapconfig(i)
1518- if (mapconfig(i) .lt. 10) then
1519- write(26,'(i1$)') mapconfig(i)
1520- elseif (mapconfig(i) .lt. 100) then
1521- write(26,'(i2$)') mapconfig(i)
1522- elseif (mapconfig(i) .lt. 1000) then
1523- write(26,'(i3$)') mapconfig(i)
1524- elseif (mapconfig(i) .lt. 10000) then
1525- write(26,'(i4$)') mapconfig(i)
1526- endif
1527- if (icode .eq. 0) then
1528-c write(26,'($a)') '.000'
1529- elseif (icode .lt. 10) then
1530- write(26,'(a,i1$)') '.00', icode
1531- elseif (icode .lt. 100) then
1532- write(26,'(a,i2$)') '.0', icode
1533- elseif (icode .lt. 1000) then
1534- write(26,'(a,i3$)') '.', icode
1535+ nconf=int(dlog10(dble(mapconfig(i))))+1
1536+ if(icode.eq.0)then
1537+c Create format string based on number of digits
1538+ write(formstr,'(a,i1,a)') '(I',nconf,'$)'
1539+ write(26,formstr) mapconfig(i)
1540 else
1541- write(*,*) 'Error too many B.W. in symmetry.f',icode
1542- stop
1543+c Create format string based on number of digits
1544+ dconfig=mapconfig(i)+icode*1d0/10**ncode
1545+ write(formstr,'(a,i1,a,i1,a)') '(F',nconf+ncode+1,
1546+ $ '.',ncode,'$)'
1547+ write(26,formstr) dconfig
1548 endif
1549 write(26,'(a$)') ' '
1550 call bw_increment_array(iarray,imax,ibase,gForceBW(-imax,i),done)
1551@@ -532,9 +528,6 @@
1552 endif
1553 enddo
1554 call close_bash_file(26)
1555- if (mapconfig(0) .gt. 9999) then
1556- write(*,*) 'Only writing first 9999 jobs',mapconfig(0)
1557- endif
1558 c
1559 c Now write out the symmetry factors for each graph
1560 c
1561@@ -569,8 +562,11 @@
1562 do while (.not. done)
1563 call enCode(icode,iarray,ibase,imax)
1564 if (icode .gt. 0) then
1565- write(26,'(f9.3,i6)') mapconfig(i)+real(icode)/1000.,
1566- $ use_config(i)
1567+ nconf=int(dlog10(dble(mapconfig(i))))+1
1568+ write(formstr,'(a,i1,a,i1,a)') '(F',nconf+ncode+1,
1569+ $ '.',ncode,',i6)'
1570+ dconfig=mapconfig(i)+icode*1d0/10**ncode
1571+ write(26,formstr) dconfig,use_config(i)
1572 else
1573 write(26,'(2i6)') mapconfig(i),use_config(i)
1574 endif
1575@@ -632,6 +628,8 @@
1576 c
1577 do i=1,nexternal
1578 xmass(i) = 0d0
1579+ enddo
1580+ do i=1,nexternal-1
1581 lconflict(-i) = .false.
1582 enddo
1583 c
1584@@ -644,19 +642,27 @@
1585 if (pwidth(-i,iconfig) .gt. 0d0) then
1586 c JA 3/31/11 Keep track of identical particles (i.e., radiation vertices)
1587 c by tracing the particle identity from the external particle.
1588- if(itree(1,-i).gt.0.and.
1589- $ sprop(-i).eq.idup(itree(1,-i),1,1).or.
1590- $ itree(2,-i).gt.0.and.
1591- $ sprop(-i).eq.idup(itree(2,-i),1,1).or.
1592- $ itree(1,-i).lt.0.and.(iden_part(itree(1,-i)).ne.0.and.
1593+ if(itree(1,-i).gt.0) then
1594+ if(sprop(-i).eq.idup(itree(1,-i),1,1))
1595+ $ iden_part(-i) = sprop(-i)
1596+ endif
1597+ if(itree(2,-i).gt.0) then
1598+ if(sprop(-i).eq.idup(itree(2,-i),1,1))
1599+ $ iden_part(-i) = sprop(-i)
1600+ endif
1601+ if(itree(1,-i).lt.0) then
1602+ if(iden_part(itree(1,-i)).ne.0.and.
1603 $ sprop(-i).eq.iden_part(itree(1,-i)) .or.
1604 $ forcebw(itree(1,-i)).and.
1605- $ sprop(-i).eq.sprop(itree(1,-i))).or.
1606- $ itree(2,-i).lt.0.and.(iden_part(itree(2,-i)).ne.0.and.
1607+ $ sprop(-i).eq.sprop(itree(1,-i)))
1608+ $ iden_part(-i) = sprop(-i)
1609+ endif
1610+ if(itree(2,-i).lt.0) then
1611+ if(iden_part(itree(2,-i)).ne.0.and.
1612 $ sprop(-i).eq.iden_part(itree(2,-i)).or.
1613 $ forcebw(itree(2,-i)).and.
1614- $ sprop(-i).eq.sprop(itree(2,-i))))then
1615- iden_part(-i) = sprop(-i)
1616+ $ sprop(-i).eq.sprop(itree(2,-i)))
1617+ $ iden_part(-i) = sprop(-i)
1618 endif
1619 if (xmass(-i) .gt. pmass(-i,iconfig) .and.
1620 $ iden_part(-i).eq.0) then !Can't be on shell, and not radiation
1621
1622=== modified file 'Template/SubProcesses/unwgt.f'
1623--- Template/SubProcesses/unwgt.f 2010-12-03 19:28:13 +0000
1624+++ Template/SubProcesses/unwgt.f 2011-04-22 01:24:30 +0000
1625@@ -391,6 +391,7 @@
1626
1627 double precision sscale,aaqcd,aaqed
1628 integer ievent,npart
1629+ logical flip
1630
1631 real ran1
1632 external ran1
1633@@ -411,7 +412,7 @@
1634 Double Precision amp2(maxamps), jamp2(0:maxflow)
1635 common/to_amps/ amp2, jamp2
1636
1637- character*79 hel_buf
1638+ character*101 hel_buf
1639 common/to_helicity/hel_buf
1640
1641 integer mincfig, maxcfig
1642@@ -501,7 +502,7 @@
1643
1644 c Set helicities
1645 c write(*,*) 'Getting helicity',hel_buf(1:50)
1646- read(hel_buf,'(15i5)') (jpart(7,isym(i, jsym)),i=1,nexternal)
1647+ read(hel_buf,'(20i5)') (jpart(7,isym(i, jsym)),i=1,nexternal)
1648 c write(*,*) 'ihel',jpart(7,1),jpart(7,2)
1649
1650 c Fix ordering of ptclus
1651@@ -513,20 +514,14 @@
1652 enddo
1653
1654 c Check if we have flipped particle 1 and 2, and flip back
1655+ flip = .false.
1656 if (p(3,1).lt.0) then
1657 do j=0,3
1658 pdum(j)=p(j,1)
1659 p(j,1)=p(j,2)
1660 p(j,2)=pdum(j)
1661 enddo
1662- do i=1,7
1663- j=jpart(i,1)
1664- jpart(i,1)=jpart(i,2)
1665- jpart(i,2)=j
1666- enddo
1667- ptcltmp(1)=ptclus(1)
1668- ptclus(1)=ptclus(2)
1669- ptclus(2)=ptcltmp(1)
1670+ flip = .true.
1671 endif
1672
1673 c
1674@@ -556,6 +551,18 @@
1675 call addmothers(ip,jpart,pb,isym,jsym,sscale,aaqcd,aaqed,buff,
1676 $ npart,numproc)
1677
1678+c Need to flip after addmothers, since color might get overwritten
1679+ if (flip) then
1680+ do i=1,7
1681+ j=jpart(i,1)
1682+ jpart(i,1)=jpart(i,2)
1683+ jpart(i,2)=j
1684+ enddo
1685+ ptcltmp(1)=ptclus(1)
1686+ ptclus(1)=ptclus(2)
1687+ ptclus(2)=ptcltmp(1)
1688+ endif
1689+
1690 c
1691 c Write events to lun
1692 c
1693
1694=== modified file 'Template/bin/gen_crossxhtml-pl'
1695--- Template/bin/gen_crossxhtml-pl 2011-04-04 01:05:14 +0000
1696+++ Template/bin/gen_crossxhtml-pl 2011-04-22 01:24:30 +0000
1697@@ -98,7 +98,7 @@
1698 print PAGE "<HTML> <HEAD> \n";
1699
1700 if (-e "RunWeb") {
1701- print PAGE "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"30\" > ";
1702+ print PAGE "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"10\" > ";
1703 }
1704 print PAGE "<META HTTP-EQUIV=\"EXPIRES\" CONTENT=\"20\" > ";
1705 print PAGE "\n <TITLE>Online Event Generation</TITLE></HEAD> \n <BODY>";
1706
1707=== modified file 'Template/bin/generate_events'
1708--- Template/bin/generate_events 2011-04-04 01:05:14 +0000
1709+++ Template/bin/generate_events 2011-04-22 01:24:30 +0000
1710@@ -201,7 +201,6 @@
1711 mv survey refine
1712 $dirbin/gen_crossxhtml-pl $t
1713 $dirbin/refine $a $mode $n 5 $t
1714- #$dirbin/refine 0.01 $mode $n
1715 mv refine refine2
1716 $dirbin/gen_crossxhtml-pl $t
1717 $dirbin/refine $a $mode $n 1 $t
1718
1719=== added file 'UpdateNotes.txt'
1720--- UpdateNotes.txt 1970-01-01 00:00:00 +0000
1721+++ UpdateNotes.txt 2011-04-22 01:24:30 +0000
1722@@ -0,0 +1,36 @@
1723+Update notes for MadGraph 5 (in reverse time order)
1724+
1725+1.1.0 (21/04/11): JA: Removed hard limit on number of external particles in
1726+ MadEvent, allowing for unlimited length decay chains there
1727+ (up to 14 final state particles successfully integrated).
1728+ JA: Improved helicity selection and automatic full helicity
1729+ sum if needed. Optimization of run parameters.
1730+ JA: New flag in run_card.dat to decide whether basic cuts
1731+ are applied to decay products or not.
1732+ OM: Merged ALOHA calls for different lorentz structures
1733+ with the same color structures, increasing the speed and
1734+ efficiency of matrix element evaluations.
1735+ OM: Added new "open" command in command line interface,
1736+ allowing to open standard file types directly.
1737+ Automatically open crossx.html at launch.
1738+ JA: Fixed MadEvent bugs for multiparton processes with
1739+ conflicting decays and some faulty array limits.
1740+ JA: Suppressed scary but irrelevant warnings for compiling
1741+ 2->1 and 1->2 processes in MadEvent.
1742+ JA: Pythia 8 output further optimized.
1743+ JA: Several minor fixes relating to user interface etc.
1744+
1745+1.0.0 (12/04/11): Official release of MadGraph 5. Some of the features:
1746+ - Complete FeynRules compatibility through the UFO interface
1747+ - Automatic writing of HELAS routines for any model in
1748+ Fortran, C++ or Python through ALOHA
1749+ - Matrix element output in Fortran, C++ or Python
1750+ - Output formats: MadEvent, Pythia 8, Standalone (Fortran/C++)
1751+ - Support for spin 0, 1/2, 1, 2 particles
1752+ - Support for color 1, 3, 6, 8
1753+ - Revamped MadEvent with improved subprocess directory
1754+ organization and vastly increased speed and stability
1755+ - Unlimited length decay chains (up to 12 final state
1756+ particles tested with MadEvent, see v. 1.0.1)
1757+ - Process checks for new model implementations
1758+ - ...and much more (see paper "MadGraph 5: Going Beyond")
1759
1760=== modified file 'aloha/aloha_writers.py'
1761--- aloha/aloha_writers.py 2011-04-01 22:38:18 +0000
1762+++ aloha/aloha_writers.py 2011-04-22 01:24:30 +0000
1763@@ -19,10 +19,16 @@
1764
1765 def __init__(self, abstract_routine, dirpath):
1766
1767+
1768+ name = get_routine_name(abstract_routine.name, abstract_routine.outgoing)
1769+ if dirpath:
1770+ self.dir_out = dirpath
1771+ self.out_path = os.path.join(dirpath, name + self.extension)
1772+ else:
1773+ self.out_path = None
1774+ self.dir_out = None
1775+
1776 self.obj = abstract_routine.expr
1777- name = get_routine_name(abstract_routine.name, abstract_routine.outgoing)
1778- self.out_path = os.path.join(dirpath, name + self.extension)
1779- self.dir_out = dirpath
1780 self.particles = [self.type_to_variable[spin] for spin in \
1781 abstract_routine.spins]
1782 self.namestring = name
1783@@ -36,6 +42,9 @@
1784 self.make_all_lists() # Compute the expression for the call ordering
1785 #the definition of objects,..
1786
1787+
1788+
1789+
1790 def pass_to_HELAS(self, indices, start=0):
1791 """find the Fortran HELAS position for the list of index"""
1792
1793@@ -170,18 +179,19 @@
1794
1795 return call_arg
1796
1797- def reorder_call_list(self, call_list, old, new):
1798- """ restore the correct order for symmetries """
1799- spins = self.particles
1800- assert(0 < old < new)
1801- old, new = old -1, new -1 # pass in real position in particles list
1802- assert(spins[old] == spins[new])
1803- spin =spins[old]
1804-
1805- new_call = call_list[:]
1806- val = new_call.pop(old)
1807- new_call.insert(new - 1, val)
1808- return new_call
1809+# def reorder_call_list(self, call_list, old, new):
1810+# """ restore the correct order for symmetries """
1811+# raise
1812+# #spins = self.particles
1813+# #assert(0 < old < new)
1814+# #old, new = old -1, new -1 # pass in real position in particles list
1815+# #assert(spins[old] == spins[new])
1816+# #spin =spins[old]
1817+#
1818+# new_call = call_list[:]
1819+# #val = new_call.pop(old)
1820+# #new_call.insert(new - 1, val)
1821+# return new_call
1822
1823
1824 def make_momentum_conservation(self):
1825@@ -249,42 +259,45 @@
1826 'V':'double complex V%d(6)',
1827 'T':'double complex T%s(18)'}
1828
1829- def define_header(self):
1830+ def define_header(self, name=None):
1831 """Define the Header of the fortran file. This include
1832 - function tag
1833 - definition of variable
1834 """
1835-
1836+
1837+ if not name:
1838+ name = self.namestring
1839+
1840 Momenta = self.collected['momenta']
1841 OverM = self.collected['om']
1842
1843 CallList = self.calllist['CallList']
1844 declare_list = self.calllist['DeclareList']
1845- if 'double complex C' in declare_list:
1846+ if 'double complex COUP' in declare_list:
1847 alredy_update = True
1848 else:
1849 alredy_update = False
1850
1851 if not alredy_update:
1852- declare_list.append('double complex C')
1853+ declare_list.append('double complex COUP')
1854
1855 # define the type of function and argument
1856 if not self.offshell:
1857 str_out = 'subroutine %(name)s(%(args)s,vertex)\n' % \
1858- {'name': self.namestring,
1859- 'args': ','.join(CallList+ ['C']) }
1860+ {'name': name,
1861+ 'args': ','.join(CallList+ ['COUP']) }
1862 if not alredy_update:
1863- declare_list.append('double complex vertex\n')
1864+ declare_list.append('double complex vertex')
1865 else:
1866 if not alredy_update:
1867 declare_list.append('double complex denom')
1868 declare_list.append('double precision M%(id)d, W%(id)d' %
1869 {'id': self.offshell})
1870- call_arg = '%(args)s, C, M%(id)d, W%(id)d, %(spin)s%(id)d' % \
1871+ call_arg = '%(args)s, COUP, M%(id)d, W%(id)d, %(spin)s%(id)d' % \
1872 {'args': ', '.join(CallList),
1873 'spin': self.particles[self.offshell -1],
1874 'id': self.offshell}
1875- str_out = ' subroutine %s(%s)\n' % (self.namestring, call_arg)
1876+ str_out = ' subroutine %s(%s)\n' % (name, call_arg)
1877
1878 # Forcing implicit None
1879 str_out += 'implicit none \n'
1880@@ -402,7 +415,7 @@
1881 OutString = ''
1882 if not self.offshell:
1883 for ind in self.obj.listindices():
1884- string = 'Vertex = C*' + self.write_obj(self.obj.get_rep(ind))
1885+ string = 'Vertex = COUP*' + self.write_obj(self.obj.get_rep(ind))
1886 string = string.replace('+-', '-')
1887 string = re.sub('\((?P<num>[+-]*[0-9])(?P<num2>[+-][0-9])[Jj]\)\.', '(\g<num>d0,\g<num2>d0)', string)
1888 string = re.sub('(?P<num>[0-9])[Jj]\.', '\g<num>.*(0d0,1d0)', string)
1889@@ -420,7 +433,7 @@
1890 string = re.sub('(?P<num>[0-9])[Jj]\.', '\g<num>*(0d0,1d0)', string)
1891 OutString = OutString + string + '\n'
1892 for ind in numerator.listindices():
1893- string = '%s(%d)= C*denom*' % (OffShellParticle, self.pass_to_HELAS(ind, start=1))
1894+ string = '%s(%d)= COUP*denom*' % (OffShellParticle, self.pass_to_HELAS(ind, start=1))
1895 string += self.write_obj(numerator.get_rep(ind))
1896 string = string.replace('+-', '-')
1897 string = re.sub('\((?P<num>[+-][0-9])\+(?P<num2>[+-][0-9])[Jj]\)\.', '(\g<num>d0,\g<num2>d0)', string)
1898@@ -430,45 +443,178 @@
1899
1900 def define_symmetry(self, new_nb):
1901 number = self.offshell
1902- calls = self.reorder_call_list(self.calllist['CallList'], self.offshell,
1903- new_nb)
1904- Outstring = 'call '+self.namestring+'('+','.join(calls)+',C,M%s,W%s,%s%s)' \
1905+ calls = self.calllist['CallList']
1906+
1907+ Outstring = 'call '+self.namestring+'('+','.join(calls)+',COUP,M%s,W%s,%s%s)\n' \
1908 %(number,number,self.particles[number-1],number)
1909 return Outstring
1910
1911 def define_foot(self):
1912- return 'end'
1913+ return 'end\n\n'
1914
1915 def write(self, mode='self'):
1916-
1917- writer = writers.FortranWriter(self.out_path)
1918- writer.downcase = False
1919- commentstring = 'This File is Automatically generated by ALOHA \n'
1920- commentstring += 'The process calculated in this file is: \n'
1921- commentstring += self.comment + '\n'
1922- writer.write_comments(commentstring)
1923-
1924+
1925 # write head - momenta - body - foot
1926- writer.writelines(self.define_header())
1927- writer.writelines(self.define_momenta())
1928- writer.writelines(self.define_expression())
1929- writer.writelines(self.define_foot())
1930+ text = self.define_header()+'\n'
1931+ text += self.define_momenta()+'\n'
1932+ text += self.define_expression()
1933+ text += self.define_foot()
1934
1935+ sym_text = []
1936 for elem in self.symmetries:
1937 symmetryhead = self.define_header().replace( \
1938 self.namestring,self.namestring[0:-1]+'%s' %(elem))
1939 symmetrybody = self.define_symmetry(elem)
1940- writer.write_comments('\n%s\n' % ('#'*65))
1941- writer.writelines(symmetryhead)
1942- writer.writelines(symmetrybody)
1943- writer.writelines(self.define_foot())
1944-
1945-
1946+
1947+ sym_text.append(symmetryhead + symmetrybody + self.define_foot())
1948+
1949+
1950+ if self.out_path:
1951+ writer = writers.FortranWriter(self.out_path)
1952+ writer.downcase = False
1953+ commentstring = 'This File is Automatically generated by ALOHA \n'
1954+ commentstring += 'The process calculated in this file is: \n'
1955+ commentstring += self.comment + '\n'
1956+ writer.write_comments(commentstring)
1957+ writer.writelines(text)
1958+ for text in sym_text:
1959+ writer.write_comments('\n%s\n' % ('#'*65))
1960+ writer.writelines(text)
1961+ else:
1962+ for stext in sym_text:
1963+ text += '\n\n' + stext
1964+
1965+ return text + '\n'
1966+
1967+ def write_combined(self, lor_names, mode='self', offshell=None):
1968+ """Write routine for combine ALOHA call (more than one coupling)"""
1969+
1970+ # Set some usefull command
1971+ if offshell is None:
1972+ sym = 1
1973+ offshell = self.offshell
1974+ else:
1975+ sym = None # deactivate symetry
1976+
1977+ name = combine_name(self.abstractname, lor_names, offshell)
1978+
1979+
1980+ # write header
1981+ header = self.define_header(name=name)
1982+ new_couplings = ['COUP%s' % (i+1) for i in range(len(lor_names)+1)]
1983+ text = header.replace('COUP', ','.join(new_couplings))
1984+ # define the TMP for storing output
1985+ if not offshell:
1986+ text += ' double complex TMP\n'
1987+ else:
1988+ spin = self.particles[offshell -1]
1989+ text += ' double complex TMP(%s)\n integer i' % self.type_to_size[spin]
1990+
1991+ # Define which part of the routine should be called
1992+ addon = ''
1993+ if 'C' in self.namestring:
1994+ short_name, addon = name.split('C',1)
1995+ if addon.split('_')[0].isdigit():
1996+ addon = 'C' +self.namestring.split('C',1)[1]
1997+ else:
1998+ addon = '_%s' % self.offshell
1999+ else:
2000+ addon = '_%s' % self.offshell
2001+
2002+ # how to call the routine
2003+ if not offshell:
2004+ main = 'vertex'
2005+ call_arg = '%(args)s, %(COUP)s, %(LAST)s' % \
2006+ {'args': ', '.join(self.calllist['CallList']),
2007+ 'COUP':'COUP%d',
2008+ 'spin': self.particles[self.offshell -1],
2009+ 'LAST': '%s'}
2010+ else:
2011+ main = '%(spin)s%(id)d' % \
2012+ {'spin': self.particles[offshell -1],
2013+ 'id': self.offshell}
2014+ call_arg = '%(args)s, %(COUP)s, M%(id)d, W%(id)d, %(LAST)s' % \
2015+ {'args': ', '.join(self.calllist['CallList']),
2016+ 'COUP':'COUP%d',
2017+ 'id': self.offshell,
2018+ 'LAST': '%s'}
2019+
2020+ # make the first call
2021+ line = " CALL %s%s("+call_arg+")\n"
2022+ text += '\n\n' + line % (self.namestring, '', 1, main)
2023+
2024+ # make the other call
2025+ for i,lor in enumerate(lor_names):
2026+ text += line % (lor, addon, i+2, 'TMP')
2027+ if not offshell:
2028+ text += ' vertex = vertex + tmp\n'
2029+ else:
2030+ size = self.type_to_size[spin] -2
2031+ text += """ do i=1,%(id)d
2032+ %(main)s(i) = %(main)s(i) + tmp(i)
2033+ enddo\n""" % {'id': size, 'main':main}
2034+
2035+
2036+ text += self.define_foot()
2037+
2038+ #ADD SYMETRY
2039+ if sym:
2040+ for elem in self.symmetries:
2041+ text += self.write_combined(lor_names, mode, elem)
2042+
2043+
2044+ if self.out_path:
2045+ # Prepare a specific file
2046+ path = os.path.join(os.path.dirname(self.out_path), name+'.f')
2047+ writer = writers.FortranWriter(path)
2048+ writer.downcase = False
2049+ commentstring = 'This File is Automatically generated by ALOHA \n'
2050+ writer.write_comments(commentstring)
2051+ writer.writelines(text)
2052+
2053+ return text
2054+
2055 def get_routine_name(name,outgoing):
2056 """ build the name of the aloha function """
2057
2058 return '%s_%s' % (name, outgoing)
2059
2060+def combine_name(name, other_names, outgoing):
2061+ """ build the name for combined aloha function """
2062+
2063+ # Two possible scheme FFV1C1_2_X or FFV1__FFV2C1_X
2064+ # If they are all in FFVX scheme then use the first
2065+ p=re.compile('^(?P<type>[FSVT]+)(?P<id>\d+)')
2066+ routine = ''
2067+ if p.search(name):
2068+ base, id = p.search(name).groups()
2069+ routine = name
2070+ for s in other_names:
2071+ try:
2072+ base2,id2 = p.search(s).groups()
2073+ except:
2074+ routine = ''
2075+ break # one matching not good -> other scheme
2076+ if base != base2:
2077+ routine = ''
2078+ break # one matching not good -> other scheme
2079+ else:
2080+ routine += '_%s' % id2
2081+ if routine:
2082+ return routine +'_%s' % outgoing
2083+
2084+ addon = ''
2085+ if 'C' in name:
2086+ short_name, addon = name.split('C',1)
2087+ try:
2088+ addon = 'C' + str(int(addon))
2089+ except:
2090+ addon = ''
2091+ else:
2092+ name = short_name
2093+
2094+ return '_'.join((name,) + tuple(other_names)) + addon + '_%s' % outgoing
2095+
2096 class ALOHAWriterForCPP(WriteALOHA):
2097 """Routines for writing out helicity amplitudes as C++ .h and .cc files."""
2098
2099@@ -477,17 +623,20 @@
2100 'V':'double complex V%d[6]',
2101 'T':'double complex T%s[18]'}
2102
2103- def define_header(self):
2104+ def define_header(self, name=None):
2105 """Define the headers for the C++ .h and .cc files. This include
2106 - function tag
2107 - definition of variable
2108 - momentum conservation
2109 """
2110+
2111+ if name is None:
2112+ name = self.namestring
2113
2114 #Width = self.collected['width']
2115 #Mass = self.collected['mass']
2116
2117- CallList = self.calllist['CallList']
2118+ CallList = self.calllist['CallList'][:]
2119
2120 local_declare = []
2121 OffShell = self.offshell
2122@@ -503,12 +652,12 @@
2123 # define the type of function and argument
2124 if not OffShell:
2125 str_out = 'void %(name)s(%(args)s, complex<double>& vertex)' % \
2126- {'name': self.namestring,
2127- 'args': ','.join(CallList + ['complex<double> C'])}
2128+ {'name': name,
2129+ 'args': ','.join(CallList + ['complex<double> COUP'])}
2130 else:
2131 str_out = 'void %(name)s(%(args)s, double M%(number)d, double W%(number)d, complex<double>%(out)s%(number)d[])' % \
2132- {'name': self.namestring,
2133- 'args': ','.join(CallList+ ['complex<double> C']),
2134+ {'name': name,
2135+ 'args': ','.join(CallList+ ['complex<double> COUP']),
2136 'out': self.particles[OffShellParticle],
2137 'number': OffShellParticle + 1
2138 }
2139@@ -613,7 +762,7 @@
2140 OutString = ''
2141 if not self.offshell:
2142 for ind in self.obj.listindices():
2143- string = 'vertex = C*' + self.write_obj(self.obj.get_rep(ind))
2144+ string = 'vertex = COUP*' + self.write_obj(self.obj.get_rep(ind))
2145 string = string.replace('+-', '-')
2146 OutString = OutString + string + ';\n'
2147 else:
2148@@ -626,7 +775,7 @@
2149 string = string.replace('+-', '-')
2150 OutString = OutString + string + ';\n'
2151 for ind in numerator.listindices():
2152- string = '%s[%d]= C*denom*' % (OffShellParticle, self.pass_to_HELAS(ind))
2153+ string = '%s[%d]= COUP*denom*' % (OffShellParticle, self.pass_to_HELAS(ind))
2154 string += self.write_obj(numerator.get_rep(ind))
2155 string = string.replace('+-', '-')
2156 OutString = OutString + string + ';\n'
2157@@ -636,8 +785,7 @@
2158 remove_double = re.compile('complex<double> (?P<name>[\w]+)\[\]')
2159 def define_symmetry(self, new_nb):
2160 """Write the call for symmetric routines"""
2161- calls = self.reorder_call_list(self.calllist['CallList'],
2162- self.offshell, new_nb)
2163+ calls = self.calllist['CallList']
2164
2165 for i, call in enumerate(calls):
2166 if self.remove_double.match(call):
2167@@ -647,22 +795,24 @@
2168 #calls = [self.remove_double.match(call).group('name') for call in \
2169 # calls]
2170 number = self.offshell
2171- Outstring = self.namestring+'('+','.join(calls)+',C,M%s,W%s,%s%s);' \
2172+ Outstring = self.namestring+'('+','.join(calls)+',COUP,M%s,W%s,%s%s);\n' \
2173 %(number,number,self.particles[self.offshell-1],number)
2174 return Outstring
2175
2176 def define_foot(self):
2177 """Return the end of the function definition"""
2178
2179- return '}\n'
2180+ return '}\n\n'
2181
2182- def write_h(self, header):
2183+ def write_h(self, header, compiler_cmd=True):
2184 """Return the full contents of the .h file"""
2185
2186- h_string = '#ifndef '+ self.namestring + '_guard\n'
2187- h_string += '#define ' + self.namestring + '_guard\n'
2188- h_string += '#include <complex>\n'
2189- h_string += 'using namespace std;\n\n'
2190+ h_string = ''
2191+ if compiler_cmd:
2192+ h_string = '#ifndef '+ self.namestring + '_guard\n'
2193+ h_string += '#define ' + self.namestring + '_guard\n'
2194+ h_string += '#include <complex>\n'
2195+ h_string += 'using namespace std;\n\n'
2196
2197 h_header = header['h_header']
2198
2199@@ -672,15 +822,44 @@
2200 symmetryhead = h_header.replace( \
2201 self.namestring,self.namestring[0:-1]+'%s' %(elem))
2202 h_string += symmetryhead
2203-
2204- h_string += '#endif'
2205+
2206+ if compiler_cmd:
2207+ h_string += '#endif\n\n'
2208
2209 return h_string
2210
2211- def write_cc(self, header):
2212+ def write_combined_h(self, lor_names, offshell=None, compiler_cmd=True):
2213+ """Return the content of the .h file linked to multiple lorentz call."""
2214+
2215+ name = combine_name(self.abstractname, lor_names, offshell)
2216+ text= ''
2217+ if compiler_cmd:
2218+ text = '#ifndef '+ name + '_guard\n'
2219+ text += '#define ' + name + '_guard\n'
2220+ text += '#include <complex>\n'
2221+ text += 'using namespace std;\n\n'
2222+
2223+ # write header
2224+ header = self.define_header(name=name)
2225+ h_header = header['h_header']
2226+ new_couplings = ['COUP%s' % (i+1) for i in range(len(lor_names)+1)]
2227+ h_string = h_header.replace('COUP', ', complex <double>'.join(new_couplings))
2228+ text += h_string
2229+
2230+ for elem in self.symmetries:
2231+ text += h_string.replace(name, name[0:-1]+str(elem))
2232+
2233+ if compiler_cmd:
2234+ text += '#endif'
2235+
2236+ return text
2237+
2238+ def write_cc(self, header, compiler_cmd=True):
2239 """Return the full contents of the .cc file"""
2240
2241- cc_string = '#include \"%s.h\"\n\n' % self.namestring
2242+ cc_string = ''
2243+ if compiler_cmd:
2244+ cc_string = '#include \"%s.h\"\n\n' % self.namestring
2245 cc_header = header['cc_header']
2246 cc_string += cc_header
2247 cc_string += self.define_momenta()
2248@@ -696,24 +875,154 @@
2249 cc_string += self.define_foot()
2250
2251 return cc_string
2252+
2253+ def write_combined_cc(self, lor_names, offshell=None, compiler_cmd=True, sym=True):
2254+ "Return the content of the .cc file linked to multiple lorentz call."
2255+
2256+ # Set some usefull command
2257+ if offshell is None:
2258+ offshell = self.offshell
2259+
2260+ name = combine_name(self.abstractname, lor_names, offshell)
2261+
2262+ text = ''
2263+ if compiler_cmd:
2264+ text += '#include "%s.h"\n\n' % name
2265+
2266+ # write header
2267+ header = self.define_header(name=name)['cc_header']
2268+ new_couplings = ['COUP%s' % (i+1) for i in range(len(lor_names)+1)]
2269+ text += header.replace('COUP', ', complex<double>'.join(new_couplings))
2270+ # define the TMP for storing output
2271+ if not offshell:
2272+ text += 'complex<double> tmp;\n'
2273+ else:
2274+ spin = self.particles[offshell -1]
2275+ text += 'complex<double> tmp[%s];\n int i = 0;' % self.type_to_size[spin]
2276+
2277+ # Define which part of the routine should be called
2278+ addon = ''
2279+ if 'C' in self.namestring:
2280+ short_name, addon = name.split('C',1)
2281+ if addon.split('_')[0].isdigit():
2282+ addon = 'C' +self.namestring.split('C',1)[1]
2283+ else:
2284+ addon = '_%s' % self.offshell
2285+ else:
2286+ addon = '_%s' % self.offshell
2287+
2288+ # how to call the routine
2289+ if not offshell:
2290+ main = 'vertex'
2291+ call_arg = '%(args)s, %(COUP)s, %(LAST)s' % \
2292+ {'args': ', '.join(self.calllist['CallList']),
2293+ 'COUP':'COUP%d',
2294+ 'spin': self.particles[self.offshell -1],
2295+ 'LAST': '%s'}
2296+ else:
2297+ main = '%(spin)s%(id)d' % \
2298+ {'spin': self.particles[self.offshell -1],
2299+ 'id': self.offshell}
2300+ call_arg = '%(args)s, %(COUP)s, M%(id)d, W%(id)d, %(LAST)s' % \
2301+ {'args': ', '.join(self.calllist['CallList']),
2302+ 'COUP':'COUP%d',
2303+ 'id': self.offshell,
2304+ 'LAST': '%s'}
2305+
2306+ # make the first call
2307+ line = "%s%s("+call_arg+");\n"
2308+ text += '\n\n' + line % (self.namestring, '', 1, main)
2309+
2310+ # make the other call
2311+ for i,lor in enumerate(lor_names):
2312+ text += line % (lor, addon, i+2, 'tmp')
2313+ if not offshell:
2314+ text += ' vertex = vertex + tmp;\n'
2315+ else:
2316+ size = self.type_to_size[spin] -2
2317+ text += """ while (i < %(id)d)
2318+ {
2319+ %(main)s[i] = %(main)s[i] + tmp[i];
2320+ i++;
2321+ }\n""" % {'id': size, 'main':main}
2322+
2323+
2324+ text += self.define_foot()
2325+
2326+ if sym:
2327+ for elem in self.symmetries:
2328+ text += self.write_combined_cc(lor_names, elem,
2329+ compiler_cmd=compiler_cmd,
2330+ sym=False)
2331+
2332+
2333+ if self.out_path:
2334+ # Prepare a specific file
2335+ path = os.path.join(os.path.dirname(self.out_path), name+'.f')
2336+ writer = writers.FortranWriter(path)
2337+ writer.downcase = False
2338+ commentstring = 'This File is Automatically generated by ALOHA \n'
2339+ writer.write_comments(commentstring)
2340+ writer.writelines(text)
2341+
2342+ return text
2343+
2344+
2345
2346- def write(self, mode='self'):
2347+ def write(self, mode='self', **opt):
2348 """Write the .h and .cc files"""
2349
2350- writer_h = writers.CPPWriter(self.out_path + ".h")
2351- writer_cc = writers.CPPWriter(self.out_path + ".cc")
2352- commentstring = 'This File is Automatically generated by ALOHA \n'
2353- commentstring += 'The process calculated in this file is: \n'
2354- commentstring += self.comment + '\n'
2355- writer_h.write_comments(commentstring)
2356- writer_cc.write_comments(commentstring)
2357-
2358+
2359 # write head - momenta - body - foot
2360-
2361 header = self.define_header()
2362- writer_h.writelines(self.write_h(header))
2363- writer_cc.writelines(self.write_cc(header))
2364-
2365+ h_text = self.write_h(header, **opt)
2366+ cc_text = self.write_cc(header, **opt)
2367+
2368+ # write in two file
2369+ if self.out_path:
2370+ writer_h = writers.CPPWriter(self.out_path + ".h")
2371+ writer_cc = writers.CPPWriter(self.out_path + ".cc")
2372+ commentstring = 'This File is Automatically generated by ALOHA \n'
2373+ commentstring += 'The process calculated in this file is: \n'
2374+ commentstring += self.comment + '\n'
2375+ writer_h.write_comments(commentstring)
2376+ writer_cc.write_comments(commentstring)
2377+ writer_h.writelines(h_text)
2378+ writer_cc.writelines(cc_text)
2379+
2380+ return h_text, cc_text
2381+
2382+
2383+
2384+ def write_combined(self, lor_names, mode='self', offshell=None, **opt):
2385+ """Write the .h and .cc files associated to the combined file"""
2386+
2387+ # Set some usefull command
2388+ if offshell is None:
2389+ offshell = self.offshell
2390+
2391+ name = combine_name(self.abstractname, lor_names, offshell)
2392+
2393+ h_text = self.write_combined_h(lor_names, offshell, **opt)
2394+ cc_text = self.write_combined_cc(lor_names, offshell, sym=True, **opt)
2395+
2396+ if self.out_path:
2397+ # Prepare a specific file
2398+ path = os.path.join(os.path.dirname(self.out_path), name)
2399+ commentstring = 'This File is Automatically generated by ALOHA \n'
2400+
2401+ writer_h = writers.CPPWriter(path + ".h")
2402+ writer_h.write_comments(commentstring)
2403+ writer_h.writelines(h_text)
2404+
2405+ writer_cc = writers.CPPWriter(path + ".cc")
2406+ writer_cc.write_comments(commentstring)
2407+ writer_cc.writelines(cc_text)
2408+ else:
2409+ return h_text, cc_text
2410+
2411+ return h_text, cc_text
2412+
2413 class ALOHAWriterForPython(WriteALOHA):
2414 """ A class for returning a file/a string for python evaluation """
2415
2416@@ -723,18 +1032,11 @@
2417 """ standard init but if dirpath is None the write routine will
2418 return a string (which can be evaluated by an exec"""
2419
2420- if dirpath:
2421- WriteALOHA.__init__(self, abstract_routine, dirpath)
2422- else:
2423- WriteALOHA.__init__(self, abstract_routine, '')
2424- self.out_path = None
2425- self.dir_out = None
2426+ WriteALOHA.__init__(self, abstract_routine, dirpath)
2427 self.outname = '%s%s' % (self.particles[self.offshell -1], \
2428 self.offshell)
2429
2430-
2431-
2432-
2433+
2434 def change_var_format(self, name):
2435 """Formatting the variable name to Python format
2436 start to count at zero"""
2437@@ -759,7 +1061,7 @@
2438 OutString = ''
2439 if not self.offshell:
2440 for ind in self.obj.listindices():
2441- string = 'vertex = C*' + self.write_obj(self.obj.get_rep(ind))
2442+ string = 'vertex = COUP*' + self.write_obj(self.obj.get_rep(ind))
2443 string = string.replace('+-', '-')
2444 OutString = OutString + string + '\n'
2445 else:
2446@@ -773,7 +1075,7 @@
2447 string = string.replace('+-', '-')
2448 OutString += string + '\n'
2449 for ind in numerator.listindices():
2450- string = '%s[%d]= C*denom*' % (self.outname, self.pass_to_HELAS(ind))
2451+ string = '%s[%d]= COUP*denom*' % (self.outname, self.pass_to_HELAS(ind))
2452 string += self.write_obj(numerator.get_rep(ind))
2453 string = string.replace('+-', '-')
2454 OutString += string + '\n'
2455@@ -781,17 +1083,19 @@
2456
2457 def define_foot(self):
2458 if not self.offshell:
2459- return 'return vertex'
2460+ return 'return vertex\n\n'
2461 else:
2462- return 'return %s' % (self.outname)
2463+ return 'return %s\n\n' % (self.outname)
2464
2465
2466- def define_header(self):
2467+ def define_header(self, name=None):
2468 """Define the Header of the fortran file. This include
2469 - function tag
2470 - definition of variable
2471 """
2472-
2473+ if name is None:
2474+ name = self.namestring
2475+
2476 Momenta = self.collected['momenta']
2477 OverM = self.collected['om']
2478
2479@@ -801,11 +1105,11 @@
2480 # define the type of function and argument
2481 if not self.offshell:
2482 str_out += 'def %(name)s(%(args)s):\n' % \
2483- {'name': self.namestring,
2484- 'args': ','.join(CallList+ ['C']) }
2485+ {'name': name,
2486+ 'args': ','.join(CallList+ ['COUP']) }
2487 else:
2488- str_out += 'def %(name)s(%(args)s, C, M%(id)d, W%(id)d):\n' % \
2489- {'name': self.namestring,
2490+ str_out += 'def %(name)s(%(args)s, COUP, M%(id)d, W%(id)d):\n' % \
2491+ {'name': name,
2492 'args': ', '.join(CallList),
2493 'id': self.offshell}
2494 return str_out
2495@@ -871,9 +1175,8 @@
2496
2497 def define_symmetry(self, new_nb):
2498 number = self.offshell
2499- calls = self.reorder_call_list(self.calllist['CallList'], self.offshell,
2500- new_nb)
2501- Outstring = 'return '+self.namestring+'('+','.join(calls)+',C,M%s,W%s)' \
2502+ calls = self.calllist['CallList']
2503+ Outstring = 'return '+self.namestring+'('+','.join(calls)+',COUP,M%s,W%s)\n' \
2504 %(number,number)
2505 return Outstring
2506
2507@@ -900,5 +1203,82 @@
2508
2509 if self.out_path:
2510 ff = open(self.out_path,'w').write(text)
2511- else:
2512- return text
2513+
2514+ return text + '\n'
2515+
2516+ def write_combined(self, lor_names, mode='self', offshell=None):
2517+ """Write routine for combine ALOHA call (more than one coupling)"""
2518+
2519+ # Set some usefull command
2520+ if offshell is None:
2521+ sym = 1
2522+ offshell = self.offshell
2523+ else:
2524+ sym = None
2525+ name = combine_name(self.abstractname, lor_names, offshell)
2526+
2527+ # write head - momenta - body - foot
2528+ text = ''
2529+ #if mode == 'mg5':
2530+ # text = 'import aloha.template_files.wavefunctions as wavefunctions\n'
2531+ #else:
2532+ # text = 'import wavefunctions\n'
2533+
2534+
2535+ # write header
2536+ header = self.define_header(name=name)
2537+ new_couplings = ['COUP%s' % (i+1) for i in range(len(lor_names)+1)]
2538+ header = header.replace('COUP', ','.join(new_couplings))
2539+
2540+ text += header
2541+
2542+ # Define which part of the routine should be called
2543+ addon = ''
2544+ if 'C' in self.namestring:
2545+ short_name, addon = name.split('C',1)
2546+ if addon.split('_')[0].isdigit():
2547+ addon = 'C' +self.namestring.split('C',1)[1]
2548+ else:
2549+ addon = '_%s' % self.offshell
2550+ else:
2551+ addon = '_%s' % self.offshell
2552+
2553+ # how to call the routine
2554+ if not offshell:
2555+ main = 'vertex'
2556+ call_arg = '%(args)s, %(COUP)s' % \
2557+ {'args': ', '.join(self.calllist['CallList']),
2558+ 'COUP':'COUP%d',
2559+ 'spin': self.particles[self.offshell -1]}
2560+ else:
2561+ main = '%(spin)s%(id)d' % \
2562+ {'spin': self.particles[self.offshell -1],
2563+ 'id': self.offshell}
2564+ call_arg = '%(args)s, %(COUP)s, M%(id)d, W%(id)d' % \
2565+ {'args': ', '.join(self.calllist['CallList']),
2566+ 'COUP':'COUP%d',
2567+ 'id': self.offshell}
2568+
2569+ # make the first call
2570+ line = " %s = %s%s("+call_arg+")\n"
2571+ text += '\n\n' + line % (main, self.namestring, '', 1)
2572+
2573+ # make the other call
2574+ for i,name in enumerate(lor_names):
2575+ text += line % ('tmp',name, addon, i+2)
2576+ if not offshell:
2577+ text += ' vertex += tmp\n'
2578+ else:
2579+ size = self.type_to_size[self.particles[offshell -1]] -2
2580+ text += " for i in range(%(id)d):\n" % {'id': size}
2581+ text += " %(main)s[i] += tmp[i]\n" %{'main': main}
2582+
2583+ text += ' '+self.define_foot()
2584+
2585+ #ADD SYMETRY
2586+ if sym:
2587+ for elem in self.symmetries:
2588+ text += self.write_combined(lor_names, mode, elem)
2589+
2590+ return text
2591+
2592\ No newline at end of file
2593
2594=== modified file 'aloha/bin/aloha'
2595--- aloha/bin/aloha 2011-02-03 09:33:24 +0000
2596+++ aloha/bin/aloha 2011-04-22 01:24:30 +0000
2597@@ -31,7 +31,7 @@
2598
2599 (options, args) = parser.parse_args()
2600 if len(args) != 1:
2601- sys.exit('ALOHA requires as arguments the path to UFO directory')
2602+ sys.exit('ALOHA requires exactly one argument (the path to UFO directory)')
2603
2604 # Set logging level according to the logging level given by options
2605 logging.basicConfig(level=vars(logging)[options.logging])
2606
2607=== modified file 'aloha/create_aloha.py'
2608--- aloha/create_aloha.py 2011-04-14 21:57:13 +0000
2609+++ aloha/create_aloha.py 2011-04-22 01:24:30 +0000
2610@@ -56,18 +56,32 @@
2611 self.outgoing = outgoing
2612 self.infostr = infostr
2613 self.symmetries = []
2614+ self.combined = []
2615
2616 def add_symmetry(self, outgoing):
2617 """ add an outgoing """
2618
2619 if not outgoing in self.symmetries:
2620 self.symmetries.append(outgoing)
2621-
2622- def write(self, output_dir, language='Fortran', mode='self'):
2623+
2624+ def add_combine(self, lor_list):
2625+ """add a combine rule """
2626+
2627+ if lor_list not in self.combined:
2628+ self.combined.append(lor_list)
2629+
2630+ def write(self, output_dir, language='Fortran', mode='self', **opt):
2631 """ write the content of the object """
2632- return getattr(aloha_writers, 'ALOHAWriterFor%s' % language)(self, output_dir).write(mode=mode)
2633-
2634-
2635+
2636+ writer = getattr(aloha_writers, 'ALOHAWriterFor%s' % language)(self, output_dir)
2637+ text = writer.write(mode=mode, **opt)
2638+ for grouped in self.combined:
2639+ if isinstance(text, tuple):
2640+ text = tuple([old.__add__(new) for old, new in zip(text,
2641+ writer.write_combined(grouped, mode=mode, **opt))])
2642+ else:
2643+ text += writer.write_combined(grouped, mode=mode, **opt)
2644+ return text
2645
2646 class AbstractRoutineBuilder(object):
2647 """ Launch the creation of the Helicity Routine"""
2648@@ -346,6 +360,7 @@
2649 # init the dictionary
2650 dict.__init__(self)
2651 self.symmetries = {}
2652+ self.multiple_lor = {}
2653
2654 # check the mass of spin2 (if any)
2655 self.massless_spin2 = self.has_massless_spin2()
2656@@ -394,6 +409,7 @@
2657
2658 def load(self, filepos=None):
2659 """ reload the pickle file """
2660+ return False
2661 if not filepos:
2662 filepos = os.path.join(self.model_pos,'aloha.pkl')
2663 if os.path.exists(filepos):
2664@@ -426,6 +442,7 @@
2665 #to compute identical contribution
2666 self.look_for_symmetries()
2667 conjugate_list = self.look_for_conjugate()
2668+ self.look_for_multiple_lorentz_interactions()
2669 if not wanted_lorentz:
2670 wanted_lorentz = [l.name for l in self.model.all_lorentz]
2671 for lorentz in self.model.all_lorentz:
2672@@ -445,6 +462,13 @@
2673 if 5 in lorentz.spins and self.massless_spin2 is not None:
2674 builder.spin2_massless = self.massless_spin2
2675 self.compute_aloha(builder)
2676+
2677+ if lorentz.name in self.multiple_lor:
2678+ for m in self.multiple_lor[lorentz.name]:
2679+ for outgoing in range(len(lorentz.spins)+1):
2680+ self[(lorentz.name, outgoing)].add_combine(m)
2681+
2682+
2683 if lorentz.name in conjugate_list:
2684 conjg_builder_list= builder.define_all_conjugate_builder(\
2685 conjugate_list[lorentz.name])
2686@@ -452,6 +476,11 @@
2687 # No duplication of conjugation:
2688 assert conjg_builder_list.count(conjg_builder) == 1
2689 self.compute_aloha(conjg_builder, lorentz.name)
2690+ if lorentz.name in self.multiple_lor:
2691+ for m in self.multiple_lor[lorentz.name]:
2692+ for outgoing in range(len(lorentz.spins)+1):
2693+ self[(conjg_builder.name, outgoing)].add_combine(m)
2694+
2695
2696
2697 if save:
2698@@ -471,14 +500,16 @@
2699 # reorganize the data (in order to use optimization for a given lorentz
2700 #structure
2701 request = {}
2702- for l_name, conjugate, outgoing in data:
2703- try:
2704- request[l_name][conjugate].append(outgoing)
2705- except:
2706+ for list_l_name, conjugate, outgoing in data:
2707+ for l_name in list_l_name:
2708 try:
2709- request[l_name][conjugate] = [outgoing]
2710+ request[l_name][conjugate].append(outgoing)
2711 except:
2712- request[l_name] = {conjugate: [outgoing]}
2713+ try:
2714+ request[l_name][conjugate] = [outgoing]
2715+ except:
2716+ request[l_name] = {conjugate: [outgoing]}
2717+
2718 # Loop on the structure to build exactly what is request
2719 for l_name in request:
2720 lorentz = eval('self.model.lorentz.%s' % l_name)
2721@@ -504,7 +535,14 @@
2722 # Compute routines
2723 self.compute_aloha(conjg_builder, symmetry=lorentz.name,
2724 routines=routines)
2725-
2726+
2727+ # Build mutiple lorentz call
2728+ for list_l_name, conjugate, outgoing in data:
2729+ if len(list_l_name) >1:
2730+ lorentzname = list_l_name[0]
2731+ for c in conjugate:
2732+ lorentzname += 'C%s' % c
2733+ self[(lorentzname, outgoing)].add_combine(list_l_name[1:])
2734
2735 def compute_aloha(self, builder, symmetry=None, routines=None):
2736 """ define all the AbstractRoutine linked to a given lorentz structure
2737@@ -521,7 +559,7 @@
2738 for outgoing in routines:
2739 symmetric = self.has_symmetries(symmetry, outgoing, valid_output=routines)
2740 if symmetric:
2741- self.get(symmetry, symmetric).add_symmetry(outgoing)
2742+ self.get(name, symmetric).add_symmetry(outgoing)
2743 else:
2744 wavefunction = builder.compute_routine(outgoing)
2745 #Store the information
2746@@ -590,9 +628,9 @@
2747 for i, part1 in enumerate(vertex.particles):
2748 for j in range(i-1,-1,-1):
2749 part2 = vertex.particles[j]
2750- if part1.name == part2.name and \
2751- part1.color == part2.color == 1 and\
2752- part1.spin != 2:
2753+ if part1.pdg_code == part2.pdg_code:
2754+ if part1.spin == 2 and (i % 2 != j % 2 ):
2755+ continue
2756 for lorentz in vertex.lorentz:
2757 if self.symmetries.has_key(lorentz.name):
2758 if self.symmetries[lorentz.name].has_key(i+1):
2759@@ -602,7 +640,46 @@
2760 else:
2761 self.symmetries[lorentz.name] = {i+1:j+1}
2762 break
2763+
2764+ def look_for_multiple_lorentz_interactions(self):
2765+ """Search the interaction associate with more than one lorentz structure.
2766+ If those lorentz structure have the same order and the same color then
2767+ associate a multiple lorentz routines to ALOHA """
2768+
2769+ orders = {}
2770+ for coup in self.model.all_couplings:
2771+ orders[coup.name] = str(coup.order)
2772+
2773+ for vertex in self.model.all_vertices:
2774+ if len(vertex.lorentz) == 1:
2775+ continue
2776+ #remove ghost
2777+ if -1 in vertex.lorentz[0].spins:
2778+ continue
2779+
2780+ # assign each order/color to a set of lorentz routine
2781+ combine = {}
2782+ for (id_col, id_lor), coup in vertex.couplings.items():
2783+ order = orders[coup.name]
2784+ key = (id_col, order)
2785+ if key in combine:
2786+ combine[key].append(id_lor)
2787+ else:
2788+ combine[key] = [id_lor]
2789
2790+ # Check if more than one routine are associated
2791+ for list_lor in combine.values():
2792+ if len(list_lor) == 1:
2793+ continue
2794+ list_lor.sort()
2795+ main = vertex.lorentz[list_lor[0]].name
2796+ if main not in self.multiple_lor:
2797+ self.multiple_lor[main] = []
2798+
2799+ info = tuple([vertex.lorentz[id].name for id in list_lor[1:]])
2800+ if info not in self.multiple_lor[main]:
2801+ self.multiple_lor[main].append(info)
2802+
2803 def has_massless_spin2(self):
2804 """Search if the spin2 particles are massless or not"""
2805
2806@@ -691,10 +768,10 @@
2807 aloha_files = []
2808
2809 # Identify the valid files
2810- alohafile_pattern = re.compile(r'''^[STFV]*[_C\d]*_\d%s''' % file_ext)
2811+ alohafile_pattern = re.compile(r'''_\d%s''' % file_ext)
2812 for filename in os.listdir(aloha_dir):
2813 if os.path.isfile(os.path.join(aloha_dir, filename)):
2814- if alohafile_pattern.match(filename):
2815+ if alohafile_pattern.search(filename):
2816 aloha_files.append(filename.replace(file_ext, comp_ext))
2817
2818 text="ALOHARoutine = "
2819
2820=== modified file 'input/mg5_configuration.txt'
2821--- input/mg5_configuration.txt 2011-04-01 09:24:18 +0000
2822+++ input/mg5_configuration.txt 2011-04-22 01:24:30 +0000
2823@@ -14,6 +14,7 @@
2824 ################################################################################
2825 #
2826 # This File contains some configuration variable for mg5
2827+# This File is use if the file ~/.mg5_config is not present.
2828 #
2829 ################################################################################
2830
2831@@ -21,3 +22,20 @@
2832 # Define the path to the pythia8 directory.
2833 # relative path start from mg5 directory
2834 pythia8_path = ./pythia8
2835+# symmetry_max_time
2836+# Set maximum time for trying to find symmetric diagrams for a single
2837+# matrix element. 0 means no timeout.
2838+symmetry_max_time= 600
2839+
2840+# Prefered Text Editor
2841+# Default: use the shell default Editor
2842+# or try to find one available on the system
2843+text_editor = None
2844+
2845+# Prefered WebBrower
2846+# If None: try to find one available on the system
2847+web_browser = None
2848+
2849+# Prefered PS viewer
2850+# If None: try to find one available on the system
2851+eps_viewer = None
2852
2853=== modified file 'madgraph/VERSION'
2854--- madgraph/VERSION 2011-04-12 16:49:18 +0000
2855+++ madgraph/VERSION 2011-04-22 01:24:30 +0000
2856@@ -1,2 +1,2 @@
2857-version = 1.0.0
2858-date = 2011-04-12
2859+version = 1.1.0
2860+date = 2011-04-22
2861
2862=== modified file 'madgraph/core/helas_objects.py'
2863--- madgraph/core/helas_objects.py 2011-04-03 22:06:00 +0000
2864+++ madgraph/core/helas_objects.py 2011-04-22 01:24:30 +0000
2865@@ -72,16 +72,16 @@
2866 # interaction_id = the id of the interaction in the model
2867 # pdg_codes = the pdg_codes property of the interaction, [11, -11, 22]
2868 # inter_color = the 'color' property of the interaction: []
2869- # lorentz = the 'lorentz' property of the interaction: ['']
2870+ # lorentz = the 'lorentz' property of the interaction: ('')
2871 # couplings = the coupling names from the interaction: {(0,0):'MGVX12'}
2872 self['interaction_id'] = 0
2873 self['pdg_codes'] = []
2874 self['orders'] = {}
2875 self['inter_color'] = None
2876- self['lorentz'] = ''
2877- self['coupling'] = 'none'
2878- # The Lorentz and color index used in this wavefunction
2879- self['coupl_key'] = (0, 0)
2880+ self['lorentz'] = []
2881+ self['coupling'] = ['none']
2882+ # The color index used in this wavefunction
2883+ self['color_key'] = 0
2884 # Properties relating to the leg/vertex
2885 # state = initial/final (for external bosons),
2886 # intermediate (for intermediate bosons),
2887@@ -206,28 +206,32 @@
2888 "%s is not a valid Color String" % str(value)
2889
2890 if name == 'lorentz':
2891- #Should be a string
2892- if not isinstance(value, str):
2893- raise self.PhysicsObjectError, \
2894- "%s is not a valid string" % str(value)
2895+ #Should be a list of string
2896+ if not isinstance(value, list):
2897+ raise self.PhysicsObjectError, \
2898+ "%s is not a valid tuple" % str(value)
2899+ for name in value:
2900+ if not isinstance(name, str):
2901+ raise self.PhysicsObjectError, \
2902+ "%s doesn't contain only string" % str(value)
2903
2904 if name == 'coupling':
2905- #Should be a string
2906- if not isinstance(value, str):
2907- raise self.PhysicsObjectError, \
2908- "%s is not a valid coupling string" % \
2909- str(value)
2910+ #Should be a list of string
2911+ if not isinstance(value, list):
2912+ raise self.PhysicsObjectError, \
2913+ "%s is not a valid coupling string" % str(value)
2914+ for name in value:
2915+ if not isinstance(name, str):
2916+ raise self.PhysicsObjectError, \
2917+ "%s doesn't contain only string" % str(value)
2918+ if len(value) == 0:
2919+ raise self.PhysicsObjectError, \
2920+ "%s should have at least one value" % str(value)
2921
2922- if name == 'coupl_key':
2923- if value and not isinstance(value, tuple):
2924- raise self.PhysicsObjectError, \
2925- "%s is not a valid tuple" % str(value)
2926- if len(value) != 2:
2927- raise self.PhysicsObjectError, \
2928- "%s is not a valid tuple with 2 elements" % str(value)
2929- if not isinstance(value[0], int) or not isinstance(value[1], int):
2930- raise self.PhysicsObjectError, \
2931- "%s is not a valid tuple of integer" % str(value)
2932+ if name == 'color_key':
2933+ if value and not isinstance(value, int):
2934+ raise self.PhysicsObjectError, \
2935+ "%s is not a valid integer" % str(value)
2936
2937 if name == 'state':
2938 if not isinstance(value, str):
2939@@ -320,9 +324,9 @@
2940 if inter.get('color'):
2941 self.set('inter_color', inter.get('color')[0])
2942 if inter.get('lorentz'):
2943- self.set('lorentz', inter.get('lorentz')[0])
2944+ self.set('lorentz', [inter.get('lorentz')[0]])
2945 if inter.get('couplings'):
2946- self.set('coupling', inter.get('couplings').values()[0])
2947+ self.set('coupling', [inter.get('couplings').values()[0]])
2948 return True
2949 elif name == 'particle':
2950 self.set('particle', model.get('particle_dict')[value])
2951@@ -343,7 +347,7 @@
2952
2953 return ['particle', 'antiparticle', 'is_part',
2954 'interaction_id', 'pdg_codes', 'orders', 'inter_color',
2955- 'lorentz', 'coupling', 'coupl_key', 'state', 'number_external',
2956+ 'lorentz', 'coupling', 'color_key', 'state', 'number_external',
2957 'number', 'fermionflow', 'mothers']
2958
2959 # Helper functions
2960@@ -369,8 +373,8 @@
2961 array_rep = array.array('i', [self['interaction_id']])
2962 # Need the coupling key, to distinguish between
2963 # wavefunctions from the same interaction but different
2964- # Lorentz or color structures
2965- array_rep.extend(list(self['coupl_key']))
2966+ # color structures
2967+ array_rep.append(self['color_key'])
2968 # Finally, the mother numbers
2969 array_rep.extend([mother['number'] for \
2970 mother in self['mothers']])
2971@@ -406,7 +410,7 @@
2972 particles[1].get_anti_pdg_code()\
2973 and self.get('coupling')[0] != '-':
2974 # We need a minus sign in front of the coupling
2975- self.set('coupling', '-' + self.get('coupling'))
2976+ self.set('coupling', ['-' + c for c in self.get('coupling')])
2977
2978 def set_octet_majorana_coupling_sign(self):
2979 """For octet Majorana fermions, need an extra minus sign in
2980@@ -418,7 +422,7 @@
2981 self.get_spin_state_number() == -2 and \
2982 self.get('self_antipart') and \
2983 [m.get('color') for m in self.get('mothers')] == [8, 8]:
2984- self.set('coupling', '-' + self.get('coupling'))
2985+ self.set('coupling', ['-' + c for c in self.get('coupling')])
2986
2987 def set_state_and_particle(self, model):
2988 """Set incoming/outgoing state according to mother states and
2989@@ -794,7 +798,7 @@
2990 if self.needs_hermitian_conjugate():
2991 res.append(self.get_conjugate_index())
2992
2993- return (tuple(res), self.get('lorentz'))
2994+ return (tuple(res), tuple(self.get('lorentz')))
2995
2996 def get_base_vertices(self, wf_dict = {}, vx_list = [], optimization = 1):
2997 """Recursive method to get a base_objects.VertexList
2998@@ -876,7 +880,7 @@
2999 # This is where recursion happens
3000 color_indices.extend(mother.get_color_indices())
3001 # Add this wf's color index
3002- color_indices.append(self.get('coupl_key')[0])
3003+ color_indices.append(self.get('color_key'))
3004
3005 return color_indices
3006
3007@@ -1058,7 +1062,7 @@
3008 # Check relevant directly defined properties
3009 if self['number_external'] != other['number_external'] or \
3010 self['fermionflow'] != other['fermionflow'] or \
3011- self['coupl_key'] != other['coupl_key'] or \
3012+ self['color_key'] != other['color_key'] or \
3013 self['lorentz'] != other['lorentz'] or \
3014 self['coupling'] != other['coupling'] or \
3015 self['state'] != other['state'] or \
3016@@ -1293,10 +1297,10 @@
3017 self['pdg_codes'] = []
3018 self['orders'] = {}
3019 self['inter_color'] = None
3020- self['lorentz'] = ''
3021- self['coupling'] = 'none'
3022+ self['lorentz'] = []
3023+ self['coupling'] = ['none']
3024 # The Lorentz and color index used in this amplitude
3025- self['coupl_key'] = (0, 0)
3026+ self['color_key'] = 0
3027 # Properties relating to the vertex
3028 self['number'] = 0
3029 self['fermionfactor'] = 0
3030@@ -1359,28 +1363,33 @@
3031 "%s is not a valid Color String" % str(value)
3032
3033 if name == 'lorentz':
3034- #Should be a string
3035- if not isinstance(value, str):
3036- raise self.PhysicsObjectError, \
3037- "%s is not a valid string" % str(value)
3038-
3039+ #Should be a list of string
3040+ if not isinstance(value, list):
3041+ raise self.PhysicsObjectError, \
3042+ "%s is not a valid list of string" % str(value)
3043+ for name in value:
3044+ if not isinstance(name, str):
3045+ raise self.PhysicsObjectError, \
3046+ "%s doesn't contain only string" % str(value)
3047+
3048 if name == 'coupling':
3049- #Should be a string
3050- if not isinstance(value, str):
3051- raise self.PhysicsObjectError, \
3052- "%s is not a valid coupling string" % \
3053- str(value)
3054+ #Should be a list of string
3055+ if not isinstance(value, list):
3056+ raise self.PhysicsObjectError, \
3057+ "%s is not a valid coupling (list of string)" % str(value)
3058+
3059+ for name in value:
3060+ if not isinstance(name, str):
3061+ raise self.PhysicsObjectError, \
3062+ "%s doesn't contain only string" % str(value)
3063+ if not len(value):
3064+ raise self.PhysicsObjectError, \
3065+ 'coupling should have at least one value'
3066
3067- if name == 'coupl_key':
3068- if value and not isinstance(value, tuple):
3069- raise self.PhysicsObjectError, \
3070- "%s is not a valid tuple" % str(value)
3071- if len(value) != 2:
3072- raise self.PhysicsObjectError, \
3073- "%s is not a valid tuple with 2 elements" % str(value)
3074- if not isinstance(value[0], int) or not isinstance(value[1], int):
3075- raise self.PhysicsObjectError, \
3076- "%s is not a valid tuple of integer" % str(value)
3077+ if name == 'color_key':
3078+ if value and not isinstance(value, int):
3079+ raise self.PhysicsObjectError, \
3080+ "%s is not a valid integer" % str(value)
3081
3082 if name == 'number':
3083 if not isinstance(value, int):
3084@@ -1416,6 +1425,30 @@
3085
3086 return True
3087
3088+ def __str__(self):
3089+ """ practicle way to represent an HelasAmplitude"""
3090+
3091+ mystr = '{\n'
3092+ for prop in self.get_sorted_keys():
3093+ if isinstance(self[prop], str):
3094+ mystr = mystr + ' \'' + prop + '\': \'' + \
3095+ self[prop] + '\',\n'
3096+ elif isinstance(self[prop], float):
3097+ mystr = mystr + ' \'' + prop + '\': %.2f,\n' % self[prop]
3098+ elif isinstance(self[prop], int):
3099+ mystr = mystr + ' \'' + prop + '\': %s,\n' % self[prop]
3100+ elif prop != 'mothers':
3101+ mystr = mystr + ' \'' + prop + '\': ' + \
3102+ str(self[prop]) + ',\n'
3103+ else:
3104+ info = [m.get('pdg_code') for m in self['mothers']]
3105+ mystr += ' \'%s\': %s,\n' % (prop, info)
3106+
3107+ mystr = mystr.rstrip(',\n')
3108+ mystr = mystr + '\n}'
3109+
3110+ return mystr
3111+
3112 # Enhanced get function
3113 def get(self, name):
3114 """Get the value of the property name."""
3115@@ -1453,9 +1486,9 @@
3116 if inter.get('color'):
3117 self.set('inter_color', inter.get('color')[0])
3118 if inter.get('lorentz'):
3119- self.set('lorentz', inter.get('lorentz')[0])
3120+ self.set('lorentz', [inter.get('lorentz')[0]])
3121 if inter.get('couplings'):
3122- self.set('coupling', inter.get('couplings').values()[0])
3123+ self.set('coupling', [inter.get('couplings').values()[0]])
3124 return True
3125 else:
3126 raise self.PhysicsObjectError, \
3127@@ -1467,7 +1500,7 @@
3128 """Return particle property names as a nicely sorted list."""
3129
3130 return ['interaction_id', 'pdg_codes', 'orders', 'inter_color',
3131- 'lorentz', 'coupling', 'coupl_key', 'number', 'color_indices',
3132+ 'lorentz', 'coupling', 'color_key', 'number', 'color_indices',
3133 'fermionfactor', 'mothers']
3134
3135
3136@@ -1516,7 +1549,7 @@
3137 if self.needs_hermitian_conjugate():
3138 res.append(self.get_conjugate_index())
3139
3140- return (tuple(res), self.get('lorentz'))
3141+ return (tuple(res), tuple(self.get('lorentz')))
3142
3143 def calculate_fermionfactor(self):
3144 """Calculate the fermion factor for the diagram corresponding
3145@@ -1770,7 +1803,7 @@
3146
3147 # Add this amp's color index
3148 if self.get('interaction_id'):
3149- color_indices.append(self.get('coupl_key')[0])
3150+ color_indices.append(self.get('color_key'))
3151
3152 return color_indices
3153
3154@@ -2218,15 +2251,22 @@
3155
3156 # Now generate new wavefunction for the last leg
3157
3158- # Need one amplitude for each Lorentz/color structure,
3159- # i.e. for each coupling
3160+ # Need one amplitude for each color structure,
3161+ done_color = {} # store link to color
3162 for coupl_key in sorted(inter.get('couplings').keys()):
3163+ color = coupl_key[0]
3164+ if color in done_color:
3165+ wf = done_color[color]
3166+ wf.get('coupling').append(inter.get('couplings')[coupl_key])
3167+ wf.get('lorentz').append(inter.get('lorentz')[coupl_key[1]])
3168+ continue
3169 wf = HelasWavefunction(last_leg, vertex.get('id'), model)
3170- wf.set('coupling', inter.get('couplings')[coupl_key])
3171+ wf.set('coupling', [inter.get('couplings')[coupl_key]])
3172 if inter.get('color'):
3173 wf.set('inter_color', inter.get('color')[coupl_key[0]])
3174- wf.set('lorentz', inter.get('lorentz')[coupl_key[1]])
3175- wf.set('coupl_key', coupl_key)
3176+ done_color[color] = wf
3177+ wf.set('lorentz', [inter.get('lorentz')[coupl_key[1]]])
3178+ wf.set('color_key', color)
3179 wf.set('mothers', mothers)
3180 # Need to set incoming/outgoing and
3181 # particle/antiparticle according to the fermion flow
3182@@ -2312,24 +2352,29 @@
3183 wf_number,
3184 False,
3185 number_to_wavefunctions)
3186-
3187+ done_color = {}
3188 for i, coupl_key in enumerate(keys):
3189+ color = coupl_key[0]
3190+ if inter and color in done_color.keys():
3191+ amp = done_color[color]
3192+ amp.get('coupling').append(inter.get('couplings')[coupl_key])
3193+ amp.get('lorentz').append(inter.get('lorentz')[coupl_key[1]])
3194+ continue
3195 amp = HelasAmplitude(lastvx, model)
3196 if inter:
3197- amp.set('coupling', inter.get('couplings')[coupl_key])
3198- amp.set('lorentz', inter.get('lorentz')[\
3199- coupl_key[1]])
3200+ amp.set('coupling', [inter.get('couplings')[coupl_key]])
3201+ amp.set('lorentz', [inter.get('lorentz')[coupl_key[1]]])
3202 if inter.get('color'):
3203- amp.set('inter_color', inter.get('color')[\
3204- coupl_key[0]])
3205- amp.set('coupl_key', coupl_key)
3206+ amp.set('inter_color', inter.get('color')[color])
3207+ amp.set('color_key', color)
3208+ done_color[color] = amp
3209 amp.set('mothers', mothers)
3210 amplitude_number = amplitude_number + 1
3211 amp.set('number', amplitude_number)
3212 # Add the list with color indices to the amplitude
3213 new_color_list = copy.copy(color_list)
3214 if inter:
3215- new_color_list.append(coupl_key[0])
3216+ new_color_list.append(color)
3217
3218 amp.set('color_indices', new_color_list)
3219
3220@@ -3291,7 +3336,7 @@
3221 """Return a list of (lorentz_name, conjugate, outgoing) with
3222 all lorentz structures used by this HelasMatrixElement."""
3223
3224- return [(wa.get('lorentz'), tuple(wa.get_conjugate_index()),
3225+ return [(tuple(wa.get('lorentz')), tuple(wa.get_conjugate_index()),
3226 wa.find_outgoing_number()) for wa in \
3227 self.get_all_wavefunctions() + self.get_all_amplitudes() \
3228 if wa.get('interaction_id') != 0]
3229@@ -3967,7 +4012,7 @@
3230 coupling_list = []
3231
3232 for me in self.get('matrix_elements'):
3233- coupling_list.extend(me.get_used_couplings())
3234+ coupling_list.extend([c for l in me.get_used_couplings() for c in l])
3235
3236 return list(set(coupling_list))
3237
3238
3239=== modified file 'madgraph/interface/cmd_interface.py'
3240--- madgraph/interface/cmd_interface.py 2011-04-11 19:58:39 +0000
3241+++ madgraph/interface/cmd_interface.py 2011-04-22 01:24:30 +0000
3242@@ -12,6 +12,7 @@
3243 # For more information, please visit: http://madgraph.phys.ucl.ac.be
3244 #
3245 ################################################################################
3246+from compiler.ast import Break
3247 """A user friendly command line interface to access MadGraph features.
3248 Uses the cmd package for command interpretation and tab completion.
3249 """
3250@@ -84,10 +85,10 @@
3251 'display multiparticles'],
3252 'generate': ['add process PROCESS','output [OUTPUT_TYPE] [PATH]','draw .'],
3253 'add process':['output [OUTPUT_TYPE] [PATH]', 'display processes'],
3254- 'output':['launch','history PATH', 'exit'],
3255+ 'output':['launch','open index.html','history PATH', 'exit'],
3256 'display': ['generate PROCESS', 'add process PROCESS', 'output [OUTPUT_TYPE] [PATH]'],
3257- 'draw': ['shell CMD'],
3258 'import proc_v4' : ['launch','exit'],
3259+ 'launch': ['open index.html','exit'],
3260 'tutorial': ['generate PROCESS', 'import model MODEL', 'help TOPIC']
3261 }
3262
3263@@ -280,9 +281,11 @@
3264 logger.info("-- display a the status of various internal state variables")
3265 logger.info(" for particles/interactions you can specify the name or id of the")
3266 logger.info(" particles/interactions to receive more details information.")
3267- logger.info(" example display particles e+.")
3268+ logger.info(" Example: display particles e+.")
3269 logger.info(" For \"checks\", can specify only to see failed checks.")
3270-
3271+ logger.info(" For \"diagrams\", you can specify where the file will be written.")
3272+ logger.info(" Example: display diagrams ./")
3273+
3274 def help_launch(self):
3275 """help for launch command"""
3276 _launch_parser.print_help()
3277@@ -291,8 +294,16 @@
3278 logger.info("syntax: tutorial [" + "|".join(self._tutorial_opts) + "]")
3279 logger.info("-- start/stop the tutorial mode")
3280
3281+ def help_open(self):
3282+ logger.info("syntax: open FILE ")
3283+ logger.info("-- open a file with the appropriate editor.")
3284+ logger.info(' If FILE belongs to index.html, param_card.dat, run_card.dat')
3285+ logger.info(' the path to the last created/used directory is used')
3286+ logger.info(' The program used to open those files can be chosen in the')
3287+ logger.info(' configuration file ./input/mg5_configuration.txt')
3288+
3289 def help_output(self):
3290- logger.info("syntax [" + "|".join(self._export_formats) + \
3291+ logger.info("syntax: output [" + "|".join(self._export_formats) + \
3292 "] [path|.|auto] [options]")
3293 logger.info("-- Output any generated process(es) to file.")
3294 logger.info(" mode: Default mode is madevent. Default path is \'.\' or auto.")
3295@@ -380,13 +391,13 @@
3296 logger.info(" If FILEPATH is omitted, the history will be output to stdout.")
3297 logger.info(" \"clean\" will remove all entries from the history.")
3298
3299- def help_draw(self):
3300- _draw_parser.print_help()
3301+# def help_draw(self):
3302+# _draw_parser.print_help()
3303
3304 def help_set(self):
3305 logger.info("syntax: set %s argument" % "|".join(self._set_options))
3306 logger.info("-- set options for generation or output")
3307- logger.info(" group_subprocesses_output True/False: ")
3308+ logger.info(" group_subprocesses True/False: ")
3309 logger.info(" Smart grouping of subprocesses into directories,")
3310 logger.info(" mirroring of initial states, and combination of")
3311 logger.info(" integration channels.")
3312@@ -397,7 +408,10 @@
3313 logger.info(" of the quarks given in multi_part_label.")
3314 logger.info(" These processes give negligible contribution to the")
3315 logger.info(" cross section but have subprocesses/channels.")
3316-
3317+ logger.info(" symmetry_max_time N")
3318+ logger.info(" (default 600) maximum time (in s) to find symmetric")
3319+ logger.info(" diagrams for each matrix element (0 means no timeout)")
3320+
3321 def help_shell(self):
3322 logger.info("syntax: shell CMD (or ! CMD)")
3323 logger.info("-- run the shell command CMD and catch output")
3324@@ -491,8 +505,7 @@
3325 """
3326
3327 if len(args) < 1:
3328- self.help_draw()
3329- raise self.InvalidCmd('\"draw\" command requires a directory path')
3330+ args.append('/tmp')
3331
3332 if not self._curr_amps:
3333 raise self.InvalidCmd("No process generated, please generate a process!")
3334@@ -665,6 +678,8 @@
3335 mode = self.find_output_type(path)
3336 args[0] = mode
3337 args.append(path)
3338+ # inform where we are for future command
3339+ self._done_export = [path, mode]
3340
3341
3342 def find_output_type(self, path):
3343@@ -714,7 +729,7 @@
3344 raise self.InvalidCmd('Possible options for set are %s' % \
3345 self._set_options)
3346
3347- if args[0] in ['group_subprocesses_output']:
3348+ if args[0] in ['group_subprocesses']:
3349 if args[1] not in ['False', 'True']:
3350 raise self.InvalidCmd('%s needs argument False or True' % \
3351 args[0])
3352@@ -727,7 +742,46 @@
3353 if args[1] not in ['DEBUG','INFO','WARNING','ERROR','CRITICAL']:
3354 raise self.InvalidCmd('output_level needs ' + \
3355 'a valid level')
3356+
3357+ def check_open(self, args):
3358+ """ check the validity of the line """
3359
3360+ if len(args) != 1:
3361+ self.help_open()
3362+ raise self.InvalidCmd('OPEN command requires exactly one argument')
3363+
3364+ if args[0].startswith('./'):
3365+ if not os.path.isfile(args[0]):
3366+ raise self.InvalidCmd('%s: not such file' % args[0])
3367+ return True
3368+
3369+ # if special : create the path.
3370+ if not self._done_export:
3371+ if not os.path.isfile(args[0]):
3372+ self.help_open()
3373+ raise self.InvalidCmd('No command \"output\" or \"launch\" used. Impossible to associate this name to a file')
3374+ else:
3375+ return True
3376+
3377+ path = self._done_export[0]
3378+ if os.path.isfile(os.path.join(path,args[0])):
3379+ args[0] = os.path.join(path,args[0])
3380+ elif os.path.isfile(os.path.join(path,'Cards',args[0])):
3381+ args[0] = os.path.join(path,'Cards',args[0])
3382+ elif os.path.isfile(os.path.join(path,'HTML',args[0])):
3383+ args[0] = os.path.join(path,'HTML',args[0])
3384+ # special for card with _default define: copy the default and open it
3385+ elif '_card.dat' in args[0]:
3386+ name = args[0].replace('_card.dat','_card_default.dat')
3387+ if os.path.isfile(os.path.join(path,'Cards', name)):
3388+ files.cp(path + '/Cards/' + name, path + '/Cards/'+ args[0])
3389+ args[0] = os.path.join(path,'Cards', args[0])
3390+ else:
3391+ raise self.InvalidCmd('No default path for this file')
3392+ elif not os.path.isfile(args[0]):
3393+ raise self.InvalidCmd('No default path for this file')
3394+
3395+
3396 def check_output(self, args):
3397 """ check the validity of the line"""
3398
3399@@ -746,7 +800,7 @@
3400
3401 if self._model_v4_path and \
3402 (self._export_format not in self._v4_export_formats or \
3403- self._options['group_subprocesses_output']):
3404+ self._options['group_subprocesses']):
3405 text = " The Model imported (MG4 format) does not contain enough\n "
3406 text += " information for this type of output. In order to create\n"
3407 text += " output for " + args[0] + ", you have to use a UFO model.\n"
3408@@ -763,30 +817,37 @@
3409 self.get_default_path()
3410 else:
3411 self._export_dir = path
3412-
3413- if not self._export_dir:
3414+ else:
3415 # No valid path
3416 self.get_default_path()
3417
3418- if self._done_export == (self._export_dir, self._export_format):
3419- # We have already done export in this path
3420- logger.info("Matrix elements already exported to directory %s" % \
3421- self._export_dir)
3422- return
3423-
3424- if self._export_format in ['madevent', 'standalone'] \
3425- and not self._mgme_dir and \
3426- os.path.realpath(self._export_dir) != os.path.realpath('.'):
3427- raise MadGraph5Error, \
3428- "To generate a new MG4 directory, you need a valid MG_ME path"
3429-
3430 self._export_dir = os.path.realpath(self._export_dir)
3431
3432
3433 def get_default_path(self):
3434 """Set self._export_dir to the default (\'auto\') path"""
3435+
3436+ if self._export_format in ['madevent', 'standalone']:
3437+ # Detect if this script is launched from a valid copy of the Template,
3438+ # if so store this position as standard output directory
3439+ if 'TemplateVersion.txt' in os.listdir('.'):
3440+ #Check for ./
3441+ self._export_dir = os.path.realpath('.')
3442+ return
3443+ elif 'TemplateVersion.txt' in os.listdir('..'):
3444+ #Check for ../
3445+ self._export_dir = os.path.realpath('..')
3446+ return
3447+ elif self.stdin != sys.stdin:
3448+ #Check for position defined by the input files
3449+ input_path = os.path.realpath(self.stdin.name).split(os.path.sep)
3450+ print "Not standard stdin, use input path"
3451+ if input_path[-2] == 'Cards':
3452+ self._export_dir = os.path.sep.join(input_path[:-2])
3453+ if 'TemplateVersion.txt' in self._export_dir:
3454+ return
3455
3456- if self._export_format.startswith('madevent'):
3457+ if self._export_format.startswith('madevent'):
3458 name_dir = lambda i: 'PROC_%s_%s' % \
3459 (self._curr_model['name'], i)
3460 auto_path = lambda i: os.path.join(self.writing_dir,
3461@@ -885,7 +946,10 @@
3462 """ not authorize on web"""
3463 raise self.WebRestriction('\"save\" command not authorize online')
3464
3465-
3466+ def check_open(self, args):
3467+ """ not authorize on web"""
3468+ raise self.WebRestriction('\"open\" command not authorize online')
3469+
3470 def check_output(self, args):
3471 """ check the validity of the line"""
3472
3473@@ -1141,7 +1205,37 @@
3474 # Filename if directory is not given
3475 if len(args) == 2:
3476 return self.path_completion(text)
3477-
3478+
3479+ def complete_open(self, text, line, begidx, endidx):
3480+ """ complete the open command """
3481+
3482+ args = split_arg(line[0:begidx])
3483+
3484+ # Directory continuation
3485+ if os.path.sep in args[-1] + text:
3486+ return self.path_completion(text,
3487+ os.path.join('.',*[a for a in args if \
3488+ a.endswith(os.path.sep)]))
3489+
3490+ possibility = []
3491+ if self._done_export:
3492+ path = self._done_export[0]
3493+ possibility = ['index.html']
3494+ if os.path.isfile(os.path.join(path,'README')):
3495+ possibility.append('README')
3496+ if os.path.isdir(os.path.join(path,'Cards')):
3497+ possibility += [f for f in os.listdir(os.path.join(path,'Cards'))
3498+ if f.endswith('.dat')]
3499+ if os.path.isdir(os.path.join(path,'HTML')):
3500+ possibility += [f for f in os.listdir(os.path.join(path,'HTML'))
3501+ if f.endswith('.html') and 'default' not in f]
3502+ else:
3503+ possibility.extend(['./','../'])
3504+ if os.path.exists('MG5_debug'):
3505+ possibility.append('MG5_debug')
3506+
3507+ return self.list_completion(text, possibility)
3508+
3509 def complete_output(self, text, line, begidx, endidx,
3510 possible_options = ['f', 'noclean', 'nojpeg'],
3511 possible_options_full = ['-f', '-noclean', '-nojpeg']):
3512@@ -1191,7 +1285,7 @@
3513 return self.list_completion(text, self._set_options)
3514
3515 if len(args) == 2:
3516- if args[1] in ['group_subprocesses_output']:
3517+ if args[1] in ['group_subprocesses']:
3518 return self.list_completion(text, ['False', 'True'])
3519
3520 elif args[1] in ['ignore_six_quark_processes']:
3521@@ -1340,8 +1434,8 @@
3522
3523 # Options and formats available
3524 _display_opts = ['particles', 'interactions', 'processes', 'diagrams',
3525- 'multiparticles', 'couplings', 'lorentz', 'checks',
3526- 'parameters']
3527+ 'diagrams_text', 'multiparticles', 'couplings', 'lorentz',
3528+ 'checks', 'parameters']
3529 _add_opts = ['process']
3530 _save_opts = ['model', 'processes']
3531 _tutorial_opts = ['start', 'stop']
3532@@ -1349,8 +1443,9 @@
3533 _import_formats = ['model_v4', 'model', 'proc_v4', 'command']
3534 _v4_export_formats = ['madevent', 'standalone', 'matrix']
3535 _export_formats = _v4_export_formats + ['standalone_cpp', 'pythia8']
3536- _set_options = ['group_subprocesses_output',
3537+ _set_options = ['group_subprocesses',
3538 'ignore_six_quark_processes',
3539+ 'symmetry_max_time',
3540 'stdout_level']
3541 # Variables to store object information
3542 _curr_model = None #base_objects.Model()
3543@@ -1391,21 +1486,6 @@
3544 mgme_dir)
3545 self._mgme_dir = MG4DIR
3546
3547- # Detect if this script is launched from a valid copy of the Template,
3548- # if so store this position as standard output directory
3549- if 'TemplateVersion.txt' in os.listdir('.'):
3550- #Check for ./
3551- self._export_dir = os.path.realpath('.')
3552- elif 'TemplateVersion.txt' in os.listdir('..'):
3553- #Check for ../
3554- self._export_dir = os.path.realpath('..')
3555- elif self.stdin != sys.stdin:
3556- #Check for position defined by the input files
3557- input_path = os.path.realpath(self.stdin.name).split(os.path.sep)
3558- print "Not standard stdin, use input path"
3559- if input_path[-2] == 'Cards':
3560- self._export_dir = os.path.sep.join(input_path[:-2])
3561-
3562 # Load the configuration file
3563 self.set_configuration()
3564
3565@@ -1447,7 +1527,7 @@
3566
3567 # Generate processes
3568 collect_mirror_procs = \
3569- self._options['group_subprocesses_output']
3570+ self._options['group_subprocesses']
3571 ignore_six_quark_processes = \
3572 self._options['ignore_six_quark_processes'] if \
3573 "ignore_six_quark_processes" in self._options \
3574@@ -1513,6 +1593,9 @@
3575 #check the validity of the arguments
3576 self.check_display(args)
3577
3578+ if args[0] == 'diagrams':
3579+ self.draw(' '.join(args[1:]))
3580+
3581 if args[0] == 'particles' and len(args) == 1:
3582 print "Current model contains %i particles:" % \
3583 len(self._curr_model['particles'])
3584@@ -1589,7 +1672,7 @@
3585 for amp in self._curr_amps:
3586 print amp.nice_string_processes()
3587
3588- elif args[0] == 'diagrams':
3589+ elif args[0] == 'diagrams_text':
3590 text = "\n".join([amp.nice_string() for amp in self._curr_amps])
3591 pydoc.pager(text)
3592
3593@@ -1691,7 +1774,7 @@
3594 "please run from a" + \
3595 "\n\t valid MG_ME directory.")
3596
3597- def do_draw(self, line):
3598+ def draw(self, line):
3599 """ draw the Feynman diagram for the given process """
3600
3601 args = split_arg(line)
3602@@ -1728,6 +1811,7 @@
3603 amp.get('process').nice_string())
3604 plot.draw(opt=options)
3605 logger.info("Wrote file " + filename)
3606+ self.exec_cmd('open %s' % filename)
3607
3608 stop = time.time()
3609 logger.info('time to draw %s' % (stop - start))
3610@@ -1820,6 +1904,9 @@
3611 # Also reset _export_format and _export_dir
3612 self._export_format = None
3613
3614+ # Remove previous generations from history
3615+ self.clean_history('generate', 'add process')
3616+
3617 # Call add process
3618 args = split_arg(line)
3619 args.insert(0, 'process')
3620@@ -1958,7 +2045,7 @@
3621 # leg.get('state') == False,
3622 # myleglist)) == 1
3623
3624- if overall_orders and self._options['group_subprocesses_output']:
3625+ if overall_orders and self._options['group_subprocesses']:
3626 raise MadGraph5Error, \
3627 "For grouped subprocess output, orders should be specified for each process (no overall orders after @N)"
3628
3629@@ -2134,7 +2221,18 @@
3630
3631 if self.log:
3632 logger.info("History written to " + output_file.name)
3633-
3634+
3635+ def clean_history(self,*arguments):
3636+ """Remove all commands in arguments from history"""
3637+
3638+ nline = 0
3639+ arguments = list(arguments) + ['display', 'open', 'launch', 'output']
3640+ while nline < len(self.history) - 1:
3641+ if any([self.history[nline].startswith(arg) for arg in arguments]):
3642+ self.history.pop(nline)
3643+ else:
3644+ nline += 1
3645+
3646 # Import files
3647 def do_import(self, line):
3648 """Import files with external formats"""
3649@@ -2146,7 +2244,9 @@
3650 if args[0].startswith('model'):
3651 self._model_v4_path = None
3652 # Clear history, amplitudes and matrix elements when a model is imported
3653- self.history = self.history[-1:]
3654+ # Remove previous imports, generations and outputs from history
3655+ self.clean_history('import', 'generate', 'add process')
3656+ # Reset amplitudes and matrix elements
3657 self._curr_amps = diagram_generation.AmplitudeList()
3658 self._curr_matrix_elements = helas_objects.HelasMultiProcess()
3659 # Import model
3660@@ -2157,7 +2257,7 @@
3661 helas_call_writers.FortranHelasCallWriter(\
3662 self._curr_model)
3663 # Automatically turn off subprocess grouping
3664- self.do_set('group_subprocesses_output False')
3665+ self.do_set('group_subprocesses False')
3666 else:
3667 self._curr_model = import_ufo.import_model(args[1])
3668 self._curr_fortran_model = \
3669@@ -2167,7 +2267,7 @@
3670 helas_call_writers.CPPUFOHelasCallWriter(\
3671 self._curr_model)
3672 # Automatically turn on subprocess grouping
3673- self.do_set('group_subprocesses_output True')
3674+ self.do_set('group_subprocesses True')
3675
3676 if '-modelname' not in args:
3677 self._curr_model.pass_particles_name_in_mg_default()
3678@@ -2181,6 +2281,9 @@
3679 process_checks.store_aloha = []
3680
3681 elif args[0] == 'command':
3682+ # Remove previous imports, generations and outputs from history
3683+ self.clean_history('import', 'generate', 'add process')
3684+
3685 if not os.path.isfile(args[1]):
3686 raise MadGraph5Error("Path %s is not a valid pathname" % args[1])
3687 else:
3688@@ -2192,6 +2295,9 @@
3689
3690 elif args[0] == 'proc_v4':
3691
3692+ # Remove previous imports, generations and outputs from history
3693+ self.clean_history('import', 'generate', 'add process')
3694+
3695 if len(args) == 1 and self._export_dir:
3696 proc_card = os.path.join(self._export_dir, 'Cards', \
3697 'proc_card.dat')
3698@@ -2327,7 +2433,10 @@
3699 """ assign all configuration variable from file
3700 ./input/mg5_configuration.txt. assign to default if not define """
3701
3702- config = {'pythia8_path': './pythia8'}
3703+ self.configuration = {'pythia8_path': './pythia8',
3704+ 'web_browser':None,
3705+ 'eps_viewer':None,
3706+ 'text_editor':None}
3707
3708 if not config_path:
3709 try:
3710@@ -2351,21 +2460,81 @@
3711 else:
3712 name = name.strip()
3713 value = value.strip()
3714- config[name] = value
3715+ self.configuration[name] = value
3716+ if value.lower() == "none":
3717+ self.configuration[name] = None
3718
3719 # Treat each expected input
3720 # 1: Pythia8_path
3721 # try relative path
3722- pythia8_dir = os.path.join(MG5DIR, config['pythia8_path'])
3723- if not os.path.isfile(os.path.join(pythia8_dir, 'include', 'Pythia.h')):
3724- if os.path.isfile(os.path.join(config['pythia8_path'], 'include', 'Pythia.h')):
3725- pythia8_dir = config['pythia8_path']
3726+ for key in self.configuration:
3727+ if key == 'pythia8_path':
3728+ pythia8_dir = os.path.join(MG5DIR, self.configuration['pythia8_path'])
3729+ if not os.path.isfile(os.path.join(pythia8_dir, 'include', 'Pythia.h')):
3730+ if os.path.isfile(os.path.join(self.configuration['pythia8_path'], 'include', 'Pythia.h')):
3731+ pythia8_dir = self.configuration['pythia8_path']
3732+ else:
3733+ pythia8_dir = None
3734+ self.pythia8_path = pythia8_dir
3735+ elif key == 'text_editor':
3736+ # Treat text editor -> overwrites madgraph value
3737+ if self.configuration[key] and not misc.which(self.configuration[key]):
3738+ logger.warning('Specified text editor %s not valid.' % \
3739+ self.configuration[key])
3740+ self.configuration[key] = None
3741+ if self.configuration[key]:
3742+ # All is good
3743+ pass
3744+ elif os.environ.has_key('EDITOR'):
3745+ self.configuration[key] = os.environ['EDITOR']
3746+ else:
3747+ prog = ['vi', 'emacs', 'vim', 'gedit', 'nano']
3748+ for p in prog:
3749+ if misc.which(p):
3750+ self.configuration[key] = p
3751+ logger.warning(('Using default text editor \"%s\". ' % p) + \
3752+ 'Set text_editor in ./input/mg5_configuration.txt')
3753+ break
3754+ if not self.configuration[key]:
3755+ logger.warning('No valid text editor found. ' + \
3756+ 'Please set in ./input/mg5_configuration.txt')
3757+ elif key == 'eps_viewer':
3758+ if self.configuration[key]:
3759+ continue
3760+ prog = ['gv', 'ggv', 'evince']
3761+ for p in prog:
3762+ if misc.which(p):
3763+ self.configuration[key] = p
3764+ logger.warning(('Using default eps viewer \"%s\". ' % p) + \
3765+ 'Set eps_viewer in ./input/mg5_configuration.txt')
3766+ break
3767+ if not self.configuration[key] and sys.platform != 'darwin':
3768+ logger.warning('No valid eps viewer found. ' + \
3769+ 'Please set in ./input/mg5_configuration.txt')
3770+ elif key == 'web_browser':
3771+ if self.configuration[key]:
3772+ continue
3773+ prog = ['firefox', 'chrome', 'safari','opera']
3774+ for p in prog:
3775+ if misc.which(p):
3776+ self.configuration[key] = p
3777+ logger.warning(('Using default web browser \"%s\". ' % p) + \
3778+ 'Set web_browser in ./input/mg5_configuration.txt')
3779+ break
3780+ if not self.configuration[key] and sys.platform != 'darwin':
3781+ logger.warning('No valid web browser found. ' + \
3782+ 'Please set in ./input/mg5_configuration.txt')
3783 else:
3784- pythia8_dir = None
3785- self.pythia8_path = pythia8_dir
3786-
3787- return config
3788-
3789+ # Default: try to set parameter
3790+ try:
3791+ self.do_set("%s %s" % (key, self.configuration[key]))
3792+ except MadGraph5Error:
3793+ logger.warning("Option %s from config file not understood" \
3794+ % key)
3795+
3796+
3797+ return self.configuration
3798+
3799 def check_for_export_dir(self, filepath):
3800 """Check if the files is in a valid export directory and assign it to
3801 export path if if is"""
3802@@ -2396,16 +2565,28 @@
3803 # args is now MODE PATH
3804
3805 if args[0].startswith('standalone'):
3806- ext_program = launch_ext.SALauncher(args[1], self.timeout, **options)
3807+ ext_program = launch_ext.SALauncher(args[1], self.timeout,
3808+ configuration = self.configuration,
3809+ **options)
3810 elif args[0] == 'madevent':
3811- ext_program = launch_ext.MELauncher(args[1], self.timeout, **options)
3812+ #check if this is a cross-section
3813+ if len(self._generate_info.split('>')[0].strip().split())>1:
3814+ ext_program = launch_ext.MELauncher(args[1], self.timeout,
3815+ configuration = self.configuration,
3816+ **options)
3817+ else:
3818+ # This is a width computation
3819+ ext_program = launch_ext.MELauncher(args[1], self.timeout, unit='GeV',
3820+ configuration = self.configuration,
3821+ **options)
3822 elif args[0] == 'pythia8':
3823- ext_program = launch_ext.Pythia8Launcher(args[1], self.timeout, **options)
3824+ ext_program = launch_ext.Pythia8Launcher(args[1], self.timeout,
3825+ configuration = self.configuration,
3826+ **options)
3827 else:
3828 raise self.InvalidCmd , '%s cannot be run from MG5 interface' % args[0]
3829
3830
3831-
3832 ext_program.run()
3833
3834
3835@@ -2478,10 +2659,10 @@
3836 raise self.RWError('Could not load processes from file %s' % args[1])
3837 if self._model_v4_path:
3838 # Automatically turn off subprocess grouping
3839- self.do_set('group_subprocesses_output False')
3840+ self.do_set('group_subprocesses False')
3841 else:
3842 # Automatically turn on subprocess grouping
3843- self.do_set('group_subprocesses_output True')
3844+ self.do_set('group_subprocesses True')
3845
3846
3847 def do_save(self, line):
3848@@ -2527,22 +2708,40 @@
3849 self._curr_model.get_particle(q).get('name') \
3850 for q in self._options[args[0]]]))
3851
3852- elif args[0] == 'group_subprocesses_output':
3853+ elif args[0] == 'group_subprocesses':
3854 self._options[args[0]] = eval(args[1])
3855- logger.info('Set group_subprocesses_output to %s' % \
3856+ logger.info('Set group_subprocesses to %s' % \
3857+ str(self._options[args[0]]))
3858+
3859+ elif args[0] == 'symmetry_max_time':
3860+ self._options[args[0]] = int(args[1])
3861+ logger.info('Set symmetry_max_time to %s' % \
3862 str(self._options[args[0]]))
3863
3864 elif args[0] == "stdout_level":
3865 logging.root.setLevel(eval('logging.' + args[1]))
3866 logging.getLogger('madgraph').setLevel(eval('logging.' + args[1]))
3867 logger.info('set output information to level: %s' % args[1])
3868-
3869+
3870+ def do_open(self, line):
3871+ """Open a text file/ eps file / html file"""
3872+
3873+ args = split_arg(line)
3874+ # Check Argument validity and modify argument to be the real path
3875+ self.check_open(args)
3876+ file_path = args[0]
3877+
3878+ launch_ext.open_file(file_path, self.configuration)
3879+
3880 def do_output(self, line):
3881 """Initialize a new Template or reinitialize one"""
3882
3883 args = split_arg(line)
3884 # Check Argument validity
3885 self.check_output(args)
3886+
3887+ # Remove previous outputs from history
3888+ self.clean_history()
3889
3890 noclean = '-noclean' in args
3891 force = '-f' in args
3892@@ -2553,11 +2752,6 @@
3893 except:
3894 pass
3895
3896- if self._done_export == (self._export_dir, self._export_format):
3897- logger.info('Matrix elements already exported to directory %s' % \
3898- self._export_dir)
3899- return
3900-
3901 if not force and not noclean and os.path.isdir(self._export_dir)\
3902 and self._export_format in ['madevent', 'standalone']:
3903 # Don't ask if user already specified force or noclean
3904@@ -2568,13 +2762,14 @@
3905 raise MadGraph5Error('Stopped by user request')
3906
3907 group_subprocesses = self._export_format == 'madevent' and \
3908- self._options['group_subprocesses_output']
3909+ self._options['group_subprocesses']
3910 # Make a Template Copy
3911 if self._export_format == 'madevent':
3912 if group_subprocesses:
3913 self._curr_exporter = export_v4.ProcessExporterFortranMEGroup(\
3914 self._mgme_dir, self._export_dir,
3915- not noclean)
3916+ not noclean,
3917+ self._options["symmetry_max_time"])
3918 else:
3919 self._curr_exporter = export_v4.ProcessExporterFortranME(\
3920 self._mgme_dir, self._export_dir,
3921@@ -2596,6 +2791,12 @@
3922 # Perform export and finalize right away
3923 self.export(nojpeg, main_file_name)
3924
3925+ # Automatically run finalize
3926+ self.finalize(nojpeg)
3927+
3928+ # Remember that we have done export
3929+ self._done_export = (self._export_dir, self._export_format)
3930+
3931 # Reset _export_dir, so we don't overwrite by mistake later
3932 self._export_dir = None
3933
3934@@ -2615,7 +2816,7 @@
3935 cpu_time1 = time.time()
3936 ndiags = 0
3937 if not self._curr_matrix_elements.get_matrix_elements():
3938- if self._options['group_subprocesses_output']:
3939+ if self._options['group_subprocesses']:
3940 cpu_time1 = time.time()
3941 dc_amps = [amp for amp in self._curr_amps if isinstance(amp, \
3942 diagram_generation.DecayChainAmplitude)]
3943@@ -2780,12 +2981,12 @@
3944
3945 if self._export_format == 'pythia8':
3946 logger.info("- All necessary files for Pythia 8 generated.")
3947- logger.info(" Please go to %s/examples and run" % path)
3948+ logger.info("- Run \"launch\" and select %s.cc," % filename)
3949+ logger.info(" or go to %s/examples and run" % path)
3950 logger.info(" make -f %s" % make_filename)
3951 logger.info(" (with process_name replaced by process name).")
3952 logger.info(" You can then run ./%s to produce events for the process" % \
3953 filename)
3954- logger.info("- Or run launch and select %s.cc." % filename)
3955
3956 # Replace the amplitudes with the actual amplitudes from the
3957 # matrix elements, which allows proper diagram drawing also of
3958@@ -2794,12 +2995,6 @@
3959 [me.get('base_amplitude') for me in \
3960 matrix_elements])
3961
3962- # Remember that we have done export
3963- self._done_export = (self._export_dir, self._export_format)
3964-
3965- # Automatically run finalize
3966- self.finalize(nojpeg)
3967-
3968 def finalize(self, nojpeg, online = False):
3969 """Make the html output, write proc_card_mg5.dat and create
3970 madevent.tar.gz for a MadEvent directory"""
3971@@ -2844,12 +3039,9 @@
3972 if self._export_format in ['madevent', 'standalone', 'standalone_cpp']:
3973 logger.info('Output to directory ' + self._export_dir + ' done.')
3974 if self._export_format == 'madevent':
3975- logger.info('Please see ' + self._export_dir + '/README')
3976- logger.info('for information about how to generate events from this process.')
3977- logger.info('You can also use the launch command.')
3978-
3979- #reinitialize to empty the default output dir
3980- self._export_dir = None
3981+ logger.info('Type \"launch\" to generate events from this process, or see')
3982+ logger.info(self._export_dir + '/README')
3983+ logger.info('Run \"open index.html\" to see more information about this process.')
3984
3985 def do_help(self, line):
3986 """ propose some usefull possible action """
3987
3988=== modified file 'madgraph/interface/launch_ext_program.py'
3989--- madgraph/interface/launch_ext_program.py 2011-04-04 09:45:24 +0000
3990+++ madgraph/interface/launch_ext_program.py 2011-04-22 01:24:30 +0000
3991@@ -18,6 +18,7 @@
3992 import os
3993 import pydoc
3994 import re
3995+import sys
3996 import subprocess
3997 import time
3998
3999@@ -38,40 +39,20 @@
4000 cards = [] # files can be modified (path from self.card_dir)
4001 force = False
4002
4003- def __init__(self, running_dir, card_dir='', timeout=None, **options):
4004+ def __init__(self, running_dir, card_dir='', timeout=None, configuration = {},
4005+ **options):
4006 """ initialize an object """
4007
4008 self.running_dir = running_dir
4009 self.card_dir = os.path.join(self.running_dir, card_dir)
4010 self.timeout = timeout
4011- self.found_editor()
4012+ self.configuration = configuration
4013
4014 #include/overwrite options
4015 for key,value in options.items():
4016 setattr(self, key, value)
4017
4018
4019- def found_editor(self):
4020- """ found a (shell) program for editing file """
4021-
4022- # let first try to use the prefer editor (if EDITOR is define)
4023- # if not define use the first define in a pre-define list
4024-
4025- if os.environ.has_key('EDITOR') and misc.which(os.environ['EDITOR']):
4026- self.editor = os.environ['EDITOR']
4027- return
4028-
4029- logger.info('INFO: You can choose your prefered editor by defining the shell variable EDITOR')
4030-
4031- possibility = ['vi', 'emacs', 'vim', 'gedit', 'nano']
4032- for editor in possibility:
4033- if misc.which(editor):
4034- self.editor = editor
4035- return
4036-
4037- logger.warning(
4038- 'No valid editor detected. Please configure the shell variable EDITOR')
4039-
4040 def run(self):
4041 """ execute the main code """
4042
4043@@ -94,8 +75,8 @@
4044 """edit a file"""
4045
4046 path = os.path.realpath(path)
4047- subprocess.call([self.editor, path], cwd=os.getcwd())
4048-
4049+ open_file(path, self.configuration)
4050+
4051 def ask(self, question, default, choices=[], path_info=[]):
4052 """ ask a question """
4053
4054@@ -192,16 +173,16 @@
4055
4056 cards = ['param_card.dat', 'run_card.dat']
4057
4058- def __init__(self, running_dir, timeout, **option):
4059+ def __init__(self, running_dir, timeout, unit='pb', **option):
4060 """ initialize the StandAlone Version"""
4061
4062-
4063 ExtLauncher.__init__(self, running_dir, './Cards', timeout, **option)
4064 self.executable = os.path.join('.', 'bin','generate_events')
4065
4066 assert hasattr(self, 'cluster')
4067 assert hasattr(self, 'name')
4068-
4069+ self.unit = unit
4070+
4071 # Check for pythia-pgs directory
4072 if os.path.isdir(os.path.join(MG5DIR,'pythia-pgs')):
4073 self.pythia = os.path.join(MG5DIR,'pythia-pgs')
4074@@ -221,7 +202,7 @@
4075
4076 # Assign a valid run name if not put in options
4077 if self.name == '':
4078- for i in range(1000):
4079+ for i in range(1,1000):
4080 path = os.path.join(self.running_dir, 'Events','run_%02i_banner.txt' % i)
4081 if not os.path.exists(path):
4082 self.name = 'run_%02i' % i
4083@@ -282,6 +263,13 @@
4084 def launch_program(self):
4085 """launch the main program"""
4086
4087+ # Open the corresponding crossx.html page
4088+ os.system('touch %s' % os.path.join(self.running_dir,'RunWeb'))
4089+ subprocess.call([os.path.join('bin','gen_crossxhtml-pl')],
4090+ cwd=self.running_dir)
4091+ open_file(os.path.join(self.running_dir, 'HTML', 'crossx.html'),
4092+ self.configuration)
4093+
4094 mode = str(self.cluster)
4095 if mode == "0":
4096 subprocess.call([self.executable, mode, self.name],
4097@@ -308,7 +296,10 @@
4098 line = fsock.readline()
4099 cross, error = line.split()[0:2]
4100
4101- logger.info('The total cross-section is %s +- %s pb' % (cross, error))
4102+ if self.unit != 'GeV':
4103+ logger.info('The total cross-section is %s +- %s %s' % (cross, error, self.unit))
4104+ else:
4105+ logger.info('The width is %s +- %s GeV' % (cross, error))
4106 logger.info('more information in %s'
4107 % os.path.join(self.running_dir, 'index.html'))
4108
4109@@ -429,9 +420,60 @@
4110
4111 print "Output of the run is found at " + \
4112 os.path.realpath(os.path.join(self.running_dir, self.name))
4113-
4114-
4115-
4116-
4117-
4118-
4119+
4120+#
4121+# Global function to open supported file types
4122+#
4123+def open_file(file_path, configuration):
4124+ """Open file if supported type, using program given by the dict configuration"""
4125+
4126+ try:
4127+ extension = file_path.rsplit('.',1)[1]
4128+ except IndexError:
4129+ extension = ''
4130+
4131+ # For MAC:
4132+ if sys.platform == 'darwin':
4133+ if extension == 'html':
4134+ html_v = configuration['web_browser']
4135+ if misc.which(html_v):
4136+ os.system('%s %s &' % (html_v, file_path))
4137+ elif html_v:
4138+ os.system('open -a %s %s' % (html_v,file_path))
4139+ else:
4140+ os.system('open %s' % file_path)
4141+ elif extension in ['ps', 'eps']:
4142+ eps_v = configuration['eps_viewer']
4143+ if misc.which(eps_v):
4144+ os.system('%s %s &' % (eps_v, file_path))
4145+ elif eps_v:
4146+ os.system('open -a %s %s' % (eps_v,file_path))
4147+ else:
4148+ os.system('open %s' % file_path)
4149+ else:
4150+ if misc.which(configuration['text_editor']):
4151+ subprocess.call([configuration['text_editor'], file_path])
4152+ else:
4153+ logger.warning('Unable to find a valid editor for text file. Please specify one in ./input/mg5_configuration.txt')
4154+ # For Linux
4155+ else:
4156+ if extension == 'html':
4157+ if configuration['web_browser']:
4158+ os.system('%s %s &' %
4159+ (configuration['web_browser'],file_path))
4160+ else:
4161+ logger.warning('No valid web browser found. ' + \
4162+ 'Please set in ./input/mg5_configuration.txt')
4163+ elif extension in ['ps', 'eps']:
4164+ if configuration['eps_viewer']:
4165+ os.system('%s %s &' %
4166+ (configuration['eps_viewer'],file_path))
4167+ else:
4168+ logger.warning('No valid eps viewer found. ' + \
4169+ 'Please set in ./input/mg5_configuration.txt')
4170+ else:
4171+ if misc.which(configuration['text_editor']):
4172+ subprocess.call([configuration['text_editor'], file_path])
4173+ else:
4174+ logger.warning('No valid text editor found. ' + \
4175+ 'Please set in ./input/mg5_configuration.txt')
4176
4177=== modified file 'madgraph/interface/tutorial_text.py'
4178--- madgraph/interface/tutorial_text.py 2011-03-30 17:27:49 +0000
4179+++ madgraph/interface/tutorial_text.py 2011-04-22 01:24:30 +0000
4180@@ -152,33 +152,30 @@
4181 or from the shell:
4182 ./bin/mg5 my_mg5_cmd.dat
4183
4184-It is also possible to display this file directly from MG5 by
4185-launching a shell command. For example:
4186-mg5>shell less my_mg5_cmd.dat
4187+It is also possible to display this file directly from MG5:
4188+mg5>open ./my_mg5_cmd.dat
4189 """
4190
4191-shell = """
4192+
4193+
4194+open = """
4195+Note that in order to open some file, you might be need to use a shell command.
4196 Any shell command can be launched by MG5, by running \"shell\" or
4197 starting the line by an exclamation mark (!).
4198
4199-The final command of the tutorial is draw. This allows you to draw and
4200+The final command of the tutorial is display diagrams. This allows you to draw and
4201 look at the diagrams for your processes (in eps format) before
4202 creating an output for a given format. This can be useful for a fast
4203-check of your process. In order to draw diagrams, you need to specify
4204-a directory where the eps files will be written:
4205-mg5>draw .
4206+check of your process. For this last command, we will also show how combine
4207+different command in a single line:
4208+mg5>generate p p > go go; display diagrams
4209
4210 Note that when you run output [madevent_v4], the diagrams are
4211 automatically written to the matrix.ps files in subprocess
4212 directory, just like with MadGraph 4.
4213 """
4214
4215-draw = """
4216-You can look at the diagrams for example by running
4217-mg5>!gv ./diagrams_0_gg_ttx.eps
4218-or on MacOS X
4219-mg5>!open ./diagrams_0_gg_ttx.eps
4220-
4221+display_diagrams = """
4222 This command was the last step of the tutorial.
4223 Quit the tutorial by typing:
4224 mg5>tutorial stop
4225
4226=== modified file 'madgraph/iolibs/export_cpp.py'
4227--- madgraph/iolibs/export_cpp.py 2011-04-12 16:37:14 +0000
4228+++ madgraph/iolibs/export_cpp.py 2011-04-22 01:24:30 +0000
4229@@ -20,6 +20,7 @@
4230 import glob
4231 import itertools
4232 import logging
4233+from math import fmod
4234 import os
4235 import re
4236 import shutil
4237@@ -231,7 +232,10 @@
4238 else:
4239 self.process_string = self.processes[0].base_string()
4240
4241- self.process_number = process_number
4242+ if process_number:
4243+ self.process_number = process_number
4244+ else:
4245+ self.process_number = self.processes[0].get('id')
4246
4247 self.process_name = self.get_process_name()
4248 self.process_class = "CPPProcess"
4249@@ -240,7 +244,7 @@
4250 self.helas_call_writer = cpp_helas_call_writer
4251
4252 if not isinstance(self.helas_call_writer, helas_call_writers.CPPUFOHelasCallWriter):
4253- raise ProcessExporterCPPError, \
4254+ raise self.ProcessExporterCPPError, \
4255 "helas_call_writer not CPPUFOHelasCallWriter"
4256
4257 self.nexternal, self.ninitial = \
4258@@ -277,6 +281,23 @@
4259 wf.set('number', wf_number)
4260 self.wavefunctions.append(wf)
4261
4262+ # Also combine amplitudes
4263+ self.amplitudes = helas_objects.HelasAmplitudeList()
4264+ amp_number = 0
4265+ for me in self.matrix_elements:
4266+ for iamp, amp in enumerate(me.get_all_amplitudes()):
4267+ try:
4268+ old_amp = \
4269+ self.amplitudes[self.amplitudes.index(amp)]
4270+ amp.set('number', old_amp.get('number'))
4271+ except ValueError:
4272+ amp_number += 1
4273+ amp.set('number', amp_number)
4274+ self.amplitudes.append(amp)
4275+ diagram = helas_objects.HelasDiagram({'amplitudes': self.amplitudes})
4276+ self.amplitudes = helas_objects.HelasMatrixElement({\
4277+ 'diagrams': helas_objects.HelasDiagramList([diagram])})
4278+
4279 # Methods for generation of process files for C++
4280
4281 def generate_process_files(self):
4282@@ -411,8 +432,11 @@
4283 """// Calculate wavefunctions
4284 void calculate_wavefunctions(const int perm[], const int hel[]);
4285 static const int nwavefuncs = %d;
4286- std::complex<double> w[nwavefuncs][18];""" % \
4287- len(self.wavefunctions)
4288+ std::complex<double> w[nwavefuncs][18];
4289+ static const int namplitudes = %d;
4290+ std::complex<double> amp[namplitudes];""" % \
4291+ (len(self.wavefunctions),
4292+ len(self.amplitudes.get_all_amplitudes()))
4293 replace_dict['all_matrix_definitions'] = \
4294 "\n".join(["double matrix_%s();" % \
4295 me.get('processes')[0].shell_string().\
4296@@ -543,7 +567,7 @@
4297 return ret_lines
4298
4299
4300- def get_calculate_wavefunctions(self, wavefunctions):
4301+ def get_calculate_wavefunctions(self, wavefunctions, amplitudes):
4302 """Return the lines for optimized calculation of the
4303 wavefunctions for all subprocesses"""
4304
4305@@ -555,6 +579,9 @@
4306 self.helas_call_writer.get_wavefunction_calls(\
4307 helas_objects.HelasWavefunctionList(wavefunctions)))
4308
4309+ replace_dict['amplitude_calls'] = "\n".join(\
4310+ self.helas_call_writer.get_amplitude_calls(amplitudes))
4311+
4312 file = read_template_file(self.process_wavefunction_template) % \
4313 replace_dict
4314
4315@@ -645,7 +672,7 @@
4316 class_name)
4317 ret_lines.append("// Calculate wavefunctions for all processes")
4318 ret_lines.append(self.get_calculate_wavefunctions(\
4319- self.wavefunctions))
4320+ self.wavefunctions, self.amplitudes))
4321 ret_lines.append("}")
4322 else:
4323 ret_lines.extend([self.get_sigmaKin_single_process(i, me) \
4324@@ -702,6 +729,7 @@
4325 matrix_element.get('processes')[0].shell_string().replace("0_", "")
4326
4327
4328+ # Wavefunction and amplitude calls
4329 if self.single_helicities:
4330 replace_dict['matrix_args'] = ""
4331 replace_dict['all_wavefunction_calls'] = "int i, j;"
4332@@ -710,8 +738,9 @@
4333 wavefunctions = matrix_element.get_all_wavefunctions()
4334 replace_dict['all_wavefunction_calls'] = \
4335 """const int nwavefuncs = %d;
4336- std::complex<double> w[nwavefuncs][18];\n""" % len(wavefunctions)+ \
4337- self.get_calculate_wavefunctions(wavefunctions)
4338+ std::complex<double> w[nwavefuncs][18];
4339+ """ % len(wavefunctions)+ \
4340+ self.get_calculate_wavefunctions(wavefunctions, [])
4341
4342 # Process name
4343 replace_dict['process_class_name'] = class_name
4344@@ -728,9 +757,6 @@
4345 replace_dict['color_matrix_lines'] = \
4346 self.get_color_matrix_lines(matrix_element)
4347
4348- # The Helicity amplitude calls
4349- replace_dict['amplitude_calls'] = "\n".join(\
4350- self.helas_call_writer.get_amplitude_calls(matrix_element))
4351 replace_dict['jamp_lines'] = self.get_jamp_lines(color_amplitudes)
4352
4353 file = read_template_file('cpp_process_matrix.inc') % \
4354@@ -987,8 +1013,11 @@
4355 """// Calculate wavefunctions
4356 void calculate_wavefunctions(const int perm[], const int hel[]);
4357 static const int nwavefuncs = %d;
4358- std::complex<double> w[nwavefuncs][18];""" % \
4359- len(self.wavefunctions)
4360+ std::complex<double> w[nwavefuncs][18];
4361+ static const int namplitudes = %d;
4362+ std::complex<double> amp[namplitudes];""" % \
4363+ (len(self.wavefunctions),
4364+ len(self.amplitudes.get_all_amplitudes()))
4365 replace_dict['all_matrix_definitions'] = \
4366 "\n".join(["double matrix_%s();" % \
4367 me.get('processes')[0].shell_string().\
4368@@ -1269,7 +1298,7 @@
4369
4370 if final_id_list and final_mirror_id_list or \
4371 not final_id_list and not final_mirror_id_list:
4372- raise ProcessExporterCPPError,\
4373+ raise self.ProcessExporterCPPError,\
4374 "Missing processes, or both process and mirror process"
4375
4376
4377@@ -1289,7 +1318,7 @@
4378 (i, l) in items if l > 0]).\
4379 replace('*1', ''))
4380 if any([l>1 for (i, l) in items]):
4381- raise ProcessExporterCPPError,\
4382+ raise self.ProcessExporterCPPError,\
4383 "More than one process with identical " + \
4384 "external particles is not supported"
4385
4386@@ -1303,7 +1332,7 @@
4387 (i, l) in items if l > 0]).\
4388 replace('*1', ''))
4389 if any([l>1 for (i, l) in items]):
4390- raise ProcessExporterCPPError,\
4391+ raise self.ProcessExporterCPPError,\
4392 "More than one process with identical " + \
4393 "external particles is not supported"
4394
4395@@ -1386,7 +1415,7 @@
4396
4397 color_flows = []
4398 for color_flow_dict in color_flow_list:
4399- color_flows.append([color_flow_dict[l.get('number')][i] % 500 \
4400+ color_flows.append([int(fmod(color_flow_dict[l.get('number')][i], 500)) \
4401 for (l,i) in itertools.product(legs, [0,1])])
4402
4403 # Write out colors for the selected color flow
4404@@ -1855,14 +1884,21 @@
4405 aloha_model.compute_subset(self.wanted_lorentz)
4406 else:
4407 aloha_model.compute_all(save=False)
4408+
4409 for abstracthelas in dict(aloha_model).values():
4410- aloha_writer = aloha_writers.ALOHAWriterForCPP(abstracthelas,
4411- self.dir_path)
4412- header = aloha_writer.define_header()
4413- template_h_files.append(self.write_function_declaration(\
4414- aloha_writer, header))
4415- template_cc_files.append(self.write_function_definition(\
4416- aloha_writer, header))
4417+ h_rout, cc_rout = abstracthelas.write(output_dir=None, language='CPP',
4418+ compiler_cmd=False)
4419+
4420+ template_h_files.append(h_rout)
4421+ template_cc_files.append(cc_rout)
4422+
4423+ #aloha_writer = aloha_writers.ALOHAWriterForCPP(abstracthelas,
4424+ # self.dir_path)
4425+ #header = aloha_writer.define_header()
4426+ #template_h_files.append(self.write_function_declaration(\
4427+ # aloha_writer, header))
4428+ #template_cc_files.append(self.write_function_definition(\
4429+ # aloha_writer, header))
4430
4431 replace_dict['function_declarations'] = '\n'.join(template_h_files)
4432 replace_dict['function_definitions'] = '\n'.join(template_cc_files)
4433@@ -1902,27 +1938,27 @@
4434
4435 return template_files
4436
4437- def write_function_declaration(self, aloha_writer, header):
4438- """Write the function declaration for the ALOHA routine"""
4439-
4440- ret_lines = []
4441- for line in aloha_writer.write_h(header).split('\n'):
4442- if self.compiler_option_re.match(line) or self.namespace_re.match(line):
4443- # Strip out compiler flags and namespaces
4444- continue
4445- ret_lines.append(line)
4446- return "\n".join(ret_lines)
4447-
4448- def write_function_definition(self, aloha_writer, header):
4449- """Write the function definition for the ALOHA routine"""
4450-
4451- ret_lines = []
4452- for line in aloha_writer.write_cc(header).split('\n'):
4453- if self.compiler_option_re.match(line) or self.namespace_re.match(line):
4454- # Strip out compiler flags and namespaces
4455- continue
4456- ret_lines.append(line)
4457- return "\n".join(ret_lines)
4458+# def write_function_declaration(self, aloha_writer, header):
4459+# """Write the function declaration for the ALOHA routine"""
4460+#
4461+# ret_lines = []
4462+# for line in aloha_writer.write_h(header).split('\n'):
4463+# if self.compiler_option_re.match(line) or self.namespace_re.match(line):
4464+# # Strip out compiler flags and namespaces
4465+# continue
4466+# ret_lines.append(line)
4467+# return "\n".join(ret_lines)
4468+#
4469+# def write_function_definition(self, aloha_writer, header):
4470+# """Write the function definition for the ALOHA routine"""
4471+#
4472+# ret_lines = []
4473+# for line in aloha_writer.write_cc(header).split('\n'):
4474+# if self.compiler_option_re.match(line) or self.namespace_re.match(line):
4475+# # Strip out compiler flags and namespaces
4476+# continue
4477+# ret_lines.append(line)
4478+# return "\n".join(ret_lines)
4479
4480 def clean_line(self, line):
4481 """Strip a line of compiler options and namespace options."""
4482
4483=== modified file 'madgraph/iolibs/export_python.py'
4484--- madgraph/iolibs/export_python.py 2010-12-01 01:33:28 +0000
4485+++ madgraph/iolibs/export_python.py 2011-04-22 01:24:30 +0000
4486@@ -354,10 +354,12 @@
4487 parameters.remove('ZERO')
4488
4489 # Get all couplings used
4490- couplings = list(set([func.get('coupling').replace('-', '') for func \
4491+
4492+
4493+ couplings = list(set([c.replace('-', '') for func \
4494 in matrix_element.get_all_wavefunctions() + \
4495- matrix_element.get_all_amplitudes()
4496- if func.get('mothers')]))
4497+ matrix_element.get_all_amplitudes() for c in func.get('coupling')
4498+ if func.get('mothers') ]))
4499
4500 return "\n ".join([\
4501 "%(param)s = model.get(\'parameter_dict\')[\"%(param)s\"]"\
4502
4503=== modified file 'madgraph/iolibs/export_v4.py'
4504--- madgraph/iolibs/export_v4.py 2011-04-13 03:40:52 +0000
4505+++ madgraph/iolibs/export_v4.py 2011-04-22 01:24:30 +0000
4506@@ -35,6 +35,7 @@
4507 import madgraph.iolibs.template_files as template_files
4508 import madgraph.iolibs.ufo_expression_parsers as parsers
4509 import madgraph.various.diagram_symmetry as diagram_symmetry
4510+import madgraph.various.process_checks as process_checks
4511
4512
4513 import aloha.create_aloha as create_aloha
4514@@ -51,11 +52,14 @@
4515 """Class to take care of exporting a set of matrix elements to
4516 Fortran (v4) format."""
4517
4518- def __init__(self, mgme_dir = "", dir_path = "", clean = False):
4519+ def __init__(self, mgme_dir = "", dir_path = "", clean = False,
4520+ symmetry_max_time = 600):
4521 """Initiate the ProcessExporterFortran with directory information"""
4522 self.mgme_dir = mgme_dir
4523 self.dir_path = dir_path
4524 self.clean = clean
4525+ self.model = None
4526+ self.symmetry_max_time = symmetry_max_time
4527
4528 #===========================================================================
4529 # copy the Template in a new directory.
4530@@ -178,7 +182,7 @@
4531 """Make the copy/symbolic links"""
4532 model_path = self.dir_path + '/Source/MODEL/'
4533 if os.path.exists(os.path.join(model_path, 'ident_card.dat')):
4534- ln(model_path + '/ident_card.dat', self.dir_path + '/Cards', log=False)
4535+ mv(model_path + '/ident_card.dat', self.dir_path + '/Cards')
4536 if os.path.exists(os.path.join(model_path, 'particles.dat')):
4537 ln(model_path + '/particles.dat', self.dir_path + '/SubProcesses')
4538 ln(model_path + '/interactions.dat', self.dir_path + '/SubProcesses')
4539@@ -187,7 +191,9 @@
4540 ln(model_path + '/coupl.inc', self.dir_path + '/Source')
4541 ln(model_path + '/coupl.inc', self.dir_path + '/SubProcesses')
4542 ln(self.dir_path + '/Source/run.inc', self.dir_path + '/SubProcesses', log=False)
4543+ ln(self.dir_path + '/Source/genps.inc', self.dir_path + '/SubProcesses', log=False)
4544 ln(self.dir_path + '/Source/maxconfigs.inc', self.dir_path + '/SubProcesses', log=False)
4545+ ln(self.dir_path + '/Source/maxparticles.inc', self.dir_path + '/SubProcesses', log=False)
4546
4547 #===========================================================================
4548 # export the helas routine
4549@@ -258,7 +264,7 @@
4550 """Write the pmass.inc file for MG4"""
4551
4552 model = matrix_element.get('processes')[0].get('model')
4553-
4554+
4555 lines = []
4556 for wf in matrix_element.get_external_wavefunctions():
4557 mass = model.get('particle_dict')[wf.get('pdg_code')].get('mass')
4558@@ -728,7 +734,7 @@
4559 # generate_subprocess_directory_v4
4560 #===========================================================================
4561 def generate_subprocess_directory_v4(self, matrix_element,
4562- fortran_model):
4563+ fortran_model):
4564 """Generate the Pxxxxx directory for a subprocess in MG4 standalone,
4565 including the necessary matrix.f and nexternal.inc files"""
4566
4567@@ -785,30 +791,6 @@
4568 matrix_element.get('processes')[0].nice_string())
4569 plot.draw()
4570
4571- # Generate diagrams
4572- filename = "matrix.ps"
4573- plot = draw.MultiEpsDiagramDrawer(matrix_element.get('base_amplitude').\
4574- get('diagrams'),
4575- filename,
4576- model=matrix_element.get('processes')[0].\
4577- get('model'),
4578- amplitude='')
4579- logger.info("Generating Feynman diagrams for " + \
4580- matrix_element.get('processes')[0].nice_string())
4581- plot.draw()
4582-
4583- # Generate diagrams
4584- filename = "matrix.ps"
4585- plot = draw.MultiEpsDiagramDrawer(matrix_element.get('base_amplitude').\
4586- get('diagrams'),
4587- filename,
4588- model=matrix_element.get('processes')[0].\
4589- get('model'),
4590- amplitude='')
4591- logger.info("Generating Feynman diagrams for " + \
4592- matrix_element.get('processes')[0].nice_string())
4593- plot.draw()
4594-
4595 linkfiles = ['check_sa.f', 'coupl.inc', 'makefile']
4596
4597
4598@@ -935,6 +917,9 @@
4599 cwd = os.getcwd()
4600 path = os.path.join(self.dir_path, 'SubProcesses')
4601
4602+ if not self.model:
4603+ self.model = matrix_element.get('processes')[0].get('model')
4604+
4605 try:
4606 os.chdir(path)
4607 except OSError, error:
4608@@ -1064,6 +1049,7 @@
4609 'reweight.f',
4610 'run.inc',
4611 'maxconfigs.inc',
4612+ 'maxparticles.inc',
4613 'setcuts.f',
4614 'setscales.f',
4615 'sudakov.inc',
4616@@ -1108,6 +1094,11 @@
4617 self.write_maxconfigs_file(writers.FortranWriter(filename),
4618 matrix_elements)
4619
4620+ # Write maxparticles.inc based on max of ME's/subprocess groups
4621+ filename = os.path.join(self.dir_path,'Source','maxparticles.inc')
4622+ self.write_maxparticles_file(writers.FortranWriter(filename),
4623+ matrix_elements)
4624+
4625 # Touch "done" file
4626 os.system('touch %s/done' % os.path.join(self.dir_path,'SubProcesses'))
4627
4628@@ -1388,6 +1379,27 @@
4629 return True
4630
4631 #===========================================================================
4632+ # write_maxparticles_file
4633+ #===========================================================================
4634+ def write_maxparticles_file(self, writer, matrix_elements):
4635+ """Write the maxparticles.inc file for MadEvent"""
4636+
4637+ if isinstance(matrix_elements, helas_objects.HelasMultiProcess):
4638+ maxparticles = max([me.get_nexternal_ninitial()[0] for me in \
4639+ matrix_elements.get('matrix_elements')])
4640+ else:
4641+ maxparticles = max([me.get_nexternal_ninitial()[0] \
4642+ for me in matrix_elements])
4643+
4644+ lines = "integer max_particles\n"
4645+ lines += "parameter(max_particles=%d)" % maxparticles
4646+
4647+ # Write the file
4648+ writer.writelines(lines)
4649+
4650+ return True
4651+
4652+ #===========================================================================
4653 # write_configs_file
4654 #===========================================================================
4655 def write_configs_file(self, writer, matrix_element):
4656@@ -1843,16 +1855,8 @@
4657 # Update values in run_config.inc
4658 run_config = \
4659 open(os.path.join(self.dir_path, 'Source', 'run_config.inc')).read()
4660- #run_config = run_config.replace("min_events_channel = 1000",
4661- # "min_events_channel = 4000")
4662- #run_config = run_config.replace("min_events = 2000",
4663- # "min_events = 4000")
4664- run_config = run_config.replace("max_events = 2000",
4665- "max_events = 8000")
4666 run_config = run_config.replace("ChanPerJob=5",
4667 "ChanPerJob=2")
4668- run_config = run_config.replace("nhel_survey=1",
4669- "nhel_survey=0")
4670 open(os.path.join(self.dir_path, 'Source', 'run_config.inc'), 'w').\
4671 write(run_config)
4672 # Update values in generate_events
4673@@ -1878,6 +1882,11 @@
4674 raise base_objects.PhysicsObject.PhysicsObjectError,\
4675 "subproc_group object not SubProcessGroup"
4676
4677+ if not self.model:
4678+ self.model = subproc_group.get('matrix_elements')[0].\
4679+ get('processes')[0].get('model')
4680+ self.evaluator = process_checks.MatrixElementEvaluator(self.model)
4681+
4682 cwd = os.getcwd()
4683 path = os.path.join(self.dir_path, 'SubProcesses')
4684
4685@@ -2033,7 +2042,9 @@
4686
4687 # Find config symmetries and permutations
4688 symmetry, perms, ident_perms = \
4689- diagram_symmetry.find_symmetry(subproc_group)
4690+ diagram_symmetry.find_symmetry(subproc_group,
4691+ self.evaluator,
4692+ self.symmetry_max_time)
4693
4694 filename = 'symswap.inc'
4695 self.write_symswap_file(writers.FortranWriter(filename),
4696@@ -2066,6 +2077,7 @@
4697 'reweight.f',
4698 'run.inc',
4699 'maxconfigs.inc',
4700+ 'maxparticles.inc',
4701 'setcuts.f',
4702 'setscales.f',
4703 'sudakov.inc',
4704@@ -2441,11 +2453,6 @@
4705 double complex gal(2)
4706 common/weak/ gal
4707
4708- double precision DUM0
4709- common/FRDUM0/ DUM0
4710-
4711- double precision DUM1
4712- common/FRDUM1/ DUM1
4713 """
4714 fsock.writelines(header)
4715
4716@@ -2551,10 +2558,6 @@
4717 gal(2) = 1d0
4718 """)
4719
4720- fsock.write_comments("\nDefinition of DUM symbols\n")
4721- fsock.writelines(""" DUM0 = 0
4722- DUM1 = 1
4723- """)
4724
4725 def create_couplings(self):
4726 """ create couplings.f and all couplingsX.f """
4727
4728=== modified file 'madgraph/iolibs/files.py'
4729--- madgraph/iolibs/files.py 2011-03-14 16:35:14 +0000
4730+++ madgraph/iolibs/files.py 2011-04-22 01:24:30 +0000
4731@@ -165,7 +165,11 @@
4732 starting_dir = format_path(starting_dir)
4733 if not name:
4734 name = os.path.split(file_pos)[1]
4735-
4736+
4737+ # Remove existing link if necessary
4738+ if os.path.islink(os.path.join(starting_dir, name)):
4739+ os.remove(os.path.join(starting_dir, name))
4740+
4741 try:
4742 os.symlink(os.path.relpath(file_pos, starting_dir), \
4743 os.path.join(starting_dir, name))
4744
4745=== modified file 'madgraph/iolibs/gen_infohtml.py'
4746--- madgraph/iolibs/gen_infohtml.py 2011-04-11 22:45:23 +0000
4747+++ madgraph/iolibs/gen_infohtml.py 2011-04-22 01:24:30 +0000
4748@@ -104,7 +104,7 @@
4749 </TR>
4750 <TR>
4751 <TD ALIGN=CENTER> <A HREF="../Source/MODEL/interactions.dat">interactions</A></TD>
4752- <TD> Interactions file used for code generation.</TABLE><P><H3 align=center><A HREF="../index.html"> Main Page </A></TD>
4753+ <TD> Interactions file used for code generation.</TD>
4754 </TR>"""
4755 else:
4756 return ''
4757
4758=== modified file 'madgraph/iolibs/group_subprocs.py'
4759--- madgraph/iolibs/group_subprocs.py 2011-04-11 03:10:18 +0000
4760+++ madgraph/iolibs/group_subprocs.py 2011-04-22 01:24:30 +0000
4761@@ -184,6 +184,12 @@
4762 if part.get('mass').lower() == 'zero' and part.get('color') != 1 \
4763 and part.get('spin') == 2:
4764 name += "q" # "j"
4765+ elif part.get('mass').lower() == 'zero' and part.get('color') == 1 \
4766+ and part.get('spin') == 2:
4767+ if part.get('charge') == 0:
4768+ name += "vl"
4769+ else:
4770+ name += "l"
4771 else:
4772 name += part.get_name().replace('~', 'x').\
4773 replace('+', 'p').replace('-', 'm')
4774
4775=== modified file 'madgraph/iolibs/helas_call_writers.py'
4776--- madgraph/iolibs/helas_call_writers.py 2011-03-31 18:03:05 +0000
4777+++ madgraph/iolibs/helas_call_writers.py 2011-04-22 01:24:30 +0000
4778@@ -16,6 +16,7 @@
4779
4780 import madgraph.core.base_objects as base_objects
4781 import madgraph.core.helas_objects as helas_objects
4782+import aloha.aloha_writers as aloha_writers
4783 from madgraph import MadGraph5Error
4784
4785
4786@@ -224,210 +225,210 @@
4787
4788 # Gluon 4-vertex division tensor calls ggT for the FR sm and mssm
4789
4790- key = ((3, 3, 5, 3), 'A')
4791+ key = ((3, 3, 5, 3), ('A',))
4792 call = lambda wf: \
4793 "CALL UVVAXX(W(1,%d),W(1,%d),%s,zero,zero,zero,W(1,%d))" % \
4794 (FortranHelasCallWriter.sorted_mothers(wf)[0].get('number'),
4795 FortranHelasCallWriter.sorted_mothers(wf)[1].get('number'),
4796- wf.get('coupling'),
4797+ wf.get('coupling')[0],
4798 wf.get('number'))
4799 self.add_wavefunction(key, call)
4800
4801- key = ((3, 5, 3, 1), 'A')
4802+ key = ((3, 5, 3, 1), ('A',))
4803 call = lambda wf: \
4804 "CALL JVTAXX(W(1,%d),W(1,%d),%s,zero,zero,W(1,%d))" % \
4805 (FortranHelasCallWriter.sorted_mothers(wf)[0].get('number'),
4806 FortranHelasCallWriter.sorted_mothers(wf)[1].get('number'),
4807- wf.get('coupling'),
4808+ wf.get('coupling')[0],
4809 wf.get('number'))
4810 self.add_wavefunction(key, call)
4811
4812- key = ((3, 3, 5), 'A')
4813+ key = ((3, 3, 5), ('A',))
4814 call = lambda amp: \
4815 "CALL VVTAXX(W(1,%d),W(1,%d),W(1,%d),%s,zero,AMP(%d))" % \
4816 (FortranHelasCallWriter.sorted_mothers(amp)[0].get('number'),
4817 FortranHelasCallWriter.sorted_mothers(amp)[1].get('number'),
4818 FortranHelasCallWriter.sorted_mothers(amp)[2].get('number'),
4819- amp.get('coupling'),
4820+ amp.get('coupling')[0],
4821 amp.get('number'))
4822 self.add_amplitude(key, call)
4823
4824 # SM gluon 4-vertex components
4825
4826- key = ((3, 3, 3, 3, 1), 'gggg3')
4827+ key = ((3, 3, 3, 3, 1), ('gggg3',))
4828 call = lambda wf: \
4829 "CALL JGGGXX(W(1,%d),W(1,%d),W(1,%d),%s,W(1,%d))" % \
4830 (FortranHelasCallWriter.sorted_mothers(wf)[1].get('number'),
4831 FortranHelasCallWriter.sorted_mothers(wf)[0].get('number'),
4832 FortranHelasCallWriter.sorted_mothers(wf)[2].get('number'),
4833- wf.get('coupling'),
4834+ wf.get('coupling')[0],
4835 wf.get('number'))
4836 self.add_wavefunction(key, call)
4837- key = ((3, 3, 3, 3), 'gggg1')
4838+ key = ((3, 3, 3, 3), ('gggg1',))
4839 call = lambda amp: \
4840 "CALL GGGGXX(W(1,%d),W(1,%d),W(1,%d),W(1,%d),%s,AMP(%d))" % \
4841 (FortranHelasCallWriter.sorted_mothers(amp)[0].get('number'),
4842 FortranHelasCallWriter.sorted_mothers(amp)[1].get('number'),
4843 FortranHelasCallWriter.sorted_mothers(amp)[2].get('number'),
4844 FortranHelasCallWriter.sorted_mothers(amp)[3].get('number'),
4845- amp.get('coupling'),
4846+ amp.get('coupling')[0],
4847 amp.get('number'))
4848 self.add_amplitude(key, call)
4849- key = ((3, 3, 3, 3, 1), 'gggg2')
4850+ key = ((3, 3, 3, 3, 1), ('gggg2',))
4851 call = lambda wf: \
4852 "CALL JGGGXX(W(1,%d),W(1,%d),W(1,%d),%s,W(1,%d))" % \
4853 (FortranHelasCallWriter.sorted_mothers(wf)[0].get('number'),
4854 FortranHelasCallWriter.sorted_mothers(wf)[2].get('number'),
4855 FortranHelasCallWriter.sorted_mothers(wf)[1].get('number'),
4856- wf.get('coupling'),
4857+ wf.get('coupling')[0],
4858 wf.get('number'))
4859 self.add_wavefunction(key, call)
4860- key = ((3, 3, 3, 3), 'gggg2')
4861+ key = ((3, 3, 3, 3), ('gggg2',))
4862 call = lambda amp: \
4863 "CALL GGGGXX(W(1,%d),W(1,%d),W(1,%d),W(1,%d),%s,AMP(%d))" % \
4864 (FortranHelasCallWriter.sorted_mothers(amp)[2].get('number'),
4865 FortranHelasCallWriter.sorted_mothers(amp)[0].get('number'),
4866 FortranHelasCallWriter.sorted_mothers(amp)[1].get('number'),
4867 FortranHelasCallWriter.sorted_mothers(amp)[3].get('number'),
4868- amp.get('coupling'),
4869+ amp.get('coupling')[0],
4870 amp.get('number'))
4871 self.add_amplitude(key, call)
4872- key = ((3, 3, 3, 3, 1), 'gggg1')
4873+ key = ((3, 3, 3, 3, 1), ('gggg1',))
4874 call = lambda wf: \
4875 "CALL JGGGXX(W(1,%d),W(1,%d),W(1,%d),%s,W(1,%d))" % \
4876 (FortranHelasCallWriter.sorted_mothers(wf)[2].get('number'),
4877 FortranHelasCallWriter.sorted_mothers(wf)[1].get('number'),
4878 FortranHelasCallWriter.sorted_mothers(wf)[0].get('number'),
4879- wf.get('coupling'),
4880+ wf.get('coupling')[0],
4881 wf.get('number'))
4882 self.add_wavefunction(key, call)
4883- key = ((3, 3, 3, 3), 'gggg3')
4884+ key = ((3, 3, 3, 3), ('gggg3',))
4885 call = lambda amp: \
4886 "CALL GGGGXX(W(1,%d),W(1,%d),W(1,%d),W(1,%d),%s,AMP(%d))" % \
4887 (FortranHelasCallWriter.sorted_mothers(amp)[1].get('number'),
4888 FortranHelasCallWriter.sorted_mothers(amp)[2].get('number'),
4889 FortranHelasCallWriter.sorted_mothers(amp)[0].get('number'),
4890 FortranHelasCallWriter.sorted_mothers(amp)[3].get('number'),
4891- amp.get('coupling'),
4892- amp.get('number'))
4893- self.add_amplitude(key, call)
4894-
4895- # HEFT VVVS calls
4896-
4897- key = ((1, 3, 3, 3, 3), '')
4898- call = lambda wf: \
4899- "CALL JVVSXX(W(1,%d),W(1,%d),W(1,%d),DUM1,%s,%s,%s,W(1,%d))" % \
4900- (wf.get('mothers')[0].get('number'),
4901- wf.get('mothers')[1].get('number'),
4902- wf.get('mothers')[2].get('number'),
4903- wf.get('coupling'),
4904- wf.get('mass'),
4905- wf.get('width'),
4906- wf.get('number'))
4907- self.add_wavefunction(key, call)
4908-
4909- key = ((3, 3, 3, 1, 4), '')
4910- call = lambda wf: \
4911- "CALL HVVVXX(W(1,%d),W(1,%d),W(1,%d),DUM1,%s,%s,%s,W(1,%d))" % \
4912- (wf.get('mothers')[0].get('number'),
4913- wf.get('mothers')[1].get('number'),
4914- wf.get('mothers')[2].get('number'),
4915- wf.get('coupling'),
4916- wf.get('mass'),
4917- wf.get('width'),
4918- wf.get('number'))
4919- self.add_wavefunction(key, call)
4920-
4921- key = ((1, 3, 3, 3), '')
4922- call = lambda amp: \
4923- "CALL VVVSXX(W(1,%d),W(1,%d),W(1,%d),W(1,%d),DUM1,%s,AMP(%d))" % \
4924- (amp.get('mothers')[0].get('number'),
4925- amp.get('mothers')[1].get('number'),
4926- amp.get('mothers')[2].get('number'),
4927- amp.get('mothers')[3].get('number'),
4928- amp.get('coupling'),
4929- amp.get('number'))
4930- self.add_amplitude(key, call)
4931-
4932- # HEFT VVVS calls
4933-
4934- key = ((1, 3, 3, 3, 1), '')
4935- call = lambda wf: \
4936- "CALL JVVSXX(W(1,%d),W(1,%d),W(1,%d),DUM1,%s,%s,%s,W(1,%d))" % \
4937- (wf.get('mothers')[0].get('number'),
4938- wf.get('mothers')[1].get('number'),
4939- wf.get('mothers')[2].get('number'),
4940- wf.get('coupling'),
4941- wf.get('mass'),
4942- wf.get('width'),
4943- wf.get('number'))
4944- self.add_wavefunction(key, call)
4945-
4946- key = ((3, 3, 3, 1, 4), '')
4947- call = lambda wf: \
4948- "CALL HVVVXX(W(1,%d),W(1,%d),W(1,%d),DUM1,%s,%s,%s,W(1,%d))" % \
4949- (wf.get('mothers')[0].get('number'),
4950- wf.get('mothers')[1].get('number'),
4951- wf.get('mothers')[2].get('number'),
4952- wf.get('coupling'),
4953- wf.get('mass'),
4954- wf.get('width'),
4955- wf.get('number'))
4956- self.add_wavefunction(key, call)
4957-
4958- key = ((1, 3, 3, 3), '')
4959- call = lambda amp: \
4960- "CALL VVVSXX(W(1,%d),W(1,%d),W(1,%d),W(1,%d),DUM1,%s,AMP(%d))" % \
4961- (amp.get('mothers')[0].get('number'),
4962- amp.get('mothers')[1].get('number'),
4963- amp.get('mothers')[2].get('number'),
4964- amp.get('mothers')[3].get('number'),
4965- amp.get('coupling'),
4966+ amp.get('coupling')[0],
4967+ amp.get('number'))
4968+ self.add_amplitude(key, call)
4969+
4970+ # HEFT VVVS calls
4971+
4972+ key = ((1, 3, 3, 3, 3), ('',))
4973+ call = lambda wf: \
4974+ "CALL JVVSXX(W(1,%d),W(1,%d),W(1,%d),DUM1,%s,%s,%s,W(1,%d))" % \
4975+ (wf.get('mothers')[0].get('number'),
4976+ wf.get('mothers')[1].get('number'),
4977+ wf.get('mothers')[2].get('number'),
4978+ wf.get('coupling')[0],
4979+ wf.get('mass'),
4980+ wf.get('width'),
4981+ wf.get('number'))
4982+ self.add_wavefunction(key, call)
4983+
4984+ key = ((3, 3, 3, 1, 4), ('',))
4985+ call = lambda wf: \
4986+ "CALL HVVVXX(W(1,%d),W(1,%d),W(1,%d),DUM1,%s,%s,%s,W(1,%d))" % \
4987+ (wf.get('mothers')[0].get('number'),
4988+ wf.get('mothers')[1].get('number'),
4989+ wf.get('mothers')[2].get('number'),
4990+ wf.get('coupling')[0],
4991+ wf.get('mass'),
4992+ wf.get('width'),
4993+ wf.get('number'))
4994+ self.add_wavefunction(key, call)
4995+
4996+ key = ((1, 3, 3, 3), ('',))
4997+ call = lambda amp: \
4998+ "CALL VVVSXX(W(1,%d),W(1,%d),W(1,%d),W(1,%d),DUM1,%s,AMP(%d))" % \
4999+ (amp.get('mothers')[0].get('number'),
5000+ amp.get('mothers')[1].get('number'),
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches