简介:FeynCalc 是一套基于 Mathematica 的符号计算软件包,面向量子场论与基本粒子物理研究者、学生及相关工程人员,用于费曼图求值、旋量与张量代数化简、圈积分与振幅计算等场景。它支持在标准模型及扩展理论中开展可复现的解析推导,适合从入门学习到前沿课题研究的不同阶段使用。资源包以 zip 压缩包形式交付,体积约 5.75MB,平台暂未提供文件总数与类型明细,但不影响直接部署使用。目前已有 807 人学习浏览,配套 GitHub Discussions 论坛可获取社区支持,同时资源附有 FeynCalc 论文引用信息,便于在研究论文中规范致谢。对需要处理复杂粒子物理符号运算的 Mathematica 用户来说,这套软件包能显著提升工作效率,减少手工推导出错的可能。
1. FeynCalc 是什么:一个把脏活接走的 Mathematica 代数计算包
第一次跑 FeynCalc 的时候,我其实是想偷个懒:手里一个 QED 的单圈振幅,Dirac 矩阵的迹从纸上推了三页,总觉得某一项的符号不对。把表达式敲进去,DiracTrace加Contract一行出结果,和手推一对照,果然是中间某一步 gamma 矩阵的顺序写反了。FeynCalc 这个 Mathematica 软件包解决的就是这类问题——基本粒子物理里的代数计算。它能帮你处理费曼振幅里的 Dirac 结构、色因子、运动学张量,以及单圈积分的约化和整理。它不替你生成费曼图,但能把从费曼规则到可数值评估表达式之间那段最繁琐的代数过程接走。适合做粒子物理唯象计算、复现论文推导的人,也适合任何想用符号工具验证手算的初学者。
2. 装 FeynCalc 之前要明白的三件事:版本、加载顺序与冒烟测试
2.1 版本与兼容性:为什么不该去扒十年前的老包
FeynCalc 从最早的内核到现在已经迭代了很多轮。常见做法是拿当前主线版本,而不是网上流传的十几年前打包文件。老包的问题不是功能不够,而是它按旧版 Mathematica 的上下文机制编写,放进新内核会出现符号保护冲突、上下文找不到,甚至加载时报一堆红色警告。
选版本时先确认和内核的兼容关系。一般来说,主线版本对当前主流 Mathematica 内核支持最好。如果你只做树级 QED 计算,版本敏感度不高;一旦进入单圈 QCD,就会依赖 PaVe 函数和色代数模块,这两块都在后期经历过重构,老版本的函数名和化简行为和新版有明显差异。我自己的习惯是:优先用新主线,且只在需要复现旧项目时才固定某个老版本。
另一个要提前想清楚的是加载顺序。如果同一个会话里还要用 FeynArts 生成费曼图,$LoadAddOns列表里 FeynArts 要写在 FeynCalc 前面,让 FeynArts 先加载。这个顺序问题在避坑章还会展开,但初始化阶段就要养成习惯。
2.2 最小安装与初始化:$LoadAddOns 与加载函数
装包有两种常见做法。第一种是手动把包目录放进去:
# Unix 风格的包目录放置:Mac/Linux 下 Applications 一般位于用户目录 mkdir -p ~/.Mathematica/Applications cp -r FeynCalc ~/.Mathematica/Applications/第二种是用 paclet 机制安装,初始化更干净,升级也好处理。无论哪种方式,初始化入口是一致的:先设置$LoadAddOns,再调用加载函数。
(* 方式一:手动放包后,把路径交给 Mathematica *) $FeynCalcPath = "/your/path/FeynCalc"; AppendTo[$Path, $FeynCalcPath]; (* 方式二:本次会话只加载 FeynCalc,不带 FeynArts *) $LoadAddOns = {"FeynCalc"}; (* 加载并做一次冒烟测试 *) LoadFeynCalc[]; (* 打印包版本,确认加载的是目标主线 *) Print["FeynCalc loaded, version: ", $FeynCalcVersion];$LoadAddOns是初始化脚本识别的全局列表,决定本次会话加载哪些附属包。这里只写了 FeynCalc;如果还要 FeynArts,就写{"FeynArts", "FeynCalc"},顺序不能反。LoadFeynCalc[]负责把包的上下文、帮助索引和全局变量一次准备好。$FeynCalcVersion打印版本号,用来确认环境。
如果加载时报符号遮蔽,比如提示GA、SP已经被其他包定义,可以先执行Remove["Global*"]` 清掉当前上下文里的同名符号,再重新加载。很多新人以为装好就能直接写公式,实际 FeynCalc 对全局符号很敏感,残留变量会直接混进振幅表达式。
2.3 冒烟测试:两个最小命令确认内核符号可用
冒烟测试不要跑大振幅,两个最小命令足够:一个色因子化简,一个 Dirac 矩阵迹,确认SUNSimplify和DiracSimplify入口健康。
(* 色代数:SU(N) 结构常数 f^abc 的自缩并 *) SUNF[a, b, c] SUNF[a, b, c] // SUNSimplify (* Dirac 代数:两个 gamma 矩阵的迹 *) TR[GA[mu] . GA[nu]] // Contract第一行输出如果包含CA和颜色数N,说明色代数模块工作正常。第二行输出类似4 MT[mu, nu]或4 g_mu_nu的形式,说明度规张量和缩并模块可用。假如第二行留下一个没缩并的MT[mu, nu],多半是初始化时$LoadAddOns没设置成功,或者加载了老版本包。此时不要先去调振幅,回头查加载顺序。
这两个命令虽然简单,却是后面所有计算的地基。地基不稳的时候,问题往往不在物理,而在环境。
3. 第一次正式计算:从运动学澄清到最小树级振幅
3.1 先做运动学声明:ScalarProduct 与 ClearScalarProducts
写振幅前,先把外动量的内积声明清楚。FeynCalc 里一切和动量相关的化简都依赖标量积规则,SP[a,b]表示四矢量内积。不声明的话,它会保留符号形式的SP[p1,p1],最后结果看起来像没化简。
(* 清理上一次运行可能残留的标量积定义 *) ClearScalarProducts[]; (* 声明电子-缪子散射:外线质量与 s,t 变量 *) SP[p1, p1] = m^2; SP[p2, p2] = M^2; SP[p3, p3] = m^2; SP[p4, p4] = M^2; (* 两点内积由质壳条件和运动学展开给出 *) SP[p1, p2] = s/2 - m^2/2 - M^2/2; SP[p1, p3] = t/2 - m^2; SP[p2, p4] = t/2 - M^2;ClearScalarProducts[]会清掉之前会话里所有SP赋值,我习惯放在每个任务开头。外线质量、s、t 的赋值按目标过程设定;如果你算的是具体对撞几何,这里要按实际四动量展开,不能直接套上面的公式。这一段是新手最容易漏的:漏声明时 FeynCalc 不报错,只是给你留一堆符号化SP,你要花更多时间排查为什么表达式不收敛。
3.2 写一个最小 QED 树级振幅:旋量外线怎么摆
一个常见的练习是电子-缪子散射的 t 道单光子交换。忽略耦合常数后,振幅由两个旋量流相乘,再乘上光子度规和传播子分母:
(* t 道单光子交换振幅;暂略耦合常数与顶点因子 *) amp = (SpinorUBar[p3, m] . GA[mu] . SpinorU[p1, m]) * (SpinorUBar[p4, M] . GA[nu] . SpinorU[p2, M]) * MT[mu, nu] / SP[p1 - p3, p1 - p3];SpinorUBar[p, m] . GA[mu] . SpinorU[p, m]是费曼规则里旋量流的标准写法,FeynCalc 会把它们当作符号对象保留,直到你决定做自旋求和再求迹。MT[mu,nu]是度规张量,SP[p1-p3, p1-p3]会按 3.1 的声明自动展开成 t 道表达式。这样写的好处是:不需要手动展开(p1-p3)^2,内核会根据已声明的标量积做完线性代数。
第一次跑这类表达式,推荐先做一次DiracSimplify看结构是否完整,而不是直接平方:
DiracSimplify[amp] // Contract这一行会合并 gamma 矩阵乘积、完成度规缩并,输出干净的旋量链组合。如果输出里出现未缩并的GA[mu] . GA[nu]或零散MT,先检查表达式是否存在偶数个重复指标没统一,用FCCanonicalizeDummyIndices把哑指标归一到同一名字,再重新Contract。
3.3 Dirac 迹与 gamma5:TR 的快捷项和维度开关
自旋求和之后,旋量内积会落到一组 gamma 矩阵的迹。FeynCalc 的TR是DiracTrace的快捷形式,它会先展开矩阵乘积再求迹,比手推可靠得多。
(* 经典四个 gamma 矩阵的迹,无 gamma5,纯度规项 *) TR[GA[mu] . GA[nu] . GA[rho] . GA[sigma]] // Contract (* 带 gamma5 的迹:结果会含 Levi-Civita 张量 *) TR[GA[mu] . GA[nu] . GA[rho] . GA[sigma] . G5] // DiracSimplify第一行结果在四维下是 4 倍的三项度规组合,这是 QED 计算里出现频率最高的恒等式,值得记下来:4 (g_mu_rho g_nu_sigma - g_mu_sigma g_nu_rho + g_mu_nu g_rho_sigma)。第二行加入G5后,结果出现Eps[mu, nu, rho, sigma]这样的完全反对称张量,这是正常现象,不要试图用Contract消掉。
真正需要留意的是单圈计算里 gamma5 的位置和维度约化方案。FeynCalc 提供$Larin开关控制 gamma5 的处理方式。默认设置适合四维计算;当你做 D 维下的含 gamma5 计算,结果和论文对不上时,切换这个开关再比较,往往能找到差异来源。这属于典型的“版本约定差异”,不是程序算错。
4. 跑通单圈:色代数、PaVe 约化与整体化简链
4.1 QCD 色因子:让 SUNF 替你算而不是手查表格
QCD 振幅比 QED 多一层色结构。新手常去翻群因子表格,其实 FeynCalc 的色代数模块足够处理常见缩并。
(* f^{abc} f^{abc} = N C_A *) SUNF[a, b, c] SUNF[a, b, c] // SUNSimplify (* 两个 Gell-Mann 矩阵的色求和 *) SUNT[a, i, j] SUNT[a, k, l] // SUNSimplifySUNF表示结构常数,SUNT表示色矩阵,色指标用SUNIndex携带。第一行输出CA N,其中 N 是颜色数,这个因子在 QCD 费曼图里反复出现。第二行结果是1/2 (delta_il delta_kj - 1/N delta_ij delta_kl),对应夸克-胶子耦合处的色因子基。
如果输出里出现未化简的SUNDelta或挂着SUNIndex的项,先FCCanonicalizeDummyIndices再SUNSimplify。色代数化简不彻底的九成原因都是哑指标名字不统一,导致缩并无从发生。
4.2 从传播子组合到 PaVe:ToPaVe 与 OneLoop 的分工
单圈计算的本质,是把含有圈动量的积分表达式整理成标量积分基。FeynCalc 里的 PaVe 函数采用 Passarino-Veltman 记号,像PaVe[0, {s}, {m^2, 0}]这样的对象就代表一个标量积分。
(* 圈动量 q,外动量 p;一个质量为 m 的传播子,一个无质量传播子 *) ClearScalarProducts[]; SP[p, p] = s; (* 分子上出现 q_mu:一个带张量结构的单圈表达式 *) int = FAD[{q, m}, {q - p, 0}] FVD[q, mu] // FCI; (* 把分子上的圈动量约化到外动量和大标量积分 *) ToPaVe[int, q]FAD[{q, m}]表示传播子分母1/(q^2 - m^2),FVD[q, mu]是圈动量四矢量。ToPaVe会把分子上的 q 按洛伦兹结构约化,最终输出形如p_mu * PaVe[...]的组合。第二个参数写圈动量,FeynCalc 会自动识别外动量;式子复杂时,推荐先用FCLoopIsolate[expr, {q}]把单圈积分块切出来,再交给ToPaVe,避免被无关项干扰识别。
老版本风格更常用OneLoop一条命令完成全部:
OneLoop[q, int] // Simplify它会自动完成分子展开、张量约化、PaVe 整理三件事。缺点是黑匣子感强,中间量难以追溯。我的习惯是:探索期用OneLoop快速看形状,打磨期改用ToPaVe手动控制每一步。
4.3 整体化简链:一条可以抄走的流水线
实际项目里振幅表达式往往不止一个积分块。推荐按固定顺序过一遍,能省下大量排错时间:
expr = amp // FeynAmpDenominatorSimplify; expr = expr // DiracSimplify // SUNSimplify // Contract; expr = OneLoop[q, expr] // SimplifyFeynAmpDenominatorSimplify负责整理所有传播子分母,合并同类项;DiracSimplify处理 gamma 矩阵,SUNSimplify处理色因子,Contract收缩度规、delta 和哑指标;最后OneLoop或ToPaVe做圈积分。这个顺序不能乱调:先做圈积分再做色代数,中间表达式会膨胀得很快;最后才Contract,可能出现度规带着未缩并的动量指标,导致ToPaVe无法识别圈动量。
参数方面,圈动量推荐用单个字母 q 或 l,不要用p1+p2形式的复合动量,否则识别开销大增;质量参数统一写平方形式,比如m^2而不是m*m,FeynCalc 对幂次形式的分母识别更稳定;外动量多时,先把标量积声明完整再进入化简链,否则最后会残留SP[p1+p2, p3]这类无法数值化的项。
5. FeynCalc 排错与避坑:现象、原因与处理
5.1 Contract 之后还留下大量 MT[mu, nu]
现象:一条看起来正常的振幅表达式,做完Contract仍然有MT[mu, nu]残留,逐项检查又看不出语法问题。
原因:表达式里哑指标名字不一致。MT[mu, nu]需要同一对指标出现两次才能形成缩并,如果一处写mu、另一处写alpha,内核不会自动匹配。另一个常见来源是系数里带着未 factor 的多项式,收缩时无法判断指标是否真的哑。
解决:先FCCanonicalizeDummyIndices[expr]统一哑指标,再Contract;如果仍然残留,对系数做Factor或Apart,把分母处理干净后再收缩。这个操作我基本每次化简都做。
5.2 DiracTrace 输出里出现奇数个 gamma 矩阵
现象:TR或DiracTrace的结果里出现GA[mu] . GA[nu] . GA[rho]这样的奇数链,看着像没取干净迹。
原因:多数情况不是内核算错,而是表达式本身不是纯迹结构。最常见的是两个旋量链之间漏了括号,或者把点乘写成了普通乘法。FeynCalc 里GA[mu] . GA[nu]是矩阵乘法,GA[mu] GA[nu]会被当成两个独立项,导致取迹时结构错位。
解决:检查所有 gamma 矩阵连接是否用了.;表达式从 FeynArts 转过来时,先过FCPrepareFAAmp规范化再取迹。这是费曼规则代码里最容易出现的翻车点,几乎每个初学者都会踩一次。
5.3 SUNSimplify 返回一堆 SUNDelta 而不是想要的 CA
现象:QCD 色因子化简后,输出挂着SUNDelta和SUNIndex,预期中的CA或TF没出现。
原因:色指标没有统一。比如一个顶点里写SUNIndex[a],另一个顶点里写SUNIndex[b],而它们之间没有SUNDelta[a, b]或结构常数连接,化简就无从谈起。还有一种情况是表达式中本应出现SUNDelta缩并,但指标顺序写反导致符号不匹配。
解决:先FCCanonicalizeDummyIndices再SUNSimplify。如果还不行,逐个打印色因子子表达式,人工确认顶点的色矩阵是否漏写。色代数不像 Dirac 代数那样会自动补齐缺失结构,漏顶点只能靠自查。
5.4 FCLoopIsolate 报错:不是有效圈积分
现象:FCLoopIsolate[expr, {q}]直接报错,或者明明有 q 却提示找不到圈动量。
原因:传播子分母里带的是SP[q + p, q + p]这种未展开形式,或者圈动量写成了复合动量表达式。FCLoopIsolate识别的是“圈动量显式出现在传播子和分子上”的规范形态,任何多余封装都会干扰识别。
解决:先把所有括号展开,统一用FAD[{q - p, m}]形式写传播子;圈动量用单一符号 q,外动量全部替换成简单符号。圈积分块整理好后再做约化,这条经验能省掉大量和解析器较劲的时间。
5.5 加载 FeynArts 后 GA、SP 行为异常
现象:FeynCalc 已经能正常计算,但加载 FeynArts 之后,GA[mu]不展开,SP[p,q]也不按标量积规则化简。
原因:两个包的上下文重叠,加载顺序不对时符号互相遮蔽。FeynCalc 的很多快捷函数名和 FeynArts 内部符号同名,后加载的包会把先加载的包的同名符号覆盖。
解决:标准做法是在$LoadAddOns里写{"FeynArts", "FeynCalc"},让 FeynArts 先加载,FeynCalc 后加载。两包交互时优先用FCPrepareFAAmp这类接口做转换,不要在两边手工复制表达式。接口会负责把 FeynArts 的振幅对象转成 FeynCalc 内部形式,绕开符号冲突。
6. 把 FeynCalc 嵌进自己的流程:三个值得长期投资的习惯
6.1 给 FeynArts 的图输出设一个固定入口
每换一台电脑就重写一遍加载代码,很容易出错。我会把初始化固定成一个公共脚本,每次会话开头只执行它:
(* 固定入口:只加载需要的附加包 *) $LoadAddOns = {"FeynArts", "FeynCalc"}; LoadFeynCalc[]; (* 若从 FeynArts 生成振幅,一律走这个接口 *) amp = FCPrepareFAAmp[someFeynArtsAmp];这样两包的顺序问题被固化在脚本里,新环境部署时不需要回忆。FCPrepareFAAmp帮我避掉了至少三次手工转换导致的符号错位,值得养成默认习惯。
6.2 用 Table 扫参数空间而不是手改运动学
复现一个论文计算时,经常要扫能量或质量区间。不要手改一遍跑一遍,直接用Table批量生成:
results = Table[ amp /. {SP[p1, p1] -> m^2, SP[p2, p2] -> m^2, SP[p1, p2] -> sval/2 - m^2}, {sval, 400, 1600, 200} ] // Simplify;这会把运动学声明变成替换规则,循环扫束流能量。输出直接是一个列表,后续可以立刻画图或存表。这个习惯让我在处理扫描类问题时,把注意力放回物理结果,而不是反复复制粘贴同一段代码。
6.3 给化简链加哑指标检查和维度开关
最后一个习惯:每次化简前先统一哑指标,再进主链路;遇到含 gamma5 的单圈计算,主动确认维度方案开关。
expr0 = FCCanonicalizeDummyIndices[expr]; expr1 = expr0 // DiracSimplify // SUNSimplify // Contract; expr2 = OneLoop[q, expr1] // Simplify;这段代码本身不复杂,但它把“先规范、再化简、最后积分”的次序固定成了肌肉记忆。我在这上面吃过亏:有一次跳过了指标统一直接OneLoop,结果在ToPaVe阶段来回排查了半天,最后发现只是两个哑指标名字不一致。
做高能理论计算,最贵的不是算力,是定位无意义错误的时间。固定化简次序、显式控制维度开关、所有圈动量用单一字母,这三条我现在的项目已经写进了团队规范。希望帮到你。
本文还有配套的精品资源,点击获取