Skip to content
ANALYSIS

Transient Analysis ​

Download as a Dyad projecttransientanalysis.zipOpen in Dyad Studio

The TransientAnalysis is used to simulate a component over a given time interval. For this analysis, the user defines an initial value problem (IVP) with a time interval to simulate and the transient analysis returns artifacts which describe the solution trajectory of the system.

Method Overview ​

The Dyad compiler uses the physical description of the system to generate a system of differential-algebraic equations:

where are the differential variables, are the algebraic variables, are the parameters, and is the independent variable (time). This system is solved with an initial condition such that:

where is the initialization function (built from the relations marked initial). This initial value problem is then solved over a time interval from (the start time) to (the stop time) using a DAE solver. If the algebraic equations are trivial, i.e. is nothing and there are not algebraic variables, then this is an ODE and it is treated via an ODE solver.

Example Definition ​

For this example we will run a transient analysis on the component DeSauty from the ElectricalComponents standard library. This analysis runs the circuit from 0 to 1 ms. Its C parameter supplies the model's C₁ setting:

dyad
analysis MyTransientAnalysis
  extends TransientAnalysis(start = 0, stop = 1e-3)
  parameter C::Conductance = 30e-6
  model = ElectricalComponents.Analog.Examples.DeSauty(C₁ = C)
end

The Dyad compiler generates the MyTransientAnalysis function. Calling it with no arguments uses C = 30e-6; MyTransientAnalysis(C = 40e-6) runs the same circuit with C₁ = 40e-6.

julia
result = MyTransientAnalysis()
Transient Analysis Solution for ElectricalComponents.Analog.Examples.DeSauty
with 1 differential equations and 0 algebraic equations

retcode: Success
Interpolation: 3rd order Hermite
t: 18-element Vector{Float64}: [0.0, 4.852336963352711e-5 … 0.0009214246430267671, 0.001]
u: 18-element Vector{Vector{Float64}}:
 [-0.0]
 [-0.00596925]
 [-0.011923]
 [-0.025537]
 [-0.0395157]
 [-0.0589307]
 [-0.0801592]
 [-0.105371]
 [-0.133146]
 [-0.164463]
 [-0.199054]
 [-0.237868]
 [-0.282309]
 [-0.346088]
 [-0.391225]
 [-0.442475]
 [-0.488593]
 [-0.530922]

We can plot this result, using either Plots.jl or Makie.jl. We'll use Plots here:

julia
using Plots
Plots.plot(result)

Analysis Arguments ​

The following arguments define a TransientAnalysis:

Required Arguments ​

  • model: the Dyad model that the analysis is being applied to.

  • stop::Time: chooses the end time for the interval.

Optional Arguments ​

  • alg::ODEAlg: chooses the solver algorithm for the solution process. The default is ODEAlg.AutoImplicit(). The choices are:

    • ODEAlg.AutoImplicit() - Default implicit ODE algorithm choice from OrdinaryDiffEq.jl. This is good for stiff systems and DAEs.

    • ODEAlg.Auto() - Automatic algorithm choice with stiffness detection, size detection, and linear solve swapping from OrdinaryDiffEq.jl.

    • ODEAlg.Rodas5P() - Adaptive time Rosenbrock method from OrdinaryDiffEqRosenbrock.jl. The Rosenbrock methods are specifically fast for small systems of stiff equations and DAEs which avoid Jacobian singularity issues (i.e. no variable-index DAE behavior).

    • ODEAlg.BDF() - Adaptive order, adaptive time backwards differentiation formulae (BDF) method from OrdinaryDiffEqBDF.jl, in Nordsieck form (the CVODE formulation). This is the recommended BDF method for large stiff systems and DAEs.

    • ODEAlg.FBDF() - Adaptive order, adaptive time fixed leading coefficient backwards differentiation formulae (BDF) method from OrdinaryDiffEqBDF.jl, modeled after the FLC formulation of VODE. This is also a good method for large stiff systems and DAEs, and remains fully supported, but ODEAlg.BDF() is preferred for new models.

    • ODEAlg.Tsit5() - 5th order explicit Runge-Kutta method from OrdinaryDiffEqTsit5.jl. This method is not applicable to DAEs and is only applicable to systems which have no algebraic constraints (post simplification).

  • start::Time: chooses the start time for the interval. Defaults to 0.

  • abstol::Real: chooses the absolute tolerance for the solver. Defaults to 1e-6.

  • reltol::Real: chooses the relative tolerance for the solver. Defaults to 1e-6.

  • saveat::Real: chooses the saving interval for the solving process. The default is 0, which corresponds to saving a dense output with a continuous time interpolation for high-fidelity solution at all points. If a non-zero value is chosen, for example, 0.1, then it will save at only the interval points (0.1, 0.2, ...) and use a linear interpolation between those points. This should only be used as a performance and memory optimization.

  • dtmax::Time: sets the dtmax of the ODE solver. Defaults to 0 which uses the default of the solver. Setting this lower can be used to force smaller steps and thus a more accurate solution.

  • tstops::Real[:]: Time points where the integrator must step through exactly. Useful for discontinuities or events at known times. Defaults to [].

  • automatic_discontinuity_detection::Boolean: whether to add the IfLifting pass (DyadCompilerPasses.IfLifting) to mtkcompile during structural simplification. Defaults to false.

  • optimize::OptimizationLevel: The code optimization level applied when the problem is built, as an OptimizationLevel variant: OptimizationLevel.None() (no optimization passes), OptimizationLevel.Basic() (basic in-place optimizations: matmul, ldiv, triu/tril, normalize) or OptimizationLevel.Aggressive() (basic optimizations plus static array conversion for small literals). Defaults to OptimizationLevel.Aggressive().

  • progress::Boolean: whether to show a solver progress bar (passed as progress to solve). Defaults to true.

  • respecialize::Boolean: Whether to re-specialize the model based on the current parameters (ModelingToolkit.respecialize after mtkcompile). Defaults to false.

  • verbose::DEVerbosity: sets the verbosity level for the solver. Options are None(), Minimal(), Standard() (default), Detailed(), and All().

  • log_file::String: path to a log file for solver output. When set, solver output will be written to this file. Defaults to "" (no file logging).

  • specialization::SpecializationLevel: controls compilation and runtime tradeoffs. Defaults to SpecializationLevel.Despecialize(); see Specialization.

