From c11d4dda9dca29fef83b718ee58918b94cf275b6 Mon Sep 17 00:00:00 2001 From: Owen Lynch Date: Fri, 16 Aug 2024 16:51:54 -0700 Subject: [PATCH] added spaces to the sorts of forms and vector fields --- src/ThDEC.jl | 103 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 70 insertions(+), 33 deletions(-) diff --git a/src/ThDEC.jl b/src/ThDEC.jl index 52f5198..d416cbf 100644 --- a/src/ThDEC.jl +++ b/src/ThDEC.jl @@ -7,22 +7,45 @@ struct SortError <: Exception message::String end +@struct_hash_equal struct Space + name::Symbol + dim::Int +end + +dim(s::Space) = s.dim +nameof(s::Space) = s.name + +struct SpaceLookup + default::Space + named::Dict{Symbol,Space} +end + @data Sort begin Scalar() - Form(dim::Int, isdual::Bool) - VField(isdual::Bool) + Form(dim::Int, isdual::Bool, space::Space) + VField(isdual::Bool, space::Space) end export Sort, Scalar, Form, VField -const SORT_LOOKUP = Dict( - :Form0 => Form(0, false), - :Form1 => Form(1, false), - :Form2 => Form(2, false), - :DualForm0 => Form(0, true), - :DualForm1 => Form(1, true), - :DualForm2 => Form(2, true), - :Constant => Scalar() -) +function fromexpr(lookup::SpaceLookup, e, ::Type{Sort}) + (name, spacename) = @match e begin + name::Symbol => (name, nothing) + :(Form0{$}) + end + space = @match spacename begin + ::Nothing => lookup.default + name::Symbol => lookup.named[name] + end + @match name begin + :Form0 => Form(0, false, space), + :Form1 => Form(1, false, space), + :Form2 => Form(2, false, space), + :DualForm0 => Form(0, true, space), + :DualForm1 => Form(1, true, space), + :DualForm2 => Form(2, true, space), + :Constant => Scalar() + end +end function Base.nameof(s::Scalar) :Constant @@ -30,15 +53,18 @@ end function Base.nameof(f::Form) dual = isdual(f) ? "Dual" : "" - Symbol("$(dual)Form$(dim(f))") + formname = Symbol("$(dual)Form$(dim(f))") + Expr(:curly, formname, dim(space(f))) end const VF = VField dim(ω::Form) = ω.dim isdual(ω::Form) = ω.isdual +space(ω::Form) = ω.space isdual(v::VField) = v.isdual +space(v::VField) = v.space # convenience functions PrimalForm(i::Int) = Form(i, false) @@ -60,17 +86,23 @@ function Base.show(io::IO, ω::Form) print(io, isdual(ω) ? "DualForm($(dim(ω)))" : "PrimalForm($(dim(ω)))") end +# TODO: VField @nospecialize function +(s1::Sort, s2::Sort) @match (s1, s2) begin (Scalar(), Scalar()) => Scalar() - (Scalar(), Form(i, isdual)) || - (Form(i, isdual), Scalar()) => Form(i, isdual) - (Form(i1, isdual1), Form(i2, isdual2)) => - if (i1 == i2) && (isdual1 == isdual2) + (Scalar(), Form(i, isdual, space)) || + (Form(i, isdual, space), Scalar()) => Form(i, isdual, space) + (Form(i1, isdual1, space2), Form(i2, isdual2, space2)) => + if (i1 == i2) && (isdual1 == isdual2) && (space1 == space2) Form(i1, isdual1) else - throw(SortError("Cannot add two forms of different dimensions/dualities: $((i1,isdual1)) and $((i2,isdual2))")) + throw(SortError( + """ + Can not add two forms of different dimensions/dualities/spaces: + $((i1,isdual1,space1)) and $((i2,isdual2,space2)) + """) + ) end end end @@ -83,13 +115,15 @@ end # Negation is always valid -(s::Sort) = s +# TODO: VField @nospecialize function *(s1::Sort, s2::Sort) @match (s1, s2) begin (Scalar(), Scalar()) => Scalar() - (Scalar(), Form(i, isdual)) || - (Form(i, isdual), Scalar()) => Form(i, isdual) - (Form(_, _), Form(_, _)) => throw(SortError("Cannot scalar multiply a form with a form. Maybe try `∧`??")) + (Scalar(), Form(i, isdual, space)) || + (Form(i, isdual, space), Scalar()) => Form(i, isdual) + (Form(_, _, _), Form(_, _, _)) => + throw(SortError("Cannot scalar multiply a form with a form. Maybe try `∧`??")) end end @@ -99,17 +133,20 @@ function as_sub(n::Int) join(map(d -> SUBSCRIPT_DIGIT_0 + d, digits(n))) end +# TODO: VField @nospecialize function ∧(s1::Sort, s2::Sort) @match (s1, s2) begin - (Form(i, isdual), Scalar()) || (Scalar(), Form(i, isdual)) => Form(i, isdual) - (Form(i1, isdual), Form(i2, isdual)) => - if i1 + i2 <= 2 - Form(i1 + i2, isdual) + (Form(i, isdual, space), Scalar()) || (Scalar(), Form(i, isdual, space)) => + Form(i, isdual, space) + (Form(i1, isdual, space), Form(i2, isdual, space)) => begin + if i1 + i2 <= dim(space) + Form(i1 + i2, isdual, space) else throw(SortError("Can only take a wedge product when the dimensions of the forms add to less than 2: tried to wedge product $i1 and $i2")) end - _ => throw(SortError("Can only take a wedge product of two forms of the same duality")) + end + _ => throw(SortError("Can only take a wedge product of two forms of the same duality on the same space")) end end @@ -124,11 +161,11 @@ end function d(s::Sort) @match s begin Scalar() => throw(SortError("Cannot take exterior derivative of a scalar")) - Form(i, isdual) => - if i <= 1 - Form(i + 1, isdual) + Form(i, isdual, space) => + if i < dim(space) + Form(i + 1, isdual, space) else - throw(SortError("Cannot take exterior derivative of a n-form for n >= 1")) + throw(SortError("Cannot take exterior derivative of a k-form for k >= n, where n = $(dim(space)) is the dimension of its ambient space")) end end end @@ -141,13 +178,13 @@ end function ★(s::Sort) @match s begin Scalar() => throw(SortError("Cannot take Hodge star of a scalar")) - Form(i, isdual) => Form(2 - i, !isdual) + Form(i, isdual, space) => Form(dim(space) - i, !isdual, space) end end function Base.nameof(::typeof(★), s) inv = isdual(s) ? "⁻¹" : "" - Symbol("★$(as_sub(isdual(s) ? 2 - dim(s) : dim(s)))$(inv)") + Symbol("★$(as_sub(isdual(s) ? dim(space(s)) - dim(s) : dim(s)))$(inv)") end @nospecialize @@ -183,7 +220,7 @@ end function ♭♯(s::Sort) @match s begin - Form(i, isdual) => Form(i, !isdual) + Form(i, isdual, space) => Form(i, !isdual, space) _ => throw(SortError("♭♯ is only defined on forms.")) end end @@ -191,7 +228,7 @@ end # Δ = ★d⋆d, but we check signature here to throw a more helpful error function Δ(s::Sort) @match s begin - Form(0, isdual) => Form(0, isdual) + Form(0, isdual, space) => Form(0, isdual, space) _ => throw(SortError("Δ is not defined for $s")) end end