diff --git a/Models/Feynrules/python/ufo2peg/vertices.py b/Models/Feynrules/python/ufo2peg/vertices.py --- a/Models/Feynrules/python/ufo2peg/vertices.py +++ b/Models/Feynrules/python/ufo2peg/vertices.py @@ -1,851 +1,858 @@ import sys,pprint from .helpers import CheckUnique,getTemplate,writeFile,coupling_orders,def_from_model from .converter import py2cpp from .collapse_vertices import collapse_vertices from .check_lorentz import tensorCouplings,VVVordering,lorentzScalar,\ processTensorCouplings,scalarCouplings,processScalarCouplings,scalarVectorCouplings,\ processScalarVectorCouplings,vectorCouplings,processVectorCouplings,fermionCouplings,processFermionCouplings,\ RSCouplings from .general_lorentz import convertLorentz,generateEvaluateFunction,multipleEvaluate from .helpers import SkipThisVertex,extractAntiSymmetricIndices,isGoldstone # prefactors for vertices lfactors = { 'FFV' : '-complex(0,1)', # ok 'VVV' : 'complex(0,1)', # changed to fix ttbar 'VVVS' : 'complex(0,1)', # should be as VVV 'VVVV' : 'complex(0,1)', 'VVS' : '-complex(0,1)', 'VSS' : '-complex(0,1)', # changed to minus to fix dL ->x1 W- d 'SSS' : '-complex(0,1)', # ok 'VVSS' : '-complex(0,1)', # ok 'VVT' : 'complex(0,2)', 'VVVT' : '-complex(0,2)', 'SSSS' : '-complex(0,1)', # ok 'FFS' : '-complex(0,1)', # ok 'SST' : 'complex(0,2)', 'FFT' : '-complex(0,8)', 'FFVT' : '-complex(0,4)', 'RFS' : 'complex(0,1)', 'RFV' : 'complex(0,1)', } genericVertices=['FFFF','FFVV','FFSS','FFVS','VVVV','VVVT','FFVT', 'RFVV','RFVS','RFSS','SSST','VVST','FFST'] skipped5Point=False # template for the header for a vertex VERTEXHEADER = """\ #include "ThePEG/Helicity/Vertex/{spindirectory}/{lorentztag}Vertex.h" """ GENERALVERTEXHEADER = """\ #include "ThePEG/Helicity/Vertex/Abstract{lorentztag}Vertex.h" """ # template for the implmentation for a vertex VERTEXCLASS = getTemplate('Vertex_class') GENERALVERTEXCLASS = getTemplate('GeneralVertex_class') # template for the .cc file for vertices VERTEX = getTemplate('Vertex.cc') vertexline = """\ create Herwig::FRModel{classname} /Herwig/{modelname}/{classname} insert {modelname}:ExtraVertices 0 /Herwig/{modelname}/{classname} """ def get_lorentztag(spin): """Produce a ThePEG spin tag for the given numeric FR spins.""" spins = { 1 : 'S', 2 : 'F', 3 : 'V', 4 : 'R', 5 : 'T', -1 : 'U' } result=[] for i in range(0,len(spin)) : result.append((spins[spin[i]],i+1)) def spinsort(a,b): """Helper function for ThePEG's FVST spin tag ordering.""" (a1,a2) = a (b1,b2) = b if a1 == b1: return 0 for letter in 'URFVST': if a1 == letter: return -1 if b1 == letter: return 1 result = sorted(result, cmp=spinsort) order=[] output="" for i in range(0,len(result)) : (a,b) = result[i] order.append(b) output+=a return (output,order) def unique_lorentztag(vertex): """Check and return the Lorentz tag of the vertex.""" unique = CheckUnique() for l in vertex.lorentz: (lorentztag,order) = get_lorentztag(l.spins) unique( lorentztag ) lname = l.name[:len(lorentztag)] if sorted(lorentztag) != sorted(lname): raise Exception("Lorentztags: %s is not %s in %s" % (lorentztag,lname,vertex)) return (lorentztag,order) def colors(vertex) : try: unique = CheckUnique() for pl in vertex.particles_list: struct = [ p.color for p in pl ] unique(struct) except: struct = [ p.color for p in vertex.particles ] pos = colorpositions(struct) L = len(struct) return (L,pos) def coloursort(a,b) : if a == b: return 0 i1=int(a[4]) i2=int(b[4]) if(i1==i2) : return 0 elif(i1<i2) : return -1 else : return 1 def colorfactor(vertex,L,pos,lorentztag): def match(patterns,color=vertex.color): result = [ p == t for p,t in zip(patterns,color) ] return all(result) label = None l = lambda c: len(pos[c]) if l(1) == L: label = ('1',) if match(label): return ("SINGLET",('1.',)) elif l(3) == l(-3) == 1 and l(1) == L-2: nums = [pos[3][0], pos[-3][0]] label = ('Identity({0},{1})'.format(*sorted(nums)),) if match(label): return ("DELTA",('1.',)) elif l(6) == l(-6) == 1 and l(1) == L-2: nums = [pos[6][0], pos[-6][0]] label = ('Identity({0},{1})'.format(*sorted(nums)),) if match(label): return ("DELTA",('1.',)) elif l(6) == l(-6) == 2 and L==4: sys.stderr.write( 'Warning: Unknown colour structure 6 6 6~ 6~ ( {ps} ) in {name}.\n' .format(name=vertex.name, ps=' '.join(map(str,vertex.particles))) ) raise SkipThisVertex() elif l(8) == l(3) == l(-3) == 1 and l(1) == L-3: label = ('T({g},{q},{qb})'.format(g=pos[8][0],q=pos[3][0],qb=pos[-3][0]),) if match(label): return ("SU3TFUND",('1.',)) elif l(8) == l(6) == l(-6) == 1 and l(1) == L-3: label = ('T6({g},{s},{sb})'.format(g=pos[8][0],s=pos[6][0],sb=pos[-6][0]),) if match(label): return ("SU3T6",('1.',)) elif l(6) == 1 and l(-3) == 2 and L==3: label = ('K6({s},{qb1},{qb2})'.format(s=pos[6][0],qb1=pos[-3][0],qb2=pos[-3][1]),) if match(label): return ("SU3K6",('1.',)) elif l(-6) == 1 and l(3) == 2 and L==3: label = ('K6Bar({sb},{q1},{q2})'.format(sb=pos[-6][0],q1=pos[3][0],q2=pos[3][1]),) if match(label): return ("SU3K6",('1.',)) elif l(3) == L == 3: colors=[] for color in vertex.color : order,sign = extractAntiSymmetricIndices(color,"Epsilon(") colors.append("Epsilon(%s,%s,%s)" % (order[0],order[1],order[2])) label = ('Epsilon(1,2,3)',) if match(label,colors): return ("EPS",('1.',)) # TODO check factor! elif l(-3) == L == 3: colors=[] for color in vertex.color : order,sign = extractAntiSymmetricIndices(color,"EpsilonBar(") colors.append("Epsilon(%s,%s,%s)" % (order[0],order[1],order[2])) label = ('EpsilonBar(1,2,3)',) if match(label): return ("EPS",('1.',)) # TODO check factor! elif l(8) == L == 3: colors=[] for color in vertex.color : order,sign = extractAntiSymmetricIndices(color,"f(") colors.append("f(%s,%s,%s)" % (order[0],order[1],order[2])) # if lorentz is FFV get extra minus sign if lorentztag in ['FFV'] : sign *=-1 label = ('f(1,2,3)',) if match(label,colors): return ("SU3F",('-complex(0,1.)*(%s)'%sign,)) elif l(8) == 3 and l(1)==1 and L == 4: colors=[] for color in vertex.color : order,sign = extractAntiSymmetricIndices(color,"f(") colors.append("f(%s,%s,%s)" % (order[0],order[1],order[2])) if(pos[1][0]==1) : label = ('f(2,3,4)',) elif(pos[1][0]==2) : label = ('f(1,3,4)',) elif(pos[1][0]==3) : label = ('f(1,2,4)',) elif(pos[1][0]==4) : label = ('f(1,2,3)',) if match(label,colors): return ("SU3F",('-complex(0,1.)*(%s)'%sign,)) elif l(8) == L == 4: colors=[] for color in vertex.color : f = color.split("*") (o1,s1) = extractAntiSymmetricIndices(f[0],"f(") (o2,s2) = extractAntiSymmetricIndices(f[1],"f(") if(o2[0]<o1[0]) : o1,o2=o2,o1 colors.append("f(%s)*f(%s)" % (",".join(o1),",".join(o2))) colors=sorted(colors,cmp=coloursort) label = ('f(1,2,-1)*f(3,4,-1)', 'f(1,3,-1)*f(2,4,-1)', 'f(1,4,-1)*f(2,3,-1)') nmatch=0 for c1 in label: for c2 in colors : if(c1==c2) : nmatch+=1 if(nmatch==2 and lorentztag=="VVSS") : return ("SU3FF",('1.','1.')) elif(nmatch==3 and lorentztag=="VVVV") : return ("SU3FF",('1.','1.','1.')) elif l(8) == 2 and l(3) == l(-3) == 1 and L==4: subs = { 'g1' : pos[8][0], 'g2' : pos[8][1], 'qq' : pos[3][0], 'qb' : pos[-3][0] } if(vertex.lorentz[0].spins.count(1)==2) : label = ('T({g1},-1,{qb})*T({g2},{qq},-1)'.format(**subs), 'T({g1},{qq},-1)*T({g2},-1,{qb})'.format(**subs)) if match(label): return ("SU3TTFUNDS",('1.','1.')) elif(vertex.lorentz[0].spins.count(2)==2) : label = ('f({g1},{g2},-1)*T(-1,{qq},{qb})'.format(**subs),) if match(label): return ("SU3TTFUNDD",('-complex(0.,1.)',)) label = ('f(-1,{g1},{g2})*T(-1,{qq},{qb})'.format(**subs),) if match(label): return ("SU3TTFUNDD",('-complex(0.,1.)',)) + elif(vertex.lorentz[0].spins.count(3)==4) : + label = ('f(-1,{g1},{g2})*T(-1,{qq},{qb})'.format(**subs), + 'T({g1},-1,{qb})*T({g2},{qq},-1)'.format(**subs), + 'T({g1},{qq},-1)*T({g2},-1,{qb})'.format(**subs)) + if match(label): return ("SU3TTFUNDS",(('-complex(0.,1.)','complex(0.,1.)'),'1.','1.')) + elif l(8) == 2 and l(6) == l(-6) == 1 and L==4: subs = { 'g1' : pos[8][0], 'g2' : pos[8][1], 'qq' : pos[6][0], 'qb' : pos[-6][0] } label = ('T6({g1},-1,{qb})*T6({g2},{qq},-1)'.format(**subs), 'T6({g1},{qq},-1)*T6({g2},-1,{qb})'.format(**subs)) if match(label): return ("SU3TT6",('1.','1.')) elif l(8) == 2 and l(8)+l(1)==L : subs = { 'g1' : pos[8][0], 'g2' : pos[8][1] } label = ('Identity({g1},{g2})'.format(**subs),) if match(label) : return ("DELTA",('1.',)) elif l(8) == 3 and l(1)==1 and L==4 : colors=[] for color in vertex.color : order,sign = extractAntiSymmetricIndices(color,"f(") colors.append("f(%s,%s,%s)" % (order[0],order[1],order[2])) label = ('f(1,2,3)',) if match(label,colors): return ("SU3F",('-complex(0.,1.)*(%s)'%sign,)) elif l(3)==2 and l(-3) == 2 and L==4 and lorentztag=="FFFF" : labels=["Identity(1,2)*Identity(3,4)", "Identity(1,4)*Identity(2,3)", "T(-1,2,1)*T(-1,4,3)", "T(-1,2,3)*T(-1,4,1)"] cstruct=["SU3I12I34","SU3I14I23","SU3T21T43","SU3T23T41"] oname=[] ovalue=[] for color in vertex.color : for i in range(0,len(labels)) : if labels[i]==color : break if(i<len(labels)) : oname.append(cstruct[i]) ovalue.append("1.") else : sys.stderr.write( "Warning: Unknown colour structure {color} ( {ps} ) in {name} for FFFF vertex.\n" .format(color = ' '.join(vertex.color), name = vertex.name, ps = ' '.join(map(str,vertex.particles))) ) raise SkipThisVertex() return(oname,ovalue) sys.stderr.write( "Warning: Unknown colour structure {color} ( {ps} ) in {name}.\n" .format(color = ' '.join(vertex.color), name = vertex.name, ps = ' '.join(map(str,vertex.particles))) ) raise SkipThisVertex() def colorpositions(struct): positions = { 1 : [], 3 : [], -3 : [], 6 : [], -6 : [], 8 : [], } for i,s in enumerate(struct,1): positions[s].append(i) return positions def spindirectory(lt): """Return the spin directory name for a given Lorentz tag.""" if 'T' in lt: spin_directory = 'Tensor' elif 'S' in lt: spin_directory = 'Scalar' elif 'V' in lt: spin_directory = 'Vector' else: raise Exception("Unknown Lorentz tag {lt}.".format(lt=lt)) return spin_directory def write_vertex_file(subs): 'Write the .cc file for some vertices' newname = '%s_Vertices_%03d.cc' % (subs['ModelName'],subs['vertexnumber']) subs['newname'] = newname writeFile( newname, VERTEX.substitute(subs) ) def checkGhostGoldstoneVertex(lorentztag,vertex) : 'check if vertex has ghosts or goldstones' # remove vertices involving ghost fields if 'U' in lorentztag: return True # remove vertices involving goldstones for p in vertex.particles: if(isGoldstone(p)): return True return False def calculatePrefactor(lf,cf) : prefactor = '(%s) * (%s)' % (lf,cf) return prefactor def couplingValue(coupling) : if type(coupling) is not list: value = coupling.value else: value = "(" for coup in coupling : value += '+(%s)' % coup.value value +=")" return value def epsilonSign(vertex,couplingptrs,append) : EPSSIGN = """\ double sign = {epssign}; if((p1->id()=={id1} && p2->id()=={id3} && p3->id()=={id2}) || (p1->id()=={id2} && p2->id()=={id1} && p3->id()=={id3}) || (p1->id()=={id3} && p2->id()=={id2} && p3->id()=={id1})) {{ sign *= -1.; }} norm(norm()*sign); """ if(not "p1" in couplingptrs[0]) : couplingptrs[0] += ' p1' if(not "p2" in couplingptrs[1]) : couplingptrs[1] += ' p2' if(not "p3" in couplingptrs[2]) : couplingptrs[2] += ' p3' if("Bar" not in vertex.color[0]) : order,sign = extractAntiSymmetricIndices(vertex.color[0],"Epsilon(") else : order,sign = extractAntiSymmetricIndices(vertex.color[0],"EpsilonBar(") subs = {"id1" : vertex.particles[int(order[0])-1].pdg_code, "id2" : vertex.particles[int(order[1])-1].pdg_code, "id3" : vertex.particles[int(order[2])-1].pdg_code, "epssign" : sign } append+=EPSSIGN.format(**subs) return couplingptrs,append class VertexConverter: 'Convert the vertices in a FR model to extract the information ThePEG needs.' def __init__(self,model,parmsubs,defns) : 'Initialize the parameters' self.verbose=False self.vertex_skipped=False self.ignore_skipped=False self.model=model self.all_vertices= [] self.vertex_names = {} self.modelname="" self.no_generic_loop_vertices = False self.parmsubs = parmsubs self.couplingDefns = defns self.genericTensors = False def readArgs(self,args) : 'Extract the relevant command line arguments' self.ignore_skipped = args.ignore_skipped self.verbose = args.verbose self.modelname = args.name self.no_generic_loop_vertices = args.no_generic_loop_vertices self.include_generic = args.include_generic self.genericTensors = args.use_generic_for_tensors def should_print(self) : 'Check if we should output the results' return not self.vertex_skipped or self.ignore_skipped def convert(self) : 'Convert the vertices' if(self.verbose) : print 'verbose mode on: printing all vertices' print '-'*60 labels = ('vertex', 'particles', 'Lorentz', 'C_L', 'C_R', 'norm') pprint.pprint(labels) # extract the vertices self.all_vertices = self.model.all_vertices # convert the vertices vertexclasses, vertexheaders = [], set() ifile=1 icount=0 for vertexnumber,vertex in enumerate(self.all_vertices,1) : # process the vertex (skip,vertexClass,vertexHeader) = \ self.processVertex(vertexnumber,vertex) # check it can be handled if(skip) : continue # add to the list icount +=1 vertexclasses.append(vertexClass) vertexheaders.add(vertexHeader) WRAP = 25 if icount % WRAP == 0 or vertexHeader.find("Abstract")>=0: write_vertex_file({'vertexnumber' : ifile, 'vertexclasses' : '\n'.join(vertexclasses), 'vertexheaders' : ''.join(vertexheaders), 'ModelName' : self.modelname}) vertexclasses = [] vertexheaders = set() icount=0 ifile+=1 # exit if there's vertices we can't handle if not self.should_print(): sys.stderr.write( """ Error: The conversion was unsuccessful, some vertices could not be generated. If you think the missing vertices are not important and want to go ahead anyway, use --ignore-skipped. Herwig may not give correct results, though. """ ) sys.exit(1) # if still stuff to output it do it if vertexclasses: write_vertex_file({'vertexnumber' : ifile + 1, 'vertexclasses' : '\n'.join(vertexclasses), 'vertexheaders' : ''.join(vertexheaders), 'ModelName' : self.modelname}) print '='*60 def setCouplingPtrs(self,lorentztag,qcd,append,prepend) : couplingptrs = [',tcPDPtr']*len(lorentztag) if lorentztag == 'VSS': couplingptrs[1] += ' p2' elif lorentztag == 'FFV': couplingptrs[0] += ' p1' elif (lorentztag == 'VVV' or lorentztag == 'VVVS' or lorentztag == "SSS" or lorentztag == "VVVT" ) \ and (append or prepend ) : couplingptrs[0] += ' p1' couplingptrs[1] += ' p2' couplingptrs[2] += ' p3' - elif (lorentztag == 'VVVV' and qcd < 2) or\ + elif (lorentztag == 'VVVV' and (qcd < 2 or append)) or\ (lorentztag == "SSSS" and prepend ): couplingptrs[0] += ' p1' couplingptrs[1] += ' p2' couplingptrs[2] += ' p3' couplingptrs[3] += ' p4' return couplingptrs def processVertex(self,vertexnumber,vertex) : global skipped5Point # get the Lorentz tag for the vertex lorentztag,order = unique_lorentztag(vertex) # check if we should skip the vertex vertex.herwig_skip_vertex = checkGhostGoldstoneVertex(lorentztag,vertex) # check the order of the vertex and skip 5 points if(len(lorentztag)>=5) : vertex.herwig_skip_vertex = True if(not skipped5Point) : skipped5Point = True print "Skipping 5 point vertices which aren\'t used in Herwig7" if(vertex.herwig_skip_vertex) : return (True,"","") # check if we support this at all if( lorentztag not in lfactors and lorentztag not in genericVertices) : msg = 'Warning: Lorentz structure {tag} ( {ps} ) in {name} ' \ 'is not supported.\n'.format(tag=lorentztag, name=vertex.name, ps=' '.join(map(str,vertex.particles))) sys.stderr.write(msg) vertex.herwig_skip_vertex = True self.vertex_skipped=True return (True,"","") # get the factor for the vertex generic = False try: lf = lfactors[lorentztag] if( self.genericTensors and "T" in lorentztag) : raise KeyError() except KeyError: if(not self.include_generic) : msg = 'Warning: Lorentz structure {tag} ( {ps} ) in {name} ' \ 'is not supported.\n'.format(tag=lorentztag, name=vertex.name, ps=' '.join(map(str,vertex.particles))) sys.stderr.write(msg) vertex.herwig_skip_vertex = True self.vertex_skipped=True return (True,"","") else : lf=1. generic=True # get the ids of the particles at the vertex plistarray = [ ','.join([ str(vertex.particles[o-1].pdg_code) for o in order ]) ] # parse the colour structure for the vertex try: L,pos = colors(vertex) cs,cf = colorfactor(vertex,L,pos,lorentztag) except SkipThisVertex: msg = 'Warning: Color structure for vertex ( {ps} ) in {name} ' \ 'is not supported.\n'.format(tag=lorentztag, name=vertex.name, ps=' '.join(map(str,vertex.particles))) sys.stderr.write(msg) vertex.herwig_skip_vertex = True self.vertex_skipped=True return (True,"","") ### classname classname = 'V_%s' % vertex.name if(not generic) : try : return self.extractGeneric(vertex,order,lorentztag,classname,plistarray,pos,lf,cf,cs) except SkipThisVertex: if(not self.include_generic) : msg = 'Warning: Lorentz structure {tag} ( {ps} ) in {name} ' \ 'is not supported, may have a non-perturbative form.\n'.format(tag=lorentztag, name=vertex.name, ps=' '.join(map(str,vertex.particles))) sys.stderr.write(msg) vertex.herwig_skip_vertex = True self.vertex_skipped=True return (True,"","") else : try : return self.extractGeneral(vertex,order,lorentztag,classname,plistarray,pos,cf,cs) except SkipThisVertex: msg = 'Warning: Lorentz structure {tag} ( {ps} ) in {name} ' \ 'is not supported, may have a non-perturbative form.\n'.format(tag=lorentztag, name=vertex.name, ps=' '.join(map(str,vertex.particles))) sys.stderr.write(msg) vertex.herwig_skip_vertex = True self.vertex_skipped=True return (True,"","") else : try : return self.extractGeneral(vertex,order,lorentztag,classname,plistarray,pos,cf,cs) except SkipThisVertex: msg = 'Warning: Lorentz structure {tag} ( {ps} ) in {name} ' \ 'is not supported, may have a non-perturbative form.\n'.format(tag=lorentztag, name=vertex.name, ps=' '.join(map(str,vertex.particles))) sys.stderr.write(msg) vertex.herwig_skip_vertex = True self.vertex_skipped=True return (True,"","") def extractGeneric(self,vertex,order,lorentztag,classname,plistarray,pos,lf,cf,cs) : classes="" headers="" # identify the maximum colour flow and orders of the couplings maxColour=0 couplingOrders=[] self.vertex_names[vertex.name] = [classname] for (color_idx,lorentz_idx),coupling in vertex.couplings.iteritems(): maxColour=max(maxColour,color_idx) orders = coupling_orders(vertex, coupling, self.couplingDefns) if(orders not in couplingOrders) : couplingOrders.append(orders) # loop the order of the couplings iorder = 0 for corder in couplingOrders : iorder +=1 cname=classname if(iorder!=1) : cname= "%s_%s" % (classname,iorder) self.vertex_names[vertex.name].append(cname) header = "" prepend="" append="" all_couplings=[] for ix in range(0,maxColour+1) : all_couplings.append([]) # loop over the colour structures for colour in range(0,maxColour+1) : for (color_idx,lorentz_idx),coupling in vertex.couplings.iteritems() : # check colour structure and coupling order if(color_idx!=colour) : continue if(coupling_orders(vertex, coupling, self.couplingDefns)!=corder) : continue # get the prefactor for the lorentz structure L = vertex.lorentz[lorentz_idx] prefactors = calculatePrefactor(lf,cf[color_idx]) # calculate the value of the coupling value = couplingValue(coupling) # handling of the different types of couplings if lorentztag in ['FFS','FFV']: all_couplings[color_idx] = fermionCouplings(value,prefactors,L,all_couplings[color_idx],order) elif 'T' in lorentztag : append, all_couplings[color_idx] = tensorCouplings(vertex,value,prefactors,L,lorentztag,pos, all_couplings[color_idx],order) elif 'R' in lorentztag : all_couplings[color_idx] = RSCouplings(value,prefactors,L,all_couplings[color_idx],order) elif lorentztag == 'VVS' or lorentztag == "VVSS" or lorentztag == "VSS" : all_couplings[color_idx] = scalarVectorCouplings(value,prefactors,L,lorentztag, all_couplings[color_idx],order) elif lorentztag == "SSS" or lorentztag == "SSSS" : prepend, header, all_couplings[color_idx] = scalarCouplings(vertex,value,prefactors,L,lorentztag, all_couplings[color_idx],prepend,header) elif "VVV" in lorentztag : all_couplings[color_idx],append = vectorCouplings(vertex,value,prefactors,L,lorentztag,pos, all_couplings[color_idx],append,corder["QCD"],order) else: raise SkipThisVertex() - # set the coupling ptrs in the setCoupling call - couplingptrs = self.setCouplingPtrs(lorentztag,corder["QCD"],append != '',prepend != '') # final processing of the couplings symbols = set() if(lorentztag in ['FFS','FFV']) : (normcontent,leftcontent,rightcontent,append) = processFermionCouplings(lorentztag,vertex, self.model,self.parmsubs, all_couplings,order) elif('T' in lorentztag) : (leftcontent,rightcontent,normcontent) = processTensorCouplings(lorentztag,vertex,self.model, self.parmsubs,all_couplings,order) elif(lorentztag=="SSS" or lorentztag=="SSSS") : normcontent = processScalarCouplings(self.model,self.parmsubs,all_couplings) elif(lorentztag=="VVS" or lorentztag =="VVSS" or lorentztag=="VSS") : normcontent,append,lorentztag,header,sym = processScalarVectorCouplings(lorentztag,vertex, self.model,self.parmsubs, all_couplings,header,order) symbols |=sym elif("VVV" in lorentztag) : normcontent,append,header =\ processVectorCouplings(lorentztag,vertex,self.model,self.parmsubs,all_couplings,append,header) else : SkipThisVertex() + # set the coupling ptrs in the setCoupling call + couplingptrs = self.setCouplingPtrs(lorentztag.replace("General",""), + corder["QCD"],append != '',prepend != '') ### do we need left/right? if 'FF' in lorentztag and lorentztag != "FFT": #leftcalc = aStoStrongCoup(py2cpp(leftcontent)[0], paramstoreplace_, paramstoreplace_expressions_) #rightcalc = aStoStrongCoup(py2cpp(rightcontent)[0], paramstoreplace_, paramstoreplace_expressions_) leftcalc, sym = py2cpp(leftcontent) symbols |= sym rightcalc, sym = py2cpp(rightcontent) symbols |= sym left = 'left(' + leftcalc + ');' right = 'right(' + rightcalc + ');' else: left = '' right = '' leftcalc = '' rightcalc = '' #normcalc = aStoStrongCoup(py2cpp(normcontent)[0], paramstoreplace_, paramstoreplace_expressions_) normcalc, sym = py2cpp(normcontent) symbols |= sym # UFO is GeV by default if lorentztag in ['VVS','SSS']: normcalc = 'Complex((%s) * GeV / UnitRemoval::E)' % normcalc elif lorentztag in ['GeneralVVS']: normcalc = 'Complex(-(%s) * UnitRemoval::E / GeV )' % normcalc elif lorentztag in ['FFT','VVT', 'SST', 'FFVT', 'VVVT' , 'VVVS' ]: normcalc = 'Complex((%s) / GeV * UnitRemoval::E)' % normcalc norm = 'norm(' + normcalc + ');' # finally special handling for eps tensors if(len(vertex.color)==1 and vertex.color[0].find("Epsilon")>=0) : couplingptrs, append = epsilonSign(vertex,couplingptrs,append) # define unkown symbols from the model symboldefs = [ def_from_model(self.model,s) for s in symbols ] couplingOrder="" for coupName,coupVal in corder.iteritems() : couplingOrder+=" orderInCoupling(CouplingType::%s,%s);\n" %(coupName,coupVal) ### assemble dictionary and fill template subs = { 'lorentztag' : lorentztag, # ok 'classname' : cname, # ok 'symbolrefs' : '\n '.join(symboldefs), 'left' : left, # doesn't always exist in base 'right' : right, # doesn't always exist in base 'norm' : norm, # needs norm, too 'addToPlist' : '\n'.join([ 'addToList(%s);'%s for s in plistarray]), 'parameters' : '', 'couplingOrders' : couplingOrder, 'colourStructure' : cs, 'couplingptrs' : ''.join(couplingptrs), 'spindirectory' : spindirectory(lorentztag), 'ModelName' : self.modelname, 'prepend' : prepend, 'append' : append, 'header' : header } # ok # print info if required if self.verbose: print '-'*60 pprint.pprint(( classname, plistarray, leftcalc, rightcalc, normcalc )) headers+=VERTEXHEADER.format(**subs) classes+=VERTEXCLASS.substitute(subs) return (False,classes,headers) def extractGeneral(self,vertex,order,lorentztag,classname,plistarray,pos,cf,cs) : eps=False classes="" headers="" # check the colour flows, three cases supported either 1 flow or 3 in gggg # or multiple wierd ones in FFFF cidx=-1 gluon4point = (len(pos[8])==4 and vertex.lorentz[0].spins.count(3)==4) FFFF = (len(pos[3])==2 and len(pos[-3])==2 and vertex.lorentz[0].spins.count(2)==4) couplingOrders=[] colours={} for (color_idx,lorentz_idx),coupling in vertex.couplings.iteritems() : orders = coupling_orders(vertex, coupling, self.couplingDefns) if(orders not in couplingOrders) : couplingOrders.append(orders) if(gluon4point) : color = vertex.color[color_idx] f = color.split("*") (o1,s1) = extractAntiSymmetricIndices(f[0],"f(") (o2,s2) = extractAntiSymmetricIndices(f[1],"f(") if(o2[0]<o1[0]) : o1,o2=o2,o1 color = "f(%s)*f(%s)" % (",".join(o1),",".join(o2)) label = 'f(1,3,-1)*f(2,4,-1)' if(label==color) : cidx=color_idx colours[cidx] = (cs,cf[cidx]) elif (FFFF) : colours[color_idx] = (cs[color_idx],cf[color_idx]) else : cidx=color_idx if(color_idx!=0) : vertex.herwig_skip_vertex = True self.vertex_skipped=True msg = 'Warning: General spin structure code currently only '\ 'supports 1 colour structure for {tag} ( {ps} ) in {name}\n'.format(tag=lorentztag, name=vertex.name, ps=' '.join(map(str,vertex.particles))) sys.stderr.write(msg) return (True,"","") if(isinstance(cs,basestring)) : colours[cidx] = (cs,cf[cidx]) else : vertex.herwig_skip_vertex = True self.vertex_skipped=True msg = 'Warning: General spin structure code currently only '\ 'supports 1 colour structure for {tag} ( {ps} ) in {name}\n'.format(tag=lorentztag, name=vertex.name, ps=' '.join(map(str,vertex.particles))) sys.stderr.write(msg) return (True,"","") if(len(colours)==0) : msg = 'Warning: General spin structure code currently only '\ 'supports 1 colour structure for {tag} ( {ps} ) in {name}\n'.format(tag=lorentztag, name=vertex.name, ps=' '.join(map(str,vertex.particles))) sys.stderr.write(msg) vertex.herwig_skip_vertex = True self.vertex_skipped=True return (True,"","") # loop over the different orders in the couplings # and colour structures iorder=0 self.vertex_names[vertex.name]=[classname] for corder in couplingOrders : for (cidx,(cstruct,cfactor)) in colours.iteritems() : iorder +=1 cname=classname if(iorder!=1) : cname= "%s_%s" % (classname,iorder) self.vertex_names[vertex.name].append(cname) defns=[] vertexEval=[] values=[] imax = len(vertex.particles)+1 if lorentztag in genericVertices : imax=1 for (color_idx,lorentz_idx),coupling in vertex.couplings.iteritems() : # only the colour structre and coupling order we want if(color_idx != cidx) : continue if(coupling_orders(vertex, coupling, self.couplingDefns)!=corder) : continue # calculate the value of the coupling values.append(couplingValue(coupling)) # now to convert the spin structures for i in range(0,imax) : if(len(defns)<i+1) : defns.append({}) vertexEval.append([]) eps |= convertLorentz(vertex.lorentz[lorentz_idx],lorentztag,order,vertex, i,defns[i],vertexEval[i]) # we can now generate the evaluate member functions header="" impls="" spins=vertex.lorentz[0].spins mult={} for i in range(1,6) : if( spins.count(i)>1 and i!=2) : mult[i] = [] for i in range(0,imax) : (evalHeader,evalCC) = generateEvaluateFunction(self.model,vertex,i,values,defns[i],vertexEval[i],cfactor,order) if(i!=0 and spins[i-1] in mult) : if(len(mult[spins[i-1]])==0) : mult[spins[i-1]].append(evalHeader) evalHeader=evalHeader.replace("evaluate(","evaluate%s(" % i) evalCC =evalCC .replace("evaluate(","evaluate%s(" % i) mult[spins[i-1]].append(evalHeader) header+=" "+evalHeader+";\n" impls+=evalCC # combine the multiple defn if needed for (key,val) in mult.iteritems() : (evalHeader,evalCC) = multipleEvaluate(vertex,key,val) if(evalHeader!="") : header += " "+evalHeader+";\n" if(evalCC!="") : impls += evalCC impls=impls.replace("evaluate", "FRModel%s::evaluate" % cname) couplingOrder="" for coupName,coupVal in corder.iteritems() : couplingOrder+=" orderInCoupling(CouplingType::%s,%s);\n" %(coupName,coupVal) ### assemble dictionary and fill template subs = { 'lorentztag' : lorentztag, 'classname' : cname, 'addToPlist' : '\n'.join([ 'addToList(%s);'%s for s in plistarray]), 'ModelName' : self.modelname, 'couplingOrders' : couplingOrder, 'colourStructure' : cstruct, 'evaldefs' : header, 'evalimpls' : impls} newHeader = GENERALVERTEXHEADER.format(**subs) if(eps) : newHeader +="#include \"ThePEG/Helicity/epsilon.h\"\n" headers+=newHeader classes+=GENERALVERTEXCLASS.substitute(subs) return (False,classes,headers) def get_vertices(self,libname): vlist = ['library %s\n' % libname] for v in self.all_vertices: if v.herwig_skip_vertex: continue for name in self.vertex_names[v.name] : vlist.append( vertexline.format(modelname=self.modelname, classname=name) ) if( not self.no_generic_loop_vertices) : vlist.append('insert {modelname}:ExtraVertices 0 /Herwig/{modelname}/V_GenericHPP\n'.format(modelname=self.modelname) ) vlist.append('insert {modelname}:ExtraVertices 0 /Herwig/{modelname}/V_GenericHGG\n'.format(modelname=self.modelname) ) return ''.join(vlist) diff --git a/Models/General/HardProcessConstructor.cc b/Models/General/HardProcessConstructor.cc --- a/Models/General/HardProcessConstructor.cc +++ b/Models/General/HardProcessConstructor.cc @@ -1,957 +1,958 @@ // -*- C++ -*- // // This is the implementation of the non-inlined, non-templated member // functions of the HardProcessConstructor class. // #include "HardProcessConstructor.h" #include "ThePEG/Utilities/DescribeClass.h" #include "ThePEG/Interface/ClassDocumentation.h" #include "ThePEG/Interface/Switch.h" #include "ThePEG/Persistency/PersistentOStream.h" #include "ThePEG/Persistency/PersistentIStream.h" using namespace Herwig; void HardProcessConstructor::persistentOutput(PersistentOStream & os) const { os << debug_ << subProcess_ << model_; } void HardProcessConstructor::persistentInput(PersistentIStream & is, int) { is >> debug_ >> subProcess_ >> model_; } // The following static variable is needed for the type // description system in ThePEG. DescribeAbstractClass<HardProcessConstructor,Interfaced> describeHerwigHardProcessConstructor("Herwig::HardProcessConstructor", "Herwig.so"); void HardProcessConstructor::Init() { static ClassDocumentation<HardProcessConstructor> documentation ("Base class for implementation of the automatic generation of hard processes"); static Switch<HardProcessConstructor,bool> interfaceDebugME ("DebugME", "Print comparison with analytical ME", &HardProcessConstructor::debug_, false, false, false); static SwitchOption interfaceDebugMEYes (interfaceDebugME, "Yes", "Print the debug information", true); static SwitchOption interfaceDebugMENo (interfaceDebugME, "No", "Do not print the debug information", false); } void HardProcessConstructor::doinit() { Interfaced::doinit(); EGPtr eg = generator(); model_ = dynamic_ptr_cast<HwSMPtr>(eg->standardModel()); if(!model_) throw InitException() << "HardProcessConstructor:: doinit() - " << "The model pointer is null!" << Exception::abortnow; if(!eg->eventHandler()) { throw InitException() << "HardProcessConstructor:: doinit() - " << "The eventHandler pointer was null therefore " << "could not get SubProcessHandler pointer " << Exception::abortnow; } string subProcessName = eg->preinitInterface(eg->eventHandler(), "SubProcessHandlers", "get",""); subProcess_ = eg->getObject<SubProcessHandler>(subProcessName); if(!subProcess_) { ostringstream s; s << "HardProcessConstructor:: doinit() - " << "There was an error getting the SubProcessHandler " << "from the current event handler. "; generator()->logWarning( Exception(s.str(), Exception::warning) ); } } GeneralHardME::ColourStructure HardProcessConstructor:: colourFlow(const tcPDVector & extpart) const { PDT::Colour ina = extpart[0]->iColour(); PDT::Colour inb = extpart[1]->iColour(); PDT::Colour outa = extpart[2]->iColour(); PDT::Colour outb = extpart[3]->iColour(); // incoming colour neutral if(ina == PDT::Colour0 && inb == PDT::Colour0) { if( outa == PDT::Colour0 && outb == PDT::Colour0 ) { return GeneralHardME::Colour11to11; } else if( outa == PDT::Colour3 && outb == PDT::Colour3bar ) { return GeneralHardME::Colour11to33bar; } else if( outa == PDT::Colour8 && outb == PDT::Colour8 ) { return GeneralHardME::Colour11to88; } else assert(false); } // incoming 3 3 else if(ina == PDT::Colour3 && inb == PDT::Colour3 ) { if( outa == PDT::Colour3 && outb == PDT::Colour3 ) { return GeneralHardME::Colour33to33; } else if( outa == PDT::Colour6 && outb == PDT::Colour0 ) { return GeneralHardME::Colour33to61; } else if( outa == PDT::Colour0 && outb == PDT::Colour6 ) { return GeneralHardME::Colour33to16; } else if ( outa == PDT::Colour0 && outb == PDT::Colour3bar) { return GeneralHardME::Colour33to13bar; } else if ( outb == PDT::Colour0 && outa == PDT::Colour3bar) { return GeneralHardME::Colour33to3bar1; } else if ( outa == PDT::Colour8 && outb == PDT::Colour3bar) { return GeneralHardME::Colour33to83bar; } else if ( outb == PDT::Colour8 && outa == PDT::Colour3bar) { return GeneralHardME::Colour33to3bar8; } else assert(false); } // incoming 3bar 3bar else if(ina == PDT::Colour3bar && inb == PDT::Colour3bar ) { if( outa == PDT::Colour3bar && outb == PDT::Colour3bar ) { return GeneralHardME::Colour3bar3barto3bar3bar; } else if( outa == PDT::Colour6bar && outb == PDT::Colour0) { return GeneralHardME::Colour3bar3barto6bar1; } else if ( outa == PDT::Colour0 && outb == PDT::Colour6bar ) { return GeneralHardME::Colour3bar3barto16bar; } else if ( outa == PDT::Colour0 && outb == PDT::Colour3) { return GeneralHardME::Colour3bar3barto13; } else if ( outb == PDT::Colour0 && outa == PDT::Colour3) { return GeneralHardME::Colour3bar3barto31; } else if ( outa == PDT::Colour8 && outb == PDT::Colour3) { return GeneralHardME::Colour3bar3barto83; } else if ( outb == PDT::Colour8 && outa == PDT::Colour3) { return GeneralHardME::Colour3bar3barto38; } else assert(false); } // incoming 3 3bar else if(ina == PDT::Colour3 && inb == PDT::Colour3bar ) { if( outa == PDT::Colour0 && outb == PDT::Colour0 ) { return GeneralHardME::Colour33barto11; } else if( outa == PDT::Colour3 && outb == PDT::Colour3bar ) { return GeneralHardME::Colour33barto33bar; } else if( outa == PDT::Colour8 && outb == PDT::Colour8 ) { return GeneralHardME::Colour33barto88; } else if( outa == PDT::Colour8 && outb == PDT::Colour0 ) { return GeneralHardME::Colour33barto81; } else if( outa == PDT::Colour0 && outb == PDT::Colour8 ) { return GeneralHardME::Colour33barto18; } else if( outa == PDT::Colour6 && outb == PDT::Colour6bar) { return GeneralHardME::Colour33barto66bar; } else if( outa == PDT::Colour6bar && outb == PDT::Colour6) { return GeneralHardME::Colour33barto6bar6; } else assert(false); } // incoming 88 else if(ina == PDT::Colour8 && inb == PDT::Colour8 ) { if( outa == PDT::Colour0 && outb == PDT::Colour0 ) { return GeneralHardME::Colour88to11; } else if( outa == PDT::Colour3 && outb == PDT::Colour3bar ) { return GeneralHardME::Colour88to33bar; } else if( outa == PDT::Colour8 && outb == PDT::Colour8 ) { return GeneralHardME::Colour88to88; } else if( outa == PDT::Colour8 && outb == PDT::Colour0 ) { return GeneralHardME::Colour88to81; } else if( outa == PDT::Colour0 && outb == PDT::Colour8 ) { return GeneralHardME::Colour88to18; } else if( outa == PDT::Colour6 && outb == PDT::Colour6bar ) { return GeneralHardME::Colour88to66bar; } else assert(false); } // incoming 38 else if(ina == PDT::Colour3 && inb == PDT::Colour8 ) { if(outa == PDT::Colour3 && outb == PDT::Colour0) { return GeneralHardME::Colour38to31; } else if(outa == PDT::Colour0 && outb == PDT::Colour3) { return GeneralHardME::Colour38to13; } else if(outa == PDT::Colour3 && outb == PDT::Colour8) { return GeneralHardME::Colour38to38; } else if(outa == PDT::Colour8 && outb == PDT::Colour3) { return GeneralHardME::Colour38to83; } else if(outa == PDT::Colour3bar && outb == PDT::Colour6){ return GeneralHardME::Colour38to3bar6; } else if(outa == PDT::Colour6 && outb == PDT::Colour3bar) { return GeneralHardME::Colour38to63bar; } else if(outa == PDT::Colour3bar && outb == PDT::Colour3bar) { return GeneralHardME::Colour38to3bar3bar; } else assert(false); } // incoming 3bar8 else if(ina == PDT::Colour3bar && inb == PDT::Colour8 ) { if(outa == PDT::Colour3bar && outb == PDT::Colour0 ) { return GeneralHardME::Colour3bar8to3bar1; } else if(outa == PDT::Colour0 && outb == PDT::Colour3bar) { return GeneralHardME::Colour3bar8to13bar; } else if(outa == PDT::Colour3bar && outb == PDT::Colour8 ) { return GeneralHardME::Colour3bar8to3bar8; } else if(outa == PDT::Colour8 && outb == PDT::Colour3bar) { return GeneralHardME::Colour3bar8to83bar; } else if(outa == PDT::Colour3 && outb == PDT::Colour3) { return GeneralHardME::Colour3bar8to33; } else assert(false); } // unknown colour flow else assert(false); return GeneralHardME::UNDEFINED; } void HardProcessConstructor::fixFSOrder(HPDiagram & diag) { tcPDPtr psa = getParticleData(diag.incoming.first); tcPDPtr psb = getParticleData(diag.incoming.second); tcPDPtr psc = getParticleData(diag.outgoing.first); tcPDPtr psd = getParticleData(diag.outgoing.second); //fix a spin order if( psc->iSpin() < psd->iSpin() ) { swap(diag.outgoing.first, diag.outgoing.second); if(diag.channelType == HPDiagram::tChannel) { diag.ordered.second = !diag.ordered.second; } return; } if( psc->iSpin() == psd->iSpin() && psc->id() < 0 && psd->id() > 0 ) { swap(diag.outgoing.first, diag.outgoing.second); if(diag.channelType == HPDiagram::tChannel) { diag.ordered.second = !diag.ordered.second; } return; } } void HardProcessConstructor::assignToCF(HPDiagram & diag) { if(diag.channelType == HPDiagram::tChannel) { if(diag.ordered.second) tChannelCF(diag); else uChannelCF(diag); } else if(diag.channelType == HPDiagram::sChannel) { sChannelCF(diag); } else if (diag.channelType == HPDiagram::fourPoint) { fourPointCF(diag); } else assert(false); } void HardProcessConstructor::tChannelCF(HPDiagram & diag) { tcPDPtr ia = getParticleData(diag.incoming.first ); tcPDPtr ib = getParticleData(diag.incoming.second); tcPDPtr oa = getParticleData(diag.outgoing.first ); tcPDPtr ob = getParticleData(diag.outgoing.second); PDT::Colour ina = ia->iColour(); PDT::Colour inb = ib->iColour(); PDT::Colour outa = oa->iColour(); PDT::Colour outb = ob->iColour(); vector<CFPair> cfv(1, make_pair(0, 1.)); if(diag.intermediate->iColour() == PDT::Colour0) { if(ina==PDT::Colour0) { cfv[0] = make_pair(0, 1); } else if(ina==PDT::Colour3 || ina==PDT::Colour3bar) { if( inb == PDT::Colour0 ) { cfv[0] = make_pair(0, 1); } else if(inb==PDT::Colour3 || outb==PDT::Colour3bar) { cfv[0] = make_pair(2, 1); } else if(inb==PDT::Colour8) { cfv[0] = make_pair(2, 1); } } else if(ina==PDT::Colour8) { if( inb == PDT::Colour0 ) { cfv[0] = make_pair(0, 1); } else if(inb==PDT::Colour3 || outb==PDT::Colour3bar) { cfv[0] = make_pair(2, 1); } else if(inb==PDT::Colour8) { cfv[0] = make_pair(7, -1); } } } else if(diag.intermediate->iColour() == PDT::Colour8) { if(ina==PDT::Colour8&&outa==PDT::Colour8&& inb==PDT::Colour8&&outb==PDT::Colour8) { cfv[0]=make_pair(2, 2.); cfv.push_back(make_pair(3, -2.)); cfv.push_back(make_pair(1, -2.)); cfv.push_back(make_pair(4, 2.)); } else if(ina==PDT::Colour8&&outa==PDT::Colour0&& inb==PDT::Colour8&&outb==PDT::Colour8&& (oa->iSpin()==PDT::Spin0||oa->iSpin()==PDT::Spin1Half|| oa->iSpin()==PDT::Spin3Half)) { cfv[0] = make_pair(0,-1); } else if(ina==PDT::Colour8&&outa==PDT::Colour8&& inb==PDT::Colour8&&outb==PDT::Colour0&& (ob->iSpin()==PDT::Spin0||ob->iSpin()==PDT::Spin1Half|| ob->iSpin()==PDT::Spin3Half)) { cfv[0] = make_pair(0,-1); } } else if(diag.intermediate->iColour() == PDT::Colour3 || diag.intermediate->iColour() == PDT::Colour3bar) { if(outa == PDT::Colour0 || outb == PDT::Colour0) { if( outa == PDT::Colour6 || outb == PDT::Colour6 || outa == PDT::Colour6bar || outb == PDT::Colour6bar) { cfv[0] = make_pair(0,0.5); cfv.push_back(make_pair(1,0.5)); } else if ((ina==PDT::Colour3 && inb == PDT::Colour3 && (outa == PDT::Colour3bar || outb == PDT::Colour3bar))|| (ina==PDT::Colour3bar && inb == PDT::Colour3bar && (outa == PDT::Colour3 || outb == PDT::Colour3 ))) { cfv[0] = make_pair(0,1.); } else { cfv[0] = make_pair(0,1.); } } else if(outa==PDT::Colour6 && outb==PDT::Colour3bar) { cfv[0] = make_pair(4,1.); cfv.push_back(make_pair(5,1.)); } else if(outa==PDT::Colour6 && outb==PDT::Colour6bar) { cfv[0] = make_pair(4, 1.); for(unsigned int ix=5;ix<8;++ix) cfv.push_back(make_pair(ix,1.)); } else if(outa==PDT::Colour6 || outa ==PDT::Colour6bar || outb==PDT::Colour6 || outb ==PDT::Colour6bar ) { assert(false); } else if(ina==PDT::Colour3 && inb==PDT::Colour3 ) { if((outa==PDT::Colour0 && outb==PDT::Colour3bar)|| (outb==PDT::Colour0 && outa==PDT::Colour3bar)) cfv[0] = make_pair(0,1.); else if((outa==PDT::Colour8 && outb==PDT::Colour3bar)|| (outb==PDT::Colour8 && outa==PDT::Colour3bar)) { cfv[0] = make_pair(1,1.); } } else if(ina==PDT::Colour3bar && inb==PDT::Colour3bar ) { if((outa==PDT::Colour0 && outb==PDT::Colour3)|| (outb==PDT::Colour0 && outa==PDT::Colour3)) cfv[0] = make_pair(0,1.); else if((outa==PDT::Colour8 && outb==PDT::Colour3)|| (outb==PDT::Colour8 && outa==PDT::Colour3)) { double sign = diag.intermediate->iSpin()==PDT::Spin0 ? -1. : 1.; cfv[0] = make_pair(1,sign); } } else if((ina==PDT::Colour3 && inb==PDT::Colour8) || (ina==PDT::Colour3bar && inb==PDT::Colour8) || (inb==PDT::Colour3 && ina==PDT::Colour8) || (inb==PDT::Colour3bar && ina==PDT::Colour8) ) { if((outa==PDT::Colour3 && outb==PDT::Colour3 ) || (outa==PDT::Colour3bar && outb==PDT::Colour3bar)) { cfv[0] = make_pair(1,1.); } } } else if(diag.intermediate->iColour() == PDT::Colour6 || diag.intermediate->iColour() == PDT::Colour6bar) { if(ina==PDT::Colour8 && inb==PDT::Colour8) { cfv[0] = make_pair(0, 1.); for(unsigned int ix=1;ix<4;++ix) cfv.push_back(make_pair(ix,1.)); for(unsigned int ix=4;ix<8;++ix) cfv.push_back(make_pair(ix,1.)); } else if(outa==PDT::Colour3bar && outb==PDT::Colour6) { cfv[0] = make_pair(0,1.); for(unsigned int ix=1;ix<4;++ix) cfv.push_back(make_pair(ix,1.)); } else if(outa==PDT::Colour6 && outb==PDT::Colour3bar) { cfv[0] = make_pair(4,1.); cfv.push_back(make_pair(5,1.)); } } diag.colourFlow = cfv; } void HardProcessConstructor::uChannelCF(HPDiagram & diag) { tcPDPtr ia = getParticleData(diag.incoming.first ); tcPDPtr ib = getParticleData(diag.incoming.second); tcPDPtr oa = getParticleData(diag.outgoing.first ); tcPDPtr ob = getParticleData(diag.outgoing.second); PDT::Colour ina = ia->iColour(); PDT::Colour inb = ib->iColour(); PDT::Colour outa = oa->iColour(); PDT::Colour outb = ob->iColour(); PDT::Colour offshell = diag.intermediate->iColour(); vector<CFPair> cfv(1, make_pair(1, 1.)); if(offshell == PDT::Colour8) { if(outa == PDT::Colour0 && outb == PDT::Colour0) { cfv[0].first = 0; } else if( outa != outb ) { if(outa == PDT::Colour0 || outb == PDT::Colour0) { cfv[0].first = 0; } else if(ina == PDT::Colour3 && inb == PDT::Colour8 && outb == PDT::Colour3 && outa == PDT::Colour8) { tPDPtr off = diag.intermediate; if(off->CC()) off=off->CC(); if(off->iSpin()!=PDT::Spin1Half || diag.vertices.second->allowed(off->id(),diag.outgoing.first,diag.incoming.second)) { cfv[0].first = 0; cfv.push_back(make_pair(1, -1.)); } else { cfv[0].first = 1; cfv.push_back(make_pair(0, -1.)); } } else if(ina == PDT::Colour3bar && inb == PDT::Colour8 && outb == PDT::Colour3bar && outa == PDT::Colour8) { tPDPtr off = diag.intermediate; if(off->CC()) off=off->CC(); if(off->iSpin()!=PDT::Spin1Half || diag.vertices.second->allowed(diag.outgoing.first,off->id(),diag.incoming.second)) { cfv[0].first = 0; cfv.push_back(make_pair(1, -1.)); } else { cfv[0].first = 1; cfv.push_back(make_pair(0, -1.)); } } else { cfv[0].first = 0; cfv.push_back(make_pair(1, -1.)); } } else if(outa==PDT::Colour8&&ina==PDT::Colour8) { cfv[0]=make_pair(4, 2.); cfv.push_back(make_pair(5, -2.)); cfv.push_back(make_pair(0, -2.)); cfv.push_back(make_pair(2, 2.)); } } else if(offshell == PDT::Colour3 || offshell == PDT::Colour3bar) { if( outa == PDT::Colour0 || outb == PDT::Colour0 ) { if( outa == PDT::Colour6 || outb == PDT::Colour6 || outa == PDT::Colour6bar || outb == PDT::Colour6bar) { cfv[0] = make_pair(0,0.5); cfv.push_back(make_pair(1,0.5)); } else if ((ina==PDT::Colour3 && inb == PDT::Colour3 && (outa == PDT::Colour3bar || outb == PDT::Colour3bar))|| (ina==PDT::Colour3bar && inb == PDT::Colour3bar && (outa == PDT::Colour3 || outb == PDT::Colour3 ))) { double sign = diag.intermediate->iSpin()==PDT::Spin0 ? -1. : 1.; cfv[0] = make_pair(0,sign); } else { cfv[0] = make_pair(0,1.); } } else if(outa==PDT::Colour3bar && outb==PDT::Colour6) { cfv[0] = make_pair(4,1.); cfv.push_back(make_pair(5,1.)); } else if(outa==PDT::Colour6 && outb==PDT::Colour3bar) { cfv[0] = make_pair(0,1.); for(int ix=0; ix<4;++ix) cfv.push_back(make_pair(ix,1.)); } else if(outa==PDT::Colour6bar && outb==PDT::Colour6) { cfv[0] = make_pair(4,1.); for(int ix=5; ix<8;++ix) cfv.push_back(make_pair(ix,1.)); } else if(ina==PDT::Colour0 && inb==PDT::Colour0) { cfv[0] = make_pair(0,1.); } else if(ina==PDT::Colour3 && inb==PDT::Colour3 ) { if((outa==PDT::Colour0 && outb==PDT::Colour3bar)|| (outb==PDT::Colour0 && outa==PDT::Colour3bar)) cfv[0] = make_pair(0,1.); else if((outa==PDT::Colour8 && outb==PDT::Colour3bar)|| (outb==PDT::Colour8 && outa==PDT::Colour3bar)) { double sign = diag.intermediate->iSpin()==PDT::Spin0 ? -1. : 1.; cfv[0] = make_pair(2,sign); } } else if(ina==PDT::Colour3bar && inb==PDT::Colour3bar ) { if((outa==PDT::Colour0 && outb==PDT::Colour3)|| (outb==PDT::Colour0 && outa==PDT::Colour3)) cfv[0] = make_pair(0,1.); else if((outa==PDT::Colour8 && outb==PDT::Colour3)|| (outb==PDT::Colour8 && outa==PDT::Colour3)) { cfv[0] = make_pair(2,1.); } } else if(((ina==PDT::Colour3 && inb==PDT::Colour8) || (ina==PDT::Colour3bar && inb==PDT::Colour8) || (inb==PDT::Colour3 && ina==PDT::Colour8) || (inb==PDT::Colour3bar && ina==PDT::Colour8)) && ((outa==PDT::Colour3 && outb==PDT::Colour3 ) || (outa==PDT::Colour3bar && outb==PDT::Colour3bar))) { cfv[0] = make_pair(2, 1.); } else if(( ina==PDT::Colour3 && inb==PDT::Colour3bar && outa==PDT::Colour3 && outb==PDT::Colour3bar)) { cfv[0] = make_pair(2, 1.); cfv.push_back(make_pair(3,-1.)); } } else if( offshell == PDT::Colour0 ) { if(ina==PDT::Colour0) { cfv[0] = make_pair(0, 1); } else if(ina==PDT::Colour3 || ina==PDT::Colour3bar) { if( inb == PDT::Colour0 ) { cfv[0] = make_pair(0, 1); } else if(inb==PDT::Colour3 || inb==PDT::Colour3bar) { cfv[0] = make_pair(3, 1); } else if(inb==PDT::Colour8) { cfv[0] = make_pair(2, 1); } } else if(ina==PDT::Colour8) { if( inb == PDT::Colour0 ) { cfv[0] = make_pair(0, 1); } else if(inb==PDT::Colour3 || outb==PDT::Colour3bar) { cfv[0] = make_pair(2, 1); } else if(inb==PDT::Colour8) { cfv[0] = make_pair(8, -1); } } } else if(diag.intermediate->iColour() == PDT::Colour6 || diag.intermediate->iColour() == PDT::Colour6bar) { if(ina==PDT::Colour8 && inb==PDT::Colour8) { cfv[0] = make_pair(0, 1.); for(unsigned int ix=1;ix<4;++ix) cfv.push_back(make_pair(ix,1.)); for(unsigned int ix=8;ix<12;++ix) cfv.push_back(make_pair(ix,1.)); } else if(outa==PDT::Colour3bar && outa==PDT::Colour6) { cfv[0] = make_pair(4, 1.); cfv.push_back(make_pair(5,1.)); } else if(outa==PDT::Colour6 && outa==PDT::Colour3bar) { cfv[0] = make_pair(0, 1.); for(unsigned int ix=1;ix<4;++ix) cfv.push_back(make_pair(ix,1.)); } } diag.colourFlow = cfv; } void HardProcessConstructor::sChannelCF(HPDiagram & diag) { tcPDPtr pa = getParticleData(diag.incoming.first); tcPDPtr pb = getParticleData(diag.incoming.second); PDT::Colour ina = pa->iColour(); PDT::Colour inb = pb->iColour(); PDT::Colour offshell = diag.intermediate->iColour(); tcPDPtr pc = getParticleData(diag.outgoing.first); tcPDPtr pd = getParticleData(diag.outgoing.second); PDT::Colour outa = pc->iColour(); PDT::Colour outb = pd->iColour(); vector<CFPair> cfv(1); if(offshell == PDT::Colour8) { if(ina == PDT::Colour0 || inb == PDT::Colour0 || outa == PDT::Colour0 || outb == PDT::Colour0) { cfv[0] = make_pair(0, 1); } else { bool incol = ina == PDT::Colour8 && inb == PDT::Colour8; bool outcol = outa == PDT::Colour8 && outb == PDT::Colour8; bool intrip = ina == PDT::Colour3 && inb == PDT::Colour3bar; bool outtrip = outa == PDT::Colour3 && outb == PDT::Colour3bar; bool outsex = outa == PDT::Colour6 && outb == PDT::Colour6bar; bool outsexb = outa == PDT::Colour6bar && outb == PDT::Colour6; if(incol || outcol) { // Require an additional minus sign for a scalar/fermion // 33bar final state due to the way the vertex rules are defined. int prefact(1); if( ((pc->iSpin() == PDT::Spin1Half && pd->iSpin() == PDT::Spin1Half) || - (pc->iSpin() == PDT::Spin0 && pd->iSpin() == PDT::Spin0 )) && + (pc->iSpin() == PDT::Spin0 && pd->iSpin() == PDT::Spin0 ) || + (pc->iSpin() == PDT::Spin1 && pd->iSpin() == PDT::Spin1 )) && (outa == PDT::Colour3 && outb == PDT::Colour3bar) ) prefact = -1; if(incol && outcol) { cfv[0] = make_pair(0, -2.); cfv.push_back(make_pair(1, 2.)); cfv.push_back(make_pair(3, 2.)); cfv.push_back(make_pair(5, -2.)); } else if(incol && outsex) { cfv[0].first = 4; cfv[0].second = prefact; for(unsigned int ix=1;ix<4;++ix) cfv.push_back(make_pair(4+ix, prefact)); for(unsigned int ix=0;ix<4;++ix) cfv.push_back(make_pair(8+ix,-prefact)); } else { cfv[0].first = 0; cfv[0].second = -prefact; cfv.push_back(make_pair(1, prefact)); } } else if( ( intrip && !outtrip ) || ( !intrip && outtrip ) ) { if(!outsex) cfv[0] = make_pair(0, 1); else { cfv[0] = make_pair(0, 1.); for(unsigned int ix=0;ix<3;++ix) cfv.push_back(make_pair(ix+1, 1.)); } } else if((intrip && outsex) || (intrip && outsexb)) { cfv[0] = make_pair(0,1.); for(int ix=1; ix<4; ++ix) cfv.push_back(make_pair(ix,1.)); } else cfv[0] = make_pair(1, 1); } } else if(offshell == PDT::Colour0) { if( ina == PDT::Colour0 ) { cfv[0] = make_pair(0, 1); } else if(ina==PDT::Colour3 || ina==PDT::Colour3bar) { if( outa == PDT::Colour0 ) { cfv[0] = make_pair(0, 1); } else if(outa==PDT::Colour3 || outa==PDT::Colour3bar) { cfv[0] = make_pair(3, 1); } else if(outa==PDT::Colour8) { cfv[0] = make_pair(2, 1); } else if(outa==PDT::Colour6 || outa==PDT::Colour6bar) { cfv[0] = make_pair(8, 1.); cfv.push_back(make_pair(9,1.)); } else assert(false); } else if(ina==PDT::Colour8) { if( outa == PDT::Colour0 ) { cfv[0] = make_pair(0, 1); } else if(outa==PDT::Colour3 || outb==PDT::Colour3bar) { cfv[0] = make_pair(2, 1); } else if(outa==PDT::Colour8) { cfv[0] = make_pair(6, 1); } } } else if(offshell == PDT::Colour3 || offshell == PDT::Colour3bar) { if(outa == PDT::Colour6 || outa == PDT::Colour6bar || outb == PDT::Colour6bar || outb == PDT::Colour6) { cfv[0] = make_pair(6, 1.); cfv.push_back(make_pair(7,1.)); } else if((ina == PDT::Colour3 && inb == PDT::Colour3) || (ina == PDT::Colour3bar && inb == PDT::Colour3bar)) { if((outa == PDT::Colour3 && outb == PDT::Colour3 ) || (outa == PDT::Colour3bar && outb == PDT::Colour3bar)) { cfv[0] = make_pair(2, 1.); cfv.push_back(make_pair(3,-1.)); } else cfv[0] = make_pair(0,1.); } else if(((ina==PDT::Colour3 && inb==PDT::Colour8) || (ina==PDT::Colour3bar && inb==PDT::Colour8) || (inb==PDT::Colour3 && ina==PDT::Colour8) || (inb==PDT::Colour3bar && ina==PDT::Colour8) ) && ((outa==PDT::Colour3 && outb==PDT::Colour3 ) || (outa==PDT::Colour3bar && outb==PDT::Colour3bar))) { cfv[0] = make_pair(0,1.); } else { if(outa == PDT::Colour0 || outb == PDT::Colour0) cfv[0] = make_pair(0, 1); else cfv[0] = make_pair(1, 1); } } else if( offshell == PDT::Colour6 || offshell == PDT::Colour6bar) { if((ina == PDT::Colour3 && inb == PDT::Colour3 && outa == PDT::Colour3 && outb == PDT::Colour3 ) || (ina == PDT::Colour3bar && inb == PDT::Colour3bar && outa == PDT::Colour3bar && outb == PDT::Colour3bar)) { cfv[0] = make_pair(2,0.5); cfv.push_back(make_pair(3,0.5)); } else if((ina == PDT::Colour3 && inb == PDT::Colour3 && ((outa == PDT::Colour6 && outb == PDT::Colour0)|| (outb == PDT::Colour6 && outa == PDT::Colour0))) || (ina == PDT::Colour3bar && inb == PDT::Colour3bar && ((outa == PDT::Colour6bar && outb == PDT::Colour0)|| (outb == PDT::Colour6bar && outa == PDT::Colour0)))) { cfv[0] = make_pair(0,0.5); cfv.push_back(make_pair(1,0.5)); } else assert(false); } else { if(outa == PDT::Colour0 || outb == PDT::Colour0) cfv[0] = make_pair(0, 1); else cfv[0] = make_pair(1, 1); } diag.colourFlow = cfv; } void HardProcessConstructor::fourPointCF(HPDiagram & diag) { using namespace ThePEG::Helicity; // count the colours unsigned int noct(0),ntri(0),nsng(0),nsex(0),nf(0); vector<tcPDPtr> particles; for(unsigned int ix=0;ix<4;++ix) { particles.push_back(getParticleData(diag.ids[ix])); PDT::Colour col = particles.back()->iColour(); if(col==PDT::Colour0) ++nsng; else if(col==PDT::Colour3||col==PDT::Colour3bar) ++ntri; else if(col==PDT::Colour8) ++noct; else if(col==PDT::Colour6||col==PDT::Colour6bar) ++nsex; if(particles.back()->iSpin()==2) nf+=1; } if(nsng==4 || (ntri==2&&nsng==2) || (noct==3 && nsng==1) || (ntri==2 && noct==1 && nsng==1) || (noct == 2 && nsng == 2) ) { vector<CFPair> cfv(1,make_pair(0,1)); diag.colourFlow = cfv; } else if(noct==4) { // flows for SSVV, VVVV is handled in me class vector<CFPair> cfv(6); cfv[0] = make_pair(0, -2.); cfv[1] = make_pair(1, -2.); cfv[2] = make_pair(2, +4.); cfv[3] = make_pair(3, -2.); cfv[4] = make_pair(4, +4.); cfv[5] = make_pair(5, -2.); diag.colourFlow = cfv; } else if(ntri==2&&noct==2) { vector<CFPair> cfv(2); cfv[0] = make_pair(0, 1); cfv[1] = make_pair(1, 1); if(nf==2) cfv[1].second = -1.; diag.colourFlow = cfv; } else if(nsex==2&&noct==2) { vector<CFPair> cfv; for(unsigned int ix=0;ix<4;++ix) cfv.push_back(make_pair(ix ,2.)); for(unsigned int ix=0;ix<8;++ix) cfv.push_back(make_pair(4+ix,1.)); diag.colourFlow = cfv; } else if(ntri==4) { // get the order from the vertex vector<long> temp; for(unsigned int ix=0;ix<4;++ix) { temp = diag.vertices.first->search(ix,diag.outgoing.first); if(!temp.empty()) break; } // compute the mapping vector<long> ids; ids.push_back( particles[0]->CC() ? -diag.incoming.first : diag.incoming.first ); ids.push_back( particles[1]->CC() ? -diag.incoming.second : diag.incoming.second); ids.push_back( diag.outgoing.first ); ids.push_back( diag.outgoing.second); vector<unsigned int> order = {0,1,2,3}; vector<bool> matched(4,false); for(unsigned int ix=0;ix<temp.size();++ix) { for(unsigned int iy=0;iy<ids.size();++iy) { if(matched[iy]) continue; if(temp[ix]==ids[iy]) { matched[iy] = true; order[ix]=iy; break; } } } // 3 3 -> 3 3 if((particles[0]->iColour()==PDT::Colour3 && particles[1]->iColour()==PDT::Colour3) || (particles[0]->iColour()==PDT::Colour3bar && particles[1]->iColour()==PDT::Colour3bar) ) { if(diag.vertices.first->colourStructure()==ColourStructure::SU3I12I34) { if( (order[0]==0 && order[1]==2) || (order[2]==0 && order[3]==2) || (order[0]==2 && order[1]==0) || (order[2]==2 && order[3]==0)) diag.colourFlow = vector<CFPair>(1,make_pair(2,1.)); else diag.colourFlow = vector<CFPair>(1,make_pair(3,1.)); } else if(diag.vertices.first->colourStructure()==ColourStructure::SU3I14I23) { if( (order[0]==0 && order[3]==2) || (order[1]==0 && order[2]==2) || (order[0]==2 && order[3]==0) || (order[1]==2 && order[2]==0)) diag.colourFlow = vector<CFPair>(1,make_pair(2,1.)); else diag.colourFlow = vector<CFPair>(1,make_pair(3,1.)); } else if(diag.vertices.first->colourStructure()==ColourStructure::SU3T21T43) { if( (order[1]==0 && order[0]==2) || (order[3]==0 && order[2]==2) || (order[1]==2 && order[0]==0) || (order[3]==2 && order[2]==0)) diag.colourFlow = vector<CFPair>(1,make_pair(0,1.)); else diag.colourFlow = vector<CFPair>(1,make_pair(1,1.)); } else if(diag.vertices.first->colourStructure()==ColourStructure::SU3T23T41) { if( (order[1]==0 && order[2]==2) || (order[3]==0 && order[0]==2) || (order[1]==2 && order[2]==0) || (order[3]==2 && order[0]==0)) diag.colourFlow = vector<CFPair>(1,make_pair(0,1.)); else diag.colourFlow = vector<CFPair>(1,make_pair(1,1.)); } else assert(false); } else if((particles[0]->iColour()==PDT::Colour3 && particles[1]->iColour()==PDT::Colour3bar) | (particles[0]->iColour()==PDT::Colour3bar && particles[1]->iColour()==PDT::Colour3)) { if(diag.vertices.first->colourStructure()==ColourStructure::SU3I12I34) { if( (order[0]==0 && order[1]==1) || (order[2]==0 && order[3]==0) || (order[0]==1 && order[1]==0) || (order[2]==1 && order[3]==1)) diag.colourFlow = vector<CFPair>(1,make_pair(3,1.)); else diag.colourFlow = vector<CFPair>(1,make_pair(2,1.)); } else if(diag.vertices.first->colourStructure()==ColourStructure::SU3I14I23) { if( (order[0]==0 && order[3]==1) || (order[0]==2 && order[3]==3) || (order[0]==1 && order[3]==0) || (order[0]==3 && order[3]==2)) diag.colourFlow = vector<CFPair>(1,make_pair(3,1.)); else diag.colourFlow = vector<CFPair>(1,make_pair(2,1.)); } else if(diag.vertices.first->colourStructure()==ColourStructure::SU3T21T43) { if( (order[1]==0 && order[0]==1) || (order[3]==0 && order[2]==1) || (order[1]==1 && order[0]==0) || (order[3]==1 && order[2]==0)) diag.colourFlow = vector<CFPair>(1,make_pair(1,1.)); else diag.colourFlow = vector<CFPair>(1,make_pair(0,1.)); } else if(diag.vertices.first->colourStructure()==ColourStructure::SU3T23T41) { if( (order[1]==0 && order[2]==1) || (order[1]==1 && order[2]==0) || (order[1]==3 && order[2]==2) || (order[1]==2 && order[2]==3)) diag.colourFlow = vector<CFPair>(1,make_pair(1,1.)); else diag.colourFlow = vector<CFPair>(1,make_pair(2,1.)); } else assert(false); } else { assert(false); } } else { assert(false); } } namespace { // Helper functor for find_if in duplicate function. class SameDiagramAs { public: SameDiagramAs(const HPDiagram & diag) : a(diag) {} bool operator()(const HPDiagram & b) const { return a == b; } private: HPDiagram a; }; } bool HardProcessConstructor::duplicate(const HPDiagram & diag, const HPDVector & group) const { //find if a duplicate diagram exists HPDVector::const_iterator it = find_if(group.begin(), group.end(), SameDiagramAs(diag)); return it != group.end(); } bool HardProcessConstructor::checkOrder(const HPDiagram & diag) const { for(map<string,pair<unsigned int,int> >::const_iterator it=model_->couplings().begin(); it!=model_->couplings().end();++it) { int order=0; if(diag.vertices.first ) order += diag.vertices.first ->orderInCoupling(it->second.first); if(diag.vertices.second&&diag.vertices.first->getNpoint()==3) order += diag.vertices.second->orderInCoupling(it->second.first); if(order>it->second.second) return false; } return true; }