diff --git a/experimental/FTheoryTools/docs/src/g4.md b/experimental/FTheoryTools/docs/src/g4.md index 2715d8000fd9..43c16b13a9fc 100644 --- a/experimental/FTheoryTools/docs/src/g4.md +++ b/experimental/FTheoryTools/docs/src/g4.md @@ -22,6 +22,7 @@ We currently support the following attributes: ```@docs model(gf::G4Flux) cohomology_class(gf::G4Flux) +d3_tadpole_constraint(gf::G4Flux; check::Bool = true) ``` ## Methods @@ -108,6 +109,7 @@ Families of G4-fluxes currently support the following attributes: model(gf::FamilyOfG4Fluxes) matrix_integral(gf::FamilyOfG4Fluxes) matrix_rational(gf::FamilyOfG4Fluxes) +d3_tadpole_constraint(fgs::FamilyOfG4Fluxes; check::Bool = true) ``` ### Properties diff --git a/experimental/FTheoryTools/src/FamilyOfG4Fluxes/attributes.jl b/experimental/FTheoryTools/src/FamilyOfG4Fluxes/attributes.jl index 56d7836cf784..2f7b04cbcd8f 100644 --- a/experimental/FTheoryTools/src/FamilyOfG4Fluxes/attributes.jl +++ b/experimental/FTheoryTools/src/FamilyOfG4Fluxes/attributes.jl @@ -94,3 +94,158 @@ true ``` """ matrix_rational(gf::FamilyOfG4Fluxes) = gf.mat_rat + + +##################################################### +# 2 Compute the D3-tadpole constraint +##################################################### + +@doc raw""" + d3_tadpole_constraint(fgs::FamilyOfG4Fluxes; check::Bool = true) + +Return the d3-tapdole constraint of a family of G4-fluxes. Recall that for a given $G_4$-flux, this constraint +is $- \frac{1}{2} \cdot G_4^2 + \frac{1}{24} \cdot \chi(\widehat{Y}_4) \stackrel{!}{\geq} 0$. + +Note that the family of fluxes is specified by linear combination of cohomology classes, some with rational +and some with integral coefficients. In terms of these coefficients the d3-tadpole constraint is the demand +that a quadratic polynomial in the coefficients evaluates to a non-negative number. This method returns said +polynomial in the cofficients. In order to evaluate the D3-tadpole for a particular $G_4$-flux, one has to +evaluate this polynomial for the numeric coefficient values that correspond to the given $G_4$-flux. + +We use symbols $a_i$ to indicate integral coefficients and $r_i$ to indicate rational coefficients. + +```jldoctest; setup = :(Oscar.LazyArtifacts.ensure_artifact_installed("QSMDB", Oscar.LazyArtifacts.find_artifacts_toml(Oscar.oscardir))) +julia> qsm_model = literature_model(arxiv_id = "1903.00009", model_parameters = Dict("k" => 2021)) +Hypersurface model over a concrete base + +julia> fgs = special_flux_family(qsm_model, check = false) +A family of G4 fluxes: + - Elementary quantization checks: satisfied + - Verticality checks: failed + - Non-abelian gauge group: broken + +julia> d3_tadpole_constraint(fgs); +``` +""" +function d3_tadpole_constraint(fgs::FamilyOfG4Fluxes; check::Bool = true) + + # Is the result known? + if has_attribute(fgs, :d3_tadpole_constraint) + return get_attribute(fgs, :d3_tadpole_constraint)::QQMPolyRingElem + end + + # Entry checks + m = model(fgs) + @req base_space(m) isa NormalToricVariety "Computation of D3-tadpole constraint only supported for toric base and ambient spaces" + @req dim(ambient_space(m)) == 5 "Computation of D3-tadpole constraint only supported for 5-dimensional toric ambient spaces" + if check + @req is_complete(ambient_space(m)) "Computation of D3-tadpole constraint only supported for complete toric ambient spaces" + @req is_simplicial(ambient_space(m)) "Computation of D3-tadpole constraint only supported for simplicial toric ambient space" + end + + # Are intersection numbers known? + inter_dict = get_attribute!(m, :inter_dict) do + Dict{NTuple{4, Int64}, ZZRingElem}() + end::Dict{NTuple{4, Int64}, ZZRingElem} + s_inter_dict = get_attribute!(m, :s_inter_dict) do + Dict{String, ZZRingElem}() + end::Dict{String, ZZRingElem} + + # Compute data, that is used by the default/sophisticated intersection product + if arxiv_doi(m) == "10.48550/arXiv.1511.03209" + S = cox_ring(ambient_space(m)) + gS = gens(cox_ring(ambient_space(m))) + linear_relations = matrix(QQ, rays(ambient_space(m))) + scalings = [c.coeff for c in S.d] + mnf = Oscar._minimal_nonfaces(ambient_space(m)) + sr_ideal_pos = [Vector{Int}(Polymake.row(mnf, i)) for i in 1:Polymake.nrows(mnf)] + data = ( + S = S, + gS = gS, + linear_relations = linear_relations, + scalings = scalings, + sr_ideal_pos = sr_ideal_pos + ) + else + cy = polynomial(cohomology_class(toric_divisor_class(ambient_space(m), degree(hypersurface_equation(m))))) + end + + # Find the number of integral and rational parameters + numb_int_parameters = ncols(matrix_integral(fgs)) + numb_rat_parameters = ncols(matrix_rational(fgs)) + + # Create a polynomial ring with parameters ai for the integral_parameters and ri for the rational parameters + amb_ring, my_gens = polynomial_ring(QQ, "a#" => 1:numb_int_parameters, "r#" => 1: numb_rat_parameters) + + # Extract ambient space basis of G4-flux candidates used to express flux family in + basis = ambient_space_models_of_g4_fluxes(m, check = check) + basis_indices = get_attribute(m, :ambient_space_models_of_g4_fluxes_indices)::Vector{Tuple{Int64, Int64}} + + # Use MPolyBuildCtx to compute the tadpole constraint. + C = MPolyBuildCtx(amb_ring) + exp_vec = fill(0, numb_int_parameters + numb_rat_parameters) + for k1 in 1:ngens(amb_ring) + for k2 in k1:ngens(amb_ring) + + # Extract generator k1 + if numb_int_parameters >= k1 + gen1 = matrix_integral(fgs)[:, k1] + else + gen1 = matrix_rational(fgs)[:, k1 - numb_int_parameters] + end + + # Extract generator k2 + if numb_int_parameters >= k2 + gen2 = matrix_integral(fgs)[:, k2] + else + gen2 = matrix_rational(fgs)[:, k2 - numb_int_parameters] + end + + # Compute the intersection number of generator k1 and generator k2 + inter_number = ZZ(0) + for l1 in 1:length(basis) + for l2 in l1:length(basis) + + val = gen1[l1] * gen2[l2] + is_zero(val) && continue + + my_tuple = Tuple(sort([basis_indices[l1]..., basis_indices[l2]...])) + + if arxiv_doi(m) == "10.48550/arXiv.1511.03209" + change = sophisticated_intersection_product(ambient_space(m), my_tuple, hypersurface_equation(m), inter_dict, s_inter_dict, data) + else + change = get!(inter_dict, my_tuple) do + return QQ(integrate(cohomology_class(ambient_space(m), polynomial(basis[l1]) * polynomial(basis[l2]) * cy); check = check)) + end + end + + if l1 == l2 + inter_number += val * change + else + inter_number += 2 * val * change + end + + end + end + + # Update the D3-tadpole constraint polynomial + exp_vec[k1] += 1 + exp_vec[k2] += 1 + if k1 == k2 + push_term!(C, inter_number, exp_vec) + else + push_term!(C, 2 * inter_number, exp_vec) + end + exp_vec[k1] = 0 + exp_vec[k2] = 0 + + end + end + tadpole_constraint_polynomial = finish(C) + tadpole_constraint_polynomial = -1//2 * tadpole_constraint_polynomial + 1//24 * euler_characteristic(m, check = check) + set_attribute!(fgs, :d3_tadpole_constraint, tadpole_constraint_polynomial) + + # Finally, return the result + return tadpole_constraint_polynomial::QQMPolyRingElem + +end diff --git a/experimental/FTheoryTools/src/FamilyOfG4Fluxes/special_constructors.jl b/experimental/FTheoryTools/src/FamilyOfG4Fluxes/special_constructors.jl index 9cdc126e8cc7..1472c90c5d07 100644 --- a/experimental/FTheoryTools/src/FamilyOfG4Fluxes/special_constructors.jl +++ b/experimental/FTheoryTools/src/FamilyOfG4Fluxes/special_constructors.jl @@ -8,7 +8,7 @@ properties. This family is modelled by the restriction of cohomology classes on the toric ambient space to the hypersurface in question. In the toric ambient space, those cohomology classes are vertical, i.e. are of the form $a \wedge b$ for -$a,b \in H^(1,1)(X_\Sigma)$ with $X_\Sigma$. Note that this does NOT mean that +$a,b \in H^(1,1)(X_\Sigma)$ with $X_\Sigma$. Note that this does NOT mean that they are vertical on the hypersurface, which defines the actual F-theory geometry. We further subject this family to the consistency conditions for being well-quantized. Unless explicitly asked differently, it is this family of @@ -159,7 +159,7 @@ function well_quantized_ambient_space_models_of_g4_fluxes(m::AbstractFTheoryMode # (2) Compute data, that is frequently used by the sophisticated intersection product below S = cox_ring(ambient_space(m)) gS = gens(cox_ring(ambient_space(m))) - linear_relations = matrix(QQ, matrix(ZZ, rays(ambient_space(m)))) + linear_relations = matrix(QQ, rays(ambient_space(m))) scalings = [c.coeff for c in S.d] mnf = Oscar._minimal_nonfaces(ambient_space(m)) sr_ideal_pos = [Vector{Int}(Polymake.row(mnf, i)) for i in 1:Polymake.nrows(mnf)] @@ -400,7 +400,7 @@ function well_quantized_and_vertical_ambient_space_models_of_g4_fluxes(m::Abstra # (2) Compute data, that is frequently used by the sophisticated intersection product below S = cox_ring(ambient_space(m)) gS = gens(cox_ring(ambient_space(m))) - linear_relations = matrix(QQ, matrix(ZZ, rays(ambient_space(m)))) + linear_relations = matrix(QQ, rays(ambient_space(m))) scalings = [c.coeff for c in S.d] mnf = Oscar._minimal_nonfaces(ambient_space(m)) sr_ideal_pos = [Vector{Int}(Polymake.row(mnf, i)) for i in 1:Polymake.nrows(mnf)] @@ -735,7 +735,7 @@ function well_quantized_and_vertical_and_no_non_abelian_gauge_group_breaking_amb # (2) Compute data, that is frequently used by the sophisticated intersection product below S = cox_ring(ambient_space(m)) gS = gens(cox_ring(ambient_space(m))) - linear_relations = matrix(QQ, matrix(ZZ, rays(ambient_space(m)))) + linear_relations = matrix(QQ, rays(ambient_space(m))) scalings = [c.coeff for c in S.d] mnf = Oscar._minimal_nonfaces(ambient_space(m)) sr_ideal_pos = [Vector{Int}(Polymake.row(mnf, i)) for i in 1:Polymake.nrows(mnf)] diff --git a/experimental/FTheoryTools/src/G4Fluxes/attributes.jl b/experimental/FTheoryTools/src/G4Fluxes/attributes.jl index 34f0231822f0..804b01376543 100644 --- a/experimental/FTheoryTools/src/G4Fluxes/attributes.jl +++ b/experimental/FTheoryTools/src/G4Fluxes/attributes.jl @@ -54,3 +54,57 @@ true ``` """ cohomology_class(gf::G4Flux) = gf.class + + + +##################################################### +# 2 Compute the D3-tadpole constraint +##################################################### + +@doc raw""" + d3_tadpole_constraint(gf::G4Flux; check::Bool = true) + +Return the d3-tapdole constraint of a G4-flux, that is compute the quantity +$- \frac{1}{2} \cdot G_4^2 + \frac{1}{24} \cdot \chi(\widehat{Y}_4) \stackrel{!}{\geq} 0$. + +```jldoctest; setup = :(Oscar.LazyArtifacts.ensure_artifact_installed("QSMDB", Oscar.LazyArtifacts.find_artifacts_toml(Oscar.oscardir))) +julia> qsm_model = literature_model(arxiv_id = "1903.00009", model_parameters = Dict("k" => 4)) +Hypersurface model over a concrete base + +julia> divs = torusinvariant_prime_divisors(ambient_space(qsm_model)); + +julia> e1 = cohomology_class(divs[35]);e2 = cohomology_class(divs[32]);e4 = cohomology_class(divs[34]); + +julia> u = cohomology_class(divs[33]);v = cohomology_class(divs[30]);pb_Kbar = cohomology_class(sum([divs[k] for k in 1:29])); + +julia> g4_class = (-3) // kbar3(qsm_model) * (5 * e1 * e4 + pb_Kbar * (-3 * e1 - 2 * e2 - 6 * e4 + pb_Kbar - 4 * u + v)); + +julia> g4 = g4_flux(qsm_model, g4_class, check = false) +G4-flux candidate + - Elementary quantization checks: not executed + - Tadpole cancellation check: not executed + - Verticality checks: not executed + - Non-abelian gauge group: breaking pattern not analyzed + +julia> d3_tadpole_constraint(g4, check = false) +12 +``` +""" +function d3_tadpole_constraint(gf::G4Flux; check::Bool = true) + if has_attribute(gf, :d3_tadpole_constraint) + return get_attribute(gf, :d3_tadpole_constraint)::QQFieldElem + end + m = model(gf) + @req (m isa WeierstrassModel || m isa GlobalTateModel || m isa HypersurfaceModel) "Tadpole cancellation checks for G4-fluxes only supported for Weierstrass, global Tate and hypersurface models" + @req base_space(m) isa NormalToricVariety "Tadpole cancellation checks for G4-flux currently supported only for toric base" + @req ambient_space(m) isa NormalToricVariety "Tadpole cancellation checks for G4-flux currently supported only for toric ambient space" + if check + @req is_complete(ambient_space(m)) "Computation of D3-tadpole constraint only supported for complete toric ambient spaces" + @req is_simplicial(ambient_space(m)) "Computation of D3-tadpole constraint only supported for simplicial toric ambient space" + end + cy = polynomial(cohomology_class(toric_divisor_class(ambient_space(m), degree(hypersurface_equation(m))))) + numb = QQ(euler_characteristic(m; check = check)//24 - 1//2*integrate(cohomology_class(ambient_space(m), polynomial(cohomology_class(gf)) * polynomial(cohomology_class(gf)) * cy); check = check)) + set_attribute!(gf, :d3_tadpole_constraint, numb) + set_attribute!(gf, :passes_tadpole_cancellation_check, (numb >= 0 && is_integer(numb))) + return numb::QQFieldElem +end diff --git a/experimental/FTheoryTools/src/G4Fluxes/properties.jl b/experimental/FTheoryTools/src/G4Fluxes/properties.jl index 65471570972c..a4f02d4cfe82 100644 --- a/experimental/FTheoryTools/src/G4Fluxes/properties.jl +++ b/experimental/FTheoryTools/src/G4Fluxes/properties.jl @@ -182,16 +182,8 @@ G4-flux candidate @req (m isa WeierstrassModel || m isa GlobalTateModel || m isa HypersurfaceModel) "Tadpole cancellation checks for G4-fluxes only supported for Weierstrass, global Tate and hypersurface models" @req base_space(m) isa NormalToricVariety "Tadpole cancellation checks for G4-flux currently supported only for toric base" @req ambient_space(m) isa NormalToricVariety "Tadpole cancellation checks for G4-flux currently supported only for toric ambient space" - - # Compute the cohomology class corresponding to the hypersurface equation - cy = polynomial(cohomology_class(toric_divisor_class(ambient_space(m), degree(hypersurface_equation(m))))) - - # Now check if the D3-tadpole cancellation condition holds - numb = euler_characteristic(m; check = false)/24 - 1/2*integrate(cohomology_class(ambient_space(m), polynomial(cohomology_class(g4)) * polynomial(cohomology_class(g4)) * cy); check = false) - if numb > 0 && is_integer(numb) - return true - end - return false + numb = d3_tadpole_constraint(g4, check = false) + return numb >= 0 && is_integer(numb) end diff --git a/experimental/FTheoryTools/src/Serialization/hypersurface_models.jl b/experimental/FTheoryTools/src/Serialization/hypersurface_models.jl index 24582dbc4c31..d9893d2604f6 100644 --- a/experimental/FTheoryTools/src/Serialization/hypersurface_models.jl +++ b/experimental/FTheoryTools/src/Serialization/hypersurface_models.jl @@ -97,6 +97,9 @@ function save_object(s::SerializerState, h::HypersurfaceModel) res = well_quantized_ambient_space_models_of_g4_fluxes(h, check = false) attrs_dict[:well_quantized_integral] = matrix_integral(res) attrs_dict[:well_quantized_rational] = matrix_rational(res) + if has_attribute(res, :d3_tadpole_constraint) + attrs_dict[:well_quantized_d3_tadpole] = d3_tadpole_constraint(res) + end end # Do we know the well-quantized and vertical G4-fluxes @@ -104,6 +107,9 @@ function save_object(s::SerializerState, h::HypersurfaceModel) res = well_quantized_and_vertical_ambient_space_models_of_g4_fluxes(h, check = false) attrs_dict[:well_quantized_and_vertical_integral] = matrix_integral(res) attrs_dict[:well_quantized_and_vertical_rational] = matrix_rational(res) + if has_attribute(res, :d3_tadpole_constraint) + attrs_dict[:well_quantized_and_vertical_d3_tadpole] = d3_tadpole_constraint(res) + end end # Do we know the well-quantized, vertical G4-fluxes that do not break the non-Abelian gauge group? @@ -111,6 +117,9 @@ function save_object(s::SerializerState, h::HypersurfaceModel) res = well_quantized_and_vertical_and_no_non_abelian_gauge_group_breaking_ambient_space_models_of_g4_fluxes(h, check = false) attrs_dict[:well_quantized_vertical_no_break_integral] = matrix_integral(res) attrs_dict[:well_quantized_vertical_no_break_rational] = matrix_rational(res) + if has_attribute(res, :d3_tadpole_constraint) + attrs_dict[:well_quantized_vertical_and_no_breaking_d3_tadpole] = d3_tadpole_constraint(res) + end end # Save all of the above data... @@ -154,7 +163,16 @@ function load_object(s::DeserializerState, ::Type{<:HypersurfaceModel}, params:: # That is, we have a dictionary which assigns the tuple (i1, i2, i3, i4) - sorted in ascending order - the # intersection number k. In general, k could be a rational number! Cf. orbifold singularities. if haskey(attrs_data, :inter_dict) - set_attribute!(model, :inter_dict, attrs_data[:inter_dict]) + # We want this inter_dict to be of type Dict{NTuple{4, Int64}, ZZRingElem}(). + # Sadly, serializing and loading turns NTuple{4, Int64} into Tuple. + # So we need to massage this... Not at all good, as it doubles memory usage! + original_dict = attrs_data[:inter_dict] + new_dict = Dict{NTuple{4, Int64}, ZZRingElem}() + for (key, value) in original_dict + new_key = NTuple{4, Int64}(key) + new_dict[new_key] = value + end + set_attribute!(model, :inter_dict, new_dict) end # Some special intersection numbers known? If we intersect the toric divisors @@ -204,6 +222,9 @@ function load_object(s::DeserializerState, ::Type{<:HypersurfaceModel}, params:: set_attribute!(fgs, :is_well_quantized, true) set_attribute!(fgs, :is_vertical, false) set_attribute!(fgs, :breaks_non_abelian_gauge_group, true) + if haskey(attrs_data, :well_quantized_d3_tadpole) + set_attribute!(fgs, :d3_tadpole_constraint, attrs_dict[:well_quantized_d3_tadpole]) + end set_attribute!(model, :well_quantized_ambient_space_models_of_g4_fluxes, fgs) end @@ -214,6 +235,9 @@ function load_object(s::DeserializerState, ::Type{<:HypersurfaceModel}, params:: set_attribute!(fgs, :is_well_quantized, true) set_attribute!(fgs, :is_vertical, true) set_attribute!(fgs, :breaks_non_abelian_gauge_group, true) + if haskey(attrs_data, :well_quantized_and_vertical_d3_tadpole) + set_attribute!(fgs, :d3_tadpole_constraint, attrs_dict[:well_quantized_and_vertical_d3_tadpole]) + end set_attribute!(model, :well_quantized_and_vertical_ambient_space_models_of_g4_fluxes, fgs) end @@ -224,6 +248,9 @@ function load_object(s::DeserializerState, ::Type{<:HypersurfaceModel}, params:: set_attribute!(fgs, :is_well_quantized, true) set_attribute!(fgs, :is_vertical, true) set_attribute!(fgs, :breaks_non_abelian_gauge_group, false) + if haskey(attrs_data, :well_quantized_vertical_and_no_breaking_d3_tadpole) + set_attribute!(fgs, :d3_tadpole_constraint, attrs_dict[:well_quantized_vertical_and_no_breaking_d3_tadpole]) + end set_attribute!(model, :well_quantized_and_vertical_and_no_non_abelian_gauge_group_breaking_ambient_space_models_of_g4_fluxes, fgs) end diff --git a/experimental/FTheoryTools/src/Serialization/tate_models.jl b/experimental/FTheoryTools/src/Serialization/tate_models.jl index 5c2b43cf08b1..feee259cee49 100644 --- a/experimental/FTheoryTools/src/Serialization/tate_models.jl +++ b/experimental/FTheoryTools/src/Serialization/tate_models.jl @@ -98,6 +98,9 @@ function save_object(s::SerializerState, gtm::GlobalTateModel) res = well_quantized_ambient_space_models_of_g4_fluxes(gtm, check = false) attrs_dict[:well_quantized_integral] = matrix_integral(res) attrs_dict[:well_quantized_rational] = matrix_rational(res) + if has_attribute(res, :d3_tadpole_constraint) + attrs_dict[:well_quantized_d3_tadpole] = d3_tadpole_constraint(res) + end end # Do we know the well-quantized and vertical G4-fluxes @@ -105,6 +108,9 @@ function save_object(s::SerializerState, gtm::GlobalTateModel) res = well_quantized_and_vertical_ambient_space_models_of_g4_fluxes(gtm, check = false) attrs_dict[:well_quantized_and_vertical_integral] = matrix_integral(res) attrs_dict[:well_quantized_and_vertical_rational] = matrix_rational(res) + if has_attribute(res, :d3_tadpole_constraint) + attrs_dict[:well_quantized_and_vertical_d3_tadpole] = d3_tadpole_constraint(res) + end end # Do we know the well-quantized, vertical G4-fluxes that do not break the non-Abelian gauge group? @@ -112,6 +118,9 @@ function save_object(s::SerializerState, gtm::GlobalTateModel) res = well_quantized_and_vertical_and_no_non_abelian_gauge_group_breaking_ambient_space_models_of_g4_fluxes(gtm, check = false) attrs_dict[:well_quantized_vertical_no_break_integral] = matrix_integral(res) attrs_dict[:well_quantized_vertical_no_break_rational] = matrix_rational(res) + if has_attribute(res, :d3_tadpole_constraint) + attrs_dict[:well_quantized_vertical_and_no_breaking_d3_tadpole] = d3_tadpole_constraint(res) + end end # Save all of the above data... @@ -156,7 +165,16 @@ function load_object(s::DeserializerState, ::Type{<: GlobalTateModel}, params::T # That is, we have a dictionary which assigns the tuple (i1, i2, i3, i4) - sorted in ascending order - the # intersection number k. In general, k could be a rational number! Cf. orbifold singularities. if haskey(attrs_data, :inter_dict) - set_attribute!(model, :inter_dict, attrs_data[:inter_dict]) + # We want this inter_dict to be of type Dict{NTuple{4, Int64}, ZZRingElem}(). + # Sadly, serializing and loading turns NTuple{4, Int64} into Tuple. + # So we need to massage this... Not at all good, as it doubles memory usage! + original_dict = attrs_data[:inter_dict] + new_dict = Dict{NTuple{4, Int64}, ZZRingElem}() + for (key, value) in original_dict + new_key = NTuple{4, Int64}(key) + new_dict[new_key] = value + end + set_attribute!(model, :inter_dict, new_dict) end # Some special intersection numbers known? If we intersect the toric divisors @@ -205,6 +223,9 @@ function load_object(s::DeserializerState, ::Type{<: GlobalTateModel}, params::T set_attribute!(fgs, :is_well_quantized, true) set_attribute!(fgs, :is_vertical, false) set_attribute!(fgs, :breaks_non_abelian_gauge_group, true) + if haskey(attrs_data, :well_quantized_d3_tadpole) + set_attribute!(fgs, :d3_tadpole_constraint, attrs_dict[:well_quantized_d3_tadpole]) + end set_attribute!(model, :well_quantized_ambient_space_models_of_g4_fluxes, fgs) end @@ -215,6 +236,9 @@ function load_object(s::DeserializerState, ::Type{<: GlobalTateModel}, params::T set_attribute!(fgs, :is_well_quantized, true) set_attribute!(fgs, :is_vertical, true) set_attribute!(fgs, :breaks_non_abelian_gauge_group, true) + if haskey(attrs_data, :well_quantized_and_vertical_d3_tadpole) + set_attribute!(fgs, :d3_tadpole_constraint, attrs_dict[:well_quantized_and_vertical_d3_tadpole]) + end set_attribute!(model, :well_quantized_and_vertical_ambient_space_models_of_g4_fluxes, fgs) end @@ -225,6 +249,9 @@ function load_object(s::DeserializerState, ::Type{<: GlobalTateModel}, params::T set_attribute!(fgs, :is_well_quantized, true) set_attribute!(fgs, :is_vertical, true) set_attribute!(fgs, :breaks_non_abelian_gauge_group, false) + if haskey(attrs_data, :well_quantized_vertical_and_no_breaking_d3_tadpole) + set_attribute!(fgs, :d3_tadpole_constraint, attrs_dict[:well_quantized_vertical_and_no_breaking_d3_tadpole]) + end set_attribute!(model, :well_quantized_and_vertical_and_no_non_abelian_gauge_group_breaking_ambient_space_models_of_g4_fluxes, fgs) end diff --git a/experimental/FTheoryTools/src/Serialization/weierstrass_models.jl b/experimental/FTheoryTools/src/Serialization/weierstrass_models.jl index b1f31c0c43ed..596c184cfb40 100644 --- a/experimental/FTheoryTools/src/Serialization/weierstrass_models.jl +++ b/experimental/FTheoryTools/src/Serialization/weierstrass_models.jl @@ -97,6 +97,9 @@ function save_object(s::SerializerState, w::WeierstrassModel) res = well_quantized_ambient_space_models_of_g4_fluxes(w, check = false) attrs_dict[:well_quantized_integral] = matrix_integral(res) attrs_dict[:well_quantized_rational] = matrix_rational(res) + if has_attribute(res, :d3_tadpole_constraint) + attrs_dict[:well_quantized_d3_tadpole] = d3_tadpole_constraint(res) + end end # Do we know the well-quantized and vertical G4-fluxes @@ -104,6 +107,9 @@ function save_object(s::SerializerState, w::WeierstrassModel) res = well_quantized_and_vertical_ambient_space_models_of_g4_fluxes(w, check = false) attrs_dict[:well_quantized_and_vertical_integral] = matrix_integral(res) attrs_dict[:well_quantized_and_vertical_rational] = matrix_rational(res) + if has_attribute(res, :d3_tadpole_constraint) + attrs_dict[:well_quantized_and_vertical_d3_tadpole] = d3_tadpole_constraint(res) + end end # Do we know the well-quantized, vertical G4-fluxes that do not break the non-Abelian gauge group? @@ -111,6 +117,9 @@ function save_object(s::SerializerState, w::WeierstrassModel) res = well_quantized_and_vertical_and_no_non_abelian_gauge_group_breaking_ambient_space_models_of_g4_fluxes(w, check = false) attrs_dict[:well_quantized_vertical_no_break_integral] = matrix_integral(res) attrs_dict[:well_quantized_vertical_no_break_rational] = matrix_rational(res) + if has_attribute(res, :d3_tadpole_constraint) + attrs_dict[:well_quantized_vertical_and_no_breaking_d3_tadpole] = d3_tadpole_constraint(res) + end end # Save all of the above data... @@ -154,7 +163,16 @@ function load_object(s::DeserializerState, ::Type{<: WeierstrassModel}, params:: # That is, we have a dictionary which assigns the tuple (i1, i2, i3, i4) - sorted in ascending order - the # intersection number k. In general, k could be a rational number! Cf. orbifold singularities. if haskey(attrs_data, :inter_dict) - set_attribute!(model, :inter_dict, attrs_data[:inter_dict]) + # We want this inter_dict to be of type Dict{NTuple{4, Int64}, ZZRingElem}(). + # Sadly, serializing and loading turns NTuple{4, Int64} into Tuple. + # So we need to massage this... Not at all good, as it doubles memory usage! + original_dict = attrs_data[:inter_dict] + new_dict = Dict{NTuple{4, Int64}, ZZRingElem}() + for (key, value) in original_dict + new_key = NTuple{4, Int64}(key) + new_dict[new_key] = value + end + set_attribute!(model, :inter_dict, new_dict) end # Some special intersection numbers known? If we intersect the toric divisors @@ -204,6 +222,9 @@ function load_object(s::DeserializerState, ::Type{<: WeierstrassModel}, params:: set_attribute!(fgs, :is_well_quantized, true) set_attribute!(fgs, :is_vertical, false) set_attribute!(fgs, :breaks_non_abelian_gauge_group, true) + if haskey(attrs_data, :well_quantized_d3_tadpole) + set_attribute!(fgs, :d3_tadpole_constraint, attrs_dict[:well_quantized_d3_tadpole]) + end set_attribute!(model, :well_quantized_ambient_space_models_of_g4_fluxes, fgs) end @@ -214,6 +235,9 @@ function load_object(s::DeserializerState, ::Type{<: WeierstrassModel}, params:: set_attribute!(fgs, :is_well_quantized, true) set_attribute!(fgs, :is_vertical, true) set_attribute!(fgs, :breaks_non_abelian_gauge_group, true) + if haskey(attrs_data, :well_quantized_and_vertical_d3_tadpole) + set_attribute!(fgs, :d3_tadpole_constraint, attrs_dict[:well_quantized_and_vertical_d3_tadpole]) + end set_attribute!(model, :well_quantized_and_vertical_ambient_space_models_of_g4_fluxes, fgs) end @@ -224,6 +248,9 @@ function load_object(s::DeserializerState, ::Type{<: WeierstrassModel}, params:: set_attribute!(fgs, :is_well_quantized, true) set_attribute!(fgs, :is_vertical, true) set_attribute!(fgs, :breaks_non_abelian_gauge_group, false) + if haskey(attrs_data, :well_quantized_vertical_and_no_breaking_d3_tadpole) + set_attribute!(fgs, :d3_tadpole_constraint, attrs_dict[:well_quantized_vertical_and_no_breaking_d3_tadpole]) + end set_attribute!(model, :well_quantized_and_vertical_and_no_non_abelian_gauge_group_breaking_ambient_space_models_of_g4_fluxes, fgs) end diff --git a/experimental/FTheoryTools/src/exports.jl b/experimental/FTheoryTools/src/exports.jl index 70451523730b..4667738f691b 100644 --- a/experimental/FTheoryTools/src/exports.jl +++ b/experimental/FTheoryTools/src/exports.jl @@ -54,6 +54,7 @@ export degrees_of_kbar_restrictions_to_components_of_simplified_dual_graph export discriminant export display_all_literature_models export dual_graph +export d3_tadpole_constraint export estimated_number_of_triangulations export euler_characteristic export explicit_model_sections diff --git a/experimental/FTheoryTools/test/FTM-1511-03209.jl b/experimental/FTheoryTools/test/FTM-1511-03209.jl index 0c1a71b7e073..f122ae2554c1 100644 --- a/experimental/FTheoryTools/test/FTM-1511-03209.jl +++ b/experimental/FTheoryTools/test/FTM-1511-03209.jl @@ -1,7 +1,8 @@ @testset "Test Downloading Artifact and elementary properties" begin - h = literature_model(arxiv_id = "1511.03209") - h_resolved = resolve(h, 1) + t = literature_model(arxiv_id = "1511.03209") + t_resolved = resolve(h, 1) - @test n_rays(ambient_space(h)) == 104 - @test n_rays(ambient_space(h_resolved)) == 310 + @test n_rays(ambient_space(t)) == 104 + @test n_rays(ambient_space(t_resolved)) == 310 + @test typeof(get_attribute(t_resolved, :inter_dict)) == Dict{NTuple{4, Int64}, ZZRingElem} end