changeset 1154:3108963cc42c feature/rv

Improve efficiency of diffOps in Burgers2d, the artificial diffusion operator in rv.constructDiffOps and the RungekuttaExteriorRv time-steppers
author Vidar Stiernström <vidar.stiernstrom@it.uu.se>
date Wed, 06 Mar 2019 09:45:52 +0100
parents 635386c073b9
children 336ee37a0617
files +rv/+time/RungekuttaExteriorRv.m +rv/+time/RungekuttaExteriorRvBdf.m +rv/constructDiffOps.m +scheme/Burgers2d.m
diffstat 4 files changed, 63 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/+rv/+time/RungekuttaExteriorRv.m	Tue Mar 05 10:57:26 2019 +0100
+++ b/+rv/+time/RungekuttaExteriorRv.m	Wed Mar 06 09:45:52 2019 +0100
@@ -5,7 +5,7 @@
         t       % Time point
         v       % Solution vector
         n       % Time level
-        coeffs  % The coefficents used for the RK time integration
+        rkScheme  % The particular RK scheme used for time integration
         RV              % Residual Viscosity operator
         DvDt            % Function for computing the time deriative used for the RV evaluation
     end
@@ -17,10 +17,16 @@
             obj.t = t0;
             obj.v = v0;
             obj.n = 0;
-            % Extract the coefficients for the specified order
-            % used for the RK updates from the Butcher tableua.
-            [s,a,b,c] = time.rk.butcherTableau(order);
-            obj.coeffs = struct('s',s,'a',a,'b',b,'c',c);
+            
+            if (order == 4) % Use specialized RK4 scheme
+                obj.rkScheme = @time.rk.rungekutta_4;
+            else
+                % Extract the coefficients for the specified order
+                % used for the RK updates from the Butcher tableua.
+                [s,a,b,c] = time.rk.butcherTableau(order);
+                coeffs = struct('s',s,'a',a,'b',b,'c',c);
+                obj.rkScheme = @(v,t,dt,F) time.rk.rungekutta(v, t , dt, F, coeffs);
+            end
         
             obj.RV = RV;
             obj.DvDt = DvDt;
@@ -41,8 +47,10 @@
         % obj.coeffs, using a fixed residual viscosity for the Runge-Kutta substeps
         function obj = step(obj)            
             % Fix the viscosity of the RHS function F
-            F_visc = @(v,t) obj.F(v,t,obj.RV.evaluateViscosity(obj.v, obj.DvDt(obj.v)));
-            obj.v = time.rk.rungekutta(obj.v, obj.t, obj.k, F_visc, obj.coeffs);
+            viscosity = obj.RV.evaluateViscosity(obj.v, obj.DvDt(obj.v));
+            m = length(viscosity);
+            F_visc = @(v,t) obj.F(v,t,spdiags(viscosity,0,m,m));
+            obj.v = obj.rkScheme(obj.v, obj.t, obj.k, F_visc);
             obj.t = obj.t + obj.k;
             obj.n = obj.n + 1;
         end
--- a/+rv/+time/RungekuttaExteriorRvBdf.m	Tue Mar 05 10:57:26 2019 +0100
+++ b/+rv/+time/RungekuttaExteriorRvBdf.m	Wed Mar 06 09:45:52 2019 +0100
@@ -5,7 +5,8 @@
         t       % Time point
         v       % Solution vector
         n       % Time level
-        coeffs  % The coefficents used for the RK time integration
+        rkScheme  % The particular RK scheme used for time integration
+
         
         % Properties related to the residual viscositys
         RV              % Residual Viscosity operator
@@ -15,6 +16,8 @@
                         % dictates which accuracy the boot-strapping should start from.
         upperBdfOrder   % Orders of the approximation of the time deriative, used for the RV evaluation.
                         % Dictates the order of accuracy used once the boot-strapping is complete.
+
+
     end
     methods
         function obj = RungekuttaExteriorRvBdf(F, k, t0, v0, RV, rkOrder, bdfOrders)
@@ -23,17 +26,23 @@
             obj.t = t0;
             obj.v = v0;
             obj.n = 0;
-            % Extract the coefficients for the specified rkOrder
-            % used for the RK updates from the Butcher tableua.
-            [s,a,b,c] = time.rk.butcherTableau(rkOrder);
-            obj.coeffs = struct('s',s,'a',a,'b',b,'c',c);
-        
             obj.RV = RV;
             obj.lowerBdfOrder = bdfOrders.lowerBdfOrder;
             obj.upperBdfOrder = bdfOrders.upperBdfOrder;
             assert((obj.lowerBdfOrder >= 1) && (obj.upperBdfOrder <= 6));
             obj.v_prev = [];
             obj.DvDt = rv.time.BdfDerivative();
