-
-
Notifications
You must be signed in to change notification settings - Fork 213
/
Copy pathsearch_index.js
3 lines (3 loc) · 148 KB
/
search_index.js
1
2
3
var documenterSearchIndex = {"docs":
[{"location":"tutorials/ode_modeling/#Component-Based-Modeling-with-Ordinary-Differential-Equations-1","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Component-Based Modeling with Ordinary Differential Equations","text":"","category":"section"},{"location":"tutorials/ode_modeling/#Copy-Paste-Example-1","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Copy-Paste Example","text":"","category":"section"},{"location":"tutorials/ode_modeling/#","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Component-Based Modeling with Ordinary Differential Equations","text":"Here is the complete example, with explanation to follow:","category":"page"},{"location":"tutorials/ode_modeling/#","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Component-Based Modeling with Ordinary Differential Equations","text":"using ModelingToolkit, OrdinaryDiffEq\r\n\r\n@parameters t σ ρ β\r\n@variables x(t) y(t) z(t)\r\n@derivatives D'~t\r\n\r\neqs = [D(x) ~ σ*(y-x),\r\n D(y) ~ x*(ρ-z)-y,\r\n D(z) ~ x*y - β*z]\r\n\r\nlorenz1 = ODESystem(eqs,name=:lorenz1)\r\nlorenz2 = ODESystem(eqs,name=:lorenz2)\r\n\r\n@variables a\r\n@parameters γ\r\nconnections = [0 ~ lorenz1.x + lorenz2.y + a*γ]\r\nconnected = ODESystem(connections,t,[a],[γ],systems=[lorenz1,lorenz2])\r\n\r\nu0 = [lorenz1.x => 1.0,\r\n lorenz1.y => 0.0,\r\n lorenz1.z => 0.0,\r\n lorenz2.x => 0.0,\r\n lorenz2.y => 1.0,\r\n lorenz2.z => 0.0,\r\n a => 2.0]\r\n\r\np = [lorenz1.σ => 10.0,\r\n lorenz1.ρ => 28.0,\r\n lorenz1.β => 8/3,\r\n lorenz2.σ => 10.0,\r\n lorenz2.ρ => 28.0,\r\n lorenz2.β => 8/3,\r\n γ => 2.0]\r\n\r\ntspan = (0.0,100.0)\r\nprob = ODEProblem(connected,u0,tspan,p)\r\nsol = solve(prob,Rodas5())\r\n\r\nusing Plots; plot(sol,vars=(a,lorenz1.x,lorenz2.z))","category":"page"},{"location":"tutorials/ode_modeling/#Generating-ODESystems-1","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Generating ODESystems","text":"","category":"section"},{"location":"tutorials/ode_modeling/#","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Component-Based Modeling with Ordinary Differential Equations","text":"First let's build an ODE model. To do this we start by defining some variables. In a differential equation system, we need to differentiate between our (dependent) variables and parameters. Therefore, we label them as follows:","category":"page"},{"location":"tutorials/ode_modeling/#","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Component-Based Modeling with Ordinary Differential Equations","text":"using ModelingToolkit\r\n\r\n@parameters t σ ρ β\r\n@variables x(t) y(t) z(t)\r\n@derivatives D'~t","category":"page"},{"location":"tutorials/ode_modeling/#","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Component-Based Modeling with Ordinary Differential Equations","text":"Then we build the system:","category":"page"},{"location":"tutorials/ode_modeling/#","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Component-Based Modeling with Ordinary Differential Equations","text":"eqs = [D(x) ~ σ*(y-x),\r\n D(y) ~ x*(ρ-z)-y,\r\n D(z) ~ x*y - β*z]","category":"page"},{"location":"tutorials/ode_modeling/#","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Component-Based Modeling with Ordinary Differential Equations","text":"Each operation builds an Term type, and thus eqs is an array of Term and Syms (possibly wrapped in Num). This holds a tree of the full system that can be analyzed by other programs. We can turn this into a ODESystem via:","category":"page"},{"location":"tutorials/ode_modeling/#","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Component-Based Modeling with Ordinary Differential Equations","text":"sys = ODESystem(eqs)","category":"page"},{"location":"tutorials/ode_modeling/#","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Component-Based Modeling with Ordinary Differential Equations","text":"This ODESystem can then be used to generate an ODEProblem by supplying the constructor with a map from the states of the system to their initial condition values and from the parameters of the system to their values. For example:","category":"page"},{"location":"tutorials/ode_modeling/#","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Component-Based Modeling with Ordinary Differential Equations","text":"u0 = [x => 1.0\r\n y => 0.0\r\n z => 0.0]\r\n\r\np = [σ => 10.0\r\n ρ => 28.0\r\n β => 8/3]\r\ntspan = (0.0,100.0)\r\nprob = ODEProblem(sys,u0,tspan,p;jac=true,sparse=true)","category":"page"},{"location":"tutorials/ode_modeling/#","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Component-Based Modeling with Ordinary Differential Equations","text":"Note that the additional jac=true tells the system to symbolically generate an optimized Jacobian function to enhance the differential equation solvers, and sparse tells it to build the ODEProblem with all of the enhancements setup for sparse Jacobians.","category":"page"},{"location":"tutorials/ode_modeling/#Building-Component-Based-Models-1","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Building Component-Based Models","text":"","category":"section"},{"location":"tutorials/ode_modeling/#","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Component-Based Modeling with Ordinary Differential Equations","text":"Now let's use ModelingToolkit to start building component-based models. Component-based models are compositions between submodels. This allows one to keep independently generated libraries of components intact and use them as the building blocks to construct more complicated models.","category":"page"},{"location":"tutorials/ode_modeling/#","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Component-Based Modeling with Ordinary Differential Equations","text":"Let's define two interacting Lorenz equations. To do this, we will build two ODESystems from the equations we used in the first part:","category":"page"},{"location":"tutorials/ode_modeling/#","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Component-Based Modeling with Ordinary Differential Equations","text":"lorenz1 = ODESystem(eqs,name=:lorenz1)\r\nlorenz2 = ODESystem(eqs,name=:lorenz2)","category":"page"},{"location":"tutorials/ode_modeling/#","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Component-Based Modeling with Ordinary Differential Equations","text":"Now let's define an interconnection between these ODE systems. Here we will define a new variable α which is defined by the interplay between these two models:","category":"page"},{"location":"tutorials/ode_modeling/#","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Component-Based Modeling with Ordinary Differential Equations","text":"@variables a(t)\r\n@parameters γ\r\nconnections = [0 ~ lorenz1.x + lorenz2.y + a*γ]\r\nconnected = ODESystem(connections,t,[a],[γ],systems=[lorenz1,lorenz2])","category":"page"},{"location":"tutorials/ode_modeling/#","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Component-Based Modeling with Ordinary Differential Equations","text":"This ODESystem thus connects the two Lorenz systems and defines the dynamics of α according to the continuous algebraic equation, thus this is now a differential-algebraic equation (DAE) of 7 variables. We can then define the resulting ODEProblem and send it over to DifferentialEquations.jl:","category":"page"},{"location":"tutorials/ode_modeling/#","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Component-Based Modeling with Ordinary Differential Equations","text":"u0 = [lorenz1.x => 1.0,\r\n lorenz1.y => 0.0,\r\n lorenz1.z => 0.0,\r\n lorenz2.x => 0.0,\r\n lorenz2.y => 1.0,\r\n lorenz2.z => 0.0,\r\n a => 2.0]\r\n\r\np = [lorenz1.σ => 10.0,\r\n lorenz1.ρ => 28.0,\r\n lorenz1.β => 8/3,\r\n lorenz2.σ => 10.0,\r\n lorenz2.ρ => 28.0,\r\n lorenz2.β => 8/3,\r\n γ => 2.0]\r\n\r\ntspan = (0.0,100.0)\r\nprob = ODEProblem(connected,u0,tspan,p)\r\nsol = solve(prob,Rodas5())\r\n\r\nusing Plots; plot(sol,vars=(a,lorenz1.x,lorenz2.z))","category":"page"},{"location":"tutorials/ode_modeling/#","page":"Component-Based Modeling with Ordinary Differential Equations","title":"Component-Based Modeling with Ordinary Differential Equations","text":"(Image: )","category":"page"},{"location":"systems/ReactionSystem/#ReactionSystem-1","page":"ReactionSystem","title":"ReactionSystem","text":"","category":"section"},{"location":"systems/ReactionSystem/#","page":"ReactionSystem","title":"ReactionSystem","text":"A ReactionSystem represents a system of chemical reactions. Conversions are provided to generate corresponding chemical reaction ODE models, chemical Langevin equation SDE models, and stochastic chemical kinetics jump process models. As a simple example, the code below creates a SIR model, and solves the corresponding ODE, SDE, and jump process models.","category":"page"},{"location":"systems/ReactionSystem/#","page":"ReactionSystem","title":"ReactionSystem","text":"using ModelingToolkit, OrdinaryDiffEq, StochasticDiffEq, DiffEqJump\r\n@parameters β γ t\r\n@variables S(t) I(t) R(t)\r\n\r\nrxs = [Reaction(β, [S,I], [I], [1,1], [2])\r\n Reaction(γ, [I], [R])]\r\nrs = ReactionSystem(rxs, t, [S,I,R], [β,γ])\r\n\r\nu₀map = [S => 999.0, I => 1.0, R => 0.0]\r\nparammap = [β => 1/10000, γ => 0.01]\r\ntspan = (0.0, 250.0)\r\n\r\n# solve as ODEs\r\nodesys = convert(ODESystem, rs)\r\noprob = ODEProblem(odesys, u₀map, tspan, parammap)\r\nsol = solve(oprob, Tsit5())\r\n\r\n# solve as SDEs\r\nsdesys = convert(SDESystem, rs)\r\nsprob = SDEProblem(sdesys, u₀map, tspan, parammap)\r\nsol = solve(sprob, EM(), dt=.01)\r\n\r\n# solve as jump process\r\njumpsys = convert(JumpSystem, rs)\r\nu₀map = [S => 999, I => 1, R => 0]\r\ndprob = DiscreteProblem(jumpsys, u₀map, tspan, parammap)\r\njprob = JumpProblem(jumpsys, dprob, Direct())\r\nsol = solve(jprob, SSAStepper())","category":"page"},{"location":"systems/ReactionSystem/#System-Constructors-1","page":"ReactionSystem","title":"System Constructors","text":"","category":"section"},{"location":"systems/ReactionSystem/#","page":"ReactionSystem","title":"ReactionSystem","text":"Reaction\r\nReactionSystem","category":"page"},{"location":"systems/ReactionSystem/#ModelingToolkit.Reaction","page":"ReactionSystem","title":"ModelingToolkit.Reaction","text":"struct Reaction{S, T<:Number}\n\nOne chemical reaction.\n\nFields\n\nrate\nThe rate function (excluding mass action terms).\nsubstrates\nReaction substrates.\nproducts\nReaction products.\nsubstoich\nThe stoichiometric coefficients of the reactants.\nprodstoich\nThe stoichiometric coefficients of the products.\nnetstoich\nThe net stoichiometric coefficients of all species changed by the reaction.\nonly_use_rate\nfalse (default) if rate should be multiplied by mass action terms to give the rate law. true if rate represents the full reaction rate law.\n\nExamples\n\nusing ModelingToolkit\n@parameters t k[1:20]\n@variables A(t) B(t) C(t) D(t)\nrxs = [Reaction(k[1], nothing, [A]), # 0 -> A\n Reaction(k[2], [B], nothing), # B -> 0\n Reaction(k[3],[A],[C]), # A -> C\n Reaction(k[4], [C], [A,B]), # C -> A + B\n Reaction(k[5], [C], [A], [1], [2]), # C -> A + A\n Reaction(k[6], [A,B], [C]), # A + B -> C\n Reaction(k[7], [B], [A], [2], [1]), # 2B -> A\n Reaction(k[8], [A,B], [A,C]), # A + B -> A + C\n Reaction(k[9], [A,B], [C,D]), # A + B -> C + D\n Reaction(k[10], [A], [C,D], [2], [1,1]), # 2A -> C + D\n Reaction(k[11], [A], [A,B], [2], [1,1]), # 2A -> A + B\n Reaction(k[12], [A,B,C], [C,D], [1,3,4], [2, 3]), # A+3B+4C -> 2C + 3D\n Reaction(k[13], [A,B], nothing, [3,1], nothing), # 3A+B -> 0\n Reaction(k[14], nothing, [A], nothing, [2]), # 0 -> 2A\n Reaction(k[15]*A/(2+A), [A], nothing; only_use_rate=true), # A -> 0 with custom rate\n Reaction(k[16], [A], [B]; only_use_rate=true), # A -> B with custom rate.\n Reaction(k[17]*A*exp(B), [C], [D], [2], [1]), # 2C -> D with non constant rate.\n Reaction(k[18]*B, nothing, [B], nothing, [2]), # 0 -> 2B with non constant rate.\n Reaction(k[19]*t, [A], [B]), # A -> B with non constant rate.\n Reaction(k[20]*t*A, [B,C], [D],[2,1],[2]) # 2A +B -> 2C with non constant rate.\n ]\n\nNotes:\n\nnothing can be used to indicate a reaction that has no reactants or no products. In this case the corresponding stoichiometry vector should also be set to nothing.\nThe three-argument form assumes all reactant and product stoichiometric coefficients are one.\n\n\n\n\n\n","category":"type"},{"location":"systems/ReactionSystem/#ModelingToolkit.ReactionSystem","page":"ReactionSystem","title":"ModelingToolkit.ReactionSystem","text":"struct ReactionSystem <: ModelingToolkit.AbstractSystem\n\nA system of chemical reactions.\n\nFields\n\neqs\nThe reactions defining the system.\niv\nIndependent variable (usually time).\nstates\nDependent (state) variables representing amount of each species.\nps\nParameter variables.\npins\nobserved\nname\nThe name of the system\nsystems\nsystems: The internal systems\n\nExample\n\nContinuing from the example in the Reaction definition:\n\nrs = ReactionSystem(rxs, t, [A,B,C,D], k)\n\n\n\n\n\n","category":"type"},{"location":"systems/ReactionSystem/#Composition-and-Accessor-Functions-1","page":"ReactionSystem","title":"Composition and Accessor Functions","text":"","category":"section"},{"location":"systems/ReactionSystem/#","page":"ReactionSystem","title":"ReactionSystem","text":"sys.eqs or equations(sys): The reactions that define the system.\nsys.states or states(sys): The set of chemical species in the system.\nsys.parameters or parameters(sys): The parameters of the system.\nsys.iv or independent_variable(sys): The independent variable of the reaction system, usually time.","category":"page"},{"location":"systems/ReactionSystem/#Query-Functions-1","page":"ReactionSystem","title":"Query Functions","text":"","category":"section"},{"location":"systems/ReactionSystem/#","page":"ReactionSystem","title":"ReactionSystem","text":"oderatelaw\r\njumpratelaw\r\nismassaction","category":"page"},{"location":"systems/ReactionSystem/#ModelingToolkit.oderatelaw","page":"ReactionSystem","title":"ModelingToolkit.oderatelaw","text":"oderatelaw(rx; combinatoric_ratelaw=true)\n\nGiven a Reaction, return the reaction rate law Operation used in generated ODEs for the reaction. Note, for a reaction defined by\n\nk*X*Y, X+Z --> 2X + Y\n\nthe expression that is returned will be k*X(t)^2*Y(t)*Z(t). For a reaction of the form\n\nk, 2X+3Y --> Z\n\nthe Operation that is returned will be k * (X(t)^2/2) * (Y(t)^3/6).\n\nNotes:\n\nAllocates\ncombinatoric_ratelaw=true uses factorial scaling factors in calculating the rate law, i.e. for 2S -> 0 at rate k the ratelaw would be k*S^2/2!. If combinatoric_ratelaw=false then the ratelaw is k*S^2, i.e. the scaling factor is ignored.\n\n\n\n\n\n","category":"function"},{"location":"systems/ReactionSystem/#ModelingToolkit.jumpratelaw","page":"ReactionSystem","title":"ModelingToolkit.jumpratelaw","text":"jumpratelaw(rx; rxvars=get_variables(rx.rate), combinatoric_ratelaw=true)\n\nGiven a Reaction, return the reaction rate law Operation used in generated stochastic chemical kinetics model SSAs for the reaction. Note, for a reaction defined by\n\nk*X*Y, X+Z --> 2X + Y\n\nthe expression that is returned will be k*X^2*Y*Z. For a reaction of the form\n\nk, 2X+3Y --> Z\n\nthe Operation that is returned will be k * binomial(X,2) * binomial(Y,3).\n\nNotes:\n\nrxvars should give the Variables, i.e. species and parameters, the rate depends on.\nAllocates\ncombinatoric_ratelaw=true uses binomials in calculating the rate law, i.e. for 2S -> 0 at rate k the ratelaw would be k*S*(S-1)/2. If combinatoric_ratelaw=false then the ratelaw is k*S*(S-1), i.e. the rate law is not normalized by the scaling factor.\n\n\n\n\n\n","category":"function"},{"location":"systems/ReactionSystem/#ModelingToolkit.ismassaction","page":"ReactionSystem","title":"ModelingToolkit.ismassaction","text":"ismassaction(rx, rs; rxvars = get_variables(rx.rate),\n haveivdep = any(var -> isequal(rs.iv,var), rxvars),\n stateset = Set(states(rs)))\n\nTrue if a given reaction is of mass action form, i.e. rx.rate does not depend on any chemical species that correspond to states of the system, and does not depend explicitly on the independent variable (usually time).\n\nArguments\n\nrx, the Reaction.\nrs, a ReactionSystem containing the reaction.\nOptional: rxvars, Variables which are not in rxvars are ignored as possible dependencies.\nOptional: haveivdep, true if the Reaction rate field explicitly depends on the independent variable.\nOptional: stateset, set of states which if the rxvars are within mean rx is non-mass action.\n\n\n\n\n\n","category":"function"},{"location":"systems/ReactionSystem/#Transformations-1","page":"ReactionSystem","title":"Transformations","text":"","category":"section"},{"location":"systems/ReactionSystem/#","page":"ReactionSystem","title":"ReactionSystem","text":"Base.convert","category":"page"},{"location":"systems/ReactionSystem/#Base.convert","page":"ReactionSystem","title":"Base.convert","text":"Base.convert(::Type{<:ODESystem},rs::ReactionSystem)\n\nConvert a ReactionSystem to an ODESystem.\n\nNotes:\n\ncombinatoric_ratelaws=true uses factorial scaling factors in calculating the rate\n\nlaw, i.e. for 2S -> 0 at rate k the ratelaw would be k*S^2/2!. If combinatoric_ratelaws=false then the ratelaw is k*S^2, i.e. the scaling factor is ignored.\n\n\n\n\n\nBase.convert(::Type{<:SDESystem},rs::ReactionSystem)\n\nConvert a ReactionSystem to an SDESystem.\n\nNotes:\n\ncombinatoric_ratelaws=true uses factorial scaling factors in calculating the rate\n\nlaw, i.e. for 2S -> 0 at rate k the ratelaw would be k*S^2/2!. If combinatoric_ratelaws=false then the ratelaw is k*S^2, i.e. the scaling factor is ignored.\n\nnoise_scaling=nothing::Union{Vector{Operation},Operation,Nothing} allows for linear\n\nscaling of the noise in the chemical Langevin equations. If nothing is given, the default value as in Gillespie 2000 is used. Alternatively, an Operation can be given, this is added as a parameter to the system (at the end of the parameter array). All noise terms are linearly scaled with this value. The parameter may be one already declared in the ReactionSystem. Finally, a Vector{Operation} can be provided (the length must be equal to the number of reactions). Here the noise for each reaction is scaled by the corresponding parameter in the input vector. This input may contain repeat parameters.\n\n\n\n\n\nBase.convert(::Type{<:JumpSystem},rs::ReactionSystem; combinatoric_ratelaws=true)\n\nConvert a ReactionSystem to an JumpSystem.\n\nNotes:\n\ncombinatoric_ratelaws=true uses binomials in calculating the rate law, i.e. for 2S -> 0 at rate k the ratelaw would be k*S*(S-1)/2. If combinatoric_ratelaws=false then the ratelaw is k*S*(S-1), i.e. the rate law is not normalized by the scaling factor.\n\n\n\n\n\nBase.convert(::Type{<:NonlinearSystem},rs::ReactionSystem)\n\nConvert a ReactionSystem to an NonlinearSystem.\n\nNotes:\n\ncombinatoric_ratelaws=true uses factorial scaling factors in calculating the rate\n\nlaw, i.e. for 2S -> 0 at rate k the ratelaw would be k*S^2/2!. If combinatoric_ratelaws=false then the ratelaw is k*S^2, i.e. the scaling factor is ignored.\n\n\n\n\n\n","category":"function"},{"location":"systems/NonlinearSystem/#NonlinearSystem-1","page":"NonlinearSystem","title":"NonlinearSystem","text":"","category":"section"},{"location":"systems/NonlinearSystem/#System-Constructors-1","page":"NonlinearSystem","title":"System Constructors","text":"","category":"section"},{"location":"systems/NonlinearSystem/#","page":"NonlinearSystem","title":"NonlinearSystem","text":"NonlinearSystem","category":"page"},{"location":"systems/NonlinearSystem/#ModelingToolkit.NonlinearSystem","page":"NonlinearSystem","title":"ModelingToolkit.NonlinearSystem","text":"struct NonlinearSystem <: ModelingToolkit.AbstractSystem\n\nA nonlinear system of equations.\n\nFields\n\neqs\nVector of equations defining the system.\nstates\nUnknown variables.\nps\nParameters.\npins\nobserved\nname\nName: the name of the system\n\nsystems\nsystems: The internal systems\n\nExamples\n\n@variables x y z\n@parameters σ ρ β\n\neqs = [0 ~ σ*(y-x),\n 0 ~ x*(ρ-z)-y,\n 0 ~ x*y - β*z]\nns = NonlinearSystem(eqs, [x,y,z],[σ,ρ,β])\n\n\n\n\n\n","category":"type"},{"location":"systems/NonlinearSystem/#Composition-and-Accessor-Functions-1","page":"NonlinearSystem","title":"Composition and Accessor Functions","text":"","category":"section"},{"location":"systems/NonlinearSystem/#","page":"NonlinearSystem","title":"NonlinearSystem","text":"sys.eqs or equations(sys): The equations that define the nonlinear system.\nsys.states or states(sys): The set of states in the nonlinear system.\nsys.parameters or parameters(sys): The parameters of the nonlinear system.","category":"page"},{"location":"systems/NonlinearSystem/#Transformations-1","page":"NonlinearSystem","title":"Transformations","text":"","category":"section"},{"location":"systems/NonlinearSystem/#Applicable-Calculation-and-Generation-Functions-1","page":"NonlinearSystem","title":"Applicable Calculation and Generation Functions","text":"","category":"section"},{"location":"systems/NonlinearSystem/#","page":"NonlinearSystem","title":"NonlinearSystem","text":"calculate_jacobian\r\ngenerate_jacobian\r\njacobian_sparsity","category":"page"},{"location":"systems/NonlinearSystem/#Problem-Constructors-1","page":"NonlinearSystem","title":"Problem Constructors","text":"","category":"section"},{"location":"systems/NonlinearSystem/#","page":"NonlinearSystem","title":"NonlinearSystem","text":"NonlinearProblem","category":"page"},{"location":"systems/NonlinearSystem/#DiffEqBase.NonlinearProblem","page":"NonlinearSystem","title":"DiffEqBase.NonlinearProblem","text":"function DiffEqBase.NonlinearProblem{iip}(sys::NonlinearSystem,u0map,tspan,\n parammap=DiffEqBase.NullParameters();\n jac = false, sparse=false,\n checkbounds = false,\n linenumbers = true, parallel=SerialForm(),\n kwargs...) where iip\n\nGenerates an NonlinearProblem from a NonlinearSystem and allows for automatically symbolically calculating numerical enhancements.\n\n\n\n\n\n","category":"type"},{"location":"comparison/#Comparison-of-Julia's-ModelingToolkit-vs-SymPy-for-Symbolic-Computation-1","page":"Comparison Against SymPy","title":"Comparison of Julia's ModelingToolkit vs SymPy for Symbolic Computation","text":"","category":"section"},{"location":"comparison/#","page":"Comparison Against SymPy","title":"Comparison Against SymPy","text":"ModelingToolkit.jl is a symbolic modeling language for Julia built in Julia. Its goal is very different from Sympy: it was made to support symbolic-numerics, the combination of symbolic computing with numerical methods to allow for extreme performance computing that would not be possible without modifying the model. Because of this, ModelingToolkit.jl excels in many areas due to purposeful design decisions:","category":"page"},{"location":"comparison/#","page":"Comparison Against SymPy","title":"Comparison Against SymPy","text":"Performance: ModelingToolkit.jl is built in Julia, whereas SymPy was built in Python. Thus the performance bar for ModelingToolkit.jl is much higher. ModelingToolkit.jl started because SymPy was far too slow and SymEngine was far too inflexible for the projects they were doing. Performance is key to ModelingToolkit.jl. If you find any performance issues, please file an issue.\nbuild_function: lambdify is \"fine\" for some people, but if you're building a super fast MPI-enabled Julia/C/Fortran simulation code, having a function that hits the Python interpreter is less than optimal. By default, build_function builds fast JIT-compiled functions due to being in Julia. However, it has support for things like static arrays, non-allocating functions via mutation, fast functions on sparse matrices and arrays of arrays, etc.: all core details of doing high performance computing.\nParallelism: ModelingToolkit.jl has pervasive parallelism. The symbolic simplification via SymbolicUtils.jl has built-in parallelism, ModelingToolkit.jl builds functions that parallelizes across threads and multiprocesses across clusters, and it has dynamic scheduling through tools like Dagger.jl. ModelingToolkit.jl is compatible with GPU libraries like CUDA.jl.\nScientific Machine Learning (SciML): ModelingToolkit.jl is made to synergize with the high performance Julia SciML ecosystem in many ways. At a base level, all expressions and built functions are compatible with automatic differentiation like ForwardDiff.jl and Zygote.jl, meaning that it can be used in and with neural networks. Tools like DataDrivenDiffEq.jl can reconstruct symbolic expressions from neural networks and data while NeuralNetDiffEq.jl can automatically solve partial differential equations from symbolic descriptions using physics-informed neural networks.\nPrimitives for high-performance numerics. Features like ODESystem can be used to easily generate automatically parallelized ODE solver code with sparse Jacobians and all of the pieces required to get the most optimal solves. Support for differential-algebraic equations, chemical reaction networks, and generation of code for nonlinear optimization tools makes ModelingToolkit.jl a tool for, well, building, generating, and analyzing models.\nDeep integration with the Julia ecosystem: ModelingToolkit.jl's integration with neural networks is not the only thing that's deep. ModelingToolkit.jl is built with the same philosophy as other SciML packages, eschewing \"monorepos\" for a distributed development approach that ties together the work of many developers. The differentiation parts utilize tools from automatic differentiation libraries, all linear algebra functionality comes from tracing Julia Base itself, symbolic rewriting (simplification and substitution) comes from SymbolicUtils.jl, parallelism comes from Julia Base libraries and Dagger.jl, and etc. The list keeps going. All told, by design ModelingToolkit.jl's development moves fast because it's effectively using the work of hundreds of Julia developers, allowing it to grow fast.","category":"page"},{"location":"systems/ControlSystem/#ControlSystem-1","page":"ControlSystem","title":"ControlSystem","text":"","category":"section"},{"location":"systems/ControlSystem/#System-Constructors-1","page":"ControlSystem","title":"System Constructors","text":"","category":"section"},{"location":"systems/ControlSystem/#","page":"ControlSystem","title":"ControlSystem","text":"ControlSystem","category":"page"},{"location":"systems/ControlSystem/#ModelingToolkit.ControlSystem","page":"ControlSystem","title":"ModelingToolkit.ControlSystem","text":"struct ControlSystem <: ModelingToolkit.AbstractControlSystem\n\nA system describing an optimal control problem. This contains a loss function and ordinary differential equations with control variables that describe the dynamics.\n\nFields\n\nloss\nThe Loss function\neqs\nThe ODEs defining the system.\niv\nIndependent variable.\nstates\nDependent (state) variables.\ncontrols\nControl variables.\nps\nParameter variables.\npins\nobserved\nname\nName: the name of the system\n\nsystems\nsystems: The internal systems\n\nExample\n\nusing ModelingToolkit\n\n@variables t x(t) v(t) u(t)\n@derivatives D'~t\n\nloss = (4-x)^2 + 2v^2 + u^2\neqs = [\n D(x) ~ v\n D(v) ~ u^3\n]\n\nsys = ControlSystem(loss,eqs,t,[x,v],[u],[])\n\n\n\n\n\n","category":"type"},{"location":"systems/ControlSystem/#Composition-and-Accessor-Functions-1","page":"ControlSystem","title":"Composition and Accessor Functions","text":"","category":"section"},{"location":"systems/ControlSystem/#","page":"ControlSystem","title":"ControlSystem","text":"sys.eqs or equations(sys): The equations that define the system.\nsys.states or states(sys): The set of states in the system.\nsys.parameters or parameters(sys): The parameters of the system.\nsys.controls or controls(sys): The control variables of the system","category":"page"},{"location":"systems/ControlSystem/#Transformations-1","page":"ControlSystem","title":"Transformations","text":"","category":"section"},{"location":"systems/ControlSystem/#","page":"ControlSystem","title":"ControlSystem","text":"runge_kutta_discretize","category":"page"},{"location":"systems/ControlSystem/#ModelingToolkit.runge_kutta_discretize","page":"ControlSystem","title":"ModelingToolkit.runge_kutta_discretize","text":"runge_kutta_discretize(sys::ControlSystem,dt,tspan;\n tab = ModelingToolkit.constructRadauIIA5())\n\nTransforms a nonlinear optimal control problem into a constrained OptimizationProblem according to a Runge-Kutta tableau that describes a collocation method. Requires a fixed dt over a given timespan. Defaults to using the 5th order RadauIIA tableau, and altnerative tableaus can be specified using the SciML tableau style.\n\n\n\n\n\n","category":"function"},{"location":"highlevel/#High-Level-API-1","page":"High Level API","title":"High Level API","text":"","category":"section"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"The high-level API allows modelers to interactively build models in a symbolic manner. It is designed as a semi-DSL for easily building large complex models and manipulating the models to generate optimal forms to be used in numerical methods.","category":"page"},{"location":"highlevel/#High-Level-API-Documentation-1","page":"High Level API","title":"High-Level API Documentation","text":"","category":"section"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"@parameters\r\n@variables\r\n@derivatives\r\nBase.:~(::Num, ::Num)\r\nmodelingtoolkitize","category":"page"},{"location":"highlevel/#ModelingToolkit.@parameters","page":"High Level API","title":"ModelingToolkit.@parameters","text":"Define one or more known variables.\n\n\n\n\n\n","category":"macro"},{"location":"highlevel/#ModelingToolkit.@variables","page":"High Level API","title":"ModelingToolkit.@variables","text":"Define one or more unknown variables.\n\n@parameters t α σ(..) β[1:2]\n@variables w(..) x(t) y() z(t, α, x)\n\nexpr = β₁* x + y^α + σ(3) * (z - t) - β₂ * w(t - 1)\n\nNote that @parameters and @variables implicitly add () to values that are not given a call. The former specifies the values as known, while the latter specifies it as unknown. (..) signifies that the value should be left uncalled.\n\nSometimes it is convenient to define arrays of variables to model things like x₁,…,x₃. The @variables and @parameters macros support this with the following syntax:\n\n@variables x[1:3];\nx\n\n3-element Array{Operation,1}:\n x₁()\n x₂()\n x₃()\n\n# support for arbitrary ranges and tensors\n@variables y[2:3,1:5:6];\ny\n\n2×2 Array{Operation,2}:\n y₂̒₁() y₂̒₆()\n y₃̒₁() y₃̒₆()\n\n# also works for dependent variables\n@parameters t; @variables z[1:3](t);\nz\n\n3-element Array{Operation,1}:\n z₁(t())\n z₂(t())\n z₃(t())\n\n\n\n\n\n","category":"macro"},{"location":"highlevel/#ModelingToolkit.@derivatives","page":"High Level API","title":"ModelingToolkit.@derivatives","text":"Define one or more differentials.\n\nExamples\n\njulia> using ModelingToolkit\n\njulia> @variables x y z;\n\njulia> @derivatives Dx'~x Dy'~y # Create differentials wrt. x and y\n((D'~x()), (D'~y()))\n\njulia> Dx(z) # Differentiate z wrt. x\n(D'~x())(z())\n\njulia> Dy(z) # Differentiate z wrt. y\n(D'~y())(z())\n\n\n\n\n\n","category":"macro"},{"location":"highlevel/#Base.:~-Tuple{Num,Num}","page":"High Level API","title":"Base.:~","text":"~(lhs::Num, rhs::Num) -> Equation\n\n\nCreate an Equation out of two Num instances, or an Num and a Number.\n\nExamples\n\njulia> using ModelingToolkit\n\njulia> @variables x y;\n\njulia> x ~ y\nEquation(x(), y())\n\njulia> x - y ~ 0\nEquation(x() - y(), 0)\n\n\n\n\n\n","category":"method"},{"location":"highlevel/#ModelingToolkit.modelingtoolkitize","page":"High Level API","title":"ModelingToolkit.modelingtoolkitize","text":"modelingtoolkitize(prob::ODEProblem) -> Union{Tuple{Any,Any,Any}, ODESystem}\n\n\nGenerate ODESystem, dependent variables, and parameters from an ODEProblem.\n\n\n\n\n\nmodelingtoolkitize(prob::SDEProblem) -> Union{Tuple{Any,Any,Any}, SDESystem}\n\n\nGenerate SDESystem, dependent variables, and parameters from an SDEProblem.\n\n\n\n\n\nmodelingtoolkitize(prob::OptimizationProblem) -> OptimizationSystem\n\n\nGenerate OptimizationSystem, dependent variables, and parameters from an OptimizationProblem.\n\n\n\n\n\n","category":"function"},{"location":"highlevel/#Differentiation-Functions-1","page":"High Level API","title":"Differentiation Functions","text":"","category":"section"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"ModelingToolkit.gradient\r\nModelingToolkit.jacobian\r\nModelingToolkit.sparsejacobian\r\nModelingToolkit.hessian\r\nModelingToolkit.sparsehessian","category":"page"},{"location":"highlevel/#ModelingToolkit.sparsejacobian","page":"High Level API","title":"ModelingToolkit.sparsejacobian","text":"sparsejacobian(ops::AbstractVector, vars::AbstractVector; simplify = true)\n\nA helper function for computing the sparse Jacobian of an array of expressions with respect to an array of variable expressions.\n\n\n\n\n\n","category":"function"},{"location":"highlevel/#ModelingToolkit.sparsehessian","page":"High Level API","title":"ModelingToolkit.sparsehessian","text":"sparsehessian(O, vars::AbstractVector; simplify = true)\n\nA helper function for computing the sparse Hessian of an expression with respect to an array of variable expressions.\n\n\n\n\n\n","category":"function"},{"location":"highlevel/#Sparsity-Detection-1","page":"High Level API","title":"Sparsity Detection","text":"","category":"section"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"ModelingToolkit.jacobian_sparsity\r\nModelingToolkit.hessian_sparsity","category":"page"},{"location":"highlevel/#ModelingToolkit.jacobian_sparsity","page":"High Level API","title":"ModelingToolkit.jacobian_sparsity","text":"jacobian_sparsity(ops::AbstractVector, vars::AbstractVector)\n\nReturn the sparsity pattern of the Jacobian of an array of expressions with respect to an array of variable expressions.\n\n\n\n\n\n","category":"function"},{"location":"highlevel/#ModelingToolkit.hessian_sparsity","page":"High Level API","title":"ModelingToolkit.hessian_sparsity","text":"hessian_sparsity(ops::AbstractVector, vars::AbstractVector)\n\nReturn the sparsity pattern of the Hessian of an array of expressions with respect to an array of variable expressions.\n\n\n\n\n\n","category":"function"},{"location":"highlevel/#Latexification-1","page":"High Level API","title":"Latexification","text":"","category":"section"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"ModelingToolkit.jl's expressions support Latexify.jl, and thus","category":"page"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"using Latexify\r\nlatexify(ex)","category":"page"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"will produce LaTeX output from ModelingToolkit models and expressions. This works on basics like Term all the way to higher primitives like ODESystem and ReactionSystem.","category":"page"},{"location":"highlevel/#The-Auto-Detecting-System-Constructors-1","page":"High Level API","title":"The Auto-Detecting System Constructors","text":"","category":"section"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"For the high-level interface, the system constructors, such as ODESystem, have high-level constructors, which just take in the required equations and automatically parse the expressions to figure out the states and parameters of the system. The following high-level constructors exist:","category":"page"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"ODESystem(eqs)\r\nNonlinearSystem(eqs)","category":"page"},{"location":"highlevel/#Direct-Tracing-1","page":"High Level API","title":"Direct Tracing","text":"","category":"section"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"Because ModelingToolkit expressions respect Julia semantics, one way to generate symbolic expressions is to simply place ModelingToolkit variables as inputs into existing Julia code. For example, the following uses the standard Julia function for the Lorenz equations to generate the symbolic expression for the Lorenz equations:","category":"page"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"function lorenz(du,u,p,t)\r\n du[1] = 10.0(u[2]-u[1])\r\n du[2] = u[1]*(28.0-u[3]) - u[2]\r\n du[3] = u[1]*u[2] - (8/3)*u[3]\r\nend\r\n@variables t u[1:3](t) du[1:3](t)\r\n@parameters p[1:3]\r\nlorenz(du,u,p,t)\r\ndu","category":"page"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"3-element Array{Num,1}:\r\n 10.0 * (u₂(t) - u₁(t))\r\n u₁(t) * (28.0 - u₃(t)) - u₂(t)\r\nu₁(t) * u₂(t) - 2.6666666666666665 * u₃(t)","category":"page"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"Or similarly:","category":"page"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"@variables t x(t) y(t) z(t) dx(t) dy(t) dz(t)\r\n@parameters σ ρ β\r\ndu = [dx,dy,dz]\r\nu = [x,y,z]\r\np = [σ,ρ,β]\r\nlorenz(du,u,p,t)\r\ndu","category":"page"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"3-element Array{Num,1}:\r\n 10.0 * (y(t) - x(t))\r\n x(t) * (28.0 - z(t)) - y(t)\r\nx(t) * y(t) - 2.6666666666666665 * z(t)","category":"page"},{"location":"highlevel/#Intermediate-Calculations-1","page":"High Level API","title":"Intermediate Calculations","text":"","category":"section"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"The system building functions can handle intermediate calculations by simply defining and using an Term of Syms. For example:","category":"page"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"@variables x y z\r\n@parameters σ ρ β\r\na = y - x\r\neqs = [0 ~ σ*a,\r\n 0 ~ x*(ρ-z)-y,\r\n 0 ~ x*y - β*z]\r\nns = NonlinearSystem(eqs, [x,y,z], [σ,ρ,β])\r\nnlsys_func = generate_function(ns)[2] # second is the inplace version","category":"page"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"expands to:","category":"page"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":":((var\"##MTIIPVar#368\", var\"##MTKArg#365\", var\"##MTKArg#366\")->begin\r\n @inbounds begin\r\n let (x, y, z, σ, ρ, β) = (var\"##MTKArg#365\"[1], var\"##MTKArg#365\"[2], var\"##MTKArg#365\"[3], var\"##MTKArg#366\"[1], var\"##MTKArg#366\"[2], var\"##MTKArg#366\"[3])\r\n var\"##MTIIPVar#368\"[1] = (*)(σ, (-)(y, x))\r\n var\"##MTIIPVar#368\"[2] = (-)((*)(x, (-)(ρ, z)), y)\r\n var\"##MTIIPVar#368\"[3] = (-)((*)(x, y), (*)(β, z))\r\n end\r\n end\r\n nothing\r\n end)","category":"page"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"In addition, the Jacobian calculations take into account intermediate variables to appropriately handle them.","category":"page"},{"location":"highlevel/#I/O-and-Saving-1","page":"High Level API","title":"I/O and Saving","text":"","category":"section"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"Note that Julia's standard I/O functionality can be used to save ModelingToolkit expressions out to files. For example, here we will generate an in-place version of f and save the anonymous function to a .jl file:","category":"page"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"using ModelingToolkit\r\n@variables u[1:3]\r\nfunction f(u)\r\n [u[1]-u[3],u[1]^2-u[2],u[3]+u[2]]\r\nend\r\nex1, ex2 = build_function(f(u),u)\r\nwrite(\"function.jl\", string(ex2))","category":"page"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"Now we can do something like:","category":"page"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"f = include(\"function.jl\")","category":"page"},{"location":"highlevel/#","page":"High Level API","title":"High Level API","text":"and that will load the function back in. Note that this can be done to save the transformation results of ModelingToolkit.jl so that they can be stored and used in a precompiled Julia package.","category":"page"},{"location":"systems/DependencyGraphs/#Dependency-Graphs-1","page":"Dependency Graphs","title":"Dependency Graphs","text":"","category":"section"},{"location":"systems/DependencyGraphs/#Types-1","page":"Dependency Graphs","title":"Types","text":"","category":"section"},{"location":"systems/DependencyGraphs/#","page":"Dependency Graphs","title":"Dependency Graphs","text":"BipartiteGraph","category":"page"},{"location":"systems/DependencyGraphs/#ModelingToolkit.BipartiteGraph","page":"Dependency Graphs","title":"ModelingToolkit.BipartiteGraph","text":"mutable struct BipartiteGraph{T<:Integer}\n\nA bipartite graph representation between two, possibly distinct, sets of vertices (source and dependencies). Maps source vertices, labelled 1:N₁, to vertices on which they depend (labelled 1:N₂).\n\nFields\n\nne\nNumber of edges from source vertices to vertices they depend on.\nfadjlist\nForward adjacency list mapping index of source vertices to the vertices they depend on.\nbadjlist\nBackward adjacency list mapping index of vertices that are dependencies to the source vertices that depend on them.\n\nExample\n\nusing ModelingToolkit\n\nne = 4\nsrcverts = 1:4\ndepverts = 1:2\n\n# six source vertices\nfadjlist = [[1],[1],[2],[2],[1],[1,2]]\n\n# two vertices they depend on \nbadjlist = [[1,2,5,6],[3,4,6]]\n\nbg = BipartiteGraph(7, fadjlist, badjlist)\n\n\n\n\n\n","category":"type"},{"location":"systems/DependencyGraphs/#Utility-functions-for-BiPartiteGraphs-1","page":"Dependency Graphs","title":"Utility functions for BiPartiteGraphs","text":"","category":"section"},{"location":"systems/DependencyGraphs/#","page":"Dependency Graphs","title":"Dependency Graphs","text":"Base.isequal","category":"page"},{"location":"systems/DependencyGraphs/#Base.isequal","page":"Dependency Graphs","title":"Base.isequal","text":"Base.isequal(bg1::BipartiteGraph{T}, bg2::BipartiteGraph{T}) where {T<:Integer} \n\nTest whether two BipartiteGraphs are equal.\n\n\n\n\n\n","category":"function"},{"location":"systems/DependencyGraphs/#Functions-for-calculating-dependency-graphs-1","page":"Dependency Graphs","title":"Functions for calculating dependency graphs","text":"","category":"section"},{"location":"systems/DependencyGraphs/#","page":"Dependency Graphs","title":"Dependency Graphs","text":"equation_dependencies\nasgraph\nvariable_dependencies\nasdigraph\neqeq_dependencies\nvarvar_dependencies","category":"page"},{"location":"systems/DependencyGraphs/#ModelingToolkit.equation_dependencies","page":"Dependency Graphs","title":"ModelingToolkit.equation_dependencies","text":"equation_dependencies(sys::AbstractSystem; variables=states(sys))\n\nGiven an AbstractSystem calculate for each equation the variables it depends on. \n\nNotes:\n\nVariables that are not in variables are filtered out.\nget_variables! is used to determine the variables within a given equation. \nreturns a Vector{Vector{Variable}}() mapping the index of an equation to the variables it depends on.\n\nExample:\n\nusing ModelingToolkit\n@parameters β γ κ η t\n@variables S(t) I(t) R(t)\n\n# use a reaction system to easily generate ODE and jump systems\nrxs = [Reaction(β, [S,I], [I], [1,1], [2]),\n Reaction(γ, [I], [R]),\n Reaction(κ+η, [R], [S])]\nrs = ReactionSystem(rxs, t, [S,I,R], [β,γ,κ,η])\n\n# ODEs:\nodesys = convert(ODESystem, rs)\n\n# dependency of each ODE on state variables\nequation_dependencies(odesys) \n\n# dependency of each ODE on parameters\nequation_dependencies(odesys, variables=parameters(odesys))\n\n# Jumps\njumpsys = convert(JumpSystem, rs)\n\n# dependency of each jump rate function on state variables\nequation_dependencies(jumpsys) \n\n# dependency of each jump rate function on parameters\nequation_dependencies(jumpsys, variables=parameters(jumpsys)) \n\n\n\n\n\n","category":"function"},{"location":"systems/DependencyGraphs/#ModelingToolkit.asgraph","page":"Dependency Graphs","title":"ModelingToolkit.asgraph","text":"asgraph(eqdeps, vtois) \n\nConvert a collection of equation dependencies, for example as returned by equation_dependencies, to a BipartiteGraph.\n\nNotes:\n\nvtois should provide a Dict like mapping from each Variable dependency in eqdeps to the integer idx of the variable to use in the graph.\n\nExample: Continuing the example started in equation_dependencies\n\ndigr = asgraph(equation_dependencies(odesys), Dict(s => i for (i,s) in enumerate(states(odesys))))\n\n\n\n\n\nasgraph(sys::AbstractSystem; variables=states(sys), \n variablestoids=Dict(convert(Variable, v) => i for (i,v) in enumerate(variables)))\n\nConvert an AbstractSystem to a BipartiteGraph mapping the index of equations to the indices of variables they depend on.\n\nNotes:\n\nDefaults for kwargs creating a mapping from equations(sys) to states(sys) they depend on.\nvariables should provide the list of variables to use for generating the dependency graph.\nvariablestoids should provide Dict like mapping from a Variable to its Int index within variables.\n\nExample: Continuing the example started in equation_dependencies\n\ndigr = asgraph(odesys)\n\n\n\n\n\n","category":"function"},{"location":"systems/DependencyGraphs/#ModelingToolkit.variable_dependencies","page":"Dependency Graphs","title":"ModelingToolkit.variable_dependencies","text":"variable_dependencies(sys::AbstractSystem; variables=states(sys), variablestoids=nothing)\n\nFor each variable determine the equations that modify it and return as a BipartiteGraph.\n\nNotes:\n\nDependencies are returned as a BipartiteGraph mapping variable indices to the indices of equations that modify them.\nvariables denotes the list of variables to determine dependencies for.\nvariablestoids denotes a Dict mapping Variables to their Int index in variables.\n\nExample: Continuing the example of equation_dependencies\n\nvariable_dependencies(odesys)\n\n\n\n\n\n","category":"function"},{"location":"systems/DependencyGraphs/#ModelingToolkit.asdigraph","page":"Dependency Graphs","title":"ModelingToolkit.asdigraph","text":"asdigraph(g::BipartiteGraph, sys::AbstractSystem; variables = states(sys), equationsfirst = true)\n\nConvert a BipartiteGraph to a LightGraph.SimpleDiGraph.\n\nNotes:\n\nThe resulting SimpleDiGraph unifies the two sets of vertices (equations and then states in the case it comes from asgraph), producing one ordered set of integer vertices (SimpleDiGraph does not support two distinct collections of vertices so they must be merged).\nvariables gives the variables that g is associated with (usually the states of a system).\nequationsfirst (default is true) gives whether the BipartiteGraph gives a mapping from equations to variables they depend on (true), as calculated by asgraph, or whether it gives a mapping from variables to the equations that modify them, as calculated by variable_dependencies.\n\nExample: Continuing the example in asgraph\n\ndg = asdigraph(digr)\n\n\n\n\n\n","category":"function"},{"location":"systems/DependencyGraphs/#ModelingToolkit.eqeq_dependencies","page":"Dependency Graphs","title":"ModelingToolkit.eqeq_dependencies","text":"eqeq_dependencies(eqdeps::BipartiteGraph{T}, vardeps::BipartiteGraph{T}) where {T <: Integer}\n\nCalculate a LightGraph.SimpleDiGraph that maps each equation to equations they depend on.\n\nNotes:\n\nThe fadjlist of the SimpleDiGraph maps from an equation to the equations that modify variables it depends on.\nThe badjlist of the SimpleDiGraph maps from an equation to equations that depend on variables it modifies.\n\nExample: Continuing the example of equation_dependencies\n\neqeqdep = eqeq_dependencies(asgraph(odesys), variable_dependencies(odesys))\n\n\n\n\n\n","category":"function"},{"location":"systems/DependencyGraphs/#ModelingToolkit.varvar_dependencies","page":"Dependency Graphs","title":"ModelingToolkit.varvar_dependencies","text":"varvar_dependencies(eqdeps::BipartiteGraph{T}, vardeps::BipartiteGraph{T}) where {T <: Integer} = eqeq_dependencies(vardeps, eqdeps)\n\nCalculate a LightGraph.SimpleDiGraph that maps each variable to variables they depend on.\n\nNotes:\n\nThe fadjlist of the SimpleDiGraph maps from a variable to the variables that depend on it.\nThe badjlist of the SimpleDiGraph maps from a variable to variables on which it depends.\n\nExample: Continuing the example of equation_dependencies\n\nvarvardep = varvar_dependencies(asgraph(odesys), variable_dependencies(odesys))\n\n\n\n\n\n","category":"function"},{"location":"IR/#ModelingToolkit-IR-1","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"","category":"section"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"ModelingToolkit IR mirrors the Julia AST but allows for easy mathematical manipulation by itself following mathematical semantics. The base of the IR is the Sym type, which defines a symbolic variable. Registered (mathematical) functions on Syms (or Terms) return Terms. For example, op1 = x+y is one Term and op2 = 2z is another, and so op1*op2 is another Term. Then, at the top, an Equation, normally written as op1 ~ op2, defines the symbolic equality between two operations.","category":"page"},{"location":"IR/#Types-1","page":"ModelingToolkit IR","title":"Types","text":"","category":"section"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"Sym, Term, and FnType are from SymbolicUtils.jl. Note that in ModelingToolkit, we always use Sym{Real}, Term{Real}, and FnType{Tuple{Any}, Real}. To get the arguments of a Term use arguments(t::Term), and to get the operation of a Term use operation(t::Term).","category":"page"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"Equation","category":"page"},{"location":"IR/#ModelingToolkit.Equation","page":"ModelingToolkit IR","title":"ModelingToolkit.Equation","text":"struct Equation\n\nAn equality relationship between two expressions.\n\nFields\n\nlhs\nThe expression on the left-hand side of the equation.\nrhs\nThe expression on the right-hand side of the equation.\n\n\n\n\n\n","category":"type"},{"location":"IR/#A-note-about-functions-restricted-to-Numbers-1","page":"ModelingToolkit IR","title":"A note about functions restricted to Numbers","text":"","category":"section"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"Sym and Term objects are NOT subtypes of Number. ModelingToolkit provides a simple wrapper type called Num which is a subtype of Real. Num wraps either a Sym or a Term or any other object, defines the same set of operations as symbolic expressions and forwards those to the values it wraps. You can use ModelingToolkit.value function to unwrap a Num.","category":"page"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"By default, the @variables and @parameters functions return Num-wrapped objects so as to allow calling functions which are restricted to Number or Real.","category":"page"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"julia> @parameters t; @variables x y z(t);\r\n\r\njulia> ModelingToolkit.operation(ModelingToolkit.value(x + y))\r\n+ (generic function with 377 methods)\r\n\r\njulia> ModelingToolkit.operation(ModelingToolkit.value(z))\r\nz(::Any)::Real\r\n\r\njulia> ModelingToolkit.arguments(ModelingToolkit.value(x + y))\r\n2-element Vector{Sym{Real}}:\r\n x\r\n y","category":"page"},{"location":"IR/#Function-Registration-1","page":"ModelingToolkit IR","title":"Function Registration","text":"","category":"section"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"The ModelingToolkit graph only allowed for registered Julia functions for the operations. All other functions are automatically traced down to registered functions. By default, ModelingToolkit.jl pre-registers the common functions utilized in SymbolicUtils.jl and pre-defines their derivatives. However, the user can utilize the @register macro to add their function to allowed functions of the computation graph.","category":"page"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"@register","category":"page"},{"location":"IR/#ModelingToolkit.@register","page":"ModelingToolkit IR","title":"ModelingToolkit.@register","text":"@register(expr, Ts = [Num, Symbolic, Real])\n\nOverload approperate methods such that ModelingToolkit can stop tracing into the registered function.\n\nExamples\n\n@register foo(x, y)\n@register goo(x, y::Int) # `y` is not overloaded to take symbolic objects\n\n\n\n\n\n","category":"macro"},{"location":"IR/#Derivatives-and-Differentials-1","page":"ModelingToolkit IR","title":"Derivatives and Differentials","text":"","category":"section"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"A Differential(op) is a partial derivative with respect to op, which can then be applied to some other operations. For example, D=Differential(t) is what would commonly be referred to as d/dt, which can then be applied to other operations using its function call, so D(x+y) is d(x+y)/dt.","category":"page"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"By default, the derivatives are left unexpanded to capture the symbolic representation of the differential equation. If the user would like to expand out all of the differentials, the expand_derivatives function eliminates all of the differentials down to basic one-variable expressions.","category":"page"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"ModelingToolkit.derivative\r\nDifferential\r\nexpand_derivatives\r\nModelingToolkit.jacobian\r\nModelingToolkit.gradient\r\nModelingToolkit.hessian","category":"page"},{"location":"IR/#ModelingToolkit.derivative","page":"ModelingToolkit IR","title":"ModelingToolkit.derivative","text":"derivative(O, idx)\n\n\nCalculate the derivative of the op O with respect to its argument with index idx.\n\nExamples\n\njulia> using ModelingToolkit\n\njulia> @variables x y;\n\njulia> ModelingToolkit.derivative(sin(x), 1)\ncos(x())\n\nNote that the function does not recurse into the operation's arguments, i.e., the chain rule is not applied:\n\njulia> myop = sin(x) * y^2\nsin(x()) * y() ^ 2\n\njulia> typeof(myop.op) # Op is multiplication function\ntypeof(*)\n\njulia> ModelingToolkit.derivative(myop, 1) # wrt. sin(x)\ny() ^ 2\n\njulia> ModelingToolkit.derivative(myop, 2) # wrt. y^2\nsin(x())\n\n\n\n\n\n","category":"function"},{"location":"IR/#ModelingToolkit.Differential","page":"ModelingToolkit IR","title":"ModelingToolkit.Differential","text":"struct Differential <: Function\n\nRepresents a differential operator.\n\nFields\n\nx\nThe variable or expression to differentiate with respect to.\n\nExamples\n\njulia> using ModelingToolkit\n\njulia> @variables x y;\n\njulia> D = Differential(x)\n(D'~x())\n\njulia> D(y) # Differentiate y wrt. x\n(D'~x())(y())\n\n\n\n\n\n","category":"type"},{"location":"IR/#ModelingToolkit.expand_derivatives","page":"ModelingToolkit IR","title":"ModelingToolkit.expand_derivatives","text":"expand_derivatives(O)\nexpand_derivatives(O, simplify; occurances)\n\n\nTODO\n\n\n\n\n\n","category":"function"},{"location":"IR/#ModelingToolkit.jacobian","page":"ModelingToolkit IR","title":"ModelingToolkit.jacobian","text":"jacobian(ops::AbstractVector, vars::AbstractVector; simplify = true)\n\nA helper function for computing the Jacobian of an array of expressions with respect to an array of variable expressions.\n\n\n\n\n\n","category":"function"},{"location":"IR/#ModelingToolkit.gradient","page":"ModelingToolkit IR","title":"ModelingToolkit.gradient","text":"gradient(O, vars::AbstractVector; simplify = true)\n\nA helper function for computing the gradient of an expression with respect to an array of variable expressions.\n\n\n\n\n\n","category":"function"},{"location":"IR/#ModelingToolkit.hessian","page":"ModelingToolkit IR","title":"ModelingToolkit.hessian","text":"hessian(O, vars::AbstractVector; simplify = true)\n\nA helper function for computing the Hessian of an expression with respect to an array of variable expressions.\n\n\n\n\n\n","category":"function"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"For jacobians which are sparse, use the sparsejacobian function. For hessians which are sparse, use the sparsehessian function.","category":"page"},{"location":"IR/#Adding-Derivatives-1","page":"ModelingToolkit IR","title":"Adding Derivatives","text":"","category":"section"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"There is a large amount of derivatives pre-defined by DiffRules.jl.","category":"page"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"f(x,y,z) = x^2 + sin(x+y) - z","category":"page"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"automatically has the derivatives defined via the tracing mechanism. It will do this by directly building the operation the internals of your function and differentiating that.","category":"page"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"However, in many cases you may want to define your own derivatives so that way automatic Jacobian etc. calculations can utilize this information. This can allow for more succinct versions of the derivatives to be calculated in order to better scale to larger systems. You can define derivatives for your own function via the dispatch:","category":"page"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"# `N` arguments are accepted by the relevant method of `my_function`\r\nModelingToolkit.derivative(::typeof(my_function), args::NTuple{N,Any}, ::Val{i})","category":"page"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"where i means that it's the derivative with respect to the ith argument. args is the array of arguments, so, for example, if your function is f(x,t), then args = [x,t]. You should return an Term for the derivative of your function.","category":"page"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"For example, sin(t)'s derivative (by t) is given by the following:","category":"page"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"ModelingToolkit.derivative(::typeof(sin), args::NTuple{1,Any}, ::Val{1}) = cos(args[1])","category":"page"},{"location":"IR/#IR-Manipulation-1","page":"ModelingToolkit IR","title":"IR Manipulation","text":"","category":"section"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"ModelingToolkit.jl provides functionality for easily manipulating expressions. Most of the functionality comes by the expression objects obeying the standard mathematical semantics. For example, if one has A a matrix of symbolic expressions wrapped in Num, then A^2 calculates the expressions for the squared matrix. In that sense, it is encouraged that one uses standard Julia for performing a lot of the manipulation on the IR, as, for example, calculating the sparse form of the matrix via sparse(A) is valid, legible, and easily understandable to all Julia programmers.","category":"page"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"Other additional manipulation functions are given below.","category":"page"},{"location":"IR/#","page":"ModelingToolkit IR","title":"ModelingToolkit IR","text":"get_variables\r\nsubstitute\r\ntovar\r\ntoparam\r\ntosymbol\r\nmakesym\r\ndiff2term","category":"page"},{"location":"IR/#ModelingToolkit.get_variables","page":"ModelingToolkit IR","title":"ModelingToolkit.get_variables","text":"get_variables(O) -> Vector{Union{Sym, Term}}\n\nReturns the variables in the expression. Note that the returned variables are not wrapped in the Num type.\n\nExamples\n\njulia> @parameters t\n(t,)\n\njulia> @variables x y z(t)\n(x, y, z(t))\n\njulia> ex = x + y + sin(z)\n(x + y) + sin(z(t))\n\njulia> ModelingToolkit.get_variables(ex)\n3-element Vector{Any}:\n x\n y\n z(t)\n\n\n\n\n\n","category":"function"},{"location":"IR/#SymbolicUtils.substitute","page":"ModelingToolkit IR","title":"SymbolicUtils.substitute","text":"substitute(expr, s::Pair)\nsubstitute(expr, s::Dict)\nsubstitute(expr, s::Vector)\n\nPerforms the substitution on expr according to rule(s) s.\n\nExamples\n\njulia> @parameters t\n(t,)\n\njulia> @variables x y z(t)\n(x, y, z(t))\n\njulia> ex = x + y + sin(z)\n(x + y) + sin(z(t))\n\njulia> substitute(ex, Dict([x => z, sin(z) => z^2]))\n(z(t) + y) + (z(t) ^ 2)\n\n\n\n\n\n","category":"function"},{"location":"systems/SDESystem/#SDESystem-1","page":"SDESystem","title":"SDESystem","text":"","category":"section"},{"location":"systems/SDESystem/#System-Constructors-1","page":"SDESystem","title":"System Constructors","text":"","category":"section"},{"location":"systems/SDESystem/#","page":"SDESystem","title":"SDESystem","text":"SDESystem","category":"page"},{"location":"systems/SDESystem/#ModelingToolkit.SDESystem","page":"SDESystem","title":"ModelingToolkit.SDESystem","text":"struct SDESystem <: ModelingToolkit.AbstractODESystem\n\nA system of stochastic differential equations.\n\nFields\n\neqs\nThe expressions defining the drift term.\nnoiseeqs\nThe expressions defining the diffusion term.\niv\nIndependent variable.\nstates\nDependent (state) variables.\nps\nParameter variables.\npins\nobserved\ntgrad\nTime-derivative matrix. Note: this field will not be defined until calculate_tgrad is called on the system.\n\njac\nJacobian matrix. Note: this field will not be defined until calculate_jacobian is called on the system.\n\nWfact\nWfact matrix. Note: this field will not be defined until generate_factorized_W is called on the system.\n\nWfact_t\nWfact_t matrix. Note: this field will not be defined until generate_factorized_W is called on the system.\n\nname\nName: the name of the system\n\nsystems\nSystems: the internal systems\n\nExample\n\nusing ModelingToolkit\n\n@parameters t σ ρ β\n@variables x(t) y(t) z(t)\n@derivatives D'~t\n\neqs = [D(x) ~ σ*(y-x),\n D(y) ~ x*(ρ-z)-y,\n D(z) ~ x*y - β*z]\n\nnoiseeqs = [0.1*x,\n 0.1*y,\n 0.1*z]\n\nde = SDESystem(eqs,noiseeqs,t,[x,y,z],[σ,ρ,β])\n\n\n\n\n\n","category":"type"},{"location":"systems/SDESystem/#Composition-and-Accessor-Functions-1","page":"SDESystem","title":"Composition and Accessor Functions","text":"","category":"section"},{"location":"systems/SDESystem/#","page":"SDESystem","title":"SDESystem","text":"sys.eqs or equations(sys): The equations that define the SDE.\nsys.states or states(sys): The set of states in the SDE.\nsys.parameters or parameters(sys): The parameters of the SDE.\nsys.iv or independent_variable(sys): The independent variable of the SDE.","category":"page"},{"location":"systems/SDESystem/#Transformations-1","page":"SDESystem","title":"Transformations","text":"","category":"section"},{"location":"systems/SDESystem/#Applicable-Calculation-and-Generation-Functions-1","page":"SDESystem","title":"Applicable Calculation and Generation Functions","text":"","category":"section"},{"location":"systems/SDESystem/#","page":"SDESystem","title":"SDESystem","text":"calculate_jacobian\r\ncalculate_tgrad\r\ncalculate_factorized_W\r\ngenerate_jacobian\r\ngenerate_tgrad\r\ngenerate_factorized_W\r\njacobian_sparsity","category":"page"},{"location":"systems/SDESystem/#Problem-Constructors-1","page":"SDESystem","title":"Problem Constructors","text":"","category":"section"},{"location":"systems/SDESystem/#","page":"SDESystem","title":"SDESystem","text":"SDEFunction\r\nSDEProblem","category":"page"},{"location":"systems/SDESystem/#DiffEqBase.SDEFunction","page":"SDESystem","title":"DiffEqBase.SDEFunction","text":"function DiffEqBase.SDEFunction{iip}(sys::SDESystem, dvs = sys.states, ps = sys.ps;\n version = nothing, tgrad=false, sparse = false,\n jac = false, Wfact = false, kwargs...) where {iip}\n\nCreate an SDEFunction from the SDESystem. The arguments dvs and ps are used to set the order of the dependent variable and parameter vectors, respectively.\n\n\n\n\n\n","category":"type"},{"location":"systems/SDESystem/#DiffEqBase.SDEProblem","page":"SDESystem","title":"DiffEqBase.SDEProblem","text":"function DiffEqBase.SDEProblem{iip}(sys::SDESystem,u0map,tspan,p=parammap;\n version = nothing, tgrad=false,\n jac = false, Wfact = false,\n checkbounds = false, sparse = false,\n sparsenoise = sparse,\n skipzeros = true, fillzeros = true,\n linenumbers = true, parallel=SerialForm(),\n kwargs...)\n\nGenerates an SDEProblem from an SDESystem and allows for automatically symbolically calculating numerical enhancements.\n\n\n\n\n\n","category":"type"},{"location":"tutorials/symbolic_functions/#Symbolic-Calculations-and-Building-Fast-Parallel-Functions-1","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"","category":"section"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"ModelingToolkit.jl is first and foremost a symbolic modeling language. The way to define symbolic variables is via the @variables macro:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"@variables x y","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"After defining variables as symbolic, symbolic expressions, which we call a Term, can be generated by utilizing Julia expressions. For example:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"z = x^2 + y","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"Here, z is the Term for \"square x and add y\". To make an array of symbolic expressions, simply make an array of symbolic expressions:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"A = [x^2+y 0 2x\n 0 0 2y\n y^2+x 0 0]\n\n3×3 Array{Num,2}:\n x ^ 2 + y 0 2x\n 0 0 2y\n y ^ 2 + x 0 0","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"Note that by default, @variables returns Sym or Term objects wrapped in Num in order to make them behave like subtypes of Real. Any operation on these Num objects will return a new Num object, wrapping the result of computing symbolically on the underlying values.","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"To better view the results, we can use Latexify.jl. ModelingToolkit.jl comes with Latexify recipes so it works automatically:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"using Latexify\nlatexify(A)","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"beginequation\nleft\nbeginarrayccc\n(x ^ 2) + y 0 2 * x \n0 0 2 * y \n(y ^ 2) + x 0 0 \nendarray\nright\nendequation","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"Normal Julia functions work on ModelingToolkit expressions, so if we want to create the sparse version of A we would just call sparse:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"using SparseArrays\nspA = sparse(A)\n\n3×3 SparseMatrixCSC{Num,Int64} with 4 stored entries:\n [1, 1] = (x ^ 2) + y\n [3, 1] = (y ^ 2) + x\n [1, 3] = 2 * x\n [2, 3] = 2 * y","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"We can thus use normal Julia functions as generators for sparse expressions. For example, here we will define","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"function f(u)\n [u[1]-u[3],u[1]^2-u[2],u[3]+u[2]]\nend\nf([x,y,z]) # Recall that z = x^2 + y\n\n3-element Array{Num,1}:\n x - (x ^ 2 + y)\n x ^ 2 - y\n (x ^ 2 + y) + y","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"Or we can build array variables and use these to trace:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"@variables u[1:3]\nf(u)\n\n3-element Array{Num,1}:\n u₁ - u₃\n u₁ ^ 2 - u₂\n u₃ + u₂","category":"page"},{"location":"tutorials/symbolic_functions/#Building-Functions-1","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Building Functions","text":"","category":"section"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"The function for building functions is the aptly-named build_function. The first argument is the symbolic expression or the array of symbolic expressions to compile, and the trailing arguments are the arguments for the function. For example:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"to_compute = [x^2 + y, y^2 + x]\nf_expr = build_function(to_compute,[x,y])","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"gives back two codes. The first is a function f([x,y]) that computes and builds an output vector [x^2 + y, y^2 + x]. Because this tool was made to be used by all the cool kids writing fast Julia codes, it is specialized to Julia and supports features like StaticArrays. For example:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"myf = eval(f_expr[1])\nmyf(SA[2.0,3.0])\n\n2-element SArray{Tuple{2},Float64,1,2} with indices SOneTo(2):\n 7.0\n 11.0","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"The second function is an in-place non-allocating mutating function which mutates its first value:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"f_expr[2]\n\n:((var\"##MTIIPVar#292\", var\"##MTKArg#290\")->begin\n @inbounds begin\n let (x, y) = (var\"##MTKArg#290\"[1], var\"##MTKArg#290\"[2])\n var\"##MTIIPVar#292\"[1] = (getproperty(Base, :+))(x ^ 2, y)\n var\"##MTIIPVar#292\"[2] = (getproperty(Base, :+))(y ^ 2, x)\n end\n end\n nothing\n end)","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"Thus we'd use it like the following:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"myf! = eval(f_expr[2])\nout = zeros(2)\nmyf!(out,[2.0,3.0])\nout\n\n2-element Array{Float64,1}:\n 7.0\n 11.0","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"To save the symbolic calculations for later, we can take this expression and save it out to a file:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"write(\"function.jl\", string(f_expr[2]))","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"Note that if we need to avoid eval, for example to avoid world-age issues, one could do expression = Val{false}:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"build_function(to_compute,[x,y],expression=Val{false})","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"which will use GeneralizedGenerated.jl to build Julia functions which avoid world-age issues.","category":"page"},{"location":"tutorials/symbolic_functions/#Building-Non-Allocating-Parallel-Functions-for-Sparse-Matrices-1","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Building Non-Allocating Parallel Functions for Sparse Matrices","text":"","category":"section"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"Now let's show off a little bit. build_function is kind of like if lambdify ate its spinach. To show this, let's build a non-allocating function that fills sparse matrices in a multithreaded manner. To do this, we just have to represent the operation that we're turning into a function via a sparse matrix. For example:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"N = 8\nA = sparse(Tridiagonal([x^i for i in 1:N-1],[x^i * y^(8-i) for i in 1:N], [y^i for i in 1:N-1]))\n\n8×8 SparseMatrixCSC{Num,Int64} with 22 stored entries:\n [1, 1] = x ^ 1 * y ^ 7\n [2, 1] = x ^ 1\n [1, 2] = y ^ 1\n [2, 2] = x ^ 2 * y ^ 6\n [3, 2] = x ^ 2\n [2, 3] = y ^ 2\n [3, 3] = x ^ 3 * y ^ 5\n [4, 3] = x ^ 3\n [3, 4] = y ^ 3\n ⋮\n [5, 5] = x ^ 5 * y ^ 3\n [6, 5] = x ^ 5\n [5, 6] = y ^ 5\n [6, 6] = x ^ 6 * y ^ 2\n [7, 6] = x ^ 6\n [6, 7] = y ^ 6\n [7, 7] = x ^ 7 * y ^ 1\n [8, 7] = x ^ 7\n [7, 8] = y ^ 7\n [8, 8] = x ^ 8 * y ^ 0","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"Now we call build_function:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"build_function(A,[x,y],parallel=ModelingToolkit.MultithreadedForm())[2]","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"which generates the code:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"(var\"##MTIIPVar#317\", var\"##MTKArg#315\")->begin\n @inbounds begin\n @sync begin\n let (x, y) = (var\"##MTKArg#315\"[1], var\"##MTKArg#315\"[2])\n begin\n Threads.@spawn begin\n (var\"##MTIIPVar#317\").nzval[1] = (getproperty(Base, :*))((getproperty(Base, :^))(x, 1), (getproperty(Base, :^))(y, 7))\n (var\"##MTIIPVar#317\").nzval[2] = (getproperty(Base, :^))(x, 1)\n (var\"##MTIIPVar#317\").nzval[3] = (getproperty(Base, :^))(y, 1)\n (var\"##MTIIPVar#317\").nzval[4] = (getproperty(Base, :*))((getproperty(Base, :^))(x, 2), (getproperty(Base, :^))(y, 6))\n (var\"##MTIIPVar#317\").nzval[5] = (getproperty(Base, :^))(x, 2)\n (var\"##MTIIPVar#317\").nzval[6] = (getproperty(Base, :^))(y, 2)\n end\n end\n begin\n Threads.@spawn begin\n (var\"##MTIIPVar#317\").nzval[7] = (getproperty(Base, :*))((getproperty(Base, :^))(x, 3), (getproperty(Base, :^))(y, 5))\n (var\"##MTIIPVar#317\").nzval[8] = (getproperty(Base, :^))(x, 3)\n (var\"##MTIIPVar#317\").nzval[9] = (getproperty(Base, :^))(y, 3)\n (var\"##MTIIPVar#317\").nzval[10] = (getproperty(Base, :*))((getproperty(Base, :^))(x, 4), (getproperty(Base, :^))(y, 4))\n (var\"##MTIIPVar#317\").nzval[11] = (getproperty(Base, :^))(x, 4)\n (var\"##MTIIPVar#317\").nzval[12] = (getproperty(Base, :^))(y, 4)\n end\n end\n begin\n Threads.@spawn begin\n (var\"##MTIIPVar#317\").nzval[13] = (getproperty(Base, :*))((getproperty(Base, :^))(x, 5), (getproperty(Base, :^))(y, 3))\n (var\"##MTIIPVar#317\").nzval[14] = (getproperty(Base, :^))(x, 5)\n (var\"##MTIIPVar#317\").nzval[15] = (getproperty(Base, :^))(y, 5)\n (var\"##MTIIPVar#317\").nzval[16] = (getproperty(Base, :*))((getproperty(Base, :^))(x, 6), (getproperty(Base, :^))(y, 2))\n (var\"##MTIIPVar#317\").nzval[17] = (getproperty(Base, :^))(x, 6)\n (var\"##MTIIPVar#317\").nzval[18] = (getproperty(Base, :^))(y, 6)\n end\n end\n begin\n Threads.@spawn begin\n (var\"##MTIIPVar#317\").nzval[19] = (getproperty(Base, :*))((getproperty(Base, :^))(x, 7), (getproperty(Base, :^))(y, 1))\n (var\"##MTIIPVar#317\").nzval[20] = (getproperty(Base, :^))(x, 7)\n (var\"##MTIIPVar#317\").nzval[21] = (getproperty(Base, :^))(y, 7)\n (var\"##MTIIPVar#317\").nzval[22] = (getproperty(Base, :*))((getproperty(Base, :^))(x, 8), (getproperty(Base, :^))(y, 0))\n end\n end\n end\n end\n end\n nothing\n end","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"Let's unpack what that's doing. It's using A.nzval in order to linearly index through the sparse matrix, avoiding the A[i,j] form because that is a more expensive way to index a sparse matrix if you know exactly the order that the data is stored. Then, it's splitting up the calculation into Julia threads so they can be operated on in parallel. It synchronizes after spawning all of the tasks so the computation is ensured to be complete before moving on. And it does this with all in-place operations to the original matrix instead of generating arrays. This is the fanciest way you could fill a sparse matrix, and ModelingToolkit makes this dead simple.","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"(Note: this example may be slower with multithreading due to the thread spawning overhead, but the full version was not included in the documentation for brevity. It will be the faster version if N is sufficiently large!)","category":"page"},{"location":"tutorials/symbolic_functions/#Derivatives-1","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Derivatives","text":"","category":"section"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"One common thing to compute in a symbolic system is derivatives. In ModelingToolkit.jl, derivatives are represented lazily via operations, just like any other function. To build a differential operator, use @derivatives like:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"@variables t\n@derivatives D'~t","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"This is the differential operator D = fracpartialpartial t: the number of ' is the order of the derivative and the second variable is the variable we're differentiating by. Now let's write down the derivative of some expression:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"z = t + t^2\nD(z) # derivative(t + t ^ 2, t)","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"Notice that this hasn't computed anything yet: D is a lazy operator because it lets us symbolically represent \"The derivative of z with respect to t\", which is useful for example when representing our favorite thing in the world, differential equations. However, if we want to expand the derivative operators, we'd use expand_derivatives:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"expand_derivatives(D(z)) # 1 + 2t","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"We can also have simplified functions for multivariable calculus. For example, we can compute the Jacobian of an array of expressions like:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"ModelingToolkit.jacobian([x+x*y,x^2+y],[x,y])\n\n2×2 Array{Num,2}:\n 1 + y x\n 2x Constant(1)","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"and similarly we can do Hessians, gradients, and define whatever other derivatives you want.","category":"page"},{"location":"tutorials/symbolic_functions/#Simplification-and-Substitution-1","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Simplification and Substitution","text":"","category":"section"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"ModelingToolkit interfaces with SymbolicUtils.jl to allow for simplifying symbolic expressions. This is done simply through the simplify command:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"simplify(t+t) # 2t","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"This can be applied to arrays by using Julia's broadcast mechanism:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"B = simplify.([t^2+t+t^2 2t+4t\n x+y+y+2t x^2 - x^2 + y^2])\n\n2×2 Array{Num,2}:\n 2 * t ^ 2 + t 6t\nx + 2 * (t + y) y ^ 2","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"We can then use substitute to change values of an expression around:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"simplify.(substitute.(B,[x=>y^2]))\n\n2×2 Array{Num,2}:\n 2 * t ^ 2 + t 6t\n y ^ 2 + 2 * (t + y) y ^ 2","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"and we can use this to interactively evaluate expressions without generating and compiling Julia functions:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"substitute.(B,([x=>2.0,y=>3.0,t=>4.0],))\n\n2×2 Array{ModelingToolkit.Constant,2}:\n Constant(36.0) Constant(24.0)\n Constant(16.0) Constant(9.0)","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"Where we can reference the values via:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"ModelingToolkit.Constant(2.0).value # 2.0","category":"page"},{"location":"tutorials/symbolic_functions/#Non-Interactive-Development-(No-Macro-Version)-1","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Non-Interactive Development (No Macro Version)","text":"","category":"section"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"Note that the macros are for the high-level case where you're doing symbolic computation on your own code. If you want to do symbolic computation on someone else's code, like in a macro, you may not want to do @variables x because you might want the name \"x\" to come from the user's code. For these cases, ModelingToolkit.jl allows for fully macro-free usage. For example:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"x = Num(Sym{Float64}(:x))\ny = Num(Sym{Float64}(:y))\nx+y^2.0 # isa Num\n\nt = Num(Variable{ModelingToolkit.Parameter{Real}}(:t)) # independent variables are treated as known\nα = Num(Variable{ModelingToolkit.Parameter{Real}}(:α)) # parameters are known\nσ = Num(Variable{ModelingToolkit.FnType{Tuple{Any},Real}}(:σ)) # left uncalled, since it is used as a function\nw = Num(Variable{ModelingToolkit.FnType{Tuple{Any},Real}}(:w)) # unknown, left uncalled\nx = Num(Variable{ModelingToolkit.FnType{Tuple{Any},Real}}(:x))(t) # unknown, depends on `t`\ny = Num(Variable(:y)) # unknown, no dependents\nz = Num(Variable{ModelingToolkit.FnType{NTuple{3,Any},Real}}(:z))(t, α, x) # unknown, multiple arguments\nβ₁ = Num(Variable(:β, 1)) # with index 1\nβ₂ = Num(Variable(:β, 2)) # with index 2\n\nexpr = β₁ * x + y^α + σ(3) * (z - t) - β₂ * w(t - 1)","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"Does what you'd expect. Note that Variable is simply a convenient function for making variables with indices that always returns Sym. The reference documentation shows how to define any of the quantities in such a way that the names can come from runtime values.","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"If we need to use this to generate new Julia code, we can simply convert the output to an Expr:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"toexpr(x+y^2)","category":"page"},{"location":"tutorials/symbolic_functions/#Syms-and-callable-Syms-1","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Syms and callable Syms","text":"","category":"section"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"In the definition","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"@variables t x(t) y(t)","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"t is of type Sym{Real} but the name x refers to an object that represents the Term x(t). The operation of this expression is itself the object Sym{FnType{Tuple{Real}, Real}}(:x). The type Sym{FnType{...}} represents a callable object. In this case specifically it's a function that takes 1 Real argument (noted by Tuple{Real}) and returns a Real result. You can call such a callable Sym with either a number or a symbolic expression of a permissible type.","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"this expression also defines t as a dependent variable while x(t) and y(t) are independent variables. This is accounted for in differentiation:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"z = x + y*t\nexpand_derivatives(D(z)) # derivative(x(t), t) + y(t) + derivative(y(t), t) * t","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"Since x and y are time-dependent, they are not automatically eliminated from the expression and thus the D(x) and D(y) operations still exist in the expanded derivatives for correctness.","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"We can also define unrestricted functions:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"@variables g(..)","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"Here g is a variable that is a function of other variables. Any time that we reference g we have to utilize it as a function:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"z = g(x) + g(y)","category":"page"},{"location":"tutorials/symbolic_functions/#Registering-Functions-1","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Registering Functions","text":"","category":"section"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"One of the benefits of a one-language Julia symbolic stack is that the primitives are all written in Julia, and therefore it's trivially extendable from Julia itself. By default, new functions are traced to the primitives and the symbolic expressions are written on the primitives. However, we can expand the allowed primitives by registering new functions. For example, let's register a new function h:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"h(x,y) = x^2 + y\n@register h(x,y)","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"Now when we use h(x,y), it is a symbolic expression and doesn't expand:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"h(x,y) + y^2","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"In order to use it with the differentiation system, we need to register its derivatives. We would do it like this:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"# Derivative w.r.t. the first argument\nModelingToolkit.derivative(::typeof(h), args::NTuple{2,Any}, ::Val{1}) = 2args[1]\n# Derivative w.r.t. the second argument\nModelingToolkit.derivative(::typeof(h), args::NTuple{2,Any}, ::Val{2}) = 1","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"and now it works with the rest of the system:","category":"page"},{"location":"tutorials/symbolic_functions/#","page":"Symbolic Calculations and Building Fast Parallel Functions","title":"Symbolic Calculations and Building Fast Parallel Functions","text":"@derivatives Dx'~x Dy'~y\nexpand_derivatives(Dx(h(x,y) + y^2)) # 2x\nexpand_derivatives(Dy(h(x,y) + y^2)) # 1 + 2y","category":"page"},{"location":"systems/PDESystem/#PDESystem-1","page":"PDESystem","title":"PDESystem","text":"","category":"section"},{"location":"systems/PDESystem/#","page":"PDESystem","title":"PDESystem","text":"PDESystem is still a work in progress.","category":"page"},{"location":"tutorials/modelingtoolkitize/#Symbolic-Extensions-to-ODEProblem-via-Modelingtoolkize-1","page":"Symbolic Extensions to ODEProblem via Modelingtoolkize","title":"Symbolic Extensions to ODEProblem via Modelingtoolkize","text":"","category":"section"},{"location":"tutorials/modelingtoolkitize/#","page":"Symbolic Extensions to ODEProblem via Modelingtoolkize","title":"Symbolic Extensions to ODEProblem via Modelingtoolkize","text":"For some DEProblem types, automatic tracing functionality is already included via the modelingtoolkitize function. Take, for example, the Robertson ODE defined as an ODEProblem for DifferentialEquations.jl:","category":"page"},{"location":"tutorials/modelingtoolkitize/#","page":"Symbolic Extensions to ODEProblem via Modelingtoolkize","title":"Symbolic Extensions to ODEProblem via Modelingtoolkize","text":"using DifferentialEquations\r\nfunction rober(du,u,p,t)\r\n y₁,y₂,y₃ = u\r\n k₁,k₂,k₃ = p\r\n du[1] = -k₁*y₁+k₃*y₂*y₃\r\n du[2] = k₁*y₁-k₂*y₂^2-k₃*y₂*y₃\r\n du[3] = k₂*y₂^2\r\n nothing\r\nend\r\nprob = ODEProblem(rober,[1.0,0.0,0.0],(0.0,1e5),(0.04,3e7,1e4))","category":"page"},{"location":"tutorials/modelingtoolkitize/#","page":"Symbolic Extensions to ODEProblem via Modelingtoolkize","title":"Symbolic Extensions to ODEProblem via Modelingtoolkize","text":"If we want to get a symbolic representation, we can simply call modelingtoolkitize on the prob, which will return an ODESystem:","category":"page"},{"location":"tutorials/modelingtoolkitize/#","page":"Symbolic Extensions to ODEProblem via Modelingtoolkize","title":"Symbolic Extensions to ODEProblem via Modelingtoolkize","text":"sys = modelingtoolkitize(prob)","category":"page"},{"location":"tutorials/modelingtoolkitize/#","page":"Symbolic Extensions to ODEProblem via Modelingtoolkize","title":"Symbolic Extensions to ODEProblem via Modelingtoolkize","text":"Using this, we can symbolically build the Jacobian and then rebuild the ODEProblem:","category":"page"},{"location":"tutorials/modelingtoolkitize/#","page":"Symbolic Extensions to ODEProblem via Modelingtoolkize","title":"Symbolic Extensions to ODEProblem via Modelingtoolkize","text":"jac = eval(ModelingToolkit.generate_jacobian(sys)[2])\r\nf = ODEFunction(rober, jac=jac)\r\nprob_jac = ODEProblem(f,[1.0,0.0,0.0],(0.0,1e5),(0.04,3e7,1e4))","category":"page"},{"location":"systems/OptimizationSystem/#OptimizationSystem-1","page":"OptimizationSystem","title":"OptimizationSystem","text":"","category":"section"},{"location":"systems/OptimizationSystem/#System-Constructors-1","page":"OptimizationSystem","title":"System Constructors","text":"","category":"section"},{"location":"systems/OptimizationSystem/#","page":"OptimizationSystem","title":"OptimizationSystem","text":"OptimizationSystem","category":"page"},{"location":"systems/OptimizationSystem/#ModelingToolkit.OptimizationSystem","page":"OptimizationSystem","title":"ModelingToolkit.OptimizationSystem","text":"struct OptimizationSystem <: ModelingToolkit.AbstractSystem\n\nA scalar equation for optimization.\n\nFields\n\nop\nVector of equations defining the system.\nstates\nUnknown variables.\nps\nParameters.\npins\nobserved\nequality_constraints\ninequality_constraints\nname\nName: the name of the system\n\nsystems\nsystems: The internal systems\n\nExamples\n\n@variables x y z\n@parameters σ ρ β\n\nop = σ*(y-x) + x*(ρ-z)-y + x*y - β*z\nos = OptimizationSystem(eqs, [x,y,z],[σ,ρ,β])\n\n\n\n\n\n","category":"type"},{"location":"systems/OptimizationSystem/#Composition-and-Accessor-Functions-1","page":"OptimizationSystem","title":"Composition and Accessor Functions","text":"","category":"section"},{"location":"systems/OptimizationSystem/#","page":"OptimizationSystem","title":"OptimizationSystem","text":"sys.eqs or equations(sys): The equation to be minimized.\nsys.states or states(sys): The set of states for the optimization.\nsys.parameters or parameters(sys): The parameters for the optimization.","category":"page"},{"location":"systems/OptimizationSystem/#Transformations-1","page":"OptimizationSystem","title":"Transformations","text":"","category":"section"},{"location":"systems/OptimizationSystem/#Applicable-Calculation-and-Generation-Functions-1","page":"OptimizationSystem","title":"Applicable Calculation and Generation Functions","text":"","category":"section"},{"location":"systems/OptimizationSystem/#","page":"OptimizationSystem","title":"OptimizationSystem","text":"calculate_gradient\r\ncalculate_hessian\r\ngenerate_gradient\r\ngenerate_hessian\r\nhessian_sparsity","category":"page"},{"location":"systems/OptimizationSystem/#Problem-Constructors-1","page":"OptimizationSystem","title":"Problem Constructors","text":"","category":"section"},{"location":"systems/OptimizationSystem/#","page":"OptimizationSystem","title":"OptimizationSystem","text":"OptimizationProblem","category":"page"},{"location":"systems/OptimizationSystem/#DiffEqBase.OptimizationProblem","page":"OptimizationSystem","title":"DiffEqBase.OptimizationProblem","text":"function DiffEqBase.OptimizationProblem{iip}(sys::OptimizationSystem,\n parammap=DiffEqBase.NullParameters();\n u0=nothing, lb=nothing, ub=nothing,\n grad = false,\n hess = false, sparse = false,\n checkbounds = false,\n linenumbers = true, parallel=SerialForm(),\n kwargs...) where iip\n\nGenerates an OptimizationProblem from an OptimizationSystem and allows for automatically symbolically calculating numerical enhancements.\n\n\n\n\n\n","category":"type"},{"location":"systems/AbstractSystem/#The-AbstractSystem-Interface-1","page":"The AbstractSystem Interface","title":"The AbstractSystem Interface","text":"","category":"section"},{"location":"systems/AbstractSystem/#Overview-1","page":"The AbstractSystem Interface","title":"Overview","text":"","category":"section"},{"location":"systems/AbstractSystem/#","page":"The AbstractSystem Interface","title":"The AbstractSystem Interface","text":"The AbstractSystem interface is the core of the system level of ModelingToolkit.jl. It establishes a common set of functionality that is used between systems from ODEs and chemical reactions, allowing users to have a common framework for model manipulation and compilation.","category":"page"},{"location":"systems/AbstractSystem/#Composition-and-Accessor-Functions-1","page":"The AbstractSystem Interface","title":"Composition and Accessor Functions","text":"","category":"section"},{"location":"systems/AbstractSystem/#","page":"The AbstractSystem Interface","title":"The AbstractSystem Interface","text":"Each AbstractSystem has lists of variables in context, such as distinguishing parameters vs states. In addition, an AbstractSystem also can hold other AbstractSystem types. Direct accessing of the values, such as sys.states, gives the immediate list, while the accessor functions states(sys) gives the total set, which includes that of all systems held inside.","category":"page"},{"location":"systems/AbstractSystem/#","page":"The AbstractSystem Interface","title":"The AbstractSystem Interface","text":"The values which are common to all AbstractSystems are:","category":"page"},{"location":"systems/AbstractSystem/#","page":"The AbstractSystem Interface","title":"The AbstractSystem Interface","text":"sys.eqs or equations(sys): The equations that define the system.\nsys.states or states(sys): The set of states in the system.\nsys.parameters or parameters(sys): The parameters of the system.\nsys.systems: The subsystems of the system.","category":"page"},{"location":"systems/AbstractSystem/#Transformations-1","page":"The AbstractSystem Interface","title":"Transformations","text":"","category":"section"},{"location":"systems/AbstractSystem/#","page":"The AbstractSystem Interface","title":"The AbstractSystem Interface","text":"Transformations are functions which send a valid AbstractSystem definition to another AbstractSystem. These are passes, like optimizations (e.g., Block-Lower Triangle transformations), or changes to the representation, which allow for alternative numerical methods to be utilized on the model (e.g., DAE index reduction).","category":"page"},{"location":"systems/AbstractSystem/#Function-Calculation-and-Generation-1","page":"The AbstractSystem Interface","title":"Function Calculation and Generation","text":"","category":"section"},{"location":"systems/AbstractSystem/#","page":"The AbstractSystem Interface","title":"The AbstractSystem Interface","text":"The calculation and generation functions allow for calculating additional quantities to enhance the numerical methods applied to the resulting system. The calculations, like calculate_jacobian, generate ModelingToolkit IR for the Jacobian of the system, while the generations, like generate_jacobian, generate compiled output for the numerical solvers by applying build_function to the generated code. Additionally, many systems have function-type outputs, which cobble together the generation functionality for a system, for example, ODEFunction can be used to generate a DifferentialEquations-based ODEFunction with compiled version of the ODE itself, the Jacobian, the mass matrix, etc.","category":"page"},{"location":"systems/AbstractSystem/#","page":"The AbstractSystem Interface","title":"The AbstractSystem Interface","text":"Below are the possible calculation and generation functions:","category":"page"},{"location":"systems/AbstractSystem/#","page":"The AbstractSystem Interface","title":"The AbstractSystem Interface","text":"calculate_tgrad\r\ncalculate_gradient\r\ncalculate_jacobian\r\ncalculate_factorized_W\r\ncalculate_hessian\r\ngenerate_tgrad\r\ngenerate_gradient\r\ngenerate_jacobian\r\ngenerate_factorized_W\r\ngenerate_hessian","category":"page"},{"location":"systems/AbstractSystem/#ModelingToolkit.calculate_tgrad","page":"The AbstractSystem Interface","title":"ModelingToolkit.calculate_tgrad","text":"calculate_tgrad(sys::AbstractSystem)\n\nCalculate the time gradient of a system.\n\nReturns a vector of Num instances. The result from the first call will be cached in the system object.\n\n\n\n\n\n","category":"function"},{"location":"systems/AbstractSystem/#ModelingToolkit.calculate_gradient","page":"The AbstractSystem Interface","title":"ModelingToolkit.calculate_gradient","text":"calculate_gradient(sys::AbstractSystem)\n\nCalculate the gradient of a scalar system.\n\nReturns a vector of Num instances. The result from the first call will be cached in the system object.\n\n\n\n\n\n","category":"function"},{"location":"systems/AbstractSystem/#ModelingToolkit.calculate_jacobian","page":"The AbstractSystem Interface","title":"ModelingToolkit.calculate_jacobian","text":"calculate_jacobian(sys::AbstractSystem)\n\nCalculate the jacobian matrix of a system.\n\nReturns a matrix of Num instances. The result from the first call will be cached in the system object.\n\n\n\n\n\n","category":"function"},{"location":"systems/AbstractSystem/#ModelingToolkit.calculate_factorized_W","page":"The AbstractSystem Interface","title":"ModelingToolkit.calculate_factorized_W","text":"calculate_factorized_W(sys::AbstractSystem)\n\nCalculate the factorized W-matrix of a system.\n\nReturns a matrix of Num instances. The result from the first call will be cached in the system object.\n\n\n\n\n\n","category":"function"},{"location":"systems/AbstractSystem/#ModelingToolkit.calculate_hessian","page":"The AbstractSystem Interface","title":"ModelingToolkit.calculate_hessian","text":"calculate_hessian(sys::AbstractSystem)\n\nCalculate the hessian matrix of a scalar system.\n\nReturns a matrix of Num instances. The result from the first call will be cached in the system object.\n\n\n\n\n\n","category":"function"},{"location":"systems/AbstractSystem/#ModelingToolkit.generate_tgrad","page":"The AbstractSystem Interface","title":"ModelingToolkit.generate_tgrad","text":"generate_tgrad(sys::AbstractSystem, dvs = states(sys), ps = parameters(sys), expression = Val{true}; kwargs...)\n\nGenerates a function for the time gradient of a system. Extra arguments control the arguments to the internal build_function call.\n\n\n\n\n\n","category":"function"},{"location":"systems/AbstractSystem/#ModelingToolkit.generate_gradient","page":"The AbstractSystem Interface","title":"ModelingToolkit.generate_gradient","text":"generate_gradient(sys::AbstractSystem, dvs = states(sys), ps = parameters(sys), expression = Val{true}; kwargs...)\n\nGenerates a function for the gradient of a system. Extra arguments control the arguments to the internal build_function call.\n\n\n\n\n\n","category":"function"},{"location":"systems/AbstractSystem/#ModelingToolkit.generate_jacobian","page":"The AbstractSystem Interface","title":"ModelingToolkit.generate_jacobian","text":"generate_jacobian(sys::AbstractSystem, dvs = states(sys), ps = parameters(sys), expression = Val{true}; sparse = false, kwargs...)\n\nGenerates a function for the jacobian matrix matrix of a system. Extra arguments control the arguments to the internal build_function call.\n\n\n\n\n\n","category":"function"},{"location":"systems/AbstractSystem/#ModelingToolkit.generate_factorized_W","page":"The AbstractSystem Interface","title":"ModelingToolkit.generate_factorized_W","text":"generate_factorized_W(sys::AbstractSystem, dvs = states(sys), ps = parameters(sys), expression = Val{true}; sparse = false, kwargs...)\n\nGenerates a function for the factorized W-matrix matrix of a system. Extra arguments control the arguments to the internal build_function call.\n\n\n\n\n\n","category":"function"},{"location":"systems/AbstractSystem/#ModelingToolkit.generate_hessian","page":"The AbstractSystem Interface","title":"ModelingToolkit.generate_hessian","text":"generate_hessian(sys::AbstractSystem, dvs = states(sys), ps = parameters(sys), expression = Val{true}; sparse = false, kwargs...)\n\nGenerates a function for the hessian matrix matrix of a system. Extra arguments control the arguments to the internal build_function call.\n\n\n\n\n\n","category":"function"},{"location":"systems/AbstractSystem/#","page":"The AbstractSystem Interface","title":"The AbstractSystem Interface","text":"Additionally, jacobian_sparsity(sys) and hessian_sparsity(sys) exist on the appropriate systems for fast generation of the sparsity patterns via an abstract interpretation without requiring differentiation.","category":"page"},{"location":"systems/AbstractSystem/#Problem-Constructors-1","page":"The AbstractSystem Interface","title":"Problem Constructors","text":"","category":"section"},{"location":"systems/AbstractSystem/#","page":"The AbstractSystem Interface","title":"The AbstractSystem Interface","text":"At the end, the system types have DEProblem constructors, like ODEProblem, which allow for directly generating the problem types required for numerical methods. The first argument is always the AbstractSystem, and the proceeding arguments match the argument order of their original constructors. Whenever an array would normally be provided, such as u0 the initial condition of an ODEProblem, it is instead replaced with a variable map, i.e., an array of pairs var=>value, which allows the user to designate the values without having to know the order that ModelingToolkit is internally using.","category":"page"},{"location":"tutorials/higher_order/#Automatic-Transformation-of-Nth-Order-ODEs-to-1st-Order-ODEs-1","page":"Automatic Transformation of Nth Order ODEs to 1st Order ODEs","title":"Automatic Transformation of Nth Order ODEs to 1st Order ODEs","text":"","category":"section"},{"location":"tutorials/higher_order/#","page":"Automatic Transformation of Nth Order ODEs to 1st Order ODEs","title":"Automatic Transformation of Nth Order ODEs to 1st Order ODEs","text":"ModelingToolkit has a system for transformations of mathematical systems. These transformations allow for symbolically changing the representation of the model to problems that are easier to numerically solve. One simple to demonstrate transformation is the ode_order_lowering transformation that sends an Nth order ODE to a 1st order ODE.","category":"page"},{"location":"tutorials/higher_order/#","page":"Automatic Transformation of Nth Order ODEs to 1st Order ODEs","title":"Automatic Transformation of Nth Order ODEs to 1st Order ODEs","text":"To see this, let's define a second order riff on the Lorenz equations. We utilize the derivative operator twice here to define the second order:","category":"page"},{"location":"tutorials/higher_order/#","page":"Automatic Transformation of Nth Order ODEs to 1st Order ODEs","title":"Automatic Transformation of Nth Order ODEs to 1st Order ODEs","text":"using ModelingToolkit, OrdinaryDiffEq\r\n\r\n@parameters t σ ρ β\r\n@variables x(t) y(t) z(t)\r\n@derivatives D'~t\r\n\r\neqs = [D(D(x)) ~ σ*(y-x),\r\n D(y) ~ x*(ρ-z)-y,\r\n D(z) ~ x*y - β*z]\r\n\r\nsys = ODESystem(eqs)","category":"page"},{"location":"tutorials/higher_order/#","page":"Automatic Transformation of Nth Order ODEs to 1st Order ODEs","title":"Automatic Transformation of Nth Order ODEs to 1st Order ODEs","text":"Note that we could've used an alternative syntax for 2nd order, i.e. @derivatives E''~t and then E(x) would be the second derivative, and this syntax extends to Nth order.","category":"page"},{"location":"tutorials/higher_order/#","page":"Automatic Transformation of Nth Order ODEs to 1st Order ODEs","title":"Automatic Transformation of Nth Order ODEs to 1st Order ODEs","text":"Now let's transform this into the ODESystem of first order components. We do this by simply calling ode_order_lowering:","category":"page"},{"location":"tutorials/higher_order/#","page":"Automatic Transformation of Nth Order ODEs to 1st Order ODEs","title":"Automatic Transformation of Nth Order ODEs to 1st Order ODEs","text":"sys = ode_order_lowering(sys)","category":"page"},{"location":"tutorials/higher_order/#","page":"Automatic Transformation of Nth Order ODEs to 1st Order ODEs","title":"Automatic Transformation of Nth Order ODEs to 1st Order ODEs","text":"Now we can directly numerically solve the lowered system. Note that, following the original problem, the solution requires knowing the initial condition for x', and thus we include that in our input specification:","category":"page"},{"location":"tutorials/higher_order/#","page":"Automatic Transformation of Nth Order ODEs to 1st Order ODEs","title":"Automatic Transformation of Nth Order ODEs to 1st Order ODEs","text":"u0 = [D(x) => 2.0,\r\n x => 1.0,\r\n y => 0.0,\r\n z => 0.0]\r\n\r\np = [σ => 28.0,\r\n ρ => 10.0,\r\n β => 8/3]\r\n\r\ntspan = (0.0,100.0)\r\nprob = ODEProblem(sys,u0,tspan,p,jac=true)\r\nsol = solve(prob,Tsit5())\r\nusing Plots; plot(sol,vars=(x,y))","category":"page"},{"location":"tutorials/higher_order/#","page":"Automatic Transformation of Nth Order ODEs to 1st Order ODEs","title":"Automatic Transformation of Nth Order ODEs to 1st Order ODEs","text":"(Image: Lorenz2)","category":"page"},{"location":"tutorials/auto_parallel/#Automated-Sparse-Parallelism-of-ODEs-via-Tracing-1","page":"Automated Sparse Parallelism of ODEs via Tracing","title":"Automated Sparse Parallelism of ODEs via Tracing","text":"","category":"section"},{"location":"tutorials/auto_parallel/#","page":"Automated Sparse Parallelism of ODEs via Tracing","title":"Automated Sparse Parallelism of ODEs via Tracing","text":"Because the ModelingToolkit expressions obey Julia semantics, one can directly transform existing Julia functions into ModelingToolkit symbolic representations of the function by simply inputting the symbolic values into the function and using what is returned. For example, let's take the following numerical PDE discretization:","category":"page"},{"location":"tutorials/auto_parallel/#","page":"Automated Sparse Parallelism of ODEs via Tracing","title":"Automated Sparse Parallelism of ODEs via Tracing","text":"using ModelingToolkit, LinearAlgebra, SparseArrays\r\n\r\n# Define the constants for the PDE\r\nconst α₂ = 1.0\r\nconst α₃ = 1.0\r\nconst β₁ = 1.0\r\nconst β₂ = 1.0\r\nconst β₃ = 1.0\r\nconst r₁ = 1.0\r\nconst r₂ = 1.0\r\nconst _DD = 100.0\r\nconst γ₁ = 0.1\r\nconst γ₂ = 0.1\r\nconst γ₃ = 0.1\r\nconst N = 32\r\nconst X = reshape([i for i in 1:N for j in 1:N],N,N)\r\nconst Y = reshape([j for i in 1:N for j in 1:N],N,N)\r\nconst α₁ = 1.0.*(X.>=4*N/5)\r\n\r\nconst Mx = Array(Tridiagonal([1.0 for i in 1:N-1],[-2.0 for i in 1:N],[1.0 for i in 1:N-1]))\r\nconst My = copy(Mx)\r\nMx[2,1] = 2.0\r\nMx[end-1,end] = 2.0\r\nMy[1,2] = 2.0\r\nMy[end,end-1] = 2.0\r\n\r\n# Define the discretized PDE as an ODE function\r\nfunction f(u,p,t)\r\n A = u[:,:,1]\r\n B = u[:,:,2]\r\n C = u[:,:,3]\r\n MyA = My*A\r\n AMx = A*Mx\r\n DA = @. _DD*(MyA + AMx)\r\n dA = @. DA + α₁ - β₁*A - r₁*A*B + r₂*C\r\n dB = @. α₂ - β₂*B - r₁*A*B + r₂*C\r\n dC = @. α₃ - β₃*C + r₁*A*B - r₂*C\r\n cat(dA,dB,dC,dims=3)\r\nend","category":"page"},{"location":"tutorials/auto_parallel/#","page":"Automated Sparse Parallelism of ODEs via Tracing","title":"Automated Sparse Parallelism of ODEs via Tracing","text":"We can build the ModelingToolkit version of this model by tracing the model function:","category":"page"},{"location":"tutorials/auto_parallel/#","page":"Automated Sparse Parallelism of ODEs via Tracing","title":"Automated Sparse Parallelism of ODEs via Tracing","text":"# Define the initial condition as normal arrays\r\n@variables u[1:N,1:N,1:3]\r\ndu = simplify.(f(u,nothing,0.0))","category":"page"},{"location":"tutorials/auto_parallel/#","page":"Automated Sparse Parallelism of ODEs via Tracing","title":"Automated Sparse Parallelism of ODEs via Tracing","text":"The output, here the in-place modified du, is a symbolic representation of each output of the function. We can then utilize this in the ModelingToolkit functionality. For example, let's build a parallel version of f first:","category":"page"},{"location":"tutorials/auto_parallel/#","page":"Automated Sparse Parallelism of ODEs via Tracing","title":"Automated Sparse Parallelism of ODEs via Tracing","text":"fastf = eval(ModelingToolkit.build_function(du,u,\r\n parallel=ModelingToolkit.MultithreadedForm())[2])","category":"page"},{"location":"tutorials/auto_parallel/#","page":"Automated Sparse Parallelism of ODEs via Tracing","title":"Automated Sparse Parallelism of ODEs via Tracing","text":"Now let's compute the sparse Jacobian function and compile a fast multithreaded version:","category":"page"},{"location":"tutorials/auto_parallel/#","page":"Automated Sparse Parallelism of ODEs via Tracing","title":"Automated Sparse Parallelism of ODEs via Tracing","text":"jac = ModelingToolkit.sparsejacobian(vec(du),vec(u))\r\nfjac = eval(ModelingToolkit.build_function(jac,u,\r\n parallel=ModelingToolkit.MultithreadedForm())[2])","category":"page"},{"location":"tutorials/auto_parallel/#","page":"Automated Sparse Parallelism of ODEs via Tracing","title":"Automated Sparse Parallelism of ODEs via Tracing","text":"It takes awhile for this to generate, but the results will be worth it! Now let's setup the parabolic PDE to be solved by DifferentialEquations.jl. We will setup the vanilla version and the sparse multithreaded version:","category":"page"},{"location":"tutorials/auto_parallel/#","page":"Automated Sparse Parallelism of ODEs via Tracing","title":"Automated Sparse Parallelism of ODEs via Tracing","text":"using OrdinaryDiffEq\r\nu0 = zeros(N,N,3)\r\nMyA = zeros(N,N);\r\nAMx = zeros(N,N);\r\nDA = zeros(N,N);\r\nprob = ODEProblem(f!,u0,(0.0,10.0))\r\nfastprob = ODEProblem(ODEFunction((du,u,p,t)->fastf(du,u),\r\n jac = (du,u,p,t) -> fjac(du,u),\r\n jac_prototype = similar(jac,Float64)),\r\n u0,(0.0,10.0))","category":"page"},{"location":"tutorials/auto_parallel/#","page":"Automated Sparse Parallelism of ODEs via Tracing","title":"Automated Sparse Parallelism of ODEs via Tracing","text":"Let's see the timing difference:","category":"page"},{"location":"tutorials/auto_parallel/#","page":"Automated Sparse Parallelism of ODEs via Tracing","title":"Automated Sparse Parallelism of ODEs via Tracing","text":"using BenchmarkTools\r\n@btime solve(prob, TRBDF2()) # 33.073 s (895404 allocations: 23.87 GiB)\r\n@btime solve(fastprob, TRBDF2()) # 209.670 ms (8208 allocations: 109.25 MiB)","category":"page"},{"location":"tutorials/auto_parallel/#","page":"Automated Sparse Parallelism of ODEs via Tracing","title":"Automated Sparse Parallelism of ODEs via Tracing","text":"Boom, an automatic 157x acceleration that grows as the size of the problem increases!","category":"page"},{"location":"tutorials/converting_to_C/#Automatic-Conversion-of-Julia-Code-to-C-Functions-1","page":"Automatic Conversion of Julia Code to C Functions","title":"Automatic Conversion of Julia Code to C Functions","text":"","category":"section"},{"location":"tutorials/converting_to_C/#","page":"Automatic Conversion of Julia Code to C Functions","title":"Automatic Conversion of Julia Code to C Functions","text":"Since ModelingToolkit can trace Julia code into MTK IR that can be built and compiled via build_function to C, this gives us a nifty way to automatically generate C functions from Julia code! To see this in action, let's start with the Lotka-Volterra equations:","category":"page"},{"location":"tutorials/converting_to_C/#","page":"Automatic Conversion of Julia Code to C Functions","title":"Automatic Conversion of Julia Code to C Functions","text":"using ModelingToolkit\nfunction lotka_volterra!(du, u, p, t)\n x, y = u\n α, β, δ, γ = p\n du[1] = dx = α*x - β*x*y\n du[2] = dy = -δ*y + γ*x*y\nend","category":"page"},{"location":"tutorials/converting_to_C/#","page":"Automatic Conversion of Julia Code to C Functions","title":"Automatic Conversion of Julia Code to C Functions","text":"Now we trace this into ModelingToolkit:","category":"page"},{"location":"tutorials/converting_to_C/#","page":"Automatic Conversion of Julia Code to C Functions","title":"Automatic Conversion of Julia Code to C Functions","text":"@variables t du[1:2] u[1:2] p[1:4]\nlotka_volterra!(du, u, p, t)","category":"page"},{"location":"tutorials/converting_to_C/#","page":"Automatic Conversion of Julia Code to C Functions","title":"Automatic Conversion of Julia Code to C Functions","text":"which gives:","category":"page"},{"location":"tutorials/converting_to_C/#","page":"Automatic Conversion of Julia Code to C Functions","title":"Automatic Conversion of Julia Code to C Functions","text":"du = Num[p₁ * u₁ - (p₂ * u₁) * u₂, -p₃ * u₂ + (p₄ * u₁) * u₂]","category":"page"},{"location":"tutorials/converting_to_C/#","page":"Automatic Conversion of Julia Code to C Functions","title":"Automatic Conversion of Julia Code to C Functions","text":"Now we build the equations we want to solve:","category":"page"},{"location":"tutorials/converting_to_C/#","page":"Automatic Conversion of Julia Code to C Functions","title":"Automatic Conversion of Julia Code to C Functions","text":"eqs = @. D(u) ~ du\n\n2-element Array{Equation,1}:\n Equation(derivative(u₁, t), p₁ * u₁ - (p₂ * u₁) * u₂)\n Equation(derivative(u₂, t), -p₃ * u₂ + (p₄ * u₁) * u₂)","category":"page"},{"location":"tutorials/converting_to_C/#","page":"Automatic Conversion of Julia Code to C Functions","title":"Automatic Conversion of Julia Code to C Functions","text":"and then we build the function:","category":"page"},{"location":"tutorials/converting_to_C/#","page":"Automatic Conversion of Julia Code to C Functions","title":"Automatic Conversion of Julia Code to C Functions","text":"build_function(eqs, u, p, t, target=ModelingToolkit.CTarget())\n\nvoid diffeqf(double* du, double* RHS1, double* RHS2, double RHS3) {\n du[0] = RHS2[0] * RHS1[0] - (RHS2[1] * RHS1[0]) * RHS1[1];\n du[1] = -(RHS2[2]) * RHS1[1] + (RHS2[3] * RHS1[0]) * RHS1[1];\n}","category":"page"},{"location":"tutorials/converting_to_C/#","page":"Automatic Conversion of Julia Code to C Functions","title":"Automatic Conversion of Julia Code to C Functions","text":"If we want to compile this, we do expression=Val{false}:","category":"page"},{"location":"tutorials/converting_to_C/#","page":"Automatic Conversion of Julia Code to C Functions","title":"Automatic Conversion of Julia Code to C Functions","text":"f = build_function(eqs, u, p, t, target=ModelingToolkit.CTarget(),expression=Val{false})","category":"page"},{"location":"tutorials/converting_to_C/#","page":"Automatic Conversion of Julia Code to C Functions","title":"Automatic Conversion of Julia Code to C Functions","text":"now we check it computes the same thing:","category":"page"},{"location":"tutorials/converting_to_C/#","page":"Automatic Conversion of Julia Code to C Functions","title":"Automatic Conversion of Julia Code to C Functions","text":"du = rand(2); du2 = rand(2)\nu = rand(2)\np = rand(4)\nt = rand()\nf(du,u,p,t)\nlotka_volterra!(du2, u, p, t)\ndu == du2 # true!","category":"page"},{"location":"build_function/#Function-Building-and-Compilation-(build_function)-1","page":"Function Building and Compilation (build_function)","title":"Function Building and Compilation (build_function)","text":"","category":"section"},{"location":"build_function/#","page":"Function Building and Compilation (build_function)","title":"Function Building and Compilation (build_function)","text":"At any time, callable functions can be generated from ModelingToolkit IR by using ModelingToolkit.toexpr. This performs some cleaning to return an expression without extraneous pieces that commonly matches expressions one would write in functions like those for differential equation solvers and optimization libraries. These functions can be automatically parallelize and specialize on Julia types like static arrays and sparse matrices.","category":"page"},{"location":"build_function/#","page":"Function Building and Compilation (build_function)","title":"Function Building and Compilation (build_function)","text":"The core compilation process of ModelingToolkit IR is build_function. build_function takes an operation or an AbstractArray of operations and generates a compilable version of the model for numerical solvers. The form of this output is dependent on the target. By default, the target outputs Julia code, but other formats, such as C, Stan, and MATLAB are available. These can be generated as expressions which can then be evaluated into a callable function, or the compilers for the respective targets can be invoked to directly give back the function handle.","category":"page"},{"location":"build_function/#build_function-1","page":"Function Building and Compilation (build_function)","title":"build_function","text":"","category":"section"},{"location":"build_function/#","page":"Function Building and Compilation (build_function)","title":"Function Building and Compilation (build_function)","text":"build_function","category":"page"},{"location":"build_function/#ModelingToolkit.build_function","page":"Function Building and Compilation (build_function)","title":"ModelingToolkit.build_function","text":"build_function\n\nGenerates a numerically-usable function from a ModelingToolkit Num.\n\nbuild_function(ex, args...;\n expression = Val{true},\n target = JuliaTarget(),\n\t\t\t kwargs...)\n\nArguments:\n\nex: The Num to compile\nargs: The arguments of the function\nexpression: Whether to generate code or whether to generate the compiled form. By default, expression = Val{true}, which means that the code for the function is returned. If Val{false}, then the returned value is compiled.\n\nKeyword Arguments:\n\ntarget: The output target of the compilation process. Possible options are:\nJuliaTarget: Generates a Julia function\nCTarget: Generates a C function\nStanTarget: Generates a function for compiling with the Stan probabilistic programming language\nMATLABTarget: Generates an anonymous function for use in MATLAB and Octave environments\nfname: Used by some targets for the name of the function in the target space.\n\nNote that not all build targets support the full compilation interface. Check the individual target documentation for details.\n\n\n\n\n\n","category":"function"},{"location":"build_function/#Target-Specific-Definitions-1","page":"Function Building and Compilation (build_function)","title":"Target-Specific Definitions","text":"","category":"section"},{"location":"build_function/#","page":"Function Building and Compilation (build_function)","title":"Function Building and Compilation (build_function)","text":"_build_function(target::JuliaTarget,args...;kwargs...)\n_build_function(target::CTarget,args...;kwargs...)\n_build_function(target::StanTarget,args...;kwargs...)\n_build_function(target::MATLABTarget,args...;kwargs...)","category":"page"},{"location":"systems/ODESystem/#ODESystem-1","page":"ODESystem","title":"ODESystem","text":"","category":"section"},{"location":"systems/ODESystem/#System-Constructors-1","page":"ODESystem","title":"System Constructors","text":"","category":"section"},{"location":"systems/ODESystem/#","page":"ODESystem","title":"ODESystem","text":"ODESystem","category":"page"},{"location":"systems/ODESystem/#ModelingToolkit.ODESystem","page":"ODESystem","title":"ModelingToolkit.ODESystem","text":"struct ODESystem <: ModelingToolkit.AbstractODESystem\n\nA system of ordinary differential equations.\n\nFields\n\neqs\nThe ODEs defining the system.\niv\nIndependent variable.\nstates\nDependent (state) variables.\nps\nParameter variables.\npins\nobserved\ntgrad\nTime-derivative matrix. Note: this field will not be defined until calculate_tgrad is called on the system.\n\njac\nJacobian matrix. Note: this field will not be defined until calculate_jacobian is called on the system.\n\nWfact\nWfact matrix. Note: this field will not be defined until generate_factorized_W is called on the system.\n\nWfact_t\nWfact_t matrix. Note: this field will not be defined until generate_factorized_W is called on the system.\n\nname\nName: the name of the system\n\nsystems\nsystems: The internal systems\n\nExample\n\nusing ModelingToolkit\n\n@parameters t σ ρ β\n@variables x(t) y(t) z(t)\n@derivatives D'~t\n\neqs = [D(x) ~ σ*(y-x),\n D(y) ~ x*(ρ-z)-y,\n D(z) ~ x*y - β*z]\n\nde = ODESystem(eqs,t,[x,y,z],[σ,ρ,β])\n\n\n\n\n\n","category":"type"},{"location":"systems/ODESystem/#Composition-and-Accessor-Functions-1","page":"ODESystem","title":"Composition and Accessor Functions","text":"","category":"section"},{"location":"systems/ODESystem/#","page":"ODESystem","title":"ODESystem","text":"sys.eqs or equations(sys): The equations that define the ODE.\nsys.states or states(sys): The set of states in the ODE.\nsys.parameters or parameters(sys): The parameters of the ODE.\nsys.iv or independent_variable(sys): The independent variable of the ODE.","category":"page"},{"location":"systems/ODESystem/#Transformations-1","page":"ODESystem","title":"Transformations","text":"","category":"section"},{"location":"systems/ODESystem/#","page":"ODESystem","title":"ODESystem","text":"ode_order_lowering","category":"page"},{"location":"systems/ODESystem/#ModelingToolkit.ode_order_lowering","page":"ODESystem","title":"ModelingToolkit.ode_order_lowering","text":"ode_order_lowering(sys::ODESystem) -> ODESystem\n\n\nTakes a Nth order ODESystem and returns a new ODESystem written in first order form by defining new variables which represent the N-1 derivatives.\n\n\n\n\n\n","category":"function"},{"location":"systems/ODESystem/#Applicable-Calculation-and-Generation-Functions-1","page":"ODESystem","title":"Applicable Calculation and Generation Functions","text":"","category":"section"},{"location":"systems/ODESystem/#","page":"ODESystem","title":"ODESystem","text":"calculate_jacobian\r\ncalculate_tgrad\r\ncalculate_factorized_W\r\ngenerate_jacobian\r\ngenerate_tgrad\r\ngenerate_factorized_W\r\njacobian_sparsity","category":"page"},{"location":"systems/ODESystem/#Problem-Constructors-1","page":"ODESystem","title":"Problem Constructors","text":"","category":"section"},{"location":"systems/ODESystem/#","page":"ODESystem","title":"ODESystem","text":"ODEFunction\r\nODEProblem","category":"page"},{"location":"systems/ODESystem/#DiffEqBase.ODEFunction","page":"ODESystem","title":"DiffEqBase.ODEFunction","text":"function DiffEqBase.ODEFunction{iip}(sys::AbstractODESystem, dvs = states(sys),\n ps = parameters(sys);\n version = nothing, tgrad=false,\n jac = false,\n sparse = false,\n kwargs...) where {iip}\n\nCreate an ODEFunction from the ODESystem. The arguments dvs and ps are used to set the order of the dependent variable and parameter vectors, respectively.\n\n\n\n\n\n","category":"type"},{"location":"systems/ODESystem/#DiffEqBase.ODEProblem","page":"ODESystem","title":"DiffEqBase.ODEProblem","text":"function DiffEqBase.ODEProblem{iip}(sys::AbstractODESystem,u0map,tspan,\n parammap=DiffEqBase.NullParameters();\n version = nothing, tgrad=false,\n jac = false,\n checkbounds = false, sparse = false,\n simplify = true,\n linenumbers = true, parallel=SerialForm(),\n kwargs...) where iip\n\nGenerates an ODEProblem from an ODESystem and allows for automatically symbolically calculating numerical enhancements.\n\n\n\n\n\n","category":"type"},{"location":"tutorials/nonlinear/#Solving-Nonlinear-Systems-with-NLsolve-1","page":"Solving Nonlinear Systems with NLsolve","title":"Solving Nonlinear Systems with NLsolve","text":"","category":"section"},{"location":"tutorials/nonlinear/#","page":"Solving Nonlinear Systems with NLsolve","title":"Solving Nonlinear Systems with NLsolve","text":"In this example we will go one step deeper and showcase the direct function generation capabilities in ModelingToolkit.jl to build nonlinear systems. Let's say we wanted to solve for the steady state of the previous ODE. This is the nonlinear system defined by where the derivatives are zero. We use (unknown) variables for our nonlinear system.","category":"page"},{"location":"tutorials/nonlinear/#","page":"Solving Nonlinear Systems with NLsolve","title":"Solving Nonlinear Systems with NLsolve","text":"using ModelingToolkit\r\n\r\n@variables x y z\r\n@parameters σ ρ β\r\n\r\n# Define a nonlinear system\r\neqs = [0 ~ σ*(y-x),\r\n 0 ~ x*(ρ-z)-y,\r\n 0 ~ x*y - β*z]\r\nns = NonlinearSystem(eqs, [x,y,z], [σ,ρ,β])\r\nnlsys_func = generate_function(ns)[2] # second is the inplace version","category":"page"},{"location":"tutorials/nonlinear/#","page":"Solving Nonlinear Systems with NLsolve","title":"Solving Nonlinear Systems with NLsolve","text":"which generates:","category":"page"},{"location":"tutorials/nonlinear/#","page":"Solving Nonlinear Systems with NLsolve","title":"Solving Nonlinear Systems with NLsolve","text":"(var\"##MTIIPVar#405\", u, p)->begin\r\n @inbounds begin\r\n @inbounds begin\r\n let (x, y, z, σ, ρ, β) = (u[1], u[2], u[3], p[1], p[2], p[3])\r\n var\"##MTIIPVar#405\"[1] = (*)(σ, (-)(y, x))\r\n var\"##MTIIPVar#405\"[2] = (-)((*)(x, (-)(ρ, z)), y)\r\n var\"##MTIIPVar#405\"[3] = (-)((*)(x, y), (*)(β, z))\r\n end\r\n end\r\n end\r\n nothing\r\n end","category":"page"},{"location":"tutorials/nonlinear/#","page":"Solving Nonlinear Systems with NLsolve","title":"Solving Nonlinear Systems with NLsolve","text":"We can use this to build a nonlinear function for use with NLsolve.jl:","category":"page"},{"location":"tutorials/nonlinear/#","page":"Solving Nonlinear Systems with NLsolve","title":"Solving Nonlinear Systems with NLsolve","text":"f = eval(nlsys_func)\r\ndu = zeros(3); u = ones(3)\r\nparams = (10.0,26.0,2.33)\r\nf(du,u,params)\r\ndu\r\n\r\n#=\r\n3-element Array{Float64,1}:\r\n 0.0\r\n 24.0\r\n -1.33\r\n =#","category":"page"},{"location":"tutorials/nonlinear/#","page":"Solving Nonlinear Systems with NLsolve","title":"Solving Nonlinear Systems with NLsolve","text":"We can similarly ask to generate the in-place Jacobian function:","category":"page"},{"location":"tutorials/nonlinear/#","page":"Solving Nonlinear Systems with NLsolve","title":"Solving Nonlinear Systems with NLsolve","text":"j_func = generate_jacobian(ns)[2] # second is in-place\r\nj! = eval(j_func)","category":"page"},{"location":"tutorials/nonlinear/#","page":"Solving Nonlinear Systems with NLsolve","title":"Solving Nonlinear Systems with NLsolve","text":"which gives:","category":"page"},{"location":"tutorials/nonlinear/#","page":"Solving Nonlinear Systems with NLsolve","title":"Solving Nonlinear Systems with NLsolve","text":":((var\"##MTIIPVar#582\", u, p)->begin\r\n #= C:\\Users\\accou\\.julia\\dev\\ModelingToolkit\\src\\utils.jl:70 =#\r\n #= C:\\Users\\accou\\.julia\\dev\\ModelingToolkit\\src\\utils.jl:71 =#\r\n #= C:\\Users\\accou\\.julia\\dev\\ModelingToolkit\\src\\utils.jl:71 =# @inbounds begin\r\n #= C:\\Users\\accou\\.julia\\dev\\ModelingToolkit\\src\\utils.jl:72 =#\r\n #= C:\\Users\\accou\\.julia\\dev\\ModelingToolkit\\src\\utils.jl:53 =# @inbounds begin\r\n #= C:\\Users\\accou\\.julia\\dev\\ModelingToolkit\\src\\utils.jl:53 =#\r\n let (x, y, z, σ, ρ, β) = (u[1], u[2], u[3], p[1], p[2], p[3])\r\n var\"##MTIIPVar#582\"[1] = (*)(σ, -1)\r\n var\"##MTIIPVar#582\"[2] = (-)(ρ, z)\r\n var\"##MTIIPVar#582\"[3] = y\r\n var\"##MTIIPVar#582\"[4] = σ\r\n var\"##MTIIPVar#582\"[5] = -1\r\n var\"##MTIIPVar#582\"[6] = x\r\n var\"##MTIIPVar#582\"[7] = 0\r\n var\"##MTIIPVar#582\"[8] = (*)(x, -1)\r\n var\"##MTIIPVar#582\"[9] = (*)(-1, β)\r\n end\r\n end\r\n end\r\n #= C:\\Users\\accou\\.julia\\dev\\ModelingToolkit\\src\\utils.jl:74 =#\r\n nothing\r\n end)","category":"page"},{"location":"tutorials/nonlinear/#","page":"Solving Nonlinear Systems with NLsolve","title":"Solving Nonlinear Systems with NLsolve","text":"Now, we can call nlsolve by enclosing our parameters into the functions:","category":"page"},{"location":"tutorials/nonlinear/#","page":"Solving Nonlinear Systems with NLsolve","title":"Solving Nonlinear Systems with NLsolve","text":"using NLsolve\r\nnlsolve((out, x) -> f(out, x, params), (out, x) -> j!(out, x, params), ones(3))","category":"page"},{"location":"tutorials/nonlinear/#","page":"Solving Nonlinear Systems with NLsolve","title":"Solving Nonlinear Systems with NLsolve","text":"If one would like the generated function to be a Julia function instead of an expression, and allow this function to be used from within the same world-age, one simply needs to pass Val{false} to tell it to generate the function, i.e.:","category":"page"},{"location":"tutorials/nonlinear/#","page":"Solving Nonlinear Systems with NLsolve","title":"Solving Nonlinear Systems with NLsolve","text":"nlsys_func = generate_function(ns, [x,y,z], [σ,ρ,β], expression=Val{false})[2]","category":"page"},{"location":"tutorials/nonlinear/#","page":"Solving Nonlinear Systems with NLsolve","title":"Solving Nonlinear Systems with NLsolve","text":"which uses GeneralizedGenerated.jl to build the same world-age function on the fly without eval.","category":"page"},{"location":"systems/JumpSystem/#JumpSystem-1","page":"JumpSystem","title":"JumpSystem","text":"","category":"section"},{"location":"systems/JumpSystem/#System-Constructors-1","page":"JumpSystem","title":"System Constructors","text":"","category":"section"},{"location":"systems/JumpSystem/#","page":"JumpSystem","title":"JumpSystem","text":"JumpSystem","category":"page"},{"location":"systems/JumpSystem/#ModelingToolkit.JumpSystem","page":"JumpSystem","title":"ModelingToolkit.JumpSystem","text":"struct JumpSystem{U<:RecursiveArrayTools.ArrayPartition} <: ModelingToolkit.AbstractSystem\n\nA system of jump processes.\n\nFields\n\neqs\nThe jumps of the system. Allowable types are ConstantRateJump, VariableRateJump, MassActionJump.\n\niv\nThe independent variable, usually time.\nstates\nThe dependent variables, representing the state of the system.\nps\nThe parameters of the system.\npins\nobserved\nname\nThe name of the system.\nsystems\nThe internal systems.\n\nExample\n\nusing ModelingToolkit\n\n@parameters β γ t\n@variables S I R\nrate₁ = β*S*I\naffect₁ = [S ~ S - 1, I ~ I + 1]\nrate₂ = γ*I\naffect₂ = [I ~ I - 1, R ~ R + 1]\nj₁ = ConstantRateJump(rate₁,affect₁)\nj₂ = ConstantRateJump(rate₂,affect₂)\nj₃ = MassActionJump(2*β+γ, [R => 1], [S => 1, R => -1])\njs = JumpSystem([j₁,j₂,j₃], t, [S,I,R], [β,γ])\n\n\n\n\n\n","category":"type"},{"location":"systems/JumpSystem/#Composition-and-Accessor-Functions-1","page":"JumpSystem","title":"Composition and Accessor Functions","text":"","category":"section"},{"location":"systems/JumpSystem/#","page":"JumpSystem","title":"JumpSystem","text":"sys.eqs or equations(sys): The equations that define the jump system.\nsys.states or states(sys): The set of states in the jump system.\nsys.parameters or parameters(sys): The parameters of the jump system.\nsys.iv or independent_variable(sys): The independent variable of the jump system.","category":"page"},{"location":"systems/JumpSystem/#Problem-Constructors-1","page":"JumpSystem","title":"Problem Constructors","text":"","category":"section"},{"location":"systems/JumpSystem/#","page":"JumpSystem","title":"JumpSystem","text":"DiscreteProblem\nJumpProblem","category":"page"},{"location":"systems/JumpSystem/#DiffEqBase.DiscreteProblem","page":"JumpSystem","title":"DiffEqBase.DiscreteProblem","text":"function DiffEqBase.DiscreteProblem(sys::JumpSystem, u0map, tspan,\n parammap=DiffEqBase.NullParameters; kwargs...)\n\nGenerates a blank DiscreteProblem for a pure jump JumpSystem to utilize as its prob.prob. This is used in the case where there are no ODEs and no SDEs associated with the system.\n\nContinuing the example from the JumpSystem definition:\n\nusing DiffEqBase, DiffEqJump\nu₀map = [S => 999, I => 1, R => 0]\nparammap = [β => .1/1000, γ => .01]\ntspan = (0.0, 250.0)\ndprob = DiscreteProblem(js, u₀map, tspan, parammap)\n\n\n\n\n\n","category":"type"},{"location":"systems/JumpSystem/#DiffEqJump.JumpProblem","page":"JumpSystem","title":"DiffEqJump.JumpProblem","text":"function DiffEqBase.JumpProblem(js::JumpSystem, prob, aggregator; kwargs...)\n\nGenerates a JumpProblem from a JumpSystem.\n\nContinuing the example from the DiscreteProblem definition:\n\njprob = JumpProblem(js, dprob, Direct())\nsol = solve(jprob, SSAStepper())\n\n\n\n\n\n","category":"type"},{"location":"#ModelingToolkit.jl-1","page":"Home","title":"ModelingToolkit.jl","text":"","category":"section"},{"location":"#","page":"Home","title":"Home","text":"ModelingToolkit.jl is a modeling language for high-performance symbolic-numeric computation in scientific computing and scientific machine learning. It allows for users to give a high-level description of a model for symbolic preprocessing to analyze and enhance the model. ModelingToolkit can automatically generate fast functions for model components like Jacobians and Hessians, along with automatically sparsifying and parallelizing the computations. Automatic transformations, such as index reduction, can be applied to the model to make it easier for numerical solvers to handle.","category":"page"},{"location":"#Package-Overview-1","page":"Home","title":"Package Overview","text":"","category":"section"},{"location":"#","page":"Home","title":"Home","text":"ModelingToolkit has 3 layers:","category":"page"},{"location":"#","page":"Home","title":"Home","text":"The model definition level. This is a high level of syntactic sugar for easily generating ModelingToolkit models. It can be used directly like a DSL for advanced users who want a lot of flexibility in a modeling language. Additionally, automatic tracing functionality allows for easily generating ModelingToolkit models directly from Julia code.\nThe AbstractSystem level. This is the level where content-dependent functionality is added, where models such an ordinary differential equation are represented. At the system level, there are transformations which take one system to another, and targets which output code for numerical solvers.\nThe IR level, also referred to as the direct level. At this level, one directly acts on arrays of Equations, and symbolic expressions to generate functions.","category":"page"},{"location":"#","page":"Home","title":"Home","text":"Each level above is built on the level below, giving more context to allow for more automation. For example, the system level allows for automatically generating fast multithreaded sparse Jacobian functions of an ODESystem, which is just calling the sparsity functions and the multithreading capabilities of build_function at the IR level.","category":"page"}]
}