# This worksheet illustrates the use of Sage for the toric intersection calculations in the paper
# "Modular Amplitudes and Flux-Superpotentials on elliptic Calabi-Yau fourfolds", https://arxiv.org/abs/1709.02820
# As an example, we construct a 4-parameter elliptically fibered Calabi-Yau 4-fold with an E8 fiber and
# polytope 27 as the base.
# We choose polytope 27 because the corresponding variety is Fano and the intersection ring is relatively
# non-trivial.
# If you use this code or parts of it for a publication, please
# cite the above paper.
ReflexivePolytope(3, 27).points()
# Triangulate polytope and create toric variety
vertices = \
[[1, 0, 0, -2, -3], \
[-1, 0, 0, -2, -3], \
[0, 1, 0, -2, -3], \
[0, 0, 1, -2, -3], \
[1, 0, -1, -2, -3], \
[1, -1, 0, -2, -3], \
[0, 0, 0, -2, -3], \
[0, 0, 0, 1, 0], \
[0, 0, 0, 0, 1]]
poly = LatticePolytope(vertices)
irrelevantPoints = [b for a in map(lambda a: map(tuple, a.interior_points()), poly.faces_lp(codim=1)) for b in a]
relevantPoints = list(set(map(tuple, poly.points())) - set(irrelevantPoints))
pointTuples = relevantPoints
pointConfiguration = PointConfiguration(pointTuples, fine=True, star=pointTuples.index((0, 0, 0, 0, 0)))
triang = pointConfiguration.triangulate()
fan = Fan([Cone([pointTuples[i] for i in indices]) for indices in triang])
variety = ToricVariety(fan)
HH = variety.cohomology_ring()
D = [ HH(c) for c in variety.fan(dim=1) ]
# Print Mori cone
print variety.Mori_cone().rays()
print variety.fan(dim = 1)[3].rays() # <-- this is (0,0,-2,-3)
s = D[3] # <-- the corresponding toric divisor is the section
# Using the Mori cone, we determine a basis for the Kähler cone
d1 = D[5]
d2 = D[1]
d3 = D[0]
d4 = D[3] + D[5] + 2*D[1] + D[0]
tc1 = d4 - s
kaehlerClasses = [d1,d2,d3,d4]
cy = sum(D)
cc=(reduce(operator.mul, [(1+d) for d in D], 1)/(1+sum(D)))
c1=cc.part_of_degree(1)
c2=cc.part_of_degree(2)
c3=cc.part_of_degree(3)
c4=cc.part_of_degree(4)
todd=1+(1/12)*c2+(1/240)*c2*c2-(1/720)*c4
intersections = {}
import itertools
import math
print ""
for comb in itertools.combinations_with_replacement(range(4), 4):
intersection = variety.integrate(reduce(operator.mul, [[d1, d2,d3,d4][i] for i in comb], 1) * cy)
intersections[tuple([a + 1 for a in comb])] = intersection
print "C" + str([a + 1 for a in comb]) + ": " + str(intersection)
# Intersection ring of the base:
for comb in itertools.combinations_with_replacement(range(3), 3):
intersection = variety.integrate(reduce(operator.mul, [[d1, d2, d3][i] for i in comb], 1) * s * cy)
intersections[tuple([a + 1 for a in comb])] = intersection
print "C" + str([a + 1 for a in comb]) + ": " + str(intersection)
# Determine dual basis of the base:
basecurves = [a * s for a in [d1*d1, d1*d2, d1*d3, d2*d2, d2*d3, d3*d3]]
for c in basecurves:
print [variety.integrate(c*a*cy) for a in [d1,d2,d3]]
print ""
basecurvebasis = [d2*d3 - d1*d3, d1*d3, d1*d2 - d1*d3]
print matrix([[variety.integrate(c*a*s*cy) for a in [d1,d2,d3]] for c in basecurvebasis])
# We choose the following basis of H22 cycles:
hilist=[s*d1,s*d2,s*d3] + basecurvebasis
# Print the intersections
print matrix([[variety.integrate(h*hp*cy) for hp in hilist] for h in hilist])
# Determine the fundamental class
print variety.integrate(s*d1*d2*d3*cy)
fundamentalClass = s*d1*d2*d3
# Express the basis of the Mori cone as intersections of toric divisors
curves = [s * a for a in basecurvebasis] + [d1*d2*d3]
print matrix([[variety.integrate(c*d*cy) for d in [d1,d2,d3,d4]] for c in curves])
import itertools
def totalChern(te):
totalChernClass = 0
for h in te:
if len(h[1]) == 0:
chernClass = 1 + kaehlerClasses[0]
chernClass = chernClass - kaehlerClasses[0] # Just a hack to lift the identity into the cohomology ring
elif len(h[1]) == 1:
d = h[1][0]
chernClass = -d-(1/2)*d*d-(1/6)*d*d*d-(1/24)*d*d*d*d
elif len(h[1]) == 2:
da = h[1][0]
db = h[1][1]
chernClass = da*db+(1/2)*da*db*(da+db)+(1/12)*da*db*(2*da*da+3*da*db+2*db*db)
elif len(h[1]) == 3:
da = h[1][0]
db = h[1][1]
dc = h[1][2]
chernClass = -da*db*dc-(1/2)*(da*da*db*dc+da*db*db*dc+da*db*dc*dc)
elif len(h[1]) == 4:
da = h[1][0]
db = h[1][1]
dc = h[1][2]
dd = h[1][3]
chernClass = da*db*dc*dd
else:
print "parameter error!"
return
totalChernClass = totalChernClass + h[0]*chernClass
return totalChernClass
def asymptotics(te):
cy=sum(D)
cc=(reduce(operator.mul, [(1+d) for d in D], 1)/(1+sum(D)))
c2=cc.part_of_degree(2)
c3=cc.part_of_degree(3)
c4=cc.part_of_degree(4)
totalChernClass = totalChern(te)
curveC0 = totalChernClass.part_of_degree(0)
curveC1 = totalChernClass.part_of_degree(1)
curveC2 = totalChernClass.part_of_degree(2)
curveC3 = totalChernClass.part_of_degree(3)
curveC4 = totalChernClass.part_of_degree(4)
kaehlerVariableString = ['t'+str(i) for i in range(1,len(kaehlerClasses)+1)]
_ = var(kaehlerVariableString)
kaehlerVariables = eval(",".join(kaehlerVariableString))
gammaClass = [(1,1),(1/24,c2),(I*zeta(3)/(8*pi^3),c3),((1/5760),7*c2*c2-4*c4)]
fourTuples = list(itertools.product(range(1,len(kaehlerClasses)+1), repeat=4))
threeTuples = list(itertools.product(range(1,len(kaehlerClasses)+1), repeat=3))
twoTuples = list(itertools.product(range(1,len(kaehlerClasses)+1), repeat=2))
oneTuples = list(itertools.product(range(1,len(kaehlerClasses)+1), repeat=1))
asymptotics = sum([g[0]*variety.integrate(g[1]*cy*totalChernClass) for g in gammaClass]) \
+ sum([(1/factorial(len(tup)))*sum([g[0]*variety.integrate(g[1]*cy*totalChernClass*reduce(operator.mul, [kaehlerClasses[i - 1] for i in tup])) \
for g in gammaClass]) * reduce(operator.mul, [kaehlerVariables[i - 1] for i in tup]) for tup in oneTuples]) \
+ sum([(1/factorial(len(tup)))*sum([g[0]*variety.integrate(g[1]*cy*totalChernClass*reduce(operator.mul, [kaehlerClasses[i - 1] for i in tup])) \
for g in gammaClass]) * reduce(operator.mul, [kaehlerVariables[i - 1] for i in tup]) for tup in twoTuples]) \
+ sum([(1/factorial(len(tup)))*sum([g[0]*variety.integrate(g[1]*cy*totalChernClass*reduce(operator.mul, [kaehlerClasses[i - 1] for i in tup])) \
for g in gammaClass]) * reduce(operator.mul, [kaehlerVariables[i - 1] for i in tup]) for tup in threeTuples]) \
+ sum([(1/factorial(len(tup)))*sum([g[0]*variety.integrate(g[1]*cy*totalChernClass*reduce(operator.mul, [kaehlerClasses[i - 1] for i in tup])) \
for g in gammaClass]) * reduce(operator.mul, [kaehlerVariables[i - 1] for i in tup]) for tup in fourTuples]) \
return str(asymptotics).replace("zeta(3)","Zeta[3]").replace("pi","Pi")
def dualClass(cl):
return cl.part_of_degree(0) - cl.part_of_degree(1) + cl.part_of_degree(2) - cl.part_of_degree(3) + cl.part_of_degree(4)
# The syntax of asymptotics(...) (and totalChern) is such that you pass a list of tuples
# (a_i, [D_{i,1},...,D_{i,n}]) and get the asymptotic period (or the chern class)
# of a brane corresponding to \sum_i a_i D_{i,1}*...*D_{i,n}
print "d8asy="+asymptotics([(1,[])])+";"
print "d6asy1="+asymptotics([(1,[s])])+";"
print "d6asy2="+asymptotics([(1,[d1])])+";"
print "d6asy3="+asymptotics([(1,[d2])])+";"
print "d6asy4="+asymptotics([(1,[d3])])+";"
print "d4asy1="+asymptotics([(1,[s,d1])])+";"
print "d4asy2="+asymptotics([(1,[s,d2])])+";"
print "d4asy3="+asymptotics([(1,[s,d3])])+";"
print "d4asy4="+asymptotics([(1,[d2,d3]),(-1,[d1,d3])])+";"
print "d4asy5="+asymptotics([(1,[d1,d3])])+";"
print "d4asy6="+asymptotics([(1,[d1,d2]),(-1,[d1,d3])])+";"
print "d2asy1="+asymptotics([(1,[s,d2,d3]),(-1,[s,d1,d3])])+";"
print "d2asy2="+asymptotics([(1,[s,d1,d3]),(-1,[s,d1,d2,d3])])+";" # <-- choosen such that d2asy2 == -t2
print "d2asy3="+asymptotics([(1,[s,d1,d2]),(-1,[s,d1,d3])])+";"
print "d2asy4="+asymptotics([(1,[d1,d2,d3])])+";"
print "d0asy="+asymptotics([(1,[s,d1,d2,d3])])+";"
charges = [[(1,[d2,d3]),(-1,[d1,d3])], \
[(1,[d1,d3])], \
[(1,[d1,d2]),(-1,[d1,d3])]]
hv = [variety.integrate(s*totalChern((c)).part_of_degree(3)*cy) for c in charges]
avo = [variety.integrate(s*c*tc1*cy) for c in [d2*d3-d1*d3,d1*d3,d1*d2-d1*d3]]
print "The vector h^i is"
print hv
def cal_cijk(i,j,k):
di = [d1,d2,d3][i]
dj = [d1,d2,d3][j]
dk = [d1,d2,d3][k]
return variety.integrate(di*dj*dk*s*cy)
def cal_aij(i,j):
di = [d1,d2,d3][i]
dj = [d1,d2,d3][j]
return variety.integrate(di*dj*tc1*s*cy)
def cal_aiu(i):
di = [d1,d2,d3][i]
return variety.integrate(di*tc1*tc1*s*cy)
def cal_aio(i):
c = basecurvebasis[i]
return variety.integrate(tc1*c*s*cy)
def cal_a():
return variety.integrate(tc1*tc1*tc1*s*cy)
d8cc=totalChern([(1,[])])
d6cc1=totalChern([(1,[s])])
d6cc2=totalChern([(1,[d1])])
d6cc3=totalChern([(1,[d2])])
d6cc4=totalChern([(1,[d3])])
d4cc1=totalChern([(1,[s,d1])])
d4cc2=totalChern([(1,[s,d2])])
d4cc3=totalChern([(1,[s,d3])])
d4cc4=totalChern([(1,[d2,d3]),(-1,[d1,d3])])
d4cc5=totalChern([(1,[d1,d3])])
d4cc6=totalChern([(1,[d1,d2]),(-1,[d1,d3])])
d2cc1=totalChern([(1,[s,d2,d3]),(-1,[s,d1,d3])])
d2cc2=totalChern([(1,[s,d1,d3])])
d2cc3=totalChern([(1,[s,d1,d2]),(-1,[s,d1,d3])])
d2cc4=totalChern([(1,[d1,d2,d3])])
d0cc=totalChern([(1,[s,d1,d2,d3])])
chargeList = [d8cc,d6cc1,d6cc2,d6cc3,d6cc4,d4cc1,d4cc2,d4cc3,d4cc4,d4cc5,d4cc6,d2cc1,d2cc2,d2cc3,d2cc4,d0cc]
intersection = matrix([[variety.integrate(dualClass(f1)*f2*todd*cy) for f1 in chargeList] for f2 in chargeList])
print "The mirror dual 4-cycles intersect as"
print intersection
print ""
print "int="+("["+(str(intersection).replace("\n",",").replace(" ",",").replace(" ","").replace(" ","").replace(" ","").replace(" ","").replace(",,",",").replace(",,",",").replace(",,",",").replace("[,","["))+"]").replace("[","{").replace("]","}")+";"
tp_a = variety.integrate(tc1*tc1*tc1*d4*cy)
tp_ai = [variety.integrate(tc1*tc1*i*d4*cy) for i in [d1,d2,d3]]
tp_aij = [[variety.integrate(tc1*i*j*d4*cy) for i in [d1,d2,d3]] for j in [d1,d2,d3]]
tp_cijk = [[[variety.integrate(i*j*k*d4*cy) for i in [d1,d2,d3]] for j in [d1,d2,d3]] for k in [d1,d2,d3]]
tp_aio = [cal_aio(i) for i in range(3)]
print "a: " + str(tp_a) + "\n"
print "a_i: " + str(tp_ai) + "\n"
print "a_ij:\n" + str(matrix(tp_aij)) + "\n"
print "c_ijk: " + str(tp_cijk) + "\n"
print "a^i: " + str(tp_aio) + "\n"
print "h^i: " + str(hv)