Program Listing for File solve.m¶
↰ Return to documentation for file (+Indigo/@RungeKutta/solve.m
)
%> Solve the system and calculate the approximate solution over the mesh of
%> time points.
%>
%> \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$.
%>
%> \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, v_out, h_out] = solve( this, t, x_0 )
CMD = 'Indigo.RungeKutta.solve(...): ';
% 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
x_out = zeros(num_eqns, length(t));
v_out = zeros(num_veil, length(t));
h_out = zeros(num_invs, length(t));
% Store first step
x_out(:,1) = x_0(:);
v_out(:,1) = this.m_sys.v(x_out(:,1), t(1));
y_out(:,1) = this.m_sys.y(x_out(:,1), v_out(:,1), t(1));
h_out(:,1) = this.m_sys.h(x_out(:,1), y_out(:,1), v_out(:,1), t(1));
% Instantiate temporary variables
s = 1; % Current step
tol = sqrt(eps); % Tolerance
% Update the current step
x_s = x_out(:,1);
t_s = t(1);
d_t_s = t(2) - t(1);
d_t_tmp = d_t_s;
% 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_s/t(end)))
end
% Integrate system
[x_s, d_t_star, ~] = this.advance(x_s, t_s, d_t_s);
% Update the current step
t_s = t_s + d_t_s;
% Saturate the suggested timestep
mesh_point_bool = abs(t_s - t(s+1)) < tol;
saturation_bool = t_s + d_t_star > t(s+1) + tol;
if (this.m_adaptive_step && ~mesh_point_bool && saturation_bool)
d_t_tmp = d_t_star;
d_t_s = t(s+1) - t_s;
else
d_t_s = d_t_star;
end
% Store solution if the step is a mesh point
if (~this.m_adaptive_step || mesh_point_bool)
% Update temporaries
s = s+1;
d_t_s = d_t_tmp;
% Update outputs
x_out(:,s) = x_s;
v_out(:,s) = this.m_sys.v(x_out(:,s), t(s));
y_out(:,s) = this.m_sys.y(x_out(:,s), v_out(:,s), t(s));
h_out(:,s) = this.m_sys.h(x_out(:,s), y_out(:,s), v_out(:,s), t(s));
% Check if the current step is the last one
if (abs(t_s - t(end)) < tol)
break;
end
end
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
end