Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
02737ae
Create devcontainer.json
CSchank Feb 18, 2025
aadf409
first attempts to encode Clifford algebra
CSchank Feb 19, 2025
b8c5bbd
moving around some Clifford types
CSchank Feb 19, 2025
4ecf77d
fix small typo
CSchank Feb 19, 2025
c5fd09b
vector migration in progress (far from compiling successfully current…
CSchank Feb 25, 2025
7dcb188
code compiles again, but need to investigate errors
CSchank Feb 26, 2025
5b3c919
a lot more refactoring (it compiles now)
CSchank Feb 26, 2025
aca77d1
Add vectND for vectors of a variable length
CSchank Mar 10, 2025
d55288e
Export vectND and add Wedge and geometric products
CSchank Mar 10, 2025
905a96b
Convet all examples to use vectors of length n - compiles but still n…
CSchank Mar 10, 2025
ebebbf3
Add Clif grade operator
CSchank Mar 11, 2025
f32335a
Change comment in tempW
CSchank Mar 11, 2025
2b24b9b
Change tempW to Real for now, leaving note to check it
CSchank Mar 11, 2025
1af0625
Adding grade selection
CSchank Mar 13, 2025
3d6d52a
Revert tempW back to a clif
CSchank Mar 13, 2025
fb06419
Fix some comments and started work on indexes
CSchank Mar 14, 2025
960c0a5
Remove grade parameter from space as it is not relevant
CSchank Mar 15, 2025
f921ccf
limit Clifs to contain real values for now
CSchank Mar 17, 2025
87675e8
Fix type error with
CSchank Mar 18, 2025
ded720e
fix types of other vector physics quantities
CSchank Mar 20, 2025
f323dbc
refactor Clif to be a full Clifford algebra space, and have optional …
CSchank Mar 20, 2025
b4b6cb5
Redefine clifs again, using a map for sparseness
CSchank Mar 22, 2025
e58564a
Add a note that we should move the clif stuff elsewhere and out of Ex…
CSchank Mar 22, 2025
f16d784
More documentation and added trivectorKey
CSchank Mar 22, 2025
8887c09
Re-base vectors on Clifs, and rename clif vector Space helpers
CSchank Mar 22, 2025
5274725
Work on April 3rd in ITB 207
balacij Apr 3, 2025
3025324
Fixing bug
CSchank Apr 23, 2025
8d4747d
Revert commit - bug fixed in code gen branch
CSchank Apr 24, 2025
38aba8b
Revert projectile example to canonical version
CSchank May 16, 2025
5e3a82e
Spacing fixes
CSchank May 16, 2025
ba0f0da
Remove devcontainer for now
CSchank May 16, 2025
47207ae
Merge branch 'main' into geometric
CSchank May 16, 2025
9bce503
Fix problems after merge conflict
CSchank May 16, 2025
01d5aee
fix: appease hlint warnings
balacij May 25, 2025
b48ac7e
fix: appease GHC warnings that would convert to errors
balacij May 25, 2025
30fe9ea
Stabilize
balacij May 25, 2025
445440d
fix: appease ghc unused variables warnings and non-exhaustive patterns
balacij May 25, 2025
5ab549d
Merge remote-tracking branch 'origin' into geometric
balacij May 26, 2025
599361b
Merge branch 'main' into geometric
balacij Jun 5, 2025
7eaf629
Align output matrices in render of Clifs
balacij Jun 5, 2025
8c25b38
fixup! stabilize all artifacts after aligning output matrices in rend…
balacij Jun 5, 2025
f03bf6c
fixup! use an OrderedMap implementation so we can retain order of bas…
balacij Jun 6, 2025
8be1c15
Merge branch 'main' into geometric
balacij Jun 9, 2025
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
20 changes: 20 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
Copy link
Owner

Choose a reason for hiding this comment

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

any reason to add this file?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oh sorry, I should have explained. This was so I could develop the project on GitHub Codespaces (instead of using more disk space on my laptop). It's up to you if you want to merge it in or not, I can remove it from any future mergeable PRs. It's actually not foolproof because it doesn't install Stack by default yet. If you're interested I'll get it fully working, if not, I'll leave it as-is/remove it before we merge.

Copy link
Owner

Choose a reason for hiding this comment

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

On that topic, I'll want the opinion of @balacij .

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not against this, but I'm hesitant to say we should merge until (at least):

  1. We've cleaned up our own project configuration a little bit.
  2. We can install all dependencies (for which we have many) through the file.
  3. We write instructions on how to use it.
  4. We confirm that it works for all of usual tasks and that we have a usecase. The pricing of Codespaces doesn't look too bad, which is certainly appealing if we ever have students with low-spec computers!

Does HLS work with this? I would imagine that GitHub Codespaces has fairly limited resources?

Copy link
Owner

Choose a reason for hiding this comment

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

So we should definitely not merge this in via this particular PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@balacij HLS works on Codespaces just fine, the smallest one has 2 vCores, 8gb of RAM and 32gb of storage. But I agree we shouldn't merge this yet.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Also, there is a way to get "unlimited" (for practical purposes) Codespaces for free for education settings. It is nice for helping people get started for sure.

"name": "GitHub Codespaces (Haskell)",
"image": "davidgontrum/haskellcodespaces",
"settings": {
"terminal.integrated.shell.linux": "/bin/bash",
},
"remoteUser": "codespace",
"overrideCommand": false,
"workspaceMount": "source=${localWorkspaceFolder},target=/home/codespace/workspace,type=bind,consistency=cached",
"workspaceFolder": "/home/codespace/workspace",
"mounts": [ "source=/var/run/docker.sock,target=/var/run/docker-host.sock,type=bind" ],
"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],

"extensions": [
"haskell.haskell",
"k--kato.intellij-idea-keybindings",
"GitHub.vscode-pull-request-github",
"MS-vsliveshare.vsliveshare"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ module Data.Drasil.ExternalLibraries.ODELibraries (
) where

import Language.Drasil (HasSymbol(symbol), HasUID(uid), MayHaveUnit(getUnit),
QuantityDict, HasSpace(typ), Space (Actor, Natural, Real, Void, Boolean, String, Array, Vect), implVar,
QuantityDict, HasSpace(typ), Space (Actor, Natural, Real, Void, Boolean, String, Array, ClifS), implVar,
implVarUID, implVarUID', qw, compoundPhrase, nounPhrase, nounPhraseSP, label,
sub, Idea(getA), NamedIdea(term), Stage(..), (+++))
import Language.Drasil.Display (Symbol(Label, Concat))
Expand Down Expand Up @@ -443,15 +443,15 @@ odeint = externalLib [
customObjArg [] "Class representing an ODE system" ode odeCtor
(customClass [constructorInfo odeCtor [] [],
methodInfoNoReturn odeOp "function representation of ODE system"
[unnamedParam (Vect Real), unnamedParam (Vect Real), lockedParam t]
[unnamedParam undefined, unnamedParam undefined, lockedParam t] -- TODO: what do we put here? We need specific dimensions now.
Copy link
Owner

Choose a reason for hiding this comment

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

Design decision needs to be made: either we support "arbitrary" dimensional vector spaces (i.e. where the dimension is not mentioned" or we support "specific but unknown" (i.e. symbolic) dimension. Or both.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes. Currently, I support specific dimensions and symbolic dimensions (currently, very simple ones: strings). We could add more such as "dimension is not mentioned" (not sure the ramifications of that for the operations), and things like addition of dimensions.

Copy link
Owner

Choose a reason for hiding this comment

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

Let's try to handle this particular case with symbolic dimensions and see what that means, i.e. what else that forces us to think about.

[assignArrayIndex]]),
-- Need to declare variable holding initial value because odeint will update this variable at each step
preDefinedArg odeintCurrVals,
inlineArg Real, inlineArg Real, inlineArg Real,
customObjArg []
"Class for populating a list during an ODE solution process"
pop popCtor (customClass [
constructorInfo popCtor [unnamedParam (Vect Real)] [],
constructorInfo popCtor [unnamedParam undefined] [], -- TODO: Same as above TODO
methodInfoNoReturn popOp
"appends solution point for current ODE solution step"
[lockedParam y, lockedParam t] [appendCurrSol (sy y)]])]]
Expand Down Expand Up @@ -496,7 +496,7 @@ odeintCurrVals, rk, stepper, pop :: CodeVarChunk
odeintCurrVals = quantvar $ implVar "currVals_odeint" (nounPhrase
"vector holding ODE solution values for the current step"
"vectors holding ODE solution values for the current step")
(Vect Real) (label "currVals")
undefined (label "currVals") -- TODO: Same as above, what do we fill in here?
rk = quantvar $ implVar "rk_odeint" (nounPhrase
"stepper for solving ODE system using Runge-Kutta-Dopri5 method"
"steppers for solving ODE system using Runge-Kutta-Dopri5 method")
Expand Down Expand Up @@ -555,7 +555,7 @@ t = quantvar $ implVar "t_ode" (nounPhrase
y = quantvar $ implVar "y_ode" (nounPhrase
"current dependent variable value in ODE solution"
"current dependent variable value in ODE solution")
(Vect Real) (label "y")
undefined (label "y") -- TODO: Same as above - what dimension do we use here?

-- | ODE object constructor.
odeCtor :: CodeFuncChunk
Expand Down Expand Up @@ -599,8 +599,8 @@ modifiedODESyst sufx info = map replaceDepVar (odeSyst info)
replaceDepVar (Matrix es) = Matrix $ map (map replaceDepVar) es
replaceDepVar (UnaryOp u e) = UnaryOp u $ replaceDepVar e
replaceDepVar (UnaryOpB u e) = UnaryOpB u $ replaceDepVar e
replaceDepVar (UnaryOpVV u e) = UnaryOpVV u $ replaceDepVar e
replaceDepVar (UnaryOpVN u e) = UnaryOpVN u $ replaceDepVar e
replaceDepVar (UnaryOpCC u e) = UnaryOpCC u $ replaceDepVar e
replaceDepVar (UnaryOpCN u e) = UnaryOpCN u $ replaceDepVar e
replaceDepVar (ArithBinaryOp b e1 e2) = ArithBinaryOp b
(replaceDepVar e1) (replaceDepVar e2)
replaceDepVar (BoolBinaryOp b e1 e2) = BoolBinaryOp b
Expand All @@ -611,9 +611,9 @@ modifiedODESyst sufx info = map replaceDepVar (odeSyst info)
(replaceDepVar e1) (replaceDepVar e2)
replaceDepVar (OrdBinaryOp b e1 e2) = OrdBinaryOp b
(replaceDepVar e1) (replaceDepVar e2)
replaceDepVar (VVNBinaryOp b e1 e2) = VVNBinaryOp b
replaceDepVar (CCNBinaryOp b e1 e2) = CCNBinaryOp b
(replaceDepVar e1) (replaceDepVar e2)
replaceDepVar (VVVBinaryOp b e1 e2) = VVVBinaryOp b
replaceDepVar (CCCBinaryOp b e1 e2) = CCCBinaryOp b
(replaceDepVar e1) (replaceDepVar e2)
replaceDepVar (Operator ao dd e) = Operator ao dd $ replaceDepVar e
replaceDepVar e = e
4 changes: 2 additions & 2 deletions code/drasil-code/lib/Language/Drasil/Chunk/Parameter.hs
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@
-- | Finds the units of the 'CodeChunk' used to make the 'ParameterChunk'.
instance MayHaveUnit ParameterChunk where getUnit = getUnit . view pcc

-- | Automatically chooses 'PassBy' based on 'Space' ('Vect'ors and 'Actor's passed by reference).
-- | Automatically chooses 'PassBy' based on 'Space' ('Clif's and 'Actor's passed by reference).
pcAuto :: (CodeIdea c) => c -> ParameterChunk
pcAuto c = PC cdch (choosePB $ cdch ^. typ)
where cdch = codeChunk c
choosePB (Vect _) = Ref
choosePB (ClifS _ _ _) = Ref

Check warning on line 44 in code/drasil-code/lib/Language/Drasil/Chunk/Parameter.hs

View workflow job for this annotation

GitHub Actions / Linter

Suggestion in pcAuto in module Language.Drasil.Chunk.Parameter: Use record patterns ▫︎ Found: "ClifS _ _ _" ▫︎ Perhaps: "ClifS {}"
choosePB (Actor _) = Ref
choosePB _ = Val

Expand Down
2 changes: 1 addition & 1 deletion code/drasil-code/lib/Language/Drasil/Code/Code.hs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ spaceToCodeType S.Rational = [Double, Float]
spaceToCodeType S.Boolean = [Boolean]
spaceToCodeType S.Char = [Char]
spaceToCodeType S.String = [String]
spaceToCodeType (S.Vect s) = map List (spaceToCodeType s)
spaceToCodeType (S.ClifS _ _ s) = map List (spaceToCodeType s)
spaceToCodeType (S.Matrix _ _ s) = map (List . List) (spaceToCodeType s)
Copy link
Owner

Choose a reason for hiding this comment

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

I guess you're choosing not to replace Matrix with ClifS this go around?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oops - I should have included that as another question. I didn't because I wasn't quite sure what kind of clif it should be represented as. Do you have thoughts? Would an m-by-n matrix be represented as something like an n-grade clif in an m-dimensional space? Dr. Smith and I did some research and there's not much about using clifs to represent matrices. The geometric algebra people have this attitude of "we don't need matrices" so they seem not to even think about them.

Copy link
Owner

Choose a reason for hiding this comment

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

https://math.stackexchange.com/questions/850869/linear-algebra-without-matrices is one place to start reading. It points to the nice book "Linear Algebra Done Right" which is really quite a gem. [In a sense, chapter 1 of https://arkadiusz-jadczyk.eu/docs/clifford.pdf says that concrete Clifford Algebras are equivalent to some spaces of matrices...]

However, we will still want to be able to enter 'concrete' matrices (in a basis).

The book "Guide to Geometric Algebra in Practice " is available for download from McMaster's library - I think that one would help most.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@JacquesCarette these look to be good resources. @CSchank can you please add links to these resources to your slide show on Clifford algebra. I worry that if we the links only appear here, we won't be able to find them in the future if we go looking. 😄

Copy link
Owner

Choose a reason for hiding this comment

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

We should have a page on our Wiki for that too - maybe @balacij can show @CSchank how to do a PR for that?

spaceToCodeType (S.Set s) = map List (spaceToCodeType s)
spaceToCodeType (S.Array s) = map Array (spaceToCodeType s)
Expand Down
56 changes: 28 additions & 28 deletions code/drasil-code/lib/Language/Drasil/Code/Imperative/Import.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import Language.Drasil.CodeExpr (sy, ($<), ($>), ($<=), ($>=), ($&&), in')
import qualified Language.Drasil.CodeExpr.Development as S (CodeExpr(..))
import Language.Drasil.CodeExpr.Development (CodeExpr(..), ArithBinOp(..),
AssocArithOper(..), AssocBoolOper(..), AssocConcatOper(..), BoolBinOp(..), EqBinOp(..),
LABinOp(..), OrdBinOp(..), UFunc(..), UFuncB(..), UFuncVV(..), UFuncVN(..),
VVNBinOp(..), VVVBinOp(..), NVVBinOp(..), ESSBinOp(..), ESBBinOp(..))
LABinOp(..), OrdBinOp(..), UFunc(..), UFuncB(..), UFuncCC(..), UFuncCN(..),
CCNBinOp(..), CCCBinOp(..), NCCBinOp(..), ESSBinOp(..), ESBBinOp(..))
import Language.Drasil.Code.Imperative.Comments (getComment)
import Language.Drasil.Code.Imperative.ConceptMatch (conceptToGOOL)
import Language.Drasil.Code.Imperative.GenerateGOOL (auxClass, fApp, fAppProc,
Expand Down Expand Up @@ -337,8 +337,8 @@ convExpr (Field o f) = do
return $ valueOf v
convExpr (UnaryOp o u) = fmap (unop o) (convExpr u)
convExpr (UnaryOpB o u) = fmap (unopB o) (convExpr u)
convExpr (UnaryOpVV o u) = fmap (unopVV o) (convExpr u)
convExpr (UnaryOpVN o u) = fmap (unopVN o) (convExpr u)
convExpr (UnaryOpCC o u) = fmap (unopCC o) (convExpr u)
convExpr (UnaryOpCN o u) = fmap (unopCN o) (convExpr u)
convExpr (ArithBinaryOp Frac (Lit (Int a)) (Lit (Int b))) = do -- hack to deal with integer division
sm <- spaceCodeType Rational
let getLiteral Double = litDouble (fromIntegral a) #/ litDouble (fromIntegral b)
Expand All @@ -350,9 +350,9 @@ convExpr (BoolBinaryOp o a b) = liftM2 (boolBfunc o) (convExpr a) (convExpr b)
convExpr (LABinaryOp o a b) = liftM2 (laBfunc o) (convExpr a) (convExpr b)
convExpr (EqBinaryOp o a b) = liftM2 (eqBfunc o) (convExpr a) (convExpr b)
convExpr (OrdBinaryOp o a b) = liftM2 (ordBfunc o) (convExpr a) (convExpr b)
convExpr (VVVBinaryOp o a b) = liftM2 (vecVecVecBfunc o) (convExpr a) (convExpr b)
convExpr (VVNBinaryOp o a b) = liftM2 (vecVecNumBfunc o) (convExpr a) (convExpr b)
convExpr (NVVBinaryOp o a b) = liftM2 (numVecVecBfunc o) (convExpr a) (convExpr b)
convExpr (CCCBinaryOp o a b) = liftM2 (clfClfClfBfunc o) (convExpr a) (convExpr b)
convExpr (CCNBinaryOp o a b) = liftM2 (clfClfNumBfunc o) (convExpr a) (convExpr b)
convExpr (NCCBinaryOp o a b) = liftM2 (numClfClfBfunc o) (convExpr a) (convExpr b)
convExpr (ESSBinaryOp o a b) = liftM2 (elementSetSetBfunc o) (convExpr a) (convExpr b)
convExpr (ESBBinaryOp o a b) = liftM2 (elementSetBoolBfunc o) (convExpr a) (convExpr b)
convExpr (Case c l) = doit l -- FIXME this is sub-optimal
Expand Down Expand Up @@ -447,13 +447,13 @@ unopB :: (SharedProg r) => UFuncB -> (SValue r -> SValue r)
unopB Not = (?!)

-- | Similar to 'unop', but for vectors.
unopVN :: (SharedProg r) => UFuncVN -> (SValue r -> SValue r)
unopVN Dim = listSize
unopVN Norm = error "unop: Norm not implemented" -- TODO
unopCN :: (SharedProg r) => UFuncCN -> (SValue r -> SValue r)
unopCN Dim = listSize
unopCN Norm = error "unop: Norm not implemented" -- TODO

-- | Similar to 'unop', but for vectors.
unopVV :: (SharedProg r) => UFuncVV -> (SValue r -> SValue r)
unopVV NegV = error "unop: Negation on Vectors not implemented" -- TODO
unopCC :: (SharedProg r) => UFuncCC -> (SValue r -> SValue r)
unopCC NegC = error "unop: Negation on Clifs not implemented" -- TODO

-- Maps an 'ArithBinOp' to it's corresponding GOOL binary function.
arithBfunc :: (SharedProg r) => ArithBinOp -> (SValue r -> SValue r -> SValue r)
Expand Down Expand Up @@ -483,19 +483,19 @@ ordBfunc Lt = (?<)
ordBfunc LEq = (?<=)
ordBfunc GEq = (?>=)

-- Maps a 'VVVBinOp' to it's corresponding GOOL binary function.
vecVecVecBfunc :: VVVBinOp -> (SValue r -> SValue r -> SValue r)
vecVecVecBfunc Cross = error "bfunc: Cross not implemented"
vecVecVecBfunc VAdd = error "bfunc: Vector addition not implemented"
vecVecVecBfunc VSub = error "bfunc: Vector subtraction not implemented"
-- Maps a 'CCCBinOp' to it's corresponding GOOL binary function.
clfClfClfBfunc :: CCCBinOp -> (SValue r -> SValue r -> SValue r)
clfClfClfBfunc Cross = error "bfunc: Cross not implemented"
clfClfClfBfunc CAdd = error "bfunc: Clif addition not implemented"
clfClfClfBfunc CSub = error "bfunc: Clif subtraction not implemented"

-- Maps a 'VVNBinOp' to it's corresponding GOOL binary function.
vecVecNumBfunc :: VVNBinOp -> (SValue r -> SValue r -> SValue r)
vecVecNumBfunc Dot = error "convExpr DotProduct"
-- Maps a 'CCNBinOp' to it's corresponding GOOL binary function.
clfClfNumBfunc :: CCNBinOp -> (SValue r -> SValue r -> SValue r)
clfClfNumBfunc Dot = error "convExpr DotProduct"

-- Maps a 'NVVBinOp' to it's corresponding GOOL binary function.
numVecVecBfunc :: NVVBinOp -> (SValue r -> SValue r -> SValue r)
numVecVecBfunc Scale = error "convExpr Scaling of Vectors"
-- Maps a 'NCCBinOp' to it's corresponding GOOL binary function.
numClfClfBfunc :: NCCBinOp -> (SValue r -> SValue r -> SValue r)
numClfClfBfunc Scale = error "convExpr Scaling of Vectors"

-- Maps a 'ESSBinOp' to its corresponding GOOL binary function.
elementSetSetBfunc :: (SharedProg r) => ESSBinOp -> (SValue r -> SValue r -> SValue r)
Expand Down Expand Up @@ -1038,8 +1038,8 @@ convExprProc (Message {}) = error "convExprProc: Procedural renderers do not sup
convExprProc (Field _ _) = error "convExprProc: Procedural renderers do not support object field access"
convExprProc (UnaryOp o u) = fmap (unop o) (convExprProc u)
convExprProc (UnaryOpB o u) = fmap (unopB o) (convExprProc u)
convExprProc (UnaryOpVV o u) = fmap (unopVV o) (convExprProc u)
convExprProc (UnaryOpVN o u) = fmap (unopVN o) (convExprProc u)
convExprProc (UnaryOpCC o u) = fmap (unopCC o) (convExprProc u)
convExprProc (UnaryOpCN o u) = fmap (unopCN o) (convExprProc u)
convExprProc (ArithBinaryOp Frac (Lit (Int a)) (Lit (Int b))) = do -- hack to deal with integer division
sm <- spaceCodeType Rational
let getLiteral Double = litDouble (fromIntegral a) #/ litDouble (fromIntegral b)
Expand All @@ -1051,9 +1051,9 @@ convExprProc (BoolBinaryOp o a b) = liftM2 (boolBfunc o) (convExprProc a) (conv
convExprProc (LABinaryOp o a b) = liftM2 (laBfunc o) (convExprProc a) (convExprProc b)
convExprProc (EqBinaryOp o a b) = liftM2 (eqBfunc o) (convExprProc a) (convExprProc b)
convExprProc (OrdBinaryOp o a b) = liftM2 (ordBfunc o) (convExprProc a) (convExprProc b)
convExprProc (VVVBinaryOp o a b) = liftM2 (vecVecVecBfunc o) (convExprProc a) (convExprProc b)
convExprProc (VVNBinaryOp o a b) = liftM2 (vecVecNumBfunc o) (convExprProc a) (convExprProc b)
convExprProc (NVVBinaryOp o a b) = liftM2 (numVecVecBfunc o) (convExprProc a) (convExprProc b)
convExprProc (CCCBinaryOp o a b) = liftM2 (clfClfClfBfunc o) (convExprProc a) (convExprProc b)
convExprProc (CCNBinaryOp o a b) = liftM2 (clfClfNumBfunc o) (convExprProc a) (convExprProc b)
convExprProc (NCCBinaryOp o a b) = liftM2 (numClfClfBfunc o) (convExprProc a) (convExprProc b)
convExprProc (ESSBinaryOp o a b) = liftM2 (elementSetSetBfunc o) (convExprProc a) (convExprProc b)
convExprProc (ESBBinaryOp o a b) = liftM2 (elementSetBoolBfunc o) (convExprProc a) (convExprProc b)
convExprProc (Case c l) = doit l -- FIXME this is sub-optimal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import Language.Drasil.Code.DataDesc (DataDesc'(..), Data'(..), DataItem'(..),
Delimiter, dataDesc, junk, list, singleton')
import Language.Drasil.Chunk.Code (CodeVarChunk)
import Language.Drasil.Expr.Development (Expr(Matrix))
import Language.Drasil.Expr.Development (Expr(Matrix, Clif)) -- TODO: remove Matrix entirely

import Control.Lens ((^.))
import Data.List (intersperse, isPrefixOf, transpose)
Expand Down Expand Up @@ -66,7 +66,7 @@
sampleInputDD :: [CodeVarChunk] -> DataDesc'
sampleInputDD ds = dataDesc (junk : intersperse junk (map toData ds)) "\n"
where toData d = toData' (d ^. typ) d
toData' t@(Vect _) d = list d
toData' t@(ClifS _ _ _) d = list d

Check warning on line 69 in code/drasil-code/lib/Language/Drasil/Code/Imperative/ReadInput.hs

View workflow job for this annotation

GitHub Actions / Linter

Suggestion in sampleInputDD in module Language.Drasil.Code.Imperative.ReadInput: Use record patterns ▫︎ Found: "ClifS _ _ _" ▫︎ Perhaps: "ClifS {}"
(take (getDimension t) ([", ", "; "] ++ iterate (':':) ":"))
toData' _ d = singleton' d

Expand All @@ -83,7 +83,7 @@

-- | Gets the dimension of a 'Space'.
getDimension :: Space -> Int
getDimension (Vect t) = 1 + getDimension t
getDimension (ClifS _ _ s) = 1 + getDimension s -- TODO: Does this make sense? Maybe we're overloading the term "dimension" now.
Copy link
Owner

Choose a reason for hiding this comment

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

I agree, this is weird. Can you figure out who calls getDimension and what they need from it? It looks like this is always going to return '1' for a Vector and 0 in all other cases!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Well, we had things like Vect (Vect Natural) which would return 2.

Copy link
Owner

Choose a reason for hiding this comment

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

Ah, yes. Horrible hack that. See if you can get rid of it?

getDimension _ = 0

-- | Splits a string at the first (and only the first) occurrence of a delimiter.
Expand All @@ -98,12 +98,12 @@
dropDelim [] s = s
dropDelim _ [] = error "impossible"

-- | Converts a list of 'String's to a Matrix 'Expr' of a given 'Space'.
-- | Converts a list of 'String's to a Clif 'Expr' of a given 'Space'.
strListAsExpr :: Space -> [String] -> Expr
strListAsExpr (Vect t) ss = Matrix [map (strAsExpr t) ss]
Copy link
Owner

Choose a reason for hiding this comment

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

you shouldn't do Matrix partially; either try for all cases or none, but not just some!

strListAsExpr (ClifS gr d s) ss = undefined -- TODO: fill this in
strListAsExpr _ _ = error "strListsAsExpr called on non-vector space"

-- | Converts a 2D list of 'String's to a Matrix 'Expr' of a given 'Space'.
-- | Converts a 2D list of 'String's to a Clif 'Expr' of a given 'Space'.
strList2DAsExpr :: Space -> [[String]] -> Expr
strList2DAsExpr (Vect (Vect t)) sss = Matrix $ map (map (strAsExpr t)) sss
strList2DAsExpr (ClifS gr0 d0 (ClifS gr1 d1 s)) sss = undefined -- TODO: fill this in
Copy link
Owner

Choose a reason for hiding this comment

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

Trying to fill these particular TODOs will be very instructive.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is another question I had: does geometric algebra have such a thing as "clifs of clifs"?

Copy link
Owner

Choose a reason for hiding this comment

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

No, GA does not nest.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Didn't think so. So, if Clifs take Expr as an argument, we will have to have type checking to make sure they don't take another clif as an argument.

Copy link
Owner

Choose a reason for hiding this comment

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

Correct.

strList2DAsExpr _ _ = error "strLists2DAsExprs called on non-2D-vector space"
3 changes: 2 additions & 1 deletion code/drasil-data/lib/Data/Drasil/Quantities/Physics.hs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ acceleration, angularAccel, angularDisplacement, angularVelocity, chgInVelocity,
yVel, momentum, moment, moment2D, fOfGravity, positionVec, tension, angularFrequency,
period, frequency, chgMomentum :: UnitalChunk

acceleration = uc CP.acceleration (Concat [vec lA, label "(", lT, label ")"]) (Vect Real) accelU
-- TODO: what should the type here be?
acceleration = uc CP.acceleration (Concat [vec lA, label "(", lT, label ")"]) undefined accelU
Copy link
Collaborator

Choose a reason for hiding this comment

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

Taking a look at usage in GamePhysics, a Real -> Real function seems more likely than a Vect Real.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Note that functions are still mostly unsupported as well, hence why the time variable is manually added to the symbol of acceleration.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Another option for the type is Real -> Vect Real. In 3D the acceleration is a function of time. In general, at any time, we can have 3 components of acceleration. We also have a 1D version of acceleration in Game Physics which would have the type Real -> Real.

Copy link
Owner

Choose a reason for hiding this comment

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

This is a symptom of a deeper problem in Drasil: acceleration should exist in many different ways (as a concept, as an instance of properties for several objects, but also as something that may be represented in different ways!)

So acceleration can be Real, Vect Real and Real -> Real depending on the case at hand. Thus we need to be able to do that.

Copy link
Owner

Choose a reason for hiding this comment

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

So this is where @CSchank is likely going to need to rely on @balacij sorting out some stuff in our chunks.

For this one: I don't think the concept of acceleration should be a UnitalChunk because its 'units' will actually depend on the setting in which it is used, i.e. acceleration gets a unit once the object of concern is known.

We could treat it as a vector of unknown dimension if we insisted on giving it units 'early', thus indicating that it is a dependent concept.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@balacij any chance we can work on this?

Copy link
Owner

Choose a reason for hiding this comment

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

@balacij might now be free, given that his Comp II was earlier today.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Hi, sorry @CSchank! I will message you on Discord!

angularAccel = uc CP.angAccel lAlpha Real angAccelU
angularDisplacement = uc CP.angDisp lTheta Real radian
angularFrequency = uc CP.angFreq cOmega Real second
Expand Down
24 changes: 12 additions & 12 deletions code/drasil-example/glassbr/lib/Drasil/GlassBR/ModuleDefs.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

module Drasil.GlassBR.ModuleDefs (allMods, implVars, interpY, interpZ) where

import Language.Drasil (QuantityDict, Space(..), implVar, nounPhraseSP,
import Language.Drasil (QuantityDict, Space(..), vect3D, implVar, nounPhraseSP,
label, sub, HasSymbol(..), HasUID, Symbol)
import Language.Drasil.Display (Symbol(..))
import Language.Drasil.ShortHands
Expand Down Expand Up @@ -64,25 +64,25 @@ y = var "y" "y-coordinate to interpolate at" lY Real
z = var "z" "z-coordinate to interpolate at" lZ Real

zVector = var "zVector" "list of z values"
(sub lZ (label "vector")) (Vect Real)
(sub lZ (label "vector")) (vect3D Real)
yMatrix = var "yMatrix" "lists of y values at different z values"
(sub lY (label "matrix")) (Vect $ Vect Real)
(sub lY (label "matrix")) (vect3D $ vect3D Real)
xMatrix = var "xMatrix" "lists of x values at different z values"
(sub lX (label "matrix")) (Vect $ Vect Real)
(sub lX (label "matrix")) (vect3D $ vect3D Real)
arr = var "arr" "array in which value should be found"
(label "arr") (Vect Real) --FIXME: temporary variable for findCT?
(label "arr") (vect3D Real) --FIXME: temporary variable for findCT?
x_z_1 = var "x_z_1" "list of x values at a specific z value"
(sub lX (sub lZ one)) (Vect Real)
(sub lX (sub lZ one)) (vect3D Real)
y_z_1 = var "y_z_1" "list of y values at a specific z value"
(sub lY (sub lZ one)) (Vect Real)
(sub lY (sub lZ one)) (vect3D Real)
x_z_2 = var "x_z_2" "list of x values at a specific z value"
(sub lX (sub lZ two)) (Vect Real)
(sub lX (sub lZ two)) (vect3D Real)
y_z_2 = var "y_z_2" "list of y values at a specific z value"
(sub lY (sub lZ two)) (Vect Real)
(sub lY (sub lZ two)) (vect3D Real)
mat = var "mat" "matrix from which column will be extracted"
(label "mat") (Vect $ Vect Real)
(label "mat") (vect3D $ vect3D Real)
col = var "col" "extracted column"
(label "col") (Vect Real)
(label "col") (vect3D Real)
filename = var "filename" "name of file with x y and z data"
(label "filename") String

Expand Down Expand Up @@ -152,7 +152,7 @@ findCT = funcDef "find"

extractColumnCT :: Func
extractColumnCT = funcDef "extractColumn" "Extracts a column from a 2D matrix"
[mat, j] (Vect Real) (Just "column of the given matrix at the given index")
[mat, j] (vect3D Real) (Just "column of the given matrix at the given index") -- TODO: is this correct?
Copy link
Owner

Choose a reason for hiding this comment

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

while the above 3Ds are likely right, I agree, this one is less clear. You'll have to see where extractColumnCT is used to see what the context says.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, so this is to extract a given column in the matrix. It's used as part of this:

interpMod :: Mod
interpMod = packmod "Interpolation" 
  "Provides functions for linear interpolation on three-dimensional data" []
  [linInterpCT, findCT, extractColumnCT, interpY, interpZ]

So yes, 3D.

Copy link
Owner

Choose a reason for hiding this comment

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

Right, so this is 'different' in the sense that this isn't a semantic operation but rather this is a programming-level operation where an array is used for packed storage and then its columns are extracted.

So in a separate language (ModelExpr ?), we need ways to talk about storage and concrete representations. It's a typical mistake to conflate these.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@JacquesCarette should this separate language be within the scope of the project by @CSchank? Ideally I would like us to include at least parts of this other language as needed for the current examples, but I don't have a feel for how difficult a task this is.

Copy link
Owner

Choose a reason for hiding this comment

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

It should be in-scope. It's a much simpler language.

[
fDecDef col (matrix [[]]),
--
Expand Down
2 changes: 1 addition & 1 deletion code/drasil-example/swhs/lib/Drasil/SWHS/Unitals.hs
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ outputs = [tempW, tempPCM, watE, pcmE]
tempW = cuc' "tempW"
(nounPhraseSP "temperature of the water")
"the average kinetic energy of the particles within the water"
(sub (eqSymb temp) lWater) centigrade (Vect Real)
(sub (eqSymb temp) lWater) centigrade (vect undefined Real) -- TODO: dimension of vector?
Copy link
Owner

Choose a reason for hiding this comment

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

I believe this is 3D

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm having trouble thinking of what the dimension of tempW should be. The temperature of the water is a scalar value. The problem is 1D. There is only one temperature for the water. It varies over time, but not over space. Even if temperature varies over space, it is still a scalar. The only reason I can think for a vector is that in solving the ODE we use a vector, but Tw is one of the components of the vector, not a vector itself.

Copy link
Owner

Choose a reason for hiding this comment

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

So this is a bug in our 'formalization' of tempW?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't know if it is a bug, or a misunderstanding on my part. The generated documentation for tempW has been reviewed many times, so I believe it is correct. The definition of tempW looks good (the average kinetic energy part) and I believe that part appears in the generated documentation. I don't know if the type of tempW is ever displayed or used. If the "formalization" of tempW is not used to do anything, it could be wrong and we'd never know because there are no consequences of a mistake. If someone could explain the consequences of the formalization in the generated artifacts, I would help judge whether they are correct or not. If they really aren't used, then I'm fairly sure they are currently incorrect. 😄

Copy link
Owner

Choose a reason for hiding this comment

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

I'm not sure we print 'types' in the SRS (because they didn't exist when you last reviewed). So I wouldn't be surprised if there were uncaught bugs here.

Copy link
Collaborator Author

@CSchank CSchank Mar 12, 2025

Choose a reason for hiding this comment

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

Yes, I came to the same conclusion. This appears to result in the output constraints table (below), but it was likely never caught because the type is not printed, as you say. I have changed it to be Real for now, which I believe is the correct type.

image

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm fine with using Real for Tw just to move on, but the constraint isn't on a single value of Tw; it is on every value of the function for Tw between the start of the simulation and the conclusion of the simulation. The constraint should be something like:

$$ \forall (t: \mathbb{R} | 0 \leq t \leq t_\text{final} : T_\text{init} \leq T_w(t) \leq T_c)$$

Since we don't handle types consistently right now, I don't think we should make any changes. It also seems out of scope of the work by @CSchank to explore this. 😄

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@smiths well, I now have a partial answer why this was listed as a vector type. I tried running the example again changed to Real and I got an error produced by this line of code, producing the following error:

=====[ Start type checking ]=====
`theory:eBalanceOnWtrRC` exposes ill-typed expressions!
  - ERROR: Associative arithmetic operation expects all operands to be of the same expected type.
    Received:
    - ERROR: List accessor expects a list/vector, but received `Real`.
`heatEInWtrIM` exposes ill-typed expressions!
  - ERROR: Associative arithmetic operation expects all operands to be of the same expected type.
    Received:
    - Real
    - ERROR: Function application on non-function `tempW` (Real).
`wMass` OK!
`wVol` OK!
`tankVol` OK!
`tauW` OK!
=====[ Finished type checking ]=====
swhsnopcm: Type mismatch between variable and value in declare-define FuncStmt
CallStack (from HasCallStack):
  error, called at lib/Language/Drasil/Code/Imperative/Import.hs:650:28 in drasil-code-0.1.9.0-BZ5f3ZI9HUq1TjClKZN633:Language.Drasil.Code.Imperative.Import

From what I can understand from that linked line of code, this section of the code checks an expression that is a function definition to ensure that if the output type is a matrix then the input type must be either a list or an array. At some point vectors (now clifs) get converted into arrays for their concrete code representation. Reals, of course, do not get converted to arrays or lists. So this caused this error. So obviously this type is factoring in, albeit in a pretty roundabout way. So I'll have to switch it back to vectND (a clif) for now to appease avoid this error for now as, like you said, this issue is beyond my scope.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thank you for the explanation @CSchank. I agree with your solution. In some sense, it is a good error. The generated code will not be a single scalar for the output. The types of the output in the code and the output in the SRS should be the same, or at least have a translation between them, like between a continuous function and a discrete sequence of output. Since we don't have types fully and consistently used right now, we should move on from this instance and let it be sorted out in the future when types are handled more consistently and completely.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sounds good, thank you!

[physRange $ Bounded (Inc, sy tempInit) (Inc, sy tempC)] (exactDbl 0)

-- Constraint 19
Expand Down
Loading
Loading