提供了一个MMA程序可以计算任意多个自由场之间的OPE以及NOP之间的OPE。

点击下面的按钮可以下载源码:

Download Codes

或者访问项目Github网址,那里更新更快,这里只会放稳定版

代码解释

起因是在读Polchinski弦论BRST量子化这一章的时候一个OPE老是算错红温了,所以就想着自由场很简单,不妨直接使用电脑计算。得益于今年暑假在何颂老师课题组极大提升了MMA代码能力,所以就尝试写一个MMA计算代码。对于自由场其实很简单,在90年代就有计算程序包,但是太过久远,基本思路是来源于那篇文章1

  • 麻烦的点有三个:
  • 如何准确数出所有的Wick收缩
  • 如何考虑费米子的反对易性,从而正确计算收缩前的符号
  • 其间还涉及到一系列复杂的化简
d = 27;
eta = DiagonalMatrix[PadRight[{-1}, d, 1]];
\[Alpha] = 2;
fields = {psi, b, c, be, ga, phi};
bosons = {be, ga, phi};
fermions = Complement[fields, bosons];

这里的$d$是维数,eta表示Minkowski度规。弦论里面用的CFT无非是自由玻色子$X^\mu$,Majorana费米子$\psi$和$bc,\beta\gamma$鬼场,这里分别用phi,psi,b,c,be,ga表示。输入的时候形式为:

X[i_,j_,z_]

意思是$\partial^i X_j(z)$。然后最简单的就是两个场之间的ope,最终我们的目的也是用wick定理化简为所有两点ope之间的计算,ope有下面的性质:

(*OPE基本特性定义*)
ope[a_ x_[i__] /; MemberQ[fields, x], y_[j__]] := a ope[x[i], y[j]];
ope[ x_[i__], a_ y_[j__] /; MemberQ[fields, y]] := a ope[x[i], y[j]];
ope[x_ + y_, z_] := ope[x, z] + ope[y, z];
ope[x_, y_ + z_] := ope[x, z] + ope[x, y];
ope[x_[i__] /; MemberQ[fermions, x], 
    y_[j__] /; MemberQ[fermions, y]] /; Order[x[i], y[j]] == 0 := 0;
ope[x_[i__] /; MemberQ[fermions, x], 
    y_[j__] /; MemberQ[fermions, y]] /; 
   Order[x[i], y[j]] == -1 := -ope[y[j], x[i]];
ope[x_[i__] /; MemberQ[bosons, x], y_[j__] /; MemberQ[fields, y]] /; 
   Order[x[i], y[j]] == -1 := ope[y[j], x[i]];
ope[x_[i__] /; MemberQ[fields, x], y_[j__] /; MemberQ[fields, y]] /; 
   Order[x[i], y[j]] == -1 := ope[y[j], x[i]];

还有自由场之间ope的数值:

ope[b[i_, j_, z_], c[m_, n_, w_]] := 
  D[DiscreteDelta[j - n]/(z - w), {z, i}, {w, m}];
ope[psi[i_, j_, z_], psi[m_, n_, w_]] := 
  D[DiscreteDelta[j - n]/(z - w), {z, i}, {w, m}];
ope[be[i_, j_, z_], ga[m_, n_, w_]] := 
  D[DiscreteDelta[j - n]/(z - w), {z, i}, {w, m}];
ope[phi[i_, \[Mu]_, z_], phi[m_, \[Nu]_, w_]] := 
  D[-\[Alpha]/2 eta[[\[Mu], \[Nu]]] Log[z - w], {z, i}, {w, m}];

第二个重要单元是NOP,也有类似的性质定义,但是这个时候我们定义的是任意多点的NOP:

