generated from AlgebraicJulia/AlgebraicTemplate.jl
-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Interop with SymbolicUtils #64
Merged
Merged
Changes from 1 commit
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
c2d64b5
symbolicutils interop
olynch c11d4dd
added spaces to the sorts of forms and vector fields
olynch 7de10e8
integrated changes to ThDEC with DecaSymbolic
olynch 5928cc7
added tests for decasymbolic, but needs wrinkles ironed out. musical …
quffaro d7d6a5b
reverted src/DiagX to restore exports and adding Project.toml
quffaro 2f79b0c
Merge remote-tracking branch 'origin/space-sorts' into symbolicutilsi…
quffaro a438192
updated code and tests after merge from space-sorts
quffaro 18a1585
review changes:
jpfairbanks 090ddfe
resolving some comments from code review.
quffaro d8be4ae
adding @alias and @register macros to make DecaSymbolic function work…
quffaro 77770e5
experimenting with a type-driven approach
quffaro 1fa477b
adding promote_symtype and addressing some of the code review comment…
quffaro 3b265ac
refactoring @operator to integrate with promote_symtype
quffaro 7f8597a
operator macro parses @rule but need to write tests and iron out rela…
quffaro 154e51f
rewriting just needs tests
quffaro 18bb71f
TST: add some klausmeier rewrites
jpfairbanks 4ba6dce
BUG: fix method shadowing for existing operators like +/-
jpfairbanks 82f65ce
added more tests, @operator macro is more flexible
quffaro e23459f
Merge pull request #73 from AlgebraicJulia/jpf/symbolictypes
quffaro e82e826
almost round-tripping in klausmeier. equations are not currently pass…
quffaro f32b3c0
Merge branch 'cm/symbolictypes' of github.com:AlgebraicJulia/Diagramm…
quffaro ecfa931
added rules function which dispatches on function symbol and the Val(…
quffaro 4603ed9
fixed docs for @operator, fixed Term
quffaro f2ef1d0
Merge pull request #71 from AlgebraicJulia/cm/symbolictypes
quffaro 5324de3
Loosened aqua tests
GeorgeR227 0a314a8
fixing bug where (+) always returns Scalar
quffaro 5d5c25d
Expression level rewriting (#69)
GeorgeR227 70a420d
added tests for errors and consolidated errors with George
quffaro 85572a4
Fixed hodge nameof and more tests
GeorgeR227 df41b18
Many more tests
GeorgeR227 6d1edf0
Merge branch 'main' into symbolicutilsinterop
jpfairbanks ccf0a79
More tests
GeorgeR227 467a93c
Remove unused functions
GeorgeR227 7c5155d
Fixed test in acset2symbolics
GeorgeR227 4f1f327
Added some improvements to naming
GeorgeR227 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,270 @@ | ||
module ThDEC | ||
using MLStyle | ||
|
||
import Base: +, -, * | ||
|
||
struct SortError <: Exception | ||
message::String | ||
end | ||
|
||
@data Sort begin | ||
Scalar() | ||
Form(dim::Int, isdual::Bool) | ||
VField(isdual::Bool) | ||
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 Base.nameof(s::Scalar) | ||
:Constant | ||
end | ||
|
||
function Base.nameof(f::Form) | ||
dual = isdual(f) ? "Dual" : "" | ||
Symbol("$(dual)Form$(dim(f))") | ||
end | ||
|
||
const VF = VField | ||
|
||
dim(ω::Form) = ω.dim | ||
isdual(ω::Form) = ω.isdual | ||
|
||
isdual(v::VField) = v.isdual | ||
|
||
# convenience functions | ||
PrimalForm(i::Int) = Form(i, false) | ||
export PrimalForm | ||
|
||
DualForm(i::Int) = Form(i, true) | ||
export DualForm | ||
|
||
PrimalVF() = VF(false) | ||
export PrimalVF | ||
|
||
DualVF() = VF(true) | ||
export DualVF | ||
|
||
# show methods | ||
show_duality(ω::Form) = isdual(ω) ? "dual" : "primal" | ||
|
||
function Base.show(io::IO, ω::Form) | ||
print(io, isdual(ω) ? "DualForm($(dim(ω)))" : "PrimalForm($(dim(ω)))") | ||
end | ||
|
||
@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) | ||
Form(i1, isdual1) | ||
else | ||
throw(SortError("Cannot add two forms of different dimensions/dualities: $((i1,isdual1)) and $((i2,isdual2))")) | ||
end | ||
end | ||
end | ||
|
||
# Type-checking inverse of addition follows addition | ||
-(s1::Sort, s2::Sort) = +(s1, s2) | ||
|
||
# TODO error for Forms | ||
|
||
# Negation is always valid | ||
-(s::Sort) = s | ||
|
||
@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 `∧`??")) | ||
end | ||
end | ||
|
||
const SUBSCRIPT_DIGIT_0 = '₀' | ||
|
||
function as_sub(n::Int) | ||
join(map(d -> SUBSCRIPT_DIGIT_0 + d, digits(n))) | ||
end | ||
|
||
@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) | ||
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 | ||
end | ||
|
||
function Base.nameof(::typeof(∧), s1, s2) | ||
Symbol("∧$(as_sub(dim(s1)))$(as_sub(dim(s2)))") | ||
end | ||
|
||
@nospecialize | ||
∂ₜ(s::Sort) = s | ||
|
||
@nospecialize | ||
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) | ||
else | ||
throw(SortError("Cannot take exterior derivative of a n-form for n >= 1")) | ||
end | ||
end | ||
end | ||
|
||
function Base.nameof(::typeof(d), s) | ||
Symbol("d$(as_sub(dim(s)))") | ||
end | ||
|
||
@nospecialize | ||
function ★(s::Sort) | ||
@match s begin | ||
Scalar() => throw(SortError("Cannot take Hodge star of a scalar")) | ||
Form(i, isdual) => Form(2 - i, !isdual) | ||
end | ||
end | ||
|
||
function Base.nameof(::typeof(★), s) | ||
inv = isdual(s) ? "⁻¹" : "" | ||
Symbol("★$(as_sub(isdual(s) ? 2 - dim(s) : dim(s)))$(inv)") | ||
end | ||
|
||
@nospecialize | ||
function ι(s1::Sort, s2::Sort) | ||
@match (s1, s2) begin | ||
(VF(true), Form(i, true)) => PrimalForm() # wrong | ||
(VF(true), Form(i, false)) => DualForm() | ||
_ => throw(SortError("Can only define the discrete interior product on: | ||
PrimalVF, DualForm(i) | ||
DualVF(), PrimalForm(i) | ||
.")) | ||
end | ||
end | ||
|
||
# in practice, a scalar may be treated as a constant 0-form. | ||
function ♯(s::Sort) | ||
@match s begin | ||
Scalar() => PrimalVF() | ||
Form(1, isdual) => VF(isdual) | ||
_ => throw(SortError("Can only take ♯ to 1-forms")) | ||
end | ||
end | ||
# musical isos may be defined for any combination of (primal/dual) form -> (primal/dual) vf. | ||
|
||
function ♭(s::Sort) | ||
@match s begin | ||
VF(true) => PrimalForm(1) | ||
_ => throw(SortError("Can only apply ♭ to dual vector fields")) | ||
end | ||
end | ||
|
||
# OTHER | ||
|
||
function ♭♯(s::Sort) | ||
@match s begin | ||
Form(i, isdual) => Form(i, !isdual) | ||
_ => throw(SortError("♭♯ is only defined on forms.")) | ||
end | ||
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) | ||
_ => throw(SortError("Δ is not defined for $s")) | ||
end | ||
end | ||
|
||
const OPERATOR_LOOKUP = Dict( | ||
:⋆₀ => ★, | ||
:⋆₁ => ★, | ||
:⋆₂ => ★, | ||
|
||
# Inverse Hodge Stars | ||
:⋆₀⁻¹ => ★, | ||
:⋆₁⁻¹ => ★, | ||
:⋆₂⁻¹ => ★, | ||
|
||
# Differentials | ||
:d₀ => d, | ||
:d₁ => d, | ||
|
||
# Dual Differentials | ||
:dual_d₀ => d, | ||
:d̃₀ => d, | ||
:dual_d₁ => d, | ||
:d̃₁ => d, | ||
|
||
# Wedge Products | ||
:∧₀₁ => ∧, | ||
:∧₁₀ => ∧, | ||
:∧₀₂ => ∧, | ||
:∧₂₀ => ∧, | ||
:∧₁₁ => ∧, | ||
|
||
# Primal-Dual Wedge Products | ||
:∧ᵖᵈ₁₁ => ∧, | ||
:∧ᵖᵈ₀₁ => ∧, | ||
:∧ᵈᵖ₁₁ => ∧, | ||
:∧ᵈᵖ₁₀ => ∧, | ||
|
||
# Dual-Dual Wedge Products | ||
:∧ᵈᵈ₁₁ => ∧, | ||
:∧ᵈᵈ₁₀ => ∧, | ||
:∧ᵈᵈ₀₁ => ∧, | ||
|
||
# Dual-Dual Interior Products | ||
:ι₁₁ => ι, | ||
:ι₁₂ => ι, | ||
|
||
# Dual-Dual Lie Derivatives | ||
# :ℒ₁ => ℒ, | ||
|
||
# Dual Laplacians | ||
# :Δᵈ₀ => Δ, | ||
# :Δᵈ₁ => Δ, | ||
|
||
# Musical Isomorphisms | ||
:♯ => ♯, | ||
:♯ᵈ => ♯, :♭ => ♭, | ||
|
||
# Averaging Operator | ||
# :avg₀₁ => avg, | ||
|
||
# Negatives | ||
:neg => -, | ||
|
||
# Basics | ||
|
||
:- => -, | ||
:+ => +, | ||
:* => *, | ||
:/ => /, | ||
:.- => .-, | ||
:.+ => .+, | ||
:.* => .*, | ||
:./ => ./, | ||
) | ||
|
||
end |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need a deeper consideration of the dimension that our physics in occurring in here. I've noticed that the current code is mostly hard-coded for 2D and in the case of the Hodge star, the resulting operator would be wrong if we were working in 1D.
I can say that the way our current inference/overloading rules work is by grouping them into contexts based on the dimension, so we have separate rules to apply in the 1D case and in the 2D case. The way the dimension is figured out is by the user explicitly passing us that information, since some physics can work without modification in multiple dimensions, like the Heat equation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think one way to work around this is to store the Space as a parameter in the Form sort. Space may be a wrapper for the dimension of Space, but can be embiggened with other attributes down the line, with the provision we have to update our signature checking.
I think this makes philosophical sense. n-forms are the same in any (n+k)-dimensional space, but since they are also determined by duality, their dual varies according to the dimensionality. So this means every n-form is determined by a different dual per dimension. Tagging this dimension
Form(dim, isdual, space)
allows us to track this.@lukem12345 what do you think about this philosophically and practically?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Philosophically, here are some probing questions: How do you want to distinguish between the Heat equation in 1D, 2D, and 3D? What do morphisms between diagrams (of possibly differing dimension) look like?
Practically: the entire PR seems to be hard-coded for the 2D Discrete Exterior Calculus over a double de Rham complex. I believe more consideration needs to be taken as to how we reconcile having 3 similar algebraic theories in the same package. Is there any advantage to using parameters here besides code reduction? What is the scale of that code reduction? And is the generalization worth the mental overhead? Are we going to be auto-generating rules by doing index arithmetic on these parameters or not? Do we want it to be clear when we are programming in a 1D environment vs a 3D environment? How does this impact representations with respect to the multi-dimensional multiphysics project? Do we want to represent the various DECs over a single de Rham complex?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This all makes sense. This was supposed to be a first stab at what the API would look like. I think the next step is to add the space to the types, and part of the information about the space will be its dimension.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When we convert a DecaExpr to a DecaSymbolic, you should have to also provide a mapping from space symbol to dimension.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What would you all think of something like:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jpfairbanks and I discussed this exact suggestion earlier today. I'd like to implement it, but I think @lukem12345 's practical questions still remain open. @lukem12345 @GeorgeR227 for clarification, should these questions + considerations should be resolved in this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing is immediately keeping this PR open as long as tests pass.