From 1c460912d0ed19567703f4bc4de093b213bf8329 Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Fri, 4 Oct 2024 11:39:02 +0200 Subject: [PATCH 1/9] Repair methods for has_dim_leq_zero. --- src/AlgebraicGeometry/Schemes/Sheaves/IdealSheaves.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/AlgebraicGeometry/Schemes/Sheaves/IdealSheaves.jl b/src/AlgebraicGeometry/Schemes/Sheaves/IdealSheaves.jl index 7628da425b3..b4f5e059f29 100644 --- a/src/AlgebraicGeometry/Schemes/Sheaves/IdealSheaves.jl +++ b/src/AlgebraicGeometry/Schemes/Sheaves/IdealSheaves.jl @@ -345,6 +345,7 @@ end end @attr Bool function has_dimension_leq_zero(I::Ideal) + is_one(I) && return true return dim(I) <= 0 end @@ -353,6 +354,7 @@ end P = base_ring(R)::MPolyRing J = ideal(P, numerator.(gens(I))) has_dimension_leq_zero(J) && return true + is_one(I) && return true return dim(I) <= 0 end From 9684758c372a3c8f444a41a47f476be73cdf1e8d Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Mon, 7 Oct 2024 20:54:29 +0200 Subject: [PATCH 2/9] WIP to reduce to pos. char. --- experimental/Schemes/src/elliptic_surface.jl | 72 ++++++++++++++++--- .../Schemes/Sheaves/IdealSheaves.jl | 1 + 2 files changed, 64 insertions(+), 9 deletions(-) diff --git a/experimental/Schemes/src/elliptic_surface.jl b/experimental/Schemes/src/elliptic_surface.jl index 1aa0c17040c..71229bcdba4 100644 --- a/experimental/Schemes/src/elliptic_surface.jl +++ b/experimental/Schemes/src/elliptic_surface.jl @@ -1220,6 +1220,17 @@ function _section(X::EllipticSurface, P::EllipticCurvePoint) @vprint :EllipticSurface 3 "Computing a section from a point on the generic fiber\n" weierstrass_contraction(X) # trigger required computations PX = _section_on_weierstrass_ambient_space(X, P) + + if !is_zero(P) + WC = weierstrass_chart_on_minimal_model(X) + U = original_chart(PX) + @assert OO(U) === ambient_coordinate_ring(WC) + PY = PrimeIdealSheafFromChart(X, WC, ideal(OO(WC), PX(U))) + set_attribute!(PY, :name, string("section: (",P[1]," : ",P[2]," : ",P[3],")")) + set_attribute!(PY, :_self_intersection, -euler_characteristic(X)) + return WeilDivisor(PY, check=false) + end + for f in X.ambient_blowups PX = strict_transform(f , PX) end @@ -1313,7 +1324,10 @@ function _prop217(E::EllipticCurve, P::EllipticCurvePoint, k) eqns = vcat(eq1, eq2) # collect the equations as a matrix + @show first(eqns) + @show typeof(first(eqns)) cc = [[coeff(j, abi) for abi in ab] for j in eqns] + @show cc M = matrix(B, length(eqns), length(ab), reduce(vcat,cc, init=elem_type(base)[])) # @assert M == matrix(base, cc) # does not work if length(eqns)==0 K = kernel(M; side = :right) @@ -1368,7 +1382,8 @@ function linear_system(X::EllipticSurface, P::EllipticCurvePoint, k::Int64) I = saturated_ideal(defining_ideal(U)) IP = ideal([x*xd(t)-xn(t),y*yd(t)-yn(t)]) - issubset(I, IP) || error("P does not define a point on the Weierstrasschart") + # Test is disabled for the moment; should eventually be put behind @check! + #issubset(I, IP) || error("P does not define a point on the Weierstrasschart") @assert gcd(xn, xd)==1 @assert gcd(yn, yd)==1 @@ -1414,7 +1429,7 @@ function two_neighbor_step(X::EllipticSurface, F::Vector{QQFieldElem}) @assert scheme(parent(u)) === X pr = weierstrass_contraction(X) WX, _ = weierstrass_model(X) - # The following is a cheating version of the command u = pushforward(pr)(u) + # The following is a cheating version of the command u = pushforward(pr)(u) (the latter has now been deprecated!) u = function_field(WX)(u[weierstrass_chart_on_minimal_model(X)]) @assert scheme(parent(u)) === weierstrass_model(X)[1] @@ -1568,8 +1583,7 @@ function horizontal_decomposition(X::EllipticSurface, F::Vector{QQFieldElem}) @assert all(F4[i]>=0 for i in 1:length(basisNS)) D = D + sum(ZZ(F4[i])*basisNS[i] for i in 1:length(basisNS)) @assert D<=D1 - l = Int(l) - return D1, D, P, l, c + return D1, D, P, Int(l), c end @doc raw""" @@ -1662,6 +1676,15 @@ function reduction_to_pos_char(X::EllipticSurface, red_map::Map) end::Tuple{<:Map, <:Map} end +function reduction_of_algebraic_lattice(X::EllipticSurface) + return get_attribute!(X, :reduction_of_algebraic_lattice) do + @assert has_attribute(X, :reduction_to_pos_char) "no reduction morphism specified" + red_map, bc = get_attribute(X, :reduction_to_pos_char) + basis_ambient, _, _= algebraic_lattice(X) + return red_dict = IdDict{AbsWeilDivisor, AbsWeilDivisor}(D=>_reduce_as_prime_divisor(bc, D) for D in basis_ambient) + end::IdDict +end + @doc raw""" basis_representation(X::EllipticSurface, D::WeilDivisor) @@ -1677,11 +1700,12 @@ function basis_representation(X::EllipticSurface, D::WeilDivisor) kk = base_ring(X) if iszero(characteristic(kk)) && has_attribute(X, :reduction_to_pos_char) red_map, bc = get_attribute(X, :reduction_to_pos_char) - for i in 1:n - @vprintln :EllipticSurface 4 "intersecting with $(i): $(basis_ambient[i])" - - v[i] = intersect(base_change(red_map, basis_ambient[i]; scheme_base_change=bc), - base_change(red_map, D; scheme_base_change=bc)) + red_dict = IdDict{AbsWeilDivisor, AbsWeilDivisor}(D=>_reduce_as_prime_divisor(bc, D) for D in basis_ambient) + #red_dict_inv = IdDict{AbsWeilDivisor, AbsWeilDivisor}(D=>E for (E, D) in red_dict) + D_red = _reduce_as_prime_divisor(bc, D) + for (i, E) in enumerate(basis_ambient) + @vprintln :EllipticSurface 4 "intersecting in positive characteristic with $(i): $(basis_ambient[i])" + v[i] = intersect(red_dict[E], D_red) end else for i in 1:n @@ -1694,6 +1718,36 @@ function basis_representation(X::EllipticSurface, D::WeilDivisor) return v*inv(G) end +function _reduce_as_prime_divisor(bc::AbsCoveredSchemeMorphism, D::AbsWeilDivisor) + return WeilDivisor(domain(bc), coefficient_ring(D), + IdDict{AbsIdealSheaf, elem_type(coefficient_ring(D))}( + _reduce_as_prime_divisor(bc, I) => c for (I, c) in coefficient_dict(D) + ) + ) +end + +function _reduce_as_prime_divisor(bc::AbsCoveredSchemeMorphism, I::AbsIdealSheaf) + result = pullback(bc, I) + has_attribute(I, :_self_intersection) && set_attribute!(result, :_self_intersection=> + (get_attribute(I, :_self_intersection)::Int)) + return result +end + +function _reduce_as_prime_divisor(bc::AbsCoveredSchemeMorphism, I::PrimeIdealSheafFromChart) + U = original_chart(I) + bc_cov = covering_morphism(bc) + V = __find_chart(U, codomain(bc_cov)) + @show U + @show V + @show U == V + @show U === V + IV = I(V) + bc_loc = first(maps_with_given_codomain(bc_cov, V)) + J = pullback(bc_loc)(IV) + set_attribute!(J, :is_prime=>true) + return PrimeIdealSheafFromChart(domain(bc), domain(bc_loc), J) +end + ################################################################################ # # patches for Oscar diff --git a/src/AlgebraicGeometry/Schemes/Sheaves/IdealSheaves.jl b/src/AlgebraicGeometry/Schemes/Sheaves/IdealSheaves.jl index b4f5e059f29..bba517f1af4 100644 --- a/src/AlgebraicGeometry/Schemes/Sheaves/IdealSheaves.jl +++ b/src/AlgebraicGeometry/Schemes/Sheaves/IdealSheaves.jl @@ -1693,6 +1693,7 @@ function produce_object( algorithm::Symbol=:pullback # Either :pushforward or :pullback # This determines how to extend through the gluings. ) + U2 === original_chart(F) && return F.P # Initialize some local variables X = scheme(F) OOX = OO(X) From bc918bccb1a9d34241297ef30845204e8581accf Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Mon, 7 Oct 2024 21:42:17 +0200 Subject: [PATCH 3/9] Make two_neighbor_step work in char. 0. --- experimental/Schemes/src/elliptic_surface.jl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/experimental/Schemes/src/elliptic_surface.jl b/experimental/Schemes/src/elliptic_surface.jl index 71229bcdba4..07c75d847d9 100644 --- a/experimental/Schemes/src/elliptic_surface.jl +++ b/experimental/Schemes/src/elliptic_surface.jl @@ -1324,11 +1324,12 @@ function _prop217(E::EllipticCurve, P::EllipticCurvePoint, k) eqns = vcat(eq1, eq2) # collect the equations as a matrix - @show first(eqns) - @show typeof(first(eqns)) cc = [[coeff(j, abi) for abi in ab] for j in eqns] - @show cc - M = matrix(B, length(eqns), length(ab), reduce(vcat,cc, init=elem_type(base)[])) + mat = reduce(vcat,cc, init=elem_type(base)[]) + @assert all(is_one(denominator(x)) for x in mat) + @assert all(is_constant(numerator(x)) for x in mat) + mat2 = [constant_coefficient(numerator(x)) for x in mat] + M = matrix(B, length(eqns), length(ab), mat2) # @assert M == matrix(base, cc) # does not work if length(eqns)==0 K = kernel(M; side = :right) kerdim = ncols(K) From af1e9c843339bc7b448a4044ee5a50920e39411c Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Mon, 7 Oct 2024 21:43:46 +0200 Subject: [PATCH 4/9] Remove debug comments. --- experimental/Schemes/src/elliptic_surface.jl | 4 ---- 1 file changed, 4 deletions(-) diff --git a/experimental/Schemes/src/elliptic_surface.jl b/experimental/Schemes/src/elliptic_surface.jl index 07c75d847d9..23c60b44d8d 100644 --- a/experimental/Schemes/src/elliptic_surface.jl +++ b/experimental/Schemes/src/elliptic_surface.jl @@ -1738,10 +1738,6 @@ function _reduce_as_prime_divisor(bc::AbsCoveredSchemeMorphism, I::PrimeIdealShe U = original_chart(I) bc_cov = covering_morphism(bc) V = __find_chart(U, codomain(bc_cov)) - @show U - @show V - @show U == V - @show U === V IV = I(V) bc_loc = first(maps_with_given_codomain(bc_cov, V)) J = pullback(bc_loc)(IV) From a1c1f2888bc9e8049316bf49ab1401c0a65772be Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Tue, 8 Oct 2024 10:00:24 +0200 Subject: [PATCH 5/9] Take care of non-principal exceptional divisors. --- experimental/Schemes/src/BlowupMorphism.jl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/experimental/Schemes/src/BlowupMorphism.jl b/experimental/Schemes/src/BlowupMorphism.jl index 9498e0586c5..9a0aa5a5dff 100644 --- a/experimental/Schemes/src/BlowupMorphism.jl +++ b/experimental/Schemes/src/BlowupMorphism.jl @@ -644,18 +644,18 @@ function produce_object_on_affine_chart(I::StrictTransformIdealSheaf, U::AbsAffi f_loc = covering_morphism(f)[U] V = codomain(f_loc) IE_loc = IE(U) - @assert isone(ngens(IE_loc)) "ideal sheaf of exceptional locus is not principal" - tot = pullback(f_loc)(J(V)) - #return saturation_with_index(tot, IE_loc) # It is usually better to pass to the simplified covering to do the computations simp_cov = simplified_covering(X) U_simp = first([V for V in patches(simp_cov) if original(V) === U]) a, b = identification_maps(U_simp) - # This used to be the following line. But we don't use the index, so we - # switch to the more performant version - # result, _ = saturation_with_index(pullback(a)(tot), pullback(a)(IE_loc)) - result = _iterative_saturation(pullback(a)(tot), elem_type(OO(U_simp))[pullback(a)(u) for (u, _) in factor(lifted_numerator(first(gens(IE_loc))))]) - return pullback(b)(result) + tot = pullback(f_loc)(J(V)) + if isone(ngens(IE_loc)) + result = _iterative_saturation(pullback(a)(tot), elem_type(OO(U_simp))[pullback(a)(u) for (u, _) in factor(lifted_numerator(first(gens(IE_loc))))]) + return pullback(b)(result) + else + result, _ = saturation_with_index(pullback(a)(tot), pullback(a)(IE_loc)) + return result + end end @attr Bool function is_prime(I::StrictTransformIdealSheaf) From ff04310394f2725c3649e4d5ad294717297b05de Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Tue, 8 Oct 2024 10:53:17 +0200 Subject: [PATCH 6/9] Clean up reduction to positive characteristic. --- experimental/Schemes/src/elliptic_surface.jl | 55 ++++++++++++-------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/experimental/Schemes/src/elliptic_surface.jl b/experimental/Schemes/src/elliptic_surface.jl index 23c60b44d8d..e51bd84025b 100644 --- a/experimental/Schemes/src/elliptic_surface.jl +++ b/experimental/Schemes/src/elliptic_surface.jl @@ -1664,23 +1664,39 @@ function extended_ade(ADE::Symbol, n::Int) return -G, kernel(G; side = :left) end -# This function allows to store a reduction map to positive characteristic, -# e.g. for computing intersection numbers. -function reduction_to_pos_char(X::EllipticSurface, red_map::Map) - return get_attribute!(X, :reduction_to_pos_char) do - kk0 = base_ring(X) - @assert domain(red_map) === kk0 - kkp = codomain(red_map) - @assert characteristic(kkp) > 0 - _, result = base_change(red_map, X) - return red_map, result - end::Tuple{<:Map, <:Map} +######################################################################## +# Reduction to positive characteristic +# +# We allow to store a reduction of an elliptic surface `X` to positive +# characteristic. The user needs to know what they're doing here! +# +# The functionality can be made available by specifying a reduction +# map for the `base_ring` (actually a field) of `X` to a field of +# positive characteristic. This can then be stored in `X` via +# `set_good_reduction_map!`. The latter unlocks certain features such +# as computation of intersection numbers in positive characteristic. +######################################################################## +function set_good_reduction_map!(X::EllipticSurface, red_map::Map) + has_attribute(X, :good_reduction_map) && error("reduction map has already been set") + kk0 = base_ring(X) + @assert domain(red_map) === kk0 + kkp = codomain(red_map) + @assert characteristic(kkp) > 0 + set_attribute!(X, :good_reduction_map=>red_map) +end + +@attr AbsCoveredSchemeMorphism function good_reduction(X::EllipticSurface) + is_zero(characteristic(base_ring(X))) || error("reduction to positive characteristic is only possible from characteristic zero") + has_attribute(X, :good_reduction_map) || error("no reduction map is available; please set it manually via `set_good_reduction_map!`") + red_map = get_attribute(X, :good_reduction_map)::Map + _, result = base_change(red_map, X) + return red_map, result end function reduction_of_algebraic_lattice(X::EllipticSurface) return get_attribute!(X, :reduction_of_algebraic_lattice) do @assert has_attribute(X, :reduction_to_pos_char) "no reduction morphism specified" - red_map, bc = get_attribute(X, :reduction_to_pos_char) + red_map, bc = good_reduction(X) basis_ambient, _, _= algebraic_lattice(X) return red_dict = IdDict{AbsWeilDivisor, AbsWeilDivisor}(D=>_reduce_as_prime_divisor(bc, D) for D in basis_ambient) end::IdDict @@ -1699,10 +1715,9 @@ function basis_representation(X::EllipticSurface, D::WeilDivisor) v = zeros(ZZRingElem, n) @vprint :EllipticSurface 3 "computing basis representation of $D\n" kk = base_ring(X) - if iszero(characteristic(kk)) && has_attribute(X, :reduction_to_pos_char) - red_map, bc = get_attribute(X, :reduction_to_pos_char) + if iszero(characteristic(kk)) && has_attribute(X, :good_reduction_map) + red_map, bc = good_reduction(X) red_dict = IdDict{AbsWeilDivisor, AbsWeilDivisor}(D=>_reduce_as_prime_divisor(bc, D) for D in basis_ambient) - #red_dict_inv = IdDict{AbsWeilDivisor, AbsWeilDivisor}(D=>E for (E, D) in red_dict) D_red = _reduce_as_prime_divisor(bc, D) for (i, E) in enumerate(basis_ambient) @vprintln :EllipticSurface 4 "intersecting in positive characteristic with $(i): $(basis_ambient[i])" @@ -1719,6 +1734,10 @@ function basis_representation(X::EllipticSurface, D::WeilDivisor) return v*inv(G) end +### Some functions to do custom pullback of divisors along reduction maps. +# We assume that primeness is preserved along the reduction. In particular, the +# user is responsible for this to hold for all cases used! +# They specify the "good reduction" in the end. function _reduce_as_prime_divisor(bc::AbsCoveredSchemeMorphism, D::AbsWeilDivisor) return WeilDivisor(domain(bc), coefficient_ring(D), IdDict{AbsIdealSheaf, elem_type(coefficient_ring(D))}( @@ -1745,12 +1764,6 @@ function _reduce_as_prime_divisor(bc::AbsCoveredSchemeMorphism, I::PrimeIdealShe return PrimeIdealSheafFromChart(domain(bc), domain(bc_loc), J) end -################################################################################ -# -# patches for Oscar -# -################################################################################ - ######################################################################## # Internal functionality for Weierstrass transformation From 611adfca06b90b2bfff5147ea33eb26e49a95510 Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Tue, 8 Oct 2024 15:19:49 +0200 Subject: [PATCH 7/9] Introduce a type of its own for sections and use it. --- experimental/Schemes/src/elliptic_surface.jl | 97 ++++++++++++-------- 1 file changed, 60 insertions(+), 37 deletions(-) diff --git a/experimental/Schemes/src/elliptic_surface.jl b/experimental/Schemes/src/elliptic_surface.jl index e51bd84025b..962208868f8 100644 --- a/experimental/Schemes/src/elliptic_surface.jl +++ b/experimental/Schemes/src/elliptic_surface.jl @@ -1198,9 +1198,39 @@ function section(X::EllipticSurface, P::EllipticCurvePoint) if iszero(P[1])&&iszero(P[3]) return zero_section(X) end - return _section(X, P) + return EllipticSurfaceSection(X, P) +end + +@attributes mutable struct EllipticSurfaceSection{ + CoveredSchemeType<:AbsCoveredScheme, + CoefficientRingType<:AbstractAlgebra.Ring, + CoefficientRingElemType<:AbstractAlgebra.RingElem + } <: AbsWeilDivisor{CoveredSchemeType, CoefficientRingType} + D::WeilDivisor{CoveredSchemeType, CoefficientRingType, CoefficientRingElemType} + P::EllipticCurvePoint + + function EllipticSurfaceSection(X::EllipticSurface, P::EllipticCurvePoint; coefficient_ring::Ring=ZZ) + @vprint :EllipticSurface 3 "Computing a section from a point on the generic fiber\n" + weierstrass_contraction(X) # trigger required computations + PX = _section_on_weierstrass_ambient_space(X, P) + for f in X.ambient_blowups + PX = strict_transform(f , PX) + end + PY = pullback(X.inc_Y, PX) + set_attribute!(PY, :name, string("section: (",P[1]," : ",P[2]," : ",P[3],")")) + set_attribute!(PY, :_self_intersection, -euler_characteristic(X)) + W = WeilDivisor(PY, check=false) + set_attribute!(W, :is_prime=>true) + I = first(components(W)) + set_attribute!(I, :is_prime=>true) + return new{typeof(X), typeof(coefficient_ring), elem_type(coefficient_ring)}(W, P) + end end +underlying_divisor(D::EllipticSurfaceSection) = D.D +rational_point(D::EllipticSurfaceSection) = D.P + + function _section_on_weierstrass_ambient_space(X::EllipticSurface, P::EllipticCurvePoint) S0,incS0 = weierstrass_model(X) X0 = codomain(incS0) @@ -1216,41 +1246,13 @@ function _section_on_weierstrass_ambient_space(X::EllipticSurface, P::EllipticCu return ideal_sheaf(X0,U,[OO(U)(i) for i in [x*denominator(b[1])(t)-numerator(b[1])(t),y*denominator(b[2])(t)-numerator(b[2])(t)]]; check=false) end -function _section(X::EllipticSurface, P::EllipticCurvePoint) - @vprint :EllipticSurface 3 "Computing a section from a point on the generic fiber\n" - weierstrass_contraction(X) # trigger required computations - PX = _section_on_weierstrass_ambient_space(X, P) - - if !is_zero(P) - WC = weierstrass_chart_on_minimal_model(X) - U = original_chart(PX) - @assert OO(U) === ambient_coordinate_ring(WC) - PY = PrimeIdealSheafFromChart(X, WC, ideal(OO(WC), PX(U))) - set_attribute!(PY, :name, string("section: (",P[1]," : ",P[2]," : ",P[3],")")) - set_attribute!(PY, :_self_intersection, -euler_characteristic(X)) - return WeilDivisor(PY, check=false) - end - - for f in X.ambient_blowups - PX = strict_transform(f , PX) - end - PY = pullback(X.inc_Y, PX) - set_attribute!(PY, :name, string("section: (",P[1]," : ",P[2]," : ",P[3],")")) - set_attribute!(PY, :_self_intersection, -euler_characteristic(X)) - W = WeilDivisor(PY, check=false) - set_attribute!(W, :is_prime=>true) - I = first(components(W)) - set_attribute!(I, :is_prime=>true) - return W -end - @doc raw""" zero_section(S::EllipticSurface) -> WeilDivisor Return the zero section of the relatively minimal elliptic fibration \pi\colon X \to C$. """ -@attr Any zero_section(S::EllipticSurface) = _section(S, generic_fiber(S)([0,1,0])) +@attr Any zero_section(S::EllipticSurface) = EllipticSurfaceSection(S, generic_fiber(S)([0,1,0])) ################################################################################ # @@ -1383,8 +1385,7 @@ function linear_system(X::EllipticSurface, P::EllipticCurvePoint, k::Int64) I = saturated_ideal(defining_ideal(U)) IP = ideal([x*xd(t)-xn(t),y*yd(t)-yn(t)]) - # Test is disabled for the moment; should eventually be put behind @check! - #issubset(I, IP) || error("P does not define a point on the Weierstrasschart") + @hassert :EllipticSurface 2 issubset(I, IP) || error("P does not define a point on the Weierstrasschart") @assert gcd(xn, xd)==1 @assert gcd(yn, yd)==1 @@ -1685,7 +1686,7 @@ function set_good_reduction_map!(X::EllipticSurface, red_map::Map) set_attribute!(X, :good_reduction_map=>red_map) end -@attr AbsCoveredSchemeMorphism function good_reduction(X::EllipticSurface) +@attr Tuple{<:Map, <:AbsCoveredSchemeMorphism} function good_reduction(X::EllipticSurface) is_zero(characteristic(base_ring(X))) || error("reduction to positive characteristic is only possible from characteristic zero") has_attribute(X, :good_reduction_map) || error("no reduction map is available; please set it manually via `set_good_reduction_map!`") red_map = get_attribute(X, :good_reduction_map)::Map @@ -1708,7 +1709,7 @@ end Return the vector representing the numerical class of `D` with respect to the basis of the ambient space of `algebraic_lattice(X)`. """ -function basis_representation(X::EllipticSurface, D::WeilDivisor) +function basis_representation(X::EllipticSurface, D::AbsWeilDivisor) basis_ambient,_, NS = algebraic_lattice(X) G = gram_matrix(ambient_space(NS)) n = length(basis_ambient) @@ -1746,6 +1747,28 @@ function _reduce_as_prime_divisor(bc::AbsCoveredSchemeMorphism, D::AbsWeilDiviso ) end +function _reduce_as_prime_divisor(bc::AbsCoveredSchemeMorphism, D::EllipticSurfaceSection) + P = rational_point(D) + @show is_infinite(P) + is_infinite(P) && return _reduce_as_prime_divisor(bc, underlying_divisor(D)) + X = codomain(bc) + @assert parent(P) === generic_fiber(X) + W = weierstrass_chart_on_minimal_model(X) + R = ambient_coordinate_ring(W) + (x, y, t) = gens(R) + I = ideal(R, R.([evaluate(denominator(P[1]), t)*x-evaluate(numerator(P[1]), t), + evaluate(denominator(P[2]), t)*y-evaluate(numerator(P[2]), t)]) + ) + bc_loc = first(maps_with_given_codomain(covering_morphism(bc), W)) + bc_I = pullback(bc_loc)(I) + @assert is_one(dim(bc_I)) + set_attribute!(bc_I, :is_prime=>true) + J = PrimeIdealSheafFromChart(domain(bc), domain(bc_loc), bc_I) + return WeilDivisor(domain(bc), coefficient_ring(D), + IdDict{AbsIdealSheaf, elem_type(coefficient_ring(D))}(J => one(coefficient_ring(D))) + ) +end + function _reduce_as_prime_divisor(bc::AbsCoveredSchemeMorphism, I::AbsIdealSheaf) result = pullback(bc, I) has_attribute(I, :_self_intersection) && set_attribute!(result, :_self_intersection=> @@ -2433,7 +2456,7 @@ end =# function morphism_from_section( X::EllipticSurface, P::EllipticCurvePoint; - divisor::AbsWeilDivisor=_section(X, P) + divisor::AbsWeilDivisor=EllipticSurfaceSection(X, P) ) U = weierstrass_chart_on_minimal_model(X) II = first(components(divisor)) @@ -2468,7 +2491,7 @@ end ######################################################################## function translation_morphism(X::EllipticSurface, P::EllipticCurvePoint; - divisor::AbsWeilDivisor=_section(X, P) + divisor::AbsWeilDivisor=EllipticSurfaceSection(X, P) ) E = generic_fiber(X) @assert parent(P) === E "point does not lay on the underlying elliptic curve" @@ -2502,7 +2525,7 @@ end function _pushforward_section( phi::MorphismFromRationalFunctions{<:EllipticSurface, <:EllipticSurface}, P::EllipticCurvePoint; - divisor::AbsWeilDivisor=_section(domain(phi), P), + divisor::AbsWeilDivisor=EllipticSurfaceSection(domain(phi), P), codomain_charts::Vector{<:AbsAffineScheme} = affine_charts(codomain(phi)) ) X = domain(phi)::EllipticSurface From 929ddacfe8953169db5a7ce0861d9ac69c3222b2 Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Tue, 8 Oct 2024 16:25:17 +0200 Subject: [PATCH 8/9] Use AbsWeilDivisor consistently. --- experimental/Schemes/src/elliptic_surface.jl | 24 ++++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/experimental/Schemes/src/elliptic_surface.jl b/experimental/Schemes/src/elliptic_surface.jl index 962208868f8..c8571330d76 100644 --- a/experimental/Schemes/src/elliptic_surface.jl +++ b/experimental/Schemes/src/elliptic_surface.jl @@ -243,7 +243,7 @@ Return $\chi(\mathcal{O}_X)$. euler_characteristic(X::EllipticSurface) = X.euler_characteristic @doc raw""" - algebraic_lattice(X) -> Vector{WeilDivisor}, ZZLat + algebraic_lattice(X) -> Vector{AbsWeilDivisor}, ZZLat Return the sublattice `L` of ``Num(X)`` spanned by fiber components, torsion sections and the sections provided at the construction of ``X``. @@ -935,7 +935,7 @@ Internal function. Returns a list consisting of: end @doc raw""" - trivial_lattice(X::EllipticSurface) -> Vector{WeilDivisor}, ZZMatrix + trivial_lattice(X::EllipticSurface) -> Vector{AbsWeilDivisor}, ZZMatrix Return a basis for the trivial lattice as well as its gram matrix. @@ -968,7 +968,7 @@ end @doc raw""" - standardize_fiber(S::EllipticSurface, f::Vector{<:WeilDivisor}) + standardize_fiber(S::EllipticSurface, f::Vector{<:AbsWeilDivisor}) Internal method. Used to prepare for [`reducible_fibers`](@ref). `f` must be the list of the components of the reducible fiber `F`. @@ -978,7 +978,7 @@ Output a list of tuples with each tuple as follows - the irreducible components `[F0,...Fn]` of `F` sorted such that the first entry `F0` is the one intersecting the zero section. The others are sorted in some standard way - gram matrix of the intersection of [F0,...,Fn], it is an extended ADE-lattice. """ -function standardize_fiber(S::EllipticSurface, f::Vector{<:WeilDivisor}) +function standardize_fiber(S::EllipticSurface, f::Vector{<:AbsWeilDivisor}) @hassert :EllipticSurface 2 all(is_prime(i) for i in f) f = copy(f) O = components(zero_section(S))[1] @@ -1078,7 +1078,7 @@ function fiber_cartier(S::EllipticSurface, P::Vector = ZZ.([0,1])) end @doc raw""" - fiber_components(S::EllipticSurface, P) -> Vector{<:WeilDivisor} + fiber_components(S::EllipticSurface, P) -> Vector{<:AbsWeilDivisor} Return the fiber components of the fiber over the point $P \in C$. """ @@ -1192,7 +1192,7 @@ end section(X::EllipticSurface, P::EllipticCurvePoint) Given a rational point $P\in E(C)$ of the generic fiber $E/C$ of $\pi\colon X \to C$, -return its closure in $X$ as a `WeilDivisor`. +return its closure in $X$ as a `AbsWeilDivisor`. """ function section(X::EllipticSurface, P::EllipticCurvePoint) if iszero(P[1])&&iszero(P[3]) @@ -1247,7 +1247,7 @@ function _section_on_weierstrass_ambient_space(X::EllipticSurface, P::EllipticCu end @doc raw""" - zero_section(S::EllipticSurface) -> WeilDivisor + zero_section(S::EllipticSurface) -> AbsWeilDivisor Return the zero section of the relatively minimal elliptic fibration \pi\colon X \to C$. @@ -1483,7 +1483,7 @@ function two_neighbor_step(X::EllipticSurface, F::Vector{QQFieldElem}) end @doc raw""" - horizontal_decomposition(X::EllipticSurface, L::Vector{QQFieldElem}) -> WeilDivisor, EllipticCurvePoint + horizontal_decomposition(X::EllipticSurface, L::Vector{QQFieldElem}) -> AbsWeilDivisor, EllipticCurvePoint Given a divisor ``L`` as a vector in the `algebraic_lattice(X)` find a linearly equivalent divisor ``(n-1) O + P + V = D ~ L`` where @@ -1603,14 +1603,14 @@ function elliptic_parameter(X::EllipticSurface, F::Vector{QQFieldElem}) end @doc raw""" - _elliptic_parameter(X::EllipticSurface, D::WeilDivisor, l, c) + _elliptic_parameter(X::EllipticSurface, D::AbsWeilDivisor, l, c) Compute the linear system of ``D = (n-1) O + P + V``. where V is vertical and `l` is the coefficient of the fiber class. Assumes `D` nef and `D^2=0`. Typically ``D`` is the output of `horizontal_decomposition`. """ -function _elliptic_parameter(X::EllipticSurface, D1::WeilDivisor, D::WeilDivisor, P::EllipticCurvePoint, l::Int, c) +function _elliptic_parameter(X::EllipticSurface, D1::AbsWeilDivisor, D::AbsWeilDivisor, P::EllipticCurvePoint, l::Int, c) S, piS = weierstrass_model(X); piX = weierstrass_contraction(X) c = function_field(X)(c) @@ -1704,7 +1704,7 @@ function reduction_of_algebraic_lattice(X::EllipticSurface) end @doc raw""" - basis_representation(X::EllipticSurface, D::WeilDivisor) + basis_representation(X::EllipticSurface, D::AbsWeilDivisor) Return the vector representing the numerical class of `D` with respect to the basis of the ambient space of `algebraic_lattice(X)`. @@ -2440,7 +2440,7 @@ function _pushforward_lattice_along_isomorphism(step::MorphismFromRationalFuncti end end - res = WeilDivisor[result[D] for D in lat_X] + res = AbsWeilDivisor[result[D] for D in lat_X] for a in res set_attribute!(first(components(a)), :_self_intersection, -2) end From 1e85bd34e0748f2feab9de9029a7a235321ca162 Mon Sep 17 00:00:00 2001 From: HechtiDerLachs Date: Tue, 8 Oct 2024 22:44:31 +0200 Subject: [PATCH 9/9] More AbsWeilDivisor. --- .../MorphismFromRationalFunctions/Methods.jl | 2 +- .../Schemes/Divisors/WeilDivisor.jl | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/AlgebraicGeometry/Schemes/CoveredSchemes/Morphisms/MorphismFromRationalFunctions/Methods.jl b/src/AlgebraicGeometry/Schemes/CoveredSchemes/Morphisms/MorphismFromRationalFunctions/Methods.jl index b4b10284f6f..3416ba8a696 100644 --- a/src/AlgebraicGeometry/Schemes/CoveredSchemes/Morphisms/MorphismFromRationalFunctions/Methods.jl +++ b/src/AlgebraicGeometry/Schemes/CoveredSchemes/Morphisms/MorphismFromRationalFunctions/Methods.jl @@ -574,7 +574,7 @@ function pushforward(Phi::MorphismFromRationalFunctions, D::AbsAlgebraicCycle) error("not implemented") end -function pushforward(Phi::MorphismFromRationalFunctions, D::WeilDivisor) +function pushforward(Phi::MorphismFromRationalFunctions, D::AbsWeilDivisor) is_isomorphism(Phi) || error("method not implemented unless for the case of an isomorphism") #is_proper(Phi) || error("morphism must be proper") all(is_prime, components(D)) || error("divisor must be given in terms of irreducible components") diff --git a/src/AlgebraicGeometry/Schemes/Divisors/WeilDivisor.jl b/src/AlgebraicGeometry/Schemes/Divisors/WeilDivisor.jl index 0e4af4ca0e0..9275a72e3b2 100644 --- a/src/AlgebraicGeometry/Schemes/Divisors/WeilDivisor.jl +++ b/src/AlgebraicGeometry/Schemes/Divisors/WeilDivisor.jl @@ -5,12 +5,12 @@ underlying_cycle(D::AbsWeilDivisor) = underlying_cycle(underlying_divisor(D)) underlying_cycle(D::WeilDivisor) = D.C ### type getters -scheme_type(D::WeilDivisor{S, U, V}) where{S, U, V} = S -scheme_type(::Type{WeilDivisor{S, U, V}}) where{S, U, V} = S -coefficient_ring_type(D::WeilDivisor{S, U, V}) where{S, U, V} = U -coefficient_ring_type(::Type{WeilDivisor{S, U, V}}) where{S, U, V} = U -coefficient_type(D::WeilDivisor{S, U, V}) where{S, U, V} = V -coefficient_type(::Type{WeilDivisor{S, U, V}}) where{S, U, V} = V +scheme_type(D::AbsWeilDivisor{S, U}) where{S, U} = S +scheme_type(::Type{AbsWeilDivisor{S, U}}) where{S, U} = S +coefficient_ring_type(D::AbsWeilDivisor{S, U}) where{S, U} = U +coefficient_ring_type(::Type{AbsWeilDivisor{S, U}}) where{S, U} = U +coefficient_type(D::AbsWeilDivisor{S, U}) where{S, U} = elem_type(U) +coefficient_type(::Type{AbsWeilDivisor{S, U}}) where{S, U} = elem_type(U) @doc raw""" WeilDivisor(X::CoveredScheme, R::Ring) @@ -352,7 +352,7 @@ function intersect(D::AbsWeilDivisor, E::AbsWeilDivisor; end -function pushforward(inc::CoveredClosedEmbedding, W::WeilDivisor) +function pushforward(inc::CoveredClosedEmbedding, W::AbsWeilDivisor) X = domain(inc) Y = codomain(inc) X === ambient_scheme(W) || error("divisor not defined on the domain") @@ -420,7 +420,7 @@ end @doc raw""" - is_in_linear_system(f::VarietyFunctionFieldElem, D::WeilDivisor; regular_on_complement::Bool=true, check::Bool=true) -> Bool + is_in_linear_system(f::VarietyFunctionFieldElem, D::AbsWeilDivisor; regular_on_complement::Bool=true, check::Bool=true) -> Bool Return whether the rational function `f` is in the linear system ``|D|``, i.e. if $(f) + D \geq 0$.