diff +rv/constructDiffOps.m @ 1033:037f203b9bf5 feature/burgers1d

Merge with branch feature/advectioRV to utilize the +rv package
author Vidar Stiernström <vidar.stiernstrom@it.uu.se>
date Thu, 17 Jan 2019 10:44:12 +0100
parents 44c3ea38097e
children 1a5c8723c9be 2d7ba44340d0
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+rv/constructDiffOps.m	Thu Jan 17 10:44:12 2019 +0100
@@ -0,0 +1,85 @@
+function [D_rv, D_flux, DvDt, solutionPenalties, residualPenalties] = constructDiffOps(scheme, grid, order, opSet, waveSpeed, BCs, fluxSplitting)
+    default_arg('fluxSplitting',[]);
+
+    %% DiffOps for solution vector
+    [D, solutionPenalties] = constructTotalFluxDiffOp(scheme, grid, order, opSet, waveSpeed, BCs, fluxSplitting);
+    D2 = constructSymmetricD2Operator(grid, order, opSet);
+    D_rv = @(v,viscosity)(D + D2(viscosity))*v;
+
+    %% DiffOps for residual viscosity
+    [D_flux, residualPenalties] = constructTotalFluxDiffOp(scheme, grid, max(order-2,2), opSet, waveSpeed, BCs, fluxSplitting);
+    % DiffOp for flux in residual viscosity. Due to sign conventions of the implemnted schemes, we need to
+    % change the sign.
+    D_flux = -D_flux;
+    D_flux = @(v) D_flux*v;
+    % DiffOp for time derivative in residual viscosity
+    DvDt = @(v)D*v;
+end
+
+function [D, penalties] = constructTotalFluxDiffOp(scheme, grid, order, opSet, waveSpeed, BCs, fluxSplitting)
+    if isequal(opSet, @sbp.D1Upwind)
+        diffOp = scheme(grid, order, opSet, waveSpeed, fluxSplitting);
+    else
+        diffOp = scheme(grid, order, opSet, waveSpeed);
+    end
+    [D, penalties]  = addClosuresToDiffOp(diffOp, BCs);
+end
+
+function [D, penalties] = addClosuresToDiffOp(diffOp, BCs)
+    D = diffOp.D;
+    penalties = cell(size(BCs));
+    for i = 1:size(BCs,1)
+        for j = 1:size(BCs,2)
+            [closure, penalties{i,j}] = diffOp.boundary_condition(BCs{i,j}.boundary, BCs{i,j}.type);
+            D = D + closure;
+        end
+    end
+end
+
+function D2 = constructSymmetricD2Operator(grid, order, opSet)
+    % TODO: 
+    % Currently only implemented for upwind operators.
+    % Remove this part once the time-dependent D2 operator is implemented for other opSets
+    % or if it is decided that it should only be supported for upwind operators.
+    assert(isequal(opSet,@sbp.D1Upwind))
+
+    m = grid.size();
+    ops = cell(grid.D(),1);
+    I = cell(grid.D(),1);
+    for i = 1:grid.D()
+       lim = {grid.x{i}(1), grid.x{i}(end)};
+       ops{i} = opSet(m(i), lim, order);
+       I{i} = speye(m(i));
+    end
+
+    % TBD: How is this generalized to a loop over dimensions or similar?
+    switch grid.D()
+        case 1
+            e_r = ops{1}.e_r;
+            e_l = ops{1}.e_l;
+            Dm = ops{1}.Dm;
+            Dp = ops{1}.Dp;
+            Hi = ops{1}.HI;
+            B = e_r*e_r' - e_l*e_l';
+            D2 = @(viscosity) Dm*spdiag(viscosity)*Dp-Hi*(B*spdiag(viscosity)*Dp);
+        case 2
+            e_e = kron(ops{1}.e_r,I{2});
+            e_w = kron(ops{1}.e_l,I{2});
+            Dm_x = kron(ops{1}.Dm,I{2});
+            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);
+
+            e_n = kron(I{1},ops{2}.e_r);
+            e_s = kron(I{1},ops{2}.e_l);
+            Dm_y = kron(I{1},ops{2}.Dm);
+            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);
+        otherwise
+            error('3D not yet implemented')
+    end
+end
\ No newline at end of file