+
+            if (rkOrder == 4) % Use specialized RK4 scheme
+                obj.rkScheme = @time.rk.rungekutta_4;
+            else
+                % Extract the coefficients for the specified order
+                % used for the RK updates from the Butcher tableua.
+                [s,a,b,c] = time.rk.butcherTableau(rkOrder);
+                coeffs = struct('s',s,'a',a,'b',b,'c',c);
+                obj.rkScheme = @(v,t,dt,F) time.rk.rungekutta(v, t , dt, F, coeffs);
+            end
+
         end
 
         function [v, t] = getV(obj)
@@ -74,8 +83,9 @@
             end
 
             % Fix the viscosity of the RHS function F
-            F_visc = @(v,t) obj.F(v, t, viscosity);
-            obj.v = time.rk.rungekutta(obj.v, obj.t, obj.k, F_visc, obj.coeffs);
+            m = length(viscosity);
+            F_visc = @(v,t) obj.F(v, t, spdiags(viscosity,0,m,m));
+            obj.v = obj.rkScheme(obj.v, obj.t, obj.k, F_visc);
             obj.t = obj.t + obj.k;
             obj.n = obj.n + 1;
         end
--- a/+rv/constructDiffOps.m	Tue Mar 05 10:57:26 2019 +0100
+++ b/+rv/constructDiffOps.m	Wed Mar 06 09:45:52 2019 +0100
@@ -1,11 +1,11 @@
 function [D_rv, D_flux, DvDt, solutionPenalties, residualPenalties] = constructDiffOps(scheme, g, order, schemeParams, opSet, BCs)
     %% DiffOps for solution vector
-    [D, solutionPenalties] = constructTotalFluxDiffOp(scheme, g, order, schemeParams, opSet, BCs);
+    [D, solutionPenalties] = constructFluxDiffOp(scheme, g, order, schemeParams, opSet, BCs);
     D2 = constructSymmetricD2Operator(g, order, opSet);
-    D_rv = @(v,viscosity)(D(v) + D2(v, viscosity));
+    D_rv = @(v,Viscosity)(D(v) + D2(Viscosity)*v);
 
     %% DiffOps for residual viscosity
-    [D_flux, residualPenalties] = constructTotalFluxDiffOp(scheme, g, max(order-2,2), schemeParams, opSet, BCs);
+    [D_flux, residualPenalties] = constructFluxDiffOp(scheme, g, max(order-2,2), schemeParams, opSet, BCs);
     % DiffOp for flux in residual viscosity. Due to sign conventions of the implemnted schemes, we need to
     % change the sign.
     D_flux = @(v) -D_flux(v);
@@ -13,7 +13,7 @@
     DvDt = D;
 end
 
-function [D, penalties] = constructTotalFluxDiffOp(scheme, g, order, schemeParams, opSet, BCs)
+function [D, penalties] = constructFluxDiffOp(scheme, g, order, schemeParams, opSet, BCs)
     diffOp = scheme(g, order, schemeParams{:}, opSet);
     [D, penalties]  = addClosuresToDiffOp(diffOp, BCs);
 end
@@ -48,10 +48,8 @@
        I{i} = speye(m(i));
     end
 
-    % TBD: How is this generalized to a loop over dimensions or similar?
     switch g.D()
         case 1
-            
             e_r = ops{1}.e_r;
             e_l = ops{1}.e_l;
             Hi = ops{1}.HI;
@@ -59,9 +57,11 @@
             if isequal(opSet,@sbp.D1Upwind)
                 Dm = ops{1}.Dm;
                 Dp = ops{1}.Dp;
-                D2 = @(viscosity) Dm*spdiag(viscosity)*Dp-Hi*(B*spdiag(viscosity)*Dp);
+                M =  Dm - Hi*B;
+                D2 = @(Viscosity) M*Viscosity*Dp;
             else
-                D2 = @(viscosity)ops{1}.D2(viscosity);
+                % TODO: Fix closure for D2Variable
+                D2 = @(Viscosity)ops{1}.D2(Viscosity);
             end
         case 2
             % TODO: 
@@ -75,7 +75,8 @@
             Dp_x  = kron(ops{1}.Dp,I{2});
             H_x  = kron(ops{1}.HI,I{2});
             B_x = e_e*e_e' - e_w*e_w';
-            D2_x = @(viscosity) Dm_x*spdiag(viscosity)*Dp_x-H_x*(B_x*spdiag(viscosity)*Dp_x);
+            M_x = Dm_x-H_x*B_x;
+            D2_x = @(Viscosity) M_x*Viscosity*Dp_x;
 
             e_n = kron(I{1},ops{2}.e_r);
             e_s = kron(I{1},ops{2}.e_l);
@@ -83,10 +84,10 @@
             Dp_y  = kron(I{1},ops{2}.Dp);
             H_y = kron(I{1},ops{2}.HI);
             B_y = e_n*e_n' - e_s*e_s';
