comparison +time/CdiffImplicit.m @ 978:1a30dbe99c7c

Refactor CdiffImplicit to take input arguments in the right order
author Jonatan Werpers <jonatan@werpers.com>
date Mon, 07 Jan 2019 16:15:49 +0100
parents ea8fefc326b2
children 47e86b5270ad
comparison
equal deleted inserted replaced
977:c9009d5a3101 978:1a30dbe99c7c
1 classdef CdiffImplicit < time.Timestepper 1 classdef CdiffImplicit < time.Timestepper
2 properties 2 properties
3 A, B, C, G 3 A, B, C
4 AA, BB, CC 4 AA, BB, CC
5 G
5 k 6 k
6 t 7 t
7 v, v_prev 8 v, v_prev
8 n 9 n
9 10
11 L,U,p,q 12 L,U,p,q
12 end 13 end
13 14
14 methods 15 methods
15 % Solves 16 % Solves
16 % A*u_tt + B*u + C*u_t = G(t) 17 % A*v_tt + B*v_t + C*v = G(t)
17 % u(t0) = f1 18 % v(t0) = v0
18 % u_t(t0) = f2 19 % v_t(t0) = v0t
19 % starting at time t0 with timestep k 20 % starting at time t0 with timestep
20 21 % Using
21 % TODO: Fix order of matrices 22 % A*Dp*Dm*v_n + B*D0*v_n + C*I0*v_n = G(t_n)
22 function obj = CdiffImplicit(A, B, C, G, f1, f2, k, t0) 23 function obj = CdiffImplicit(A, B, C, G, v0, v0t, k, t0)
23 default_arg('A', []); 24 m = length(v0);
24 default_arg('C', []); 25 default_arg('A', speye(m));
25 default_arg('G', []); 26 default_arg('B', sparse(m,m));
26 default_arg('f1', 0); 27 default_arg('G', @(t) sparse(m,1));
27 default_arg('f2', 0);
28 default_arg('t0', 0); 28 default_arg('t0', 0);
29
30 m = size(B,1);
31
32 if isempty(A)
33 A = speye(m);
34 end
35
36 if isempty(C)
37 C = sparse(m,m);
38 end
39
40 if isempty(G)
41 G = @(t) sparse(m,1);
42 end
43
44 if isempty(f1)
45 f1 = sparse(m,1);
46 end
47
48 if isempty(f2)
49 f2 = sparse(m,1);
50 end
51 29
52 obj.A = A; 30 obj.A = A;
53 obj.B = B; 31 obj.B = B;
54 obj.C = C; 32 obj.C = C;
55 obj.G = G; 33 obj.G = G;
56 34
57 AA = 1/k^2*A + 1/2*B + 1/(2*k)*C; 35 % Rewrite as AA*v_(n+1) + BB*v_n + CC*v_(n-1) = G(t_n)
58 BB = -2/k^2*A; 36 AA = A/k^2 + B/(2*k) + C/2;
59 CC = 1/k^2*A + 1/2*B - 1/(2*k)*C; 37 BB = -2*A/k^2;
60 % AA*v_next + BB*v + CC*v_prev == G(t_n) 38 CC = A/k^2 - B/(2*k) + C/2;
61 39
62 obj.AA = AA; 40 obj.AA = AA;
63 obj.BB = BB; 41 obj.BB = BB;
64 obj.CC = CC; 42 obj.CC = CC;
65 43
66 v_prev = f1; 44 v_prev = v0;
67 I = speye(m); 45 I = speye(m);
68 % v = (1/k^2*A)\((1/k^2*A - 1/2*B)*f1 + (1/k*I - 1/2*C)*f2 + 1/2*G(0)); 46 v = v0 + k*v0t;
69 v = f1 + k*f2;
70
71 47
72 if ~issparse(A) || ~issparse(B) || ~issparse(C) 48 if ~issparse(A) || ~issparse(B) || ~issparse(C)
73 error('LU factorization with full pivoting only works for sparse matrices.') 49 error('LU factorization with full pivoting only works for sparse matrices.')
74 end 50 end
75 51
77 53
78 obj.L = L; 54 obj.L = L;
79 obj.U = U; 55 obj.U = U;
80 obj.p = p; 56 obj.p = p;
81 obj.q = q; 57 obj.q = q;
82
83 58
84 obj.k = k; 59 obj.k = k;
85 obj.t = t0+k; 60 obj.t = t0+k;
86 obj.n = 1; 61 obj.n = 1;
87 obj.v = v; 62 obj.v = v;
92 v = obj.v; 67 v = obj.v;
93 t = obj.t; 68 t = obj.t;
94 end 69 end
95 70
96 function [vt,t] = getVt(obj) 71 function [vt,t] = getVt(obj)
97 % Calculate next time step to be able to do centered diff. 72 vt = (obj.v-obj.v_prev)/obj.k; % Could be improved using u_tt = f(u))
98 v_next = zeros(size(obj.v));
99 b = obj.G(obj.t) - obj.BB*obj.v - obj.CC*obj.v_prev;
100
101 y = obj.L\b(obj.p);
102 z = obj.U\y;
103 v_next(obj.q) = z;
104
105
106 vt = (v_next-obj.v_prev)/(2*obj.k);
107 t = obj.t; 73 t = obj.t;
108 end 74 end
109 75
110 % Calculate the conserved energy (Dm*v_n)^2_A + Im*v_n^2_B 76 % Calculate the conserved energy (Dm*v_n)^2_A + Im*v_n^2_B
111 function E = getEnergy(obj) 77 function E = getEnergy(obj)
112 v = obj.v; 78 v = obj.v;
113 vp = obj.v_prev; 79 vp = obj.v_prev;
114 vt = (obj.v - obj.v_prev)/obj.k; 80 vt = (obj.v - obj.v_prev)/obj.k;
115 81
116 E = vt'*obj.A*vt + 1/2*(v'*obj.B*v + vp'*obj.B*vp); 82 E = vt'*obj.A*vt + 1/2*(v'*obj.C*v + vp'*obj.C*vp);
117 end 83 end
118 84
119 function obj = step(obj) 85 function obj = step(obj)
120 b = obj.G(obj.t) - obj.BB*obj.v - obj.CC*obj.v_prev; 86 b = obj.G(obj.t) - obj.BB*obj.v - obj.CC*obj.v_prev;
121 obj.v_prev = obj.v; 87 obj.v_prev = obj.v;
132 obj.t = obj.t + obj.k; 98 obj.t = obj.t + obj.k;
133 obj.n = obj.n + 1; 99 obj.n = obj.n + 1;
134 end 100 end
135 end 101 end
136 end 102 end
137
138
139
140
141
142 %%% Derivation
143 % syms A B C G
144 % syms n k
145 % syms f1 f2
146
147 % v = symfun(sym('v(n)'),n);
148
149
150 % d = A/k^2 * (v(n+1) - 2*v(n) +v(n-1)) + B/2*(v(n+1)+v(n-1)) + C/(2*k)*(v(n+1) - v(n-1)) == G
151 % ic1 = v(0) == f1
152 % ic2 = A/k*(v(1)-f1) + k/2*(B*f1 + C*f2 - G) - f2 == 0
153
154 % c = collect(d, [v(n) v(n-1) v(n+1)]) % (-(2*A)/k^2)*v(n) + (B/2 + A/k^2 - C/(2*k))*v(n - 1) + (B/2 + A/k^2 + C/(2*k))*v(n + 1) == G
155 % syms AA BB CC
156 % % AA = B/2 + A/k^2 + C/(2*k)
157 % % BB = -(2*A)/k^2
158 % % CC = B/2 + A/k^2 - C/(2*k)
159 % s = subs(c, [B/2 + A/k^2 + C/(2*k), -(2*A)/k^2, B/2 + A/k^2 - C/(2*k)], [AA, BB, CC])
160
161
162 % ic2_a = collect(ic2, [v(1) f1 f2]) % (A/k)*v(1) + ((B*k)/2 - A/k)*f1 + ((C*k)/2 - 1)*f2 - (G*k)/2 == 0
163