Skip to content

Commit

Permalink
Merge branch 'master' into dependabot/github_actions/dependabot/fetch…
Browse files Browse the repository at this point in the history
…-metadata-2.1.0
  • Loading branch information
APN-Pucky authored May 28, 2024
2 parents a99cbb8 + f53a1ee commit 9410c25
Show file tree
Hide file tree
Showing 17 changed files with 970 additions and 23 deletions.
17 changes: 17 additions & 0 deletions CITATION.cff
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
cff-version: 1.2.0
title: 'feynamp'
version: 0.0.10
abstract: Convert feynml Feynman diagrams to sympy amplitudes.
message: If you use this software, please cite it using these metadata.
authors:
- family-names: Neuwirth
given-names: Alexander Puck
orcid: "https://orcid.org/0000-0002-2484-1328"
date-released: '2024-04-30'
doi: 10.5281/zenodo.11091562
license: GPL-3.0-only
type: software
identifiers:
- description: Zenodo release
type: doi
value: "10.5281/zenodo.11091562"
551 changes: 551 additions & 0 deletions debug/ee->qq_.ipynb

Large diffs are not rendered by default.

19 changes: 17 additions & 2 deletions feynamp/form/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import form
import sympy
from feynml.feynmandiagram import FeynmanDiagram
from feynml.leg import Leg
from feynmodel.feyn_model import FeynModel

import feynamp.amplitude as amplitude
Expand All @@ -19,12 +20,24 @@
get_mandelstamm,
get_onshell,
)
from feynamp.leg import get_leg_momentum
from feynamp.log import debug

# TODO compute squared functino which coutns legs!!"!!!" and picks right mandelstamm,s


def compute_squared(fds: List[FeynmanDiagram], fm: FeynModel, tag=False):
# def compute_squared(fds: List[FeynmanDiagram], fm: FeynModel, tag=False):
# return compute_squared_correlated(
# fds, fm, colorcorrelated=False, tag=tag
# )


def compute_squared(
fds: List[FeynmanDiagram],
fm: FeynModel,
colorcorrelated=False,
tag=False,
):
assert len(fds) > 0, "No FeynmanDiagrams to compute"
dims = fds[0].get_externals_size()
for fd in fds:
Expand All @@ -34,7 +47,9 @@ def compute_squared(fds: List[FeynmanDiagram], fm: FeynModel, tag=False):
s2 = amplitude.square_parallel(fds, fm, tag=tag)
debug(f"{s2=}")

s2 = apply_color_parallel(s2)
s2 = apply_color_parallel(
s2, fds=fds, legs=fds[0].legs, model=fm, colorcorrelation=colorcorrelated
)

fs = ""
fs += get_metrics()
Expand Down
111 changes: 105 additions & 6 deletions feynamp/form/color.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
from typing import List

from feynamp.form.form import init, run, run_parallel, string_to_form
from feynamp.form.form import get_dummy_index, init, run, run_parallel, string_to_form
from feynamp.leg import (
color_vector_to_id,
color_vector_to_index,
color_vector_to_operator,
get_color_vector,
get_leg_momentum,
is_swapped_color_vector,
)
from feynamp.log import debug

from .colorh import colorh

