Program Listing for File adaptive_solve.m¶
↰ Return to documentation for file (+Indigo/@RungeKutta/adaptive_solve.m
)
%> Solve the system and calculate the approximate solution over the
%> suggested mesh of time points with adaptive step size control.
%>
%> \param t Time mesh points \f$ \mathbf{t} = \left[ t_0, t_1, \ldots,
%> t_n \right]^T \f$.
%> \param x_0 Initial states value \f$ \mathbf{x}(t_0) \f$.
%> \param t_min [optional] Minimum timestep \f$ \Delta t_{\mathrm{min}} \f$.
%> \param t_max [optional] Maximum timestep \f$ \Delta t_{\mathrm{max}} \f$.
%>
%> \return A matrix \f$ \left[(\mathrm{size}(\mathbf{x}) \times \mathrm{size}
%> (\mathbf{t})\right] \f$ containing the approximated solution
%> \f$ \mathbf{x}(t) \f$ and \f$ \mathbf{x}^\prime(t) \f$ of the
%> system. Additionally, the veils \f$ \mathbf{v}(t) \f$ and
%> invariants \f$ \mathbf{h}(\mathbf{x}, \mathbf{v}, t) \f$ are also
%> returned.
%
function [x_out, t_out, v_out, h_out] = adaptive_solve( this, t, x_0, varargin )
CMD = 'Indigo.RungeKutta.adaptive_solve(...): ';
% Collect optional arguments
d_t = t(2) - t(1);
if (nargin == 3)
scale = 100.0;
t_min = max(this.m_d_t_min, d_t/scale);
t_max = scale*d_t;
elseif (nargin == 4)
[t_min, t_max] = varargin{1};
elseif (nargin == 5)
t_min = varargin{1};
t_max = varargin{2};
else
error([CMD, 'invalid number of inputs detected.']);
end
assert(t_max > t_min && t_min > 0, [CMD, 'invalid time bounds detected.']);
d_t = max(min(d_t, t_max), t_min);
% Check initial conditions
num_eqns = this.m_sys.get_num_eqns();
num_veil = this.m_sys.get_num_veil();
num_invs = this.m_sys.get_num_invs();
assert(num_eqns == length(x_0), ...
[CMD, 'in %s solver, length(x_0) is %d, expected %d.'], ...
this.m_name, length(x_0), num_eqns);
% Instantiate output
safety_length = ceil(1.5/this.m_factor_min)*length(t);
t_out = zeros(1, safety_length);
x_out = zeros(num_eqns, safety_length);
v_out = zeros(num_veil, safety_length);
h_out = zeros(num_invs, safety_length);
% Store first step
t_out(1) = t(1);
x_out(:,1) = x_0(:);
v_out(:,1) = this.m_sys.v(x_0, t(1));
y_out(:,1) = this.m_sys.y(x_0, v_out(:,1), t(1));
h_out(:,1) = this.m_sys.h(x_0, y_out(:,1), v_out(:,1), t(1));
% Instantiate temporary variables
s = 1; % Current step
% Start progress bar
if (this.m_progress_bar)
Indigo.Utils.progress_bar('_start');
end
while (true)
% Print percentage of solution completion
if (this.m_progress_bar)
Indigo.Utils.progress_bar(ceil(100*t_out(s)/t(end)))
end
% Integrate system
[x_new, d_t_star, ~] = this.advance(x_out(:,s), t_out(s), d_t);
% Store solution
t_out(s+1) = t_out(s) + d_t;
x_out(:,s+1) = x_new;
v_out(:,s+1) = this.m_sys.v(x_new, t_out(s+1));
y_out(:,s+1) = this.m_sys.y(x_new, v_out(:,s+1), t_out(s+1));
h_out(:,s+1) = this.m_sys.h(x_new, y_out(:,s+1), v_out(:,s+1), t_out(s+1));
% Saturate the suggested timestep
d_t = max(min(d_t_star, t_max), t_min);
% Check if the current step is the last one
if (t_out(s+1) + d_t > t(end))
break;
end
% Update steps counter
s = s+1;
end
% End progress bar
if (this.m_progress_bar)
Indigo.Utils.progress_bar(100);
if (this.m_projection)
bar_str = sprintf('Projected-%s completed! (%d steps)', this.m_name, s);
else
bar_str = sprintf('%s completed! (%d steps)', this.m_name, s);
end
Indigo.Utils.progress_bar(bar_str);
end
% Resize the output
t_out = t_out(:,1:s-1);
x_out = x_out(:,1:s-1);
v_out = v_out(:,1:s-1);
h_out = h_out(:,1:s-1);
end
%
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
%