Program Listing for File implicit_step.m¶
↰ Return to documentation for file (+Indigo/@RungeKutta/implicit_step.m
)
%> Compute an integration step using the implicit Runge-Kutta method for a
%> system of the form \f$ \mathbf{F}(\mathbf{x}, \mathbf{x}', t) =
%> \mathbf{0} \f$.
%>
%> **Solution Algorithm**
%>
%> Consider a Runge-Kutta method, written for a system of the form
%> \f$ \mathbf{x}' = \mathbf{f}(\mathbf{x}, \mathbf{v}, t) \f$:
%>
%> \f[
%> \begin{array}{l}
%> \mathbf{K}_i = \mathbf{f} \left(
%> \mathbf{x}_k + \Delta t \displaystyle\sum_{j=1}^{s} a_{ij}
%> \mathbf{K}_j,
%> \, t_k + c_i \Delta t
%> \right), \qquad i = 1, 2, \ldots, s \\
%> \mathbf{x}_{k+1} = \mathbf{x}_k + \Delta t \displaystyle\sum_{j=1}^s b_j
%> \mathbf{K}_j \, ,
%> \end{array}
%> \f]
%>
%> Then the implicit Runge-Kutta method for an implicit system of the form
%> \f$\mathbf{F}(\mathbf{x}, \mathbf{x}', t) = \mathbf{0} \f$ can be written
%> as:
%>
%> \f[
%> \begin{array}{l}
%> \mathbf{F}_i \left(
%> \mathbf{x}_k + \Delta t \displaystyle\sum_{j=1}^s a_{ij}
%> \mathbf{K}_j, \, \mathbf{K}_i, \, t_k + c_i \Delta t
%> \right) = \mathbf{0}, \qquad i = 1, 2, \ldots, s \\
%> \mathbf{x}_{k+1} = \mathbf{x}_k + \displaystyle\sum_{j=1}^s b_j \mathbf{K}_j.
%> \end{array}
%> \f]
%>
%> Thus, the final system to be solved is the following:
%>
%> \f[
%> \left\{\begin{array}{l}
%> \mathbf{F}_1 \left(
%> \mathbf{x}_k + \Delta t \displaystyle\sum_{j=1}^s a_{1j}
%> \mathbf{K}_j, \, \mathbf{K}_1, \, t_k + c_1 \Delta t
%> \right) = \mathbf{0} \\
%> \mathbf{F}_2 \left(
%> \mathbf{x}_k + \Delta t \displaystyle\sum_{j=1}^s a_{2j}
%> \mathbf{K}_j, \, \mathbf{K}_2, \, t_k + c_2 \Delta t
%> \right) = \mathbf{0} \\
%> ~~ \vdots \\
%> \mathbf{F}_s \left(
%> \mathbf{x}_k + \Delta t \displaystyle\sum_{j=1}^s a_{sj}
%> \mathbf{K}_j, \, \mathbf{K}_s, \, t_k + c_s \Delta t
%> \right) = \mathbf{0}
%> \end{array}\right.
%> \f]
%>
%> The \f$ \mathbf{K} \f$ variables are computed using the Newton's method.
%>
%> The suggested time step for the next advancing step
%> \f$ \Delta t_{k+1} \f$, is the same as the input time step
%> \f$ \Delta t \f$ since in the implicit Runge-Kutta method the time step
%> is not modified through any error control method.
%>
%> \param x_k States value at \f$ k \f$-th time step \f$ \mathbf{x}(t_k) \f$.
%> \param t_k Time step \f$ t_k \f$.
%> \param d_t Advancing time step \f$ \Delta t\f$.
%>
%> \return The approximation of the states at \f$ k+1 \f$-th time step \f$
%> \mathbf{x_{k+1}}(t_{k}+\Delta t) \f$, the suggested time step for the
%> next advancing step \f$ \Delta t_{k+1} \f$, and the error control flag.
%
function [x_out, d_t_star, ierr] = implicit_step( this, x_k, t_k, d_t )
% Extract lengths
nc = length(this.m_c);
nx = length(x_k);
% default suggested time step for the next advancing step
d_t_star = d_t;
x_out = x_k;
% Create the intial guess for K
K0 = zeros( nc * nx, 1);
% Define the function handles
fun = @(K) this.implicit_residual(x_k, K, t_k, d_t);
jac = @(K) this.implicit_jacobian(x_k, K, t_k, d_t);
% Solve using Newton's method
[K, ierr] = this.m_newton_solver.solve_handle(fun, jac, K0);
% Error code check
if (ierr ~= 0)
return;
end
% Perform the step and obtain x_k+1
x_out = x_k + reshape(K, nx, nc) * this.m_b';
% Adapt next time step
if this.m_adaptive_step && this.m_is_embedded
x_e = x_k + reshape(K, nx, nc) * this.m_b_e';
d_t_star = this.estimate_step( x_out, x_e, d_t );
end
end