Merge lp:~maddevelopers/mg5amcnlo/3.0.2-alpha0 into lp:~maddevelopers/mg5amcnlo/3.2.1

Proposed by marco zaro
Status: Merged
Merged at revision: 973
Proposed branch: lp:~maddevelopers/mg5amcnlo/3.0.2-alpha0
Merge into: lp:~maddevelopers/mg5amcnlo/3.2.1
Diff against target: 2463 lines (+1387/-325)
21 files modified
Template/NLO/Cards/run_card.dat (+4/-1)
Template/NLO/FixedOrderAnalysis/analysis_HwU_general.f (+290/-19)
Template/NLO/SubProcesses/BinothLHA.f (+37/-3)
Template/NLO/SubProcesses/chooser_functions.f (+9/-0)
Template/NLO/SubProcesses/cuts.f (+537/-277)
Template/NLO/SubProcesses/fks_singular.f (+31/-7)
Template/NLO/SubProcesses/makefile_fks_dir (+1/-0)
Template/NLO/SubProcesses/recmom.f (+64/-8)
UpdateNotes.txt (+2/-1)
madgraph/core/diagram_generation.py (+19/-3)
madgraph/fks/fks_base.py (+8/-0)
madgraph/fks/fks_common.py (+12/-3)
madgraph/fks/fks_helas_objects.py (+2/-0)
madgraph/fks/fks_tag.py (+75/-0)
madgraph/interface/madgraph_interface.py (+37/-3)
madgraph/iolibs/export_fks.py (+86/-0)
madgraph/iolibs/template_files/fks_info.inc (+7/-0)
madgraph/iolibs/template_files/rescale_alpha_tagged.inc (+40/-0)
madgraph/various/banner.py (+11/-0)
tests/acceptance_tests/test_cmd_amcatnlo.py (+35/-0)
tests/unit_tests/fks/test_fks_taggedphotons.py (+80/-0)
To merge this branch: bzr merge lp:~maddevelopers/mg5amcnlo/3.0.2-alpha0
Reviewer Review Type Date Requested Status
Rikkert Frederix Approve
Olivier Mattelaer Approve
Review via email: mp+408723@code.launchpad.net

Description of the change

This merge includes the possibility to use tagged particles in the final state, which is particularly relevant for EW corrections with tagged photons (see 2106.02059).
Note that cuts.f has been deeply refactored.

To post a comment you must log in.
1000. By marco zaro

removed process folders

Revision history for this message
Rikkert Frederix (frederix) wrote :

Hi Marco,

I'll have a closer look next week. But for now:

- There is a text conflict in the UpdateNotes.txt
- Why do you add the new models? Shouldn't they part of FeynRules webpage so that they are simply downloaded when needed?

Best,
Rikkert

1001. By marco zaro

merged with 3.2.1

Revision history for this message
marco zaro (marco-zaro) wrote :

Hi Rikkert,
thanks.

> On 16 Sep 2021, at 16:22, Rikkert Frederix <email address hidden> wrote:
>
> Hi Marco,
>
> I'll have a closer look next week. But for now:
>
> - There is a text conflict in the UpdateNotes.txt
I solved it, putting the changes for 3.1.2 together with 3.2.1, since the former was never released
> - Why do you add the new models? Shouldn't they part of FeynRules webpage so that they are simply downloaded when needed?
I will discuss with Olivier and put the models on the web repository

Cheers,

Marco
>
> Best,
> Rikkert
>
> --
> https://code.launchpad.net/~maddevelopers/mg5amcnlo/3.0.2-alpha0/+merge/408723
> Your team MadDevelopers is subscribed to branch lp:~maddevelopers/mg5amcnlo/3.2.1.
>

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

Hi,

I have given a quick look and this sounds very good.

- I agree with Rikkert that it is better to put the model online (maybe not on the Feynrules website but on our madgraph website) the branch lp:~maddevelopers/mg5amcnlo/UFOmodel_db is designed for that actually.

- I'm worried about the re-introduction of the fortran function SORTTI and SORTTC.
If I remember correctly, such function had some issue with GCC10, did you check.

I do not see in the diff any kind of test (maybe it is just truncated). Can you add at least on parralel test such that I can run it on various GCC version and check that they are no issue on that.

Did you add unittest for the new syntax? if not I will likely add those when running some tests.

Cheers,

Olivier

1002. By marco zaro

fix in cuts.f to remove sortti/sorttc; unit+acceptance test added; models removed and added to the UFOmodel branch

Revision history for this message
marco zaro (marco-zaro) wrote :

Hello both
thanks for the reviews.
I have removed the models rom the branch and added to the UFOmodel one. I should have taken care of all the other comments in revision 1002.

Cheers,

Marco

> On 17 Sep 2021, at 09:54, Olivier Mattelaer <email address hidden> wrote:
>
> Hi,
>
> I have given a quick look and this sounds very good.
>
> - I agree with Rikkert that it is better to put the model online (maybe not on the Feynrules website but on our madgraph website) the branch lp:~maddevelopers/mg5amcnlo/UFOmodel_db is designed for that actually.
>
> - I'm worried about the re-introduction of the fortran function SORTTI and SORTTC.
> If I remember correctly, such function had some issue with GCC10, did you check.
>
> I do not see in the diff any kind of test (maybe it is just truncated). Can you add at least on parralel test such that I can run it on various GCC version and check that they are no issue on that.
>
> Did you add unittest for the new syntax? if not I will likely add those when running some tests.
>
> Cheers,
>
> Olivier
> --
> https://code.launchpad.net/~maddevelopers/mg5amcnlo/3.0.2-alpha0/+merge/408723
> Your team MadDevelopers is subscribed to branch lp:~maddevelopers/mg5amcnlo/3.2.1.
>

Revision history for this message
Rikkert Frederix (frederix) wrote :

Hi Marco,

I've done the following test with this branch:

import model loop_qcd_qed_sm_Gmu-a0
generate p p > !a! !a! [real=QCD] ; output ; launch -p -f

and it crashes stating that there are "no integration channels". Looking in the relevant gensym.log, there is "ERROR, too many photons 2". I thought that the above process should have worked, no? Have I misunderstood something here?

Best,
Rikkert

1003. By marco zaro

cuts.f updated so that recombine_momenta won't crash for too many photons (thanks Ioannis Tsinikos); the gmu<>alpha scheme conversion is written dinamically, to ensure compatibility with processes without tagged photons

Revision history for this message
marco zaro (marco-zaro) wrote :

Hi Rikkert,
Indeed, Ioannis had produces a modified version of cuts.f that makes disappear your error. I have updated cuts.f in the branch accordingly, and fixed some other things in the code.
Cheers,

Marco

> On 21 Sep 2021, at 09:56, Rikkert Frederix <email address hidden> wrote:
>
> Hi Marco,
>
> I've done the following test with this branch:
>
> import model loop_qcd_qed_sm_Gmu-a0
> generate p p > !a! !a! [real=QCD] ; output ; launch -p -f
>
> and it crashes stating that there are "no integration channels". Looking in the relevant gensym.log, there is "ERROR, too many photons 2". I thought that the above process should have worked, no? Have I misunderstood something here?
>
> Best,
> Rikkert
>
>
> --
> https://code.launchpad.net/~maddevelopers/mg5amcnlo/3.0.2-alpha0/+merge/408723
> Your team MadDevelopers is subscribed to branch lp:~maddevelopers/mg5amcnlo/3.2.1z

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

This is very good and basically ready to be merged.

Some minor point.
1) !z! works ... should not be this forbidden?
2) can we use tagged photon with QCD correction only?
-- In the commit I did, I have added unittest that crash related to the above command, you can remove those test if those are fine--
3) 2!a! was making the code to crash but !2a! was working fine. I have updated the parser to support both.
4) I have spotted a typo in banner.py (see the comment within the diff for that)
5) I have loose track of all the change in cuts.f but did not spot anything obviously wrong. If you are not confident enough about that part maybe I should go deeper and track that we did not "loose" any previous cut but sounds like it.

Thanks a lot and sorry for being slow on this review

review: Approve
1004. By olivier-mattelaer

add unittest --not all passing-- and update the parser to allow duplicate tagged particcle

1005. By marco zaro

fix in banner.py according to Olivier's comment

Revision history for this message
marco zaro (marco-zaro) wrote :

Hi Olivier,
thanks for your comments

> On 14 Oct 2021, at 16:26, Olivier Mattelaer <email address hidden> wrote:
>
> Review: Approve
>
> This is very good and basically ready to be merged.
>
> Some minor point.
> 1) !z! works ... should not be this forbidden?
yes, but it should do nothing
> 2) can we use tagged photon with QCD correction only?
> -- In the commit I did, I have added unittest that crash related to the above command, you can remove those test if those are fine—
In principle the syntax should work, giving identical results with the case without tagging
> 3) 2!a! was making the code to crash but !2a! was working fine. I have updated the parser to support both.
I was not aware of the fact that one can use the numbers to specify multiple times the same particle
> 4) I have spotted a typo in banner.py (see the comment within the diff for that)
I have fixed it, please have a look
> 5) I have loose track of all the change in cuts.f but did not spot anything obviously wrong. If you are not confident enough about that part maybe I should go deeper and track that we did not "loose" any previous cut but sounds like it.
>
Let us see what Rik says here…

Cheers,

Marco

> Thanks a lot and sorry for being slow on this review
>
> Diff comments:
>
>>
>> === modified file 'madgraph/various/banner.py'
>> --- madgraph/various/banner.py 2021-07-29 07:14:14 +0000
>> +++ madgraph/various/banner.py 2021-10-04 14:52:23 +0000
>> @@ -4552,11 +4553,20 @@
>> if proc_characteristic['ninitial'] == 1:
>> #remove all cut
>> self.remove_all_cut()
>> +
>> + # check for tagged photons
>> + tagged_particles = set()
>>
>> # Check if need matching
>> min_particle = 99
>> max_particle = 0
>> for proc in proc_def:
>> + for leg in proc['legs']:
>> + if leg['is_tagged']:
>> + tagged_particles.add(leg['id'])
>> +
>> + if 22 in tagged_particles:
>> + self['gamma_is_j'] = False
>> min_particle = min(len(proc['legs']), min_particle)
>> max_particle = max(len(proc['legs']), max_particle)
>
> The min_particle/max_particle should not be in the if ""22" block but still in the
> for proc in proc_def: loop
>
>> matching = False
>
>
> --
> https://code.launchpad.net/~maddevelopers/mg5amcnlo/3.0.2-alpha0/+merge/408723
> Your team MadDevelopers is subscribed to branch lp:~maddevelopers/mg5amcnlo/3.2.1.
>

Revision history for this message
Rikkert Frederix (frederix) wrote :

Hi Marco,

I think this is ready for merging.