Specialization ​

Set specialization on TransientAnalysis in Dyad or Julia:

ValueTradeoff
SpecializationLevel.Despecialize() (default)Reduces compilation latency by reusing solver code, with dispatch overhead during simulation.
SpecializationLevel.AutoSpecialize()Reuses solver code through callable wrappers where supported; otherwise uses full specialization.
SpecializationLevel.FullSpecialize()Compiles for the model's concrete types, favoring runtime performance at the cost of more compilation.

To compare simulation runtimes, set specialization = SpecializationLevel.FullSpecialize() on every analysis being compared. Run each analysis once to compile its code, then time subsequent runs to exclude compilation. Measurements at the default specialization level include its dispatch overhead.

Artifacts ​

A TransientAnalysis returns the following artifacts:

Customizable Plot ​

The customizable plot of a TransientAnalysis is the timeseries plot of the ODE/DAE solve which satisfies the rules and definitiosn of the DifferentialEquations.jl plotting interface.

Standard Plots ​

  • :SimulationSolutionPlot: Returns the standard time series plot of the solution trajectory for all values in the state vector.

Tables ​

  • :SimulationSolutionTable: Returns a DataFrame of the solution. If saveat=0, then the t are the adaptively chosen points, otherwise the t matches the interval chosen by saveat.

Julia-Side Artifacts ​

  • :RawSolution: Returns the DifferentialEquations.jl solution type from the run.

  • :SimplifiedSystem: Returns the ModelingToolkit.jl model after structural simplification was performed.

  • :InitialSystem: Returns the initial ModelingToolkit.jl model that was passed to the analysis.

Special Julia-Side Interactivity ​

The TransientAnalysis includes special Julia-side behaviors for better analyzing the time series of solutions. In particular, if you do:

julia
result = MyTransientAnalysis(; #= kwargs... =#)
Transient Analysis Solution for ElectricalComponents.Analog.Examples.DeSauty
with 1 differential equations and 0 algebraic equations

retcode: Success
Interpolation: 3rd order Hermite
t: 18-element Vector{Float64}: [0.0, 4.852336963352711e-5 … 0.0009214246430267671, 0.001]
u: 18-element Vector{Vector{Float64}}:
 [-0.0]
 [-0.00596925]
 [-0.011923]
 [-0.025537]
 [-0.0395157]
 [-0.0589307]
 [-0.0801592]
 [-0.105371]
 [-0.133146]
 [-0.164463]
 [-0.199054]
 [-0.237868]
 [-0.282309]
 [-0.346088]
 [-0.391225]
 [-0.442475]
 [-0.488593]
 [-0.530922]

then artifacts(result, :RawSolution) gives you the DifferentialEquations.jl solution type from the run. Thus for example:

julia
using DyadInterface: artifacts
sol = artifacts(result, :RawSolution)
retcode: Success
Interpolation: 3rd order Hermite
t: 18-element Vector{Float64}:
 0.0
 4.852336963352711e-5
 7.077832073560511e-5
 0.00010910294118787747
 0.0001414722231988259
 0.0001813350179643336
 0.00022140909748033177
 0.0002664394121871152
 0.00031426445194514393
 0.00036700129925247815
 0.00042457385813533485
 0.0004889598616031174
 0.0005629614822665885
 0.0006705433516463849
 0.0007481478673713181
 0.0008382084375659088
 0.0009214246430267671
 0.001
u: 18-element Vector{Vector{Float64}}:
 [-0.0]
 [-0.0059692503516523355]
 [-0.011922977244326198]
 [-0.025536954114592565]
 [-0.03951568621437362]
 [-0.05893070613834684]
 [-0.08015915269639426]
 [-0.10537129563491744]
 [-0.133145864810417]
 [-0.16446275611672007]
 [-0.19905396104772333]
 [-0.23786841784723906]
 [-0.28230928043841275]
 [-0.34608808477860387]
 [-0.3912247227926978]
 [-0.44247463107337537]
 [-0.48859252246960516]
 [-0.5309220975329656]
julia
sol(1.0)
1-element Vector{Float64}:
 -6.859594938900766e10

For more information on using the solution object, see the DifferentialEquations.jl solution interface for more information. This solution allows for using the DifferentialEquations.jl plotting interface, for example:

julia
using Plots
plot(sol)

See the DifferentialEquations.jl plotting documentation for more details. Note that for convenience, the original result object can be plotted directly without rebuilding the solution:

julia
plot(result)

Further Reading ​