diff --git a/.gitignore b/.gitignore index 895eb4be7..a0e99ec02 100644 --- a/.gitignore +++ b/.gitignore @@ -105,3 +105,6 @@ result # vm image catcolab-vm.qcow2 + +# VSCode +.vscode/* \ No newline at end of file diff --git a/packages/algjulia-interop/Project.toml b/packages/algjulia-interop/Project.toml index 9e270ce35..0d1e76d5b 100644 --- a/packages/algjulia-interop/Project.toml +++ b/packages/algjulia-interop/Project.toml @@ -1,53 +1,28 @@ name = "CatColabInterop" uuid = "9ecda8fb-39ab-46a2-a496-7285fa6368c1" license = "MIT" -authors = ["CatColab team"] version = "0.1.1" +authors = ["CatColab team"] [deps] -ACSets = "227ef7b5-1206-438b-ac65-934d6da304b8" -Catlab = "134e5e36-593f-5add-ad60-77f754baafbe" -CombinatorialSpaces = "b1c52339-7909-45ad-8b6a-6e388f7c67f2" -ComponentArrays = "b0b7db55-cfe3-40fc-9ded-d10e2dbeff66" -CoordRefSystems = "b46f11dc-f210-4604-bfba-323c1ec968cb" -Decapodes = "679ab3ea-c928-4fe6-8d59-fd451142d391" -DiagrammaticEquations = "6f00c28b-6bed-4403-80fa-30e0dc12f317" -Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" -GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326" -IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" -JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" -LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" MLStyle = "d8e11817-5142-5d16-987a-aa16d5891078" -OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" -Preferences = "21216c6a-2e73-6563-6e65-726566657250" -REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" +Oxygen = "df9a0d86-3283-4920-82dc-4555fc0d1d8b" Reexport = "189a3867-3050-52da-a836-e630ba90ab69" -StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" +StructTypes = "856f2bd8-1eba-4b0a-8007-ebc267875bd4" [weakdeps] -PackageCompiler = "9b87118b-4619-50d2-8e1e-99f35a4d4d9d" +ACSets = "227ef7b5-1206-438b-ac65-934d6da304b8" +Catlab = "134e5e36-593f-5add-ad60-77f754baafbe" [extensions] -SysImageExt = "PackageCompiler" +CatlabExt = ["Catlab", "ACSets"] [compat] -ACSets = "0.2.21" -Catlab = "0.16.20" -CombinatorialSpaces = "0.7.4" -ComponentArrays = "0.15" -CoordRefSystems = "0.18.9" -Decapodes = "0.6" -DiagrammaticEquations = "0.2" -Distributions = "0.25" -GeometryBasics = "0.5.7" -IJulia = "1.26.0" -JSON3 = "1" -LinearAlgebra = "1" -MLStyle = "0.4" -OrdinaryDiffEq = "6.101.0" -PackageCompiler = "2.2.1" -Preferences = "1.5.0" -REPL = "1.11.0" +Catlab = "0.17.2" +HTTP = "1.10.19" +MLStyle = "0.4.17" +Oxygen = "1.7.5" Reexport = "1.2.2" -StaticArrays = "1" +StructTypes = "1.11.0" julia = "1.11" diff --git a/packages/algjulia-interop/README.md b/packages/algjulia-interop/README.md index f2f08390f..2ea02942e 100644 --- a/packages/algjulia-interop/README.md +++ b/packages/algjulia-interop/README.md @@ -1,47 +1,37 @@ # AlgebraicJulia Service This small package makes functionality from -[AlgebraicJulia](https://www.algebraicjulia.org/) available to CatColab, -intermediated by a Julia kernel running in the [Jupyter](https://jupyter.org/) -server. At this time, only a -[Decapodes.jl](https://github.com/AlgebraicJulia/Decapodes.jl) service is -provided. Other packages may be added in the future. - -## Setup - -1. Install [Julia](https://julialang.org/), say by using -[`juliaup`](https://github.com/JuliaLang/juliaup) -2. Install [Jupyter](https://jupyter.org/), say by using `pip` or `conda` -3. Install [IJulia](https://github.com/JuliaLang/IJulia.jl), which provides the - Julia kernel to Jupyter - -At this stage, you should be able to launch a Julia kernel inside a JupyterLab. - -Having done that, navigate to this directory and run: - -```sh -julia --project -e 'import Pkg; Pkg.instantiate()' -``` +[AlgebraicJulia](https://www.algebraicjulia.org/) available to CatColab.At this +time, only a [Catlab.jl](https://github.com/AlgebraicJulia/Catlab.jl) service is +provided. Other packages (e.g. Decapodes.jl) will be added in the future. ## Usage -To start the server, run the following in a Julia REPL -```julia -using CatColabInterop -start_server!() -``` -This will run the Jupyter kernel in the REPL. You may stop the server by -running `stop_server!()`. While the Jupyter server is running, the AlgebraicJulia service will be usable by CatColab when served locally. - -## Compiling a Sysimage +First, install [Julia](https://julialang.org/), say by using +[`juliaup`](https://github.com/JuliaLang/juliaup). + +We then need a Julia environment that has all the requisite packages installed. +The `test` folder of this repo is a perfectly good candidate for this, although +in principal one might want to use their own environment (if they don't want to +load all dependencies for all possible analyses, or if they have a locally +modified version of the code that is running the analysis). To make sure this +environment is ready to use, navigate to this directory and run +`julia --project=test` and then press `]` and enter the commands `instantiate` +and `precompile`. + +Having done that, to start the server, from this directory run: -Precompiling dependencies like `CairoMakie.jl` and `OrdinaryDiffEq.jl` can be -time-consuming. A **sysimage** is a file that stores precompilation statements, -making future invocations of `AlgebraicJuliaService` and its dependencies -immediate. +```sh +julia --project=test scripts/endpoint.jl +``` -To build a sysimage, run `build_sysimage()` in a REPL where `CatColabInterop` -module is in scope. This process may take upwards of five minutes or longer, depending on your machine. +This starts an instance that is listening on localhost port 8080. When you run +CatColab, you should be able to use analyses that communicate with Julia via +this address. -Building a sysimage installs an additional kernel which points to the sysimage. You may change the kernel to your sysimage by running `change_kernel!()`, which will populate a menu of kernels in your IJulia kernel directory. +## For developers +If one is interested in using a version of CatColabInterop.jl that doesn't match +the latest tagged release, then one must first open the Julia environment from the +test directory (`julia --project=test`) and declare one wants to use the local +version of the package (press `]` and then `dev .`) diff --git a/packages/algjulia-interop/ext/CatlabExt.jl b/packages/algjulia-interop/ext/CatlabExt.jl new file mode 100644 index 000000000..15c30202d --- /dev/null +++ b/packages/algjulia-interop/ext/CatlabExt.jl @@ -0,0 +1,120 @@ +module CatlabExt + +using ACSets +using Catlab: Presentation, FreeSchema, Left +import Catlab: id, dom +using Catlab.CategoricalAlgebra.Pointwise.FunctorialDataMigrations.Yoneda: + yoneda, colimit_representables, DiagramData +using CatColabInterop, Oxygen, HTTP +import CatColabInterop: endpoint + +""" +Take a parsed CatColab model of ThSchema and make a Catlab schema. Also +collect the mapping from UUIDs to human-readable names. +""" +function model_to_schema(m::Model)::Tuple{Schema, Dict{String,Symbol}} + obs, homs, attrtypes, attrs = Symbol[],[],[],[] + names = Dict{String, Symbol}() + + for stmt in m.obGenerators + names[stmt.id] = Symbol(only(stmt.label)) + if stmt.obType.content == "Entity" + push!(obs, names[stmt.id]) + elseif stmt.obType.content == "AttrType" + push!(attrtypes, names[stmt.id]) + else + error(stmt.obType) + end + end + + for stmt in m.morGenerators + h = (Symbol(only(stmt.label)), names[stmt.dom.content], + names[stmt.cod.content]) + names[stmt.id] = h[1] + if stmt.morType.content == "Attr" + push!(attrs, h) + else + push!(homs, h) + end + end + (Schema(Presentation(BasicSchema{Symbol}(obs, homs, attrtypes, attrs, []))), + names) +end + +""" +Take a CatColab diagram in a model of ThSchema and construct the input data +that gets parsed normally from `@acset_colim`. Mutate an existing mapping of +UUIDs to schema-level names to include UUID mappings for instance-level names. +""" +function diagram_to_data(d::Types.Diagram, names::Dict{String,Symbol} + )::DiagramData + data = DiagramData() + for o in d.obGenerators + names[o.id] = Symbol(only(o.label)) + push!(data.reprs[names[o.over.content]], names[o.id]) + end + for m in d.morGenerators + p1 = names[m.cod.content] => Symbol[] + p2 = names[m.dom.content] => [names[m.over.content]] + push!(data.eqs, p1 => p2) + end + data +end + +""" +Receiver of the data already knows the schema, so the JSON payload to CatColab +just includes the columns of data. Every part is named, so we use the names +(including for primary key columns) rather than numeric indices. +""" +function acset_to_json(X::ACSet, S::Schema, names::Dict{Symbol, Vector{String}} + )::AbstractDict + Dict{Symbol, Vector{String}}( + [t => names[t] for t in types(S)] + ∪ [f => names[c][X[f]] for (f,_,c) in homs(S)] + ∪ [f => names[c][getvalue.(X[f])] for (f,_,c) in attrs(S)] ) +end + +""" +Pick a human-readable name for all parts of the ACSet, given explicit names for +some of the parts. There is some ambiguity here (the vertex of a generic +reflexive edge `e` could be either `src(e)` or `tgt(e)`), but an arbitrary name +is chosen after minimizing length (`src(e)` preferred over `src(refl(src(e)))`). +""" +function make_names(res::ACSet, names::NamedTuple + )::Dict{Symbol, Vector{String}} + S = acset_schema(res) + function get_name(o::Symbol, i, curr=[])::Vector{Vector{Symbol}} + V(x) = o in attrtypes(S) ? AttrVar(x) : x # embellish attrvars + L(x) = o in attrtypes(S) ? Left(x) : x # embellish attrvars + found = findfirst(==((o, L(i))), names) # if (o,i) is in names + isnothing(found) || return [[found; curr]] # then just give the name + inc = [(d, new_i, f) for (f, d, _) in arrows(S, to=o) + for new_i in incident(res, V(i), f)] + return vcat([get_name(d, new_i, [f; curr]) for (d, new_i, f) in inc]...) + end + return Dict{Symbol, Vector{String}}(map(types(acset_schema(res))) do o + o => map(parts(res, o)) do i + possible_names = sort(get_name(o, i); by=length) + foldl((x,y)->"$y($x)", string.(first(possible_names))) + end + end) +end + +""" +Top level function called by CatColab. Computes an ACSet colimit of a + diagrammatic instance. Return a JSON tabular representation. +""" +function endpoint(::Val{:ACSetColim}) + @post "/acsetcolim" function(req::HTTP.Request) + payload = json(req, ModelDiagram) + schema, names = model_to_schema(payload.model) + data = diagram_to_data(payload.diagram, names) + acset_type = AnonACSet( + schema; type_assignment=Dict(a=>Nothing for a in schema.attrtypes)) + y = yoneda(constructor(acset_type)) + names, res = colimit_representables(data, y) + acset_to_json(res, schema, make_names(res, names)) + end +end + +end # module diff --git a/packages/algjulia-interop/ext/SysImageExt.jl b/packages/algjulia-interop/ext/SysImageExt.jl deleted file mode 100644 index 698555ae1..000000000 --- a/packages/algjulia-interop/ext/SysImageExt.jl +++ /dev/null @@ -1,24 +0,0 @@ -module SysImageExt - -import CatColabInterop: ServerConfig, load_kernels!, install_ccl_kernel!, CONFIG -import PackageCompiler: create_sysimage -import IJulia: installkernel - -function install_ccl_kernel!(::Val{:sysimg}; config::ServerConfig=CONFIG, sysimg = "CatColabInteropSysImage.so") - @info "Creating the sys image. This may take a while..." - mktemp() do path, io - write(io, """import CatColabInterop - include(joinpath(pkgdir(CatColabInterop), "test", "runtests.jl")) - """) - flush(io) - create_sysimage(["CatColabInterop"], sysimage_path=sysimg, precompile_execution_file=path) - end - - @info "Adding $sysimg to IJulia kernel" - installkernel("CatColabInteropSysImage", "--project=@.", "--sysimage=$sysimg") - - load_kernels!() - @info "Done!" -end - -end diff --git a/packages/algjulia-interop/make_sysimage.jl b/packages/algjulia-interop/make_sysimage.jl deleted file mode 100755 index eb1c2e763..000000000 --- a/packages/algjulia-interop/make_sysimage.jl +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env julia - -@info "Verifying PackageCompiler is installed globally" -using Pkg; Pkg.activate(); Pkg.add("PackageCompiler") -using PackageCompiler - -@info "Activating sysimage environment" -Pkg.activate(@__DIR__) - -@info "Creating the sysimage. This may take a while..." -sysimg="CatColabInterop.so" -create_sysimage(["CatColabInterop"], sysimage_path=sysimg, - precompile_execution_file="sysimage_precompile.jl") -sysimg_path=joinpath(@__DIR__, sysimg); - -@info "Adding $sysimg_path to IJulia kernel" -Pkg.activate(); Pkg.add("IJulia") -using IJulia -Pkg.build("IJulia") - -installkernel("Julia CatColab Interop", "--project=@.", "--sysimage=$sysimg_path") - -@info "Done!" -exit() diff --git a/packages/algjulia-interop/scripts/endpoint.jl b/packages/algjulia-interop/scripts/endpoint.jl new file mode 100644 index 000000000..115a0e018 --- /dev/null +++ b/packages/algjulia-interop/scripts/endpoint.jl @@ -0,0 +1,50 @@ + +# Example usage: + +# julia --project=my_alg_julia_env --threads 4 endpoint.jl Catlab AlgebraicPetri + +# Where my_alg_julia_env is a Julia environment with CatColabInterop, Oxygen, +# HTTP, and any AlgJulia dependencies. + +using CatColabInterop +using Oxygen +using HTTP + +const CORS_HEADERS = [ + "Access-Control-Allow-Origin" => "*", + "Access-Control-Allow-Headers" => "*", + "Access-Control-Allow-Methods" => "POST, GET, OPTIONS" +] + +function CorsHandler(handle) + return function (req::HTTP.Request) + # return headers on OPTIONS request + if HTTP.method(req) == "OPTIONS" + return HTTP.Response(200, CORS_HEADERS) + else + r = handle(req) + r.headers = CORS_HEADERS + r + end + end +end + +defaults = [:Catlab,:ACSets] # all extensions to date + +# Dynamically load packages in command lin eargs +for pkg in (isempty(ARGS) ? defaults : ARGS ) + @info "using $pkg" + @eval using $pkg +end + +for m in methods(CatColabInterop.endpoint) + sig = m.sig.parameters + (length(sig)==2 && sig[2].instance isa Val) || error("Unexpected signature $sig") + name = only(sig[2].parameters) + @info "Loading endpoint $name" + name isa Symbol || error("Unexpected endpoint name $name") + fntype, argtypes... = m.sig.types + invoke(fntype.instance, Tuple{argtypes...}, Val(name)) +end + +serve(middleware=[CorsHandler]) diff --git a/packages/algjulia-interop/src/CatColabInterop.jl b/packages/algjulia-interop/src/CatColabInterop.jl index a0b0d2320..18bd4b81a 100644 --- a/packages/algjulia-interop/src/CatColabInterop.jl +++ b/packages/algjulia-interop/src/CatColabInterop.jl @@ -1,86 +1,15 @@ module CatColabInterop -using MLStyle -using Reexport - -# this code tracks integrations and allows for basic theory/model-building code to dispatch from it. -# the intent is that this is an interface for AlgebraicJulia code to interoperate with CatColab -abstract type AlgebraicJuliaIntegration end - -# cells in the JSON are tagged. these are just objects for dispatching `to_model` -@data ModelElementTag begin - ObTag() - HomTag() -end -export ObTag, HomTag - -#= -@active patterns are MLStyle-implementations of F# active patterns that forces us to work in the Maybe/Option pattern. -Practically, yet while a matter of opinion, they make @match statements cleaner; a statement amounts to a helpful pattern -name and the variables we intend to capture. -=# -@active IsObject(x) begin; x[:content][:tag] == "object" ? Some(x[:content]) : nothing end -@active IsMorphism(x) begin; x[:content][:tag] == "morphism" ? Some(x[:content]) : nothing end -export IsObject, IsMorphism - -# Obs, Homs -@data ModelElementValue begin - ObValue() - HomValue(dom,cod) -end -export ObValue, HomValue - -""" -Struct capturing the name of the object and its relevant information. -ModelElementValue may be objects or homs, each of which has different data. -""" -struct ModelElement - name::Union{Symbol, Nothing} - val::Union{<:ModelElementValue, Nothing} - function ModelElement(;name::Symbol=nothing,val::Any=nothing) - new(name, val) - end -end -export ModelElement - -Base.nameof(t::ModelElement) = t.name +export endpoint -""" Struct wrapping a dictionary """ -struct Model{T<:AlgebraicJuliaIntegration} - data::Dict{String, ModelElement} -end -export Model - -function Model(::T) where T<:AlgebraicJuliaIntegration - Model{T}(Dict{String, ModelElement}()) -end - -Base.values(model::Model) = values(model.data) +using Reexport """ -Functions to build a dictionary associating ids in the theory to elements in the model +Extend this method with endpoint(::Val{my_analysis_name}) in extension packages. """ -function to_model end -export to_model - - -# TODO supposes bijection between theories, models, diagrams, etc. -abstract type AbstractDiagram{T<:AlgebraicJuliaIntegration} end - -abstract type AbstractAnalysis{T<:AlgebraicJuliaIntegration} end - -struct ImplError <: Exception - name::String -end -export ImplError - -Base.showerror(io::IO, e::ImplError) = print(io, "$(e.name) not implemented") - -include("result.jl") -include("kernel_management.jl") -include("kernel_support.jl") -include("decapodes-service/DecapodesService.jl") +function endpoint end -@reexport using .DecapodesService +include("Types.jl") +@reexport using .Types -end +end # module diff --git a/packages/algjulia-interop/src/Types.jl b/packages/algjulia-interop/src/Types.jl new file mode 100644 index 000000000..5d61abe8b --- /dev/null +++ b/packages/algjulia-interop/src/Types.jl @@ -0,0 +1,74 @@ +# TODO make this automatically generated by CatColab +""" Common types useful for deserializing CatColab JSON payloads """ +module Types + +export ObType, MorType, DiagramObGenerator, DiagramMorGenerator, ObGenerator, + MorGenerator, Diagram, Model, ModelDiagram + +using StructTypes + +struct ObType + tag::String + content::String +end +StructTypes.StructType(::Type{ObType}) = StructTypes.Struct() + +struct MorType + tag::String + content::Union{String,ObType} +end +StructTypes.StructType(::Type{MorType}) = StructTypes.Struct() + +struct DiagramObGenerator + id::String + label::Vector{String} + obType::ObType + over::ObType +end +StructTypes.StructType(::Type{DiagramObGenerator}) = StructTypes.Struct() + +struct DiagramMorGenerator + id::String + morType::MorType + over::ObType + dom::ObType + cod::ObType +end +StructTypes.StructType(::Type{DiagramMorGenerator}) = StructTypes.Struct() + +struct ObGenerator + id::String + label::Vector{String} + obType::ObType +end +StructTypes.StructType(::Type{ObGenerator}) = StructTypes.Struct() + +struct MorGenerator + id::String + label::Vector{String} + morType::MorType + dom::ObType + cod::ObType +end +StructTypes.StructType(::Type{MorGenerator}) = StructTypes.Struct() + +struct Diagram + obGenerators::Vector{DiagramObGenerator} + morGenerators::Vector{DiagramMorGenerator} +end +StructTypes.StructType(::Type{Diagram}) = StructTypes.Struct() + +struct Model + obGenerators::Vector{ObGenerator} + morGenerators::Vector{MorGenerator} +end +StructTypes.StructType(::Type{Model}) = StructTypes.Struct() + + +struct ModelDiagram + model::Model + diagram::Diagram +end +StructTypes.StructType(::Type{ModelDiagram}) = StructTypes.Struct() + +end # module diff --git a/packages/algjulia-interop/src/decapodes-service/DecapodesService.jl b/packages/algjulia-interop/src/decapodes-service/DecapodesService.jl deleted file mode 100644 index 1539cbbfb..000000000 --- a/packages/algjulia-interop/src/decapodes-service/DecapodesService.jl +++ /dev/null @@ -1,42 +0,0 @@ -module DecapodesService - -# algebraicjulia dependencies -using ACSets -using DiagrammaticEquations -using Decapodes -using CombinatorialSpaces - -# dependencies -import JSON3 -using StaticArrays -using MLStyle -using LinearAlgebra -using ComponentArrays -using Distributions # for initial conditions - -# meshing -using CoordRefSystems -using GeometryBasics: Point2, Point3 -Point3D = Point3{Float64}; - -# simulation -using OrdinaryDiffEq - -using ..CatColabInterop -using ..CatColabInterop: AlgebraicJuliaIntegration, AbstractDiagram, AbstractAnalysis -import ..CatColabInterop: Model, to_model - -# necessary to export -export infer_types!, evalsim, default_dec_generate, default_dec_matrix_generate, - DiagonalHodge, ComponentArray - -struct ThDecapode <: AlgebraicJuliaIntegration end -export ThDecapode - -# funcitons for geometry and initial conditions -include("geometry.jl") -include("model.jl") ## model-building -include("diagram.jl") ## diagram-building -include("analysis/Analysis.jl") - -end diff --git a/packages/algjulia-interop/src/decapodes-service/analysis/Analysis.jl b/packages/algjulia-interop/src/decapodes-service/analysis/Analysis.jl deleted file mode 100644 index af3f267a3..000000000 --- a/packages/algjulia-interop/src/decapodes-service/analysis/Analysis.jl +++ /dev/null @@ -1,3 +0,0 @@ -include("ns_helper.jl") -include("initial_conditions.jl") -include("simulation.jl") diff --git a/packages/algjulia-interop/src/decapodes-service/analysis/initial_conditions.jl b/packages/algjulia-interop/src/decapodes-service/analysis/initial_conditions.jl deleted file mode 100644 index 29ce151f6..000000000 --- a/packages/algjulia-interop/src/decapodes-service/analysis/initial_conditions.jl +++ /dev/null @@ -1,101 +0,0 @@ -## INITIAL CONDITIONS - -# This ADT defines the parameters for initial conditions data. -@data InitialConditionsData begin - GaussianData(μ::Vector{Float64}, Σ::Diagonal{Float64, Vector{Float64}}) - TaylorVortexData(lat::Float64, vortices::Int, p::AbstractVortexParams) -end - -function GaussianData(μ::Vector{Float64}, Σ::Vector{Float64}) - GaussianData(μ, LinearAlgebra.Diagonal(abs.(Σ))) -end - -# default method -function GaussianData(r::Rectangle) - μ = middle(r) - GaussianData(μ, μ/10) -end - -""" Normal distribution should understand GaussianData """ -Distributions.MvNormal(ξ::GaussianData) = MvNormal(ξ.μ, ξ.Σ) - -TaylorVortexData() = TaylorVortexData(0.2, 2, TaylorVortexParams(0.5, 0.1)) - -#= -This IC contains the domain and the initial conditions data. - -While these are currently tightly-interlinked with InitialConditionsData, they are formally separated to distinguish between the initial conditions schema and the data it might be parameterized over. -=# -@data InitialConditions begin - # planar - GaussianIC(r::Rectangle, ξ::GaussianData) - # spherical - TaylorVortexIC(d::Sphere, ξ::TaylorVortexData) - SixVortexIC(m::Sphere, data::Any) -end - -# DEFAULT METHOD -GaussianIC(r::Rectangle) = GaussianIC(r, GaussianData(r)) -TaylorVortexIC(d::Sphere) = TaylorVortexIC(d, TaylorVortexData()) - -function initial_conditions(ic_specs::AbstractDict, geometry::Geometry, uuid2symb::Dict{String, Symbol}) - dict = Dict([uuid2symb[string(uuid)] => ic_specs[string(uuid)] for uuid ∈ keys(ic_specs)]...) - initial_conditions(dict, geometry) # the resulting sim will only have (C,) as initial conditions -end - -""" Takes a string, a domain, and a mesh and returns the initial conditios object associated to it. - -Example: -``` -associate("TaylorVortex", Sphere(6, 1.0), sd) == TaylorVortexIC(Sphere(6, 1.0), sd) -``` -""" -function associate(str::String, geometry::Geometry) - @match str begin - "Gaussian" => GaussianIC(geometry.domain) - "TaylorVortex" => TaylorVortexIC(geometry.domain) - _ => error("$str is not implemented") - end -end - -""" Methods for this function implement initial conditions for their given schema. There are also helper functions.""" -function initial_conditions end -export initial_conditions - -""" associates the values in a dictionary to their initial condition flags, and passes the output to initial_conditions -""" -function initial_conditions(ics::Dict{Symbol, String}, geometry::Geometry) - ic_dict = Dict([var => associate(ics[var], geometry) for var in keys(ics)]...) - # Now we have a mapping between variables and their initial condition specs. - initial_conditions(ic_dict, geometry) -end - -""" builds a mapping between symbols and their initial conditions """ -function initial_conditions(ics::Dict{Symbol,<:InitialConditions}, geometry::Geometry) - u0 = ComponentArray(; Dict([ - var => initial_conditions(ics[var], geometry) for var ∈ keys(ics) - ])...) - return u0 -end - -function initial_conditions(ics::GaussianIC, geometry::Geometry) - c_dist = MvNormal(ics.ξ) - c = [pdf(c_dist, [p[1], p[2]]) for p ∈ geometry.dualmesh[:point]] - return c -end - -function vort_ring(ics::TaylorVortexIC, geometry::Geometry) - vort_ring(ics.d, ics.ξ.lat, ics.ξ.vortices, ics.ξ.p, geometry.dualmesh, taylor_vortex) -end - -function initial_conditions(ics::TaylorVortexIC, geometry::Geometry) - # TODO prefer not to load `s0` here but che sara sara - s0 = dec_hodge_star(0, geometry.dualmesh, GeometricHodge()) - X = vort_ring(ics, geometry) - du = s0 * X - return du -end - -function initial_conditions(ics::SixVortexIC, geometry::Geometry) - X = vort_ring(0.4, 6, PointVortexParams(3.0, 0.15), point_vortex) -end diff --git a/packages/algjulia-interop/src/decapodes-service/analysis/ns_helper.jl b/packages/algjulia-interop/src/decapodes-service/analysis/ns_helper.jl deleted file mode 100644 index b74e579a0..000000000 --- a/packages/algjulia-interop/src/decapodes-service/analysis/ns_helper.jl +++ /dev/null @@ -1,87 +0,0 @@ -### -#This code was lifted from the Navier-Stokes simulation `ns.jl` in the Decapodes docs page, originally authored by Luke Morris -### -abstract type AbstractVortexParams end - -struct TaylorVortexParams <: AbstractVortexParams - G::Real - a::Real -end - -struct PointVortexParams <: AbstractVortexParams - τ::Real - a::Real -end - -""" function ring_centers(lat, n) - -Find n equispaced points at the given latitude. -""" -function ring_centers(lat, n, radius=1.0) - ϕs = range(0.0, 2π; length=n+1)[1:n] - map(ϕs) do ϕ - v_sph = Spherical(radius, lat, ϕ) - v_crt = convert(Cartesian, v_sph) - Point3D(v_crt.x.val, v_crt.y.val, v_crt.z.val) - end -end - -""" function great_circle_dist(pnt,G,a,cntr) - -Compute the length of the shortest path along a sphere, given Cartesian coordinates. -""" -function great_circle_dist(radius::Float64, pnt1::Point3D, pnt2::Point3D) - radius * acos(dot(pnt1,pnt2)) -end - -function taylor_vortex(sd::HasDeltaSet, radius::Float64, cntr::Point3D, p::TaylorVortexParams) - map(x -> taylor_vortex(x, radius, cntr, p), point(sd)) -end - -""" function taylor_vortex(pnt::Point3D, cntr::Point3D, p::TaylorVortexParams) - -Compute the value of a Taylor vortex at the given point. -""" -function taylor_vortex(pnt::Point3D, radius::Float64, cntr::Point3D, p::TaylorVortexParams) - gcd = great_circle_dist(radius, pnt, cntr) - (p.G/p.a) * (2 - (gcd/p.a)^2) * exp(0.5 * (1 - (gcd/p.a)^2)) -end - -""" function vort_ring(lat, n_vorts, p::T, formula) where {T<:AbstractVortexParams} - -Compute vorticity as primal 0-forms for a ring of vortices. - -Specify the latitude, number of vortices, and a formula for computing vortex strength centered at a point. -""" -function vort_ring(d::Sphere, lat, n_vorts, p::T, sd, formula) where {T<:AbstractVortexParams} - sum(map(x -> formula(sd, d.radius, x, p), ring_centers(lat, n_vorts, d.radius))) -end - -""" function vort_ring(lat, n_vorts, p::PointVortexParams, formula) - -Compute vorticity as primal 0-forms for a ring of vortices. - -Specify the latitude, number of vortices, and a formula for computing vortex strength centered at a point. - -Additionally, place a counter-balance vortex at the South Pole such that the integral of vorticity is 0. -""" -function vort_ring(radius, lat, n_vorts, p::PointVortexParams, formula) - Xs = sum(map(x -> formula(radius, sd, x, p), ring_centers(lat, n_vorts))) - Xsp = point_vortex(sd, Point3D(0.0, 0.0, -1.0), PointVortexParams(-1*n_vorts*p.τ, p.a)) - Xs + Xsp -end - - - - - - -""" function point_vortex(pnt::Point3D, cntr::Point3D, p::PointVortexParams) - -Compute the value of a smoothed point vortex at the given point. -""" -function point_vortex(pnt::Point3D, cntr::Point3D, p::PointVortexParams) - gcd = great_circle_dist(pnt,cntr) - p.τ / (cosh(3gcd/p.a)^2) -end - diff --git a/packages/algjulia-interop/src/decapodes-service/analysis/simulation.jl b/packages/algjulia-interop/src/decapodes-service/analysis/simulation.jl deleted file mode 100644 index 044a261d8..000000000 --- a/packages/algjulia-interop/src/decapodes-service/analysis/simulation.jl +++ /dev/null @@ -1,161 +0,0 @@ -""" Constructs an analysis from the diagram of a Decapode Model""" -function Analysis(analysis::JSON3.Object, diagram::DecapodeDiagram, hodge=GeometricHodge()) - - # TODO want a safer way to get this information - id = findfirst(cell -> haskey(cell, :content), analysis[:notebook][:cells]) - content = analysis[:notebook][:cells][id][:content][:content] - - PodeSystem(content, diagram, hodge) -end -export Analysis - -# accepts payload -function Analysis(::ThDecapode, payload::String, args...) - analysis = JSON3.read(payload) - Analysis(ThDecapode(), analysis) -end - -function Analysis(::ThDecapode, analysis::JSON3.Object, args...) - model = Model(ThDecapode(), analysis.model) - diagram = Diagram(analysis.diagram, model) - PodeSystem(analysis, diagram, args...) -end - -struct PodeSystem <: AbstractAnalysis{ThDecapode} - pode::SummationDecapode - plotVars::Dict{String, Bool} - scalars::Dict{Symbol, Any} # closures - geometry::Geometry - init::ComponentArray - generate::Any - uuiddict::Dict{Symbol, String} - duration::Int -end -export PodeSystem - -function Base.show(io::IO, system::PodeSystem) - println(io, system.pode) -end - -# the origin is the SimulationData payload -function PodeSystem(content::JSON3.Object, diagram::DecapodeDiagram, hodge=GeometricHodge()) - - domain = content[:domain] - duration = content[:duration] - initialConditions = content[:initialConditions] - mesh = content[:mesh] - # TODO we need a more principled way of defining this - plotVars = @match content[:plotVariables] begin - vars::AbstractArray => Dict{String, Bool}([ k => k ∈ vars for k in keys(diagram.vars)]) - vars => Dict{String, Bool}([ "$k" => v for (k,v) in vars]) - end - scalars = content[:scalars] - anons = Dict{Symbol, Any}() - - dot_rename!(diagram.pode) - uuid2symb = uuid_to_symb(diagram.pode, diagram.vars) - - geometry = Geometry(content) - - ♭♯_m = ♭♯_mat(geometry.dualmesh) - wedge_dp10 = dec_wedge_product_dp(Tuple{1,0}, geometry.dualmesh) - dual_d1_m = dec_dual_derivative(1, geometry.dualmesh) - star0_inv_m = dec_inv_hodge_star(0, geometry.dualmesh, hodge) - Δ0 = Δ(0,geometry.dualmesh) - #fΔ0 = factorize(Δ0); - function sys_generate(s, my_symbol) - op = @match my_symbol begin - sym && if haskey(diagram.scalars, sym) end => x -> begin - k = scalars[diagram.scalars[sym]] - k * x - end - :♭♯ => x -> ♭♯_m * x - # TODO are we indexing right? - :dpsw => x -> wedge_dp10(x, star0_inv_m*(dual_d1_m*x)) - :Δ⁻¹ => x -> begin - y = Δ0 \ x - y .- minimum(y) - end - _ => default_dec_matrix_generate(s, my_symbol, hodge) - end - return (args...) -> op(args...) - end - - u0 = initial_conditions(initialConditions, geometry, uuid2symb) - - # reversing `uuid2symb` into `symbol => uuid.` we need this to reassociate the var to its UUID - symb2uuid = Dict([v => k for (k,v) in pairs(uuid2symb)]) - - # TODO return the whole system - return PodeSystem(diagram.pode, plotVars, anons, geometry, u0, sys_generate, symb2uuid, duration) -end - -points(system::PodeSystem) = collect(values(system.geometry.dualmesh.subparts.point.m)) -indexing_bounds(system::PodeSystem) = indexing_bounds(system.geometry.domain) - -function run_sim(fm, u0, t0, constparam) - prob = ODEProblem(fm, u0, (0, t0), constparam) - soln = solve(prob, Tsit5(), saveat=0.01) -end -export run_sim - -struct SimResult - time::Vector{Float64} - state::Dict{String, Vector{AbstractArray{SVector{3, Float64}}}} - x::Vector{Float64} # axis - y::Vector{Float64} -end -export SimResult - -function SimResult(soln::ODESolution, system::PodeSystem) - idx_bounds = indexing_bounds(system) - state_val_dict = variables_state(soln, system) # Dict("UUID1" => VectorMatrixSVectr...) - SimResult(soln.t, state_val_dict, 0:idx_bounds.x, 0:idx_bounds.y) -end -# TODO generalize to HasDeltaSet - -""" for the variables in a system, associate them to their state values over the duration of the simulation """ -function variables_state(soln::ODESolution, system::PodeSystem) - plottedVars = [ k for (k, v) in system.plotVars if v == true ] - uuid2symb = Dict([ v => k for (k, v) in system.uuiddict]) # TODO why reverse again? - Dict([ String(uuid2symb[var]) => state_entire_sim(soln, system, uuid2symb[var]) for var ∈ plottedVars ]) -end - -""" given a simulation, a domain, and a variable, gets the state values over the duration of a simulation. -Called by `variables_state`[@ref] """ -function state_entire_sim(soln::ODESolution, system::PodeSystem, var::Symbol) - map(1:length(soln.t)) do i - state_at_time(soln, system, var, i) - end -end - -# TODO type `points` -function state_at_time(soln::ODESolution, system::PodeSystem, plotvar::Symbol, t::Int) - @match system.geometry.domain begin - # TODO check time indexing here - domain::Rectangle => state_at_time(soln, domain, plotvar, t) - domain::Sphere => state_at_time(soln, domain, plotvar, t, points(system)) - _ => throw(ImplError("state_at_time function for domain $domain")) - end -end - -function state_at_time(soln::ODESolution, domain::Rectangle, var::Symbol, t::Int) - (x, y) = indexing_bounds(domain) - [SVector(i, j, getproperty(soln.u[t], var)[(x+1)*(i-1) + j]) for i in 1:x+1, j in 1:y+1] -end - -# TODO just separated this from the SimResult function and added type parameters, but need to generalize -function grid(pt3::Point3, grid_size::Vector{Int}) - pt2 = [(pt3[1]+1)/2, (pt3[2]+1)/2] - [round(Int, pt2[1]*grid_size[1]), round(Int, pt2[2]*grid_size[2])] -end - -function state_at_time(soln::ODESolution, domain::Sphere, var::Symbol, t::Int, points) - l , _ = indexing_bounds(domain) # TODO this is hardcoded to return 100, 100 - northern_indices = filter(i -> points[i][3] > 0, keys(points)) - map(northern_indices) do n - i, j = grid(points[n], [l, l]) # TODO - SVector(i, j, getproperty(soln.u[t], var)[n]) - end -end - diff --git a/packages/algjulia-interop/src/decapodes-service/diagram.jl b/packages/algjulia-interop/src/decapodes-service/diagram.jl deleted file mode 100644 index fee454d4e..000000000 --- a/packages/algjulia-interop/src/decapodes-service/diagram.jl +++ /dev/null @@ -1,113 +0,0 @@ -## DIAGRAM BUILDING - - -@kwdef mutable struct DecapodeDiagram <: AbstractDiagram{ThDecapode} - pode::SummationDecapode = SummationDecapode(parse_decapode(quote end)) - scalars::Dict{Symbol, String} = Dict{Symbol, String}() - vars::Dict{String, Int} = Dict{String, Int}() - nc::Dict{Int, String} = Dict{Int, String}() -end - -function Base.nameof(model::Model, content::AbstractDict) - if isnothing(content[:over]) - :no_name - else - Symbol(model.data[content[:over][:content]].name) - end -end - -# endpoint being `dom` or `codom` -function check_endpoint!(diagram::DecapodeDiagram, endpoint) - if haskey(diagram.vars, endpoint) - diagram.vars[endpoint] - else - if endpoint ∉ values(diagram.nc) - id = isempty(keys(diagram.nc)) ? 1 : length(keys(diagram.nc)) + 1 - name = Symbol("•$id") - acset_id = add_part!(diagram.pode, :Var, name=name, type=:infer) - push!(diagram.nc, acset_id => endpoint) - acset_id - else - out = filter(x -> x[2] == endpoint, pairs(diagram.nc)) - first(keys(out)) - end - end -end - -function add_to_pode!(diagram::DecapodeDiagram, - model::Any, - content::AbstractDict, - ::ObTag) - # indexes the model by UUID - model_element = model.data[content[:over][:content]] - # checks if the cell is an anonymous (intermediate) variable. - # if so, we increment the intermediate variable counter and make an intermediate variable name. - # otherwise we use the existing name of the given content. - name = if isempty(content[:name]) - id = isempty(keys(diagram.nc)) ? 1 : maximum(keys(diagram.nc)) + 1 - push!(diagram.nc, id => "") - Symbol("•$id") - else - Symbol(content[:name]) - end - id = add_part!(diagram.pode, :Var, name=name, type=nameof(model_element)) - push!(diagram.vars, content[:id] => id) - return diagram -end -export add_to_pode! - -# TODO we are restricted to Op1 -function add_to_pode!(diagram::DecapodeDiagram, - model::Model{ThDecapode}, - content::AbstractDict, - ::HomTag) - dom = content[:dom][:content] - cod = content[:cod][:content] - - # TODO Simpler to extend the Decapodes Var table by a UUID attribute - dom_id = check_endpoint!(diagram, dom) - cod_id = check_endpoint!(diagram, cod) - - # get the name of the Op1 and add it to the model - op1 = nameof(model, content) - - add_part!(diagram.pode, :Op1, src=dom_id, tgt=cod_id, op1=op1) - # we need to add an inclusion to the TVar table - if op1 == :∂ₜ - add_part!(diagram.pode, :TVar, incl=cod_id) - end - if content[:morType][:content] isa JSON3.Object - scalar = model.data[content[:over][:content]].name - push!(diagram.scalars, scalar => content[:over][:content]) - end - diagram -end - -""" Diagram(diagram::AbstractVector{<:AbstractDict}, model::Model{ThDecapode}) => (::SummationDecapode, ::Dict{Symbol, Any}, ::Dict{String, Int}) - -This returns - 1. a Decapode - 2. a dictionary of symbols mapped to anonymous functions - 3. a dictionary of JSON UUIDs mapped to symbols -""" -function Diagram(json_array::JSON3.Array{T}, model::Model{ThDecapode}; scalars=[]) where T - diagram = DecapodeDiagram() - for cell in json_array - cell = haskey(cell, :content) ? cell[:content] : cell - @match cell begin - content && if haskey(content, :obType) end => add_to_pode!(diagram, model, content, ObTag()) - content && if haskey(content, :morType) end => add_to_pode!(diagram, model, content, HomTag()) - _ => throw(ImplError(cell)) - end - end - return diagram -end -export Diagram - -function Diagram(json_diagram::JSON3.Object, model::Model{ThDecapode}; scalars=[]) - Diagram(json_diagram[:cells], model; scalars) -end - -function uuid_to_symb(decapode::SummationDecapode, vars::Dict{String, Int}) - Dict([key => (subpart(decapode, vars[key], :name)) for key ∈ keys(vars)]) -end diff --git a/packages/algjulia-interop/src/decapodes-service/geometry.jl b/packages/algjulia-interop/src/decapodes-service/geometry.jl deleted file mode 100644 index addb0201c..000000000 --- a/packages/algjulia-interop/src/decapodes-service/geometry.jl +++ /dev/null @@ -1,120 +0,0 @@ -## INTEROP - -""" Supported domains. """ -const domain_names = [:Plane, :Sphere] - -""" Mapping from supported domains to meshes for the domain. """ -const mesh_names = Dict( - :Plane => [:Rectangle, :Periodic], - :Sphere => [:Icosphere6, :Icosphere7, :Icosphere8, :UV], -) - -""" Mapping from supported domains to initial/boundary conditions. """ -const initial_condition_names = Dict( - :Plane => [:Gaussian], - :Sphere => [:TaylorVortex, :SixVortex], -) - -""" Supported geometries, in the JSON format expected by the frontend. """ -function supported_decapodes_geometries() - domains = map(domain_names) do domain - Dict( - :name => domain, - :meshes => mesh_names[domain], - :initialConditions => initial_condition_names[domain], - ) - end - Dict(:domains => domains) -end -export supported_decapodes_geometries - -## DOMAINS - -abstract type Domain end - -# meshes associated with Planes -@data Planar <: Domain begin - Rectangle(max_x::Int, max_y::Int, dx::Float64, dy::Float64) - Periodic # TODO -end - -# rectangle methods - -# TODO it is semantically better to case to Point2? -middle(r::Rectangle) = [r.max_x/2, r.max_y/2] - -function indexing_bounds(r::Rectangle) - (x=floor(Int, r.max_x/r.dx), y=floor(Int, r.max_y/r.dy)) -end - -# meshes associated with Spheres -@data Spheric <: Domain begin - Sphere(dim::Int, radius::Float64) - UV(minlat::Int, maxlat::Int, dlat::Float64, minlong::Int, maxlong::Int, dlong::Float64, radius::Float64) -end - -# default -Sphere(dim) = Sphere(dim, 1.0) - -# TODO XXX hardcoded alert! -function indexing_bounds(m::Sphere) - (x=100, y=100) -end - -""" helper function for UV """ -function makeSphere(m::UV) - makeSphere(m.minlat, m.maxlat, m.dlat, m.minlong, m.maxlong, m.dlong, m.radius) -end - -## GEOMETRY - -struct Geometry - domain::Domain - dualmesh::HasDeltaSet -end - -function Base.show(io::IO, g::Geometry) - println(io, g.domain) -end - -function Geometry(json_object::AbstractDict) - mesh_name = Symbol(json_object[:mesh]) - domain = PREDEFINED_MESHES[mesh_name] - Geometry(domain) -end - -# function Geometry(d::Domain, args...) -# throw(ImplError("The mesh ($(d)) is")) -# end - -function Geometry(r::Rectangle, division::SimplexCenter=Circumcenter()) - s = triangulated_grid(r.max_x, r.max_y, r.dx, r.dy, Point2{Float64}) - sd = EmbeddedDeltaDualComplex2D{Bool, Float64, Point2{Float64}}(s) - subdivide_duals!(sd, division) - Geometry(r, sd) -end - -# function Geometry(r::Periodic, division::SimplexCenter=Circumcenter()) end - -function Geometry(m::Sphere, division::SimplexCenter=Circumcenter()) - s = loadmesh(Icosphere(m.dim, m.radius)) - sd = EmbeddedDeltaDualComplex2D{Bool, Float64, Point3{Float64}}(s) - subdivide_duals!(sd, division) - Geometry(m, sd) -end - -function Geometry(m::UV, division::SimplexCenter=Circumcenter()) - s, _, _ = makeSphere(m) - sd = EmbeddedDeltaDualComplex2D{Bool, Float64, Point3{Float64}}(s) - subdivide_duals!(sd, division) - Geometry(m, sd) -end - -## Prefined meshes - -const PREDEFINED_MESHES = Dict( - :Rectangle => Rectangle(100, 100, 2, 2), - :Icosphere6 => Sphere(6, 1.0), - :Icosphere7 => Sphere(7, 1.0), - :Icosphere8 => Sphere(8, 1.0), - :UV => UV(0, 180, 2.5, 0, 360, 2.5, 1.0)) diff --git a/packages/algjulia-interop/src/decapodes-service/model.jl b/packages/algjulia-interop/src/decapodes-service/model.jl deleted file mode 100644 index e1b4bb0c3..000000000 --- a/packages/algjulia-interop/src/decapodes-service/model.jl +++ /dev/null @@ -1,107 +0,0 @@ -# Build the model - -export Model - -""" -A model for the Decapodes integration is the same as the default Model method. -A dictionary mapping UUID strings with ModelElements is instantiated. -""" -Model(::ThDecapode) = Model{ThDecapode}(Dict{String, ModelElement}()) - -""" Helper function to convert CatColab values (Obs) in Decapodes """ -function to_model(model::ThDecapode, type::ObTag, name::String) - @match lowercase(name) begin - "0-form" => :Form0 - "1-form" => :Form1 - "2-form" => :Form2 - "primal 0-form" => :Form0 - "primal 1-form" => :Form1 - "primal 2-form" => :Form2 - "dual 0-form" => :DualForm0 - "dual 1-form" => :DualForm1 - "dual 2-form" => :DualForm2 - x => throw(ImplError(x)) - end -end - -""" Helper function to convert CatColab values (Homs) in Decapodes """ -function to_model(model::ThDecapode, type::HomTag, name::String) - @match replace(name," " => "") begin - "∂t" || "∂ₜ" => :∂ₜ - "Δ" => :Δ - "Δ⁻¹" => :Δ⁻¹ - "d*" || "d̃₁" => :dual_d₁ - "⋆" || "⋆₁" || "★₁" || "★1" => :⋆₁ - "⋆⁻¹" || "⋆₀⁻¹" => :⋆₀⁻¹ - "★" || "★⁻¹" => :⋆₁ - "d" || "d₀" || "d01" => :d₀ - "d12" => :d₁ - "⋆2" => :⋆₂ - "♭♯" => :♭♯ - "lamb" => :dpsw # dual-primal self-wedge - "-" => :neg - x => throw(ImplError(x)) - end -end - -# add_to_model! - -@active IsMorphismNonScalar(x) begin - x[:morType][:content] == "Nonscalar" ? Some(x) : nothing -end - -function add_to_model! end -export add_to_model! - -function add_to_model!(model::Model{ThDecapode}, content::AbstractDict, type::ObTag) - push!(model.data, content[:id] => ModelElement(;name=to_model(ThDecapode(), type, content[:name]))) -end - -function add_to_model!(model::Model{ThDecapode}, content::AbstractDict, type::HomTag) - @match content begin - IsMorphismNonScalar(x) => push!(model.data, content[:id] => - ModelElement(;name=to_model(ThDecapode(), type, content[:name]), - val=HomValue(content[:dom][:content], - content[:cod][:content]))) - _ => push!(model.data, content[:id] => - ModelElement(;name=Symbol(content[:name]), - val=HomValue(content[:dom][:content], - content[:cod][:content]))) - end -end - -# TODO generalize -function Model(::ThDecapode, path::String) - json = JSON3.read(read(path, String)) - Model(ThDecapode(), json) -end - -# for each cell, if it is... -# ...an object, we convert its type to a symbol and add it to the modeldict -# ...a morphism, we add it to the modeldict with a field for the ids of its -# domain and codomain to its -function Model(::ThDecapode, json_model::JSON3.Object) # AbstractDict is the JSON - newmodel = Model(ThDecapode()) - __name = json_model[:name] # TODO unused - for cell in json_model[:notebook][:cells] - @match cell begin - IsObject(content) => add_to_model!(newmodel, content, ObTag()) - IsMorphism(content) => add_to_model!(newmodel, content, HomTag()) - _ => throw(ImplError(cell)) - end - end - return newmodel -end -export Model - -function Model(::ThDecapode, json_array::JSON3.Array{T}; name="model") where T - newmodel = Model(ThDecapode()) - for cell in json_array - @match cell begin - content && if haskey(content, :obType) end => add_to_model!(newmodel, content, ObTag()) - content && if haskey(content, :morType) end => add_to_model!(newmodel, content, HomTag()) - _ => throw(ImplError(cell)) - end - end - return newmodel -end diff --git a/packages/algjulia-interop/src/kernel_management.jl b/packages/algjulia-interop/src/kernel_management.jl deleted file mode 100644 index c658ddb89..000000000 --- a/packages/algjulia-interop/src/kernel_management.jl +++ /dev/null @@ -1,256 +0,0 @@ -using IJulia -using Preferences -import REPL -using REPL.TerminalMenus -using MLStyle - -struct KernelNotFoundException <: Exception - dir::String -end - -KernelNotFoundException() = KernelNotFoundException(IJulia.kerneldir()) - -function Base.showerror(io::IO, err::KernelNotFoundException) - print(io, """ - IJulia cannot find any kernels in the directory `$(err.dir)`. - - To install a kernel, you may run `CatColabInterop.install_ccl_kernel()`. - Refer to the [IJulia documentation](https://julialang.github.io/IJulia.jl/stable/library/public/#IJulia.installkernel) - for more information about managing Jupyter kernels in IJulia. - - If you wish to install a sysimage instead, run - ```julia - using PackageCompiler - install_ccl_kernel(Val(:sysimge)) - ``` - """) -end - -const YESNO = ["Yes", "No"] - -const MODES = Dict("dev" => "http://localhost:5173", - "staging" => "https://next.catcolab.org", - "production" => "https://catcolab.org") - -@kwdef mutable struct ServerConfig - sysimg_path::Union{String, Nothing} = nothing - kernels::Vector{String} = readdir(IJulia.kerneldir(), join=true) - kernel::Union{String, Nothing} = @load_preference("kernel", nothing) - modes::Dict{String, String} = MODES - mode::String = @load_preference("mode", "production") - limit::Int = 1e9 - server::Union{Base.Process, Nothing} = nothing -end - -const CONFIG::ServerConfig = ServerConfig() -export CONFIG - -function origin(s::ServerConfig) - s.modes[s.mode] -end - -function Base.show(io::IO, config::ServerConfig) - kernel = !isnothing(config.kernel) ? config.kernel : "No kernel selected" - status = !isnothing(config.server) ? "Running" : "Not running." - s = """ - Current kernel: $kernel - Server: $status - Origin: $(origin(config)) - """ - print(io, s) -end - -function set_mode!(config::ServerConfig, mode::String) - if mode ∈ collect(keys(config.modes)) - config.mode = mode - @info """"$mode" set!""" - else - error("""Your selection "$mode" is not a valid mode. Please choose from $(join(config.modes, ", ", " or "))""") - end -end - -function change_mode!(prefer::Bool=true; config::ServerConfig=CONFIG) - modes = collect(keys(config.modes)) - menu = RadioMenu(modes, pagesize=3) - cursor = something(findfirst(==(config.mode), modes), 0) - choice = request("Select a mode: ", menu; cursor = cursor) - if choice != -1 - config.mode = modes[choice] - if prefer - @set_preferences!("mode" => modes[choice]) - @info "Preferred mode set to $(modes[choice])" - end - Ok("""Mode "$(config.mode)" chosen.""") - else - Err("Mode selection canceled") - end -end -export change_mode! - -function change_kernel!(prefer::Bool=true; config::ServerConfig=CONFIG) - menu = RadioMenu(config.kernels, pagesize=4) - cursor = something(findfirst(==(config.kernel), config.kernels), 0) - choice = request("Select a kernel: ", menu; cursor=cursor) - if choice != -1 - config.kernel = config.kernels[choice] - if prefer - @set_preferences!("kernel" => config.kernel) - @info "Preferred kernel set to $(config.kernels[choice])" - end - Ok("Kernel $(config.kernel) chosen.") - else - Err("Kernel selection canceled") - end -end -export change_kernel! - -""" load_kernels() - -Loads kernels visible to IJulia's [kernel_dir](@ref IJulia.kerneldir) function. -""" -function load_kernels!(;config::ServerConfig=CONFIG, warn=false) - dir = IJulia.kerneldir() - kernels = readdir(dir, join=true) - if !isempty(kernels) - config.kernels = kernels - return Ok("Kernels reloaded!") - end - # otherwise, throw a warning or an error - warn ? @warn(sprint(showerror, KernelNotFoundException(dir))) : throw(KernelNotFoundException(dir)) -end - -""" uninstall_kernel!(;config::ServerConfig=CONFIG)::Union{Nothing, Bool} - -Wraps `Base.rm` in a terminal menu interface to uninstall Julia kernels. Using `Base.rm` is recommended by IJulia. - -Usage: -``` -uninstall_kernel!() -``` -""" -function uninstall_kernel!(;config::ServerConfig=CONFIG) - isempty(config.kernels) && throw(KernelNotFoundException()) - menu = MultiSelectMenu(config.kernels, pagesize=4) - cursor = something(findfirst(==(config.kernel), config.kernels), 0) - choices = request("Select a kernel to be uninstalled: ", menu; cursor=cursor) - if !isempty(choices) - selections = getindex(config.kernels, collect(choices)) - confirm = RadioMenu(YESNO, pagesize=2) - permission = request("Kernel(s) will be uninstalled from your machine. Continue?", confirm) - if YESNO[permission] == "Yes" - for selection in selections - isdir(selection) && rm(selection; recursive=true) - @info selection isdir(selection) "Removed!" - end - preferred = @load_preference("kernel", nothing) - if preferred ∈ selections - @delete_preferences!("kernel") - @info "Preferred kernel $preferred was removed." - end - load_kernels!(;config=config, warn=true) - Ok() - else - Err("Kernel uninstallation cancelled.") - end - Ok("Kernel deletion successful.") - else - Err("Kernel uninstallation cancelled") - end -end -export uninstall_kernel! - - -""" install_ccl_kernel!() - -This calls IJulia to install a kernel `CatColabInteropKernel` in the current project directory. - -To build a sysimage, load the `SysImageExt` package extension by loading `PackageCompiler.jl`. This adds an additional method to `install_ccl_kernel!` which builds the sysimg. - -You can see installed kernels visible to IJulia by running `change_kernel!()`. - -Usage: - -For building an IJulia kernel -``` -using CatColabInterop -install_ccl_kernel!() -``` -For building the sysimg: -``` -using CatColabInterop -using PackageCompiler # loads Julia extension for building the sysimage -install_ccl_kernel!(Val(:sysimg)) -``` -""" -function install_ccl_kernel!(;config::ServerConfig=CONFIG, kwargs...) - kernel = installkernel("CatColabInteropKernel", "--project=@.", kwargs...) - load_kernels!(config=config) - preferred = @load_preference("kernel", nothing) - if isnothing(preferred) || length(config.kernels) == 1 - @set_preferences!("kernel" => kernel) - @info "Preferred kernel set to $(kernel)" - end -end -export install_ccl_kernel! - -function build_jupyter_server_cmd(args::Dict{String, Any}) - return ` - jupyter server \ - --IdentityProvider.token="" \ - --ServerApp.disable_check_xsrf=True \ - --ServerApp.allow_origin="$(args["mode"])" \ - --ServerApp.allow_credentials=True \ - --ServerApp.iopub_data_rate_limit=$(args["limit"]) \ - --MultiKernelManager.default_kernel_name="$(basename(args["kernel"]))" - ` -end - -function build_jupyter_server_cmd(config::ServerConfig) - build_jupyter_server_cmd(Dict{String, Any}("limit" => config.limit, "kernel" => config.kernel, "mode" => origin(config))) -end - -""" start_server(;config::ServerConfig=CONFIG, mode::Union{String, Nothing}=nothing, manual=false) - -This starts a Jupyter server with an optional kernel and mode. - -The **mode** is the origin for the Jupyter server. Eligible values are "dev", "staging", and "production". - -The available kernels can be checked by running `jupyter-server kernelspec list` from the command line or `;jupyter-server kernelspec list` from the REPL. - -## Usage: - -```julia -start_server!() -# do stuff -stop_server!() -``` -To select the kernel and mode in a wizard-like interface, -```julia -start_server!(;manual=true) -``` -""" -function start_server!(;config::ServerConfig=CONFIG, mode::Union{String, Nothing}=nothing, manual=false) - if manual - change_kernel!(;config=config) | Err("Start server process aborted because kernel selection was cancelled.") - change_mode!(;config=config) | Err("Start server process aborted because mode selection was cancelled.") - end - if isnothing(config.kernel) - change_kernel!(;config=config) - end - if !isnothing(mode) - set_mode!(config, mode) - end - cmd = build_jupyter_server_cmd(config) - @info "Starting server: - kernel: $(config.kernel) - mode: $(origin(config))" - config.server = open(pipeline(cmd)) -end -export start_server! - -function stop_server!(;config::ServerConfig=CONFIG) - if !isnothing(config.server) - kill(config.server, Base.SIGTERM) - end -end -export stop_server! diff --git a/packages/algjulia-interop/src/kernel_support.jl b/packages/algjulia-interop/src/kernel_support.jl deleted file mode 100644 index 15bfde4da..000000000 --- a/packages/algjulia-interop/src/kernel_support.jl +++ /dev/null @@ -1,32 +0,0 @@ -import JSON3 - -export JsonValue - -# NOTE: JsonValue should not be used for returning large amounts of data (Anything over 1kb? -# Whatever the size is for "trivially readable by humans"), there is a catastrophic performance -# dropoff as payload size increases. Performance of JsonValue vs -# display(MIME"application/json"(), JSON3.write()) has not been studied in detail, both have bad -# performance, but one might be worse than the other. Whether or not the performance is different might -# help inform a future investigation. -# -# NOTE: the use of the `show` methods is the only way I was able to get the contents of the message -# (`content["data"]?.["application/json"]`) to be interpreted as JSON in the browser. using something -# like `display(MIME"application/json"(), JSON3.write(...))` caused the -# content to be the JSON in string form, even though the mime type was "application/json" -# -# NOTE: It looks like IJulia is delivering payloads for each mime type available according to this -# docstring https://github.com/JuliaLang/IJulia.jl/blob/master/src/display.jl -# -# NOTE: Jason is not 100% confident that these show methods do what it looks like they're doing. -# -# NOTE: Sometime the Jupyter server needs to be restarted. Do not trust performance tests are run twice -# back to back right after server startup. - -""" Container for an arbitrary JSON value. """ -struct JsonValue - value::Any -end - -function Base.show(io::IO, ::MIME"application/json", json::JsonValue) - JSON3.write(io, json.value) -end diff --git a/packages/algjulia-interop/src/result.jl b/packages/algjulia-interop/src/result.jl deleted file mode 100644 index 1178e2dd9..000000000 --- a/packages/algjulia-interop/src/result.jl +++ /dev/null @@ -1,23 +0,0 @@ -struct ResultException <: Exception - msg::String -end - -Base.showerror(io::IO, err::ResultException) = print(io, err.msg) - -@data Result begin - Ok(msg::String) - Err(msg::String) -end - -Ok() = Ok("") - -Base.show(io::IO, ok::Ok) = !isempty(ok.msg) ? print(io, ok.msg) : nothing -Base.show(io::IO, err::Err) = !isempty(err.msg) ? print(io, err.msg) : nothing - -import Base: | - -(|)(left::Ok, right) = handle(left) -(|)(left::Err, right) = handle(right) - -handle(ok::Ok) = ok -handle(err::Err) = throw(ResultException(err.msg)) diff --git a/packages/algjulia-interop/sysimage_precompile.jl b/packages/algjulia-interop/sysimage_precompile.jl deleted file mode 100755 index 2fb9f0d7b..000000000 --- a/packages/algjulia-interop/sysimage_precompile.jl +++ /dev/null @@ -1,2 +0,0 @@ -import CatColabInterop -include(joinpath(pkgdir(CatColabInterop), "test", "runtests.jl")) diff --git a/packages/algjulia-interop/test/Project.toml b/packages/algjulia-interop/test/Project.toml index afd8e968a..84cb3f020 100644 --- a/packages/algjulia-interop/test/Project.toml +++ b/packages/algjulia-interop/test/Project.toml @@ -1,13 +1,8 @@ [deps] ACSets = "227ef7b5-1206-438b-ac65-934d6da304b8" CatColabInterop = "9ecda8fb-39ab-46a2-a496-7285fa6368c1" -CombinatorialSpaces = "b1c52339-7909-45ad-8b6a-6e388f7c67f2" -ComponentArrays = "b0b7db55-cfe3-40fc-9ded-d10e2dbeff66" -Decapodes = "679ab3ea-c928-4fe6-8d59-fd451142d391" -DiagrammaticEquations = "6f00c28b-6bed-4403-80fa-30e0dc12f317" +Catlab = "134e5e36-593f-5add-ad60-77f754baafbe" +HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" -LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" -MLStyle = "d8e11817-5142-5d16-987a-aa16d5891078" -OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" -StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" -Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +Oxygen = "df9a0d86-3283-4920-82dc-4555fc0d1d8b" +StructTypes = "856f2bd8-1eba-4b0a-8007-ebc267875bd4" diff --git a/packages/algjulia-interop/test/TestCatlab.jl b/packages/algjulia-interop/test/TestCatlab.jl new file mode 100644 index 000000000..eeaf86682 --- /dev/null +++ b/packages/algjulia-interop/test/TestCatlab.jl @@ -0,0 +1,54 @@ +module TestCatlab + +using CatColabInterop, Catlab +using Catlab.CategoricalAlgebra.Pointwise.FunctorialDataMigrations.Yoneda: + colimit_representables +using HTTP, Test, Oxygen, JSON3 +const CatlabExt = Base.get_extension(CatColabInterop, :CatlabExt) + +# Example JSON +#------------- +body = read((@__DIR__)*"/data/diagrams/acset.json", String) + +# Parse the JSON +#--------------- +p = JSON3.read(body, ModelDiagram) + +# Convert to ACSet +#----------------- +schema, names = CatlabExt.model_to_schema(p.model) +acset_type = AnonACSet( + schema; type_assignment=Dict(a=>Nothing for a in schema.attrtypes)) +y = yoneda(constructor(acset_type)) +data = CatlabExt.diagram_to_data(p.diagram, names) +names, res = colimit_representables(data, y) + +S = acset_schema(res) + +# This is what we expect +#------------------------ +expected = acset_type +add_part!.(Ref(expected), [:X,:Y,:Z]) +expected[1, :f] = 1 +expected[1, :g] = AttrVar(1) + +@test is_isomorphic(res, expected) + +# Test final JSON output +#----------------------- +expected_json = Dict(:Z => ["z"],:f => ["y"],:X => ["x"],:Y => ["y"],:g => ["z"]) +@test expected_json == CatlabExt.acset_to_json(res, schema, CatlabExt.make_names(res, names)) + +# Optionally test the endpoint if running endpoint.jl: +# resp = HTTP.post("http://127.0.0.1:8080/acsetcolim"; body) +# @test resp.status == 200 + +# Test make_names on a more complicated example +#---------------------------------------------- +@present SchThree(FreeSchema) begin (A,B,C)::Ob; f::Hom(A,B); g::Hom(B,C) end +@acset_type T(SchThree) +exT = @acset T begin A=2; B=3; C=3; f=[2,3]; g=[2,3,2] end +names = (z=(:C, 1), y= (:B, 1), x = (:A, 1), x2 = (:A, 2)) +@test CatlabExt.make_names(exT, names) == Dict(:A=>["x","x2"], :B=>["y","f(x)","f(x2)"], :C=>["z","g(y)","g(f(x))"]) + +end # module diff --git a/packages/algjulia-interop/test/data/diagrams/acset.json b/packages/algjulia-interop/test/data/diagrams/acset.json new file mode 100644 index 000000000..ff637da03 --- /dev/null +++ b/packages/algjulia-interop/test/data/diagrams/acset.json @@ -0,0 +1,166 @@ +{ + "model": { + "obGenerators": [ + { + "id": "019a6042-1241-77bd-8055-bfea5c206bc7", + "label": [ + "X" + ], + "obType": { + "tag": "Basic", + "content": "Entity" + } + }, + { + "id": "019a6042-1f1c-745e-bfea-753eeaccedf2", + "label": [ + "Y" + ], + "obType": { + "tag": "Basic", + "content": "Entity" + } + }, + { + "id": "019a60e3-1785-72b9-90d2-84dc8bdddc85", + "label": [ + "Z" + ], + "obType": { + "tag": "Basic", + "content": "AttrType" + } + } + ], + "morGenerators": [ + { + "id": "019a6042-2872-7654-a9b4-67becc9ef693", + "label": [ + "f" + ], + "morType": { + "tag": "Hom", + "content": { + "tag": "Basic", + "content": "Entity" + } + }, + "dom": { + "tag": "Basic", + "content": "019a6042-1241-77bd-8055-bfea5c206bc7" + }, + "cod": { + "tag": "Basic", + "content": "019a6042-1f1c-745e-bfea-753eeaccedf2" + } + }, + { + "id": "019a60e3-2ccf-74ef-a1e1-1c940564e1ca", + "label": [ + "g" + ], + "morType": { + "tag": "Basic", + "content": "Attr" + }, + "dom": { + "tag": "Basic", + "content": "019a6042-1241-77bd-8055-bfea5c206bc7" + }, + "cod": { + "tag": "Basic", + "content": "019a60e3-1785-72b9-90d2-84dc8bdddc85" + } + } + ] + }, + "diagram": { + "obGenerators": [ + { + "id": "019a6042-7531-77c7-83db-67018685b551", + "label": [ + "x" + ], + "obType": { + "tag": "Basic", + "content": "Entity" + }, + "over": { + "tag": "Basic", + "content": "019a6042-1241-77bd-8055-bfea5c206bc7" + } + }, + { + "id": "019a6042-88fb-73f5-bd90-9d337485793a", + "label": [ + "y" + ], + "obType": { + "tag": "Basic", + "content": "Entity" + }, + "over": { + "tag": "Basic", + "content": "019a6042-1f1c-745e-bfea-753eeaccedf2" + } + }, + { + "id": "019a60e3-5bdb-745c-acd5-6f341f56833a", + "label": [ + "z" + ], + "obType": { + "tag": "Basic", + "content": "AttrType" + }, + "over": { + "tag": "Basic", + "content": "019a60e3-1785-72b9-90d2-84dc8bdddc85" + } + } + ], + "morGenerators": [ + { + "id": "019a6042-98ab-7120-80b7-3223fa942e96", + "morType": { + "tag": "Hom", + "content": { + "tag": "Basic", + "content": "Entity" + } + }, + "over": { + "tag": "Basic", + "content": "019a6042-2872-7654-a9b4-67becc9ef693" + }, + "dom": { + "tag": "Basic", + "content": "019a6042-7531-77c7-83db-67018685b551" + }, + "cod": { + "tag": "Basic", + "content": "019a6042-88fb-73f5-bd90-9d337485793a" + } + }, + { + "id": "019a60e3-6dbf-74cf-8bd9-be0d073a4ee8", + "morType": { + "tag": "Basic", + "content": "Attr" + }, + "over": { + "tag": "Basic", + "content": "019a60e3-2ccf-74ef-a1e1-1c940564e1ca" + }, + "dom": { + "tag": "Basic", + "content": "019a6042-7531-77c7-83db-67018685b551" + }, + "cod": { + "tag": "Basic", + "content": "019a60e3-5bdb-745c-acd5-6f341f56833a" + } + } + ] + } +} \ No newline at end of file diff --git a/packages/algjulia-interop/test/runtests.jl b/packages/algjulia-interop/test/runtests.jl index 4688b379c..56ed0d76f 100644 --- a/packages/algjulia-interop/test/runtests.jl +++ b/packages/algjulia-interop/test/runtests.jl @@ -1,239 +1,5 @@ using Test -# -using CatColabInterop -using ACSets -using CombinatorialSpaces -using Decapodes -using DiagrammaticEquations -# -using MLStyle -using JSON3 -using ComponentArrays -using StaticArrays -using LinearAlgebra -import OrdinaryDiffEq: ReturnCode -const KEYS = Set([:mesh, :plotVariables, :initialConditions, :domain, :diagram, :model, :scalars, :duration]) - -@testset "Text-to-Pode" begin - @test to_model(ThDecapode(), ObTag(), "0-form") == :Form0 - @test to_model(ThDecapode(), ObTag(), "1-form") == :Form1 - @test to_model(ThDecapode(), ObTag(), "2-form") == :Form2 - @test to_model(ThDecapode(), ObTag(), "dual 0-form") == :DualForm0 - @test to_model(ThDecapode(), ObTag(), "dual 1-form") == :DualForm1 - @test to_model(ThDecapode(), ObTag(), "dual 2-form") == :DualForm2 - @test_throws CatColabInterop.ImplError to_model(ThDecapode(), ObTag(), "Form3") - @test to_model(ThDecapode(), HomTag(), "∂t") == :∂ₜ - @test to_model(ThDecapode(), HomTag(), "Δ") == :Δ - @test_throws CatColabInterop.ImplError to_model(ThDecapode(), HomTag(), "∧") -end - -modeljson = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "models", "model_dec.json"), "r") -model_dec = Model(ThDecapode(), modeljson) -@testset "Validating the JSON object" begin - # validate the JSON - @test keys(modeljson) == Set([:name, :notebook, :theory, :type]) - cells = modeljson[:notebook][:cells] - @test @match cells[1] begin - IsObject(_) => true - _ => false - end - @test @match cells[5] begin - IsMorphism(_) => true - _ => false - end - model = Model(ThDecapode()) - @match cells[1] begin - IsObject(content) => add_to_model!(model, content, ObTag()) - _ => nothing - end -end -@testset "Validate model" begin - # caveat: \star and \bigstar are different, but indistinguishable in some fonts - @test Set(nameof.(values(model_dec))) == Set([:DualForm1, :⋆₀⁻¹, :dual_d₁, :dpsw, :Form1, :neg, :⋆₁, :DualForm2, :Form0, :Δ⁻¹, :♭♯, :∂ₜ, :d₀]) -end - -# ## load diagram -diagram_json = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "diagrams", "inverse_laplacian", "diagram.json"), "r") -diagram = Diagram(diagram_json[:notebook], model_dec) -@testset "Diagram - Inverse Laplacian" begin - handcrafted_pode = SummationDecapode(parse_decapode(quote end)) - add_part!(handcrafted_pode, :Var, name=:A, type=:Form0) - add_part!(handcrafted_pode, :Var, name=:B, type=:Form0) - add_part!(handcrafted_pode, :Op1, src=1, tgt=2, op1=:Δ⁻¹) - @test diagram.pode == handcrafted_pode -end - -# TODO not specifying initial boundary conditions for `B` on the front-end -# means that it will be automatically specified -@testset "Analysis - Inverse Laplacian" begin - analysis_json = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "diagrams", "inverse_laplacian", "analysis.json"), "r") - system = Analysis(analysis_json, diagram) - simulator = evalsim(system.pode) - f = simulator(system.geometry.dualmesh, system.generate, DiagonalHodge()) - soln = run_sim(f, system.init, 50.0, ComponentArray(k=0.5,)) - @test soln.retcode == ReturnCode.Success - result = SimResult(soln, system) - @test typeof(result.state) == Dict{String, Vector{AbstractArray{SVector{3, Float64}}}} - jv = JsonValue(result) -end - -# ## load diagram -diagram_json = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "diagrams", "inverse_laplacian_longtrip", "diagram.json"), "r") -diagram = Diagram(diagram_json[:notebook], model_dec) -infer_types!(diagram.pode) -@testset "Diagram - Inverse Laplacian - Longtrip" begin - handcrafted_pode = SummationDecapode(parse_decapode(quote end)) - add_part!(handcrafted_pode, :Var, name=:u, type=:Form0) - add_part!(handcrafted_pode, :Var, name=:Δu, type=:Form0) - add_part!(handcrafted_pode, :Var, name=Symbol("•1"), type=:Form1) - add_part!(handcrafted_pode, :Var, name=Symbol("•2"), type=:DualForm1) - add_part!(handcrafted_pode, :Var, name=Symbol("•3"), type=:DualForm2) - add_part!(handcrafted_pode, :Op1, src=1, tgt=3, op1=:d₀) - add_part!(handcrafted_pode, :Op1, src=3, tgt=4, op1=:⋆₁) - add_part!(handcrafted_pode, :Op1, src=4, tgt=5, op1=:dual_d₁) - add_part!(handcrafted_pode, :Op1, src=5, tgt=2, op1=:⋆₀⁻¹) - add_part!(handcrafted_pode, :Op1, src=1, tgt=2, op1=:Δ⁻¹) - @test diagram.pode == handcrafted_pode -end -# TODO not specifying initial boundary conditions for `B` on the front-end means that it will be automatically specified -@testset "Analysis - Inverse Laplacian - Longtrip" begin - analysis_json = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "diagrams", "inverse_laplacian_longtrip", "analysis.json"), "r") - system = Analysis(analysis_json, diagram) - simulator = evalsim(system.pode) - f = simulator(system.geometry.dualmesh, system.generate, DiagonalHodge()) - soln = run_sim(f, system.init, 50.0, ComponentArray(k=0.5,)) - @test soln.retcode == ReturnCode.Success - result = SimResult(soln, system) - @test typeof(result.state) == Dict{String, Vector{AbstractArray{SVector{3, Float64}}}} - jv = JsonValue(result) -end - -# ## load diagram -diagram_json = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "diagrams", "ns_vort", "diagram.json"), "r") -diagram = Diagram(diagram_json[:notebook], model_dec) -infer_types!(diagram.pode) -@testset "Diagram - NS Vorticity" begin - # construct a decapode - handcrafted_pode = SummationDecapode(parse_decapode(quote end)) - add_part!(handcrafted_pode, :Var, name=:v, type=:DualForm1) - add_part!(handcrafted_pode, :Var, name=:dv, type=:DualForm2) - add_part!(handcrafted_pode, :Var, name=:ψ, type=:Form0) - # infer - add_part!(handcrafted_pode, :Var, name=Symbol("•1"), type=:Form0) - add_part!(handcrafted_pode, :Var, name=Symbol("•2"), type=:Form1) - add_part!(handcrafted_pode, :Var, name=Symbol("•3"), type=:infer) - add_part!(handcrafted_pode, :Var, name=Symbol("•4"), type=:infer) - add_part!(handcrafted_pode, :Var, name=Symbol("•5"), type=:infer) - add_part!(handcrafted_pode, :Var, name=Symbol("•6"), type=:infer) - add_part!(handcrafted_pode, :Var, name=Symbol("•7"), type=:infer) - # tvar - add_part!(handcrafted_pode, :TVar, incl=9) - # op1 - add_part!(handcrafted_pode, :Op1, src=2, tgt=4, op1=:⋆₀⁻¹) - add_part!(handcrafted_pode, :Op1, src=3, tgt=5, op1=:d₀) - add_part!(handcrafted_pode, :Op1, src=5, tgt=1, op1=:⋆₁) - add_part!(handcrafted_pode, :Op1, src=1, tgt=6, op1=:dpsw) # TODO breaks infer_types - add_part!(handcrafted_pode, :Op1, src=6, tgt=7, op1=:♭♯) - add_part!(handcrafted_pode, :Op1, src=7, tgt=8, op1=:⋆₁) - add_part!(handcrafted_pode, :Op1, src=2, tgt=9, op1=:∂ₜ) - add_part!(handcrafted_pode, :Op1, src=8, tgt=10, op1=:dual_d₁) - add_part!(handcrafted_pode, :Op1, src=10, tgt=9, op1=:neg) - infer_types!(handcrafted_pode) - @test diagram.pode == handcrafted_pode -end -# TODO not specifying initial boundary conditions for `B` on the front-end -# means that it will be automatically specified -@testset "Analysis - Navier-Stokes Vorticity" begin - analysis_json = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "diagrams", "ns_vort", "analysis.json"), "r") - system = Analysis(analysis_json, diagram) - simulator = evalsim(system.pode) - f = simulator(system.geometry.dualmesh, system.generate, DiagonalHodge()) - soln = run_sim(f, system.init, system.duration, ComponentArray(k=0.5,)) - @test soln.retcode == ReturnCode.Success - result = SimResult(soln, system) - @test typeof(result.state) == Dict{String, Vector{AbstractArray{SVector{3, Float64}}}} - jv = JsonValue(result) -end - -## load diagram -modeljson = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "models", "model_dec_scalar.json"), "r") -model_dec_scalar = Model(ThDecapode(), modeljson) -diagram_json = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "diagrams", "diffusivity_constant", "diagram.json"), "r") -diagram = Diagram(diagram_json[:notebook], model_dec_scalar) -infer_types!(diagram.pode) -@testset "Diagram - Diffusivity Constant" begin - # construct a decapode - handcrafted_pode = SummationDecapode(parse_decapode(quote end)) - add_part!(handcrafted_pode, :Var, name=:u, type=:DualForm2) - add_part!(handcrafted_pode, :Var, name=Symbol("du/dt"), type=:DualForm2) - add_part!(handcrafted_pode, :Var, name=Symbol("•1"), type=:Form0) - add_part!(handcrafted_pode, :Var, name=Symbol("•2"), type=:Form1) - add_part!(handcrafted_pode, :Var, name=Symbol("•3"), type=:DualForm1) - add_part!(handcrafted_pode, :Var, name=Symbol("•4"), type=:DualForm2) - add_part!(handcrafted_pode, :TVar, incl=2) - add_part!(handcrafted_pode, :Op1, src=1, tgt=3, op1=:⋆₀⁻¹) - add_part!(handcrafted_pode, :Op1, src=3, tgt=4, op1=:d₀) - add_part!(handcrafted_pode, :Op1, src=4, tgt=5, op1=:⋆₁) - add_part!(handcrafted_pode, :Op1, src=5, tgt=6, op1=:dual_d₁) - add_part!(handcrafted_pode, :Op1, src=6, tgt=2, op1=:any_scalar) - add_part!(handcrafted_pode, :Op1, src=1, tgt=2, op1=:∂ₜ) - @test diagram.pode == handcrafted_pode -end -# TODO not specifying initial boundary conditions for `B` on the front-end -# means that it will be automatically specified -@testset "Analysis - Diffusivity Constant" begin - analysis_json = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "diagrams", "diffusivity_constant", "analysis.json"), "r") - system = Analysis(analysis_json, diagram) - simulator = evalsim(system.pode) - f = simulator(system.geometry.dualmesh, system.generate, DiagonalHodge()) - soln = run_sim(f, system.init, system.duration, ComponentArray(k=0.5,)) - @test soln.retcode == ReturnCode.Success - result = SimResult(soln, system) - @test typeof(result.state) == Dict{String, Vector{AbstractArray{SVector{3, Float64}}}} - jv = JsonValue(result) -end - - -# Payload -payloadjson = open(JSON3.read, joinpath(@__DIR__, "test_jsons", "payload.json")) -model = Model(ThDecapode(), payloadjson.model) -diagram = Diagram(payloadjson.diagram, model) -infer_types!(diagram.pode) -# TODO need to verify -@testset "(Payload) Diagram - Diffusivity Constant" begin - # construct a decapode - handcrafted_pode = SummationDecapode(parse_decapode(quote end)) - add_part!(handcrafted_pode, :Var, name=Symbol("dv/dt"), type=:DualForm2) - add_part!(handcrafted_pode, :Var, name=Symbol("•1"), type=:Form0) - add_part!(handcrafted_pode, :Var, name=Symbol("•2"), type=:Form1) - add_part!(handcrafted_pode, :Var, name=Symbol("•3"), type=:DualForm1) - add_part!(handcrafted_pode, :Var, name=Symbol("•4"), type=:DualForm2) - add_part!(handcrafted_pode, :Var, name=:v, type=:DualForm2) - add_part!(handcrafted_pode, :TVar, incl=1) - add_part!(handcrafted_pode, :Op1, src=6, tgt=2, op1=:⋆₀⁻¹) - add_part!(handcrafted_pode, :Op1, src=3, tgt=4, op1=:⋆₁) - add_part!(handcrafted_pode, :Op1, src=5, tgt=1, op1=:any_scalar) - add_part!(handcrafted_pode, :Op1, src=6, tgt=1, op1=:∂ₜ) - add_part!(handcrafted_pode, :Op1, src=4, tgt=5, op1=:dual_d₁) - add_part!(handcrafted_pode, :Op1, src=2, tgt=3, op1=:d₀) - @test diagram.pode == handcrafted_pode -end -# TODO not specifying initial boundary conditions for `B` on the front-end -# means that it will be automatically specified -@testset "Analysis - Diffusivity Constant" begin - system = Analysis(ThDecapode(), payloadjson) - simulator = evalsim(system.pode) - # DEBUGGING SNIPPET: - # path = joinpath(@__DIR__, "testsim.jl") - # open(path, "w") do f - # write(f, string(gensim(system.pode))) - # end - # simulator = include(path) - f = simulator(system.geometry.dualmesh, system.generate, DiagonalHodge()) - soln = run_sim(f, system.init, system.duration, ComponentArray(k=0.5,)) - @test soln.retcode == ReturnCode.Success - result = SimResult(soln, system) - @test typeof(result.state) == Dict{String, Vector{AbstractArray{SVector{3, Float64}}}} - jv = JsonValue(result) +@testset "Catlab" begin + include("TestCatlab.jl") end diff --git a/packages/algjulia-interop/test/test_jsons/diagrams/diffusivity_constant/analysis.json b/packages/algjulia-interop/test/test_jsons/diagrams/diffusivity_constant/analysis.json deleted file mode 100644 index 5f986cf67..000000000 --- a/packages/algjulia-interop/test/test_jsons/diagrams/diffusivity_constant/analysis.json +++ /dev/null @@ -1,47 +0,0 @@ -{ - "analysisOf": { - "_id": "0196021c-dee3-75b3-bb79-2f940651a1a1", - "_server": "backend.catcolab.org", - "_version": null, - "type": "analysis-of" - }, - "analysisType": "diagram", - "name": "", - "notebook": { - "cells": [ - { - "content": { - "content": { - "domain": "Plane", - "duration": 10, - "initialConditions": { - "0196021c-f5fe-70f3-ac68-89ae212970ea": "Gaussian", - "0196021d-1aa4-776d-b4fb-05d24d0c6de4": "Gaussian" - }, - "mesh": "Rectangle", - "plotVariables": { - "0196021c-f5fe-70f3-ac68-89ae212970ea": true - }, - "scalars": { - "01960dde-1193-7132-b662-9bf24ed05264": 1 - } - }, - "id": "decapodes" - }, - "id": "0196021f-beef-74b0-9103-9ab1982255cf", - "tag": "formal" - }, - { - "content": { - "content": { - "layout": "graphviz-directed" - }, - "id": "graph" - }, - "id": "01960ddd-8fc3-7482-a2c8-a0a59ee85709", - "tag": "formal" - } - ] - }, - "type": "analysis" -} diff --git a/packages/algjulia-interop/test/test_jsons/diagrams/diffusivity_constant/diagram.json b/packages/algjulia-interop/test/test_jsons/diagrams/diffusivity_constant/diagram.json deleted file mode 100644 index 53d93e9fb..000000000 --- a/packages/algjulia-interop/test/test_jsons/diagrams/diffusivity_constant/diagram.json +++ /dev/null @@ -1,201 +0,0 @@ -{ - "diagramIn": { - "_id": "0196021c-d1ff-75b1-9f38-bdecdb7680d2", - "_server": "backend.catcolab.org", - "_version": null, - "type": "diagram-in" - }, - "name": "", - "notebook": { - "cells": [ - { - "content": { - "id": "0196021c-f5fe-70f3-ac68-89ae212970ea", - "name": "u", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "over": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0196021c-f5fe-70f3-ac68-8f4da8bb79be", - "tag": "formal" - }, - { - "content": { - "id": "0196021d-1aa4-776d-b4fb-05d24d0c6de4", - "name": "du/dt", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "over": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0196021d-1aa4-776d-b4fb-098aea19edd5", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0196021e-9635-74de-845a-cee56d3e5cc5", - "tag": "Basic" - }, - "dom": { - "content": "0196021c-f5fe-70f3-ac68-89ae212970ea", - "tag": "Basic" - }, - "id": "0196021e-848d-704c-a45c-a325b63951e6", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "", - "over": { - "content": "0194d399-34f3-773c-91b9-857da9c4311f", - "tag": "Basic" - }, - "tag": "morphism" - }, - "id": "0196021e-848d-704c-a45c-a6b09dac0136", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0196021e-e55e-764e-85c8-827f94d7f3bd", - "tag": "Basic" - }, - "dom": { - "content": "0196021e-9635-74de-845a-cee56d3e5cc5", - "tag": "Basic" - }, - "id": "0196021e-c8a6-74df-8194-3ec769ba3d1d", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "", - "over": { - "content": "0194d39a-6084-7537-aec1-caf560ba416b", - "tag": "Basic" - }, - "tag": "morphism" - }, - "id": "0196021e-c8a6-74df-8194-40ee060a7684", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0196021f-0a11-7443-b5da-31175c628e3c", - "tag": "Basic" - }, - "dom": { - "content": "0196021e-e55e-764e-85c8-827f94d7f3bd", - "tag": "Basic" - }, - "id": "0196021e-ecf9-7408-b881-d981c4e85222", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "", - "over": { - "content": "0194d39a-ed25-710f-b53f-89541021281f", - "tag": "Basic" - }, - "tag": "morphism" - }, - "id": "0196021e-ecf9-7408-b881-ddb32ac3d85e", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0196021f-4c93-70dc-8e61-24459f79f837", - "tag": "Basic" - }, - "dom": { - "content": "0196021f-0a11-7443-b5da-31175c628e3c", - "tag": "Basic" - }, - "id": "0196021f-1ba8-77a5-a635-8b3ca32ae99c", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "", - "over": { - "content": "0194d39d-d297-77a9-95a2-6ed7105fdca3", - "tag": "Basic" - }, - "tag": "morphism" - }, - "id": "0196021f-1ba8-77a5-a635-8f6c9f8b2c4c", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0196021d-1aa4-776d-b4fb-05d24d0c6de4", - "tag": "Basic" - }, - "dom": { - "content": "0196021f-4c93-70dc-8e61-24459f79f837", - "tag": "Basic" - }, - "id": "0196021f-6b45-751e-8313-df1024cd9fa0", - "morType": { - "content": { - "content": "Object", - "tag": "Basic" - }, - "tag": "Hom" - }, - "name": "", - "over": { - "content": "01960dde-1193-7132-b662-9bf24ed05264", - "tag": "Basic" - }, - "tag": "morphism" - }, - "id": "0196021f-6b46-73b4-8b8a-1417d000ecfd", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0196021d-1aa4-776d-b4fb-05d24d0c6de4", - "tag": "Basic" - }, - "dom": { - "content": "0196021c-f5fe-70f3-ac68-89ae212970ea", - "tag": "Basic" - }, - "id": "01960df4-b95f-7660-90b6-aaf1dc940a15", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "", - "over": { - "content": "0194d39c-622d-7599-bc5c-e7e8208d6cdd", - "tag": "Basic" - }, - "tag": "morphism" - }, - "id": "01960df4-b95f-7660-90b6-ae21afb022aa", - "tag": "formal" - } - ] - }, - "type": "diagram" -} diff --git a/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian/analysis.json b/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian/analysis.json deleted file mode 100644 index bcc7c72b3..000000000 --- a/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian/analysis.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "analysisOf": { - "_id": "0195c95c-b3eb-7142-8b38-b7287cf2c76f", - "_server": "backend.catcolab.org", - "_version": null, - "type": "analysis-of" - }, - "analysisType": "diagram", - "name": "", - "notebook": { - "cells": [ - { - "content": { - "content": { - "domain": "Sphere", - "duration": 1, - "initialConditions": { - "0195c95c-c200-73a0-bf58-1cc188ecd0c4": "TaylorVortex", - "0195c95c-d4b4-779b-ae65-a89269f63b43": "TaylorVortex" - }, - "mesh": "Icosphere6", - "plotVariables": { - "0195c95c-c200-73a0-bf58-1cc188ecd0c4": true, - "0195c95c-d4b4-779b-ae65-a89269f63b43": false - }, - "scalars": {} - }, - "id": "decapodes" - }, - "id": "0195c95d-3b6b-71cb-8bd2-9fbc90fc609f", - "tag": "formal" - }, - { - "id": "0195ca0d-166a-7179-87d8-b5cf9dd9eaf1", - "tag": "stem" - }, - { - "content": { - "content": { - "layout": "graphviz-directed" - }, - "id": "graph" - }, - "id": "0195ca0d-b210-72c5-a091-3e57ced85ed5", - "tag": "formal" - }, - { - "id": "0195dddf-faaa-76ea-a966-ba4b9be5b36e", - "tag": "stem" - } - ] - }, - "type": "analysis" -} diff --git a/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian/diagram.json b/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian/diagram.json deleted file mode 100644 index a0c3ae2c0..000000000 --- a/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian/diagram.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "diagramIn": { - "_id": "0195c95c-9917-7402-82b9-1b6c735258b7", - "_server": "backend.catcolab.org", - "_version": null, - "type": "diagram-in" - }, - "name": "", - "notebook": { - "cells": [ - { - "content": { - "id": "0195c95c-c200-73a0-bf58-1cc188ecd0c4", - "name": "A", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "over": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0195c95c-c200-73a0-bf58-22914f83428d", - "tag": "formal" - }, - { - "content": { - "id": "0195c95c-d4b4-779b-ae65-a89269f63b43", - "name": "B", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "over": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0195c95c-d4b4-779b-ae65-ad0a7af96410", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0195c95c-d4b4-779b-ae65-a89269f63b43", - "tag": "Basic" - }, - "dom": { - "content": "0195c95c-c200-73a0-bf58-1cc188ecd0c4", - "tag": "Basic" - }, - "id": "0195dde5-27aa-72fa-9cde-ff6571346ca7", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "", - "over": { - "content": "0194d399-b2a2-73ff-aece-cb0f26644045", - "tag": "Basic" - }, - "tag": "morphism" - }, - "id": "0195dde5-27aa-72fa-9cdf-0313e512eb41", - "tag": "formal" - } - ] - }, - "type": "diagram" -} diff --git a/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian_longtrip/analysis.json b/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian_longtrip/analysis.json deleted file mode 100644 index f42780bee..000000000 --- a/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian_longtrip/analysis.json +++ /dev/null @@ -1 +0,0 @@ -{"analysisOf":{"_id":"0195ecdc-cf21-7091-94a3-7644d5103743","_server":"backend.catcolab.org","_version":null,"type":"analysis-of"},"analysisType":"diagram","name":"","notebook":{"cells":[{"id":"0195ed44-aa9e-730d-807d-57cf94417236","tag":"stem"},{"content":{"content":{"domain":"Plane","duration":10,"initialConditions":{"0195ecdc-d7e1-768a-8862-76a47f2f4e06":"Gaussian","0195ecdc-f625-71c8-a044-a6ce2fb3dd31":"Gaussian"},"mesh":"Rectangle","plotVariables":{"0195ecdc-d7e1-768a-8862-76a47f2f4e06":true},"scalars":{}},"id":"decapodes"},"id":"0195ed44-c260-755f-9c1f-80c13253e575","tag":"formal"}]},"type":"analysis"} diff --git a/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian_longtrip/diagram.json b/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian_longtrip/diagram.json deleted file mode 100644 index 09e15e238..000000000 --- a/packages/algjulia-interop/test/test_jsons/diagrams/inverse_laplacian_longtrip/diagram.json +++ /dev/null @@ -1 +0,0 @@ -{"diagramIn":{"_id":"0195ecc4-309b-7742-b7d7-35f8ba9021f9","_server":"backend.catcolab.org","_version":null,"type":"diagram-in"},"name":"","notebook":{"cells":[{"content":{"id":"0195ecdc-d7e1-768a-8862-76a47f2f4e06","name":"u","obType":{"content":"Object","tag":"Basic"},"over":{"content":"0194d398-a28e-7433-89f8-563bae6e6875","tag":"Basic"},"tag":"object"},"id":"0195ecdc-d7e1-768a-8862-780d2b88ba8f","tag":"formal"},{"content":{"id":"0195ecdc-f625-71c8-a044-a6ce2fb3dd31","name":"Δu","obType":{"content":"Object","tag":"Basic"},"over":{"content":"0194d398-a28e-7433-89f8-563bae6e6875","tag":"Basic"},"tag":"object"},"id":"0195ecdc-f625-71c8-a044-a898b541279d","tag":"formal"},{"content":{"cod":{"content":"0195ecdd-c6c2-705b-ad25-44d72de6fc99","tag":"Basic"},"dom":{"content":"0195ecdc-d7e1-768a-8862-76a47f2f4e06","tag":"Basic"},"id":"0195ecdd-a1d8-771f-a5db-47c43a43da66","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39a-6084-7537-aec1-caf560ba416b","tag":"Basic"},"tag":"morphism"},"id":"0195ecdd-a1d8-771f-a5db-48e03a65f8a9","tag":"formal"},{"content":{"cod":{"content":"0195ecde-1719-72af-8f7e-bcfa1c6fa617","tag":"Basic"},"dom":{"content":"0195ecdd-c6c2-705b-ad25-44d72de6fc99","tag":"Basic"},"id":"0195ecdd-e894-7111-a026-21f6b8f17f86","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39a-ed25-710f-b53f-89541021281f","tag":"Basic"},"tag":"morphism"},"id":"0195ecdd-e895-77f9-b6ec-38d511443d63","tag":"formal"},{"content":{"cod":{"content":"0195ece5-5cc4-718f-82bb-1a5bb0cf8ac8","tag":"Basic"},"dom":{"content":"0195ecde-1719-72af-8f7e-bcfa1c6fa617","tag":"Basic"},"id":"0195ece5-4a90-7047-bcd6-10834ee90cea","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39d-d297-77a9-95a2-6ed7105fdca3","tag":"Basic"},"tag":"morphism"},"id":"0195ece5-4a90-7047-bcd6-172ee350261f","tag":"formal"},{"content":{"cod":{"content":"0195ecdc-f625-71c8-a044-a6ce2fb3dd31","tag":"Basic"},"dom":{"content":"0195ece5-5cc4-718f-82bb-1a5bb0cf8ac8","tag":"Basic"},"id":"0195ece5-80df-71a1-b50e-cf38757198ba","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d399-34f3-773c-91b9-857da9c4311f","tag":"Basic"},"tag":"morphism"},"id":"0195ece5-80df-71a1-b50e-d0d77173e3a9","tag":"formal"},{"content":{"cod":{"content":"0195ecdc-f625-71c8-a044-a6ce2fb3dd31","tag":"Basic"},"dom":{"content":"0195ecdc-d7e1-768a-8862-76a47f2f4e06","tag":"Basic"},"id":"0195ece7-6b59-76a8-b973-d83c90bae58a","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d399-b2a2-73ff-aece-cb0f26644045","tag":"Basic"},"tag":"morphism"},"id":"0195ece7-6b59-76a8-b973-dfca48ecabd6","tag":"formal"}]},"type":"diagram"} diff --git a/packages/algjulia-interop/test/test_jsons/diagrams/ns_vort/analysis.json b/packages/algjulia-interop/test/test_jsons/diagrams/ns_vort/analysis.json deleted file mode 100644 index 8838d4941..000000000 --- a/packages/algjulia-interop/test/test_jsons/diagrams/ns_vort/analysis.json +++ /dev/null @@ -1 +0,0 @@ -{"analysisOf":{"_id":"0195ecc4-4c4d-70e2-bee7-18221e6c42e7","_server":"backend.catcolab.org","_version":null,"type":"analysis-of"},"analysisType":"diagram","name":"","notebook":{"cells":[{"content":{"content":{"domain":"Sphere","duration":1,"initialConditions":{"0195ecc5-9eaf-71dd-a9c8-621d888e2add":"TaylorVortex","0195ecc5-b1b0-746e-8a04-ebd359da2bfd":"TaylorVortex","0195ecc5-d39a-72bf-8cd3-236d5211e122":"TaylorVortex"},"mesh":"Icosphere6","plotVariables":{"0195ecc5-9eaf-71dd-a9c8-621d888e2add":true},"scalars":{}},"id":"decapodes"},"id":"0195ecca-f11e-74c8-8fa4-fb8b03a93274","tag":"formal"}]},"type":"analysis"} diff --git a/packages/algjulia-interop/test/test_jsons/diagrams/ns_vort/diagram.json b/packages/algjulia-interop/test/test_jsons/diagrams/ns_vort/diagram.json deleted file mode 100644 index 4e0f694ed..000000000 --- a/packages/algjulia-interop/test/test_jsons/diagrams/ns_vort/diagram.json +++ /dev/null @@ -1 +0,0 @@ -{"diagramIn":{"_id":"0195ecc4-309b-7742-b7d7-35f8ba9021f9","_server":"backend.catcolab.org","_version":null,"type":"diagram-in"},"name":"","notebook":{"cells":[{"content":{"id":"0195ecc5-9eaf-71dd-a9c8-621d888e2add","name":"v","obType":{"content":"Object","tag":"Basic"},"over":{"content":"0194d398-b3ef-728d-bd88-60b48fd7349a","tag":"Basic"},"tag":"object"},"id":"0195ecc5-9eb0-70f9-b2c0-36f0f3d4cd28","tag":"formal"},{"content":{"id":"0195ecc5-b1b0-746e-8a04-ebd359da2bfd","name":"dv","obType":{"content":"Object","tag":"Basic"},"over":{"content":"0194d398-d0cb-7308-b7e0-eace5b21af24","tag":"Basic"},"tag":"object"},"id":"0195ecc5-b1b0-746e-8a04-ef250a7afe00","tag":"formal"},{"content":{"id":"0195ecc5-d39a-72bf-8cd3-236d5211e122","name":"ψ","obType":{"content":"Object","tag":"Basic"},"over":{"content":"0194d398-a28e-7433-89f8-563bae6e6875","tag":"Basic"},"tag":"object"},"id":"0195ecc5-d39a-72bf-8cd3-26a9e71b49bf","tag":"formal"},{"content":{"cod":{"content":"0195ecc6-f2ab-719c-844b-b8413517e269","tag":"Basic"},"dom":{"content":"0195ecc5-b1b0-746e-8a04-ebd359da2bfd","tag":"Basic"},"id":"0195ecc6-ce3f-7607-bce9-cb3fa3ddb4a6","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d399-34f3-773c-91b9-857da9c4311f","tag":"Basic"},"tag":"morphism"},"id":"0195ecc6-ce3f-7607-bce9-cf213389bf95","tag":"formal"},{"content":{"cod":{"content":"0195ecc7-388f-72c0-a4f1-3b89ed8aa6e0","tag":"Basic"},"dom":{"content":"0195ecc5-d39a-72bf-8cd3-236d5211e122","tag":"Basic"},"id":"0195ecc7-10a4-755e-8cc7-a3900d37dc93","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39a-6084-7537-aec1-caf560ba416b","tag":"Basic"},"tag":"morphism"},"id":"0195ecc7-10a4-755e-8cc7-a45b6cbd1cb8","tag":"formal"},{"content":{"cod":{"content":"0195ecc5-9eaf-71dd-a9c8-621d888e2add","tag":"Basic"},"dom":{"content":"0195ecc7-388f-72c0-a4f1-3b89ed8aa6e0","tag":"Basic"},"id":"0195ecc7-4faa-751f-951d-4d854f43a59d","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39a-ed25-710f-b53f-89541021281f","tag":"Basic"},"tag":"morphism"},"id":"0195ecc7-4faa-751f-951d-50a87eb7eb09","tag":"formal"},{"content":{"cod":{"content":"0195ecc7-8f7f-720e-b1ef-befd8deb0e78","tag":"Basic"},"dom":{"content":"0195ecc5-9eaf-71dd-a9c8-621d888e2add","tag":"Basic"},"id":"0195ecc7-7698-70a8-8847-3b021b1f48fa","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39b-587f-7559-a1ff-b6ed58899461","tag":"Basic"},"tag":"morphism"},"id":"0195ecc7-7698-70a8-8847-3d286c36d0e8","tag":"formal"},{"content":{"cod":{"content":"0195ecc7-c18e-7632-990d-33dd4afe1f87","tag":"Basic"},"dom":{"content":"0195ecc7-8f7f-720e-b1ef-befd8deb0e78","tag":"Basic"},"id":"0195ecc7-9a27-77fd-bbe3-320fa00047ed","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39b-a70a-77d5-8e89-66f0e767a9da","tag":"Basic"},"tag":"morphism"},"id":"0195ecc7-9a27-77fd-bbe3-36268ee77145","tag":"formal"},{"content":{"cod":{"content":"0195ecc7-f8e6-761b-a52e-3ecbe49ddaa1","tag":"Basic"},"dom":{"content":"0195ecc7-c18e-7632-990d-33dd4afe1f87","tag":"Basic"},"id":"0195ecc7-c925-74fb-9fa4-b172831ead97","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39a-ed25-710f-b53f-89541021281f","tag":"Basic"},"tag":"morphism"},"id":"0195ecc7-c925-74fb-9fa4-b74dfa39bba8","tag":"formal"},{"content":{"cod":{"content":"0195ecca-5a2c-71cd-998d-d0f25a79a266","tag":"Basic"},"dom":{"content":"0195ecc5-b1b0-746e-8a04-ebd359da2bfd","tag":"Basic"},"id":"0195ecc9-bcfd-7689-bc42-75a237fe9c2c","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39c-622d-7599-bc5c-e7e8208d6cdd","tag":"Basic"},"tag":"morphism"},"id":"0195ecc9-bcfd-7689-bc42-7a6c6e84d4f3","tag":"formal"},{"content":{"cod":{"content":"0195ecca-8dd0-7735-9d74-c73dc1c8eb9e","tag":"Basic"},"dom":{"content":"0195ecc7-f8e6-761b-a52e-3ecbe49ddaa1","tag":"Basic"},"id":"0195ecca-64d2-71e7-9f79-31cb7d8cb95e","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39d-d297-77a9-95a2-6ed7105fdca3","tag":"Basic"},"tag":"morphism"},"id":"0195ecca-64d2-71e7-9f79-3708a3062d71","tag":"formal"},{"content":{"cod":{"content":"0195ecca-5a2c-71cd-998d-d0f25a79a266","tag":"Basic"},"dom":{"content":"0195ecca-8dd0-7735-9d74-c73dc1c8eb9e","tag":"Basic"},"id":"0195ecca-98d7-73f7-9297-b8b693434f99","morType":{"content":"Nonscalar","tag":"Basic"},"name":"","over":{"content":"0194d39e-5d44-77cd-bc5e-156c5c56ae85","tag":"Basic"},"tag":"morphism"},"id":"0195ecca-98d7-73f7-9297-be3feb46d9b9","tag":"formal"}]},"type":"diagram"} diff --git a/packages/algjulia-interop/test/test_jsons/diffconst_payload1.json b/packages/algjulia-interop/test/test_jsons/diffconst_payload1.json deleted file mode 100644 index 1a0039420..000000000 --- a/packages/algjulia-interop/test/test_jsons/diffconst_payload1.json +++ /dev/null @@ -1,435 +0,0 @@ -{ - "diagram": [ - { - "tag": "object", - "name": "du/dt", - "id": "0196021d-1aa4-776d-b4fb-05d24d0c6de4", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24" - } - }, - { - "tag": "object", - "name": "", - "id": "0196021e-9635-74de-845a-cee56d3e5cc5", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d398-a28e-7433-89f8-563bae6e6875" - } - }, - { - "tag": "object", - "name": "", - "id": "0196021e-e55e-764e-85c8-827f94d7f3bd", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7" - } - }, - { - "tag": "object", - "name": "", - "id": "0196021f-0a11-7443-b5da-31175c628e3c", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a" - } - }, - { - "tag": "object", - "name": "", - "id": "0196021f-4c93-70dc-8e61-24459f79f837", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24" - } - }, - { - "tag": "object", - "name": "u", - "id": "0196021c-f5fe-70f3-ac68-89ae212970ea", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24" - } - }, - { - "tag": "morphism", - "name": "", - "id": "0196021e-848d-704c-a45c-a325b63951e6", - "morType": { - "tag": "Basic", - "content": "Nonscalar" - }, - "over": { - "tag": "Basic", - "content": "0194d399-34f3-773c-91b9-857da9c4311f" - }, - "dom": { - "tag": "Basic", - "content": "0196021c-f5fe-70f3-ac68-89ae212970ea" - }, - "cod": { - "tag": "Basic", - "content": "0196021e-9635-74de-845a-cee56d3e5cc5" - } - }, - { - "tag": "morphism", - "name": "", - "id": "0196021e-ecf9-7408-b881-d981c4e85222", - "morType": { - "tag": "Basic", - "content": "Nonscalar" - }, - "over": { - "tag": "Basic", - "content": "0194d39a-ed25-710f-b53f-89541021281f" - }, - "dom": { - "tag": "Basic", - "content": "0196021e-e55e-764e-85c8-827f94d7f3bd" - }, - "cod": { - "tag": "Basic", - "content": "0196021f-0a11-7443-b5da-31175c628e3c" - } - }, - { - "tag": "morphism", - "name": "", - "id": "0196021f-6b45-751e-8313-df1024cd9fa0", - "morType": { - "tag": "Hom", - "content": { - "tag": "Basic", - "content": "Object" - } - }, - "over": { - "tag": "Basic", - "content": "01960dde-1193-7132-b662-9bf24ed05264" - }, - "dom": { - "tag": "Basic", - "content": "0196021f-4c93-70dc-8e61-24459f79f837" - }, - "cod": { - "tag": "Basic", - "content": "0196021d-1aa4-776d-b4fb-05d24d0c6de4" - } - }, - { - "tag": "morphism", - "name": "", - "id": "01960df4-b95f-7660-90b6-aaf1dc940a15", - "morType": { - "tag": "Basic", - "content": "Nonscalar" - }, - "over": { - "tag": "Basic", - "content": "0194d39c-622d-7599-bc5c-e7e8208d6cdd" - }, - "dom": { - "tag": "Basic", - "content": "0196021c-f5fe-70f3-ac68-89ae212970ea" - }, - "cod": { - "tag": "Basic", - "content": "0196021d-1aa4-776d-b4fb-05d24d0c6de4" - } - }, - { - "tag": "morphism", - "name": "", - "id": "0196021f-1ba8-77a5-a635-8b3ca32ae99c", - "morType": { - "tag": "Basic", - "content": "Nonscalar" - }, - "over": { - "tag": "Basic", - "content": "0194d39d-d297-77a9-95a2-6ed7105fdca3" - }, - "dom": { - "tag": "Basic", - "content": "0196021f-0a11-7443-b5da-31175c628e3c" - }, - "cod": { - "tag": "Basic", - "content": "0196021f-4c93-70dc-8e61-24459f79f837" - } - }, - { - "tag": "morphism", - "name": "", - "id": "0196021e-c8a6-74df-8194-3ec769ba3d1d", - "morType": { - "tag": "Basic", - "content": "Nonscalar" - }, - "over": { - "tag": "Basic", - "content": "0194d39a-6084-7537-aec1-caf560ba416b" - }, - "dom": { - "tag": "Basic", - "content": "0196021e-9635-74de-845a-cee56d3e5cc5" - }, - "cod": { - "tag": "Basic", - "content": "0196021e-e55e-764e-85c8-827f94d7f3bd" - } - } - ], - "model": [ - { - "id": "0194d398-a28e-7433-89f8-563bae6e6875", - "name": "0-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - { - "id": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "name": "Dual 1-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - { - "id": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "name": "Dual 2-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - { - "id": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "name": "Primal 1-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - { - "cod": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d399-34f3-773c-91b9-857da9c4311f", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": " ⋆₀⁻¹", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "id": "0194d399-b2a2-73ff-aece-cb0f26644045", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "Δ⁻¹", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "id": "0194d39a-6084-7537-aec1-caf560ba416b", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "d₀", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "dom": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "id": "0194d39a-ed25-710f-b53f-89541021281f", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "⋆₁", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39b-587f-7559-a1ff-b6ed58899461", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "lamb", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39b-a70a-77d5-8e89-66f0e767a9da", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": " ♭♯", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39d-d297-77a9-95a2-6ed7105fdca3", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "d̃₁", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d39c-622d-7599-bc5c-e7e8208d6cdd", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "∂ₜ", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d39e-5d44-77cd-bc5e-156c5c56ae85", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "-", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "01960dde-1193-7132-b662-9bf24ed05264", - "morType": { - "content": { - "content": "Object", - "tag": "Basic" - }, - "tag": "Hom" - }, - "name": "any_scalar", - "tag": "morphism" - } - ], - "domain": "Plane", - "mesh": "Rectangle", - "initialConditions": { - "0196021c-f5fe-70f3-ac68-89ae212970ea": "Gaussian", - "0196021d-1aa4-776d-b4fb-05d24d0c6de4": "Gaussian" - }, - "plotVariables": [ - "0196021c-f5fe-70f3-ac68-89ae212970ea" - ], - "scalars": { - "01960dde-1193-7132-b662-9bf24ed05264": 0.5 - }, - "duration": 10 -} diff --git a/packages/algjulia-interop/test/test_jsons/models/model_dec.json b/packages/algjulia-interop/test/test_jsons/models/model_dec.json deleted file mode 100644 index f7053967f..000000000 --- a/packages/algjulia-interop/test/test_jsons/models/model_dec.json +++ /dev/null @@ -1,250 +0,0 @@ -{ - "name": "DEC for vorticity", - "notebook": { - "cells": [ - { - "content": { - "id": "0194d398-a28e-7433-89f8-563bae6e6875", - "name": "0-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0194d398-a28e-7433-89f8-5a563b37d845", - "tag": "formal" - }, - { - "content": { - "id": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "name": "Dual 1-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0194d398-b3ef-728d-bd88-64aa410935d0", - "tag": "formal" - }, - { - "content": { - "id": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "name": "Dual 2-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0194d398-d0cb-7308-b7e0-ed7c6bca5073", - "tag": "formal" - }, - { - "content": { - "id": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "name": "Primal 1-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0194d39a-89cf-762b-9d2a-58435e3f239e", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d399-34f3-773c-91b9-857da9c4311f", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": " ⋆₀⁻¹", - "tag": "morphism" - }, - "id": "0194d399-34f3-773c-91b9-8ba5ecdb1ae3", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "id": "0194d399-b2a2-73ff-aece-cb0f26644045", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "Δ⁻¹", - "tag": "morphism" - }, - "id": "0194d399-b2a2-73ff-aece-ccafcd2f4901", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "id": "0194d39a-6084-7537-aec1-caf560ba416b", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "d₀", - "tag": "morphism" - }, - "id": "0194d39a-6084-7537-aec1-cf63f29c9a9f", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "dom": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "id": "0194d39a-ed25-710f-b53f-89541021281f", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "⋆₁", - "tag": "morphism" - }, - "id": "0194d39a-ed25-710f-b53f-8dfad8f332aa", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39b-587f-7559-a1ff-b6ed58899461", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "lamb", - "tag": "morphism" - }, - "id": "0194d39b-587f-7559-a1ff-b9a4cc198cff", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39b-a70a-77d5-8e89-66f0e767a9da", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": " ♭♯", - "tag": "morphism" - }, - "id": "0194d39b-a70a-77d5-8e89-6a34504e2754", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39d-d297-77a9-95a2-6ed7105fdca3", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "d̃₁", - "tag": "morphism" - }, - "id": "0194d39d-d297-77a9-95a2-71f5210cecf2", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d39c-622d-7599-bc5c-e7e8208d6cdd", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "∂ₜ", - "tag": "morphism" - }, - "id": "0194d39c-622d-7599-bc5c-e86b88f88031", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d39e-5d44-77cd-bc5e-156c5c56ae85", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "-", - "tag": "morphism" - }, - "id": "0194d39e-5d44-77cd-bc5e-1aa6b0a2d8d4", - "tag": "formal" - } - ] - }, - "theory": "unary-dec", - "type": "model" -} \ No newline at end of file diff --git a/packages/algjulia-interop/test/test_jsons/models/model_dec_scalar.json b/packages/algjulia-interop/test/test_jsons/models/model_dec_scalar.json deleted file mode 100644 index 595c0490a..000000000 --- a/packages/algjulia-interop/test/test_jsons/models/model_dec_scalar.json +++ /dev/null @@ -1,274 +0,0 @@ -{ - "name": "DEC for vorticity", - "notebook": { - "cells": [ - { - "content": { - "id": "0194d398-a28e-7433-89f8-563bae6e6875", - "name": "0-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0194d398-a28e-7433-89f8-5a563b37d845", - "tag": "formal" - }, - { - "content": { - "id": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "name": "Dual 1-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0194d398-b3ef-728d-bd88-64aa410935d0", - "tag": "formal" - }, - { - "content": { - "id": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "name": "Dual 2-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0194d398-d0cb-7308-b7e0-ed7c6bca5073", - "tag": "formal" - }, - { - "content": { - "id": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "name": "Primal 1-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - "id": "0194d39a-89cf-762b-9d2a-58435e3f239e", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d399-34f3-773c-91b9-857da9c4311f", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": " ⋆₀⁻¹", - "tag": "morphism" - }, - "id": "0194d399-34f3-773c-91b9-8ba5ecdb1ae3", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "id": "0194d399-b2a2-73ff-aece-cb0f26644045", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "Δ⁻¹", - "tag": "morphism" - }, - "id": "0194d399-b2a2-73ff-aece-ccafcd2f4901", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "id": "0194d39a-6084-7537-aec1-caf560ba416b", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "d₀", - "tag": "morphism" - }, - "id": "0194d39a-6084-7537-aec1-cf63f29c9a9f", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "dom": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "id": "0194d39a-ed25-710f-b53f-89541021281f", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "⋆₁", - "tag": "morphism" - }, - "id": "0194d39a-ed25-710f-b53f-8dfad8f332aa", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39b-587f-7559-a1ff-b6ed58899461", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "lamb", - "tag": "morphism" - }, - "id": "0194d39b-587f-7559-a1ff-b9a4cc198cff", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39b-a70a-77d5-8e89-66f0e767a9da", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": " ♭♯", - "tag": "morphism" - }, - "id": "0194d39b-a70a-77d5-8e89-6a34504e2754", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39d-d297-77a9-95a2-6ed7105fdca3", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "d̃₁", - "tag": "morphism" - }, - "id": "0194d39d-d297-77a9-95a2-71f5210cecf2", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d39c-622d-7599-bc5c-e7e8208d6cdd", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "∂ₜ", - "tag": "morphism" - }, - "id": "0194d39c-622d-7599-bc5c-e86b88f88031", - "tag": "formal" - }, - { - "content": { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d39e-5d44-77cd-bc5e-156c5c56ae85", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "-", - "tag": "morphism" - }, - "id": "0194d39e-5d44-77cd-bc5e-1aa6b0a2d8d4", - "tag": "formal" - }, - { - "tag": "formal", - "id": "01960dde-1194-729d-92f7-8c876f072ff8", - "content": { - "tag": "morphism", - "id": "01960dde-1193-7132-b662-9bf24ed05264", - "name": "any_scalar", - "morType": { - "tag": "Hom", - "content": { - "tag": "Basic", - "content": "Object" - } - }, - "dom": { - "tag": "Basic", - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24" - }, - "cod": { - "tag": "Basic", - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24" - } - } - } - ] - }, - "theory": "unary-dec", - "type": "model" -} diff --git a/packages/algjulia-interop/test/test_jsons/payload.json b/packages/algjulia-interop/test/test_jsons/payload.json deleted file mode 100644 index a8d46701e..000000000 --- a/packages/algjulia-interop/test/test_jsons/payload.json +++ /dev/null @@ -1,435 +0,0 @@ -{ - "diagram": [ - { - "tag": "object", - "name": "dv/dt", - "id": "0196021d-1aa4-776d-b4fb-05d24d0c6de4", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24" - } - }, - { - "tag": "object", - "name": "", - "id": "0196021e-9635-74de-845a-cee56d3e5cc5", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d398-a28e-7433-89f8-563bae6e6875" - } - }, - { - "tag": "object", - "name": "", - "id": "0196021e-e55e-764e-85c8-827f94d7f3bd", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7" - } - }, - { - "tag": "object", - "name": "", - "id": "0196021f-0a11-7443-b5da-31175c628e3c", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a" - } - }, - { - "tag": "object", - "name": "", - "id": "0196021f-4c93-70dc-8e61-24459f79f837", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24" - } - }, - { - "tag": "object", - "name": "v", - "id": "0196021c-f5fe-70f3-ac68-89ae212970ea", - "obType": { - "tag": "Basic", - "content": "Object" - }, - "over": { - "tag": "Basic", - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24" - } - }, - { - "tag": "morphism", - "name": "", - "id": "0196021e-848d-704c-a45c-a325b63951e6", - "morType": { - "tag": "Basic", - "content": "Nonscalar" - }, - "over": { - "tag": "Basic", - "content": "0194d399-34f3-773c-91b9-857da9c4311f" - }, - "dom": { - "tag": "Basic", - "content": "0196021c-f5fe-70f3-ac68-89ae212970ea" - }, - "cod": { - "tag": "Basic", - "content": "0196021e-9635-74de-845a-cee56d3e5cc5" - } - }, - { - "tag": "morphism", - "name": "", - "id": "0196021e-ecf9-7408-b881-d981c4e85222", - "morType": { - "tag": "Basic", - "content": "Nonscalar" - }, - "over": { - "tag": "Basic", - "content": "0194d39a-ed25-710f-b53f-89541021281f" - }, - "dom": { - "tag": "Basic", - "content": "0196021e-e55e-764e-85c8-827f94d7f3bd" - }, - "cod": { - "tag": "Basic", - "content": "0196021f-0a11-7443-b5da-31175c628e3c" - } - }, - { - "tag": "morphism", - "name": "", - "id": "0196021f-6b45-751e-8313-df1024cd9fa0", - "morType": { - "tag": "Hom", - "content": { - "tag": "Basic", - "content": "Object" - } - }, - "over": { - "tag": "Basic", - "content": "01960dde-1193-7132-b662-9bf24ed05264" - }, - "dom": { - "tag": "Basic", - "content": "0196021f-4c93-70dc-8e61-24459f79f837" - }, - "cod": { - "tag": "Basic", - "content": "0196021d-1aa4-776d-b4fb-05d24d0c6de4" - } - }, - { - "tag": "morphism", - "name": "", - "id": "01960df4-b95f-7660-90b6-aaf1dc940a15", - "morType": { - "tag": "Basic", - "content": "Nonscalar" - }, - "over": { - "tag": "Basic", - "content": "0194d39c-622d-7599-bc5c-e7e8208d6cdd" - }, - "dom": { - "tag": "Basic", - "content": "0196021c-f5fe-70f3-ac68-89ae212970ea" - }, - "cod": { - "tag": "Basic", - "content": "0196021d-1aa4-776d-b4fb-05d24d0c6de4" - } - }, - { - "tag": "morphism", - "name": "", - "id": "0196021f-1ba8-77a5-a635-8b3ca32ae99c", - "morType": { - "tag": "Basic", - "content": "Nonscalar" - }, - "over": { - "tag": "Basic", - "content": "0194d39d-d297-77a9-95a2-6ed7105fdca3" - }, - "dom": { - "tag": "Basic", - "content": "0196021f-0a11-7443-b5da-31175c628e3c" - }, - "cod": { - "tag": "Basic", - "content": "0196021f-4c93-70dc-8e61-24459f79f837" - } - }, - { - "tag": "morphism", - "name": "", - "id": "0196021e-c8a6-74df-8194-3ec769ba3d1d", - "morType": { - "tag": "Basic", - "content": "Nonscalar" - }, - "over": { - "tag": "Basic", - "content": "0194d39a-6084-7537-aec1-caf560ba416b" - }, - "dom": { - "tag": "Basic", - "content": "0196021e-9635-74de-845a-cee56d3e5cc5" - }, - "cod": { - "tag": "Basic", - "content": "0196021e-e55e-764e-85c8-827f94d7f3bd" - } - } - ], - "model": [ - { - "id": "0194d398-a28e-7433-89f8-563bae6e6875", - "name": "0-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - { - "id": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "name": "Dual 1-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - { - "id": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "name": "Dual 2-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - { - "id": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "name": "Primal 1-form", - "obType": { - "content": "Object", - "tag": "Basic" - }, - "tag": "object" - }, - { - "cod": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d399-34f3-773c-91b9-857da9c4311f", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": " ⋆₀⁻¹", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "id": "0194d399-b2a2-73ff-aece-cb0f26644045", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "Δ⁻¹", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-a28e-7433-89f8-563bae6e6875", - "tag": "Basic" - }, - "id": "0194d39a-6084-7537-aec1-caf560ba416b", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "d₀", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "dom": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "id": "0194d39a-ed25-710f-b53f-89541021281f", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "⋆₁", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39b-587f-7559-a1ff-b6ed58899461", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "lamb", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d39a-89cf-762b-9d2a-5678b878d6c7", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39b-a70a-77d5-8e89-66f0e767a9da", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": " ♭♯", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-b3ef-728d-bd88-60b48fd7349a", - "tag": "Basic" - }, - "id": "0194d39d-d297-77a9-95a2-6ed7105fdca3", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "d̃₁", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d39c-622d-7599-bc5c-e7e8208d6cdd", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "∂ₜ", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "0194d39e-5d44-77cd-bc5e-156c5c56ae85", - "morType": { - "content": "Nonscalar", - "tag": "Basic" - }, - "name": "-", - "tag": "morphism" - }, - { - "cod": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "dom": { - "content": "0194d398-d0cb-7308-b7e0-eace5b21af24", - "tag": "Basic" - }, - "id": "01960dde-1193-7132-b662-9bf24ed05264", - "morType": { - "content": { - "content": "Object", - "tag": "Basic" - }, - "tag": "Hom" - }, - "name": "any_scalar", - "tag": "morphism" - } - ], - "domain": "Plane", - "mesh": "Rectangle", - "initialConditions": { - "0196021c-f5fe-70f3-ac68-89ae212970ea": "Gaussian", - "0196021d-1aa4-776d-b4fb-05d24d0c6de4": "Gaussian" - }, - "plotVariables": [ - "0196021c-f5fe-70f3-ac68-89ae212970ea" - ], - "scalars": { - "01960dde-1193-7132-b662-9bf24ed05264": 1 - }, - "duration": 10 -} diff --git a/packages/frontend/pnpm-lock.yaml b/packages/frontend/pnpm-lock.yaml index 0faf6c036..909b432e4 100644 --- a/packages/frontend/pnpm-lock.yaml +++ b/packages/frontend/pnpm-lock.yaml @@ -6652,3 +6652,4 @@ snapshots: tslib: 2.3.0 zwitch@2.0.4: {} + \ No newline at end of file diff --git a/packages/frontend/src/stdlib/analyses.tsx b/packages/frontend/src/stdlib/analyses.tsx index 737c8d576..d5635981f 100644 --- a/packages/frontend/src/stdlib/analyses.tsx +++ b/packages/frontend/src/stdlib/analyses.tsx @@ -41,6 +41,16 @@ export const diagramGraph = ( const DiagramGraph = lazy(() => import("./analyses/diagram_graph")); +export const tabularView = ( + options: AnalysisOptions, +): DiagramAnalysisMeta => ({ + ...options, + component: (props) => , + initialContent: GraphLayoutConfig.defaultConfig, +}); + +const TabularView = lazy(() => import("./analyses/tabular_view")); + export function kuramoto( options: Partial & { simulate: Simulators.KuramotoSimulator; diff --git a/packages/frontend/src/stdlib/analyses/decapodes.tsx b/packages/frontend/src/stdlib/analyses/decapodes.tsx index 80a37ac22..9832bda19 100644 --- a/packages/frontend/src/stdlib/analyses/decapodes.tsx +++ b/packages/frontend/src/stdlib/analyses/decapodes.tsx @@ -313,14 +313,14 @@ const makeSimulationCode = (data: SimulationData) => # needed for returning large amounts of data, should be paired with a similar setting on the jupyter server IJulia.set_max_stdio(1_000_000_000) - system = Analysis(ThDecapode(), raw"""${JSON.stringify(data)}"""); - simulator = evalsim(system.pode); + simulation = DecapodeSimulation(raw"""${JSON.stringify(data)}"""); + simulator = evalsim(simulation.pode); - f = simulator(system.geometry.dualmesh, system.generate, DiagonalHodge()); + f = simulator(simulation.geometry.dualmesh, simulation.generate, DiagonalHodge()); - soln = run_sim(f, system.init, system.duration, ComponentArray(k=0.5,)); + result = run(f, simulation, ComponentArray(k=0.5,)) - JSON3.write(stdout, SimResult(soln, system)) + JSON3.write(stdout, result) `; /** Create data to send to the Julia kernel. */ diff --git a/packages/frontend/src/stdlib/analyses/tabular_view.css b/packages/frontend/src/stdlib/analyses/tabular_view.css new file mode 100644 index 000000000..00634c4fb --- /dev/null +++ b/packages/frontend/src/stdlib/analyses/tabular_view.css @@ -0,0 +1,4 @@ +.tabular-view-table { + border: 1px solid black; + border-collapse: collapse; +} diff --git a/packages/frontend/src/stdlib/analyses/tabular_view.tsx b/packages/frontend/src/stdlib/analyses/tabular_view.tsx new file mode 100644 index 000000000..5d889fff1 --- /dev/null +++ b/packages/frontend/src/stdlib/analyses/tabular_view.tsx @@ -0,0 +1,139 @@ +import { createResource, For, Match, Switch } from "solid-js"; + +import { PanelHeader, Spinner } from "catcolab-ui-components"; +import type { DblModel } from "catlog-wasm"; +import type { DiagramAnalysisProps } from "../../analysis"; +import type { GraphLayoutConfig } from "../../visualization"; +import "./tabular_view.css"; + +/** Create a table from row-wise data */ +function createTable(headers: Array, data: Array>) { + return ( + + {headers && ( + + + + {(header) => } + + + + )} + + + {(row) => ( + + + {(cell) => } + + + )} + + +
{header}
{cell}
+ ); +} + +/** Given a schema (DblModel of ThSchema), a JSON output `rawdata` from Catlab, + and a particular object `obname` in the schema, create an HTML table with +*/ +function createACSetTable(model: DblModel, rawdata: object, obname: string) { + // The primary key of this table is given by `rawdata[obname]` + const rows: Array = rawdata[obname as keyof typeof rawdata]; + + // Get the homs and attrs with source `obname` + const outhoms = model + .morGenerators() + .filter( + (m) => + obname === + model + .obGeneratorLabel(model.morPresentation(m)?.dom.content.toString() || "") + ?.toString(), + ); + + // Convert morgenerators to user-friendly names + const headers = [obname].concat( + outhoms.map((m) => model.morGeneratorLabel(m)?.toString() || ""), + ); + + // Data for column from indexing rawdata + const columnardata: Array> = headers.map( + (m: string) => rawdata[m as keyof typeof rawdata] || [""], + ); + + // Convert columnar data to row data + const data = Array.from(rows.keys()).map((colIndex) => + columnardata.map((row) => row[colIndex] || ""), + ); + + return createTable(headers, data); +} + +/** Stack tables on top of each other in a naive way, one per ob/attrtype */ +function createACSet(model: DblModel, rawdata: object) { + return ( +
+ + + {(ob) => + createACSetTable(model, rawdata, model.obGeneratorLabel(ob)?.toString() || "") + } + +
+ ); +} + +/** Visualize a diagram in a model of ThSchema as a collection of tables. + +Such a visualization makes sense for any discrete double theory and is in +general restricted to basic objects. See `ModelGraph` for more. + */ +export default function TabularView( + props: DiagramAnalysisProps & { + title?: string; + }, +) { + const [res] = createResource( + () => { + const model = props.liveDiagram.liveModel.elaboratedModel(); + const diagram = props.liveDiagram.elaboratedDiagram(); + return model && diagram && [model, diagram]; + }, + + async ([model, diagram]) => { + const response = await fetch("http://127.0.0.1:8080/acsetcolim", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + model: model?.presentation(), + diagram: diagram?.presentation(), + }), + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + return response.json(); + }, + ); + const model = props.liveDiagram.liveModel.elaboratedModel(); + if (model === undefined) { + throw "Bad model"; + } + return ( + + + +
⏳ Loading model...
+
+ +
❌ Error loading model: {res.error?.message || "Unknown error"}
+
+ {(data) =>
{createACSet(model, data())}
}
+
+ ); +} diff --git a/packages/frontend/src/stdlib/theories/simple-schema.ts b/packages/frontend/src/stdlib/theories/simple-schema.ts index c587f395a..9d5701402 100644 --- a/packages/frontend/src/stdlib/theories/simple-schema.ts +++ b/packages/frontend/src/stdlib/theories/simple-schema.ts @@ -118,6 +118,12 @@ export default function createSchemaTheory(theoryMeta: TheoryMeta): Theory { description: "Visualize the instance as a graph", help: "visualization", }), + analyses.tabularView({ + id: "tabularview", + name: "Tabular Visualization", + description: "Visualize the instance as a table", + help: "tabularview", + }), ], }); }