best,
Rikkert

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'Template/NLO/Cards/run_card.dat'
--- Template/NLO/Cards/run_card.dat 2021-04-05 16:07:15 +0000
+++ Template/NLO/Cards/run_card.dat 2021-10-15 11:42:16 +0000
@@ -129,7 +129,10 @@
129 %(bwcutoff)s = bwcutoff129 %(bwcutoff)s = bwcutoff
130#***********************************************************************130#***********************************************************************
131# Cuts on the jets. Jet clustering is performed by FastJet. *131# Cuts on the jets. Jet clustering is performed by FastJet. *
132# - If gamma_is_j, photons are also clustered *132# - If gamma_is_j, photons are also clustered with jets. *
133# Otherwise, they will be treated as tagged particles and photon *
134# isolation will be applied. Note that photons in the real emission *
135# will always be clustered with QCD partons. *
133# - When matching to a parton shower, these generation cuts should be *136# - When matching to a parton shower, these generation cuts should be *
134# considerably softer than the analysis cuts. *137# considerably softer than the analysis cuts. *
135# - More specific cuts can be specified in SubProcesses/cuts.f *138# - More specific cuts can be specified in SubProcesses/cuts.f *
136139
=== modified file 'Template/NLO/FixedOrderAnalysis/analysis_HwU_general.f'
--- Template/NLO/FixedOrderAnalysis/analysis_HwU_general.f 2018-10-26 09:55:25 +0000
+++ Template/NLO/FixedOrderAnalysis/analysis_HwU_general.f 2021-10-15 11:42:16 +0000
@@ -5,8 +5,12 @@
5 integer nwgt5 integer nwgt
6 character*(*) weights_info(*)6 character*(*) weights_info(*)
7 integer i,l7 integer i,l
8 character*6 cc(2)8c character*6 cc(2)
9 data cc/'|T@NLO','|T@LO '/9c data cc/'|T@NLO','|T@LO '/
10 character*13 cc(9)
11 data cc/ ' |T@NLO ',' |T@LO ',' |T@LO1 '
12 $ ,' |T@LO2 ',' |T@LO3 ',' |T@NLO1 '
13 $ ,' |T@NLO2 ',' |T@NLO3 ',' |T@NLO4 '/
1014
11c Also specific perturbative orders can be directly plotted, adding for examples15c Also specific perturbative orders can be directly plotted, adding for examples
12c the following further entries in the variable data16c the following further entries in the variable data
@@ -18,8 +22,8 @@
18c 22c
19c See also line 376 in this file 23c See also line 376 in this file
20 call HwU_inithist(nwgt,weights_info)24 call HwU_inithist(nwgt,weights_info)
21 do i=1,225 do i=1,9
22 l=(i-1)*5526 l=(i-1)*59
23c transverse momenta27c transverse momenta
24 call HwU_book(l+ 1,'total rate '//cc(i),1,0.5d0,1.5d0)28 call HwU_book(l+ 1,'total rate '//cc(i),1,0.5d0,1.5d0)
25 call HwU_book(l+ 2,'1st charged lepton log pT '//cc(i),25,-0.2d0,3.8d0)29 call HwU_book(l+ 2,'1st charged lepton log pT '//cc(i),25,-0.2d0,3.8d0)
@@ -76,6 +80,14 @@
76c HT80c HT
77 call HwU_book(l+54,'log HT (partons) '//cc(i),25,-0.2d0,3.8d0)81 call HwU_book(l+54,'log HT (partons) '//cc(i),25,-0.2d0,3.8d0)
78 call HwU_book(l+55,'log HT (reconstructed) '//cc(i),25,-0.2d0,3.8d0)82 call HwU_book(l+55,'log HT (reconstructed) '//cc(i),25,-0.2d0,3.8d0)
83
84
85 call HwU_book(l+56,'1st isolated ph log pT '//cc(i),25,-0.2d0,3.8d0)
86 call HwU_book(l+57,'2nd isolated ph log pT '//cc(i),25,-0.2d0,3.8d0)
87 call HwU_book(l+58,'3rd isolated ph log pT '//cc(i),25,-0.2d0,3.8d0)
88
89 call HwU_book(l+59,'3 isolated ph log M '//cc(i),25,-0.2d0,3.8d0)
90
79 enddo91 enddo
80 return92 return
81 end93 end
@@ -110,7 +122,7 @@
110 $ ,ptmpmm,ptepve,ptmmvm,ptepemmpmm,ptepvemmvm,ptt,ptat,pttt122 $ ,ptmpmm,ptepve,ptmmvm,ptepemmpmm,ptepvemmvm,ptt,ptat,pttt
111 $ ,etmiss,pth(2),pthh,ptv(3),ptjet(3),Mepem,Mmpmm,Mepve,Mmmvm123 $ ,etmiss,pth(2),pthh,ptv(3),ptjet(3),Mepem,Mmpmm,Mepve,Mmmvm
112 $ ,Mepemmpmm,Mepvemmvm,Mtt,Mhh,Mj1j2,Mj1j3,Mj2j3,Mj1j2j3,Mvvv124 $ ,Mepemmpmm,Mepvemmvm,Mtt,Mhh,Mj1j2,Mj1j3,Mj2j3,Mj1j2j3,Mvvv
113 $ ,HTparton,HTreco,p_reco(0:4,nexternal)125 $ ,HTparton,HTreco,p_reco(0:4,nexternal),ptphiso(nexternal),Mphphph
114 integer nQCD,jet(nexternal),njet,itop,iatop,iem,iep,imp,imm,ive126 integer nQCD,jet(nexternal),njet,itop,iatop,iem,iep,imp,imm,ive
115 $ ,ivm,iv1,iv2,iv3,ih1,ih2,il,ipdg_reco(nexternal)127 $ ,ivm,iv1,iv2,iv3,ih1,ih2,il,ipdg_reco(nexternal)
116 double precision getptv4,getptv4_2,getptv4_4,getinvm4_2128 double precision getptv4,getptv4_2,getptv4_4,getinvm4_2
@@ -119,25 +131,47 @@
119 $ ,getinvm4_4,l10131 $ ,getinvm4_4,l10
120 integer orders_tag_plot132 integer orders_tag_plot
121 common /corderstagplot/ orders_tag_plot133 common /corderstagplot/ orders_tag_plot
134
135
136c Photon isolation
137 integer nph,nem,nin,nphiso
138 double precision ptg,chi_gamma_iso,iso_getdrv40
139 double precision Etsum(0:nexternal)
140 real drlist(nexternal)
141 double precision pgamma(0:3,nexternal),pgammaiso(0:3,nexternal),pem(0:3,nexternal)
142 logical alliso,isolated
143c Sort array of results: ismode>0 for real, isway=0 for ascending order
144 integer ismode,isway,izero,isorted(nexternal)
145 parameter (ismode=1)
146 parameter (isway=0)
147 parameter (izero=0)
148 integer get_n_tagged_photons
149
150
151 logical is_a_lp(nexternal),is_a_lm(nexternal),is_a_j(nexternal)
152 $ ,is_a_ph(nexternal)
153 REAL*8 pt,eta
154 external pt,eta,chi_gamma_iso,sortzv
155c integer iph1,iph2,iph3
122c First, try to recombine photons with leptons 156c First, try to recombine photons with leptons
123 if (.not.quarkphreco) then157c if (.not.quarkphreco) then
124 write (*,*) 'quark-photon recombination is turned off. '/158c write (*,*) 'quark-photon recombination is turned off. '/
125 $ /'Do need it'159c $ /'Do need it'
126 stop160c stop
127 endif161c endif
128 if (.not. lepphreco) then162c if (.not. lepphreco) then
129 write (*,*) 'lepton-photon recombination is turned off. '163c write (*,*) 'lepton-photon recombination is turned off. '
130 $ //'Do need it.'164c $ //'Do need it.'
131 stop165c stop
132 endif166c endif
133 call recombine_momenta(rphreco, etaphreco, lepphreco, quarkphreco,167 call recombine_momenta(rphreco, etaphreco, lepphreco, quarkphreco,
134 $ p, iPDG, p_reco, iPDG_reco)168 $ p, iPDG, p_reco, iPDG_reco)
135169
136c Put all (light) QCD partons(+photon) in momentum array for jet clustering.170c Put all (light) QCD partons(+photon) in momentum array for jet clustering.
137 nQCD=0171 nQCD=0
138 do j=nincoming+1,nexternal172 do j=nincoming+1,nexternal
139 if (abs(ipdg_reco(j)).le.5 .or. ipdg_reco(j).eq.21 .or.173 if (abs(ipdg_reco(j)).le.5 .or. ipdg_reco(j).eq.21
140 $ ipdg_reco(j).eq.22)then174 $ .or. (ipdg_reco(j).eq.22.and.gamma_is_j)) then
141 nQCD=nQCD+1175 nQCD=nQCD+1
142 do i=0,3176 do i=0,3
143 pQCD(i,nQCD)=p_reco(i,j)177 pQCD(i,nQCD)=p_reco(i,j)
@@ -173,6 +207,161 @@
173c207c
174c******************************************************************************208c******************************************************************************
175209
210
211c PHOTON (ISOLATION) CUTS
212c
213c find the photons
214 do i=1,nexternal
215 if (istatus(i).eq.1 .and. ipdg(i).eq.22 .and. .not.gamma_is_j) then
216 is_a_ph(i)=.true.
217 else
218 is_a_ph(i)=.false.
219 endif
220 enddo
221 if (ptgmin.ne.0d0) then
222 nph=0
223 do j=nincoming+1,nexternal
224 if (is_a_ph(j)) then
225 nph=nph+1
226 do i=0,3
227 pgamma(i,nph)=p(i,j)
228 enddo
229 endif
230 enddo
231 if(nph.eq.0)goto 444
232c write(*,*) 'ERROR in cuts.f: photon isolation is not working'
233c $ // ' for mixed QED-QCD corrections'
234c stop 1
235
236 if(isoEM)then
237 nem=nph
238 do k=1,nem
239 do i=0,3
240 pem(i,k)=pgamma(i,k)
241 enddo
242 enddo
243 do j=nincoming+1,nexternal
244 if (is_a_lp(j).or.is_a_lm(j)) then
245 nem=nem+1
246 do i=0,3
247 pem(i,nem)=p(i,j)
248 enddo
249 endif
250 enddo
251 endif
252
253c alliso=.true.
254 nphiso=0
255
256 j=0
257c do while(j.lt.nph.and.alliso)
258 do while(j.lt.nph)
259
260c Loop over all photons
261 j=j+1
262
263 ptg=pt(pgamma(0,j))
264 if(ptg.lt.ptgmin)then
265 cycle
266c return
267 endif
268 if (etagamma.gt.0d0) then
269 if (abs(eta(pgamma(0,j))).gt.etagamma) then
270 cycle
271c return
272 endif
273 endif
274
275c Isolate from hadronic energy
276 do i=1,nQCD
277 drlist(i)=sngl(iso_getdrv40(pgamma(0,j),pQCD(0,i)))
278 enddo
279 call sortzv(drlist,isorted,nQCD,ismode,isway,izero)
280 Etsum(0)=0.d0
281 nin=0
282 do i=1,nQCD
283 if(dble(drlist(isorted(i))).le.R0gamma)then
284 nin=nin+1
285 Etsum(nin)=Etsum(nin-1)+pt(pQCD(0,isorted(i)))
286 endif
287 enddo
288 isolated=.True.
289 do i=1,nin
290c alliso=alliso .and.
291c $ Etsum(i).le.chi_gamma_iso(dble(drlist(isorted(i))),
292c $ R0gamma,xn,epsgamma,ptg)
293 if(Etsum(i).gt.chi_gamma_iso(dble(drlist(isorted(i))),
294 $ R0gamma,xn,epsgamma,ptg)) then
295 isolated=isolated.and..False.
296 endif
297 enddo
298 if(.not.isolated)cycle
299
300c Isolate from EM energy
301 if(isoEM.and.nem.gt.1)then
302 do i=1,nem
303 drlist(i)=sngl(iso_getdrv40(pgamma(0,j),pem(0,i)))
304 enddo
305 call sortzv(drlist,isorted,nem,ismode,isway,izero)
306c First of list must be the photon: check this, and drop it
307 if(isorted(1).ne.j.or.drlist(isorted(1)).gt.1.e-4)then
308 write(*,*)'Error #1 in photon isolation'
309 write(*,*)j,isorted(1),drlist(isorted(1))
310 stop
311 endif
312 Etsum(0)=0.d0
313 nin=0
314 do i=2,nem
315 if(dble(drlist(isorted(i))).le.R0gamma)then
316 nin=nin+1
317 Etsum(nin)=Etsum(nin-1)+pt(pem(0,isorted(i)))
318 endif
319 enddo
320 isolated=.True.
321 do i=1,nin
322c alliso=alliso .and.
323c $ Etsum(i).le.chi_gamma_iso(dble(drlist(isorted(i))),
324c $ R0gamma,xn,epsgamma,ptg)
325 if(Etsum(i).gt.chi_gamma_iso(dble(drlist(isorted(i))),
326 $ R0gamma,xn,epsgamma,ptg)) then
327 isolated=isolated.and..False.
328 endif
329 enddo
330 if(.not.isolated)cycle
331 endif
332c End of loop over photons
333
334 nphiso=nphiso+1
335
336 do i=0,3
337 pgammaiso(i,nphiso)=pgamma(i,j)
338 enddo
339
340
341 enddo
342 if(nphiso.lt.get_n_tagged_photons())then
343 print*,"mismatch with cuts.f"
344 stop
345 endif
346
347
348444 continue
349c End photon isolation
350 endif
351
352
353
354
355
356
357
358
359
360
361
362
363
364
176c Look for the other physics objects365c Look for the other physics objects
177 itop=0366 itop=0
178 iatop=0367 iatop=0
@@ -189,7 +378,14 @@
189 iv3=0378 iv3=0
190 ih1=0379 ih1=0
191 ih2=0380 ih2=0
381c iph1=0
382c iph2=0
383c iph3=0
384c print*,"nell'analisi"
192 do i=1,nexternal385 do i=1,nexternal
386c print*,"idpg di ",i,"=",ipdg(i)
387c print*,"idpg_reco di ",i,"=",ipdg_reco(i)
388
193 if (ipdg_reco(i).eq.6) then389 if (ipdg_reco(i).eq.6) then
194 itop=i390 itop=i
195 elseif(ipdg_reco(i).eq.-6) then391 elseif(ipdg_reco(i).eq.-6) then
@@ -232,8 +428,27 @@
232 stop428 stop
233 endif429 endif
234 endif430 endif
431c elseif(abs(ipdg_reco(i)).eq.22.and.i.gt.nincoming) then
432c if (iph1.eq.0) then
433c iph1=i
434c else
435c if (iph2.eq.0) then
436c iph2=i
437c else
438c if (iph3.eq.0) then
439c iph3=i
440c else
441c write (*,*) 'too many photonss'
442c stop
443c endif
444c endif
445c endif
235 endif446 endif
447
236 enddo448 enddo
449c print*,itop,iatop
450c stop
451
237 if (itop.ne.0) ptt=getptv4(p_reco(0,itop))452 if (itop.ne.0) ptt=getptv4(p_reco(0,itop))
238 if (iatop.ne.0) ptat=getptv4(p_reco(0,iatop))453 if (iatop.ne.0) ptat=getptv4(p_reco(0,iatop))
239 if (itop.ne.0 .and. iatop.ne.0) then454 if (itop.ne.0 .and. iatop.ne.0) then
@@ -318,11 +533,21 @@
318 pth(2)=tmp533 pth(2)=tmp
319 endif534 endif
320 endif535 endif
536
537
321 if (iv1.ne.0) ptv(1)=getptv4(p_reco(0,iv1))538 if (iv1.ne.0) ptv(1)=getptv4(p_reco(0,iv1))
322 if (iv2.ne.0) ptv(2)=getptv4(p_reco(0,iv2))539 if (iv2.ne.0) ptv(2)=getptv4(p_reco(0,iv2))
323 if (iv3.ne.0) ptv(3)=getptv4(p_reco(0,iv3))540 if (iv3.ne.0) ptv(3)=getptv4(p_reco(0,iv3))
324 if (iv1.ne.0 .and. iv2.ne.0 .and. iv3.ne.0) then541 if (iv1.ne.0 .and. iv2.ne.0 .and. iv3.ne.0) then
325 Mvvv=getinvm4_3(p_reco(0,iv1),p_reco(0,iv2),p_reco(0,iv3))542 Mvvv=getinvm4_3(p_reco(0,iv1),p_reco(0,iv2),p_reco(0,iv3))
543 endif
544
545 do i=1,nphiso
546 ptphiso(i)=getptv4(pgammaiso(0,i))
547 enddo
548
549 if (iv1.ne.0 .and. iv2.ne.0 .and. iv3.ne.0) then
550 Mvvv=getinvm4_3(p_reco(0,iv1),p_reco(0,iv2),p_reco(0,iv3))
326c order the vector bosons (if there are 3)551c order the vector bosons (if there are 3)
327 do i=1,2552 do i=1,2
328 do j=1,3-i553 do j=1,3-i
@@ -341,6 +566,31 @@
341 ptv(2)=tmp566 ptv(2)=tmp
342 endif567 endif
343 endif568 endif
569
570
571
572
573 if (nphiso.eq.3) then
574 Mphphph=getinvm4_3(pgammaiso(0,1),pgammaiso(0,2),pgammaiso(0,3))
575c order the isolated photons (if there are 3)
576 do i=1,2
577 do j=1,3-i
578 if (ptphiso(j).lt.ptphiso(j+1)) then
579 tmp=ptphiso(j)
580 ptphiso(j)=ptphiso(j+1)
581 ptphiso(j+1)=tmp
582 endif
583 enddo
584 enddo
585 elseif (nphiso.eq.2) then
586c order the isolated photons (if there are 2)
587 if (ptphiso(1).lt.ptphiso(2)) then
588 tmp=ptphiso(1)
589 ptphiso(1)=ptphiso(2)
590 ptphiso(2)=tmp
591 endif
592 endif
593
344 do i=1,njet594 do i=1,njet
345 ptjet(i)=getptv4(pjet(0,i))595 ptjet(i)=getptv4(pjet(0,i))
346 enddo596 enddo
@@ -369,9 +619,18 @@
369 enddo619 enddo
370 if (ive.ne.0 .or. ivm.ne.0) HTreco=HTreco+etmiss620 if (ive.ne.0 .or. ivm.ne.0) HTreco=HTreco+etmiss
371 621
372 do i=1,2622 do i=1,9
373 l=(i-1)*55623 l=(i-1)*59
374 if (ibody.ne.3 .and.i.eq.2) cycle624 if (ibody.ne.3 .and.i.eq.2) cycle
625 if (i.eq. 3.and.orders_tag_plot.ne.204) cycle
626 if (i.eq. 4.and.orders_tag_plot.ne.402) cycle
627 if (i.eq. 5.and.orders_tag_plot.ne.600) cycle
628 if (i.eq. 6.and.orders_tag_plot.ne.206) cycle
629 if (i.eq. 7.and.orders_tag_plot.ne.404) cycle
630 if (i.eq. 8.and.orders_tag_plot.ne.602) cycle
631 if (i.eq. 9.and.orders_tag_plot.ne.800) cycle
632
633
375634
376c How to tag orders (QCD+QED*100)635c How to tag orders (QCD+QED*100)
377c636c
@@ -493,6 +752,18 @@
493c HT752c HT
494 call HwU_fill(l+54,l10(HTparton),wgts)753 call HwU_fill(l+54,l10(HTparton),wgts)
495 call HwU_fill(l+55,l10(HTreco),wgts)754 call HwU_fill(l+55,l10(HTreco),wgts)
755
756 if (nphiso.ge.1) call HwU_fill(l+56,l10(ptphiso(1)),wgts)
757 if (nphiso.ge.2) call HwU_fill(l+57,l10(ptphiso(2)),wgts)
758 if (nphiso.ge.3) call HwU_fill(l+58,l10(ptphiso(3)),wgts)
759
760 if (nphiso.ge.3) call HwU_fill(l+59,l10(Mphphph),wgts)
761
762
763
764
765
766
496 enddo767 enddo
497768
498 999 return 769 999 return
499770
=== modified file 'Template/NLO/SubProcesses/BinothLHA.f'
--- Template/NLO/SubProcesses/BinothLHA.f 2020-06-26 09:54:58 +0000
+++ Template/NLO/SubProcesses/BinothLHA.f 2021-10-15 11:42:16 +0000
@@ -8,6 +8,7 @@
8 implicit none8 implicit none
9 include "nexternal.inc"9 include "nexternal.inc"
10 include "coupl.inc"10 include "coupl.inc"
11 include "../../Source/MODEL/input.inc"
11 include 'born_nhel.inc'12 include 'born_nhel.inc'
12 double precision pi, zero,mone13 double precision pi, zero,mone
13 parameter (pi=3.1415926535897932385d0)14 parameter (pi=3.1415926535897932385d0)
@@ -57,6 +58,7 @@
57 integer getordpowfromindex_ml558 integer getordpowfromindex_ml5
58 integer orders_to_amp_split_pos59 integer orders_to_amp_split_pos
59 logical, allocatable, save :: keep_order(:)60 logical, allocatable, save :: keep_order(:)
61 include 'a0Gmuconv.inc'
60 include 'orders.inc'62 include 'orders.inc'
61 integer amp_orders(nsplitorders)63 integer amp_orders(nsplitorders)
62 integer split_amp_orders(nsplitorders), iamp64 integer split_amp_orders(nsplitorders), iamp
@@ -74,10 +76,17 @@
7476
75 logical updateloop77 logical updateloop
76 common /to_updateloop/updateloop78 common /to_updateloop/updateloop
79
80 integer get_n_tagged_photons
81 external get_n_tagged_photons
82 double precision get_virtual_a0Gmu_conv
83 external get_virtual_a0Gmu_conv
84 integer ntagph, qed_pow_b
77c masses85c masses
78 include 'pmass.inc'86 include 'pmass.inc'
79 data nbad / 0 /87 data nbad / 0 /
8088
89
81 IOErrCounter = 090 IOErrCounter = 0
82c update the ren_scale for MadLoop and the couplings (should be the91c update the ren_scale for MadLoop and the couplings (should be the
83c Ellis-Sexton scale)92c Ellis-Sexton scale)
@@ -93,8 +102,7 @@
93 single = 0d0102 single = 0d0
94 double = 0d0103 double = 0d0
95 born_hel_from_virt = 0d0104 born_hel_from_virt = 0d0
96C reset the amp_split array105C reset the various arrays
97 amp_split(1:amp_split_size) = 0d0
98 amp_split_finite_ML(1:amp_split_size) = 0d0106 amp_split_finite_ML(1:amp_split_size) = 0d0
99 amp_split_poles_ML(1:amp_split_size,1) = 0d0107 amp_split_poles_ML(1:amp_split_size,1) = 0d0
100 amp_split_poles_ML(1:amp_split_size,2) = 0d0108 amp_split_poles_ML(1:amp_split_size,2) = 0d0
@@ -256,6 +264,32 @@
256c endif264c endif
257c virt_wgt=virt_wgt+conversion*born_wgt*ao2pi265c virt_wgt=virt_wgt+conversion*born_wgt*ao2pi
258c======================================================================266c======================================================================
267
268c======================================================================
269c If there are tagged photon and other particles in the process,
270C one must use a mixed Gmu-alpha0 renormalisation.
271 ntagph = get_n_tagged_photons()
272 if (ntagph.ne.0) then
273 do i = 1, AMP_SPLIT_SIZE_BORN
274 call amp_split_pos_to_orders(i, amp_orders)
275 born_wgt = amp_split(i)
276 ! this is the number of powers of 'e' in the born
277 qed_pow_b = amp_orders(qed_pos)
278 amp_orders(qed_pos) = amp_orders(qed_pos) + 2
279 if (amp_orders(qed_pos).gt.NLO_ORDERS(qed_pos)) cycle
280
281 amp_split_poles_ML(orders_to_amp_split_pos(amp_orders),1) =
282 $ amp_split_poles_ML(orders_to_amp_split_pos(amp_orders),1) +
283 $ get_virtual_a0Gmu_conv(qed_pow_b,ntagph,1,born_wgt)
284
285 amp_split_finite_ML(orders_to_amp_split_pos(amp_orders)) =
286 $ amp_split_finite_ML(orders_to_amp_split_pos(amp_orders)) +
287 $ get_virtual_a0Gmu_conv(qed_pow_b,ntagph,0,born_wgt)
288
289 enddo
290 endif
291c======================================================================
292
259c293c
260c Check poles for the first PS points when doing MC over helicities, and294c Check poles for the first PS points when doing MC over helicities, and
261c for all phase-space points when not doing MC over helicities. Skip295c for all phase-space points when not doing MC over helicities. Skip
@@ -268,7 +302,7 @@
268 polecheck_passed = .true.302 polecheck_passed = .true.
269 ! loop over the full result and each of the amp_split303 ! loop over the full result and each of the amp_split
270 ! contribution304 ! contribution
271 do iamp=0,amp_split_size305 do iamp=1,amp_split_size
272 ! skip 0 contributions in the amp_split array306 ! skip 0 contributions in the amp_split array
273 if (iamp.ne.0) then307 if (iamp.ne.0) then
274 if (amp_split_poles_FKS(iamp,1).eq.0d0.and.308 if (amp_split_poles_FKS(iamp,1).eq.0d0.and.
275309
=== modified file 'Template/NLO/SubProcesses/chooser_functions.f'
--- Template/NLO/SubProcesses/chooser_functions.f 2018-04-05 17:59:21 +0000
+++ Template/NLO/SubProcesses/chooser_functions.f 2021-10-15 11:42:16 +0000
@@ -100,6 +100,10 @@
100 double precision ch_i,ch_j,ch_m100 double precision ch_i,ch_j,ch_m
101 integer particle_type_born(nexternal-1)101 integer particle_type_born(nexternal-1)
102 common /c_particle_type_born/particle_type_born102 common /c_particle_type_born/particle_type_born
103 logical particle_tag(nexternal)
104 common /c_particle_tag/particle_tag
105 logical particle_tag_born(nexternal-1)
106 common /c_particle_tag/particle_tag_born
103 logical need_color_links, need_charge_links107 logical need_color_links, need_charge_links
104 common /c_need_links/need_color_links, need_charge_links108 common /c_need_links/need_color_links, need_charge_links
105 integer extra_cnt, isplitorder_born, isplitorder_cnt109 integer extra_cnt, isplitorder_born, isplitorder_cnt
@@ -130,6 +134,7 @@
130 stop134 stop
131 endif135 endif
132 particle_type(i)=particle_type_D(nFKSprocess,i)136 particle_type(i)=particle_type_D(nFKSprocess,i)
137 particle_tag(i)=particle_tag_D(nFKSprocess,i)
133 particle_charge(i)=particle_charge_D(nFKSprocess,i)138 particle_charge(i)=particle_charge_D(nFKSprocess,i)
134 pdg_type(i)=pdg_type_D(nFKSprocess,i)139 pdg_type(i)=pdg_type_D(nFKSprocess,i)
135 ! is_aorg is true if the particle can induce soft singularities140 ! is_aorg is true if the particle can induce soft singularities
@@ -144,18 +149,22 @@
144 if (i.lt.min(i_fks,j_fks)) then149 if (i.lt.min(i_fks,j_fks)) then
145 particle_type_born(i)=particle_type(i)150 particle_type_born(i)=particle_type(i)
146 particle_charge_born(i)=particle_charge(i)151 particle_charge_born(i)=particle_charge(i)
152 particle_tag_born(i)=particle_tag(i)
147 elseif (i.gt.max(i_fks,j_fks)) then153 elseif (i.gt.max(i_fks,j_fks)) then
148 particle_type_born(i-1)=particle_type(i)154 particle_type_born(i-1)=particle_type(i)
149 particle_charge_born(i-1)=particle_charge(i)155 particle_charge_born(i-1)=particle_charge(i)
156 particle_tag_born(i-1)=particle_tag(i)
150 elseif (i.eq.min(i_fks,j_fks)) then157 elseif (i.eq.min(i_fks,j_fks)) then
151 i_type=particle_type(i_fks)158 i_type=particle_type(i_fks)
152 j_type=particle_type(j_fks)159 j_type=particle_type(j_fks)
153 ch_i=particle_charge(i_fks)160 ch_i=particle_charge(i_fks)
154 ch_j=particle_charge(j_fks)161 ch_j=particle_charge(j_fks)
162 particle_tag_born(i) = particle_tag(j_fks)
155 call get_mother_col_charge(i_type,ch_i,j_type,ch_j,m_type,ch_m) 163 call get_mother_col_charge(i_type,ch_i,j_type,ch_j,m_type,ch_m)
156 particle_type_born(i)=m_type164 particle_type_born(i)=m_type
157 particle_charge_born(i)=ch_m165 particle_charge_born(i)=ch_m
158 elseif (i.ne.max(i_fks,j_fks)) then166 elseif (i.ne.max(i_fks,j_fks)) then
167 particle_tag_born(i) = particle_tag(i)
159 particle_type_born(i)=particle_type(i)168 particle_type_born(i)=particle_type(i)
160 particle_charge_born(i)=particle_charge(i)169 particle_charge_born(i)=particle_charge(i)
161 endif170 endif
162171
=== modified file 'Template/NLO/SubProcesses/cuts.f'
--- Template/NLO/SubProcesses/cuts.f 2021-01-08 10:23:30 +0000
+++ Template/NLO/SubProcesses/cuts.f 2021-10-15 11:42:16 +0000
@@ -40,42 +40,28 @@
40 external R2_04,invm2_04,pt_04,eta_04,pt,eta40 external R2_04,invm2_04,pt_04,eta_04,pt,eta
41C recombination of photons41C recombination of photons
42 double precision p_reco(0:4,nexternal), R_reco42 double precision p_reco(0:4,nexternal), R_reco
43 integer iPDG_reco(nexternal)43 integer iPDG_reco(nexternal),nphiso
44c local integers44c local integers
45 integer i,j45 integer i,j
46c temporary variable for caching locally computation46c bare parton algorithm
47 double precision tmpvar47 integer nPART
48 double precision pPART(0:3,nexternal)
48c jet cluster algorithm49c jet cluster algorithm
49 integer nQCD,NJET,JET(nexternal)50 integer nQCD,NJET,JET(nexternal)
50 double precision pQCD(0:3,nexternal),PJET(0:3,nexternal)51 double precision pQCD(0:3,nexternal),PJET(0:3,nexternal)
51 double precision rfj,sycut,palg,amcatnlo_fastjetdmerge
52 integer njet_eta52 integer njet_eta
53 integer mm53 double precision pgamma(0:3,nexternal),pgamma_iso(0:3,nexternal)
54c Photon isolation54 integer nph
55 integer nph,nem,k,nin
56 double precision ptg,chi_gamma_iso,iso_getdrv40
57 double precision Etsum(0:nexternal)
58 real drlist(nexternal)
59 double precision pgamma(0:3,nexternal),pem(0:3,nexternal)
60 logical alliso
61c Sort array of results: ismode>0 for real, isway=0 for ascending order
62 integer ismode,isway,izero,isorted(nexternal)
63 parameter (ismode=1)
64 parameter (isway=0)
65 parameter (izero=0)
66c The UNLOPS cut
67 double precision p_unlops(0:3,nexternal)
68 include "run.inc" ! includes the ickkw parameter55 include "run.inc" ! includes the ickkw parameter
69 logical passUNLOPScuts
70c PDG specific cut
71 double precision etmin(nincoming+1:nexternal-1)
72 double precision etmax(nincoming+1:nexternal-1)
73 double precision mxxmin(nincoming+1:nexternal-1,nincoming+1:nexternal-1)
74 common /to_cuts/etmin,etmax,mxxmin
75c logicals that define if particles are leptons, jets or photons. These56c logicals that define if particles are leptons, jets or photons. These
76c are filled from the PDG codes (iPDG array) in this function.57c are filled from the PDG codes (iPDG array) in this function.
77 logical is_a_lp(nexternal),is_a_lm(nexternal),is_a_j(nexternal)58 logical is_a_lp(nexternal),is_a_lm(nexternal),is_a_j(nexternal)
78 $ ,is_a_ph(nexternal)59 $,is_a_ph(nexternal),is_nph_iso(nexternal),is_nextph_iso(nexternal)
60 $,is_nextph_iso_reco(nexternal)
61 logical is_a_lp_reco(nexternal),is_a_lm_reco(nexternal)
62 logical passcuts_leptons, passcuts_unlops_jv, passcuts_photons,
63 $ passcuts_jets, passcuts_pdgs
64
7965
80 passcuts_user=.true. ! event is okay; otherwise it is changed66 passcuts_user=.true. ! event is okay; otherwise it is changed
8167
@@ -84,98 +70,329 @@
84C Cuts from the run_card.dat70C Cuts from the run_card.dat
85C***************************************************************71C***************************************************************
86C***************************************************************72C***************************************************************
87 !first recombine the photons and fermions73
74 ! Find the bare QCD partons
75 ! This is used only as input to the photon isolation
76 call identify_PART_partons(p,istatus,ipdg,pPART,nPART,is_a_lp,is_a_lm)
77
78 ! Apply the Photon cuts on isolated photons based on the bare particles
79 passcuts_user = passcuts_user .and.
80 $ passcuts_photons(p,istatus,ipdg,is_a_lp,is_a_lm,pPART,nPART,
81 $ pgamma,nph,is_nph_iso,is_nextph_iso)
82 if (.not.passcuts_user) return
83
84 ! Recombine the photons and fermions
88 call recombine_momenta(rphreco, etaphreco, lepphreco, quarkphreco,85 call recombine_momenta(rphreco, etaphreco, lepphreco, quarkphreco,
89 $ p, iPDG, p_reco, iPDG_reco)86 $ p, iPDG, is_nextph_iso, p_reco, iPDG_reco, is_nextph_iso_reco)
9087
91c88 ! Apply the reco lepton cuts
92c CHARGED LEPTON CUTS89 passcuts_user = passcuts_user .and.
93c90 $ passcuts_leptons(p_reco,istatus,ipdg_reco,is_a_lp_reco,is_a_lm_reco)
94c find the charged leptons (also used in the photon isolation cuts below)91 if (.not.passcuts_user) return
95 do i=1,nexternal92
96 if(istatus(i).eq.1 .and.93 ! Find the reco QCD partons including
97 & (ipdg_reco(i).eq.11 .or. ipdg_reco(i).eq.13 .or. ipdg_reco(i).eq.15)) then94 ! A. All photons if gamma_is_j is on
98 is_a_lm(i)=.true.95 ! B. Non-iso, non-reco photons if reco is on
99 else96 call identify_QCD_partons(is_nextph_iso_reco,p_reco,istatus,ipdg_reco,is_a_j,pQCD,nQCD)
100 is_a_lm(i)=.false.97
101 endif98 ! Apply the UNLOPS/JetVeto cuts
102 if(istatus(i).eq.1 .and.99 passcuts_user = passcuts_user .and.
103 & (ipdg_reco(i).eq.-11 .or. ipdg_reco(i).eq.-13 .or. ipdg_reco(i).eq.-15)) then100 $ passcuts_unlops_jv(p_reco,istatus,ipdg_reco,pQCD,nQCD,ickkw)
104 is_a_lp(i)=.true.101 if (.not.passcuts_user) return
105 else102
106 is_a_lp(i)=.false.103 ! Apply the Jet cuts
107 endif104 passcuts_user = passcuts_user .and.
108 enddo105 $ passcuts_jets(p_reco,pQCD,nQCD,pgamma,nph,is_nph_iso,ickkw)
109c apply the charged lepton cuts106 if (.not.passcuts_user) return
110 do i=nincoming+1,nexternal107
111 if (is_a_lp(i).or.is_a_lm(i)) then108 ! Apply PDG specific cuts
112c transverse momentum109 passcuts_user = passcuts_user .and.
113 if (ptl.gt.0d0) then110 $ passcuts_pdgs(p_reco,istatus,ipdg_reco)
114 if (pt_04(p_reco(0,i)).lt.ptl) then111 if (.not.passcuts_user) return
115 passcuts_user=.false.112
116 return113C***************************************************************
117 endif114C***************************************************************
118 endif115C PUT HERE YOUR USER-DEFINED CUTS
119c pseudo-rapidity116C***************************************************************
120 if (etal.gt.0d0) then117C***************************************************************
121 if (abs(eta_04(p_reco(0,i))).gt.etal) then118C
122 passcuts_user=.false.119c$$$C EXAMPLE: cut on top quark pT
123 return120c$$$C Note that PDG specific cut are more optimised than simple user cut
124 endif121c$$$ do i=1,nexternal ! loop over all external particles
125 endif122c$$$ if (istatus(i).eq.1 ! final state particle
126c DeltaR and invariant mass cuts123c$$$ & .and. abs(ipdg(i)).eq.6) then ! top quark
127 if (is_a_lp(i)) then124c$$$C apply the pT cut (pT should be large than 200 GeV for the event to
128 do j=nincoming+1,nexternal125c$$$C pass cuts)
129 if (is_a_lm(j)) then126c$$$ if ( p(1,i)**2+p(2,i)**2 .lt. 200d0**2 ) then
130 if (drll.gt.0d0) then127c$$$C momenta do not pass cuts. Set passcuts_user to false and return
131 if (R2_04(p_reco(0,i),p_reco(0,j)).lt.drll**2) then128c$$$ passcuts_user=.false.
132 passcuts_user=.false.129c$$$ return
133 return130c$$$ endif
134 endif131c$$$ endif
135 endif132c$$$ enddo
136 if (mll.gt.0d0) then133c
137 if (invm2_04(p_reco(0,i),p_reco(0,j),1d0).lt.mll**2) then134 return
138 passcuts_user=.false.135 end
139 return136
140 endif137 subroutine identify_PART_partons(p,istatus,ipdg,pPART,nPART,is_a_lp,is_a_lm)
141 endif138 implicit none
142 if (ipdg_reco(i).eq.-ipdg_reco(j)) then139 include 'nexternal.inc'
143 if (drll_sf.gt.0d0) then140 integer istatus(nexternal)
144 if (R2_04(p_reco(0,i),p_reco(0,j)).lt.drll_sf**2) then141 integer iPDG(nexternal)
145 passcuts_user=.false.142 double precision p(0:4,nexternal)
146 return143 integer nPART
147 endif144 double precision pPART(0:3,nexternal)
148 endif145 logical is_a_lp(nexternal),is_a_lm(nexternal)
149 if (mll_sf.gt.0d0) then146 include "run.inc"
150 if (invm2_04(p_reco(0,i),p_reco(0,j),1d0).lt.mll_sf**2)147 include "cuts.inc"
151 $ then148
152 passcuts_user=.false.149 integer i, j
153 return150c
154 endif151c Bare partons and leptons
155 endif152c
156 endif153 nPART=0
154 do j=1,nexternal
155 is_a_lp(j)=.false.
156 is_a_lm(j)=.false.
157c Partons
158 if (istatus(j).eq.1 .and.
159 & (abs(ipdg(j)).le.maxjetflavor .or. ipdg(j).eq.21)
160 &) then
161 nPART=nPART+1
162 do i=0,3
163 pPART(i,nPART)=p(i,j)
164 enddo
165 endif
166c Leptons
167 if (ipdg(j).eq.11 .or. ipdg(j).eq.13
168 $ .or. ipdg(j).eq.15) then
169 is_a_lm(j)=.true.
170 endif
171 if (ipdg(j).eq.-11 .or. ipdg(j).eq.-13
172 $ .or. ipdg(j).eq.-15) then
173 is_a_lp(j)=.true.
174 endif
175 enddo
176
177 return
178 end
179
180 logical function passcuts_photons(p,istatus,ipdg,is_a_lp,is_a_lm,
181 $pPART,nPART,pgamma,nph,is_nph_iso,is_nextph_iso)
182 implicit none
183 include 'nexternal.inc'
184 integer istatus(nexternal)
185 integer iPDG(nexternal)
186 double precision p(0:4,nexternal)
187 logical is_a_lp(nexternal),is_a_lm(nexternal)
188 integer nPART, nph
189 double precision pPART(0:3,nexternal), pgamma(0:3,nexternal)
190 double precision pgamma_iso(0:3,nexternal)
191 logical is_nph_iso(nexternal),is_nextph_iso(nexternal)
192 include "cuts.inc"
193 include "run.inc"
194 integer i,j,k,mu
195c Sort array of results: ismode>0 for real, isway=0 for ascending order
196 integer ismode,isway,izero,isorted(nexternal)
197 parameter (ismode=1)
198 parameter (isway=0)
199 parameter (izero=0)
200
201c Photon isolation
202 integer nem,nin,nphiso
203 double precision ptg,chi_gamma_iso,iso_getdrv40
204 double precision Etsum(0:nexternal)
205 real drlist(nexternal)
206 double precision pem(0:3,nexternal)
207
208 logical alliso,isolated
209 integer get_n_tagged_photons
210 logical is_a_ph(nexternal)
211
212 REAL*8 pt,eta
213 external pt,eta
214
215 passcuts_photons = .true.
216
217c
218c PHOTON (ISOLATION) CUTS
219c
220c Initialise common logical iso
221 do i=nincoming+1,nexternal
222 is_nextph_iso(i)=.False.
223 enddo
224c find the photons
225 do i=nincoming+1,nexternal
226 if (ipdg(i).eq.22 .and. .not.gamma_is_j) then
227 is_a_ph(i)=.true.
228 else
229 is_a_ph(i)=.false.
230 endif
231 enddo
232
233 if (ptgmin.ne.0d0) then
234 nph=0
235 do j=nincoming+1,nexternal
236 if (is_a_ph(j)) then
237 nph=nph+1
238 do i=0,3
239 pgamma(i,nph)=p(i,j)
240 enddo
241 endif
242 enddo
243 if(nph.eq.0) return
244
245 if(isoEM)then
246 nem=nph
247 do k=1,nem
248 do i=0,3
249 pem(i,k)=pgamma(i,k)
250 enddo
251 enddo
252 do j=nincoming+1,nexternal
253 if (is_a_lp(j).or.is_a_lm(j)) then
254 nem=nem+1
255 do i=0,3
256 pem(i,nem)=p(i,j)
257 enddo
258 endif
259 enddo
260 endif
261
262 nphiso=0
263
264 j=0
265c Loop over all photons
266 do while(j.lt.nph)
267
268 j=j+1
269 is_nph_iso(j)=.False.
270 ptg=pt(pgamma(0,j))
271 if(ptg.lt.ptgmin)then
272 cycle
273 endif
274 if (etagamma.gt.0d0) then
275 if (abs(eta(pgamma(0,j))).gt.etagamma) then
276 cycle
277 endif
278 endif
279
280c Isolate from hadronic energy
281 do i=1,nPART
282 drlist(i)=sngl(iso_getdrv40(pgamma(0,j),pPART(0,i)))
283 enddo
284 call sortzv(drlist,isorted,nPART,ismode,isway,izero)
285 Etsum(0)=0.d0
286 nin=0
287 do i=1,nPART
288 if(dble(drlist(isorted(i))).le.R0gamma)then
289 nin=nin+1
290 Etsum(nin)=Etsum(nin-1)+pt(pPART(0,isorted(i)))
291 endif
292 enddo
293 isolated=.True.
294 do i=1,nin
295 if(Etsum(i).gt.chi_gamma_iso(dble(drlist(isorted(i))),
296 $ R0gamma,xn,epsgamma,ptg)) then
297 isolated=.False.
298 exit
299 endif
300 enddo
301 if(.not.isolated)cycle
302
303c Isolate from EM energy
304 if(isoEM.and.nem.gt.1)then
305 do i=1,nem
306 drlist(i)=sngl(iso_getdrv40(pgamma(0,j),pem(0,i)))
307 enddo
308 call sortzv(drlist,isorted,nem,ismode,isway,izero)
309c First of list must be the photon: check this, and drop it
310 if(isorted(1).ne.j.or.drlist(isorted(1)).gt.1.e-4)then
311 write(*,*)'Error #1 in photon isolation'
312 write(*,*)j,isorted(1),drlist(isorted(1))
313 stop
314 endif
315 Etsum(0)=0.d0
316 nin=0
317 do i=2,nem
318 if(dble(drlist(isorted(i))).le.R0gamma)then
319 nin=nin+1
320 Etsum(nin)=Etsum(nin-1)+pt(pem(0,isorted(i)))
157 endif321 endif
158 enddo322 enddo
323 isolated=.True.
324 do i=1,nin
325 if(Etsum(i).gt.chi_gamma_iso(dble(drlist(isorted(i))),
326 $ R0gamma,xn,epsgamma,ptg)) then
327 isolated=.False.
328 exit
329 endif
330 enddo
331 if(.not.isolated)cycle
159 endif332 endif
333 is_nph_iso(j)=.True.
334 nphiso=nphiso+1
335
336 if (nphiso.gt.0) then
337 do mu=0,3
338 pgamma_iso(mu,nphiso)=pgamma(mu,j)
339 enddo
340
341 do i=nincoming+1,nexternal
342 if ( ipdg(i).eq.22 .and.
343 $ pt(p(0,i)).eq.pt(pgamma_iso(0,nphiso)) ) then
344 is_nextph_iso(i)=.True.
345 endif
346 enddo
347 endif
348 enddo
349c End of loop over photons
350
351 if(nphiso.lt.get_n_tagged_photons())then
352 passcuts_photons=.false.
353 return
160 endif354 endif
161 enddo355 endif
356
357 return
358 end
359
360
361 subroutine identify_QCD_partons(is_iso,p,istatus,ipdg,is_a_j,pQCD,nQCD)
362 implicit none
363 include 'nexternal.inc'
364 integer istatus(nexternal)
365 integer iPDG(nexternal)
366 double precision p(0:4,nexternal)
367 logical is_a_j(nexternal)
368 integer nQCD
369 double precision pQCD(0:3,nexternal)
370 logical is_iso(nexternal)
371 REAL*8 pt,eta
372 external pt,eta
373 include "run.inc"
374 include "cuts.inc"
375
376 integer i, j
377
162c378c
163c JET CUTS379c JET CUTS
164c380c
165c find the jets381c find the jets
166 do i=1,nexternal382 do i=1,nexternal
167 if (istatus(i).eq.1 .and.383 if (istatus(i).eq.1 .and.
168 & (abs(ipdg_reco(i)).le.maxjetflavor .or. ipdg_reco(i).eq.21384 & ( abs(ipdg(i)).le.maxjetflavor .or. ipdg(i).eq.21
169 & .or.(ipdg_reco(i).eq.22.and.gamma_is_j))) then385 & .or. (ipdg(i).eq.22.and.gamma_is_j) .or.
386 & (ipdg(i).eq.22.and. .not.is_iso(i)) )
387 &) then
170 is_a_j(i)=.true.388 is_a_j(i)=.true.
171 else389 else
172 is_a_j(i)=.false.390 is_a_j(i)=.false.
173 endif391 endif
174 enddo392 enddo
175
176c If we do not require a mimimum jet energy, there's no need to apply393c If we do not require a mimimum jet energy, there's no need to apply
177c jet clustering and all that.394c jet clustering and all that.
178 if (ptj.gt.0d0.or.ptgmin.gt.0d0) then395 if (ptj.ne.0d0.or.ptgmin.ne.0d0) then
179c Put all (light) QCD partons in momentum array for jet clustering.396c Put all (light) QCD partons in momentum array for jet clustering.
180c From the run_card.dat, maxjetflavor defines if b quark should be397c From the run_card.dat, maxjetflavor defines if b quark should be
181c considered here (via the logical variable 'is_a_jet'). nQCD becomes398c considered here (via the logical variable 'is_a_jet'). nQCD becomes
@@ -186,41 +403,43 @@
186 if (is_a_j(j)) then403 if (is_a_j(j)) then
187 nQCD=nQCD+1404 nQCD=nQCD+1
188 do i=0,3405 do i=0,3
189 pQCD(i,nQCD)=p_reco(i,j)406 pQCD(i,nQCD)=p(i,j)
190 enddo407 enddo
191 endif408 endif
192 enddo409 enddo
193 endif410 endif
194411
195c THE UNLOPS CUT:412 return
196 if (ickkw.eq.4 .and. ptj.gt.0d0) then413 end
197c Use special pythia pt cut for minimal pT414
198 do i=1,nexternal415
199 do j=0,3416 logical function passcuts_jets(p,pQCD,nQCD,pgamma,nph,is_nph_iso,ickkw)
200 p_unlops(j,i)=p_reco(j,i)417 implicit none
201 enddo418 include 'nexternal.inc'
202 enddo419 double precision p(0:4,nexternal)
203 call pythia_UNLOPS(p_unlops,passUNLOPScuts)420 integer nQCD, nph
204 if (.not. passUNLOPScuts) then421 double precision pQCD(0:3,nexternal), pgamma(0:3,nexternal)
205 passcuts_user=.false.422 logical is_nph_iso(nexternal)
206 return423 integer ickkw
207 endif424 include "cuts.inc"
208c Bypass normal jet cuts425
209 goto 122426 integer NJET,JET(nexternal)
210c THE VETO XSEC CUT:427 double precision rfj,sycut,palg,amcatnlo_fastjetdmerge
211 elseif (ickkw.eq.-1 .and. ptj.gt.0d0) then428 double precision PJET(0:3,nexternal)
212c Use veto'ed Xsec for analytic NNLL resummation429 integer mm
213 if (nQCD.ne.1) then430 integer i,j
214 write (*,*) 'ERROR: more than one QCD parton in '/431
215 $ /'this event in cuts.f. There should only be one'432 integer get_n_tagged_photons
216 stop433
217 endif434 REAL*8 pt,eta
218 if (pt(pQCD(0,1)) .gt. ptj) then435 external pt,eta
219 passcuts_user=.false.436
220 return437 passcuts_jets=.true.
221 endif438
222 endif439c JET CUTS
223440
441C do nothing if ickkw=4 (UNLOPS)
442 if (ickkw.eq.4)return
224443
225 if (ptj.gt.0d0.and.nQCD.gt.1) then444 if (ptj.gt.0d0.and.nQCD.gt.1) then
226445
@@ -233,11 +452,10 @@
233 if(abs(pQCD(0,j)/p(0,1)).lt.1.d-8) mm=mm+1452 if(abs(pQCD(0,j)/p(0,1)).lt.1.d-8) mm=mm+1
234 enddo453 enddo
235 if(mm.gt.1)then454 if(mm.gt.1)then
236 passcuts_user=.false.455 passcuts_jets=.false.
237 return456 return
238 endif457 endif
239458
240
241c Define jet clustering parameters (from cuts.inc via the run_card.dat)459c Define jet clustering parameters (from cuts.inc via the run_card.dat)
242 palg=JETALGO ! jet algorithm: 1.0=kt, 0.0=C/A, -1.0 = anti-kt460 palg=JETALGO ! jet algorithm: 1.0=kt, 0.0=C/A, -1.0 = anti-kt
243 rfj=JETRADIUS ! the radius parameter461 rfj=JETRADIUS ! the radius parameter
@@ -268,127 +486,178 @@
268486
269c Apply the jet cuts487c Apply the jet cuts
270 if (njet .ne. nQCD .and. njet .ne. nQCD-1) then488 if (njet .ne. nQCD .and. njet .ne. nQCD-1) then
271 passcuts_user=.false.489 passcuts_jets=.false.
272 return490 return
273 endif491 endif
274 endif492 endif
275 122 continue493
276c494 return
277c PHOTON (ISOLATION) CUTS495 end
278c496
279c find the photons497
498
499 logical function passcuts_unlops_jv(p,istatus,ipdg,pQCD,nQCD,ickkw)
500 implicit none
501 include 'nexternal.inc'
502 integer istatus(nexternal)
503 integer iPDG(nexternal)
504 double precision p(0:4,nexternal)
505 logical is_a_j(nexternal)
506 integer nQCD
507 double precision pQCD(0:3,nexternal)
508 integer ickkw
509 include "cuts.inc"
510 double precision p_unlops(0:3,nexternal)
511 logical passUNLOPScuts
512 integer i, j
513
514 REAL*8 pt
515 external pt
516
517 passcuts_unlops_jv=.true.
518
519
520c THE UNLOPS CUT:
521 if (ickkw.eq.4 .and. ptj.gt.0d0) then
522c Use special pythia pt cut for minimal pT
523 do i=1,nexternal
524 do j=0,3
525 p_unlops(j,i)=p(j,i)
526 enddo
527 enddo
528 call pythia_UNLOPS(p_unlops,passUNLOPScuts)
529 if (.not. passUNLOPScuts) then
530 passcuts_unlops_jv=.false.
531 return
532 endif
533c THE VETO XSEC CUT:
534 elseif (ickkw.eq.-1 .and. ptj.gt.0d0) then
535c Use veto'ed Xsec for analytic NNLL resummation
536 if (nQCD.ne.1) then
537 write (*,*) 'ERROR: more than one QCD parton in '/
538 $ /'this event in cuts.f. There should only be one'
539 stop
540 endif
541 if (pt(pQCD(0,1)) .gt. ptj) then
542 passcuts_unlops_jv=.false.
543 return
544 endif
545 endif
546 return
547 end
548
549
550
551 logical function passcuts_leptons(p,istatus,ipdg,is_a_lp_reco,is_a_lm_reco)
552 implicit none
553 include 'nexternal.inc'
554 integer istatus(nexternal)
555 integer iPDG(nexternal)
556 double precision p(0:4,nexternal)
557 logical is_a_lp_reco(nexternal),is_a_lm_reco(nexternal)
558
559 REAL*8 R2_04,invm2_04,pt_04,eta_04,pt,eta
560 external R2_04,invm2_04,pt_04,eta_04,pt,eta
561 integer i,j
562
563 include 'cuts.inc'
564
565 passcuts_leptons=.true.
566
567c
568c CHARGED LEPTON CUTS
569c
570c find the charged leptons (also used in the photon isolation cuts below)
280 do i=1,nexternal571 do i=1,nexternal
281 if (istatus(i).eq.1 .and. ipdg(i).eq.22 .and. .not.gamma_is_j) then572 if(istatus(i).eq.1 .and.
282 is_a_ph(i)=.true.573 & (ipdg(i).eq.11 .or. ipdg(i).eq.13 .or. ipdg(i).eq.15)) then
283 else574 is_a_lm_reco(i)=.true.
284 is_a_ph(i)=.false.575 else
576 is_a_lm_reco(i)=.false.
577 endif
578 if(istatus(i).eq.1 .and.
579 & (ipdg(i).eq.-11 .or. ipdg(i).eq.-13 .or. ipdg(i).eq.-15)) then
580 is_a_lp_reco(i)=.true.
581 else
582 is_a_lp_reco(i)=.false.
285 endif583 endif
286 enddo584 enddo
287 if (ptgmin.gt.0d0) then585c apply the charged lepton cuts
288 nph=0586 do i=nincoming+1,nexternal
289 do j=nincoming+1,nexternal587 if (is_a_lp_reco(i).or.is_a_lm_reco(i)) then
290 if (is_a_ph(j)) then588c transverse momentum
291 nph=nph+1589 if (ptl.gt.0d0) then
292 do i=0,3590 if (pt_04(p(0,i)).lt.ptl) then
293 pgamma(i,nph)=p(i,j)591 passcuts_leptons=.false.
294 enddo592 return
295 endif593 endif
296 enddo594 endif
297 if(nph.eq.0)goto 444595c pseudo-rapidity
298 write(*,*) 'ERROR in cuts.f: photon isolation is not working'596 if (etal.gt.0d0) then
299 $ // ' for mixed QED-QCD corrections'597 if (abs(eta_04(p(0,i))).gt.etal) then
300 stop 1598 passcuts_leptons=.false.
301 599 return
302 if(isoEM)then600 endif
303 nem=nph601 endif
304 do k=1,nem602c DeltaR and invariant mass cuts
305 do i=0,3603 if (is_a_lp_reco(i)) then
306 pem(i,k)=pgamma(i,k)604 do j=nincoming+1,nexternal
307 enddo605 if (is_a_lm_reco(j)) then
308 enddo606 if (drll.gt.0d0) then
309 do j=nincoming+1,nexternal607 if (R2_04(p(0,i),p(0,j)).lt.drll**2) then
310 if (is_a_lp(j).or.is_a_lm(j)) then608 passcuts_leptons=.false.
311 nem=nem+1609 return
312 do i=0,3610 endif
313 pem(i,nem)=p(i,j)611 endif
314 enddo612 if (mll.gt.0d0) then
315 endif613 if (invm2_04(p(0,i),p(0,j),1d0).lt.mll**2) then
316 enddo614 passcuts_leptons=.false.
317 endif615 return
318 616 endif
319 alliso=.true.617 endif
320618 if (ipdg(i).eq.-ipdg(j)) then
321 j=0619 if (drll_sf.gt.0d0) then
322 do while(j.lt.nph.and.alliso)620 if (R2_04(p(0,i),p(0,j)).lt.drll_sf**2) then
323c Loop over all photons621 passcuts_leptons=.false.
324 j=j+1622 return
325 623 endif
326 ptg=pt(pgamma(0,j))624 endif
327 if(ptg.lt.ptgmin)then625 if (mll_sf.gt.0d0) then
328 passcuts_user=.false.626 if (invm2_04(p(0,i),p(0,j),1d0).lt.mll_sf**2)
329 return627 $ then
330 endif628 passcuts_leptons=.false.
331 if (etagamma.gt.0d0) then629 return
332 if (abs(eta(pgamma(0,j))).gt.etagamma) then630 endif
333 passcuts_user=.false.631 endif
334 return632 endif
335 endif
336 endif
337
338c Isolate from hadronic energy
339 do i=1,nQCD
340 drlist(i)=sngl(iso_getdrv40(pgamma(0,j),pQCD(0,i)))
341 enddo
342 call sortzv(drlist,isorted,nQCD,ismode,isway,izero)
343 Etsum(0)=0.d0
344 nin=0
345 do i=1,nQCD
346 if(dble(drlist(isorted(i))).le.R0gamma)then
347 nin=nin+1
348 Etsum(nin)=Etsum(nin-1)+pt(pQCD(0,isorted(i)))
349 endif
350 enddo
351 do i=1,nin
352 alliso=alliso .and.
353 $ Etsum(i).le.chi_gamma_iso(dble(drlist(isorted(i))),
354 $ R0gamma,xn,epsgamma,ptg)
355 enddo
356
357c Isolate from EM energy
358 if(isoEM.and.nem.gt.1)then
359 do i=1,nem
360 drlist(i)=sngl(iso_getdrv40(pgamma(0,j),pem(0,i)))
361 enddo
362 call sortzv(drlist,isorted,nem,ismode,isway,izero)
363c First of list must be the photon: check this, and drop it
364 if(isorted(1).ne.j.or.drlist(isorted(1)).gt.1.e-4)then
365 write(*,*)'Error #1 in photon isolation'
366 write(*,*)j,isorted(1),drlist(isorted(1))
367 stop
368 endif
369 Etsum(0)=0.d0
370 nin=0
371 do i=2,nem
372 if(dble(drlist(isorted(i))).le.R0gamma)then
373 nin=nin+1
374 Etsum(nin)=Etsum(nin-1)+pt(pem(0,isorted(i)))
375 endif633 endif
376 enddo634 enddo
377 do i=1,nin
378 alliso=alliso .and.
379 $ Etsum(i).le.chi_gamma_iso(dble(drlist(isorted(i))),
380 $ R0gamma,xn,epsgamma,ptg)
381 enddo
382 endif635 endif
383c End of loop over photons
384 enddo
385 if(.not.alliso)then
386 passcuts_user=.false.
387 return
388 endif636 endif
389 444 continue637 enddo
390c End photon isolation638
391 endif639 return
640 end
641
642 logical function passcuts_pdgs(p,istatus,ipdg)
643 implicit none
644 include 'nexternal.inc'
645 integer istatus(nexternal)
646 integer iPDG(nexternal)
647 double precision p(0:4,nexternal)
648c PDG specific cut
649 double precision etmin(nincoming+1:nexternal-1)
650 double precision etmax(nincoming+1:nexternal-1)
651 double precision mxxmin(nincoming+1:nexternal-1,nincoming+1:nexternal-1)
652 common /to_cuts/etmin,etmax,mxxmin
653 REAL*8 invm2_04,pt_04
654 external invm2_04,pt_04
655c temporary variable for caching locally computation
656 double precision tmpvar
657 integer i,j
658
659 passcuts_pdgs = .true.
660
392661
393C662C
394C PDG SPECIFIC CUTS (PT/M_IJ)663C PDG SPECIFIC CUTS (PT/M_IJ)
@@ -397,49 +666,24 @@
397 if(etmin(i).gt.0d0 .or. etmax(i).gt.0d0)then666 if(etmin(i).gt.0d0 .or. etmax(i).gt.0d0)then
398 tmpvar = pt_04(p(0,i))667 tmpvar = pt_04(p(0,i))
399 if (tmpvar.lt.etmin(i)) then668 if (tmpvar.lt.etmin(i)) then
400 passcuts_user=.false.669 passcuts_pdgs=.false.
401 return670 return
402 elseif (tmpvar.gt.etmax(i) .and. etmax(i).gt.0d0) then671 elseif (tmpvar.gt.etmax(i) .and. etmax(i).gt.0d0) then
403 passcuts_user=.false.672 passcuts_pdgs=.false.
404 return673 return
405 endif674 endif
406 endif675 endif
407 do j=i+1, nexternal-1676 do j=i+1, nexternal-1
408 if (mxxmin(i,j).gt.0d0)then677 if (mxxmin(i,j).gt.0d0)then
409 if (invm2_04(p(0,i),p(0,j),1d0).lt.mxxmin(i,j)**2)then678 if (invm2_04(p(0,i),p(0,j),1d0).lt.mxxmin(i,j)**2)then
410 passcuts_user=.false.679 passcuts_pdgs=.false.
411 return680 return
412 endif681 endif
413 endif682 endif
414 enddo683 enddo
415 enddo684 enddo
416685 return
417686 end
418C***************************************************************
419C***************************************************************
420C PUT HERE YOUR USER-DEFINED CUTS
421C***************************************************************
422C***************************************************************
423C
424c$$$C EXAMPLE: cut on top quark pT
425c$$$C Note that PDG specific cut are more optimised than simple user cut
426c$$$ do i=1,nexternal ! loop over all external particles
427c$$$ if (istatus(i).eq.1 ! final state particle
428c$$$ & .and. abs(ipdg(i)).eq.6) then ! top quark
429c$$$C apply the pT cut (pT should be large than 200 GeV for the event to
430c$$$C pass cuts)
431c$$$ if ( p(1,i)**2+p(2,i)**2 .lt. 200d0**2 ) then
432c$$$C momenta do not pass cuts. Set passcuts_user to false and return
433c$$$ passcuts_user=.false.
434c$$$ return
435c$$$ endif
436c$$$ endif
437c$$$ enddo
438c
439 return
440 end
441
442
443687
444688
445C***************************************************************689C***************************************************************
@@ -983,5 +1227,21 @@
983 return1227 return
984 end1228 end
9851229
1230 integer function get_n_tagged_photons()
1231 implicit none
1232 integer i
1233 include "nexternal.inc"
1234 logical particle_tag(nexternal)
1235 common /c_particle_tag/particle_tag
1236 get_n_tagged_photons = 0
1237
1238 do i = nincoming+1, nexternal
1239 if (particle_tag(i))
1240 $ get_n_tagged_photons = get_n_tagged_photons+1
1241 enddo
1242
1243 return
1244 end
1245
9861246
9871247
9881248
=== modified file 'Template/NLO/SubProcesses/fks_singular.f'
--- Template/NLO/SubProcesses/fks_singular.f 2021-09-30 16:30:15 +0000
+++ Template/NLO/SubProcesses/fks_singular.f 2021-10-15 11:42:16 +0000
@@ -1519,6 +1519,12 @@
1519 double precision wgt_ME_born,wgt_ME_real1519 double precision wgt_ME_born,wgt_ME_real
1520 common /c_wgt_ME_tree/ wgt_ME_born,wgt_ME_real1520 common /c_wgt_ME_tree/ wgt_ME_born,wgt_ME_real
15211521
1522 integer ntagph
1523 double precision resc
1524 integer get_n_tagged_photons
1525 double precision get_rescale_alpha_factor
1526 external get_n_tagged_photons get_rescale_alpha_factor
1527
1522 if (wgt1.eq.0d0 .and. wgt2.eq.0d0 .and. wgt3.eq.0d0) return1528 if (wgt1.eq.0d0 .and. wgt2.eq.0d0 .and. wgt3.eq.0d0) return
1523c Check for NaN's and INF's. Simply skip the contribution1529c Check for NaN's and INF's. Simply skip the contribution
1524 if (wgt1.ne.wgt1) return1530 if (wgt1.ne.wgt1) return
@@ -1582,9 +1588,21 @@
1582 icontr=icontr+11588 icontr=icontr+1
1583 call weight_lines_allocated(nexternal,icontr,max_wgt,max_iproc)1589 call weight_lines_allocated(nexternal,icontr,max_wgt,max_iproc)
1584 itype(icontr)=type1590 itype(icontr)=type
1585 wgt(1,icontr)=wgt11591
1586 wgt(2,icontr)=wgt21592C here we rescale the contributions by the ratio of alpha's in different
1587 wgt(3,icontr)=wgt31593C schemes; it is needed when there are tagged photons around
1594 ntagph = get_n_tagged_photons()
1595 if (ntagph.eq.0) then
1596 wgt(1,icontr)=wgt1
1597 wgt(2,icontr)=wgt2
1598 wgt(3,icontr)=wgt3
1599 else if (ntagph.gt.0) then
1600 resc = get_rescale_alpha_factor(ntagph, orders(qed_pos))
1601 wgt(1,icontr) = wgt1 * resc
1602 wgt(2,icontr) = wgt2 * resc
1603 wgt(3,icontr) = wgt3 * resc
1604 endif
1605
1588 bjx(1,icontr)=xbk(1)1606 bjx(1,icontr)=xbk(1)
1589 bjx(2,icontr)=xbk(2)1607 bjx(2,icontr)=xbk(2)
1590 scales2(1,icontr)=QES21608 scales2(1,icontr)=QES2
@@ -5555,6 +5573,8 @@
5555 integer fks_j_from_i(nexternal,0:nexternal)5573 integer fks_j_from_i(nexternal,0:nexternal)
5556 & ,particle_type(nexternal),pdg_type(nexternal)5574 & ,particle_type(nexternal),pdg_type(nexternal)
5557 common /c_fks_inc/fks_j_from_i,particle_type,pdg_type5575 common /c_fks_inc/fks_j_from_i,particle_type,pdg_type
5576 logical particle_tag(nexternal)
5577 common /c_particle_tag/particle_tag
5558 double precision particle_charge(nexternal)5578 double precision particle_charge(nexternal)
5559 common /c_charges/particle_charge5579 common /c_charges/particle_charge
5560 include "run.inc"5580 include "run.inc"
@@ -5787,7 +5807,7 @@
5787 if (particle_charge(i).eq.0d0.and.pdg_type(i).ne.22)5807 if (particle_charge(i).eq.0d0.and.pdg_type(i).ne.22)
5788 $ cycle5808 $ cycle
5789C set charge factors5809C set charge factors
5790 if (pdg_type(i).eq.22) then5810 if (pdg_type(i).eq.22.and..not.particle_tag(i)) then
5791 c_used = 0d05811 c_used = 0d0
5792 gamma_used = gamma_ph5812 gamma_used = gamma_ph
5793 gammap_used = gammap_ph5813 gammap_used = gammap_ph
@@ -6067,7 +6087,7 @@
6067 if (particle_charge(i).eq.0d0.and.pdg_type(i).ne.22)6087 if (particle_charge(i).eq.0d0.and.pdg_type(i).ne.22)
6068 $ cycle6088 $ cycle
6069C set charge factors6089C set charge factors
6070 if (pdg_type(i).eq.22) then6090 if (pdg_type(i).eq.22.and..not.particle_tag(i)) then
6071 c_used = 0d06091 c_used = 0d0
6072 gamma_used = gamma_ph6092 gamma_used = gamma_ph
6073 gammap_used = gammap_ph6093 gammap_used = gammap_ph
@@ -6396,6 +6416,8 @@
6396 double precision particle_charge(nexternal), particle_charge_born(nexternal-1)6416 double precision particle_charge(nexternal), particle_charge_born(nexternal-1)
6397 common /c_charges/particle_charge6417 common /c_charges/particle_charge
6398 common /c_charges_born/particle_charge_born6418 common /c_charges_born/particle_charge_born
6419 logical particle_tag(nexternal)
6420 common /c_particle_tag/particle_tag
6399 include 'coupl.inc'6421 include 'coupl.inc'
6400 include 'q_es.inc'6422 include 'q_es.inc'
6401 double precision p(0:3,nexternal),xmu2,double,single6423 double precision p(0:3,nexternal),xmu2,double,single
@@ -6504,7 +6526,7 @@
6504 if (pdg_type(i).ne.22) then6526 if (pdg_type(i).ne.22) then
6505 contr2=contr2-particle_charge(i)**26527 contr2=contr2-particle_charge(i)**2
6506 contr1=contr1-3d0/2d0*particle_charge(i)**26528 contr1=contr1-3d0/2d0*particle_charge(i)**2
6507 else6529 elseif (.not.particle_tag(i)) then
6508 contr1=contr1-gamma_ph6530 contr1=contr1-gamma_ph
6509 endif6531 endif
6510 else6532 else
@@ -6695,6 +6717,8 @@
6695 double precision particle_charge(nexternal), particle_charge_born(nexternal-1)6717 double precision particle_charge(nexternal), particle_charge_born(nexternal-1)
6696 common /c_charges/particle_charge6718 common /c_charges/particle_charge
6697 common /c_charges_born/particle_charge_born6719 common /c_charges_born/particle_charge_born
6720 logical particle_tag(nexternal)
6721 common /c_particle_tag/particle_tag
6698 double precision zero6722 double precision zero
6699 parameter (zero=0d0)6723 parameter (zero=0d0)
67006724
@@ -6839,7 +6863,7 @@
6839 do i=nincoming+1,nexternal6863 do i=nincoming+1,nexternal
6840 if (pdg_type(i).eq.21) ngluons_FKS(nFKSprocess)6864 if (pdg_type(i).eq.21) ngluons_FKS(nFKSprocess)
6841 $ =ngluons_FKS(nFKSprocess)+16865 $ =ngluons_FKS(nFKSprocess)+1
6842 if (pdg_type(i).eq.22) nphotons_FKS(nFKSprocess)6866 if (pdg_type(i).eq.22.and..not.particle_tag(i)) nphotons_FKS(nFKSprocess)
6843 $ =nphotons_FKS(nFKSprocess)+16867 $ =nphotons_FKS(nFKSprocess)+1
6844 enddo6868 enddo
68456869
68466870
=== modified file 'Template/NLO/SubProcesses/makefile_fks_dir'
--- Template/NLO/SubProcesses/makefile_fks_dir 2020-11-27 13:41:46 +0000
+++ Template/NLO/SubProcesses/makefile_fks_dir 2021-10-15 11:42:16 +0000
@@ -32,6 +32,7 @@
32 $(patsubst %.f,%.o,$(wildcard b_sf_???.f)) \32 $(patsubst %.f,%.o,$(wildcard b_sf_???.f)) \
33 born.o sborn_sf.o extra_cnt_wrapper.o \33 born.o sborn_sf.o extra_cnt_wrapper.o \
34 $(patsubst %.f,%.o,$(wildcard born_cnt_*.f)) \34 $(patsubst %.f,%.o,$(wildcard born_cnt_*.f)) \
35 rescale_alpha_tagged.o \
35 fks_Sij.o $(fastjetfortran_madfks) fks_singular.o \36 fks_Sij.o $(fastjetfortran_madfks) fks_singular.o \
36 montecarlocounter.o reweight_xsec.o boostwdir2.o \37 montecarlocounter.o reweight_xsec.o boostwdir2.o \
37 initcluster.o cluster.o splitorders_stuff.o \38 initcluster.o cluster.o splitorders_stuff.o \
3839
=== modified file 'Template/NLO/SubProcesses/recmom.f'
--- Template/NLO/SubProcesses/recmom.f 2020-09-16 12:55:48 +0000
+++ Template/NLO/SubProcesses/recmom.f 2021-10-15 11:42:16 +0000
@@ -1,12 +1,17 @@
1 subroutine recombine_momenta(R, etaph, reco_l, reco_q, p_in, pdg_in, p_out, pdg_out)1 subroutine recombine_momenta(R, etaph, reco_l, reco_q, p_in,
2 $pdg_in, is_nextph_iso, p_out, pdg_out, is_nextph_iso_reco)
2 implicit none3 implicit none
3 ! recombine photons with the closest fermion if the distance is4 ! recombine photons with the closest fermion if the distance is
4 ! less than R and if the rapidity of photons is < etaph (etaph < 05 ! less than R and if the rapidity of photons is < etaph (etaph < 0
5 ! means no cut). Output a new set of momenta and pdgs corresponding6 ! means no cut). Output a new set of momenta and pdgs corresponding
6 ! to the recombined particles. If recombination occurs the photon7 ! to the recombined particles. If recombination occurs the photon
7 ! disappears from the output particles8 ! disappears from the output particles
9 ! If isolated photons exist (is_nextph_iso(i)=True), they are not
10 ! used for the recombination
8 ! arguments11 ! arguments
9 include 'nexternal.inc'12 include 'nexternal.inc'
13 include 'run.inc'
14 include 'cuts.inc'
10 double precision R, etaph, p_in(0:4,nexternal), p_out(0:4,nexternal)15 double precision R, etaph, p_in(0:4,nexternal), p_out(0:4,nexternal)
11 logical reco_l, reco_q16 logical reco_l, reco_q
12 integer pdg_in(nexternal), pdg_out(nexternal)17 integer pdg_in(nexternal), pdg_out(nexternal)
@@ -17,13 +22,24 @@
17 integer n_ph, i_ph22 integer n_ph, i_ph
18 integer i,j23 integer i,j
19 integer ifreco24 integer ifreco
20 double precision dreco, dthis25 double precision dreco, dthis, iso_getdrv40
21 integer skip26 integer skip
22 logical is_light_charged_fermion27 logical is_light_charged_fermion
23 double precision R2, eta28 logical iso_in(nexternal), iso_out(nexternal)
29 double precision R2_04, eta_04
30 ! use from photon isolation
31 logical is_nextph_iso(nexternal)
32c integer nphiso
33c double precision pgamma_iso(0:3,nexternal)
34c common / photon / is_nextph_iso,nphiso,pgamma_iso
35 ! Save for reco photon isolation
36 logical is_nextph_iso_reco(nexternal)
37c common / photon_reco / is_nextph_iso_reco
24 ! 38 !
25 integer times_reco39 integer times_reco
26 common/to_times_reco/ times_reco40 common/to_times_reco/ times_reco
41 REAL*8 pt,eta
42 external pt,eta
27 ! reset everything43 ! reset everything
28 do j=1,nexternal44 do j=1,nexternal
29 pdg_out(j)=045 pdg_out(j)=0
@@ -46,28 +62,36 @@
46 nq = 062 nq = 0
47 endif63 endif
4864
49 ! count the photons65 ! count the photons that are not isolated
50 n_ph=066 n_ph=0
51 do i=nincoming+1, nexternal67 do i=nincoming+1, nexternal
52 if (pdg_in(i).eq.id_ph.and.68 if (pdg_in(i).eq.id_ph .and. pt(p_in(0,i)).ne.0d0 .and.
53 $ (abs(eta(p_in(0,i))).lt.etaph.or.etaph.lt.0d0)) then69 $ (abs(eta_04(p_in(0,i))).lt.etaph.or.etaph.lt.0d0)
70 $ .and. .not.is_nextph_iso(i) ) then
54 n_ph=n_ph+171 n_ph=n_ph+1
55 i_ph=i72 i_ph=i
56 endif73 endif
57 enddo74 enddo
75
76c Define iso_in as the iso input from photon isolation
77 do i=nincoming+1,nexternal
78 iso_in(i)=is_nextph_iso(i)
79 enddo
80
58 if (n_ph.eq.0 .or. (nl.eq.0 .and. nq.eq.0)) then81 if (n_ph.eq.0 .or. (nl.eq.0 .and. nq.eq.0)) then
59 ! do nothing82 ! do nothing
60 do j=1,nexternal83 do j=1,nexternal
61 pdg_out(j)=pdg_in(j)84 pdg_out(j)=pdg_in(j)
85 iso_out(j)=iso_in(j)
62 do i=0,486 do i=0,4
63 p_out(i,j)=p_in(i,j)87 p_out(i,j)=p_in(i,j)
64 enddo88 enddo
65 enddo89 enddo
66 return
67 elseif (n_ph.eq.1) then90 elseif (n_ph.eq.1) then
68 ! do nothing for initial states91 ! do nothing for initial states
69 do j=1,nincoming92 do j=1,nincoming
70 pdg_out(j)=pdg_in(j)93 pdg_out(j)=pdg_in(j)
94 iso_out(j)=iso_in(j)
71 do i=0,495 do i=0,4
72 p_out(i,j)=p_in(i,j)96 p_out(i,j)=p_in(i,j)
73 enddo97 enddo
@@ -78,7 +102,7 @@
78 if (i_ph.gt.0) then102 if (i_ph.gt.0) then
79 do i = nincoming+1, nexternal103 do i = nincoming+1, nexternal
80 if (is_light_charged_fermion(pdg_in(i),nq,nl)) then104 if (is_light_charged_fermion(pdg_in(i),nq,nl)) then
81 dthis=dsqrt(R2(p_in(0,i_ph),p_in(0,i)))105 dthis=dsqrt(R2_04(p_in(0,i_ph),p_in(0,i)))
82 if (dthis.le.dreco) then106 if (dthis.le.dreco) then
83 dreco=dthis107 dreco=dthis
84 ifreco=i108 ifreco=i
@@ -90,6 +114,7 @@
90 ! do nothing also for final states114 ! do nothing also for final states
91 do j=nincoming+1,nexternal115 do j=nincoming+1,nexternal
92 pdg_out(j)=pdg_in(j)116 pdg_out(j)=pdg_in(j)
117 iso_out(j)=iso_in(j)
93 do i=0,4118 do i=0,4
94 p_out(i,j)=p_in(i,j)119 p_out(i,j)=p_in(i,j)
95 enddo120 enddo
@@ -100,11 +125,13 @@
100 do j=nincoming+1,nexternal125 do j=nincoming+1,nexternal
101 if (j.ne.i_ph.and.j.ne.ifreco) then126 if (j.ne.i_ph.and.j.ne.ifreco) then
102 pdg_out(j-skip)=pdg_in(j)127 pdg_out(j-skip)=pdg_in(j)
128 iso_out(j-skip)=iso_in(j)
103 do i=0,4129 do i=0,4
104 p_out(i,j-skip)=p_in(i,j)130 p_out(i,j-skip)=p_in(i,j)
105 enddo131 enddo
106 elseif (j.eq.ifreco) then132 elseif (j.eq.ifreco) then
107 pdg_out(j-skip)=pdg_in(j)133 pdg_out(j-skip)=pdg_in(j)
134 iso_out(j-skip)=iso_in(j)
108 do i=0,3135 do i=0,3
109 p_out(i,j-skip)=p_in(i,j)+p_in(i,i_ph)136 p_out(i,j-skip)=p_in(i,j)+p_in(i,i_ph)
110 enddo137 enddo
@@ -119,6 +146,35 @@
119 stop 1146 stop 1
120 endif147 endif
121148
149 do i=nincoming+1,nexternal
150 is_nextph_iso_reco(i)=iso_out(i)
151 enddo
152
153 return
154 end
155
156
157
158
159
160 subroutine recombine_momenta_notagph(R, etaph, reco_l, reco_q, p_in, pdg_in, p_out, pdg_out)
161 implicit none
162 ! wraps recombine_momenta, it provides a function interface
163 ! for the case where no tagged photon exist
164 ! (mostly for backward complatibility)
165 ! arguments
166 include 'nexternal.inc'
167 double precision R, etaph, p_in(0:4,nexternal), p_out(0:4,nexternal)
168 logical reco_l, reco_q
169 integer pdg_in(nexternal), pdg_out(nexternal)
170
171 logical is_iso_photon_in(nexternal), is_iso_photon_out(nexternal)
172
173 is_iso_photon_in(:) = .false.
174
175 call recombine_momenta(R, etaph, reco_l, reco_q, p_in,
176 $pdg_in, is_iso_photon_in, p_out, pdg_out, is_iso_photon_out)
177
122 return 178 return
123 end179 end
124180
125181
=== modified file 'UpdateNotes.txt'
--- UpdateNotes.txt 2021-09-08 08:59:52 +0000
+++ UpdateNotes.txt 2021-10-15 11:42:16 +0000
@@ -1,6 +1,7 @@
1Update notes for MadGraph5_aMC@NLO (in reverse time order)1Update notes for MadGraph5_aMC@NLO (in reverse time order)
22
33.1.2 (??/??/??)33.2.1 (XX/XX/21)
4 DP+HS+IT+MZ: EW corrections can be computed for tagged photons
4 MZ+CS: Fixes relevant to PineAPPL: 5 MZ+CS: Fixes relevant to PineAPPL:
5 - minor fix on the gluon pdg code in pineappl_interface.cc6 - minor fix on the gluon pdg code in pineappl_interface.cc
6 - the integration channels are threated the same way with or without PineAPPL 7 - the integration channels are threated the same way with or without PineAPPL
78
=== modified file 'madgraph/core/diagram_generation.py'
--- madgraph/core/diagram_generation.py 2021-07-21 19:09:13 +0000
+++ madgraph/core/diagram_generation.py 2021-10-15 11:42:16 +0000
@@ -30,6 +30,7 @@
3030
31import madgraph.core.base_objects as base_objects31import madgraph.core.base_objects as base_objects
32import madgraph.various.misc as misc32import madgraph.various.misc as misc
33import madgraph.fks.fks_tag as fks_tag
33from madgraph import InvalidCmd, MadGraph5Error34from madgraph import InvalidCmd, MadGraph5Error
34from six.moves import range35from six.moves import range
35from six.moves import zip36from six.moves import zip
@@ -1713,6 +1714,15 @@
1713 if leg['state'] == True]1714 if leg['state'] == True]
1714 polids = [tuple(leg['polarization']) for leg in process_definition['legs'] \1715 polids = [tuple(leg['polarization']) for leg in process_definition['legs'] \
1715 if leg['state'] == True]1716 if leg['state'] == True]
1717
1718 # keep track of the 'is_tagged' property of the legs if needed
1719 try:
1720 fstags = [leg['is_tagged'] for leg in process_definition['legs'] \
1721 if 'is_tagged' in leg.keys() and leg['state'] == True]
1722
1723 except KeyError:
1724 fstags = []
1725
1716 # Generate all combinations for the initial state1726 # Generate all combinations for the initial state
1717 for prod in itertools.product(*isids):1727 for prod in itertools.product(*isids):
1718 islegs = [\1728 islegs = [\
@@ -1735,10 +1745,16 @@
1735 red_fsidlist.add(tuple(tag))1745 red_fsidlist.add(tuple(tag))
1736 # Generate leg list for process1746 # Generate leg list for process
1737 leg_list = [copy.copy(leg) for leg in islegs]1747 leg_list = [copy.copy(leg) for leg in islegs]
1738 leg_list.extend([\
1739 base_objects.Leg({'id':id, 'state': True, 'polarization': fslegs[i]['polarization']}) \
1740 for i,id in enumerate(prod)])
1741 1748
1749 if not fstags:
1750 leg_list.extend([\
1751 base_objects.Leg({'id':id, 'state': True, 'polarization': fsleg['polarization']}) \
1752 for id, fsleg in zip(prod, fslegs)])
1753 else:
1754 leg_list.extend([\
1755 fks_tag.TagLeg({'id':id, 'state': True, 'polarization': fsleg['polarization'], 'is_tagged': tag}) \
1756 for id, fsleg, tag in zip(prod, fslegs, fstags)])
1757
1742 legs = base_objects.LegList(leg_list)1758 legs = base_objects.LegList(leg_list)
17431759
1744 # Check for crossed processes1760 # Check for crossed processes
17451761
=== modified file 'madgraph/fks/fks_base.py'
--- madgraph/fks/fks_base.py 2021-05-23 14:17:24 +0000
+++ madgraph/fks/fks_base.py 2021-10-15 11:42:16 +0000
@@ -416,6 +416,7 @@
416 legs = [(leg.get('id'), leg) for leg in leglist]416 legs = [(leg.get('id'), leg) for leg in leglist]
417 self.pdgs = array.array('i',[s[0] for s in legs])417 self.pdgs = array.array('i',[s[0] for s in legs])
418 self.colors = [leg['color'] for leg in leglist]418 self.colors = [leg['color'] for leg in leglist]
419 self.particle_tags = [leg['is_tagged'] for leg in leglist]
419 if not self.process['perturbation_couplings'] == ['QCD']:420 if not self.process['perturbation_couplings'] == ['QCD']:
420 self.charges = [leg['charge'] for leg in leglist]421 self.charges = [leg['charge'] for leg in leglist]
421 else:422 else:
@@ -529,6 +530,13 @@
529 leg in self.born_amp['process']['legs']] 530 leg in self.born_amp['process']['legs']]
530531
531532
533 def get_is_tagged(self):
534 """return the list of the 'is_tagged' keys
535 of each leg in born_amp"""
536 return [leg.get('is_tagged') for \
537 leg in self.born_amp['process']['legs']]
538
539
532 def get_leglist(self):540 def get_leglist(self):
533 """return the leg list541 """return the leg list
534 for the born amp"""542 for the born amp"""
535543
=== modified file 'madgraph/fks/fks_common.py'
--- madgraph/fks/fks_common.py 2021-03-16 15:13:03 +0000
+++ madgraph/fks/fks_common.py 2021-10-15 11:42:16 +0000
@@ -263,7 +263,6 @@
263 if dict == {}:263 if dict == {}:
264 dict = find_pert_particles_interactions(model, pert)264 dict = find_pert_particles_interactions(model, pert)
265 splittings = []265 splittings = []
266#check that the leg is a qcd leg
267266
268 if leg.get('id') in dict['pert_particles']:267 if leg.get('id') in dict['pert_particles']:
269 part = model.get('particle_dict')[leg.get('id')]268 part = model.get('particle_dict')[leg.get('id')]
@@ -284,6 +283,13 @@
284 nsoft += 1283 nsoft += 1
285 if nsoft >= 1:284 if nsoft >= 1:
286 for split in split_leg(leg, parts, model):285 for split in split_leg(leg, parts, model):
286 # check if the leg is tagged, that
287 # the same particles appear also in the two daughters
288 if 'is_tagged' in leg.keys() and leg['is_tagged'] and \
289 leg['id'] != split[0]['id'] and \
290 leg['id'] != split[1]['id']:
291 continue
292
287 # add the splitting, but check if there is 293 # add the splitting, but check if there is
288 # an initial-state lepton if the flag294 # an initial-state lepton if the flag
289 # include_init_leptons is False295 # include_init_leptons is False
@@ -833,6 +839,7 @@
833 -'charge', which gives the charge of the leg839 -'charge', which gives the charge of the leg
834 -'massless', boolean, true if leg is massless840 -'massless', boolean, true if leg is massless
835 -'spin' which gives the spin of leg841 -'spin' which gives the spin of leg
842 -'is_tagged', boolean, true if leg is tagged in the final state
836 -'is_part', boolean, true if leg is an particle843 -'is_part', boolean, true if leg is an particle
837 -'self_antipart', boolean, true if leg is an self-conjugated particle844 -'self_antipart', boolean, true if leg is an self-conjugated particle
838 """845 """
@@ -846,13 +853,14 @@
846 self['charge'] = 0.853 self['charge'] = 0.
847 self['massless'] = True854 self['massless'] = True
848 self['spin'] = 0855 self['spin'] = 0
856 self['is_tagged'] = False
849 self['is_part'] = True857 self['is_part'] = True
850 self['self_antipart'] = False858 self['self_antipart'] = False
851 859
852 def get_sorted_keys(self):860 def get_sorted_keys(self):
853 """Return particle property names as a nicely sorted list."""861 """Return particle property names as a nicely sorted list."""
854 keys = super(FKSLeg, self).get_sorted_keys()862 keys = super(FKSLeg, self).get_sorted_keys()
855 keys += ['fks', 'color','charge', 'massless', 'spin','is_part','self_antipart']863 keys += ['fks', 'color','charge', 'massless', 'spin','is_tagged','is_part','self_antipart',]
856 return keys864 return keys
857865
858 866
@@ -868,7 +876,7 @@
868 six.reraise(self.PhysicsObjectError, "%s is not a valid leg %s flag" % \876 six.reraise(self.PhysicsObjectError, "%s is not a valid leg %s flag" % \
869 str(value), name)877 str(value), name)
870 878
871 if name in ['massless','self_antipart','is_part']:879 if name in ['massless','is_tagged','self_antipart','is_part']:
872 if not isinstance(value, bool):880 if not isinstance(value, bool):
873 six.reraise(self.PhysicsObjectError, "%s is not a valid boolean for leg flag %s" % \881 six.reraise(self.PhysicsObjectError, "%s is not a valid boolean for leg flag %s" % \
874 str(value), name)882 str(value), name)
@@ -879,3 +887,4 @@
879 return super(FKSLeg,self).filter(name, value)887 return super(FKSLeg,self).filter(name, value)
880 888
881 889
890
882891
=== modified file 'madgraph/fks/fks_helas_objects.py'
--- madgraph/fks/fks_helas_objects.py 2021-02-08 22:58:11 +0000
+++ madgraph/fks/fks_helas_objects.py 2021-10-15 11:42:16 +0000
@@ -901,6 +901,7 @@
901 contains:901 contains:
902 -- colors902 -- colors
903 -- charges903 -- charges
904 -- particle_tags
904 -- i/j/ij fks, ij refers to the born leglist905 -- i/j/ij fks, ij refers to the born leglist
905 -- ijglu906 -- ijglu
906 -- need_color_links907 -- need_color_links
@@ -919,6 +920,7 @@
919 if fksrealproc != None:920 if fksrealproc != None:
920 self.isfinite = False921 self.isfinite = False
921 self.colors = fksrealproc.colors922 self.colors = fksrealproc.colors
923 self.particle_tags = fksrealproc.particle_tags
922 self.charges = fksrealproc.charges924 self.charges = fksrealproc.charges
923 self.fks_infos = fksrealproc.fks_infos925 self.fks_infos = fksrealproc.fks_infos
924 self.is_to_integrate = fksrealproc.is_to_integrate926 self.is_to_integrate = fksrealproc.is_to_integrate
925927
=== added file 'madgraph/fks/fks_tag.py'
--- madgraph/fks/fks_tag.py 1970-01-01 00:00:00 +0000
+++ madgraph/fks/fks_tag.py 2021-10-15 11:42:16 +0000
@@ -0,0 +1,75 @@
1################################################################################
2#
3# Copyright (c) 2009 The MadGraph5_aMC@NLO Development team and Contributors
4#
5# This file is a part of the MadGraph5_aMC@NLO project, an application which
6# automatically generates Feynman diagrams and matrix elements for arbitrary
7# high-energy processes in the Standard Model and beyond.
8#
9# It is subject to the MadGraph5_aMC@NLO license which should accompany this
10# distribution.
11#
12# For more information, visit madgraph.phys.ucl.ac.be and amcatnlo.web.cern.ch
13#
14################################################################################
15
16"""Definitions of the objects needed both for MadFKS with tagged particles"""
17
18import madgraph.core.base_objects as MG
19
20
21class MultiTagLeg(MG.MultiLeg):
22 """a daughter class of MultiLeg, with the extra possibility of specifying
23 whether a given leg is tagged or not, via the "is_tagged" key
24 """
25
26 def default_setup(self):
27 """Default values for all properties"""
28 super(MultiTagLeg, self).default_setup()
29 self['is_tagged'] = False
30
31 def get_sorted_keys(self):
32 """Return particle property names as a nicely sorted list."""
33 keys = super(MultiTagLeg, self).get_sorted_keys()
34 keys += ['is_tagged']
35 return keys
36
37
38 def filter(self, name, value):
39 """Filter for valid leg property values."""
40
41 if name == 'is_tagged':
42 if not isinstance(value, bool):
43 raise self.PhysicsObjectError( \
44 "%s is not a valid string for leg 'is_tagged' flag" \
45 % str(value))
46 return super(MultiTagLeg,self).filter(name, value)
47
48
49
50class TagLeg(MG.Leg):
51 """a daughter class of Leg, with the extra possibility of specifying
52 whether a given leg is tagged or not, via the "is_tagged" key
53 """
54
55 def default_setup(self):
56 """Default values for all properties"""
57 super(TagLeg, self).default_setup()
58 self['is_tagged'] = False
59
60 def get_sorted_keys(self):
61 """Return particle property names as a nicely sorted list."""
62 keys = super(TagLeg, self).get_sorted_keys()
63 keys += ['is_tagged']
64 return keys
65
66
67 def filter(self, name, value):
68 """Filter for valid leg property values."""
69
70 if name == 'is_tagged':
71 if not isinstance(value, bool):
72 raise self.PhysicsObjectError( \
73 "%s is not a valid string for leg 'is_tagged' flag" \
74 % str(value))
75 return super(TagLeg,self).filter(name, value)
076
=== modified file 'madgraph/interface/madgraph_interface.py'
--- madgraph/interface/madgraph_interface.py 2021-08-20 21:40:18 +0000
+++ madgraph/interface/madgraph_interface.py 2021-10-15 11:42:16 +0000
@@ -93,6 +93,8 @@
93import madgraph.various.misc as misc93import madgraph.various.misc as misc
94import madgraph.various.cluster as cluster94import madgraph.various.cluster as cluster
9595
96import madgraph.fks.fks_tag as fks_tag
97
96import models as ufomodels98import models as ufomodels
97import models.import_ufo as import_ufo99import models.import_ufo as import_ufo
98import models.write_param_card as param_writer100import models.write_param_card as param_writer
@@ -4927,6 +4929,21 @@
4927 state = True4929 state = True
4928 continue4930 continue
49294931
4932 # check if the particle is tagged (!PART!)
4933 if part_name.startswith('!') and part_name.endswith('!'):
4934 part_name = part_name[1:-1]
4935 is_tagged = True
4936 elif part_name.endswith('!') and part_name.count('!') == 2 and part_name[:part_name.find('!')].isdigit():
4937 part_name = part_name.replace('!','')
4938 is_tagged = True
4939# misc.sprint(part_name)
4940 else:
4941 is_tagged = False
4942
4943 # check that only final-state particles are tagged
4944 if is_tagged and not state:
4945 raise self.InvalidCmd("initial particles cannot be tagged")
4946
4930 mylegids = []4947 mylegids = []
4931 polarization = []4948 polarization = []
4932 if '{' in part_name:4949 if '{' in part_name:
@@ -5006,6 +5023,9 @@
50065023
5007 duplicate =15024 duplicate =1
5008 if part_name in self._multiparticles:5025 if part_name in self._multiparticles:
5026 # multiparticles cannot be tagged
5027 if is_tagged:
5028 raise self.InvalidCmd("Multiparticles cannot be tagged")
5009 if isinstance(self._multiparticles[part_name][0], list):5029 if isinstance(self._multiparticles[part_name][0], list):
5010 raise self.InvalidCmd("Multiparticle %s is or-multiparticle" % part_name + \5030 raise self.InvalidCmd("Multiparticle %s is or-multiparticle" % part_name + \
5011 " which can be used only for required s-channels")5031 " which can be used only for required s-channels")
@@ -5036,12 +5056,26 @@
50365056
5037 if mylegids:5057 if mylegids:
5038 for _ in range(duplicate):5058 for _ in range(duplicate):
5039 myleglist.append(base_objects.MultiLeg({'ids':mylegids,5059 if LoopOption in ['virt','sqrvirt','tree','noborn']:
5040 'state':state,5060 # check that no tagged particles exist in this mode
5041 'polarization': polarization}))5061 if is_tagged:
5062 raise self.InvalidCmd(
5063 "%s mode does not handle tagged particles" % LoopOption)
5064
5065 myleglist.append(base_objects.MultiLeg({'ids':mylegids,
5066 'state':state,
5067 'polarization': polarization}))
5068 else:
5069 myleglist.append(fks_tag.MultiTagLeg({'ids':mylegids,
5070 'state':state,
5071 'polarization': polarization,
5072 'is_tagged':is_tagged}))
5042 else:5073 else:
5043 raise self.InvalidCmd("No particle %s in model" % part_name)5074 raise self.InvalidCmd("No particle %s in model" % part_name)
50445075
5076 if any(['is_tagged' in l.keys() and l['is_tagged'] for l in myleglist]):
5077 logger.warning('The process involves tagged particles. Please consider citing arXiv:2106.02059 if relevant.')
5078
5045 # Apply the keyword 'all' for perturbed coupling orders.5079 # Apply the keyword 'all' for perturbed coupling orders.
5046 if perturbation_couplings.lower() in ['all', 'loonly']:5080 if perturbation_couplings.lower() in ['all', 'loonly']:
5047 if perturbation_couplings.lower() in ['loonly']:5081 if perturbation_couplings.lower() in ['loonly']:
50485082
=== modified file 'madgraph/iolibs/export_fks.py'
--- madgraph/iolibs/export_fks.py 2021-07-21 19:12:36 +0000
+++ madgraph/iolibs/export_fks.py 2021-10-15 11:42:16 +0000
@@ -627,6 +627,16 @@
627 writers.FortranWriter(filename),627 writers.FortranWriter(filename),
628 matrix_element)628 matrix_element)
629629
630 filename = 'a0Gmuconv.inc'
631 startfroma0 = self.write_a0gmuconv_file(
632 writers.FortranWriter(filename),
633 matrix_element)
634
635 filename = 'rescale_alpha_tagged.f'
636 self.write_rescale_a0gmu_file(
637 writers.FortranWriter(filename),
638 startfroma0, matrix_element)
639
630 filename = 'orders.h'640 filename = 'orders.h'
631 self.write_orders_c_header_file(641 self.write_orders_c_header_file(
632 writers.CPPWriter(filename),642 writers.CPPWriter(filename),
@@ -1096,6 +1106,23 @@
1096 writer.writelines(text)1106 writer.writelines(text)
10971107
10981108
1109 def write_a0gmuconv_file(self, writer, matrix_element):
1110 """writes an include file with the informations about the
1111 alpha0 < > gmu conversion, to be used when the process has
1112 tagged photons
1113 """
1114
1115 bool_dict = {True: '.true.', False: '.false.'}
1116 bornproc = matrix_element.born_me['processes'][0]
1117 startfromalpha0 = False
1118 if any([l['is_tagged'] and l['id'] == 22 for l in bornproc['legs']]):
1119 if 'loop_qcd_qed_sm_a0' in bornproc['model'].get('modelpath'):
1120 startfromalpha0 = True
1121
1122 text = 'logical startfroma0\nparameter (startfroma0=%s)\n' % bool_dict[startfromalpha0]
1123 writer.writelines(text)
1124 return startfromalpha0
1125
1099 def write_orders_c_header_file(self, writer, amp_split_size, amp_split_size_born):1126 def write_orders_c_header_file(self, writer, amp_split_size, amp_split_size_born):
1100 """writes the header file including the amp_split_size declaration for amcblast1127 """writes the header file including the amp_split_size declaration for amcblast
1101 """1128 """
@@ -1105,6 +1132,57 @@
1105 writer.writelines(text)1132 writer.writelines(text)
11061133
11071134
1135 def write_rescale_a0gmu_file(self, writer, startfroma0, matrix_element):
1136 """writes the function that computes the rescaling factor needed in
1137 the case of external photons
1138 """
1139
1140 # get the model parameters
1141 params = sum([v for v in self.model.get('parameters').values()], [])
1142 parnames = [p.name.lower() for p in params]
1143
1144 bornproc = matrix_element.born_me['processes'][0]
1145 # this is to ensure compatibility with standard processes
1146 if not any([l['is_tagged'] and l['id'] == 22 for l in bornproc['legs']]):
1147 to_check = []
1148 expr = '1d0'
1149 conv_pol = '0d0'
1150 conv_fin = '0d0'
1151
1152 elif startfroma0:
1153 to_check = ['mdl_aewgmu', 'mdl_aew']
1154 base = 'mdl_aewgmu/mdl_aew'
1155 exp = 'qed_pow/2d0-ntag'
1156 expr = '(%s)**(%s)' % (base, exp)
1157 conv_fin = '(qed_pow - ntagph * 2d0) * MDL_ECOUP_DGMUA0_UV_EW_FIN_ * born_wgt'
1158 conv_pol = '(qed_pow - ntagph * 2d0) * MDL_ECOUP_DGMUA0_UV_EW_1EPS_ * born_wgt'
1159 else:
1160 to_check = ['mdl_aew', 'mdl_aew0']
1161 base = 'mdl_aew0/mdl_aew'
1162 exp = 'ntag'
1163 expr = '(%s)**(%s)' % (base, exp)
1164 conv_fin = '- ntagph * 2d0 * MDL_ECOUP_DGMUA0_UV_EW_FIN_ * born_wgt'
1165 conv_pol = '- ntagph * 2d0 * MDL_ECOUP_DGMUA0_UV_EW_1EPS_ * born_wgt'
1166
1167 replace_dict = {'rescale_fact': expr,
1168 'virtual_a0Gmu_conv_finite': conv_fin,
1169 'virtual_a0Gmu_conv_pole': conv_pol}
1170
1171 if not all(p in parnames for p in to_check):
1172 raise fks_common.FKSProcessError(
1173 'Some parameters needed when there are tagged '+\
1174 'photons cannot be found in the model.\n' +\
1175 'Please load the correct model and restriction ' +\
1176 '(e.g loop_qcd_qed_sm_Gmu-a0 or loop_qcd_qed_sm_a0-Gmu)')
1177
1178 file = open(os.path.join(_file_path, \
1179 'iolibs/template_files/rescale_alpha_tagged.inc')).read()
1180 file = file % replace_dict
1181
1182 # Write the file
1183 writer.writelines(file)
1184
1185
11081186
1109 def write_orders_file(self, writer, matrix_element):1187 def write_orders_file(self, writer, matrix_element):
1110 """writes the include file with the informations about coupling orders.1188 """writes the include file with the informations about coupling orders.
@@ -2857,6 +2935,7 @@
2857 col_lines = []2935 col_lines = []
2858 pdg_lines = []2936 pdg_lines = []
2859 charge_lines = []2937 charge_lines = []
2938 tag_lines = []
2860 fks_j_from_i_lines = []2939 fks_j_from_i_lines = []
2861 split_type_lines = []2940 split_type_lines = []
2862 for i, info in enumerate(fks_info_list):2941 for i, info in enumerate(fks_info_list):
@@ -2870,6 +2949,9 @@
2870 'DATA (PARTICLE_CHARGE_D(%d, IPOS), IPOS=1, NEXTERNAL) / %s /'\2949 'DATA (PARTICLE_CHARGE_D(%d, IPOS), IPOS=1, NEXTERNAL) / %s /'\
2871 % (i + 1, ', '.join('%19.15fd0' % charg\2950 % (i + 1, ', '.join('%19.15fd0' % charg\
2872 for charg in fksborn.real_processes[info['n_me']-1].charges) ))2951 for charg in fksborn.real_processes[info['n_me']-1].charges) ))
2952 tag_lines.append( \
2953 'DATA (PARTICLE_TAG_D(%d, IPOS), IPOS=1, NEXTERNAL) / %s /' \
2954 % (i + 1, ', '.join(bool_dict[tag] for tag in fksborn.real_processes[info['n_me']-1].particle_tags) ))
2873 fks_j_from_i_lines.extend(self.get_fks_j_from_i_lines(fksborn.real_processes[info['n_me']-1],\2955 fks_j_from_i_lines.extend(self.get_fks_j_from_i_lines(fksborn.real_processes[info['n_me']-1],\
2874 i + 1))2956 i + 1))
2875 split_type_lines.append( \2957 split_type_lines.append( \
@@ -2884,6 +2966,7 @@
2884 pdgs = [l.get('id') for l in bornproc.get('legs')] + [-21]2966 pdgs = [l.get('id') for l in bornproc.get('legs')] + [-21]
2885 colors = [l.get('color') for l in bornproc.get('legs')] + [8]2967 colors = [l.get('color') for l in bornproc.get('legs')] + [8]
2886 charges = [l.get('charge') for l in bornproc.get('legs')] + [0.]2968 charges = [l.get('charge') for l in bornproc.get('legs')] + [0.]
2969 tags = [l.get('is_tagged') for l in bornproc.get('legs')] + [False]
28872970
2888 fks_i = len(colors)2971 fks_i = len(colors)
2889 # fist look for a colored legs (set j to 1 otherwise)2972 # fist look for a colored legs (set j to 1 otherwise)
@@ -2919,6 +3002,8 @@
2919 % ', '.join([str(pdg) for pdg in pdgs])]3002 % ', '.join([str(pdg) for pdg in pdgs])]
2920 charge_lines = ['DATA (PARTICLE_CHARGE_D(1, IPOS), IPOS=1, NEXTERNAL) / %s /' \3003 charge_lines = ['DATA (PARTICLE_CHARGE_D(1, IPOS), IPOS=1, NEXTERNAL) / %s /' \
2921 % ', '.join('%19.15fd0' % charg for charg in charges)]3004 % ', '.join('%19.15fd0' % charg for charg in charges)]
3005 tag_lines = ['DATA (PARTICLE_TAG_D(1, IPOS), IPOS=1, NEXTERNAL) / %s /' \
3006 % ', '.join(bool_dict[tag] for tag in tags)]
2922 fks_j_from_i_lines = ['DATA (FKS_J_FROM_I_D(1, %d, JPOS), JPOS = 0, 1) / 1, %d /' \3007 fks_j_from_i_lines = ['DATA (FKS_J_FROM_I_D(1, %d, JPOS), JPOS = 0, 1) / 1, %d /' \
2923 % (fks_i, fks_j)]3008 % (fks_i, fks_j)]
2924 split_type_lines = [ \3009 split_type_lines = [ \
@@ -2930,6 +3015,7 @@
2930 replace_dict['col_lines'] = '\n'.join(col_lines)3015 replace_dict['col_lines'] = '\n'.join(col_lines)
2931 replace_dict['pdg_lines'] = '\n'.join(pdg_lines)3016 replace_dict['pdg_lines'] = '\n'.join(pdg_lines)
2932 replace_dict['charge_lines'] = '\n'.join(charge_lines)3017 replace_dict['charge_lines'] = '\n'.join(charge_lines)
3018 replace_dict['tag_lines'] = '\n'.join(tag_lines)
2933 replace_dict['fks_j_from_i_lines'] = '\n'.join(fks_j_from_i_lines)3019 replace_dict['fks_j_from_i_lines'] = '\n'.join(fks_j_from_i_lines)
2934 replace_dict['split_type_lines'] = '\n'.join(split_type_lines)3020 replace_dict['split_type_lines'] = '\n'.join(split_type_lines)
29353021
29363022
=== modified file 'madgraph/iolibs/template_files/fks_info.inc'
--- madgraph/iolibs/template_files/fks_info.inc 2014-09-19 17:34:43 +0000
+++ madgraph/iolibs/template_files/fks_info.inc 2021-10-15 11:42:16 +0000
@@ -3,6 +3,7 @@
3 INTEGER EXTRA_CNT_D(%(nconfs)d), ISPLITORDER_BORN_D(%(nconfs)d), ISPLITORDER_CNT_D(%(nconfs)d)3 INTEGER EXTRA_CNT_D(%(nconfs)d), ISPLITORDER_BORN_D(%(nconfs)d), ISPLITORDER_CNT_D(%(nconfs)d)
4 INTEGER FKS_J_FROM_I_D(%(nconfs)d, NEXTERNAL, 0:NEXTERNAL)4 INTEGER FKS_J_FROM_I_D(%(nconfs)d, NEXTERNAL, 0:NEXTERNAL)
5 INTEGER PARTICLE_TYPE_D(%(nconfs)d, NEXTERNAL), PDG_TYPE_D(%(nconfs)d, NEXTERNAL)5 INTEGER PARTICLE_TYPE_D(%(nconfs)d, NEXTERNAL), PDG_TYPE_D(%(nconfs)d, NEXTERNAL)
6 LOGICAL PARTICLE_TAG_D(%(nconfs)d, NEXTERNAL)
6 REAL*8 PARTICLE_CHARGE_D(%(nconfs)d, NEXTERNAL)7 REAL*8 PARTICLE_CHARGE_D(%(nconfs)d, NEXTERNAL)
7 LOGICAL SPLIT_TYPE_D(%(nconfs)d, %(nsplitorders)d)8 LOGICAL SPLIT_TYPE_D(%(nconfs)d, %(nsplitorders)d)
8 LOGICAL NEED_COLOR_LINKS_D(%(nconfs)d), NEED_CHARGE_LINKS_D(%(nconfs)d)9 LOGICAL NEED_COLOR_LINKS_D(%(nconfs)d), NEED_CHARGE_LINKS_D(%(nconfs)d)
@@ -40,3 +41,9 @@
40C Particle charge:41C Particle charge:
41C charge is set 0. with QCD corrections, which is irrelevant42C charge is set 0. with QCD corrections, which is irrelevant
42%(charge_lines)s43%(charge_lines)s
44
45C
46C Tagged particles:
47C
48%(tag_lines)s
49
4350
=== added file 'madgraph/iolibs/template_files/rescale_alpha_tagged.inc'
--- madgraph/iolibs/template_files/rescale_alpha_tagged.inc 1970-01-01 00:00:00 +0000
+++ madgraph/iolibs/template_files/rescale_alpha_tagged.inc 2021-10-15 11:42:16 +0000
@@ -0,0 +1,40 @@
1double precision function get_rescale_alpha_factor(ntag,qed_pow)
2C returns the power of ratios of alpha needed to compensate
3C for the presence of external tagged photons
4C It is automatically written, and it detects whether the
5C starting model is in the Gmu or alpha0 scheme.
6C ntag is the number of tagged photons, qed_pow the power of gweak
7C of the contribution considered
8implicit none
9integer ntag, qed_pow
10INCLUDE '../../Source/MODEL/input.inc'
11
12get_rescale_alpha_factor = 1d0
13if (ntag.eq.0) return
14
15get_rescale_alpha_factor = %(rescale_fact)s
16
17return
18end
19
20
21double precision function get_virtual_a0Gmu_conv(qed_pow, ntagph, ivirt, born_wgt)
22C returns the piece to compensate the a0<>Gmu change of scheme for the
23C virtuals (single pole if ivirt = 1, finite if ivirt = 0
24implicit none
25integer qed_pow, ntagph, ivirt
26double precision born_wgt
27INCLUDE '../../Source/MODEL/input.inc'
28
29if (ivirt.eq.1) then
30! single
31get_virtual_a0Gmu_conv = %(virtual_a0Gmu_conv_pole)s
32else if (ivirt.eq.0) then
33! finite part
34get_virtual_a0Gmu_conv = %(virtual_a0Gmu_conv_finite)s
35else
36write(*,*) 'Error get_virtual_a0Gmu_conv: Invalid ivirt', ivirt
37endif
38
39return
40end
041
=== modified file 'madgraph/various/banner.py'
--- madgraph/various/banner.py 2021-10-14 15:00:59 +0000
+++ madgraph/various/banner.py 2021-10-15 11:42:16 +0000
@@ -4528,6 +4528,7 @@
4528 """Rules4528 """Rules
4529 e+ e- beam -> lpp:0 ebeam:500 4529 e+ e- beam -> lpp:0 ebeam:500
4530 p p beam -> set maxjetflavor automatically4530 p p beam -> set maxjetflavor automatically
4531 process with tagged photons -> gamma_is_j = false
4531 """4532 """
45324533
4533 # check for beam_id4534 # check for beam_id
@@ -4552,13 +4553,23 @@
4552 if proc_characteristic['ninitial'] == 1:4553 if proc_characteristic['ninitial'] == 1:
4553 #remove all cut4554 #remove all cut
4554 self.remove_all_cut()4555 self.remove_all_cut()
4556
4557 # check for tagged photons
4558 tagged_particles = set()
4555 4559
4556 # Check if need matching4560 # Check if need matching
4557 min_particle = 994561 min_particle = 99
4558 max_particle = 04562 max_particle = 0
4559 for proc in proc_def:4563 for proc in proc_def:
4564 for leg in proc['legs']:
4565 if leg['is_tagged']:
4566 tagged_particles.add(leg['id'])
4560 min_particle = min(len(proc['legs']), min_particle)4567 min_particle = min(len(proc['legs']), min_particle)
4561 max_particle = max(len(proc['legs']), max_particle)4568 max_particle = max(len(proc['legs']), max_particle)
4569
4570 if 22 in tagged_particles:
4571 self['gamma_is_j'] = False
4572
4562 matching = False4573 matching = False
4563 if min_particle != max_particle:4574 if min_particle != max_particle:
4564 #take one of the process with min_particle4575 #take one of the process with min_particle
45654576
=== modified file 'tests/acceptance_tests/test_cmd_amcatnlo.py'
--- tests/acceptance_tests/test_cmd_amcatnlo.py 2020-11-27 13:41:46 +0000
+++ tests/acceptance_tests/test_cmd_amcatnlo.py 2021-10-15 11:42:16 +0000
@@ -700,3 +700,38 @@
700 700
701 result = save_load_object.load_from_file('%s/HTML/results.pkl' % self.path)701 result = save_load_object.load_from_file('%s/HTML/results.pkl' % self.path)
702 return result[run_name]702 return result[run_name]
703
704
705 def test_generate_taggedph_nloew(self):
706 """test the param_card created is correct"""
707
708
709 text = """
710 import model loop_qcd_qed_sm_Gmu-a0
711 generate u u~ > !a! !a! [QED]
712 output %s
713 launch NLO
714 set lepphreco False
715 set quarkphreco False
716 """ % (self.path)
717
718 interface = MGCmd.MasterCmd()
719 interface.no_notification()
720
721 open(pjoin(self.tmpdir,'cmd'),'w').write(text)
722
723
724 os.system('rm -rf %s/RunWeb' % self.path)
725 os.system('rm -rf %s/Events/run_*' % self.path)
726
727 interface.exec_cmd('import command %s' % pjoin(self.tmpdir, 'cmd'))
728 # test the lhe event file exists
729 self.assertTrue(os.path.exists('%s/Events/run_01/summary.txt' % self.path))
730 self.assertTrue(os.path.exists('%s/Events/run_01/run_01_tag_1_banner.txt' % self.path))
731 self.assertTrue(os.path.exists('%s/Events/run_01/res_0.txt' % self.path))
732 self.assertTrue(os.path.exists('%s/Events/run_01/res_1.txt' % self.path))
733 self.assertTrue(os.path.exists('%s/Events/run_01/alllogs_0.html' % self.path))
734 self.assertTrue(os.path.exists('%s/Events/run_01/alllogs_1.html' % self.path))
735
736 check_html_page(self, pjoin(self.path, 'crossx.html'))
737 check_html_page(self, pjoin(self.path, 'HTML', 'run_01', 'results.html'))
703738
=== added file 'tests/unit_tests/fks/test_fks_taggedphotons.py'
--- tests/unit_tests/fks/test_fks_taggedphotons.py 1970-01-01 00:00:00 +0000
+++ tests/unit_tests/fks/test_fks_taggedphotons.py 2021-10-15 11:42:16 +0000
@@ -0,0 +1,80 @@
1##############################################################################
2#
3# Copyright (c) 2010 The MadGraph5_aMC@NLO Development team and Contributors
4#
5# This file is a part of the MadGraph5_aMC@NLO project, an application which
6# automatically generates Feynman diagrams and matrix elements for arbitrary
7# high-energy processes in the Standard Model and beyond.
8#
9# It is subject to the MadGraph5_aMC@NLO license which should accompany this
10# distribution.
11#
12# For more information, visit madgraph.phys.ucl.ac.be and amcatnlo.web.cern.ch
13#
14################################################################################
15from __future__ import absolute_import
16from __future__ import print_function
17from cmd import Cmd
18from six.moves import zip
19""" Basic test of the command interface """
20
21import unittest
22import madgraph
23import madgraph.interface.master_interface as mgcmd
24import madgraph.interface.extended_cmd as ext_cmd
25import madgraph.interface.amcatnlo_interface as amcatnlocmd
26import os
27import madgraph.fks.fks_helas_objects as fks_helas
28import copy
29import madgraph.iolibs.save_load_object as save_load_object
30import madgraph
31import madgraph.various.misc as misc
32root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0]
33root_path = os.path.dirname(root_path)
34# root_path is ./tests
35pjoin = os.path.join
36
37class TestAMCatNLOEWTagPh(unittest.TestCase):
38 """ a suite of extra tests for the ew stuff """
39
40 def setUp(self):
41 self.interface = mgcmd.MasterCmd()
42
43 def test_generate_fks_tagph(self):
44 """check that the generate command works as expected.
45 In particular the correct number of real-emission processes
46 and FKS partners"""
47 cmd_list = [
48 'u u~ > a a [real=QED]',
49 'u u~ > !a! !a! [real=QED]',
50 'u u~ > !2a! [real=QED]',
51 'u u~ > 2!a! [real=QED]']
52
53 nrealproc_list = [9, 3, 3, 3]
54 fks_j_list = [[1,2,3], [1,2], [1,2], [1,2]] # 4 is not there in the first set for symmetry
55
56
57 for cmd, nrealproc, fks_j in \
58 zip(cmd_list, nrealproc_list, fks_j_list):
59 self.interface.do_generate(cmd)
60
61 fksprocess = self.interface._fks_multi_proc['born_processes'][0]
62
63 self.assertEqual(len(fksprocess.real_amps), nrealproc)
64 self.assertEqual(set([r.fks_infos[0]['j'] for r in fksprocess.real_amps]), set(fks_j))
65
66 def test_invalid_syntax_tag(self):
67
68 cmd = "u u~ > !a! !a!"
69 self.assertRaises(madgraph.InvalidCmd, self.interface.do_generate, cmd)
70
71 cmd = "u u~ > !z! a [real=QED]"
72 self.assertRaises(madgraph.InvalidCmd, self.interface.do_generate, cmd)
73
74 cmd = "u u~ > !t! t~ a [real=QED]"
75 self.assertRaises(madgraph.InvalidCmd, self.interface.do_generate, cmd)
76
77 cmd = "u u~ > !a! a [real=QCD]" # is this valid ? I guess NOT [note this is QCD]
78 self.assertRaises(madgraph.InvalidCmd, self.interface.do_generate, cmd)
79
80

Subscribers

People subscribed via source and target branches

to all changes: