DARPA-ASKEM / Model-Representations

Modeling framework representations for ASKEM
https://darpa-askem.github.io/Model-Representations/
8 stars 2 forks source link

ENH: first stab at Decapodes AMR #54

Closed jpfairbanks closed 1 year ago

jpfairbanks commented 1 year ago

This uses PR #50 and requires a patch to decapodes https://github.com/AlgebraicJulia/Decapodes.jl/pull/132.

{
  "header": {
    "name": "diffusion",
    "schema": "modelreps.io/DEC",
    "description": "The diffusion equation in DEC",
    "schema_name": "DEC",
    "model_version": "v1.0"
  },
  "model": {
    "judgements": [
      {
        "var": {"name": "X"},
        "dim": "Form0",
        "space": "Point"},
      {
        "var": {"name": "V"},
        "dim": "Form0",
        "space": "Point"},
      {
        "var": {"name": "k"},
        "dim": "Constant",
        "space": "Point"}
    ],
    "equations": [
      {
        "lhs": {"var": {"name": "X"}},
        "rhs": {"name": "V"}},
      {
        "lhs": {"var": {"name": "V"}},
        "rhs": {
          "args": [
            {"name": "-1"},
            {"name": "k"},
            {"name": "X"}]}}]}}
jpfairbanks commented 1 year ago

The judgements are where you declare variables, then the equations are where you declare equations in those variables. The judgements tell you the types of each variable including the dimension and space over which it is defined.

jpfairbanks commented 1 year ago

Just realized I named the model diffusion, but it is harmonic oscillator

jpfairbanks commented 1 year ago

Updated some field names

{
  "header": {
    "name": "harmonic_oscillator",
    "schema": "modelreps.io/DecaExpr",
    "description": "A Simple Harmonic Oscillator as a Diagrammatic Equation",
    "schema_name": "DecaExpr",
    "model_version": "v1.0"
  },
  "model": {
    "context": [
      {
        "var": {
          "name": "X"
        },
        "dim": "Form0",
        "space": "Point"
      },
      {
        "var": {
          "name": "V"
        },
        "dim": "Form0",
        "space": "Point"
      },
      {
        "var": {
          "name": "k"
        },
        "dim": "Constant",
        "space": "Point"
      }
    ],
    "equations": [
      {
        "lhs": {
          "var": {
            "name": "X"
          }
        },
        "rhs": {
          "name": "V"
        }
      },
      {
        "lhs": {
          "var": {
            "name": "V"
          }
        },
        "rhs": {
          "args": [
            {
              "name": "-1"
            },
            {
              "name": "k"
            },
            {
              "name": "X"
            }
          ]
        }
      }
    ]
  }
}

Combinatorial Representation of the model is

{
  "Var": [
    {
      "_id": 1,
      "type": "Form0",
      "name": "X"
    },
    {
      "_id": 2,
      "type": "Form0",
      "name": "Ẋ"
    },
    {
      "_id": 3,
      "type": "Constant",
      "name": "k"
    },
    {
      "_id": 4,
      "type": "infer",
      "name": "mult_1"
    },
    {
      "_id": 5,
      "type": "infer",
      "name": "Ẋ̇"
    },
    {
      "_id": 6,
      "type": "Literal",
      "name": "-1"
    }
  ],
  "TVar": [
    {
      "_id": 1,
      "incl": 2
    },
    {
      "_id": 2,
      "incl": 5
    }
  ],
  "Op1": [
    {
      "_id": 1,
      "src": 1,
      "tgt": 2,
      "op1": "∂ₜ"
    },
    {
      "_id": 2,
      "src": 2,
      "tgt": 5,
      "op1": "∂ₜ"
    }
  ],
  "Op2": [
    {
      "_id": 1,
      "proj1": 6,
      "proj2": 3,
      "res": 4,
      "op2": "*"
    },
    {
      "_id": 2,
      "proj1": 4,
      "proj2": 1,
      "res": 5,
      "op2": "*"
    }
  ],
  "Σ": [],
  "Summand": [],
  "Type": [],
  "Operator": [],
  "Name": []
}

I think we should probably support both the Syntactic and Combinatorial forms. Because some parts of the software will be easier to write with each representation.

jpfairbanks commented 1 year ago

The relevant parts of the Decapodes Source Code are:

DecaExpr definitions: https://github.com/AlgebraicJulia/Decapodes.jl/blob/a19e268808a657360b8e6b502cbad866d5c5222f/src/language.jl#L6

Schemas for the combinatorial representaions: https://github.com/AlgebraicJulia/Decapodes.jl/blob/a19e268808a657360b8e6b502cbad866d5c5222f/src/decapodeacset.jl#L6 and https://github.com/AlgebraicJulia/Decapodes.jl/blob/a19e268808a657360b8e6b502cbad866d5c5222f/src/decapodeacset.jl#L113

YohannParis commented 1 year ago
  1. Could we not use short forms of names? for example:

    • var instead of variable
    • dim instead of dimensions
  2. Can we remove the header property and just put its content at the root level like other AMR?

  3. Also this schema is missing id for each of the context.var

jpfairbanks commented 1 year ago

I have added a UWD example.

Given a relation macro

@relation (x:X, z:Z) where y:Y begin
  R(x,y)
  S(y,z)
  T(z,y,u)
end

image

The UWD is given by the following database:

Catlab.Programs.RelationalPrograms.TypedUnnamedRelationDiagram{Symbol, Symbol, Symbol} with elements Box = 1:3, Port = 1:7, OuterPort = 1:2, Junction = 1:4, Type = 1:0, Name = 1:0, VarName = 1:0
┌─────┬──────┐
│ Box │ name │
├─────┼──────┤
│   1 │    R │
│   2 │    S │
│   3 │    T │
└─────┴──────┘
┌──────┬─────┬──────────┬───────────┐
│ Port │ box │ junction │ port_type │
├──────┼─────┼──────────┼───────────┤
│    1 │   1 │        1 │         X │
│    2 │   1 │        3 │         Y │
│    3 │   2 │        3 │         Y │
│    4 │   2 │        2 │         Z │
│    5 │   3 │        2 │         Z │
│    6 │   3 │        3 │         Y │
│    7 │   3 │        4 │   untyped │
└──────┴─────┴──────────┴───────────┘
┌───────────┬────────────────┬─────────────────┐
│ OuterPort │ outer_junction │ outer_port_type │
├───────────┼────────────────┼─────────────────┤
│         1 │              1 │               x │
│         2 │              2 │               z │
└───────────┴────────────────┴─────────────────┘
┌──────────┬───────────────┬──────────┐
│ Junction │ junction_type │ variable │
├──────────┼───────────────┼──────────┤
│        1 │             X │        x │
│        2 │             Z │        z │
│        3 │             Y │        y │
│        4 │       untyped │        u │
└──────────┴───────────────┴──────────┘

The expression that creates it is serialized as:

{
  "context": [
    {
      "var": "x",
      "type": "X"
    },
    {
      "var": "z",
      "type": "Z"
    }
  ],
  "statements": [
    {
      "relation": "R",
      "args": [
        {
          "var": "x",
          "type": "X"
        },
        {
          "var": "y",
          "type": "Y"
        }
      ]
    },
    {
      "relation": "S",
      "args": [
        {
          "var": "y",
          "type": "Y"
        },
        {
          "var": "z",
          "type": "Z"
        }
      ]
    },
    {
      "relation": "T",
      "args": [
        {
          "var": "z",
          "type": "Z"
        },
        {
          "var": "y",
          "type": "Y"
        },
        {
          "var": "u"
        }
      ]
    }
  ]
}
jpfairbanks commented 1 year ago

Take a look at src/julia/composite_models_examples.jl for an example of building a composite model in AMR.

jpfairbanks commented 1 year ago

If this were a real julia package, some of the horrific namespacing would go away.

jpfairbanks commented 1 year ago

The composite model is:


