Time evolution
Generally, solving the ODE of oscillatory systems in time requires numerically tracking the oscillations. This is a computationally expensive process; however, using the harmonic ansatz removes the oscillatory time-dependence. Simulating instead the harmonic variables of a HarmonicEquation
is vastly more efficient - a steady state of the system appears as a fixed point in multidimensional space rather than an oscillatory function.
The extension TimeEvolution
is used to interface HarmonicEquation
with the solvers contained in OrdinaryDiffEq.jl
. Time-dependent parameter sweeps are defined using the object AdiabaticSweep
. To use the TimeEvolution
extension, one must first load the OrdinaryDiffEq.jl
package.
SciMLBase.ODEProblem Method
ODEProblem(
eom::HarmonicEquation;
fixed_parameters,
u0::Vector,
sweep::AdiabaticSweep,
timespan::Tuple
)
Creates an ODEProblem object used by OrdinaryDiffEqTsit5.jl from the equations in eom
to simulate time-evolution within timespan
. fixed_parameters
must be a dictionary mapping parameters+variables to numbers (possible to use a solution index, e.g. solutions[x][y] for branch y of solution x). If u0
is specified, it is used as an initial condition; otherwise the values from fixed_parameters
are used.
HarmonicBalance.AdiabaticSweep Type
Represents a sweep of one or more parameters of a HarmonicEquation
. During a sweep, the selected parameters vary linearly over some timespan and are constant elsewhere.
Sweeps of different variables can be combined using +
.
Fields
functions::Dict{Num, Function}
: Maps each swept parameter to a function.
Examples
# create a sweep of parameter a from 0 to 1 over time 0 -> 100
julia> @variables a,b;
julia> sweep = AdiabaticSweep(a => [0., 1.], (0, 100));
julia> sweep[a](50)
0.5
julia> sweep[a](200)
1.0
# do the same, varying two parameters simultaneously
julia> sweep = AdiabaticSweep([a => [0.,1.], b => [0., 1.]], (0,100))
Successive sweeps can be combined,
sweep1 = AdiabaticSweep(ω => [0.95, 1.0], (0, 2e4))
sweep2 = AdiabaticSweep(λ => [0.05, 0.01], (2e4, 4e4))
sweep = sweep1 + sweep2
multiple parameters can be swept simultaneously,
sweep = AdiabaticSweep([ω => [0.95;1.0], λ => [5e-2;1e-2]], (0, 2e4))
and custom sweep functions may be used.
ωfunc(t) = cos(t)
sweep = AdiabaticSweep(ω => ωfunc)
Plotting
RecipesBase.plot Method
plot(soln::ODESolution, f::String, harm_eq::HarmonicEquation; kwargs...)
Plot a function f
of a time-dependent solution soln
of harm_eq
.
As a function of time
plot(soln::ODESolution, f::String, harm_eq::HarmonicEquation; kwargs...)
f
is parsed by Symbolics.jl
parametric plots
plot(soln::ODESolution, f::Vector{String}, harm_eq::HarmonicEquation; kwargs...)
Parametric plot of f[1] against f[2]
Also callable as plot!
Miscellaneous
Using a time-dependent simulation can verify solution stability in cases where the Jacobian is too expensive to compute.
HarmonicBalance.is_stable Function
is_stable(
soln::OrderedCollections.OrderedDict{Num, ComplexF64},
eom::HarmonicEquation;
timespan,
tol,
perturb_initial
)
Numerically investigate the stability of a solution soln
of eom
within timespan
. The initial condition is displaced by perturb_initial
.
Return true
the solution evolves within tol
of the initial value (interpreted as stable).
is_stable(
soln::OrderedCollections.OrderedDict{Num, ComplexF64},
res::HarmonicBalance.Result;
kwargs...
) -> Any
Returns true if the solution soln
of the Result res
is stable. Stable solutions are real and have all Jacobian eigenvalues Re[λ] <= 0. im_tol
: an absolute threshold to distinguish real/complex numbers. rel_tol
: Re(λ) considered <=0 if real.(λ) < rel_tol*abs(λmax)