Mercurial > repos > public > sbplib
comparison +time/Rungekutta4SecondOrder.m @ 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 | a99f00896b8e |
comparison
equal
deleted
inserted
replaced
984:0585a2ee7ee7 | 985:ad6de007e7f6 |
---|---|
1 classdef Rungekutta4SecondOrder < time.Timestepper | 1 classdef Rungekutta4SecondOrder < time.Timestepper |
2 properties | 2 properties |
3 F | 3 F |
4 k | 4 dt |
5 t | 5 t |
6 n | |
7 | |
8 G % RHS for rewritten system | |
6 w | 9 w |
7 m | |
8 D | |
9 E | |
10 S | |
11 M | |
12 C | |
13 n | |
14 end | 10 end |
15 | 11 |
16 | 12 |
17 methods | 13 methods |
18 % Solves u_tt = Du + Eu_t + S by | 14 % Create a time stepper for |
19 % Rewriting on first order form: | 15 % v_tt = F(t,v,v_t), v(t0) = v0, v_t(t0) = v0t |
20 % w_t = M*w + C(t) | 16 % with step size dt, by rewriting on first order form |
21 % where | 17 function obj = Rungekutta4SecondOrder(F, dt, t0, v0, v0t) |
22 % M = [ | 18 obj.F = F; |
23 % 0, I; | 19 obj.dt = dt; |
24 % D, E; | 20 obj.t = t0; |
25 % ] | |
26 % and | |
27 % C(t) = [ | |
28 % 0; | |
29 % S(t) | |
30 % ] | |
31 % D, E, S can either all be constants or all be function handles, | |
32 % They can also be omitted by setting them equal to the empty matrix. | |
33 function obj = Rungekutta4SecondOrder(D, E, S, k, t0, v0, v0t) | |
34 obj.D = D; | |
35 obj.E = E; | |
36 obj.S = S; | |
37 obj.m = length(v0); | |
38 obj.n = 0; | 21 obj.n = 0; |
39 | 22 |
40 | 23 m = length(v0); |
41 if isa(D, 'function_handle') || isa(E, 'function_handle') || isa(S, 'function_handle') | 24 obj.w = [v0; v0t]; |
42 default_arg('D', @(t)sparse(obj.m, obj.m)); | 25 obj.G = @(t, w)[ |
43 default_arg('E', @(t)sparse(obj.m, obj.m)); | 26 w(m+1:end); |
44 default_arg('S', @(t)sparse(obj.m, 1) ); | 27 F(t,w(1:m), w(m+1:end)); |
45 | 28 ]; |
46 if ~isa(D, 'function_handle') | |
47 D = @(t)D; | |
48 end | |
49 if ~isa(E, 'function_handle') | |
50 E = @(t)E; | |
51 end | |
52 if ~isa(S, 'function_handle') | |
53 S = @(t)S; | |
54 end | |
55 | |
56 obj.k = k; | |
57 obj.t = t0; | |
58 obj.w = [v0; v0t]; | |
59 | |
60 % Avoid matrix formulation because it is VERY slow | |
61 obj.F = @(w,t)[ | |
62 w(obj.m+1:end); | |
63 D(t)*w(1:obj.m) + E(t)*w(obj.m+1:end) + S(t); | |
64 ]; | |
65 else | |
66 | |
67 default_arg('D', sparse(obj.m, obj.m)); | |
68 default_arg('E', sparse(obj.m, obj.m)); | |
69 default_arg('S', sparse(obj.m, 1) ); | |
70 | |
71 I = speye(obj.m); | |
72 O = sparse(obj.m,obj.m); | |
73 | |
74 obj.M = [ | |
75 O, I; | |
76 D, E; | |
77 ]; | |
78 obj.C = [ | |
79 zeros(obj.m,1); | |
80 S; | |
81 ]; | |
82 | |
83 obj.k = k; | |
84 obj.t = t0; | |
85 obj.w = [v0; v0t]; | |
86 | |
87 obj.F = @(w,t)(obj.M*w + obj.C); | |
88 end | |
89 end | 29 end |
90 | 30 |
91 function [v,t] = getV(obj) | 31 function [v,t] = getV(obj) |
92 v = obj.w(1:end/2); | 32 v = obj.w(1:end/2); |
93 t = obj.t; | 33 t = obj.t; |
97 vt = obj.w(end/2+1:end); | 37 vt = obj.w(end/2+1:end); |
98 t = obj.t; | 38 t = obj.t; |
99 end | 39 end |
100 | 40 |
101 function obj = step(obj) | 41 function obj = step(obj) |
42 % TODO: Avoid extra storage | |
102 w = obj.w; | 43 w = obj.w; |
103 k = obj.k; | 44 dt = obj.dt; |
104 | 45 |
105 k1 = obj.F(t, w); | 46 k1 = obj.G(t, w); |
106 k2 = obj.F(t + 0.5*k, w + 0.5*k*k1); | 47 k2 = obj.G(t + 0.5*dt, w + 0.5*dt*k1); |
107 k3 = obj.F(t + 0.5*k, w + 0.5*k*k2); | 48 k3 = obj.G(t + 0.5*dt, w + 0.5*dt*k2); |
108 k4 = obj.F(t + k, w + k*k3); | 49 k4 = obj.G(t + dt, w + dt*k3); |
109 | 50 |
110 obj.w = w + k*(1/6)*(k1+2*(k2+k3)+k4); | 51 obj.w = w + dt*(1/6)*(k1+2*(k2+k3)+k4); |
111 obj.t = obj.t + obj.k; | 52 obj.t = obj.t + obj.dt; |
112 obj.n = obj.n + 1; | 53 obj.n = obj.n + 1; |
113 end | 54 end |
114 end | 55 end |
115 | 56 |
116 | 57 |