1
################################################################################
3
# Copyright (c) 2009 The MadGraph5_aMC@NLO Development team and Contributors
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.
9
# It is subject to the MadGraph5_aMC@NLO license which should accompany this
12
# For more information, visit madgraph.phys.ucl.ac.be and amcatnlo.web.cern.ch
14
################################################################################
16
"""Unit test library for the various properties of objects in
17
loop_diagram_generaiton"""
26
root_path = os.path.split(os.path.dirname(os.path.realpath( __file__ )))[0]
27
sys.path.append(os.path.join(root_path, os.path.pardir, os.path.pardir))
30
import tests.unit_tests as unittest
33
import madgraph.core.drawing as draw_lib
34
import madgraph.iolibs.drawing_eps as draw
35
import madgraph.core.base_objects as base_objects
36
import madgraph.core.diagram_generation as diagram_generation
37
import madgraph.loop.loop_base_objects as loop_base_objects
38
import madgraph.loop.loop_diagram_generation as loop_diagram_generation
39
import madgraph.iolibs.save_load_object as save_load_object
40
import models.import_ufo as models
41
from madgraph import MadGraph5Error
43
_file_path = os.path.dirname(os.path.realpath(__file__))
44
_input_file_path = os.path.join(_file_path, os.path.pardir, os.path.pardir,
46
_model_file_path = os.path.join(_file_path, os.path.pardir, os.path.pardir,
47
os.path.pardir,'models')
48
#===============================================================================
49
# Function to load a toy hardcoded Loop Model
50
#===============================================================================
53
"""Setup the NLO model"""
55
mypartlist = base_objects.ParticleList()
56
myinterlist = base_objects.InteractionList()
57
myloopmodel = loop_base_objects.LoopModel()
60
mypartlist.append(base_objects.Particle({'name':'g',
74
'counterterm':{('QCD',((),)):{-1:'GWfct'}}}))
76
# A quark U and its antiparticle
77
mypartlist.append(base_objects.Particle({'name':'u',
84
'antitexname':'\bar u',
90
'self_antipart':False}))
91
antiu = copy.copy(mypartlist[1])
92
antiu.set('is_part', False)
93
mypartlist[1].set('counterterm',{('QCD',((),)):{-1:'UQCDWfct'},
94
('QED',((),)):{-1:'UQEDWfct'}})
96
# A quark D and its antiparticle
97
mypartlist.append(base_objects.Particle({'name':'d',
104
'antitexname':'\bar d',
110
'self_antipart':False}))
111
antid = copy.copy(mypartlist[2])
112
antid.set('is_part', False)
113
mypartlist[2].set('counterterm',{('QCD',((),)):{-1:'DQCDWfct'},
114
('QED',((),)):{-1:'DQEDWfct'}})
117
mypartlist.append(base_objects.Particle({'name':'a',
124
'antitexname':'\gamma',
130
'self_antipart':True}))
132
# A electron and positron
133
mypartlist.append(base_objects.Particle({'name':'e-',
146
'self_antipart':False}))
147
antie = copy.copy(mypartlist[4])
148
antie.set('is_part', False)
150
# First set up the base interactions.
153
myinterlist.append(base_objects.Interaction({
155
'particles': base_objects.ParticleList(\
156
[mypartlist[0]] * 3),
159
'couplings':{(0, 0):'G'},
160
'orders':{'QCD':1}}))
163
myinterlist.append(base_objects.Interaction({
165
'particles': base_objects.ParticleList(\
166
[mypartlist[0]] * 4),
169
'couplings':{(0, 0):'G^2'},
170
'orders':{'QCD':2}}))
172
# Gluon and photon couplings to quarks
173
myinterlist.append(base_objects.Interaction({
175
'particles': base_objects.ParticleList(\
181
'couplings':{(0, 0):'GQQ'},
182
'orders':{'QCD':1}}))
184
myinterlist.append(base_objects.Interaction({
186
'particles': base_objects.ParticleList(\
192
'couplings':{(0, 0):'GQED'},
193
'orders':{'QED':1}}))
195
myinterlist.append(base_objects.Interaction({
197
'particles': base_objects.ParticleList(\
203
'couplings':{(0, 0):'GQQ'},
204
'orders':{'QCD':1}}))
206
myinterlist.append(base_objects.Interaction({
208
'particles': base_objects.ParticleList(\
214
'couplings':{(0, 0):'GQED'},
215
'orders':{'QED':1}}))
217
# Coupling of e to gamma
219
myinterlist.append(base_objects.Interaction({
221
'particles': base_objects.ParticleList(\
227
'couplings':{(0, 0):'GQED'},
228
'orders':{'QED':1}}))
230
# Then set up the R2 interactions proportional to those existing in the
234
myinterlist.append(base_objects.Interaction({
236
'particles': base_objects.ParticleList(\
237
[mypartlist[0]] * 3),
240
'couplings':{(0, 0):'G'},
242
'loop_particles':[[]],
243
'perturbation_type':'QCD',
247
myinterlist.append(base_objects.Interaction({
249
'particles': base_objects.ParticleList(\
250
[mypartlist[0]] * 4),
253
'couplings':{(0, 0):'G^2'},
255
'loop_particles':[[]],
256
'perturbation_type':'QCD',
259
# Gluon and photon couplings to quarks
260
myinterlist.append(base_objects.Interaction({
262
'particles': base_objects.ParticleList(\
268
'couplings':{(0, 0):'GQQ'},
270
'loop_particles':[[]],
271
'perturbation_type':'QCD',
274
myinterlist.append(base_objects.Interaction({
276
'particles': base_objects.ParticleList(\
282
'couplings':{(0, 0):'GQQ'},
283
'orders':{'QCD':1, 'QED':2},
284
'loop_particles':[[]],
285
'perturbation_type':'QED',
288
myinterlist.append(base_objects.Interaction({
290
'particles': base_objects.ParticleList(\
296
'couplings':{(0, 0):'GQED'},
297
'orders':{'QED':1, 'QCD':2},
298
'perturbation_type':'QCD',
299
'loop_particles':[[]],
302
myinterlist.append(base_objects.Interaction({
304
'particles': base_objects.ParticleList(\
310
'couplings':{(0, 0):'GQED'},
312
'loop_particles':[[]],
313
'perturbation_type':'QED',
316
myinterlist.append(base_objects.Interaction({
318
'particles': base_objects.ParticleList(\
324
'couplings':{(0, 0):'GQQ'},
326
'loop_particles':[[]],
327
'perturbation_type':'QCD',
330
myinterlist.append(base_objects.Interaction({
332
'particles': base_objects.ParticleList(\
338
'couplings':{(0, 0):'GQQ'},
339
'orders':{'QCD':1, 'QED':2},
340
'loop_particles':[[]],
341
'perturbation_type':'QED',
344
myinterlist.append(base_objects.Interaction({
346
'particles': base_objects.ParticleList(\
352
'couplings':{(0, 0):'GQED'},
353
'orders':{'QED':1, 'QCD':2},
354
'loop_particles':[[]],
355
'perturbation_type':'QCD',
358
myinterlist.append(base_objects.Interaction({
360
'particles': base_objects.ParticleList(\
366
'couplings':{(0, 0):'GQED'},
368
'loop_particles':[[]],
369
'perturbation_type':'QED',
372
# Coupling of e to gamma
374
myinterlist.append(base_objects.Interaction({
376
'particles': base_objects.ParticleList(\
382
'couplings':{(0, 0):'GQED'},
384
'loop_particles':[[]],
385
'perturbation_type':'QED',
388
# R2 interactions not proportional to the base interactions
390
# Two point interactions
393
myinterlist.append(base_objects.Interaction({
395
'particles': base_objects.ParticleList(\
396
[mypartlist[0]] * 2),
399
'couplings':{(0, 0):'G'},
401
'loop_particles':[[]],
402
'perturbation_type':'QCD',
406
myinterlist.append(base_objects.Interaction({
408
'particles': base_objects.ParticleList(\
409
[mypartlist[3]] * 2),
412
'couplings':{(0, 0):'G'},
414
'loop_particles':[[]],
415
'perturbation_type':'QED',
419
myinterlist.append(base_objects.Interaction({
421
'particles': base_objects.ParticleList([\
426
'couplings':{(0, 0):'G'},
428
'loop_particles':[[]],
429
'perturbation_type':'QED',
432
# The up quark, R2QED
433
myinterlist.append(base_objects.Interaction({
435
'particles': base_objects.ParticleList([\
440
'couplings':{(0, 0):'G'},
442
'loop_particles':[[]],
443
'perturbation_type':'QED',
446
# The up quark, R2QCD
447
myinterlist.append(base_objects.Interaction({
449
'particles': base_objects.ParticleList([\
454
'couplings':{(0, 0):'G'},
456
'loop_particles':[[]],
457
'perturbation_type':'QCD',
460
# The down quark, R2QED
461
myinterlist.append(base_objects.Interaction({
463
'particles': base_objects.ParticleList([\
468
'couplings':{(0, 0):'G'},
470
'loop_particles':[[]],
471
'perturbation_type':'QED',
474
# The down quark, R2QCD
475
myinterlist.append(base_objects.Interaction({
477
'particles': base_objects.ParticleList([\
482
'couplings':{(0, 0):'G'},
484
'loop_particles':[[]],
485
'perturbation_type':'QCD',
488
# The R2 three and four point interactions not proportional to the
492
myinterlist.append(base_objects.Interaction({
494
'particles': base_objects.ParticleList(\
495
[mypartlist[3]] * 3),
498
'couplings':{(0, 0):'G'},
500
'loop_particles':[[]],
501
'perturbation_type':'QED',
504
# 2 photon and 1 gluons
505
myinterlist.append(base_objects.Interaction({
507
'particles': base_objects.ParticleList(\
513
'couplings':{(0, 0):'G'},
514
'orders':{'QED':2, 'QCD':1},
515
'loop_particles':[[]],
516
'perturbation_type':'QED',
519
# 1 photon and 2 gluons
520
myinterlist.append(base_objects.Interaction({
522
'particles': base_objects.ParticleList(\
528
'couplings':{(0, 0):'G'},
529
'orders':{'QED':1, 'QCD':2},
530
'loop_particles':[[]],
531
'perturbation_type':'QCD',
535
myinterlist.append(base_objects.Interaction({
537
'particles': base_objects.ParticleList(\
538
[mypartlist[3]] * 4),
541
'couplings':{(0, 0):'G'},
543
'loop_particles':[[]],
544
'perturbation_type':'QED',
547
# 3 photons and 1 gluon
548
myinterlist.append(base_objects.Interaction({
550
'particles': base_objects.ParticleList(\
557
'couplings':{(0, 0):'G'},
558
'orders':{'QED':3,'QCD':1},
559
'loop_particles':[[]],
562
# 2 photons and 2 gluons
563
myinterlist.append(base_objects.Interaction({
565
'particles': base_objects.ParticleList(\
572
'couplings':{(0, 0):'G'},
573
'orders':{'QED':2,'QCD':2},
574
'loop_particles':[[]],
577
# 1 photon and 3 gluons
578
myinterlist.append(base_objects.Interaction({
580
'particles': base_objects.ParticleList(\
587
'couplings':{(0, 0):'G'},
588
'orders':{'QED':1,'QCD':3},
589
'loop_particles':[[]],
592
# Finally the UV interactions Counter-Terms
595
myinterlist.append(base_objects.Interaction({
597
'particles': base_objects.ParticleList(\
598
[mypartlist[0]] * 3),
601
'couplings':{(0, 0):'G'},
603
'loop_particles':[[]],
604
'perturbation_type':'QCD',
605
'type':'UVtree1eps'}))
608
myinterlist.append(base_objects.Interaction({
610
'particles': base_objects.ParticleList(\
611
[mypartlist[0]] * 4),
614
'couplings':{(0, 0):'G^2'},
616
'loop_particles':[[]],
617
'perturbation_type':'QCD',
618
'type':'UVtree1eps'}))
620
# Gluon and photon couplings to quarks CT
621
myinterlist.append(base_objects.Interaction({
623
'particles': base_objects.ParticleList(\
629
'couplings':{(0, 0):'GQQ'},
631
'loop_particles':[[]],
632
'perturbation_type':'QCD',
633
'type':'UVtree1eps'}))
635
# this is the CT for the renormalization of the QED corrections to alpha_QCD
636
myinterlist.append(base_objects.Interaction({
638
'particles': base_objects.ParticleList(\
644
'couplings':{(0, 0):'GQQ'},
645
'orders':{'QED':2,'QCD':1},
646
'loop_particles':[[]],
647
'perturbation_type':'QED',
648
'type':'UVtree1eps'}))
650
myinterlist.append(base_objects.Interaction({
652
'particles': base_objects.ParticleList(\
658
'couplings':{(0, 0):'GQED'},
659
'orders':{'QCD':2,'QED':1},
660
'loop_particles':[[]],
661
'perturbation_type':'QCD',
662
'type':'UVtree1eps'}))
664
myinterlist.append(base_objects.Interaction({
666
'particles': base_objects.ParticleList(\
672
'couplings':{(0, 0):'GQED'},
674
'loop_particles':[[]],
675
'perturbation_type':'QED',
676
'type':'UVtree1eps'}))
678
myinterlist.append(base_objects.Interaction({
680
'particles': base_objects.ParticleList(\
686
'couplings':{(0, 0):'GQQ'},
688
'loop_particles':[[]],
689
'perturbation_type':'QCD',
690
'type':'UVtree1eps'}))
692
myinterlist.append(base_objects.Interaction({
694
'particles': base_objects.ParticleList(\
700
'couplings':{(0, 0):'GQQ'},
701
'orders':{'QED':2,'QCD':1},
702
'loop_particles':[[]],
703
'perturbation_type':'QED',
704
'type':'UVtree1eps'}))
706
myinterlist.append(base_objects.Interaction({
708
'particles': base_objects.ParticleList(\
714
'couplings':{(0, 0):'GQED'},
715
'orders':{'QCD':2,'QED':1},
716
'loop_particles':[[]],
717
'perturbation_type':'QCD',
718
'type':'UVtree1eps'}))
720
myinterlist.append(base_objects.Interaction({
722
'particles': base_objects.ParticleList(\
728
'couplings':{(0, 0):'GQED'},
730
'loop_particles':[[]],
731
'perturbation_type':'QED',
732
'type':'UVtree1eps'}))
734
# alpha_QED to electron CT
736
myinterlist.append(base_objects.Interaction({
738
'particles': base_objects.ParticleList(\
744
'couplings':{(0, 0):'GQED'},
746
'loop_particles':[[]],
747
'perturbation_type':'QED',
748
'type':'UVtree1eps'}))
750
# The mass renormalization of the up and down quark granted
751
# a mass for the occasion
753
# The up quark, UVQED
754
myinterlist.append(base_objects.Interaction({
756
'particles': base_objects.ParticleList([\
761
'couplings':{(0, 0):'G'},
763
'loop_particles':[[]],
764
'perturbation_type':'QED',
765
'type':'UVmass1eps'}))
767
# The up quark, UVQCD
768
myinterlist.append(base_objects.Interaction({
770
'particles': base_objects.ParticleList([\
775
'couplings':{(0, 0):'G'},
777
'loop_particles':[[]],
778
'perturbation_type':'QCD',
779
'type':'UVmass1eps'}))
781
# The down quark, UVQED
782
myinterlist.append(base_objects.Interaction({
784
'particles': base_objects.ParticleList([\
789
'couplings':{(0, 0):'G'},
791
'loop_particles':[[]],
792
'perturbation_type':'QED',
793
'type':'UVmass1eps'}))
795
# The down quark, UVQCD
796
myinterlist.append(base_objects.Interaction({
798
'particles': base_objects.ParticleList([\
803
'couplings':{(0, 0):'G'},
805
'loop_particles':[[]],
806
'perturbation_type':'QCD',
807
'type':'UVmass1eps'}))
811
myloopmodel.set('particles', mypartlist)
812
myloopmodel.set('couplings', ['QCD','QED'])
813
myloopmodel.set('interactions', myinterlist)
814
myloopmodel.set('perturbation_couplings', ['QCD','QED'])
815
myloopmodel.set('order_hierarchy', {'QCD':1,'QED':2})
820
#===============================================================================
821
# LoopDiagramGeneration Test
822
#===============================================================================
824
class LoopDiagramGenerationTest(unittest.TestCase):
825
"""Test class for all functions related to the Loop diagram generation"""
827
mypartlist = base_objects.ParticleList()
828
myinterlist = base_objects.InteractionList()
829
myloopmodel = loop_base_objects.LoopModel()
834
myamplitude = diagram_generation.Amplitude()
837
"""Load different objects for the tests."""
839
#self.myloopmodel = models.import_full_model(os.path.join(\
840
# _model_file_path,'loop_sm'))
841
#self.myloopmodel.actualize_dictionaries()
842
self.myloopmodel = loadLoopModel()
844
self.mypartlist = self.myloopmodel['particles']
845
self.myinterlist = self.myloopmodel['interactions']
846
self.ref_dict_to0 = self.myinterlist.generate_ref_dict(['QCD','QED'])[0]
847
self.ref_dict_to1 = self.myinterlist.generate_ref_dict(['QCD','QED'])[1]
849
def test_NLOAmplitude(self):
850
"""test different features of the NLOAmplitude class"""
854
myleglist = base_objects.LegList()
855
myleglist.append(base_objects.Leg({'id':-11,
857
myleglist.append(base_objects.Leg({'id':11,
859
myleglist.append(base_objects.Leg({'id':1,
861
myleglist.append(base_objects.Leg({'id':-1,
863
dummyproc = base_objects.Process({'legs':myleglist,
864
'model':self.myloopmodel})
866
ampdefaultlist.append(diagram_generation.Amplitude())
867
ampdefaultlist.append(diagram_generation.Amplitude(dummyproc))
868
ampdefaultlist.append(diagram_generation.Amplitude({'process':dummyproc}))
869
ampdefaultlist.append(diagram_generation.DecayChainAmplitude(dummyproc,False))
871
dummyproc.set("perturbation_couplings",['QCD','QED'])
872
ampNLOlist.append(loop_diagram_generation.LoopAmplitude({'process':dummyproc}))
873
ampNLOlist.append(loop_diagram_generation.LoopAmplitude())
874
ampNLOlist.append(loop_diagram_generation.LoopAmplitude(dummyproc))
876
# Test the __new__ constructor of NLOAmplitude
877
for ampdefault in ampdefaultlist:
878
self.assertTrue(isinstance(ampdefault,diagram_generation.Amplitude))
879
self.assertFalse(isinstance(ampdefault,loop_diagram_generation.LoopAmplitude))
880
for ampNLO in ampNLOlist:
881
self.assertTrue(isinstance(ampNLO,loop_diagram_generation.LoopAmplitude))
883
# Now test for the usage of getter/setter of diagrams.
884
ampNLO=loop_diagram_generation.LoopAmplitude(dummyproc)
885
mydiaglist=base_objects.DiagramList([loop_base_objects.LoopDiagram({'type':0}),\
886
loop_base_objects.LoopDiagram({'type':0}),\
887
loop_base_objects.LoopDiagram({'type':0}),\
888
loop_base_objects.LoopDiagram({'type':0}),\
889
loop_base_objects.LoopDiagram({'type':0}),\
890
loop_base_objects.LoopDiagram({'type':0}),\
891
loop_base_objects.LoopDiagram({'type':1}),\
892
loop_base_objects.LoopDiagram({'type':2}),\
893
loop_base_objects.LoopDiagram({'type':3}),\
894
loop_base_objects.LoopDiagram({'type':4}),\
895
loop_base_objects.LoopUVCTDiagram()])
896
ampNLO.set('diagrams',mydiaglist)
897
self.assertEqual(len(ampNLO.get('diagrams')),11)
898
self.assertEqual(len(ampNLO.get('born_diagrams')),6)
899
self.assertEqual(len(ampNLO.get('loop_diagrams')),4)
900
self.assertEqual(len(ampNLO.get('loop_UVCT_diagrams')),1)
901
mydiaglist=base_objects.DiagramList([loop_base_objects.LoopDiagram({'type':0}),\
902
loop_base_objects.LoopDiagram({'type':0}),\
903
loop_base_objects.LoopDiagram({'type':0})])
904
ampNLO.set('born_diagrams',mydiaglist)
905
self.assertEqual(len(ampNLO.get('born_diagrams')),3)
907
def test_diagram_generation_epem_ddx(self):
908
"""Test the number of loop diagrams generated for e+e->dd~ (s channel)
909
with different choices for the perturbation couplings and squared orders.
912
myleglist = base_objects.LegList()
913
myleglist.append(base_objects.Leg({'id':-11,
915
myleglist.append(base_objects.Leg({'id':11,
917
myleglist.append(base_objects.Leg({'id':1,
919
myleglist.append(base_objects.Leg({'id':-1,
922
ordersChoices=[({},['QCD'],{},1),\
924
({},['QCD','QED'],{},10),\
925
({},['QED','QCD'],{'QED':-1},3),\
926
({},['QED','QCD'],{'QCD':-1},7)]
927
for (bornOrders,pert,sqOrders,nDiagGoal) in ordersChoices:
928
myproc = base_objects.Process({'legs':copy.copy(myleglist),
929
'model':self.myloopmodel,
931
'perturbation_couplings':pert,
932
'squared_orders':sqOrders})
934
myloopamplitude = loop_diagram_generation.LoopAmplitude()
935
myloopamplitude.set('process', myproc)
936
myloopamplitude.generate_diagrams()
937
self.assertEqual(len(myloopamplitude.get('loop_diagrams')),nDiagGoal)
939
#self.assertEqual(len([1 for diag in \
940
# myloopamplitude.get('loop_diagrams') if not isinstance(diag,
941
# loop_base_objects.LoopWavefunctionCTDiagram)]),nDiagGoal)
943
### This is to plot the diagrams obtained
944
diaglist=[diag for diag in \
945
myloopamplitude.get('loop_diagrams') if not isinstance(diag,
946
loop_base_objects.LoopUVCTDiagram)]
947
diaglist=myloopamplitude.get('loop_diagrams')
948
options = draw_lib.DrawOption()
949
filename = os.path.join('/tmp/' + \
950
myloopamplitude.get('process').shell_string() + ".eps")
951
plot = draw.MultiEpsDiagramDrawer(base_objects.DiagramList(diaglist),#myloopamplitude['loop_diagrams'],
953
model=self.myloopmodel,
954
amplitude=myloopamplitude,
955
legend=myloopamplitude.get('process').input_string())
956
plot.draw(opt=options)
958
### This is to display some informations
959
#mydiag1=myloopamplitude.get('loop_diagrams')[0]
960
#mydiag2=myloopamplitude.get('loop_diagrams')[5]
961
#print "I got tag for diag 1=",mydiag1['canonical_tag']
962
#print "I got tag for diag 2=",mydiag2['canonical_tag']
963
#print "I got vertices for diag 1=",mydiag1['vertices']
964
#print "I got vertices for diag 2=",mydiag2['vertices']
965
#print "mydiag=",str(mydiag)
966
#mydiag1.tag(trial,5,6,self.myloopmodel)
967
#print "I got tag=",mydiag['tag']
968
#print "I got struct[0]=\n",myloopamplitude['structure_repository'][0].nice_string()
969
#print "I got struct[2]=\n",myloopamplitude['structure_repository'][2].nice_string()
970
#print "I got struct[3]=\n",myloopamplitude['structure_repository'][3].nice_string()
972
def test_diagram_generation_uux_ga(self):
973
"""Test the number of loop diagrams generated for uu~>g gamma (s channel)
974
with different choices for the perturbation couplings and squared orders.
977
myleglist = base_objects.LegList()
978
myleglist.append(base_objects.Leg({'id':2,
980
myleglist.append(base_objects.Leg({'id':-2,
982
myleglist.append(base_objects.Leg({'id':21,
984
myleglist.append(base_objects.Leg({'id':22,
988
({},['QCD','QED'],{},37,12,4,18),
989
({},['QCD'],{},15,5,2,10)]
990
for (bornOrders,pert,sqOrders,nDiagGoal,nR2Goal,nUVmassGoal,nUVCTGoal) in ordersChoices:
991
myproc = base_objects.Process({'legs':copy.copy(myleglist),
992
'model':self.myloopmodel,
994
'perturbation_couplings':pert,
995
'squared_orders':sqOrders})
997
myloopamplitude = loop_diagram_generation.LoopAmplitude()
998
myloopamplitude.set('process', myproc)
999
myloopamplitude.generate_diagrams()
1001
### This is to plot the diagrams obtained
1002
#options = draw_lib.DrawOption()
1003
#filename = os.path.join('/Users/Spooner/Documents/PhD/MG5/NLO', 'diagramsVall_' + \
1004
# myloopamplitude.get('process').shell_string() + ".eps")
1005
#plot = draw.MultiEpsDiagramDrawer(myloopamplitude.get('diagrams'),
1007
# model=self.myloopmodel,
1008
# amplitude=myloopamplitude,
1009
# legend=myloopamplitude.get('process').input_string())
1010
#plot.draw(opt=options)
1014
for i, diag in enumerate(myloopamplitude.get('loop_diagrams')):
1015
sumR2+=len(diag.get_CT(self.myloopmodel,'R2'))
1016
sumUV+=len(diag.get_CT(self.myloopmodel,'UV'))
1017
self.assertEqual(len(myloopamplitude.get('loop_diagrams')),nDiagGoal)
1018
self.assertEqual(sumR2, nR2Goal)
1019
self.assertEqual(sumUV, nUVmassGoal)
1021
for loop_UVCT_diag in myloopamplitude.get('loop_UVCT_diagrams'):
1022
sumUVCT+=len(loop_UVCT_diag.get('UVCT_couplings'))
1023
self.assertEqual(sumUVCT,nUVCTGoal)
1025
def test_diagram_generation_gg_ng(self):
1026
"""Test the number of loop diagrams generated for gg>ng. n being in [1,2,3]
1030
nGluons = [(1,8,0,1,4),(2,81,0,10,23)]
1032
# (still 4 need to be re-tested)
1033
# nGluons += [(3,905,0,105,190),(4,11850,0,1290,2075)]
1035
for (n, nDiagGoal, nUVmassGoal, nR2Goal, nUVCTGoal) in nGluons:
1036
myleglist=base_objects.LegList([base_objects.Leg({'id':21,
1038
'loop_line':False}) \
1039
for num in range(1, (n+3))])
1040
myleglist[0].set('state',False)
1041
myleglist[1].set('state',False)
1043
myproc=base_objects.Process({'legs':myleglist,
1044
'model':self.myloopmodel,
1046
'squared_orders': {},
1047
'perturbation_couplings':['QCD']})
1049
myloopamplitude = loop_diagram_generation.LoopAmplitude()
1050
myloopamplitude.set('process', myproc)
1051
myloopamplitude.generate_diagrams()
1054
for i, diag in enumerate(myloopamplitude.get('loop_diagrams')):
1055
sumR2+=len(diag.get_CT(self.myloopmodel,'R2'))
1056
sumUV+=len(diag.get_CT(self.myloopmodel,'UV'))
1058
for loop_UVCT_diag in myloopamplitude.get('loop_UVCT_diagrams'):
1059
sumUVCT+=len(loop_UVCT_diag.get('UVCT_couplings'))
1060
self.assertEqual(len(myloopamplitude.get('loop_diagrams')), nDiagGoal)
1061
self.assertEqual(sumR2, nR2Goal)
1062
self.assertEqual(sumUV, nUVmassGoal)
1063
self.assertEqual(sumUVCT, nUVCTGoal)
1065
def test_diagram_generation_uux_ddx(self):
1066
"""Test the number of loop diagrams generated for uu~>dd~ for different choices
1070
myleglist = base_objects.LegList()
1071
myleglist.append(base_objects.Leg({'id':2,
1073
myleglist.append(base_objects.Leg({'id':-2,
1075
myleglist.append(base_objects.Leg({'id':1,
1077
myleglist.append(base_objects.Leg({'id':-1,
1080
ordersChoices=[({},['QCD','QED'],{},21,7,6,12),\
1081
({},['QCD','QED',],{'QED':-99},28,10,8,16),\
1082
({},['QCD'],{},9,3,2,4),\
1083
({},['QED'],{},2,2,2,4),\
1084
({'QED':0},['QCD'],{},9,3,2,4),\
1085
({'QCD':0},['QED'],{},7,3,2,4),\
1086
({},['QCD','QED'],{'QED':-1},9,3,2,4),\
1087
({},['QCD','QED'],{'QCD':-1},7,3,2,4),\
1088
({},['QCD','QED'],{'QED':-2},21,7,6,12),\
1089
({},['QCD','QED'],{'QED':-3},28,10,8,16)]
1091
for (bornOrders,pert,sqOrders,nDiagGoal,nR2Goal,nUVGoal,nUVWfctGoal) in ordersChoices:
1092
myproc = base_objects.Process({'legs':copy.copy(myleglist),
1093
'model':self.myloopmodel,
1094
'orders':bornOrders,
1095
'perturbation_couplings':pert,
1096
'squared_orders':sqOrders})
1097
myloopamplitude = loop_diagram_generation.LoopAmplitude()
1098
myloopamplitude.set('process', myproc)
1099
myloopamplitude.generate_diagrams()
1102
for i, diag in enumerate(myloopamplitude.get('loop_diagrams')):
1103
sumR2+=len(diag.get_CT(self.myloopmodel,'R2'))
1104
sumUV+=len(diag.get_CT(self.myloopmodel,'UV'))
1107
for loop_UVCT_diag in myloopamplitude.get('loop_UVCT_diagrams'):
1108
for coupl in loop_UVCT_diag.get('UVCT_couplings'):
1109
if not isinstance(coupl,str) or not 'Wfct' in coupl:
1114
self.assertEqual(len(myloopamplitude.get('loop_diagrams')), nDiagGoal)
1115
self.assertEqual(sumR2, nR2Goal)
1116
self.assertEqual(sumUV, nUVGoal)
1117
self.assertEqual(sumUVwfct, nUVWfctGoal)
1119
def test_diagram_generation_ddx_ddx(self):
1120
"""Test the number of loop diagrams generated for dd~>dd~ for different choices
1124
myleglist = base_objects.LegList()
1125
myleglist.append(base_objects.Leg({'id':1,
1127
myleglist.append(base_objects.Leg({'id':-1,
1129
myleglist.append(base_objects.Leg({'id':1,
1131
myleglist.append(base_objects.Leg({'id':-1,
1134
ordersChoices=[({},['QCD'],{},18,6,0,12),\
1135
({},['QED'],{},4,4,0,12),\
1136
({},['QCD','QED'],{},42,14,0,36),\
1137
({},['QCD','QED',],{'QED':-99},56,20,0,48),\
1138
({'QED':0},['QCD'],{},18,6,0,12),\
1139
({'QCD':0},['QED'],{},14,6,0,12),\
1140
({},['QCD','QED'],{'QED':-1},18,6,0,12),\
1141
({},['QCD','QED'],{'QCD':-1},14,6,0,12)]
1143
for (bornOrders,pert,sqOrders,nDiagGoal,nR2Goal,nUVmassGoal,nUVCTGoal) in ordersChoices:
1144
myproc = base_objects.Process({'legs':copy.copy(myleglist),
1145
'model':self.myloopmodel,
1146
'orders':bornOrders,
1147
'perturbation_couplings':pert,
1148
'squared_orders':sqOrders})
1150
myloopamplitude = loop_diagram_generation.LoopAmplitude()
1151
myloopamplitude.set('process', myproc)
1152
myloopamplitude.generate_diagrams()
1155
for i, diag in enumerate(myloopamplitude.get('loop_diagrams')):
1156
sumR2+=len(diag.get_CT(self.myloopmodel,'R2'))
1157
sumUV+=len(diag.get_CT(self.myloopmodel,'UV'))
1158
self.assertEqual(len(myloopamplitude.get('loop_diagrams')),nDiagGoal)
1159
self.assertEqual(sumR2, nR2Goal)
1160
self.assertEqual(sumUV, nUVmassGoal)
1162
for loop_UVCT_diag in myloopamplitude.get('loop_UVCT_diagrams'):
1163
sumUVCT+=len(loop_UVCT_diag.get('UVCT_couplings'))
1164
self.assertEqual(sumUVCT,nUVCTGoal)
1166
def test_CT_vertices_generation_gg_gg(self):
1167
""" test that the Counter Term vertices are correctly
1168
generated by adding some new CT interactions to the model and
1169
comparing how many CT vertices are generated on the
1170
process gg_gg for different R2 specifications. """
1172
newLoopModel=copy.deepcopy(self.myloopmodel)
1173
newInteractionList=base_objects.InteractionList()
1174
for inter in newLoopModel['interactions']:
1175
if inter['type']=='base':
1176
newInteractionList.append(inter)
1178
myleglist = base_objects.LegList()
1179
myleglist.append(base_objects.Leg({'id':21,
1181
myleglist.append(base_objects.Leg({'id':21,
1183
myleglist.append(base_objects.Leg({'id':21,
1185
myleglist.append(base_objects.Leg({'id':21,
1188
newInteractionList.append(base_objects.Interaction({
1191
'particles': base_objects.ParticleList(\
1192
[self.mypartlist[0]]*4),
1195
'couplings':{(0, 0):'G'},
1197
# We don't specify the loop content here
1198
'loop_particles':[[]],
1201
myproc = base_objects.Process({'legs':myleglist,
1202
'model':newLoopModel,
1204
'perturbation_couplings':['QCD'],
1205
'squared_orders':{'WEIGHTED':99}})
1207
myloopamplitude = loop_diagram_generation.LoopAmplitude()
1208
myloopamplitude.set('process', myproc)
1209
myloopamplitude.generate_diagrams()
1211
CTChoice=[([[]],{'QCD':4},1),
1212
([[21,]],{'QCD':4},1),
1213
([[1,]],{'QCD':4},1),
1214
([[2,]],{'QCD':4},1),
1215
([[2,],[21,],[1,]],{'QCD':4},3),
1216
([[2,],[21,2],[1,],[22,21,1]],{'QCD':4},2),
1217
([[21,]],{'QCD':4,'QED':1},0),
1218
([[1,2]],{'QCD':4},0)]
1220
for (parts,orders,nCTGoal) in CTChoice:
1221
newInteractionList[-1]['loop_particles']=parts
1222
newInteractionList[-1]['orders']=orders
1223
newLoopModel.set('interactions',newInteractionList)
1224
myloopamplitude['process']['model']=newLoopModel
1225
for diag in myloopamplitude.get('loop_diagrams'):
1226
diag['CT_vertices']=base_objects.VertexList()
1227
myloopamplitude.set_LoopCT_vertices()
1229
for i, diag in enumerate(myloopamplitude.get('loop_diagrams')):
1230
sumR2+=len(diag.get_CT(newLoopModel,'R2'))
1231
self.assertEqual(sumR2, nCTGoal)
1233
def test_CT_vertices_generation_ddx_ddx(self):
1234
""" test that the Counter Term vertices are correctly
1235
generated by adding some new CT interactions to the model and
1236
comparing how many CT vertices are generated on the
1237
process ddx_ddx for different R2 specifications. """
1239
newLoopModel=copy.deepcopy(self.myloopmodel)
1240
newInteractionList=base_objects.InteractionList()
1241
for inter in newLoopModel['interactions']:
1242
if inter['type']=='base':
1243
newInteractionList.append(inter)
1245
myleglist = base_objects.LegList()
1246
myleglist.append(base_objects.Leg({'id':1,
1248
myleglist.append(base_objects.Leg({'id':-1,
1250
myleglist.append(base_objects.Leg({'id':1,
1252
myleglist.append(base_objects.Leg({'id':-1,
1255
antid=copy.copy(self.mypartlist[2])
1256
antid.set('is_part',False)
1257
newInteractionList.append(base_objects.Interaction({
1260
'particles': base_objects.ParticleList(\
1261
[self.mypartlist[2],
1267
'couplings':{(0, 0):'G'},
1269
# We don't specify the loop content here
1270
'loop_particles':[[]],
1273
myproc = base_objects.Process({'legs':myleglist,
1274
'model':newLoopModel,
1276
'perturbation_couplings':['QCD','QED'],
1277
'squared_orders':{'WEIGHTED':99}})
1279
myloopamplitude = loop_diagram_generation.LoopAmplitude()
1280
myloopamplitude.set('process', myproc)
1281
myloopamplitude.generate_diagrams()
1283
CTChoice=[([[]],{'QCD':4},1),
1284
([[1,21]],{'QCD':4},1),
1285
([[1,22]],{'QED':4},1),
1286
([[1,22],[1,22]],{'QED':4},2),
1287
([[1,21]],{'QED':4},0),
1288
([[1,22]],{'QCD':4},0),
1289
([[21,]],{'QCD':4},0)]
1291
for (parts,orders,nCTGoal) in CTChoice:
1292
newInteractionList[-1]['loop_particles']=parts
1293
newInteractionList[-1]['orders']=orders
1294
newLoopModel.set('interactions',newInteractionList)
1295
myloopamplitude['process']['model']=newLoopModel
1296
for diag in myloopamplitude.get('loop_diagrams'):
1297
diag['CT_vertices']=base_objects.VertexList()
1298
myloopamplitude.set_LoopCT_vertices()
1300
for i, diag in enumerate(myloopamplitude.get('loop_diagrams')):
1301
sumR2+=len(diag.get_CT(newLoopModel,'R2'))
1302
self.assertEqual(sumR2, nCTGoal)
1304
#===============================================================================
1305
# LoopDiagramFDStruct Test
1306
#===============================================================================
1307
class LoopDiagramFDStructTest(unittest.TestCase):
1308
"""Test class for the tagging functions of LoopDiagram and FDStructure classes"""
1310
mypartlist = base_objects.ParticleList()
1311
myinterlist = base_objects.InteractionList()
1312
mymodel = base_objects.Model()
1313
myproc = base_objects.Process()
1314
myloopdiag = loop_base_objects.LoopDiagram()
1317
""" Setup a toy-model with gluon and down-quark only """
1320
self.mypartlist.append(base_objects.Particle({'name':'g',
1333
'self_antipart':True}))
1335
# A quark D and its antiparticle
1336
self.mypartlist.append(base_objects.Particle({'name':'d',
1343
'antitexname':'\bar d',
1349
'self_antipart':False}))
1350
antid = copy.copy(self.mypartlist[1])
1351
antid.set('is_part', False)
1354
self.myinterlist.append(base_objects.Interaction({
1356
'particles': base_objects.ParticleList(\
1357
[self.mypartlist[0]] * 3),
1360
'couplings':{(0, 0):'G'},
1361
'orders':{'QCD':1}}))
1364
self.myinterlist.append(base_objects.Interaction({
1366
'particles': base_objects.ParticleList(\
1367
[self.mypartlist[0]] * 4),
1370
'couplings':{(0, 0):'G^2'},
1371
'orders':{'QCD':2}}))
1373
# Gluon coupling to the down-quark
1374
self.myinterlist.append(base_objects.Interaction({
1376
'particles': base_objects.ParticleList(\
1377
[self.mypartlist[1], \
1379
self.mypartlist[0]]),
1382
'couplings':{(0, 0):'GQQ'},
1383
'orders':{'QCD':1}}))
1385
self.mymodel.set('particles', self.mypartlist)
1386
self.mymodel.set('interactions', self.myinterlist)
1387
self.myproc.set('model',self.mymodel)
1389
def test_gg_5gglgl_bubble_tag(self):
1390
""" Test the gg>ggggg g*g* tagging of a bubble"""
1392
# Five gluon legs with two initial states
1393
myleglist = base_objects.LegList([base_objects.Leg({'id':21,
1395
'loop_line':False}) \
1396
for num in range(1, 10)])
1397
myleglist[7].set('loop_line', True)
1398
myleglist[8].set('loop_line', True)
1408
lfinal=copy.copy(l9)
1409
lfinal.set('number',9)
1411
self.myproc.set('legs',myleglist)
1413
l67 = base_objects.Leg({'id':21,'number':6,'loop_line':False})
1414
l56 = base_objects.Leg({'id':21,'number':5,'loop_line':False})
1415
l235 = base_objects.Leg({'id':21,'number':2,'loop_line':False})
1416
l24 = base_objects.Leg({'id':21,'number':2,'loop_line':False})
1417
l28 = base_objects.Leg({'id':21,'number':2,'loop_line':True})
1418
l128 = base_objects.Leg({'id':21,'number':1,'loop_line':True})
1419
l19 = base_objects.Leg({'id':21,'number':1,'loop_line':True})
1420
l18 = base_objects.Leg({'id':21,'number':1,'loop_line':True})
1421
l12 = base_objects.Leg({'id':21,'number':1,'loop_line':True})
1423
vx19 = base_objects.Vertex({'legs':base_objects.LegList([l1, l9, l19]), 'id': 1})
1424
vx67 = base_objects.Vertex({'legs':base_objects.LegList([l6, l7, l67]), 'id': 1})
1425
vx56 = base_objects.Vertex({'legs':base_objects.LegList([l5, l67, l56]), 'id': 1})
1426
vx235 = base_objects.Vertex({'legs':base_objects.LegList([l2, l3, l56, l235]), 'id': 2})
1427
vx24 = base_objects.Vertex({'legs':base_objects.LegList([l4, l235, l24]), 'id': 1})
1428
vx28 = base_objects.Vertex({'legs':base_objects.LegList([l235, l8, l28]), 'id': 1})
1429
vx0 = base_objects.Vertex({'legs':base_objects.LegList([l19, l28]), 'id': 0})
1431
myVertexList=base_objects.VertexList([vx19,vx67,vx56,vx235,vx24,vx28,vx0])
1433
myBubbleDiag=loop_base_objects.LoopDiagram({'vertices':myVertexList,'type':21})
1435
myStructRep=loop_base_objects.FDStructureList()
1436
myStruct=loop_base_objects.FDStructure()
1438
goal_canonicalStruct=(((2, 3, 4, 5, 6, 7), 1), ((2, 3, 5, 6, 7), 2), ((5, 6, 7), 1), ((6, 7), 1))
1439
canonicalStruct=myBubbleDiag.construct_FDStructure(5, 0, 2, myStruct)
1440
self.assertEqual(canonicalStruct, goal_canonicalStruct)
1442
goal_vxList=base_objects.VertexList([vx67,vx56,vx235,vx24])
1443
myStruct.set('canonical',canonicalStruct)
1444
myStruct.generate_vertices(self.myproc)
1445
self.assertEqual(myStruct['vertices'],goal_vxList)
1447
goal_tag=[[21, [1], 1], [21, [0], 1]]
1448
vx18_tag=base_objects.Vertex({'legs':base_objects.LegList([l1, l8, l18]), 'id': 1})
1449
vx12_tag=base_objects.Vertex({'legs':base_objects.LegList([l24, l18, l12]), 'id': 1})
1450
closing_vx=base_objects.Vertex({'legs':base_objects.LegList([l12, lfinal]), 'id': -1})
1451
goal_vertices=base_objects.VertexList([vx18_tag,vx12_tag,closing_vx])
1452
myBubbleDiag.tag(myStructRep,8,9,self.myproc)
1453
self.assertEqual(myBubbleDiag.get('canonical_tag'), goal_tag)
1454
self.assertEqual(myBubbleDiag.get('vertices'), goal_vertices)
1456
def test_gg_4gdldxl_penta_tag(self):
1457
""" Test the gg>gggg d*dx* tagging of a quark pentagon"""
1459
# Five gluon legs with two initial states
1460
myleglist = base_objects.LegList([base_objects.Leg({'id':21,
1462
'loop_line':False}) \
1463
for num in range(1, 7)])
1464
myleglist.append(base_objects.Leg({'id':1,'number':7,'loop_line':True}))
1465
myleglist.append(base_objects.Leg({'id':-1,'number':8,'loop_line':True}))
1475
self.myproc.set('legs',myleglist)
1477
# One way of constructing this diagram, with a three-point amplitude
1478
l17 = base_objects.Leg({'id':1,'number':1,'loop_line':True})
1479
l12 = base_objects.Leg({'id':1,'number':1,'loop_line':True})
1480
l68 = base_objects.Leg({'id':-1,'number':6,'loop_line':True})
1481
l56 = base_objects.Leg({'id':-1,'number':5,'loop_line':True})
1482
l34 = base_objects.Leg({'id':21,'number':3,'loop_line':False})
1483
l617 = base_objects.Leg({'id':1,'number':1,'loop_line':True})
1485
vx17 = base_objects.Vertex({'legs':base_objects.LegList([l1, l7, l17]), 'id': 3})
1486
vx12 = base_objects.Vertex({'legs':base_objects.LegList([l17, l2, l12]), 'id': 3})
1487
vx68 = base_objects.Vertex({'legs':base_objects.LegList([l6, l8, l68]), 'id': 3})
1488
vx56 = base_objects.Vertex({'legs':base_objects.LegList([l5, l68, l56]), 'id': 3})
1489
vx34 = base_objects.Vertex({'legs':base_objects.LegList([l3, l4, l34]), 'id': 1})
1490
vx135 = base_objects.Vertex({'legs':base_objects.LegList([l12, l56, l34]), 'id': 3})
1492
myVertexList1=base_objects.VertexList([vx17,vx12,vx68,vx56,vx34,vx135])
1494
myPentaDiag1=loop_base_objects.LoopDiagram({'vertices':myVertexList1,'type':1})
1496
myStructRep=loop_base_objects.FDStructureList()
1497
myStruct=loop_base_objects.FDStructure()
1499
goal_tag=[[1, [0], 3], [1, [1], 3], [1, [2], 3], [1, [3], 3], [1, [4], 3]]
1500
myPentaDiag1.tag(myStructRep,7,8,self.myproc)
1501
self.assertEqual(myPentaDiag1.get('canonical_tag'), goal_tag)
1503
vx17_tag=base_objects.Vertex({'legs':base_objects.LegList([l1, l7, l17]), 'id': 3})
1504
vx12_tag=base_objects.Vertex({'legs':base_objects.LegList([l2, l17, l12]), 'id': 3})
1505
vx13_tag=base_objects.Vertex({'legs':base_objects.LegList([l34, l12, l17]), 'id': 3})
1506
vx15_tag=base_objects.Vertex({'legs':base_objects.LegList([l5, l17, l17]), 'id': 3})
1507
vx168_tag=base_objects.Vertex({'legs':base_objects.LegList([l6, l17, l617]), 'id': 3})
1508
closing_vx=base_objects.Vertex({'legs':base_objects.LegList([l617, l8]), 'id': -1})
1509
goal_vertices=base_objects.VertexList([vx17_tag,vx12_tag,vx13_tag,vx15_tag,vx168_tag,closing_vx])
1510
self.assertEqual(myPentaDiag1.get('vertices'), goal_vertices)
1512
if __name__ == '__main__':
1513
# Save this model so that it can be loaded by other loop tests
1514
save_load_object.save_to_file(os.path.join(_input_file_path, 'test_toyLoopModel.pkl'),loadLoopModel())
1515
print "test_toyLoopModel.pkl created."