(*NOP基本特性设定*)
SetAttributes[nop, Flat];
nop[a_Plus, b__] := Distribute@Unevaluated@nop[a, b];
nop[b__, a_Plus] := Distribute@Unevaluated@nop[b, a];
nop[b__, a_Plus, c__] := Distribute@Unevaluated@nop[b, a, c];
nop[c_ a_ /; MemberQ[fields, Head[a]], b__] := c nop[a, b];
nop[b__, c_ a_ /; MemberQ[fields, Head[a]]] := c nop[b, a];
nop[b__, c_ a_ /; MemberQ[fields, Head[a]], e__] := c nop[b, a, e];
nop[c_ a_nop, b__] := c nop[a, b];
nop[b__, c_ a_nop] := c nop[b, a];
nop[e__, c_ a_nop, b__] := c nop[e, a, b];
nop[0, i__] := 0;
nop[i__, 0] := 0;
nop[i__, 0, j__] := 0;

(*还需要设定当nop中存在相同fermion(取值点也相同)的时候自动计算为0*)
PauliQ[x_List] := ! DuplicateFreeQ[extractfermions[x]];
nop[x__] /; PauliQ[{x}] := 0;

由于收缩的时候涉及到费米子的移动,这个时候就会产生负号,最终其实我们只需要单独看收缩前后费米子的位置,如果费米子之间发生了奇置换那就是负号,置换的奇偶性可以用逆序数判断:

(*逆序数方法*)
PermutationParity[perm_List] := 
  Module[{invCount = 0}, 
   Do[If[perm[[i]] > perm[[j]], invCount++], {i, 1, Length[perm]}, {j,
      i + 1, Length[perm]}];
   If[EvenQ[invCount], 1, -1]];

