Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions experimental/FTheoryTools/docs/src/g4.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
155 changes: 155 additions & 0 deletions experimental/FTheoryTools/src/FamilyOfG4Fluxes/attributes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally this should use the new @attr variant as in #4476

Copy link
Copy Markdown
Member Author

@HereAround HereAround Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have an eye on it. Once the new @attr is available I am happy to update. (Am in fact looking forward to the adaptations made by @lgoettgens . Thx!)

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
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)]
Expand Down Expand Up @@ -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)]
Expand Down Expand Up @@ -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)]
Expand Down
54 changes: 54 additions & 0 deletions experimental/FTheoryTools/src/G4Fluxes/attributes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
12 changes: 2 additions & 10 deletions experimental/FTheoryTools/src/G4Fluxes/properties.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,20 +97,29 @@ 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
if has_attribute(h, :well_quantized_and_vertical_ambient_space_models_of_g4_fluxes)
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?
if has_attribute(h, :well_quantized_and_vertical_and_no_non_abelian_gauge_group_breaking_ambient_space_models_of_g4_fluxes)
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...
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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

Expand All @@ -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

Expand Down
Loading