Mercurial > repos > public > sbplib
changeset 985:ad6de007e7f6 feature/timesteppers
Convert Rungekutta4SecondOrder to take F(t,v,v_t) instead of matrices
author | Jonatan Werpers <jonatan@werpers.com> |
---|---|
date | Tue, 08 Jan 2019 12:34:29 +0100 |
parents | 0585a2ee7ee7 |
children | a32856fc2ad2 |
files | +time/Rk4SecondOrderNonlin.m +time/Rungekutta4SecondOrder.m |
diffstat | 2 files changed, 25 insertions(+), 169 deletions(-) [+] |
line wrap: on
line diff
--- a/+time/Rk4SecondOrderNonlin.m Tue Jan 08 12:19:33 2019 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -classdef Rk4SecondOrderNonlin < time.Timestepper - properties - F - k - t - w - m - - D - E - S - - n - end - - - methods - function obj = Rk4SecondOrderNonlin(D, E, S, k, t0, v0, v0t) - default_arg('S',0); - default_arg('E',0); - - if isnumeric(S) - S = @(v,t)S; - end - - if isnumeric(E) - E = @(v)E; - end - - obj.k = k; - obj.t = t0; - obj.w = [v0; v0t]; - - m = length(v0); - function wt = F(w,t) - v = w(1:m); - vt = w(m+1:end); - - % Def: w = [v; vt] - wt(1:m,1) = vt; - wt(m+1:2*m,1) = D(v)*v + E(v)*vt + S(v,t); - - end - - obj.F = @F; - obj.D = D; - obj.E = E; - obj.S = S; - obj.m = m; - obj.n = 0; - end - - function [v,t] = getV(obj) - v = obj.w(1:end/2); - t = obj.t; - end - - function [vt,t] = getVt(obj) - vt = obj.w(end/2+1:end); - t = obj.t; - end - - function obj = step(obj) - w = obj.w; - k = obj.k; - - k1 = obj.F(t, w); - k2 = obj.F(t + 0.5*k, w + 0.5*k*k1); - k3 = obj.F(t + 0.5*k, w + 0.5*k*k2); - k4 = obj.F(t + k, w + k*k3); - - obj.w = w + k*(1/6)*(k1+2*(k2+k3)+k4); - obj.t = obj.t + obj.k; - obj.n = obj.n + 1; - end - end - - - methods (Static) - function k = getTimeStep(lambda) - k = rk4.get_rk4_time_step(lambda); - end - end - -end \ No newline at end of file
--- a/+time/Rungekutta4SecondOrder.m Tue Jan 08 12:19:33 2019 +0100 +++ b/+time/Rungekutta4SecondOrder.m Tue Jan 08 12:34:29 2019 +0100 @@ -1,91 +1,31 @@ classdef Rungekutta4SecondOrder < time.Timestepper properties F - k + dt t + n + + G % RHS for rewritten system w - m - D - E - S - M - C - n end methods - % Solves u_tt = Du + Eu_t + S by - % Rewriting on first order form: - % w_t = M*w + C(t) - % where - % M = [ - % 0, I; - % D, E; - % ] - % and - % C(t) = [ - % 0; - % S(t) - % ] - % D, E, S can either all be constants or all be function handles, - % They can also be omitted by setting them equal to the empty matrix. - function obj = Rungekutta4SecondOrder(D, E, S, k, t0, v0, v0t) - obj.D = D; - obj.E = E; - obj.S = S; - obj.m = length(v0); + % Create a time stepper for + % v_tt = F(t,v,v_t), v(t0) = v0, v_t(t0) = v0t + % with step size dt, by rewriting on first order form + function obj = Rungekutta4SecondOrder(F, dt, t0, v0, v0t) + obj.F = F; + obj.dt = dt; + obj.t = t0; obj.n = 0; - - if isa(D, 'function_handle') || isa(E, 'function_handle') || isa(S, 'function_handle') - default_arg('D', @(t)sparse(obj.m, obj.m)); - default_arg('E', @(t)sparse(obj.m, obj.m)); - default_arg('S', @(t)sparse(obj.m, 1) ); - - if ~isa(D, 'function_handle') - D = @(t)D; - end - if ~isa(E, 'function_handle') - E = @(t)E; - end - if ~isa(S, 'function_handle') - S = @(t)S; - end - - obj.k = k; - obj.t = t0; - obj.w = [v0; v0t]; - - % Avoid matrix formulation because it is VERY slow - obj.F = @(w,t)[ - w(obj.m+1:end); - D(t)*w(1:obj.m) + E(t)*w(obj.m+1:end) + S(t); - ]; - else - - default_arg('D', sparse(obj.m, obj.m)); - default_arg('E', sparse(obj.m, obj.m)); - default_arg('S', sparse(obj.m, 1) ); - - I = speye(obj.m); - O = sparse(obj.m,obj.m); - - obj.M = [ - O, I; - D, E; - ]; - obj.C = [ - zeros(obj.m,1); - S; - ]; - - obj.k = k; - obj.t = t0; - obj.w = [v0; v0t]; - - obj.F = @(w,t)(obj.M*w + obj.C); - end + m = length(v0); + obj.w = [v0; v0t]; + obj.G = @(t, w)[ + w(m+1:end); + F(t,w(1:m), w(m+1:end)); + ]; end function [v,t] = getV(obj) @@ -99,16 +39,17 @@ end function obj = step(obj) + % TODO: Avoid extra storage w = obj.w; - k = obj.k; + dt = obj.dt; - k1 = obj.F(t, w); - k2 = obj.F(t + 0.5*k, w + 0.5*k*k1); - k3 = obj.F(t + 0.5*k, w + 0.5*k*k2); - k4 = obj.F(t + k, w + k*k3); + k1 = obj.G(t, w); + k2 = obj.G(t + 0.5*dt, w + 0.5*dt*k1); + k3 = obj.G(t + 0.5*dt, w + 0.5*dt*k2); + k4 = obj.G(t + dt, w + dt*k3); - obj.w = w + k*(1/6)*(k1+2*(k2+k3)+k4); - obj.t = obj.t + obj.k; + obj.w = w + dt*(1/6)*(k1+2*(k2+k3)+k4); + obj.t = obj.t + obj.dt; obj.n = obj.n + 1; end end