(*获取置换列表*)
GetPermutation[list1_List, list2_List] := 
  Flatten[Position[list1, #] & /@ list2];

顺便提一嘴,上面的代码是GPT告诉我的,包括下面的wick收缩的代码也是chatGPT告诉我的:

(*生成所有可能的收缩模式,包括未完全收缩的情况*)
AllContractions[opList_List] := 
 Module[{first, rest, result = {}, contractions, i, partner, newRest, 
   subContractions}, If[opList === {}, Return[]];
  first = opList[[1]];
  rest = opList[[2 ;;]];
  (*情况1:第一个算符未收缩*)contractions = AllContractions[rest];
  result = Map[Prepend[#, {first}] &, contractions];
  (*情况2:第一个算符与剩余算符中的每一个进行收缩*)
  For[i = 1, i <= Length[rest], i++, partner = rest[[i]];
   newRest = Delete[rest, i];
   subContractions = AllContractions[newRest];
   result = 
    Join[result, 
     Map[Prepend[#, {first, partner}] &, subContractions]];];
  Return[result];]
AllContractionsLocations[n_] := 
  Block[{x = AllContractions[Range[n]]}, 
   Table[Select[x[[i]], Length[#] == 2 &], {i, Length[x]}]];

所以chatGPT真的能提高工作效率。。。。

两个NOP之间的Wick缩并只需要在上面的基础上剔除掉那些NOP内部的缩并就好了:

(*两个nop的缩并*)
ContractAllowQ[x_, n_] := 
  If[Select[x, #[[1]] > n || #[[2]] <= n &] != {}, False, True];
TwoNopConstractions[n_, m_] := 
  Union[, 
   Select[AllContractionsLocations[n + m], ContractAllowQ[#, n] &]];

现在大写的OPE是计算OPE的函数,让输入是一个列表时定义为:

(*OPE的Wick定理*)
(*计算符号*)
FermionSign[constraction_, noploc_, fermionlocation_] := 
  PermutationParity[
   GetPermutation[
    Select[Flatten[{constraction, noploc}], 
     MemberQ[fermionlocation, #] &], fermionlocation]];
(*计算每一项*)
wickterm[constraction_, x_, fermionlocation_] := 
  Block[{noploc = 
     Complement[Range[Length[x]], Flatten[constraction]]}, 
   Times @@ ope @@@ (x[[#]] & /@ constraction) If[noploc != {}, 
     nop @@ (x[[#]] & /@ noploc), 1] FermionSign[constraction, noploc,
      fermionlocation]];
OPE[a_List] := 
  Block[{constractions = AllContractionsLocations[Length[a]], 
    fermionlocations = extractfermionsloc[a]}, 
   Plus @@ Table[
     wickterm[constractions[[i]], a, fermionlocations], {i, 
      Length[constractions]}]];

当输入为两个nop时理解为NOP之间的缩并

(*NOP之间的OPE*)
(*可以用之前的代码,减去掉内部缩并就好*)
OPE[a_nop, b_nop] := 
  Block[{A = a /. {nop -> List}, B = b /. {nop -> List}}, 
   Block[{constractions = TwoNopConstractions[Length[A], Length[B]], 
     fermionlocations = extractfermionsloc[Flatten[{A, B}]]}, 
    Plus @@ 
     Table[wickterm[constractions[[i]], Flatten[{A, B}], 
       fermionlocations], {i, Length[constractions]}]]];

为什么用OPE而不是用原先已经线性齐次都定义好了的ope主要是为了避免一些未知错误,所以现在要重新定义一下线性:

OPE[c_ a_nop, b_] := c OPE[a, b];
OPE[a_, c_ b_nop] := c OPE[a, b];
OPE[a_Plus, b_] := Distribute@Unevaluated@OPE[a, b];
OPE[a_, b_Plus] := Distribute@Unevaluated@OPE[a, b];

但是上面的线性遇到OPE[a,b (x+y)]就不起作用了,这个时候就需要先使用expandope函数将OPE里面的每一个变量都展开,然后上面的rule就继续起作用了。然后再使用SimplifyNOP函数,MMA就会自动对NOP进行泰勒展开,然后丢掉regular term。实现方法也不难,主要是需要定义一个非交换乘法的导数nopD,并且要将对场的求导解释为其第一个参数加一。然后找出每一个nop分母的次数方便告知需要泰勒展开到第几阶,避免重复运算。

说到重复运算,MMA的WithBlockModule都是非常好用的函数,让局部变量只计算一次并且在后面反复调用。

利用这个代码,成功计算了BRST流:

\[\begin{aligned}j_B&=cT^m+:bc\partial c:+\frac{3}{2}\partial^2c\\T^m&=-\frac{1}{\alpha'}:\partial X^\mu\partial X_\mu:\end{aligned}\]

之间的OPE:

\[j_{\mathrm{B}}(z)j_{\mathrm{B}}(0)\sim-\frac{c^{\mathrm{m}}-18}{2z^3}c\partial c(0)-\frac{c^{\mathrm{m}}-18}{4z^2}c\partial^2c(0)-\frac{c^{\mathrm{m}}-26}{12z}c\partial^3c(0),\quad c^m=d\]

玻色弦顶角算符关联函数计算

点击下面的按钮即可下载源码

Download Codes

这个程序就是实现了球面世界面拓扑下玻色弦顶角算符关联函数的计算,也就是下面的东东:

\[\left\langle\prod_{i=1}^n\left[e^{ik_i\cdot X(z_i,\bar{z}_i)}\right]_\mathrm{r}\prod_{j=1}^p\partial X^{\mu_j}(z_j^{\prime})\prod_{k=1}^q\bar{\partial}X^{\nu_k}(\bar{z}_k^{\prime\prime})\right\rangle_{S_2}\]

ToDoList

由于时间有限,来不及对代码进行更多测试,后续会在使用中不断发现bug并修复,一个非常重要的需要解决的问题是弦论中更多的是顶角算符OPE的计算,这也是弦论计算中非常复杂的部分,期待后续能把这一点补全。

  • 顶角算符:exp(ikX):OPE的计算
  • expandOPE优化成可以使用的样子(这是为了下面这一点的方便)
  • 利用Fold将两个NOP之间的OPE运算推广成任意NOP之间的OPE计算(虽然人为的总是可以做)
  • 顶角算符关联函数的计算alpha因子开闭弦之间4倍的关系还没有优化
  • 增加从OPE得到模展开之间对易关系的功能

Update

  • 10.14 更新了玻色弦顶角算符关联函数计算程序
  • 11.13 完善了一些注释,更新了一个 $\mathcal{N}=1$ SCFT中ghost部分生成的超共形代数OPE计算的而例子

参考文献

  1. https://doi.org/10.1016/0010-4655(94)90231-3 

原创文章转载请注明出处: 自由共形场论OPE计算程序