Decapodes.SummationDecapode{Any, Any, Symbol} with elements Var = 1:14, TVar = 1:3, Op1 = 1:4, Op2 = 1:4, Σ = 1:1, Summand = 1:2, Type = 1:0, Operator = 1:0, Name = 1:0
┌─────┬───────────┬───────────────────┐
│ Var │      type │              name │
├─────┼───────────┼───────────────────┤
│   1 │     Form0 │                 X │
│   2 │     Form0 │                 V │
│   3 │  Constant │      oscillator_k │
│   4 │     infer │ oscillator_mult_1 │
│   5 │     infer │      oscillator_Ẋ̇ │
│   6 │   Literal │                -1 │
│   7 │     Form0 │                 Q │
│   8 │  Constant │         heating_κ │
│   9 │  Constant │         heating_λ │
│  10 │ Parameter │        heating_Q₀ │
│  11 │     infer │         heating_Q̇ │
│  12 │     infer │        heating_•2 │
│  13 │     infer │        heating_•3 │
│  14 │     infer │        heating_•4 │
└─────┴───────────┴───────────────────┘
┌──────┬──────┐
│ TVar │ incl │
├──────┼──────┤
│    1 │    2 │
│    2 │    5 │
│    3 │   11 │
└──────┴──────┘
┌─────┬─────┬─────┬─────┐
│ Op1 │ src │ tgt │ op1 │
├─────┼─────┼─────┼─────┤
│   1 │   1 │   2 │  ∂ₜ │
│   2 │   2 │   5 │  ∂ₜ │
│   3 │   7 │  11 │  ∂ₜ │
│   4 │  14 │  13 │   λ │
└─────┴─────┴─────┴─────┘
┌─────┬───────┬───────┬─────┬─────┐
│ Op2 │ proj1 │ proj2 │ res │ op2 │
├─────┼───────┼───────┼─────┼─────┤
│   1 │     6 │     3 │   4 │   * │
│   2 │     4 │     1 │   5 │   * │
│   3 │     8 │     2 │  12 │   * │
│   4 │     7 │    10 │  14 │   - │
└─────┴───────┴───────┴─────┴─────┘
┌───┬─────┐
│ Σ │ sum │
├───┼─────┤
│ 1 │  11 │
└───┴─────┘
┌─────────┬─────────┬───────────┐
│ Summand │ summand │ summation │
├─────────┼─────────┼───────────┤
│       1 │      12 │         1 │
│       2 │      13 │         1 │
└─────────┴─────────┴───────────┘
jpfairbanks commented 1 year ago

json.zip

jpfairbanks commented 1 year ago

Made some progress today:

{
    "header": {
        "description": "A Simple Harmonic Oscillator as a Diagrammatic Equation",
        "name": "harmonic_oscillator",
        "_type": "Header",
        "model_version": "v1.0",
        "schema": "modelreps.io/DecaExpr",
        "schema_name": "DecaExpr"
    },
    "_type": "ASKEMDecaExpr",
    "model": {
        "context": [
            {
                "dim": "Form0",
                "var": {
                    "name": "X",
                    "_type": "Var"
                },
                "space": "Point",
                "_type": "Judgement"
            },
            {
                "dim": "Form0",
                "var": {
                    "name": "V",
                    "_type": "Var"
                },
                "space": "Point",
                "_type": "Judgement"
            },
            {
                "dim": "Constant",
                "var": {
                    "name": "k",
                    "_type": "Var"
                },
                "space": "Point",
                "_type": "Judgement"
            }
        ],
        "_type": "Decapodes.DecaExpr",
        "equations": [
            {
                "rhs": {
                    "name": "V",
                    "_type": "Var"
                },
                "lhs": {
                    "var": {
                        "name": "X",
                        "_type": "Var"
                    },
                    "_type": "Tan"
                },
                "_type": "Eq"
            },
            {
                "rhs": {
                    "args": [
                        {
                            "name": "-1",
                            "_type": "Decapodes.Lit"
                        },
                        {
                            "name": "k",
                            "_type": "Var"
                        },
                        {
                            "name": "X",
                            "_type": "Var"
                        }
                    ],
                    "_type": "Decapodes.Mult"
                },
                "lhs": {
                    "var": {
                        "name": "V",
                        "_type": "Var"
                    },
                    "_type": "Tan"
                },
                "_type": "Eq"
            }
        ]
    }
}
jpfairbanks commented 1 year ago

Current status is that the UWDs, Decapodes, and Composite models are all serializable and deserializable. The current definition of correctness for serialization is that write, read, write == write.