Expand All @@ -13,7 +22,7 @@
color_init = """
AutoDeclare Index Color;
AutoDeclare Index Glu;
Tensors f(antisymmetric);
Tensors f(antisymmetric), colorcorrelation;
CFunctions T;
Symbols NA,I2R;
"""
Expand All @@ -36,6 +45,10 @@
"""

colorh_ids = """
* https://www.nikhef.nl/~form/maindir/packages/color/color.pdf
* Appendix D
id d33(cOlpR1,cOlpR2) = I2R^3/(2*Nc)*(Nc^2-1)*(Nc^2-4);
id d44(cOlpR1,cOlpR2) = I2R^4/(6*Nc^2)*(Nc^2-1)*(Nc^4-6*Nc^2+18);
repeat;
* remove df(k,j)
id df(k?,l?)*df(l?,j?)=df(k,j);
Expand Down Expand Up @@ -112,9 +125,92 @@ def rep(s: str):
"""


def get_color():
repeat = rep


def get_color(fds=None, legs=None, model=None, colorcorrelation=False, s2=None):
assert not colorcorrelation or (
fds is not None and legs is not None and model is not None
)
# return get_color_v1()
return get_color_v2()
return get_color_v3(fds, legs, model, colorcorrelation=colorcorrelation, s2=s2)


def get_full_color_correlation_matrix(fds, legs, model, s2):

left = ""
right = ""
vec = []
ops = []
ind = []
ind1 = []
ind2 = []
mom = []
swap = []
ids = []
for i in range(len(legs)):
swap += [is_swapped_color_vector(fds[0], legs[i], model, s2)]
vec += [get_color_vector(fds[0], legs[i], model)]
ids += [color_vector_to_id(vec[i])]
mom += [get_leg_momentum(legs[i])]
ops += [("(-1)*" if swap[i] else "") + str(color_vector_to_operator(vec[i]))]
ind += [color_vector_to_index(vec[i])]
ind1 += [str(ind[i]) + legs[i].id]
ind2 += [str(ind[i]) + get_dummy_index(underscore=False, questionmark=False)]
dummy = "Glu" + get_dummy_index(underscore=False, questionmark=False)
for i in range(len(legs)):
if vec[i] is not None:
i1 = ind1[i] + " "
i2 = ind2[i] + "?"
if swap[i]:
i1, i2 = i2, i1
left += f"{vec[i]}({i1},{mom[i]})*{vec[i]}({i2},{mom[i]})*"
i1, i2 = i1[:-1], i2[:-1]
for j in range(i + 1, len(legs)):
if vec[j] is not None:

j1 = ind1[j]
j2 = ind2[j]
if swap[j]:
j1, j2 = j2, j1
deltas = "*"
for k in range(len(legs)):
if vec[k] is not None and i != k and j != k:
deltas += f"{ids[k]}({ind1[k]},{ind2[k]})*"
right += f"\ncolorcorrelation({mom[i]},{mom[j]})*{ops[i]}({i1},{i2},{dummy})*{ops[j]}({j1},{j2},{dummy}){deltas[:-1]}+"
# right += f"\n{ops[i]}({i1},{i2},{dummy})*{ops[j]}({j1},{j2},{dummy}){deltas[:-1]}+"
# right += f"\ncolorcorrelation({mom[i]},{mom[j]})*d_({i1},{i2})*d_({j1},{j2}){deltas[:-1]}+"
# The minus sign below is from https://arxiv.org/pdf/1002.2581 Eq. 2.6
ret = f"""
id {left[:-1]} = -({right[:-1]});
"""
print(ret)
return ret


def get_color_sum_v1(mom1=None, mom2=None):
ret = ""
if mom1 is not None and mom2 is not None:
# new index that is summed over
dummy = "Glu" + get_dummy_index()
ret += repeat(
f"""
id VA(Glua?,{mom1})*VA(Gluc?,{mom1}) = f(Glua,Gluc,{dummy});
id VA(Glua?,{mom2})*VA(Gluc?,{mom2}) = f(Glua,Gluc,{dummy});
id VC(Colora?,{mom1})*VC(Colorc?,{mom1}) = T(Colora,Colorc,{dummy});
id VC(Colora?,{mom2})*VC(Colorc?,{mom2}) = T(Colora,Colorc,{dummy});
"""
)
return ret + color_sum


def get_color_v3(fds, legs, model, colorcorrelation=False, s2=None):
ret = ""
if colorcorrelation:
ret += get_full_color_correlation_matrix(fds, legs, model, s2=s2)
else:
ret += color_sum
return ret + colorh_ids + color + colorh_ids + rep(color_simplify)


def get_color_v2():
Expand All @@ -134,9 +230,12 @@ def apply_color_ids(string_expr):
return run(init + colorh_init + f"Local TMP = {s};" + get_color_ids())


def apply_color_parallel(string_exprs: List[str]):
def apply_color_parallel(string_exprs: List[str], **kwargs):
return run_parallel(
init + colorh_init, get_color(), [string_to_form(a) for a in string_exprs]
init + colorh_init,
# we only forward one
get_color(s2=string_exprs[0], **kwargs),
[string_to_form(a) for a in string_exprs],
)


Expand Down
32 changes: 20 additions & 12 deletions feynamp/form/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,38 @@
AutoDeclare Index Mu,Spin,Pol,Propagator;
AutoDeclare Symbol Mass,fd,mss,mst,msu;
AutoDeclare Vector Mom;
Tensors colorcorrelation;
Tensors Metric(symmetric),df(symmetric),da(symmetric),Identity(symmetric);
Function ProjM,ProjP,VF,xg,xgi,P,dg,dgi,xeg,xegi;
CFunctions Den,Denom,P,Gamma,u,v,ubar,vbar,eps,epsstar,VC,VA,GammaId, GammaCollect, GammaIdCollect;
Indices a,o,n,m,tm,tn,beta,b,m,betap,alphap,a,alpha,ind,delta,k,j,l,c,d,e;
"""


def get_dummy_index():
def get_dummy_index(underscore=True, questionmark=True):
global dummy
dummy = dummy + 1
return f"N{dummy}_?"
return f"N{dummy}" + ("_" if underscore else "") + ("?" if questionmark else "")


