Complete Intersection Calabi-Yau Threefolds#
Release note on CICY provenance#
The CICY configuration matrices used here come from the standard Complete Intersection Calabi-Yau classifications, including the work of Candelas, Dale, Lütken, Schimmrigk, Green, and Hübsch. StringForge’s role is to expose cached rows, derived arrays, and model-loading conventions; it is not a claim of ownership over the underlying classification data.
Some derived columns may depend on collaborator-provided preprocessing or project-specific database builds. Treat those columns as documented interface examples unless the corresponding database metadata and citations are checked for the exact release you use. This notebook therefore uses deliberately soft wording: it demonstrates how to access and hand off CICY data, not that every derived CICY table is complete or independently publishable.
What’s in this notebook? This notebook explains how CICY threefolds can be loaded.
(Created: Andreas Schachner, June 25, 2024)
Imports#
# General imports
import warnings
import numpy as np
from tqdm.auto import tqdm
# JAX imports
from jax import vmap
import jax
import jax.numpy as jnp
jax.config.update("jax_enable_x64", True)
# Plotting
import seaborn as sn
import matplotlib.pyplot as plt
cmap = sn.color_palette("viridis", as_cmap=True)
# JAXVacua
import jaxvacua as jvc
warnings.filterwarnings('ignore')
Type IIB compactifications on CICYs#
Introduction#
Calabi-Yau (CY) threefolds play a central role in both algebraic geometry and theoretical physics, particularly in string theory, where they serve as compactification spaces for extra dimensions. Among the various constructions of Calabi–Yau threefolds, complete intersection Calabi-Yau (CICY) manifolds form a distinguished and well-studied class. These are defined as the zero loci of a set of polynomial equations within a higher-dimensional ambient space, typically a product of projective spaces.
The defining characteristic of a Calabi–Yau manifold is the vanishing of its first Chern class, ensuring the existence of a Ricci-flat Kähler metric. For a complete intersection in a toric or projective setting, this condition can be systematically realised through an appropriate choice of defining equations and embedding space.
CICY threefolds were systematically classified by Candelas, Green, and others in the late 1980s (see Nucl.Phys.B 298 (1988) 493 and Class.Quant.Grav. 6 (1989) 105-124), leading to an important dataset of manifolds that have been extensively used in string compactifications. These spaces are typically described by configuration matrices, encoding the structure of the defining equations and their embedding spaces.
Beyond their mathematical interest, CICY manifolds provide fertile ground for model building in string phenomenology. Their relatively simple construction makes them amenable to computational methods, and their moduli spaces are crucial for understanding physical properties such as Yukawa couplings and gauge symmetries.
In what follows, we introduce the basic formalism of CICY manifolds, outline their classification, and discuss their role in physics. We begin by reviewing the mathematical framework necessary for their construction.
The original list of favorable CICYs of Nucl.Phys.B 298 (1988) 493 was expanded to 7,842 in 1708.07907 (see also 2112.12106) by finding new favorable descriptions. After removing redundancies, there are 25 distinct geometries (24 hypersurfaces in an ambient product of two del Pezzo surfaces plus the Schoen manifold) for which no such favorable representative exists. Out of the 7,842 favorable geometries, one obtains 4,874 Kähler favorable CICYs whose Kähler cones are inherited from the ambient space corresponding to the entire positive orthant. After removing redundancies, there are 4,525 geometries of which 107 have \(h^{1,1}\geq 10\).
For the non-Kähler favorable CICYs, we can obtain the Kähler cone as follows. We compute the Mori cones generated by the rays obtained from GV invariants. The dual cone corresponds to an approximation of the Kähler cone. We restrict to \(h^{1,1}\leq 9\) for which GV invariants up to degree 10 have been obtained in 2101.07272. We use this list of GV invariants to obtain approximations of the corresponding Kähler cones for all favorable CICYs that are not Kähler favorable. We find 1,637 CICYs after removing redundancies as mentioned before. Overall, there are 1,033 favorable CICYs with \(h^{1,1}\geq 10\) for which we have not computed any GV invariants.
CICY data#
We can browse the CICY catalog using the CICYDatabase interface (see also the database-interface tutorial):
Via the database (recommended):
from stringforge.lcs_database import LCSDatabase
db = LCSDatabase(dataset="cicy")
CICYs = db.query()
CICYs[CICYs["h12"]==1]
---------------------------------------------------------------------------
HTTPStatusError Traceback (most recent call last)
File /opt/anaconda3/envs/cytools-dev-jax/lib/python3.13/site-packages/huggingface_hub/utils/_http.py:761, in hf_raise_for_status(response, endpoint_name)
760 try:
--> 761 response.raise_for_status()
762 except httpx.HTTPStatusError as e:
File /opt/anaconda3/envs/cytools-dev-jax/lib/python3.13/site-packages/httpx/_models.py:829, in Response.raise_for_status(self)
828 message = message.format(self, error_type=error_type)
--> 829 raise HTTPStatusError(message, request=request, response=self)
HTTPStatusError: Client error '404 Not Found' for url 'https://huggingface.co/datasets/aschachner/cy-database/resolve/main/cicy/catalog.parquet'
For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404
The above exception was the direct cause of the following exception:
RemoteEntryNotFoundError Traceback (most recent call last)
File ~/Software/GitHub/jax-work/stringforge/stringforge/cy_io.py:911, in CYDatabase._download_file(self, hf_path, local_path)
904 _quiet = type("_QuietTqdm", (), {
905 "__init__": lambda s, *a, **kw: None,
906 "__enter__": lambda s: s,
(...) 909 "close": lambda s: None,
910 })
--> 911 downloaded = hf_hub_download(
912 repo_id=self.hf_repo,
913 filename=hf_path,
914 repo_type="dataset",
915 local_dir=str(local_path.parent),
916 tqdm_class=_quiet,
917 )
918 # huggingface_hub may place the file in a subdirectory; move if needed.
File /opt/anaconda3/envs/cytools-dev-jax/lib/python3.13/site-packages/huggingface_hub/utils/_validators.py:88, in validate_hf_hub_args.<locals>._inner_fn(*args, **kwargs)
86 kwargs = smoothly_deprecate_legacy_arguments(fn_name=fn.__name__, kwargs=kwargs)
---> 88 return fn(*args, **kwargs)
File /opt/anaconda3/envs/cytools-dev-jax/lib/python3.13/site-packages/huggingface_hub/file_download.py:976, in hf_hub_download(repo_id, filename, subfolder, repo_type, revision, library_name, library_version, cache_dir, local_dir, user_agent, force_download, etag_timeout, token, local_files_only, headers, endpoint, tqdm_class, dry_run)
975 if local_dir is not None:
--> 976 return _hf_hub_download_to_local_dir(
977 # Destination
978 local_dir=local_dir,
979 # File info
980 repo_id=repo_id,
981 repo_type=repo_type,
982 filename=filename,
983 revision=revision,
984 # HTTP info
985 endpoint=endpoint,
986 etag_timeout=etag_timeout,
987 headers=hf_headers,
988 token=token,
989 # Additional options
990 cache_dir=cache_dir,
991 force_download=force_download,
992 local_files_only=local_files_only,
993 tqdm_class=tqdm_class,
994 dry_run=dry_run,
995 )
996 else:
File /opt/anaconda3/envs/cytools-dev-jax/lib/python3.13/site-packages/huggingface_hub/file_download.py:1288, in _hf_hub_download_to_local_dir(local_dir, repo_id, repo_type, filename, revision, endpoint, etag_timeout, headers, token, cache_dir, force_download, local_files_only, tqdm_class, dry_run)
1287 # Local file doesn't exist or commit_hash doesn't match => we need the etag
-> 1288 (url_to_download, etag, commit_hash, expected_size, xet_file_data, head_call_error) = _get_metadata_or_catch_error(
1289 repo_id=repo_id,
1290 filename=filename,
1291 repo_type=repo_type,
1292 revision=revision,
1293 endpoint=endpoint,
1294 etag_timeout=etag_timeout,
1295 headers=headers,
1296 token=token,
1297 local_files_only=local_files_only,
1298 )
1300 if head_call_error is not None:
1301 # No HEAD call but local file exists => default to local file
File /opt/anaconda3/envs/cytools-dev-jax/lib/python3.13/site-packages/huggingface_hub/file_download.py:1669, in _get_metadata_or_catch_error(repo_id, filename, repo_type, revision, endpoint, etag_timeout, headers, token, local_files_only, relative_filename, storage_folder, retry_on_errors)
1668 try:
-> 1669 metadata = get_hf_file_metadata(
1670 url=url,
1671 timeout=etag_timeout,
1672 headers=headers,
1673 token=token,
1674 endpoint=endpoint,
1675 retry_on_errors=retry_on_errors,
1676 )
1677 except RemoteEntryNotFoundError as http_error:
File /opt/anaconda3/envs/cytools-dev-jax/lib/python3.13/site-packages/huggingface_hub/utils/_validators.py:88, in validate_hf_hub_args.<locals>._inner_fn(*args, **kwargs)
86 kwargs = smoothly_deprecate_legacy_arguments(fn_name=fn.__name__, kwargs=kwargs)
---> 88 return fn(*args, **kwargs)
File /opt/anaconda3/envs/cytools-dev-jax/lib/python3.13/site-packages/huggingface_hub/file_download.py:1591, in get_hf_file_metadata(url, token, timeout, library_name, library_version, user_agent, headers, endpoint, retry_on_errors)
1590 # Retrieve metadata
-> 1591 response = _httpx_follow_relative_redirects_with_backoff(
1592 method="HEAD", url=url, headers=hf_headers, timeout=timeout, retry_on_errors=retry_on_errors
1593 )
1594 hf_raise_for_status(response)
File /opt/anaconda3/envs/cytools-dev-jax/lib/python3.13/site-packages/huggingface_hub/utils/_http.py:692, in _httpx_follow_relative_redirects_with_backoff(method, url, retry_on_errors, **httpx_kwargs)
685 response = http_backoff(
686 method=method,
687 url=url,
(...) 690 **no_retry_kwargs,
691 )
--> 692 hf_raise_for_status(response)
694 # Check if response is a relative redirect
File /opt/anaconda3/envs/cytools-dev-jax/lib/python3.13/site-packages/huggingface_hub/utils/_http.py:781, in hf_raise_for_status(response, endpoint_name)
780 message = f"{response.status_code} Client Error." + "\n\n" + f"Entry Not Found for url: {response.url}."
--> 781 raise _format(RemoteEntryNotFoundError, message, response, repo_type=repo_type, repo_id=repo_id) from e
783 elif error_code == "GatedRepo":
RemoteEntryNotFoundError: 404 Client Error. (Request ID: Root=1-6a262115-28a9ab61595be3dd319cb9af;12a6dad0-908b-4a04-b1f9-29055bdfc77d)
Entry Not Found for url: https://huggingface.co/datasets/aschachner/cy-database/resolve/main/cicy/catalog.parquet.
The above exception was the direct cause of the following exception:
RuntimeError Traceback (most recent call last)
Cell In[2], line 5
1 from stringforge.lcs_database import LCSDatabase
4 db = LCSDatabase(dataset="cicy")
----> 5 CICYs = db.query()
6 CICYs[CICYs["h12"]==1]
File ~/Software/GitHub/jax-work/stringforge/stringforge/lcs_database.py:219, in LCSDatabase.query(self, h11, h12, has_conifolds, n_conifolds_min, n_conifolds_max, has_gv, D3_tadpole_max, **filters)
191 def query(
192 self,
193 h11: Optional[int] = None,
(...) 200 **filters: Any,
201 ) -> Any:
202 r"""Filter the catalog and return matching models in mirror convention.
203
204 Same semantics as :meth:`CYDatabase.query`, except both the
(...) 217 misleading. This mirrors the ``chi=None`` line in :meth:`load`.
218 """
--> 219 df = super().query(
220 h11=h12,
221 h12=h11,
222 has_conifolds=has_conifolds,
223 n_conifolds_min=n_conifolds_min,
224 n_conifolds_max=n_conifolds_max,
225 has_gv=has_gv,
226 D3_tadpole_max=D3_tadpole_max,
227 **filters,
228 )
229 return _swap_h_columns(df).drop(columns=["chi"], errors="ignore")
File ~/Software/GitHub/jax-work/stringforge/stringforge/cy_io.py:1289, in CYDatabase.query(self, h11, h12, has_conifolds, n_conifolds_min, n_conifolds_max, has_gv, D3_tadpole_max, **filters)
1246 def query(
1247 self,
1248 h11: Optional[int] = None,
(...) 1255 **filters: Any,
1256 ) -> Any:
1257 r"""
1258 **Description:**
1259 Filter the catalog and return a ``pandas.DataFrame`` of matching models.
(...) 1287 pandas.DataFrame: Matching rows from the catalog.
1288 """
-> 1289 self._ensure_catalog()
1290 mask = np.ones(len(self._catalog), dtype=bool)
1292 if h11 is not None:
File ~/Software/GitHub/jax-work/stringforge/stringforge/cy_io.py:853, in CYDatabase._ensure_catalog(self)
847 if self.offline:
848 raise FileNotFoundError(
849 f"Catalog not found in cache ({catalog_path}) and "
850 "offline=True. Run with offline=False first to "
851 "download it."
852 )
--> 853 self._download_file(f"{self.dataset}/catalog.parquet", catalog_path)
855 self._catalog = pd.read_parquet(catalog_path)
File ~/Software/GitHub/jax-work/stringforge/stringforge/cy_io.py:923, in CYDatabase._download_file(self, hf_path, local_path)
921 shutil.move(downloaded, local_path)
922 except Exception as exc:
--> 923 raise RuntimeError(
924 f"Failed to download '{hf_path}' from '{self.hf_repo}': {exc}"
925 ) from exc
RuntimeError: Failed to download 'cicy/catalog.parquet' from 'aschachner/cy-database': 404 Client Error. (Request ID: Root=1-6a262115-28a9ab61595be3dd319cb9af;12a6dad0-908b-4a04-b1f9-29055bdfc77d)
Entry Not Found for url: https://huggingface.co/datasets/aschachner/cy-database/resolve/main/cicy/catalog.parquet.
Here, the individual entries
CICY ID: Standard ID for the CICYs.h11andh12: Hodge numbers of the Calabi-Yau.favorable: Whether or not the CY can be favorably embedded (obtained from 1708.07907).Kahler favorable: Whether or not the CY is Kahler favorable (obtained from 1708.07907).product: Whether the ambient space is a product space (obtained from 1708.07907).equivalence: Equivalence to another CICY (obtained from 2101.07272).
Alternatively, the CICY catalog can be loaded from the local pickle file shipped with the package:
import pickle, os
cicy_path = os.path.join(jvc.__path__[0], "models", "CICY", "CICY_dataframe.p")
with open(cicy_path, "rb") as f:
CICYs_local = pickle.load(f)
CICYs_local.head()
Loading CICY models#
The mirror quintic#
As a first example, we can load the mirror quintic (CICY ID 7890) using the database:
tree = db.load(cicy_id=7890, include_gv=True, maximum_degree=10)
model = jvc.FluxEFT(lcs_tree_input=tree, Q=100)
model
We can call the topological data of model through the lcs_tree:
(f"intersection numbers: {model.lcs_tree.intnums.astype(int)}",
f"Euler character: {model.lcs_tree.chi}",
f"Second Chern class: {model.lcs_tree.c2}",
f"Leading order GV invariants: {model.lcs_tree.gv_inv[:4].astype(int)}")
We can also load some additional information about the chosen CICY by calling:
model.lcs_tree.extra_data
Let us test a few explicit solutions for the F-term conditions \(D_zW=D_\tau W=0\):
fluxes = jnp.array([[ 13, -14, -3, -1, -4, -4, 5, -2],
[-31, 8, -3, -1, 7, 2, -2, 1],
[ 13, -17, 2, 0, -4, -8, 2, -2],
[ -4, 30, 1, 5, 0, -9, -2, 1],
[-23, -10, 4, -4, -1, -1, -4, 0]])
moduli = jnp.array([[-0.33957014+1.14038076j],
[ 0.16328305+1.83965502j],
[ 0.08654968+1.54423725j],
[ 0.11764233+1.50070858j],
[ 0.11973228+1.16350409j]])
tau = jnp.array([-0.08966074+2.72528655j, -0.02904458+2.57532019j, 0.4228709 +2.02225755j, 0.27414269+1.80896j, -1.37897558+4.3308653j])
We can evaluate \(D_zW, D_\tau W\) as well as \(W_0\) and \(N_{\mathrm{flux}}\)
DW = jnp.abs(vmap(model.DW)(moduli,jnp.conj(moduli),tau,jnp.conj(tau),fluxes))
W0 = vmap(model.superpotential_gauge_invariant)(moduli,tau,fluxes)
Nflux = vmap(model.tadpole)(fluxes)
print(r"Residual for the F-term conditions DW: ",np.sum(DW,axis=1))
We plot the solutions below
fig, ax = plt.subplots(2, 2,dpi=200,figsize=(6,4))
fs = 8
sn.scatterplot(x=moduli[:,0].real,y=moduli[:,0].imag,s=5,ax=ax[0,0],hue = Nflux,palette=cmap)
ax[0,0].legend_.remove()
ax[0,0].set_xlabel(r"Re$(z_1)$",fontsize = fs)
ax[0,0].set_ylabel(r"Im$(z_1)$",fontsize = fs)
sn.scatterplot(x=tau.real,y=tau.imag,s=5,ax=ax[0,1],hue = Nflux,palette=cmap)
ax[0,1].legend_.remove()
ax[0,1].set_xlabel(r"Re$(\tau)$",fontsize = fs)
ax[0,1].set_ylabel(r"Im$(\tau)$",fontsize = fs)
sn.scatterplot(x=np.log10(DW[:,0]),y=np.log10(DW[:,1]),s=5,ax=ax[1,0],hue = Nflux,palette=cmap)
ax[1,0].legend_.remove()
ax[1,0].set_xlabel(r"$\log_{10}(|DW_z|)$",fontsize = fs)
ax[1,0].set_ylabel(r"$\log_{10}(|DW_\tau|)$",fontsize = fs)
sn.scatterplot(x=W0.real,y=W0.imag,s=4,ax=ax[1,1],hue = Nflux,palette=cmap)
#ax[1,1].set_xlim(-5,5)
#ax[1,1].set_ylim(0,10)
ax[1,1].legend_.remove()
ax[1,1].set_xlabel(r"Re$(W_0)$",fontsize = fs)
ax[1,1].set_ylabel(r"Im$(W_0)$",fontsize = fs)
#ax[1,1].set_title("Superpotential",fontsize=10)
for i in range(2):
for j in range(2):
ax[i,j].tick_params(labelsize=fs-1)
plt.tight_layout()
norm = plt.Normalize(min(Nflux),max(Nflux))
sm = plt.cm.ScalarMappable(cmap="viridis", norm=norm)
sm.set_array([])
clb = fig.colorbar(sm, label=r"$N_{\mathrm{flux}}$", ax=ax.ravel().tolist())
clb.ax.tick_params(labelsize=fs)
plt.show()
Calabi–Yau threefold of Hulek–Verrill#
Another Calabi–Yau threefold is that of Hulek–Verrill recently studied in https://arxiv.org/pdf/2404.12422. It has \(h^{1,2}=5\) and \(h^{1,1}=45\) and can be loaded as follows:
tree_hv = db.load(cicy_id=7447, include_gv=True, maximum_degree=10)
model = jvc.FluxEFT(lcs_tree_input=tree_hv, Q=100)
model
As above, we can look at the model data as follows:
(f"intersection numbers: {model.lcs_tree.intnums.astype(int)}",
f"Euler character: {model.lcs_tree.chi}",
f"Second Chern class: {model.lcs_tree.c2}",
f"Leading order GV invariants: {model.lcs_tree.gv_inv[:10].astype(int)}")