Here is the example of a nested hierarchical model:

{
    "components": [
        {
            "interface": [
                "X",
                "Ẋ"
            ],
            "_type": "OpenModel",
            "model": {
                "header": {
                    "description": "A Simple Harmonic Oscillator as a Diagrammatic Equation",
                    "name": "harmonic_oscillator",
                    "_type": "Header",
                    "model_version": "v1.0",
                    "schema": "modelreps.io/DecaExpr",
                    "schema_name": "DecaExpr"
                },
                "_type": "ASKEMDecaExpr",
                "model": {
                    "context": [
                        {
                            "dim": "Form0",
                            "var": {
                                "name": "X",
                                "_type": "Var"
                            },
                            "space": "Point",
                            "_type": "Judgement"
                        },
                        {
                            "dim": "Form0",
                            "var": {
                                "name": "V",
                                "_type": "Var"
                            },
                            "space": "Point",
                            "_type": "Judgement"
                        },
                        {
                            "dim": "Constant",
                            "var": {
                                "name": "k",
                                "_type": "Var"
                            },
                            "space": "Point",
                            "_type": "Judgement"
                        }
                    ],
                    "_type": "DecaExpr",
                    "equations": [
                        {
                            "rhs": {
                                "name": "V",
                                "_type": "Var"
                            },
                            "lhs": {
                                "var": {
                                    "name": "X",
                                    "_type": "Var"
                                },
                                "_type": "Tan"
                            },
                            "_type": "Eq"
                        },
                        {
                            "rhs": {
                                "args": [
                                    {
                                        "name": "-1",
                                        "_type": "Lit"
                                    },
                                    {
                                        "name": "k",
                                        "_type": "Var"
                                    },
                                    {
                                        "name": "X",
                                        "_type": "Var"
                                    }
                                ],
                                "_type": "Mult"
                            },
                            "lhs": {
                                "var": {
                                    "name": "V",
                                    "_type": "Var"
                                },
                                "_type": "Tan"
                            },
                            "_type": "Eq"
                        }
                    ]
                }
            }
        },
        {
            "components": [
                {
                    "interface": [
                        "V",
                        "Q₊"
                    ],
                    "_type": "OpenModel",
                    "model": {
                        "header": {
                            "description": "velocity makes it get hot",
                            "name": "DragHeat",
                            "_type": "Header",
                            "model_version": "v1.0",
                            "schema": "modelreps.io/SummationDecapode",
                            "schema_name": "SummationDecapode"
                        },
                        "_type": "ASKEMDecaExpr",
                        "model": {
                            "context": [
                                {
                                    "dim": "Form0",
                                    "var": {
                                        "name": "V",
                                        "_type": "Var"
                                    },
                                    "space": "Point",
                                    "_type": "Judgement"
                                },
                                {
                                    "dim": "Form0",
                                    "var": {
                                        "name": "Q₊",
                                        "_type": "Var"
                                    },
                                    "space": "Point",
                                    "_type": "Judgement"
                                },
                                {
                                    "dim": "Constant",
                                    "var": {
                                        "name": "κ",
                                        "_type": "Var"
                                    },
                                    "space": "Point",
                                    "_type": "Judgement"
                                }
                            ],
                            "_type": "DecaExpr",
                            "equations": [
                                {
                                    "rhs": {
                                        "f": "*",
                                        "arg1": {
                                            "name": "κ",
                                            "_type": "Var"
                                        },
                                        "_type": "App2",
                                        "arg2": {
                                            "name": "V",
                                            "_type": "Var"
                                        }
                                    },
                                    "lhs": {
                                        "name": "Q₊",
                                        "_type": "Var"
                                    },
                                    "_type": "Eq"
                                }
                            ]
                        }
                    }
                },
                {
                    "interface": [
                        "Q₋",
                        "Q"
                    ],
                    "_type": "OpenModel",
                    "model": {
                        "header": {
                            "description": "heat dissipates to the enviornment",
                            "name": "NetwonCooling",
                            "_type": "Header",
                            "model_version": "v1.0",
                            "schema": "modelreps.io/SummationDecapode",
                            "schema_name": "SummationDecapode"
                        },
                        "_type": "ASKEMDecaExpr",
                        "model": {
                            "context": [
                                {
                                    "dim": "Form0",
                                    "var": {
                                        "name": "Q₋",
                                        "_type": "Var"
                                    },
                                    "space": "Point",
                                    "_type": "Judgement"
                                },
                                {
                                    "dim": "Parameter",
                                    "var": {
                                        "name": "Q₀",
                                        "_type": "Var"
                                    },
                                    "space": "Point",
                                    "_type": "Judgement"
                                },
                                {
                                    "dim": "Form0",
                                    "var": {
                                        "name": "Q",
                                        "_type": "Var"
                                    },
                                    "space": "Point",
                                    "_type": "Judgement"
                                },
                                {
                                    "dim": "Constant",
                                    "var": {
                                        "name": "λ",
                                        "_type": "Var"
                                    },
                                    "space": "Point",
                                    "_type": "Judgement"
                                }
                            ],
                            "_type": "DecaExpr",
                            "equations": [
                                {
                                    "rhs": {
                                        "f": "λ",
                                        "arg": {
                                            "f": "-",
                                            "arg1": {
                                                "name": "Q",
                                                "_type": "Var"
                                            },
                                            "_type": "App2",
                                            "arg2": {
                                                "name": "Q₀",
                                                "_type": "Var"
                                            }
                                        },
                                        "_type": "App1"
                                    },
                                    "lhs": {
                                        "name": "Q₋",
                                        "_type": "Var"
                                    },
                                    "_type": "Eq"
                                }
                            ]
                        }
                    }
                },
                {
                    "interface": [
                        "X",
                        "Y",
                        "T"
                    ],
                    "_type": "OpenModel",
                    "model": {
                        "header": {
                            "description": "variables be addin",
                            "name": "LinearSuperpositon",
                            "_type": "Header",
                            "model_version": "v1.0",
                            "schema": "modelreps.io/SummationDecapode",
                            "schema_name": "SummationDecapode"
                        },
                        "_type": "ASKEMDecaExpr",
                        "model": {
                            "context": [
                                {
                                    "dim": "Form0",
                                    "var": {
                                        "name": "X",
                                        "_type": "Var"
                                    },
                                    "space": "Point",
                                    "_type": "Judgement"
                                },
                                {
                                    "dim": "Form0",
                                    "var": {
                                        "name": "Y",
                                        "_type": "Var"
                                    },
                                    "space": "Point",
                                    "_type": "Judgement"
                                },
                                {
                                    "dim": "Form0",
                                    "var": {
                                        "name": "T",
                                        "_type": "Var"
                                    },
                                    "space": "Point",
                                    "_type": "Judgement"
                                }
                            ],
                            "_type": "DecaExpr",
                            "equations": [
                                {
                                    "rhs": {
                                        "args": [
                                            {
                                                "name": "X",
                                                "_type": "Var"
                                            },
                                            {
                                                "name": "Y",
                                                "_type": "Var"
                                            }
                                        ],
                                        "_type": "Plus"
                                    },
                                    "lhs": {
                                        "name": "T",
                                        "_type": "Var"
                                    },
                                    "_type": "Eq"
                                }
                            ]
                        }
                    }
                }
            ],
            "composition_pattern": {
                "statements": [
                    {
                        "variables": [
                            {
                                "var": "V",
                                "type": "Form0",
                                "_type": "Typed"
                            },
                            {
                                "var": "Q₊",
                                "_type": "Untyped"
                            }
                        ],
                        "_type": "Statement",
                        "relation": "drag"
                    },
                    {
                        "variables": [
                            {
                                "var": "Q₋",
                                "_type": "Untyped"
                            },
                            {
                                "var": "Q",
                                "type": "Form0",
                                "_type": "Typed"
                            }
                        ],
                        "_type": "Statement",
                        "relation": "cooling"
                    },
                    {
                        "variables": [
                            {
                                "var": "Q₊",
                                "_type": "Untyped"
                            },
                            {
                                "var": "Q₋",
                                "_type": "Untyped"
                            },
                            {
                                "var": "Q̇",
                                "_type": "Untyped"
                            }
                        ],
                        "_type": "Statement",
                        "relation": "superposition"
                    }
                ],
                "context": [
                    {
                        "var": "V",
                        "type": "Form0",
                        "_type": "Typed"
                    },
                    {
                        "var": "Q",
                        "type": "Form0",
                        "_type": "Typed"
                    }
                ],
                "_type": "UWDExpr"
            },
            "header": {
                "description": "A formula for heating - cooling",
                "name": "heating_dynamics",
                "_type": "Header",
                "model_version": "v0.1",
                "schema": "modelreps.io/Composite",
                "schema_name": "CompositeModelExpr"
            },
            "_type": "CompositeModelExpr"
        }
    ],
    "composition_pattern": {
        "statements": [
            {
                "variables": [
                    {
                        "var": "X",
                        "type": "Form0",
                        "_type": "Typed"
                    },
                    {
                        "var": "V",
                        "type": "Form0",
                        "_type": "Typed"
                    }
                ],
                "_type": "Statement",
                "relation": "oscillator"
            },
            {
                "variables": [
                    {
                        "var": "V",
                        "type": "Form0",
                        "_type": "Typed"
                    },
                    {
                        "var": "Q",
                        "type": "Form0",
                        "_type": "Typed"
                    }
                ],
                "_type": "Statement",
                "relation": "heating"
            }
        ],
        "context": [
            {
                "var": "X",
                "type": "Form0",
                "_type": "Typed"
            },
            {
                "var": "Q",
                "type": "Form0",
                "_type": "Typed"
            }
        ],
        "_type": "UWDExpr"
    },
    "header": {
        "description": "A hierarchical composite model of frictional heating",
        "name": "hierarchical_composite",
        "_type": "Header",
        "model_version": "v0.1",
        "schema": "modelreps.io/Composite",
        "schema_name": "CompositeModelExpr"
    },
    "_type": "CompositeModelExpr"
}
jpfairbanks commented 1 year ago

