Files
Calabi-Yau-Period-Geometry/README.md
T
Julian Piribauer 7217598d73
CI / lint (push) Successful in 1m20s
CI / test (push) Successful in 3m49s
Implementing Frobenius basis for PFIdeals
2026-11-01 16:46:13 +01:00

191 lines
6.9 KiB
Markdown

# Calabi-Yau-Period-Geometry
This project collects code used for analysing Calabi–Yau families.
It allows for computation of discriminant loci and topological data of manifolds defined as hypersurfaces or complete intersections in toric ambient spaces.
## toric_topdata
Supported initialisations are represented by the following examples.
```python
elliptic_curve_D = ToricPolytopeProjectiveSpace([3, 2, 1], model_name="elliptic_curve_D")
CY3_quintic = ToricPolytopeProjectiveSpace([1, 1, 1, 1, 1], model_name="quintic")
CY3_bicubic = ToricPolytopeCICY([[3, 3]], model_name="bi-cubic")
CICY3_two_parameter_manual_nef = ToricPolytope(
[
[1, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0],
[0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 1],
[-1, -1, 0, 0, 0, 0],
[0, 0, -1, -1, -1, -1],
],
nef_partition=[[0, 1, 2, 3], [4, 5, 6, 7]],
)
CICY5_two_parameter = ToricPolytopeCICY([[6, 1], [0, 2]])
```
The discriminant factors and topological data, e.g. for the quintic, can then be computed with the methods below.
```python
CY3_quintic.disc()
CY3_quintic.topdata()
```
We list the output of above two lines.
```term
INFO:__main__:Discriminant factors: [[z1 + 1/3125, 0]]
INFO:__main__:
--- Polytope and GLSM table ------------------
1|1|1|1|1|| 1
-1|1|0|0|0|| 0
-1|0|1|0|0|| 0
-1|0|0|1|0|| 0
-1|0|0|0|1|| 0
--------------
1,1,1,1,1; -5
--- L-vectors (GLSM charges) -----------------
[[1, 1, 1, 1, 1, -5]]
--- Intersection numbers CY ------------------
{(0, 0, 0): 5}
--- Intersection ring ------------------------
5*t0^3
--- Intersection ring no multiplicities ------
5*t0^3
--- Chern polynomials ------------------------
[[0], [10*t0^3], [-40*t0^3]]
--- Integrated Chern classes -----------------
[[0], [50], [-200]]
DEBUG:__main__:
--- Kähler cone generators (ambient space) ---
['[z4]']
--- Intersection numbers ambient space -------
{(0, 0, 0, 0): 1}
```
The result is saved in the folder `data/topdata` as a JSON file — giving a model name helps keeping
track of these outputs.
Note that for Calabi–Yau dimensions larger than four, the additional
## Operators and periods
`operators.sage` and `periods.sage` provide classes for working with Picard–Fuchs operators and their
period solutions: `PFOperator`, `PFIdeal` and `Period`, together with Ansatz variants of the first and
last (`PFOperatorAnsatz`, `PeriodAnsatz`) used to search for unknown operators or periods of a given
z- and theta-degree. The operator classes live in `operators.sage`, the period classes in `periods.sage`;
since the two depend on each other, load `periods.sage`, which also loads `operators.sage`.
A `PFOperator` is parsed from a string in the variables `z0, ..., z<n-1>` and `theta0, ..., theta<n-1>`,
the logarithmic derivatives theta_i = z_i d/dz_i. For example, the quintic's Picard&ndash;Fuchs operator:
```python
L = PFOperator(
"theta0^4 - 3125*z0*theta0^4 - 6250*z0*theta0^3 - 4375*z0*theta0^2 - 1250*z0*theta0 - 120*z0",
no_variables=1,
)
L.simplify().operator_string
```
```term
'-5*(5*theta0 + 4)*(5*theta0 + 3)*(5*theta0 + 2)*(5*theta0 + 1)*z0 + theta0^4'
```
An operator (or a `PFIdeal` of several) can be solved for its power series solution at given indicial
exponents and order.
```python
ideal = PFIdeal([L])
period = ideal.find_power_series_solution(indicials=[0], order=3)[0]
period.period_string
```
```term
'168168000*z0^3 + 113400*z0^2 + 120*z0 + 1'
```
The reverse direction is supported too: given a `Period`, `find_annihilating_operators` searches for
`PFOperator`s of a given z- and theta-degree that annihilate it, by solving an Ansatz of unknown
coefficients via linear algebra. Both directions extend to several moduli, e.g. for the two-parameter
model P_{2,2,2,1,1}[8]:
```python
M1 = PFOperator(
"theta1*(-2*theta0 + 2*theta1 - 1) + 2*(theta0 - 2*theta1 - 1)*(theta0 - 2*theta1)*z1",
no_variables=2,
)
M2 = PFOperator(
"theta0^2*(2*(theta0 - 2*theta1)*z1 - theta1) - 16*(2*theta0 + 1)*(4*theta0 + 1)*(4*theta0 + 3)*z0*z1",
no_variables=2,
)
ideal = PFIdeal([M1, M2])
period = ideal.find_power_series_solution(indicials=[0, 1 / 2], order=6)[0]
recovered = period.find_annihilating_operators(z_degree=1, theta_degree=2)
period.period_string
recovered[0].simplify().operator_string
```
```term
'-1/45045*(60886425600*z0^3*z1^3 - 2767564800*z0^2*z1^4 + 100638720*z0*z1^5 - 14192640*z1^6 + 830269440*z0^2*z1^3 - 30750720*z0*z1^4 + 4193280*z1^5 - 242161920*z0^2*z1^2 + 9884160*z0*z1^3 - 1281280*z1^4 - 3459456*z0*z1^2 + 411840*z1^3 + 1441440*z0*z1 - 144144*z1^2 + 60060*z1 - 45045)*sqrt(z1)'
'-2*(theta0 - 2*theta1)*(theta0 - 2*theta1 - 1)*z1 + (2*theta0 - 2*theta1 + 1)*theta1'
```
`recovered[0]` is, up to scale, `M1` &mdash; recovered purely from `M1`, `M2`'s shared power series
solution.
### Frobenius bases
A `PFIdeal` also computes its complete Frobenius basis &mdash; all solutions, logarithmic ones included &mdash;
at the origin of its current coordinates; for another point, move it to the origin with `change_coordinates`
first. The exponents are the `indicials`, the roots of the system's indicial ideal, which is completed by linear
algebra where the operators' z-free parts alone don't determine it. The optional `hodge_numbers` &mdash; the
numbers of solutions of top log-degree 0, 1, ..., n at a MUM point, e.g. `[1, 2, 2, 1]` for a two-parameter
threefold &mdash; certify that completion through their sum, the rank, and bound the powers of logarithms. For
P_{2,2,2,1,1}[8] at its MUM point and at the point (z0, z1) = (0, 1/4) on its strong coupling divisor:
```python
D1 = PFOperator(
"theta0^2*(theta0 - 2*theta1) - 4*z0*(4*theta0 + 3)*(4*theta0 + 2)*(4*theta0 + 1)",
no_variables=2,
)
D2 = PFOperator("theta1^2 - z1*(2*theta1 - theta0 + 1)*(2*theta1 - theta0)", no_variables=2)
ideal = PFIdeal([D1, D2], hodge_numbers=[1, 2, 2, 1])
strong_coupling = ideal.change_coordinates("z0", "z1 - 1/4")
ideal.indicials()
strong_coupling.indicials()
basis = strong_coupling.frobenius_basis(order=2)
basis[5].period_string
```
```term
[((0, 0), 6)]
[((0, 0), 4), ((0, 1/2), 2)]
INFO:__main__:Completed the indicial ideal at z = 0 at multiplier degree 2 with 1 extra operator(s): colength 6.
INFO:__main__:Exponent class of (0, 0): 4 solution(s) with leading terms ['1', 'log(z0)', 'log(z0)^2', 'log(z0)^3'].
INFO:__main__:Exponent class of (0, 1/2): 2 solution(s) with leading terms ['sqrt(z1)', 'sqrt(z1)*(log(z0) + log(z1))'].
INFO:__main__:Found a Frobenius basis of 6 solution(s) at order 2.
'-1/225*(7200*z0*z1*log(z0) - 720*z1^2*log(z0) + 7200*z0*z1*log(z1) - 720*z1^2*log(z1) + 33600*z0*z1 - 732*z1^2 + 300*z1*log(z0) + 300*z1*log(z1) + 250*z1 - 225*log(z0) - 225*log(z1))*sqrt(z1)'
```
Within each exponent class the basis is canonical: every solution has its own leading term with coefficient 1,
at which the class' other solutions vanish. Coefficients are those of plain powers of log(z_i), without factors
of 2&pi;i.