-            D2_y = @(viscosity) Dm_y*spdiag(viscosity)*Dp_y-H_y*(B_y*spdiag(viscosity)*Dp_y);
-            D2 = @(viscosity)D2_x(viscosity) + D2_y(viscosity);
+            M_y = Dm_y-H_y*B_y;
+            D2_y = @(Viscosity) M_y*Viscosity*Dp_y;
+            D2 = @(Viscosity) D2_x(Viscosity) + D2_y(Viscosity);
         otherwise
             error('3D not yet implemented')
     end
-    D2 = @(v, viscosity) D2(viscosity)*v;
 end
\ No newline at end of file
--- a/+scheme/Burgers2d.m	Tue Mar 05 10:57:26 2019 +0100
+++ b/+scheme/Burgers2d.m	Wed Mar 06 09:45:52 2019 +0100
@@ -47,25 +47,28 @@
             if (isequal(opSet,@sbp.D1Upwind))
                 Dx = kron((ops_x.Dp + ops_x.Dm)/2,Iy);
                 Dy = kron(Ix,(ops_y.Dp + ops_y.Dm)/2);
-                DissOpx = kron((ops_x.Dm - ops_x.Dp)/2,Iy);
-                DissOpy = kron(Ix,(ops_y.Dm - ops_y.Dp)/2);
+                DissOpx = kron((ops_x.Dp - ops_x.Dm)/2,Iy);
+                DissOpy = kron(Ix,(ops_y.Dp - ops_y.Dm)/2);
                 D1 = Dx + Dy;   
                 switch pde_form
                     case 'skew-symmetric'
+                        D = -1/3*D1
                         switch length(fluxSplitting)
                             case 1
                                 DissOp = DissOpx + DissOpy;
-                                obj.D = @(v) -(1/3*D1*v.*v + (1/3*spdiag(v)*D1 + fluxSplitting{1}(v)*DissOp)*v);
+                                obj.D = @(v) D*(v.*v) + (spdiags(v,0,m_tot,m_tot)*D + fluxSplitting{1}(v)*DissOp)*v;
                             case 2
-                                obj.D = @(v) -(1/3*D1*v.*v + (1/3*spdiag(v)*D1 + fluxSplitting{1}(v)*DissOpx + fluxSplitting{2}(v)*DissOpy)*v);
+                                obj.D = @(v) D*(v.*v) + (spdiags(v,0,m_tot,m_tot)*D + fluxSplitting{1}(v)*DissOpx + fluxSplitting{2}(v)*DissOpy)*v;
                         end
                     case 'conservative'
+                        D = -1/2*D1;
                         switch length(fluxSplitting)
                             case 1
                                 DissOp = DissOpx + DissOpy;
-                                obj.D = @(v) -(1/2*D1*v.*v + fluxSplitting{1}(v)*DissOp*v);
+                                % TODO: Check if we can use fluxSplitting{1} here instead
+                                obj.D = @(v) D*(v.*v) + max(abs(v))*DissOp*v;
                             case 2
-                                obj.D = @(v) -(1/2*D1*v.*v + (fluxSplitting{1}(v)*DissOpx + fluxSplitting{2}(v)*DissOpy)*v);
+                                obj.D = @(v) D*(v.*v) + (fluxSplitting{1}(v)*DissOpx + fluxSplitting{2}(v)*DissOpy)*v;
                         end
                         
                 end
@@ -75,9 +78,11 @@
                 D1 = Dx + Dy;
                 switch pde_form
                     case 'skew-symmetric'
-                        obj.D = @(v) -(1/3*D1*v.*v + 1/3*spdiag(v)*D1*v);
+                        D = -1/3*D1
+                        obj.D = @(v) D*(v.*v) + spdiags(v,0,m_tot,m_tot)*D*v;
                     case 'conservative'
-                        obj.D = @(v) -1/2*D1*v.*v;
+                        D = -1/2*D1;
+                        obj.D = @(v) D*(v.*v);
                 end
             end
 
@@ -103,14 +108,11 @@
                 case {'D', 'd', 'dirichlet', 'Dirichlet'}
 
                     magnitude = 2/3;
-                    tau = @(v) s*magnitude*obj.Hi*e*H_b*spdiag((v(index)-s*abs(v(index)))/2);
-                    closure = @(v) tau(v)*v(index);
+                    Tau = s*magnitude*obj.Hi*e*H_b/2;
+                    m = length(index);
+                    tau = @(v) Tau*spdiags((v(index)-s*abs(v(index))),0,m,m);
+                    closure = @(v) Tau*((v(index)-s*abs(v(index))).*v(index));
                     penalty = @(v) -tau(v);
-
-
-                    % tau = s*e*H_b;
-                    % closure = @(v) (obj.Hi*tau)*(((v(index)-s*abs(v(index)))/3).*v(index));
-                    % penalty = -obj.Hi*tau;
                 otherwise
                     error('No such boundary condition: type = %s',type);
             end