I pulled out all the data definitions from all the files using awk

The types used in the Decapodes part are

@data CompositeModel <: AbstractTerm begin
  OpenModel(model::ASKEMDecapodes.ASKEMDecaExpr, interface::Vector{Symbol})
  OpenDecapode(model::ASKEMDecapodes.ASKEMDecapode, interface::Vector{Symbol})
  CompositeModelExpr(header::Header, composition_pattern::UWDExpr, components::Vector{CompositeModel})
end

@data ASKEMDeca <: AbstractTerm begin
  ASKEMDecaExpr(header::AMR.Header, model::Decapodes.DecaExpr)
  ASKEMDecapode(header::AMR.Header, model::Decapodes.SummationDecapode)
end

@data Var <: AbstractTerm begin
  Untyped(var::Symbol)
  Typed(var::Symbol, type::Symbol)
end

@data UWDTerm <: AbstractTerm begin
  Statement(relation::Symbol, variables::Vector{Var})
  UWDExpr(context::Vector{Var}, statements::Vector{Statement})
  UWDModel(header::AMR.Header, uwd::UWDExpr)
end

@as_record struct Header <: AbstractTerm
  name::String
  schema::String
  description::String
  schema_name::String
  model_version::String
end

And from Decapodes they are

@data Term begin
  Var(name::Symbol)
  Lit(name::Symbol)
  Judgement(var::Var, dim::Symbol, space::Symbol)
  AppCirc1(fs::Vector{Symbol}, arg::Term)
  App1(f::Symbol, arg::Term)
  App2(f::Symbol, arg1::Term, arg2::Term)
  Plus(args::Vector{Term})
  Mult(args::Vector{Term})
  Tan(var::Term)
end

@data Equation begin
  Eq(lhs::Term, rhs::Term)
end

@as_record struct DecaExpr
  context::Vector{Judgement}
  equations::Vector{Equation}
end

So these are all the types you would need to implement in order to properly process a model.

jpfairbanks commented 1 year ago

This PR has moved to its own package https://github.com/AlgebraicJulia/SyntacticModels.jl please provide feedback on issues on that repo.

bgyori commented 1 year ago

Should the JSON examples that were part of this original PR still be added under multiphysics/examples in a new PR? We could also work on creating (ideally generating automatically from the implementation) a JSON schema for validation purposes.