Mercurial > repos > public > sbplib
comparison +time/CdiffImplicit.m @ 379:ca73ee0623e5 feature/beams
Added an implicit central time stepping scheme.
author | Jonatan Werpers <jonatan@werpers.com> |
---|---|
date | Fri, 09 Dec 2016 16:03:30 +0100 |
parents | |
children | 280ae4dbf93b |
comparison
equal
deleted
inserted
replaced
360:447ceb41fb65 | 379:ca73ee0623e5 |
---|---|
1 classdef CdiffImplicit < time.Timestepper | |
2 properties | |
3 A, B, C, G | |
4 AA, BB, CC | |
5 k | |
6 t | |
7 v, v_prev | |
8 n | |
9 | |
10 % LU factorization | |
11 L,U,p,q | |
12 end | |
13 | |
14 methods | |
15 % Solves | |
16 % A*u_tt + B*u + C*v_t = G(t) | |
17 % u(t0) = f1 | |
18 % u_t(t0) = f2 | |
19 % starting at time t0 with timestep k | |
20 function obj = CdiffImplicit(A, B, C, G, f1, f2, k, t0) | |
21 default_arg('A', []); | |
22 default_arg('C', []); | |
23 default_arg('G', []); | |
24 default_arg('f1', 0); | |
25 default_arg('f2', 0); | |
26 default_arg('t0', 0); | |
27 | |
28 m = size(B,1); | |
29 | |
30 if isempty(A) | |
31 A = speye(m); | |
32 end | |
33 | |
34 if isempty(C) | |
35 C = sparse(m,m); | |
36 end | |
37 | |
38 if isempty(G) | |
39 G = @(t) sparse(m,m); | |
40 end | |
41 | |
42 if isempty(f1) | |
43 f1 = sparse(m,m); | |
44 end | |
45 | |
46 if isempty(f2) | |
47 f2 = sparse(m,m); | |
48 end | |
49 | |
50 obj.A = A; | |
51 obj.B = B; | |
52 obj.C = C; | |
53 obj.G = G; | |
54 | |
55 AA = 1/k^2*A + 1/2*B + 1/(2*k)*C; | |
56 BB = -2/k^2*A; | |
57 CC = 1/k^2*A + 1/2*B - 1/(2*k)*C; | |
58 % AA*v_next + BB*v + CC*v_prev == G(t_n) | |
59 | |
60 obj.AA = AA; | |
61 obj.BB = BB; | |
62 obj.CC = CC; | |
63 | |
64 v_prev = f1; | |
65 I = speye(m); | |
66 v = (1/k^2*A)\((1/k^2*A - 1/2*B)*f1 + (1/k*I - 1/2*C)*f2 + 1/2*G(0)); | |
67 | |
68 if ~issparse(A) || ~issparse(B) || ~issparse(C) | |
69 error('LU factorization with full pivoting only works for sparse matrices.') | |
70 end | |
71 | |
72 [L,U,p,q] = lu(AA,'vector'); | |
73 | |
74 obj.L = L; | |
75 obj.U = U; | |
76 obj.p = p; | |
77 obj.q = q; | |
78 | |
79 | |
80 obj.k = k; | |
81 obj.t = t0+k; | |
82 obj.n = 0; | |
83 obj.v = v; | |
84 obj.v_prev = v_prev; | |
85 end | |
86 | |
87 function [v,t] = getV(obj) | |
88 v = obj.v; | |
89 t = obj.t; | |
90 end | |
91 | |
92 function [vt,t] = getVt(obj) | |
93 vt = (obj.v-obj.v_prev)/obj.k; | |
94 t = obj.t; | |
95 end | |
96 | |
97 function obj = step(obj) | |
98 b = obj.G(obj.t) - obj.BB*obj.v - obj.CC*obj.v_prev; | |
99 | |
100 % Backslash | |
101 obj.v_prev = obj.v; | |
102 obj.v = obj.AA\b; | |
103 | |
104 % % LU with column pivot | |
105 % y = obj.L\b(obj.p); | |
106 % Qx = U\y; | |
107 % v = Qx(q); | |
108 | |
109 | |
110 | |
111 obj.t = obj.t + obj.k; | |
112 obj.n = obj.n + 1; | |
113 end | |
114 end | |
115 end | |
116 | |
117 | |
118 | |
119 | |
120 | |
121 %%% Derivation | |
122 % syms A B C G | |
123 % syms n k | |
124 % syms f1 f2 | |
125 | |
126 % v = symfun(sym('v(n)'),n); | |
127 | |
128 | |
129 % 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 | |
130 % ic1 = v(0) == f1 | |
131 % ic2 = A/k*(v(1)-f1) + k/2*(B*f1 + C*f2 - G) - f2 == 0 | |
132 | |
133 % 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 | |
134 % syms AA BB CC | |
135 % % AA = B/2 + A/k^2 + C/(2*k) | |
136 % % BB = -(2*A)/k^2 | |
137 % % CC = B/2 + A/k^2 - C/(2*k) | |
138 % 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]) | |
139 | |
140 | |
141 % 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 | |
142 |