def string_to_form(s):
s = re.sub(r"complex\((.*?),(.*?)\)", r"(\1+i_*(\2))", s)
# s = s.replace("complex(0,1)", "i_") # form uses i_ for imaginary unit
s = s.replace("Gamma_Id", "GammaId")
s = s.replace("u_bar", "ubar")
s = s.replace("v_bar", "vbar")
s = s.replace("eps_star", "epsstar")
s = s.replace("Identity", "df") # TODO check if this holds or also happens for anti
s = s.replace("ZERO", "0")
s = s.replace(".*", "*") # handle decimals
s = s.replace(".)", ")") # handle decimals
try:
s = re.sub(r"complex\((.*?),(.*?)\)", r"(\1+i_*(\2))", s)
# s = s.replace("complex(0,1)", "i_") # form uses i_ for imaginary unit
s = s.replace("Gamma_Id", "GammaId")
s = s.replace("u_bar", "ubar")
s = s.replace("v_bar", "vbar")
s = s.replace("eps_star", "epsstar")
s = s.replace(
"Identity", "df"
) # TODO check if this holds or also happens for anti
s = s.replace("ZERO", "0")
s = s.replace(".*", "*") # handle decimals
s = s.replace(".)", ")") # handle decimals
except Exception as e:
print("Error in string_to_form", e)
print(s)
raise e
return s


Expand Down
95 changes: 92 additions & 3 deletions feynamp/leg.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import re

from feynamp.log import warning
from feynamp.momentum import insert_momentum
from feynamp.util import find_particle_in_model

Expand All @@ -6,12 +9,98 @@ def get_leg_math_string(leg, fd, model):
return get_leg_math(leg, fd, model)


def get_leg_momentum(leg):
if leg is None:
return None
if leg.momentum is None or leg.momentum.name is None:
raise ValueError("Momentum not set for particle")
mom = insert_momentum(leg.momentum.name)
return mom


def color_vector_to_casimir(color_vector: str) -> str:
if color_vector == "VA":
return "Ca"
if color_vector == "VC":
return "Cf"
return None


def color_vector_to_operator(color_vector):
if color_vector == "VA":
return "complex(0,1)*f"
if color_vector == "VC":
return "T"
return None


def color_vector_to_id(color_vector):
if color_vector == "VA":
return "da"
if color_vector == "VC":
return "df"
return None


def color_vector_to_index(color_vector):
if color_vector == "VA":
return "Glu"
if color_vector == "VC":
return "Color"
return None


def is_swapped_color_vector(fd, leg, model, s2):
"""
For colorcorrelations the chains of T's must be properly ordered so we check if they must be swapped
TODO: check this for gluons, maybe sign is wrong...
"""
p = find_leg_in_model(fd, leg, model)
if leg.is_incoming():
if p.color == 3:
return False
if p.color == -3:
return True
elif leg.is_outgoing():
if p.color == 3:
return True
if p.color == -3:
return False
return False

if re.search(r"T\(Color" + leg.id + r",.*?,.*?\)", s2):
return True
elif re.search(r"T\(.*?,Color" + leg.id + r",.*?\)", s2):
return False
elif re.search(r"f\(Glu" + leg.id + r",.*?,.*?\)", s2):
return True
elif re.search(r"f\(.*?,Glu" + leg.id + r",.*?\)", s2):
return False
elif re.search(r"f\(.*?,.*?,Glu" + leg.id + r"\)", s2):
warning("leg color third in f, check colorcorrelations")
return True
return False
# raise ValueError(f"Color vector for {leg} not found in squared amplitude")


def get_color_vector(fd, leg, model):
p = find_leg_in_model(fd, leg, model)
# give particles color vectors to sum over them in the end (or better average)
# TODO this could be also done as incoming vs outcoming
if p.color == 8:
# if particle is a gluon give it a adjoint color function
return "VA"
if p.color == 3 or p.color == -3:
# if particle is a quark give it a fundamental color function
return "VC"
return None


def get_leg_math(fd, leg, model): # epsilons or u/v optionally also barred
p = find_leg_in_model(fd, leg, model)
if p.particle.momentum is None or p.particle.momentum.name is None:
raise ValueError("Momentum not set for particle")
mom = get_leg_momentum(leg)
ret = ""
mom = insert_momentum(p.particle.momentum.name)
# give particles color vectors to sum over them in the end (or better average)
# TODO this could be also done as incoming vs outcoming
if p.color == 8:
Expand Down
Empty file added feynamp/test/__init__.py
Empty file.
Loading

0 comments on commit 9410c25

Please sign in to comment.