changeset 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 447ceb41fb65
children 280ae4dbf93b
files +time/CdiffImplicit.m
diffstat 1 files changed, 142 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
diff -r 447ceb41fb65 -r ca73ee0623e5 +time/CdiffImplicit.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+time/CdiffImplicit.m	Fri Dec 09 16:03:30 2016 +0100
@@ -0,0 +1,142 @@
+classdef CdiffImplicit < time.Timestepper
+    properties
+        A, B, C, G
+        AA, BB, CC
+        k
+        t
+        v, v_prev
+        n
+
+        % LU factorization
+        L,U,p,q
+    end
+
+    methods
+        % Solves
+        %   A*u_tt + B*u + C*v_t = G(t)
+        %   u(t0) = f1
+        %   u_t(t0) = f2
+        % starting at time t0 with timestep k
+        function obj = CdiffImplicit(A, B, C, G, f1, f2, k, t0)
+            default_arg('A', []);
+            default_arg('C', []);
+            default_arg('G', []);
+            default_arg('f1', 0);
+            default_arg('f2', 0);
+            default_arg('t0', 0);
+
+            m = size(B,1);
+
+            if isempty(A)
+                A = speye(m);
+            end
+
+            if isempty(C)
+                C = sparse(m,m);
+            end
+
+            if isempty(G)
+                G = @(t) sparse(m,m);
+            end
+
+            if isempty(f1)
+                f1 = sparse(m,m);
+            end
+
+            if isempty(f2)
+                f2 = sparse(m,m);
+            end
+
+            obj.A = A;
+            obj.B = B;
+            obj.C = C;
+            obj.G = G;
+
+            AA = 1/k^2*A + 1/2*B + 1/(2*k)*C;
+            BB = -2/k^2*A;
+            CC = 1/k^2*A + 1/2*B - 1/(2*k)*C;
+            % AA*v_next + BB*v + CC*v_prev == G(t_n)
+
+            obj.AA = AA;
+            obj.BB = BB;
+            obj.CC = CC;
+
+            v_prev = f1;
+            I = speye(m);
+            v = (1/k^2*A)\((1/k^2*A - 1/2*B)*f1 + (1/k*I - 1/2*C)*f2 + 1/2*G(0));
+
+            if ~issparse(A) || ~issparse(B) || ~issparse(C)
+                error('LU factorization with full pivoting only works for sparse matrices.')
+            end
+
+            [L,U,p,q] = lu(AA,'vector');
+
+            obj.L = L;
+            obj.U = U;
+            obj.p = p;
+            obj.q = q;
+
+
+            obj.k = k;
+            obj.t = t0+k;
+            obj.n = 0;
+            obj.v = v;
+            obj.v_prev = v_prev;
+        end
+
+        function [v,t] = getV(obj)
+            v = obj.v;
+            t = obj.t;
+        end
+
+        function [vt,t] = getVt(obj)
+            vt = (obj.v-obj.v_prev)/obj.k;
+            t = obj.t;
+        end
+
+        function obj = step(obj)
+            b = obj.G(obj.t) - obj.BB*obj.v - obj.CC*obj.v_prev;
+
+            % Backslash
+            obj.v_prev = obj.v;
+            obj.v = obj.AA\b;
+
+            % % LU with column pivot
+            % y = obj.L\b(obj.p);
+            % Qx = U\y;
+            % v = Qx(q);
+
+
+
+            obj.t = obj.t + obj.k;
+            obj.n = obj.n + 1;
+        end
+    end
+end
+
+
+
+
+
+%%% Derivation
+% syms A B C G
+% syms n k
+% syms f1 f2
+
+% v = symfun(sym('v(n)'),n);
+
+
+% 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
+% ic1 = v(0) == f1
+% ic2 = A/k*(v(1)-f1) + k/2*(B*f1 + C*f2 - G) - f2 == 0
+
+% 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
+% syms AA BB CC
+% % AA = B/2 + A/k^2 + C/(2*k)
+% % BB = -(2*A)/k^2
+% % CC = B/2 + A/k^2 - C/(2*k)
+% 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])
+
+
+% 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
+