changeset 394:026d8a3fdbfb feature/beams

Merge with default.
author Jonatan Werpers <jonatan@werpers.com>
date Wed, 25 Jan 2017 16:22:18 +0100
parents 67ca8964f03c (diff) 0976e579a6f0 (current diff)
children 359861563866
files
diffstat 137 files changed, 5976 insertions(+), 2202 deletions(-) [+]
line wrap: on
line diff
diff -r 0976e579a6f0 -r 026d8a3fdbfb +blockmatrix/fromMatrix.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+blockmatrix/fromMatrix.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,24 @@
+function bm = fromMatrix(A, div)
+    d1 = div{1};
+    d2 = div{2};
+    [n, m] = size(A);
+    if n ~= sum(d1) || m ~= sum(d2)
+        error('blockmatrix:fromMatrix:NonMatchingDim','The dimensions in div does not sum to the dimensions in A.');
+    end
+
+    bm = cell(length(d1), length(d2));
+    I = 1;
+    for i = 1:length(d1)
+        J = 1;
+        for j = 1:length(d2)
+            Asub = A(I:(I + d1(i)-1), J:(J + d2(j)-1));
+            if nnz(Asub) == 0
+                bm{i,j} = sparse(d1(i), d2(j));
+            else
+                bm{i,j} = Asub;
+            end
+            J = J + d2(j);
+        end
+        I = I + d1(i);
+    end
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +blockmatrix/fromMatrixTest.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+blockmatrix/fromMatrixTest.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,64 @@
+function tests = fromMatrixTest()
+    tests = functiontests(localfunctions);
+end
+
+function testErrorNonMatchingDim(testCase)
+    in  = {
+        {magic(5), {[1 2 3], [4]}},
+        {magic(5), {[1 1 1 1 1 1], [5]}},
+        {magic(5), {[5], [1 1 1 1 1 1]}},
+        {ones(4,2),{[2 3],[2]}},
+        {ones(4,2),{[2 2],[3]}},
+    };
+
+    for i = 1:length(in)
+        testCase.verifyError(@()blockmatrix.fromMatrix(in{i}{:}),'blockmatrix:fromMatrix:NonMatchingDim');
+    end
+end
+
+function testFromMatrix(testCase)
+    cases = {
+        {
+            {[],{[],[]}},
+            {}
+        },
+        {
+            {
+                magic(3),
+                {[3],[3]}
+            },
+            {magic(3)}
+        },
+        {
+            {
+                magic(3),
+                {[1 1 1],[1 1 1]}
+            },
+            mat2cell(magic(3),[1 1 1],[1 1 1])
+        },
+        {
+            {
+                [17 24 1 8 15; 23 5 7 14 16; 4 6 13 20 22; 10 12 19 21 3; 11 18 25 2 9],
+                {[1 4],[2 3]}
+            },
+            {
+                [17 24], [1 8 15];
+                [23 5; 4 6; 10 12; 11 18], [7 14 16; 13 20 22; 19 21 3; 25 2 9];
+            };
+        },
+    };
+    for i = 1:length(cases)
+        out = convertToFull(blockmatrix.fromMatrix(cases{i}{1}{:}));
+        expected = cases{i}{2};
+        testCase.verifyEqual(out,expected);
+    end
+end
+
+function C = convertToFull(C)
+    [N,M] = size(C);
+    for i = 1:N
+        for j = 1:M
+            C{i,j} = full(C{i,j});
+        end
+    end
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +blockmatrix/getDivision.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+blockmatrix/getDivision.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,37 @@
+function div = getDivision(bm)
+    if ~blockmatrix.isBlockmatrix(bm)
+        error('blockmatrix:getDivision:NotABlockmatrix', 'Input is not a blockmatrix');
+    end
+
+    if isempty(bm)
+        div = {[],[]};
+        return
+    end
+
+    div = {row_height(bm),col_width(bm)};
+end
+
+
+function m = col_width(C)
+    m = zeros(1,size(C,2));
+    for j = 1:size(C,2)
+        for i = 1:size(C,1)
+            if isempty(C{i,j})
+                continue
+            end
+            m(j) = size(C{i,j},2);
+        end
+    end
+end
+
+function n = row_height(C)
+    n = zeros(1,size(C,1));
+    for i = 1:size(C,1)
+        for j = 1:size(C,2)
+            if isempty(C{i,j})
+                continue
+            end
+            n(i) = size(C{i,j},1);
+        end
+    end
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +blockmatrix/getDivisionTest.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+blockmatrix/getDivisionTest.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,69 @@
+function tests = getDivisionTest()
+    tests = functiontests(localfunctions);
+end
+
+function testError(testCase)
+    cases = {
+        magic(3),
+        {[2 2 2];{1,2}},
+        {[2 2 2];[1 2]},
+        {[2; 2; 2], [1; 2]},
+    };
+
+    for i =1:length(cases)
+        testCase.verifyError(@()blockmatrix.getDivision(cases{i}), 'blockmatrix:getDivision:NotABlockmatrix')
+    end
+end
+
+function testGetDivision(testCase)
+    cases = {
+        {
+            {},
+            {[],[]};
+        },
+        {
+            {
+            [2 2; 2 1], [1; 2];
+            [2 2], [1]
+            },
+            {[2 1], [2 1]}
+        },
+        {
+            {
+            [2 2; 2 1], [];
+            [2 2], [1]
+            },
+            {[2 1], [2 1]}
+        },
+        {
+            {
+            [2 2; 2 1], [];
+            [2 2], []
+            },
+            {[2 1], [2 0]}
+        },
+        {
+            {
+            [2 2; 2 1], [1; 2];
+            [], []
+            },
+            {[2 0], [2 1]}
+        },
+        {
+            {
+            [2 2; 2 1];
+            [2 2]
+            },
+            {[2 1], 2}
+        },
+    };
+
+    for i = 1:length(cases)
+        in = cases{i}{1};
+        out = blockmatrix.getDivision(in);
+        expected = cases{i}{2};
+        testCase.verifyEqual(out, expected);
+    end
+end
+
+
diff -r 0976e579a6f0 -r 026d8a3fdbfb +blockmatrix/isBlockmatrix.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+blockmatrix/isBlockmatrix.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,59 @@
+function b = isBlockmatrix(bm)
+    if ~iscell(bm)
+        b = false;
+        return
+    end
+
+    % Make sure all blocks are numerica matrices
+    for i = 1:length(bm)
+        if ~isnumeric(bm{i})
+            b = false;
+            return
+        end
+    end
+
+    [N,M] = size(bm);
+    % Make sure column dimensions agree
+    for i = 1:N
+        d = [];
+        for j = 1:M
+            d_ij = size(bm{i,j},1);
+            if d_ij == 0
+                continue
+            end
+
+            if isempty(d)
+                d = d_ij;
+                continue
+            end
+
+            if d ~= d_ij
+                b = false;
+                return
+            end
+        end
+    end
+
+    % Make sure row dimensions agree
+    for j = 1:M
+        d = [];
+        for i = 1:N
+            d_ij = size(bm{i,j},2);
+            if d_ij == 0
+                continue
+            end
+
+            if isempty(d)
+                d = d_ij;
+                continue
+            end
+
+            if d ~= d_ij
+                b = false;
+                return
+            end
+        end
+    end
+
+    b = true;
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +blockmatrix/isBlockmatrixTest.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+blockmatrix/isBlockmatrixTest.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,67 @@
+function tests = isBlockmatrixTest()
+    tests = functiontests(localfunctions);
+end
+
+function testIsBlockmatrix(testCase)
+    cases = {
+        {
+            magic(3),
+            false % Must be a cell array
+        }
+        {
+            {[2 2 2];{1,2}},
+            false % All elements of the cell matrix must be regular matrices
+        },
+        {
+            {[2 2 2];[1 2]},
+            false % Row dimensions must match
+        },
+        {
+            {[2; 2; 2], [1; 2]},
+            false % Column dimensions must match
+        },
+        {
+            {},
+            true % An empty matrix is a matrix too
+        },
+        {
+            {
+            [2 2; 2 1], [1; 2];
+            [2 2], [1]
+            },
+            true % A simple valid one
+        },
+        {
+            {
+            [2 2; 2 1], [];
+            [2 2], [1]
+            },
+            true % Empty blocks assumed to be zero and match dimensions
+        },
+        {
+            {
+            [2 2; 2 1], [];
+            [2 2], []
+            },
+            true % Empty blocks allowed.
+        },
+        {
+            {
+            [2 2; 2 1], [1; 2];
+            [], []
+            },
+            true % Empty blocks allowed.
+        },
+        {
+            blockmatrix.zero({[1 2 3],[2 3]}),
+            true % A zero block matrix is a block matrix
+        },
+    };
+
+    for i = 1:length(cases)
+        in = cases{i}{1};
+        out = blockmatrix.isBlockmatrix(in);
+        expected = cases{i}{2};
+        testCase.verifyEqual(out, expected, sprintf('Should return %d for %s', expected, toString(in)));
+    end
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +blockmatrix/isDivision.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+blockmatrix/isDivision.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,34 @@
+function b = isDivision(div)
+    % Make sure it is a cellarray
+    if ~iscell(div)
+        b = false;
+        return
+    end
+
+    % Make sure it has the right shape
+    if numel(div) ~= 2
+        b = false;
+        return
+    end
+
+    if ~isDivisionVector(div{1}) || ~isDivisionVector(div{2})
+        b = false;
+        return
+    end
+
+    b = true;
+end
+
+function b = isDivisionVector(v)
+    if isempty(v)
+        b = false;
+        return
+    end
+
+    if any(v <= 0)
+        b = false;
+        return
+    end
+
+    b = true;
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +blockmatrix/isDivisionTest.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+blockmatrix/isDivisionTest.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,23 @@
+function tests = isDivisionTest()
+    tests = functiontests(localfunctions);
+end
+
+function testIsDivision(testCase)
+    cases = {
+        {{[2 2 2],[1 2]} ,true},
+        {{[1 2],[1 0]} ,false},
+        {{[0 2],[1 1]} ,false},
+        {{[1 2],[]} ,false},
+        {{[1 2],[1]} ,true},
+        {{[1 2],[1], [1 2 3]} ,false},
+        {{[1 2 3]} ,false},
+        {[1 2] ,false},
+    };
+
+    for i = 1:length(cases)
+        in = cases{i}{1};
+        out = blockmatrix.isDivision(in);
+        expected = cases{i}{2};
+        testCase.verifyEqual(out, expected, sprintf('Should return %d for %s', expected, toString(in)));
+    end
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +blockmatrix/multiply.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+blockmatrix/multiply.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,17 @@
+function C = multiply(A, B)
+    [n_a, m_a] = size(A);
+    [n_b, m_b] = size(B);
+
+    assert(m_a == n_b, 'Dimensions do not agree.')
+
+    C = cell(n_a, m_b);
+
+    for i = 1:n_a
+        for j = 1:m_b
+            C{i,j} = sparse(size(A{i,1},1), size(B{1,j},2));
+            for k = 1:n_b
+                C{i,j} = C{i,j} + A{i,k}*B{k,j};
+            end
+        end
+    end
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +blockmatrix/multiplyTest.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+blockmatrix/multiplyTest.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,57 @@
+function tests = multiplyTest()
+    tests = functiontests(localfunctions);
+end
+
+
+function testMultiply(testCase)
+    a11 = [
+        0.8147    0.1270;
+        0.9058    0.9134;
+    ];
+    a12 = [
+        0.6324    0.2785    0.9575;
+        0.0975    0.5469    0.9649;
+    ];
+    a21 = [
+        0.1576    0.9706;
+    ];
+    a22 = [
+        0.9572    0.4854    0.8003;
+    ];
+    A = {
+        a11 a12;
+        a21 a22;
+    };
+
+    b11 = [
+        0.1419    0.9157    0.9595;
+        0.4218    0.7922    0.6557;
+    ];
+    b12 = [
+        0.0357    0.9340;
+        0.8491    0.6787;
+    ];
+    b21 = [
+        0.7577    0.6555    0.0318;
+        0.7431    0.1712    0.2769;
+        0.3922    0.7060    0.0462;
+    ];
+    b22 = [
+        0.0971    0.3171;
+        0.8235    0.9502;
+        0.6948    0.0344;
+    ];
+
+    B = {
+        b11 b12;
+        b21 b22;
+    };
+
+
+    C = {
+        a11*b11 + a12*b21, a11*b12 + a12*b22;
+        a21*b11 + a22*b21, a21*b12 + a22*b22;
+    };
+
+    testCase.verifyEqual(blockmatrix.multiply(A,B), C);
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +blockmatrix/toMatrix.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+blockmatrix/toMatrix.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,27 @@
+function A = toMatrix(bm)
+    if ~blockmatrix.isBlockmatrix(bm)
+        error('blockmatrix:toMatrix:NotABlockmatrix', 'Input is not a blockmatrix');
+    end
+
+    div = blockmatrix.getDivision(bm);
+    n = div{1};
+    m = div{2};
+
+    N = sum(n);
+    M = sum(m);
+
+    A = sparse(N,M);
+
+    n_ind = [0 cumsum(n)];
+    m_ind = [0 cumsum(m)];
+
+    for i = 1:size(bm,1)
+        for j = 1:size(bm,2)
+            if isempty(bm{i,j})
+                continue
+            end
+            % TODO: If this ever fails for large matrices. Try cell2mat instead.
+            A(n_ind(i)+1:n_ind(i+1),m_ind(j)+1:m_ind(j+1)) = bm{i,j};
+        end
+    end
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +blockmatrix/toMatrixTest.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+blockmatrix/toMatrixTest.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,62 @@
+function tests = toMatrixTest()
+    tests = functiontests(localfunctions);
+end
+
+function testError(testCase)
+    testCase.verifyError(@()blockmatrix.toMatrix([]), 'blockmatrix:toMatrix:NotABlockmatrix')
+end
+
+function testToMatrix(testCase)
+    cases = {
+        {
+            {},
+            [],
+        },
+        {
+            {1, 2; 3, 4},
+            [1,2; 3,4],
+        }
+        {
+            {
+            [2 2; 2 1], [1; 2];
+            [2 2], [1]
+            },
+            [2 2 1;
+             2 1 2;
+             2 2 1],
+        },
+        {
+            {
+            [2 2; 2 1], [];
+            [2 2], [1]
+            },
+            [2 2 0;
+             2 1 0;
+             2 2 1],
+        },
+        {
+            {
+            [2 2; 2 1], [];
+            [2 2], []
+            },
+            [2 2;
+             2 1;
+             2 2],
+        },
+        {
+            {
+            [2 2; 2 1], [1; 2];
+            [], []
+            },
+            [2 2 1;
+             2 1 2],
+        },
+    };
+
+    for i = 1:length(cases)
+        in = cases{i}{1};
+        out = full(blockmatrix.toMatrix(in));
+        expected = cases{i}{2};
+        testCase.verifyEqual(out, expected);
+    end
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +blockmatrix/zero.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+blockmatrix/zero.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,20 @@
+% Creates a block matrix according to the division with zeros everywhere.
+function bm = zero(div)
+    if ~blockmatrix.isDivision(div);
+        error('div is not a valid division');
+    end
+
+    n = div{1};
+    m = div{2};
+
+    N = length(n);
+    M = length(m);
+
+    bm = cell(N,M);
+
+    for i = 1:N
+        for j = 1:M
+            bm{i,j} = sparse(n(i),m(j));
+        end
+    end
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +blockmatrix/zeroTest.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+blockmatrix/zeroTest.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,52 @@
+function tests = zeroTest()
+    tests = functiontests(localfunctions);
+end
+
+function testZero(testCase)
+    cases = {
+        {
+            {[],[]},
+            {},
+        },
+        {
+            {0,0},
+            {[]};
+        },
+        {
+            {1,1},
+            {0};
+        },
+        {
+            {2,1},
+            {[0; 0]};
+        },
+        {
+            {1,2},
+            {[0 0]};
+        },
+        {
+            {[1 2],2},
+            {[0 0];[0 0; 0 0]};
+        },
+        {
+            {[1 2],[2 1]},
+            {[0 0],[0];[0 0; 0 0],[0; 0]};
+        },
+    };
+
+    for i = 1:length(cases)
+        out = convertToFull(blockmatrix.zero(cases{i}{1}));
+        expected = cases{i}{2};
+        testCase.verifyEqual(out,expected);
+    end
+end
+
+
+function C = convertToFull(C)
+    [N,M] = size(C);
+    for i = 1:N
+        for j = 1:M
+            C{i,j} = full(C{i,j});
+        end
+    end
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +draw/prompt_bezier.m
--- a/+draw/prompt_bezier.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+draw/prompt_bezier.m	Wed Jan 25 16:22:18 2017 +0100
@@ -22,8 +22,8 @@
     p.Color = Color.yellow;
     p.MarkerSize = 16;
 
-    C = grid.Curve.bezier(a,c1,c2,b);
-    fprintf('C = grid.Curve.bezier([%.3g; %.3g],[%.3g; %.3g],[%.3g; %.3g],[%.3g; %.3g]);\n',a,c1,c2,b)
+    C = parametrization.Curve.bezier(a,c1,c2,b);
+    fprintf('C = parametrization.Curve.bezier([%.3g; %.3g],[%.3g; %.3g],[%.3g; %.3g],[%.3g; %.3g]);\n',a,c1,c2,b)
     h = C.plot();
     uistack(h,'bottom');
 
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/Cartesian.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/Cartesian.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,189 @@
+classdef Cartesian < grid.Structured
+    properties
+        n % Number of points in the grid
+        d % Number of dimensions
+        m % Number of points in each direction
+        x % Cell array of vectors with node placement for each dimension.
+        h % Spacing/Scaling
+    end
+
+    % General d dimensional grid with n points
+    methods
+        % Creates a cartesian grid given vectors conatining the coordinates
+        % in each direction
+        function obj = Cartesian(varargin)
+            obj.d = length(varargin);
+
+            for i = 1:obj.d
+                obj.x{i} = varargin{i};
+                obj.m(i) = length(varargin{i});
+            end
+
+            obj.n = prod(obj.m);
+            if obj.n == 0
+                error('grid:Cartesian:EmptyGrid','Input parameter gives an empty grid.')
+            end
+
+            obj.h = [];
+        end
+        % n returns the number of points in the grid
+        function o = N(obj)
+            o = obj.n;
+        end
+
+        % d returns the spatial dimension of the grid
+        function o = D(obj)
+            o = obj.d;
+        end
+
+        function m = size(obj)
+            m = obj.m;
+        end
+
+        % points returns a n x d matrix containing the coordianets for all points.
+        % points are ordered according to the kronecker product with X*Y*Z
+        function X = points(obj)
+            X = zeros(obj.n, obj.d);
+
+            for i = 1:obj.d
+                if iscolumn(obj.x{i})
+                    c = obj.x{i};
+                else
+                    c = obj.x{i}';
+                end
+
+                m_before = prod(obj.m(1:i-1));
+                m_after = prod(obj.m(i+1:end));
+
+                X(:,i) = kr(ones(m_before,1),c,ones(m_after,1));
+            end
+        end
+
+        % matrices returns a cell array with coordinates in matrix form.
+        % For 2d case these will have to be transposed to work with plotting routines.
+        function X = matrices(obj)
+
+            if obj.d == 1 % There is no 1d matrix data type in matlab, handle special case
+                X{1} = reshape(obj.x{1}, [obj.m 1]);
+                return
+            end
+
+            X = cell(1,obj.d);
+            for i = 1:obj.d
+                s = ones(1,obj.d);
+                s(i) = obj.m(i);
+
+                t = reshape(obj.x{i},s);
+
+                s = obj.m;
+                s(i) = 1;
+                X{i} = repmat(t,s);
+            end
+        end
+
+        function h = scaling(obj)
+            if isempty(obj.h)
+                error('grid:Cartesian:NoScalingSet', 'No scaling set')
+            end
+
+            h = obj.h;
+        end
+
+        % Restricts the grid function gf on obj to the subgrid g.
+        % Only works for even multiples
+        function gf = restrictFunc(obj, gf, g)
+            m1 = obj.m;
+            m2 = g.m;
+
+            % Check the input
+            if prod(m1) ~= numel(gf)
+                error('grid:Cartesian:restrictFunc:NonMatchingFunctionSize', 'The grid function has to few or too many points.');
+            end
+
+            if ~all(mod(m1-1,m2-1) == 0)
+                error('grid:Cartesian:restrictFunc:NonMatchingGrids', 'Only integer downsamplings are allowed');
+            end
+
+            % Calculate stride for each dimension
+            stride = (m1-1)./(m2-1);
+
+            % Create downsampling indecies
+            I = {};
+            for i = 1:length(m1)
+                I{i} = 1:stride(i):m1(i);
+            end
+
+            gf = reshapeRowMaj(gf, m1);
+            gf = gf(I{:});
+            gf = reshapeRowMaj(gf, prod(m2));
+        end
+
+        % Projects the grid function gf on obj to the grid g.
+        function gf = projectFunc(obj, gf, g)
+            error('grid:Cartesian:NotImplemented')
+        end
+
+        % Return the names of all boundaries in this grid.
+        function bs = getBoundaryNames(obj)
+            switch obj.D()
+                case 1
+                    bs = {'l', 'r'};
+                case 2
+                    bs = {'w', 'e', 's', 'n'};
+                case 3
+                    bs = {'w', 'e', 's', 'n', 'd', 'u'};
+                otherwise
+                    error('not implemented');
+            end
+        end
+
+        % Return coordinates for the given boundary
+        function X = getBoundary(obj, name)
+            % In what dimension is the boundary?
+            switch name
+                case {'l', 'r', 'w', 'e'}
+                    D = 1;
+                case {'s', 'n'}
+                    D = 2;
+                case {'d', 'u'}
+                    D = 3;
+                otherwise
+                    error('not implemented');
+            end
+
+            % At what index is the boundary?
+            switch name
+                case {'l', 'w', 's', 'd'}
+                    index = 1;
+                case {'r', 'e', 'n', 'u'}
+                    index = obj.m(D);
+                otherwise
+                    error('not implemented');
+            end
+
+
+
+            I = cell(1, obj.d);
+            for i = 1:obj.d
+                if i == D
+                    I{i} = index;
+                else
+                    I{i} = ':';
+                end
+            end
+
+            % Calculate size of result:
+            m = obj.m;
+            m(D) = [];
+            N = prod(m);
+
+            X = zeros(N, obj.d);
+
+            coordMat = obj.matrices();
+            for i = 1:length(coordMat)
+                Xtemp = coordMat{i}(I{:});
+                X(:,i) = reshapeRowMaj(Xtemp, [N,1]);
+            end
+        end
+    end
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/CartesianTest.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/CartesianTest.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,318 @@
+function tests = CartesianTest()
+    tests = functiontests(localfunctions);
+end
+
+
+function testWarningEmptyGrid(testCase)
+    in  = {
+        {[]},
+        {[],[1]},
+        {[1],[2], []},
+    };
+
+    for i = 1:length(in)
+        testCase.verifyError(@()grid.Cartesian(in{i}{:}),'grid:Cartesian:EmptyGrid');
+    end
+end
+
+function testN(testCase)
+    in  = {
+        {[1 2 3]},
+        {[1 2 3],[1 2]},
+        {[1 2 3],[1 2 3]},
+        {[1 2 3],[1 2 3], [1]},
+        {[1 2 3],[1 2 3], [1 3 4]},
+    };
+
+    out = [3,6,9,9,27];
+
+    for i = 1:length(in)
+        g = grid.Cartesian(in{i}{:});
+        testCase.verifyEqual(g.N(),out(i));
+    end
+end
+
+
+function testD(testCase)
+    in  = {
+        {[1 2 3]},
+        {[1 2 3],[1 2]},
+        {[1 2 3],[1 2 3]},
+        {[1 2 3],[1 2 3], [1]},
+        {[1 2 3],[1 2 3], [1 3 4]},
+    };
+
+    out = [1,2,2,3,3];
+
+    for i = 1:length(in)
+        g = grid.Cartesian(in{i}{:});
+        testCase.verifyEqual(g.D(),out(i));
+    end
+end
+
+function testSize(testCase)
+    in  = {
+        {[1 2 3]},
+        {[1 2 3],[1 2]},
+        {[1 2 3],[1 2 3]},
+        {[1 2 3],[1 2 3], [1]},
+        {[1 2 3],[1 2 3], [1 3 4]},
+    };
+
+    out = {
+        [3],
+        [3 2],
+        [3 3],
+        [3 3 1],
+        [3 3 3],
+    };
+
+    for i = 1:length(in)
+        g = grid.Cartesian(in{i}{:});
+        testCase.verifyEqual(g.size(),out{i});
+    end
+end
+
+function testPoints(testCase)
+    in  = {
+        {[1 2]},
+        {[1 2],[3 4]},
+        {[1 2],[3 4], [5 6]},
+    };
+
+    out = {
+        [[1; 2]],
+        [[1; 1; 2; 2],[3; 4; 3; 4]],
+        [[1; 1; 1; 1; 2; 2; 2; 2],[3; 3; 4; 4; 3; 3; 4; 4],[ 5; 6; 5; 6; 5; 6; 5; 6]],
+    };
+
+    for i = 1:length(in)
+        g = grid.Cartesian(in{i}{:});
+        testCase.verifyEqual(g.points(),out{i});
+    end
+end
+
+function testMatrices(testCase)
+    in  = {
+        {[1 2]},
+        {[1 2],[3 4]},
+        {[1 2],[3 4], [5 6]},
+    };
+
+    out{1}{1} = [1; 2];
+
+    out{2}{1} = [1, 1; 2, 2];
+    out{2}{2} = [3, 4; 3, 4];
+
+    out{3}{1}(:,:,1) = [1, 1; 2, 2];
+    out{3}{1}(:,:,2) = [1, 1; 2, 2];
+
+    out{3}{2}(:,:,1) = [3, 4; 3, 4];
+    out{3}{2}(:,:,2) = [3, 4; 3, 4];
+
+    out{3}{3}(:,:,1) = [5, 5; 5, 5];
+    out{3}{3}(:,:,2) = [6, 6; 6, 6];
+
+    for i = 1:length(in)
+        g = grid.Cartesian(in{i}{:});
+        testCase.verifyEqual(g.matrices(),out{i});
+    end
+end
+
+
+function testRestrictFuncInvalidInput(testCase)
+    inG1  = {
+        {[1 2 3 4 5]},
+        {[1 2 3],[4 5 6 7 8]},
+        {[1 2 3],[4 5 6 7 8]},
+        {[1 2 3],[4 5 6 7 8]},
+    };
+
+    inG2  = {
+        {[1 3 4 5]},
+        {[1 3],[4 5 6 8]},
+        {[1 3],[4 6 8]},
+        {[1 3],[4 6 8]},
+    };
+
+    inGf = {
+        [1; 2; 3; 4; 5],
+        [14; 15; 16; 17; 18; 24; 25; 26; 27; 28; 34; 35; 36; 37; 38];
+        [14; 15; 16; 17; 18; 24; 25; 26; 27; 28; 34; 35; 36];
+        [14; 15; 16; 17; 18; 24; 25; 26; 27; 28; 34; 35; 36; 37; 38; 39; 40];
+    };
+
+    out = {
+        'grid:Cartesian:restrictFunc:NonMatchingGrids',
+        'grid:Cartesian:restrictFunc:NonMatchingGrids',
+        'grid:Cartesian:restrictFunc:NonMatchingFunctionSize',
+        'grid:Cartesian:restrictFunc:NonMatchingFunctionSize',
+    };
+
+    for i = 1:length(inG1)
+        g1 = grid.Cartesian(inG1{i}{:});
+        g2 = grid.Cartesian(inG2{i}{:});
+        testCase.verifyError(@()g1.restrictFunc(inGf{i},g2),out{i});
+    end
+end
+
+function testRestrictFunc(testCase)
+    inG1  = {
+        {[1 2 3 4 5]},
+        {[1 2 3],[4 5 6 7 8]},
+    };
+
+    inG2  = {
+        {[1 3 5]},
+        {[1 3],[4 6 8]},
+    };
+
+    inGf = {
+        [1; 2; 3; 4; 5],
+        [14; 15; 16; 17; 18; 24; 25; 26; 27; 28; 34; 35; 36; 37; 38];
+    };
+
+    outGf = {
+        [1; 3; 5],
+        [14; 16; 18; 34; 36; 38];
+    };
+
+    for i = 1:length(inG1)
+        g1 = grid.Cartesian(inG1{i}{:});
+        g2 = grid.Cartesian(inG2{i}{:});
+        testCase.verifyEqual(g1.restrictFunc(inGf{i}, g2), outGf{i});
+    end
+end
+
+function testScaling(testCase)
+    in = {[1 2 3], [1 2]};
+    g = grid.Cartesian(in{:});
+
+    testCase.verifyError(@()g.scaling(),'grid:Cartesian:NoScalingSet');
+
+    g.h = [2 1];
+    testCase.verifyEqual(g.scaling(),[2 1]);
+
+end
+
+
+function testGetBoundaryNames(testCase)
+    in = {
+        {[1 2 3]},
+        {[1 2 3], [4 5]},
+        {[1 2 3], [4 5], [6 7 8]},
+    };
+
+    out = {
+        {'l', 'r'},
+        {'w', 'e', 's', 'n'},
+        {'w', 'e', 's', 'n', 'd', 'u'},
+    };
+
+    for i = 1:length(in)
+        g = grid.Cartesian(in{i}{:});
+        testCase.verifyEqual(g.getBoundaryNames(), out{i});
+    end
+end
+
+function testGetBoundary(testCase)
+    grids = {
+        {[1 2 3]},
+        {[1 2 3], [4 5]},
+        {[1 2 3], [4 5], [6 7 8]},
+    };
+
+    boundaries = {
+        {'l', 'r'},
+        {'w', 'e', 's', 'n'},
+        {'w', 'e', 's', 'n', 'd', 'u'},
+    };
+
+
+    % 1d
+    out{1,1} = 1;
+    out{1,2} = 3;
+
+    % 2d
+    out{2,1} = [
+        1,4;
+        1,5;
+    ];
+    out{2,2} = [
+        3,4;
+        3,5;
+    ];
+    out{2,3} = [
+        1,4;
+        2,4;
+        3,4;
+    ];
+    out{2,4} = [
+        1,5;
+        2,5;
+        3,5;
+    ];
+
+    % 3d
+    out{3,1} = [
+        1,4,6;
+        1,4,7;
+        1,4,8;
+        1,5,6;
+        1,5,7;
+        1,5,8;
+    ];
+    out{3,2} = [
+        3,4,6;
+        3,4,7;
+        3,4,8;
+        3,5,6;
+        3,5,7;
+        3,5,8;
+    ];
+    out{3,3} = [
+        1,4,6;
+        1,4,7;
+        1,4,8;
+        2,4,6;
+        2,4,7;
+        2,4,8;
+        3,4,6;
+        3,4,7;
+        3,4,8;
+    ];
+    out{3,4} = [
+        1,5,6;
+        1,5,7;
+        1,5,8;
+        2,5,6;
+        2,5,7;
+        2,5,8;
+        3,5,6;
+        3,5,7;
+        3,5,8;
+    ];
+    out{3,5} = [
+        1,4,6;
+        1,5,6;
+        2,4,6;
+        2,5,6;
+        3,4,6;
+        3,5,6;
+    ];
+    out{3,6} = [
+        1,4,8;
+        1,5,8;
+        2,4,8;
+        2,5,8;
+        3,4,8;
+        3,5,8;
+    ];
+
+    for ig = 1:length(grids)
+        g = grid.Cartesian(grids{ig}{:});
+        for ib = 1:length(boundaries{ig})
+            testCase.verifyEqual(g.getBoundary(boundaries{ig}{ib}), out{ig,ib});
+        end
+    end
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/Curve.m
--- a/+grid/Curve.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,388 +0,0 @@
-classdef Curve
-    properties
-        g
-        gp
-        transformation
-    end
-
-    methods
-        %TODO:
-        % Concatenation of curves
-        % Subsections of curves
-        % Stretching of curve parameter - done for arc length.
-        % Curve to cell array of linesegments
-
-        % Returns a curve object.
-        %   g -- curve parametrization for parameter between 0 and 1
-        %  gp -- parametrization of curve derivative
-        function obj = Curve(g,gp,transformation)
-            default_arg('gp',[]);
-            default_arg('transformation',[]);
-            p_test = g(0);
-            assert(all(size(p_test) == [2,1]), 'A curve parametrization must return a 2x1 vector.');
-
-            if ~isempty(transformation)
-                transformation.base_g = g;
-                transformation.base_gp = gp;
-                [g,gp] = grid.Curve.transform_g(g,gp,transformation);
-            end
-
-            obj.g = g;
-            obj.gp = gp;
-            obj.transformation = transformation;
-
-        end
-
-        function n = normal(obj,t)
-            assert(~isempty(obj.gp),'Curve has no derivative!');
-            deriv = obj.gp(t);
-            normalization = sqrt(sum(deriv.^2,1));
-            n = [-deriv(2,:)./normalization; deriv(1,:)./normalization];
-        end
-
-
-        % Plots a curve g(t) for 0<t<1, using n points. Returns a handle h to the plotted curve.
-        %   h = plot_curve(g,n)
-        function h = plot(obj,n)
-            default_arg('n',100);
-
-            t = linspace(0,1,n);
-            p = obj.g(t);
-            h = line(p(1,:),p(2,:));
-        end
-
-        function h= plot_normals(obj,l,n,m)
-            default_arg('l',0.1);
-            default_arg('n',10);
-            default_arg('m',100);
-            t_n = linspace(0,1,n);
-
-            normals = obj.normal(t_n)*l;
-
-            n0 = obj.g(t_n);
-            n1 = n0 + normals;
-
-            h = line([n0(1,:); n1(1,:)],[n0(2,:); n1(2,:)]);
-            set(h,'Color',Color.red);
-            obj.plot(m);
-        end
-
-        function h= show(obj,name)
-            p = obj.g(1/2);
-            n = obj.normal(1/2);
-            p = p + n*0.1;
-
-            % Add arrow
-
-            h = text(p(1),p(2),name);
-            h.HorizontalAlignment = 'center';
-            h.VerticalAlignment = 'middle';
-
-            obj.plot();
-        end
-            % Shows curve with name and arrow for direction.
-
-        % Length of arc from parameter t0 to t1 (which may be vectors).
-        % Computed using derivative.
-        function L = arcLength(obj,t0,t1)
-            assert(~isempty(obj.gp),'Curve has no derivative!');
-            speed = @(t) sqrt(sum(obj.gp(t).^2,1));
-            L =  integral_vec(speed,t0,t1);
-        end
-
-        % Creates the arc length parameterization of a curve.
-        %    N -- number of points used to approximate the arclength function
-        function curve = arcLengthParametrization(obj,N)
-            default_arg('N',100);
-            assert(~isempty(obj.gp),'Curve has no derivative!');
-
-            % Construct arcLength function using splines
-            tvec = linspace(0,1,N);
-            arcVec = obj.arcLength(0,tvec);
-            tFunc = spline(arcVec,tvec); % t as a function of arcLength
-            L = obj.arcLength(0,1);
-            arcPar = @(s) tFunc(s*L);
-
-            % New function and derivative
-            g_new = @(t)obj.g(arcPar(t));
-            gp_new = @(t) normalize(obj.gp(arcPar(t)));
-            curve = grid.Curve(g_new,gp_new);
-
-        end
-
-        % how to make it work for methods without returns
-        function p = subsref(obj,S)
-            %Should i add error checking here?
-            %Maybe if you want performance you fetch obj.g and then use that
-            switch S(1).type
-                case '()'
-                    p = obj.g(S.subs{1});
-                % case '.'
-
-                    % p = obj.(S.subs);
-                otherwise
-                    p = builtin('subsref',obj,S);
-                    % error()
-            end
-        end
-
-
-        %% TRANSFORMATION OF A CURVE
-        function D = reverse(C)
-            % g = C.g;
-            % gp = C.gp;
-            % D = grid.Curve(@(t)g(1-t),@(t)-gp(1-t));
-            D = C.transform([],[],-1);
-        end
-
-        function D = transform(C,A,b,flip)
-            default_arg('A',[1 0; 0 1]);
-            default_arg('b',[0; 0]);
-            default_arg('flip',1);
-            if isempty(C.transformation)
-                g  = C.g;
-                gp = C.gp;
-                transformation.A = A;
-                transformation.b = b;
-                transformation.flip = flip;
-            else
-                g  = C.transformation.base_g;
-                gp = C.transformation.base_gp;
-                A_old = C.transformation.A;
-                b_old = C.transformation.b;
-                flip_old = C.transformation.flip;
-
-                transformation.A = A*A_old;
-                transformation.b = A*b_old + b;
-                transformation.flip = flip*flip_old;
-            end
-
-            D = grid.Curve(g,gp,transformation);
-
-        end
-
-        function D = translate(C,a)
-            g = C.g;
-            gp = C.gp;
-
-            % function v = g_fun(t)
-            %     x = g(t);
-            %     v(1,:) = x(1,:)+a(1);
-            %     v(2,:) = x(2,:)+a(2);
-            % end
-
-            % D = grid.Curve(@g_fun,gp);
-
-            D = C.transform([],a);
-        end
-
-        function D = mirror(C, a, b)
-            assert_size(a,[2,1]);
-            assert_size(b,[2,1]);
-
-            g = C.g;
-            gp = C.gp;
-
-            l = b-a;
-            lx = l(1);
-            ly = l(2);
-
-
-            % fprintf('Singular?\n')
-
-            A = [lx^2-ly^2 2*lx*ly; 2*lx*ly ly^2-lx^2]/(l'*l);
-
-            % function v = g_fun(t)
-            %     % v = a + A*(g(t)-a)
-            %     x = g(t);
-
-            %     ax1 = x(1,:)-a(1);
-            %     ax2 = x(2,:)-a(2);
-            %     v(1,:) = a(1)+A(1,:)*[ax1;ax2];
-            %     v(2,:) = a(2)+A(2,:)*[ax1;ax2];
-            % end
-
-            % function v = gp_fun(t)
-            %     v = A*gp(t);
-            % end
-
-            % D = grid.Curve(@g_fun,@gp_fun);
-
-            % g = A(g-a)+a = Ag - Aa + a;
-            b = - A*a + a;
-            D = C.transform(A,b);
-
-        end
-
-        function D = rotate(C,a,rad)
-            assert_size(a, [2,1]);
-            assert_size(rad, [1,1]);
-            g = C.g;
-            gp = C.gp;
-
-
-            A = [cos(rad) -sin(rad); sin(rad) cos(rad)];
-
-            % function v = g_fun(t)
-            %     % v = a + A*(g(t)-a)
-            %     x = g(t);
-
-            %     ax1 = x(1,:)-a(1);
-            %     ax2 = x(2,:)-a(2);
-            %     v(1,:) = a(1)+A(1,:)*[ax1;ax2];
-            %     v(2,:) = a(2)+A(2,:)*[ax1;ax2];
-            % end
-
-            % function v = gp_fun(t)
-            %     v = A*gp(t);
-            % end
-
-            % D = grid.Curve(@g_fun,@gp_fun);
-
-
-             % g = A(g-a)+a = Ag - Aa + a;
-            b = - A*a + a;
-            D = C.transform(A,b);
-        end
-    end
-
-    methods (Static)
-
-        % Computes the derivative of g: R -> R^2 using an operator D1
-        function gp_out = numericalDerivative(g,D1)
-            m = length(D1);
-            t = linspace(0,1,m);
-            gVec = g(t)';
-            gpVec = (D1*gVec)';
-
-            gp1_fun = spline(t,gpVec(1,:));
-            gp2_fun = spline(t,gpVec(2,:));
-            gp_out = @(t) [gp1_fun(t);gp2_fun(t)];
-        end
-
-        function obj = line(p1, p2)
-
-            function v = g_fun(t)
-                v(1,:) = p1(1) + t.*(p2(1)-p1(1));
-                v(2,:) = p1(2) + t.*(p2(2)-p1(2));
-            end
-            g = @g_fun;
-
-            obj = grid.Curve(g);
-        end
-
-        function obj = circle(c,r,phi)
-            default_arg('phi',[0; 2*pi])
-            default_arg('c',[0; 0])
-            default_arg('r',1)
-
-            function v = g_fun(t)
-                w = phi(1)+t*(phi(2)-phi(1));
-                v(1,:) = c(1) + r*cos(w);
-                v(2,:) = c(2) + r*sin(w);
-            end
-
-            function v = g_fun_deriv(t)
-                w = phi(1)+t*(phi(2)-phi(1));
-                v(1,:) = -(phi(2)-phi(1))*r*sin(w);
-                v(2,:) =  (phi(2)-phi(1))*r*cos(w);
-            end
-
-            obj = grid.Curve(@g_fun,@g_fun_deriv);
-        end
-
-        function obj = bezier(p0, p1, p2, p3)
-            function v = g_fun(t)
-                v(1,:) = (1-t).^3*p0(1) + 3*(1-t).^2.*t*p1(1) + 3*(1-t).*t.^2*p2(1) + t.^3*p3(1);
-                v(2,:) = (1-t).^3*p0(2) + 3*(1-t).^2.*t*p1(2) + 3*(1-t).*t.^2*p2(2) + t.^3*p3(2);
-            end
-
-            function v = g_fun_deriv(t)
-                v(1,:) = 3*(1-t).^2*(p1(1)-p0(1)) + 6*(1-t).*t*(p2(1)-p1(1)) + 3*t.^2*(p3(1)-p2(1));
-                v(2,:) = 3*(1-t).^2*(p1(2)-p0(2)) + 6*(1-t).*t*(p2(2)-p1(2)) + 3*t.^2*(p3(2)-p2(2));
-            end
-
-            obj = grid.Curve(@g_fun,@g_fun_deriv);
-        end
-
-
-        function [g_out,gp_out] = transform_g(g,gp,tr)
-            A = tr.A;
-            b = tr.b;
-            flip = tr.flip;
-
-            function v = g_fun_noflip(t)
-                % v = A*g + b
-                x = g(t);
-
-                v(1,:) = A(1,:)*x+b(1);
-                v(2,:) = A(2,:)*x+b(2);
-            end
-
-            function v = g_fun_flip(t)
-                % v = A*g + b
-                x = g(1-t);
-
-                v(1,:) = A(1,:)*x+b(1);
-                v(2,:) = A(2,:)*x+b(2);
-            end
-
-
-            switch flip
-                case 1
-                    g_out  = @g_fun_noflip;
-                    gp_out = @(t)A*gp(t);
-                case -1
-                    g_out  = @g_fun_flip;
-                    gp_out = @(t)-A*gp(1-t);
-            end
-        end
-
-    end
-end
-
-
-
-function g_norm = normalize(g0)
-    g1 = g0(1,:);
-    g2 = g0(2,:);
-    normalization = sqrt(sum(g0.^2,1));
-    g_norm = [g1./normalization; g2./normalization];
-end
-
-function I = integral_vec(f,a,b)
-% Wrapper around the built-in function integral that
-% handles multiple limits.
-
-    Na = length(a);
-    Nb = length(b);
-    assert(Na == 1 || Nb == 1 || Na==Nb,...
-        'a and b must have same length, unless one is a scalar.');
-
-    if(Na>Nb);
-        I = zeros(size(a));
-        for i = 1:Na
-            I(i) = integral(f,a(i),b);
-        end
-    elseif(Nb>Na)
-        I = zeros(size(b));
-        for i = 1:Nb
-            I(i) = integral(f,a,b(i));
-        end
-    else
-        I = zeros(size(b));
-        for i = 1:Nb
-            I(i) = integral(f,a(i),b(i));
-        end
-    end
-end
-
-% Returns a function handle to the spline.
-function f = spline(tval,fval,spline_order)
-    default_arg('spline_order',4);
-    [m,~] = size(tval);
-    assert(m==1,'Need row vectors.');
-
-    f_spline = spapi( optknt(tval,spline_order), tval, fval );
-    f = @(t) fnval(f_spline,t);
-end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/Curvilinear.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/Curvilinear.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,170 @@
+classdef Curvilinear < grid.Structured & grid.Mapped
+    properties
+        logic % Grid of Logical domain
+        coords % N x D matrix with coordinates of each point in the physical domain
+    end
+
+    methods
+        % Creates a curvilinear grid.
+        % Ex: grid.Curvilinear(mapping, xi, eta, ...)
+        %    mapping     -- either a function handle, a matrix or a cell array with physical coordinates.
+        %                   A function handle should be a vector valued function of the coordinate mapping.
+        %                   A matrix should be a grid function (N*D x 1 vector) or a N x D
+        %                   A cell array should be a 1 x D cell array with either N x 1 vectors
+        %                   or matrices of the same dimesions as the logical grid.
+        %   xi, eta, ... -- are the coordinate positions of the cartesian logical grid.
+        function obj = Curvilinear(mapping, varargin)
+            xi = varargin;
+            obj.logic = grid.Cartesian(xi{:});
+
+            % If mapping is a function evaluate it
+            if isa(mapping, 'function_handle')
+                mapping = grid.evalOn(obj.logic, mapping);
+            end
+
+            D = obj.logic.D();
+            N = obj.logic.N();
+
+            obj.coords = zeros(N,D);
+
+            if iscell(mapping)
+                obj.coords = cellMappingToCoords(mapping, N, D, obj.logic.m);
+            elseif isnumeric(mapping)
+                obj.coords = matrixMappingToCoords(mapping, N, D);
+            else
+                error('grid:Curvilinear:Curvilinear','mapping must be a function handle, a matrix or a cell array.');
+            end
+        end
+
+        function m = size(obj)
+            m = obj.logic.size();
+        end
+
+        % logicalGrid returns the domain grid of the mapping.
+        function g = logicalGrid(obj)
+            g = obj.logic;
+        end
+
+        % mapping returns the mapped coordinates as a grid.Function
+        function m = mapping(obj);
+            m = obj.coords;
+        end
+
+        % n returns the number of points in the grid
+        function o = N(obj)
+            o = obj.logic.N();
+        end
+
+        % d returns the spatial dimension of the grid
+        function o = D(obj)
+            o = obj.logic.D();
+        end
+
+        % points returns a n x d matrix containing the coordinates for all points.
+        function X = points(obj)
+            X = obj.coords;
+        end
+
+        % Restricts the grid function gf on obj to the subgrid g.
+        function gf = restrictFunc(obj, gf, g)
+            gf = obj.logic.restrictFunc(gf, g.logic);
+        end
+
+        % Projects the grid function gf on obj to the grid g.
+        function gf = projectFunc(obj, gf, g)
+            gf = obj.logic.projectFunc(gf,g.logic);
+        end
+
+        function h = scaling(obj)
+            if isempty(obj.logic.h)
+                error('grid:Curvilinear:NoScalingSet','No scaling set');
+            end
+            h = obj.logic.h;
+        end
+
+        % Return the names of all boundaries in this grid.
+        function bs = getBoundaryNames(obj)
+            bs = obj.logic.getBoundaryNames();
+        end
+
+        % Return coordinates for the given boundary
+        function X = getBoundary(obj, name)
+              % In what dimension is the boundary?
+            switch name
+                case {'l', 'r', 'w', 'e'}
+                    D = 1;
+                case {'s', 'n'}
+                    D = 2;
+                case {'d', 'u'}
+                    D = 3;
+                otherwise
+                    error('not implemented');
+            end
+
+            % At what index is the boundary?
+            switch name
+                case {'l', 'w', 's', 'd'}
+                    index = 1;
+                case {'r', 'e', 'n', 'u'}
+                    index = obj.logic.m(D);
+                otherwise
+                    error('not implemented');
+            end
+
+
+
+            I = cell(1, obj.D);
+            for i = 1:obj.D
+                if i == D
+                    I{i} = index;
+                else
+                    I{i} = ':';
+                end
+            end
+
+            % Calculate size of result:
+            m = obj.logic.m;
+            m(D) = [];
+            N = prod(m);
+
+            X = zeros(N, obj.D);
+
+            p = obj.points;
+            for i = 1:obj.D()
+                coordMat{i} = reshapeRowMaj(p(:,i), obj.logic.m);
+            end
+
+            for i = 1:length(coordMat)
+                Xtemp = coordMat{i}(I{:});
+                X(:,i) = reshapeRowMaj(Xtemp, [N,1]);
+            end
+        end
+    end
+end
+
+
+function coords = cellMappingToCoords(mapping, N, D, m)
+    if ~isequal(size(mapping),[1 D])
+        error('grid:Curvilinear:Curvilinear','The cell array must be a 1xD array.');
+    end
+
+    if isequal(size(mapping{1}),[N 1])
+        coords = cell2mat(mapping);
+    elseif isequal(size(mapping{1}), m)
+        for i = 1:length(mapping)
+            coords(:,i) = reshapeRowMaj(mapping{i}, [N 1]);
+        end
+    else
+        error('grid:Curvilinear:Curvilinear','The matrix must have size [N 1] or the same dimension as the grid. Actual: %s', toString(m));
+    end
+end
+
+function coords = matrixMappingToCoords(mapping, N, D)
+    if isequal(size(mapping), [N, D])
+        coords = mapping;
+    elseif isequal(size(mapping), [N*D, 1])
+        coords = reshapeRowMaj(mapping,[N D]);
+    else
+        error('grid:Curvilinear:Curvilinear','A matrix mapping must be of size [N D] or [N*D 1].');
+    end
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/CurvilinearTest.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/CurvilinearTest.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,131 @@
+function tests = CurvilinearTest()
+    tests = functiontests(localfunctions);
+end
+
+function testMappingInputGridFunction(testCase)
+    in = {
+        {{1:10}, @(x) exp(x)},
+        {{1:10,1:6}, @(x,y) [exp(x+y); exp(x-y)]},
+        {{1:10,1:5,1:7}, @(x,y,z)[exp(x+y+z); exp(x-y-z); 2+x+y-z]},
+    };
+
+    out = {
+        [10, 1];
+        [10*6, 2];
+        [10*5*7, 3];
+    };
+
+
+    % How to test this? Just make sure it runs without errors.
+
+    for i = 1:length(in)
+        g = grid.Curvilinear(in{i}{2},in{i}{1}{:});
+        testCase.verifyEqual(size(g.coords),out{i});
+    end
+end
+
+function testMappingInputComponentMatrix(testCase)
+    in = {
+        {{1:3}, [1 2 3]'},
+        {{1:2, 1:3}, [1 2 3 4 5 6; 7 8 9 10 11 12]'},
+    };
+
+    for i = 1:length(in)
+        g = grid.Curvilinear(in{i}{2},in{i}{1}{:});
+        testCase.verifyEqual(g.coords,in{i}{2});
+    end
+end
+
+function testMappingInputCellOfMatrix(testCase)
+
+    in = {
+        {{1:3}, {[1 2 3]'}},
+        {{1:2, 1:3}, {[1 2 3; 4 5 6], [7 8 9; 10 11 12]}},
+    };
+
+    out = {
+        [1 2 3]',
+        [1 2 3 4 5 6; 7 8 9 10 11 12]',
+    };
+
+    for i = 1:length(in)
+        g = grid.Curvilinear(in{i}{2},in{i}{1}{:});
+        testCase.verifyEqual(g.coords,out{i});
+    end
+end
+
+function testMappingInputCellOfVectors(testCase)
+    in = {
+        {{1:3}, {[1 2 3]'}},
+        {{1:2, 1:3}, {[1 2 3 4 5 6]', [7 8 9 10 11 12]'}},
+    };
+
+    out = {
+        [1 2 3]',
+        [1 2 3 4 5 6; 7 8 9 10 11 12]',
+    };
+end
+
+function testMappingInputError(testCase)
+    testCase.verifyFail();
+end
+
+function testScaling(testCase)
+    in = {{1:2, 1:3}, {[1 2 3 4 5 6]', [7 8 9 10 11 12]'}};
+    g = grid.Curvilinear(in{2},in{1}{:});
+
+    testCase.verifyError(@()g.scaling(),'grid:Curvilinear:NoScalingSet');
+
+    g.logicalGrid.h = [2 1];
+    testCase.verifyEqual(g.scaling(),[2 1]);
+end
+
+function testGetBoundaryNames(testCase)
+    in = {
+        {{1:10}, @(x) exp(x)},
+        {{1:10,1:6}, @(x,y) [exp(x+y); exp(x-y)]},
+        {{1:10,1:5,1:7}, @(x,y,z)[exp(x+y+z); exp(x-y-z); 2+x+y-z]},
+    };
+
+    out = {
+        {'l', 'r'},
+        {'w', 'e', 's', 'n'},
+        {'w', 'e', 's', 'n', 'd', 'u'},
+    };
+
+    for i = 1:length(in)
+        g = grid.Curvilinear(in{i}{2},in{i}{1}{:});
+        testCase.verifyEqual(g.getBoundaryNames(), out{i});
+    end
+end
+
+function testGetBoundary(testCase)
+    grids = {
+        {{1:10}, @(x) exp(x)},
+        {{1:10,1:6}, @(x,y) [exp(x+y); exp(x-y)]},
+        {{1:10,1:5,1:7}, @(x,y,z)[exp(x+y+z); exp(x-y-z); 2+x+y-z]},
+    };
+
+    boundaries = {
+        {'l', 'r'},
+        {'w', 'e', 's', 'n'},
+        {'w', 'e', 's', 'n', 'd', 'u'},
+    };
+
+
+    for ig = 1:length(grids)
+        g = grid.Curvilinear(grids{ig}{2},grids{ig}{1}{:});
+
+        logicalGrid = grid.Cartesian(grids{ig}{1}{:});
+
+        for ib = 1:length(boundaries{ig})
+
+            logicalBoundary = logicalGrid.getBoundary(boundaries{ig}{ib});
+
+            x = num2cell(logicalBoundary',2);
+            expectedBoundary = grids{ig}{2}(x{:})';
+            testCase.verifyEqual(g.getBoundary(boundaries{ig}{ib}), expectedBoundary);
+        end
+    end
+end
+
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/Grid.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/Grid.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,25 @@
+classdef Grid < handle
+    % General d dimensional grid with n points
+    methods (Abstract)
+        % n returns the number of points in the grid
+        o = N(obj)
+
+        % d returns the spatial dimension of the grid
+        o = D(obj)
+
+        % points returns a n x d matrix containing the coordinates for all points.
+        X = points(obj)
+
+        % Restricts the grid function gf on obj to the subgrid g.
+        gf = restrictFunc(obj, gf, g)
+
+        % Projects the grid function gf on obj to the grid g.
+        gf = projectFunc(obj, gf, g)
+
+        % Return the names of all boundaries in this grid.
+        bs = getBoundaryNames(obj)
+
+        % Return coordinates for the given boundary
+        b = getBoundary(obj, name)
+    end
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/Mapped.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/Mapped.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,10 @@
+classdef Mapped < grid.Grid
+    % General grid mapping
+    methods (Abstract)
+        % logicalGrid returns the domain grid of the mapping.
+        g = logicalGrid(obj);
+
+        % mapping returns the mapped coordinates as a N x D component matrix
+        m = mapping(obj);
+    end
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/Structured.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/Structured.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,7 @@
+classdef Structured < grid.Grid
+    methods (Abstract)
+        % Returns the size of the grid in each dimension m = [mx my mz ...]
+        m = size(obj); % Is this a good idea? Isn't immersed a structured grid?
+        h = scaling(obj);
+    end
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/Ti.m
--- a/+grid/Ti.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,201 +0,0 @@
-classdef Ti
-    properties
-        gs % {4}Curve
-        S  % FunctionHandle(u,v)
-    end
-
-    methods
-        % TODO function to label boundary names.
-        %  function to find largest and smallest delta h in the grid. Maybe shouldnt live here
-        function obj = Ti(C1,C2,C3,C4)
-            obj.gs = {C1,C2,C3,C4};
-
-            g1 = C1.g;
-            g2 = C2.g;
-            g3 = C3.g;
-            g4 = C4.g;
-
-            A = g1(0);
-            B = g2(0);
-            C = g3(0);
-            D = g4(0);
-
-            function o = S_fun(u,v)
-                x1 = g1(u);
-                x2 = g2(v);
-                x3 = g3(1-u);
-                x4 = g4(1-v);
-                o1 = (1-v).*x1(1,:) + u.*x2(1,:) + v.*x3(1,:) + (1-u).*x4(1,:) ...
-                    -((1-u)*(1-v).*A(1,:) + u*(1-v).*B(1,:) + u*v.*C(1,:) + (1-u)*v.*D(1,:));
-                o2 = (1-v).*x1(2,:) + u.*x2(2,:) + v.*x3(2,:) + (1-u).*x4(2,:) ...
-                    -((1-u)*(1-v).*A(2,:) + u*(1-v).*B(2,:) + u*v.*C(2,:) + (1-u)*v.*D(2,:));
-
-                o = [o1;o2];
-            end
-
-            obj.S = @S_fun;
-        end
-
-        function [X,Y] = map(obj,u,v)
-            default_arg('v',u);
-
-            if isscalar(u)
-                u = linspace(0,1,u);
-            end
-
-            if isscalar(v)
-                v = linspace(0,1,v);
-            end
-
-            S = obj.S;
-
-            nu = length(u);
-            nv = length(v);
-
-            X = zeros(nv,nu);
-            Y = zeros(nv,nu);
-
-            u = rowVector(u);
-            v = rowVector(v);
-
-            for i = 1:nv
-                p = S(u,v(i));
-                X(i,:) = p(1,:);
-                Y(i,:) = p(2,:);
-            end
-        end
-
-        function h = plot(obj,nu,nv)
-            S = obj.S;
-
-            default_arg('nv',nu)
-
-            u = linspace(0,1,nu);
-            v = linspace(0,1,nv);
-
-            m = 100;
-
-            X = zeros(nu+nv,m);
-            Y = zeros(nu+nv,m);
-
-
-            t = linspace(0,1,m);
-            for i = 1:nu
-                p = S(u(i),t);
-                X(i,:) = p(1,:);
-                Y(i,:) = p(2,:);
-            end
-
-            for i = 1:nv
-                p = S(t,v(i));
-                X(i+nu,:) = p(1,:);
-                Y(i+nu,:) = p(2,:);
-            end
-
-            h = line(X',Y');
-        end
-
-
-        function h = show(obj,nu,nv)
-            default_arg('nv',nu)
-            S = obj.S;
-
-            if(nu>2 || nv>2)
-                h_grid = obj.plot(nu,nv);
-                set(h_grid,'Color',[0 0.4470 0.7410]);
-            end
-
-            h_bord = obj.plot(2,2);
-            set(h_bord,'Color',[0.8500 0.3250 0.0980]);
-            set(h_bord,'LineWidth',2);
-        end
-
-
-        % TRANSFORMATIONS
-        function ti = translate(obj,a)
-            gs = obj.gs;
-
-            for i = 1:length(gs)
-                new_gs{i} = gs{i}.translate(a);
-            end
-
-            ti = grid.Ti(new_gs{:});
-        end
-
-        % Mirrors the Ti so that the resulting Ti is still left handed.
-        %  (Corrected by reversing curves and switching e and w)
-        function ti = mirror(obj, a, b)
-            gs = obj.gs;
-
-            new_gs = cell(1,4);
-
-            new_gs{1} = gs{1}.mirror(a,b).reverse();
-            new_gs{3} = gs{3}.mirror(a,b).reverse();
-            new_gs{2} = gs{4}.mirror(a,b).reverse();
-            new_gs{4} = gs{2}.mirror(a,b).reverse();
-
-            ti = grid.Ti(new_gs{:});
-        end
-
-        function ti = rotate(obj,a,rad)
-            gs = obj.gs;
-
-            for i = 1:length(gs)
-                new_gs{i} = gs{i}.rotate(a,rad);
-            end
-
-            ti = grid.Ti(new_gs{:});
-        end
-
-        function ti = rotate_edges(obj,n);
-            new_gs = cell(1,4);
-            for i = 0:3
-                new_i = mod(i - n,4);
-                new_gs{new_i+1} = obj.gs{i+1};
-            end
-            ti = grid.Ti(new_gs{:});
-        end
-    end
-
-    methods(Static)
-        function obj = points(p1, p2, p3, p4)
-            g1 = grid.Curve.line(p1,p2);
-            g2 = grid.Curve.line(p2,p3);
-            g3 = grid.Curve.line(p3,p4);
-            g4 = grid.Curve.line(p4,p1);
-
-            obj = grid.Ti(g1,g2,g3,g4);
-        end
-
-        function label(varargin)
-            if nargin == 2 && ischar(varargin{2})
-                label_impl(varargin{:});
-            else
-                for i = 1:length(varargin)
-                    label_impl(varargin{i},inputname(i));
-                end
-            end
-
-
-            function label_impl(ti,str)
-                S = ti.S;
-
-                pc = S(0.5,0.5);
-
-                margin = 0.1;
-                pw = S(  margin,      0.5);
-                pe = S(1-margin,      0.5);
-                ps = S(     0.5,   margin);
-                pn = S(     0.5, 1-margin);
-
-
-                ti.show(2,2);
-                grid.place_label(pc,str);
-                grid.place_label(pw,'w');
-                grid.place_label(pe,'e');
-                grid.place_label(ps,'s');
-                grid.place_label(pn,'n');
-            end
-        end
-    end
-end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/equal_step_size.m
--- a/+grid/equal_step_size.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-% Calculates M so that the stepsize m/M is as close to n/M as possible
-function M = equal_step_size(n,N,m)
-    M = round((m*(N-1)+n)/n);
-end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/equidistant.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/equidistant.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,29 @@
+% Creates a cartesian grid of dimension length(m).
+% over the doman xlim, ylim, ...
+% Examples:
+%   g = grid.equidistant([mx, my], xlim, ylim)
+%   g = grid.equidistant([10, 15], {0,1}, {0,2})
+function g = equidistant(m, varargin)
+    if length(m) ~= length(varargin)
+        error('grid:equidistant:NonMatchingParameters','The number of provided dimensions do not match.')
+    end
+
+    for i = 1:length(m)
+        if ~iscell(varargin{i}) || numel(varargin{i}) ~= 2
+           error('grid:equidistant:InvalidLimits','The limits should be cell arrays with 2 elements.');
+        end
+
+        if varargin{i}{1} > varargin{i}{2}
+            error('grid:equidistant:InvalidLimits','The elements of the limit must be increasing.');
+        end
+    end
+
+    X = {};
+    h = [];
+    for i = 1:length(m)
+        [X{i}, h(i)] = util.get_grid(varargin{i}{:},m(i));
+    end
+
+    g = grid.Cartesian(X{:});
+    g.h = h;
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/equidistantCurvilinear.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/equidistantCurvilinear.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,35 @@
+% Creates a curvilinear grid of dimension length(m).
+% over the logical domain xi_lim, eta_lim, ...
+% If all limits are ommited they are set to {0,1}.
+% Examples:
+%   g = grid.equidistantCurvilinear(mapping, [m_xi, m_eta])
+%   g = grid.equidistantCurvilinear(mapping, [m_xi, m_eta], xi_lim, eta_lim)
+%   g = grid.equidistantCurvilinear(mapping, [10, 15], {0,1}, {0,1})
+function g = equidistantCurvilinear(mapping, m, varargin)
+    if isempty(varargin)
+        varargin = repmat({{0,1}}, [1 length(m)]);
+    end
+
+    if length(m) ~= length(varargin)
+        error('grid:equidistant:NonMatchingParameters','The number of provided dimensions do not match.')
+    end
+
+    for i = 1:length(m)
+        if ~iscell(varargin{i}) || numel(varargin{i}) ~= 2
+           error('grid:equidistant:InvalidLimits','The limits should be cell arrays with 2 elements.');
+        end
+
+        if varargin{i}{1} > varargin{i}{2}
+            error('grid:equidistant:InvalidLimits','The elements of the limit must be increasing.');
+        end
+    end
+
+    X = {};
+    h = [];
+    for i = 1:length(m)
+        [X{i}, h(i)] = util.get_grid(varargin{i}{:},m(i));
+    end
+
+    g = grid.Curvilinear(mapping, X{:});
+    g.logic.h = h;
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/equidistantCurvilinearTest.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/equidistantCurvilinearTest.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,7 @@
+function tests = equdistantCurvilinearTest()
+    tests = functiontests(localfunctions);
+end
+
+function testNoTests(testCase)
+    testCase.verifyFail();
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/equidistantTest.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/equidistantTest.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,50 @@
+function tests = equidistantTest()
+    tests = functiontests(localfunctions);
+end
+
+
+function testErrorInvalidLimits(testCase)
+     in  = {
+        {10,{1}},
+        {10,[0,1]},
+        {[10,10],{0,1},{1}},
+        {[10,10],{1},{1,0}},
+        {10,{1,0}},
+        {[10, 5],{1,0}, {0,-1}},
+    };
+
+    for i = 1:length(in)
+        testCase.verifyError(@()grid.equidistant(in{i}{:}),'grid:equidistant:InvalidLimits',sprintf('in(%d) = %s',i,toString(in{i})));
+    end
+end
+
+function testErrorNonMatchingParam(testCase)
+    in  = {
+        {[],{1}},
+        {[],{1},{0,1}},
+        {[5,5],{0,1},{0,1},{0,1}},
+        {[5,5,4],{0,1},{0,1}},
+    };
+
+    for i = 1:length(in)
+        testCase.verifyError(@()grid.equidistant(in{i}{:}),'grid:equidistant:NonMatchingParameters',sprintf('in(%d) = %s',i,toString(in{i})));
+    end
+end
+
+
+function testCompiles(testCase)
+    in  = {
+        {5, {0,1}},
+        {[3 3],{0,1},{0,2}},
+    };
+
+    out = {
+        [[0; 0.25; 0.5; 0.75; 1]],
+        [[0; 0; 0; 0.5; 0.5; 0.5; 1; 1; 1;],[0; 1; 2; 0; 1; 2; 0; 1; 2;]],
+    };
+
+    for i = 1:length(in)
+        g = grid.equidistant(in{i}{:});
+        testCase.verifyEqual(g.points(),out{i});
+    end
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/evalOn.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/evalOn.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,45 @@
+% Takes a function and evaluates it on a grid to return a grid function in the
+% form of a (n*k)x1 vector, where n is the number of grid points and k is the
+% number of components of the function.
+%      g -- Grid to evaluate on.
+%   func -- Function to evaluate. May be a function handle or a constant. If
+%           it is a vector value it has to be provided as a column vector,
+function gf = evalOn(g, func)
+    if ~isa(func, 'function_handle')
+        % We should have a constant.
+        if size(func,2) ~= 1
+            error('grid:evalOn:VectorValuedWrongDim', 'A vector valued function must be given as a column vector')
+        end
+
+        gf = repmat(func,[g.N, 1]);
+        return
+    end
+    % func should now be a function_handle
+
+    if g.D ~= nargin(func)
+        g.D
+        nargin(func)
+        error('grid:evalOn:WrongNumberOfInputs', 'The number of inputs of the function must match the dimension of the domain.')
+    end
+
+
+    % Get coordinates and convert to cell array for easier use as a parameter
+    x = num2cell(g.points());
+
+    % Find the number of components
+    x0 = x(1,:);
+    f0 = func(x0{:});
+    k = length(f0);
+
+    if size(f0,2) ~= 1
+        error('grid:evalOn:VectorValuedWrongDim', 'A vector valued function must be given as a column vector')
+    end
+
+    gf = zeros(g.N*k, 1);
+    % keyboard
+    for i = 1:g.N
+        % (1 + (i-1)*k):(i*k)
+        % func(x{i,:})
+        gf((1 + (i-1)*k):(i*k)) = func(x{i,:});
+    end
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/evalOnScalar.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/evalOnScalar.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,41 @@
+% WHAT KIND OF A FUNCTION NAME IS THIS?!
+%  This functions send matrixa arguments to func unlike grid.evalOn()
+% Takes a funciton and evaluates it on a grid to return a grid function in the
+% form of a (n*k)x1 vector, where n is the number of grid points and k is the
+% number of components of the function.
+%      g -- Grid to evaluate on.
+%   func -- Function to evaluate. May be a function handle or a constant. If
+%           it is a vector value it has to be provided as a column vector,
+function gf = evalOn(g, func)
+    if ~isa(func, 'function_handle')
+        % We should have a constant.
+        if size(func,2) ~= 1
+            error('grid:evalOnScalar:VectorValuedWrongDim', 'A vector valued function must be given as a column vector')
+        end
+
+        gf = repmat(func,[g.N, 1]);
+        return
+    end
+    % func should now be a function_handle
+
+    % Get coordinates and convert to cell array for easier use as a parameter
+    x = g.points();
+    X = {};
+    for i = 1:size(x, 2)
+        X{i} = x(:,i);
+    end
+
+    % Find the number of components
+    x0 = num2cell(x(1,:));
+    f0 = func(x0{:});
+    k = length(f0);
+
+    if size(f0,2) ~= 1
+        error('grid:evalOnScalar:VectorValuedWrongDim', 'A vector valued function must be given as a column vector')
+    end
+
+    gf = func(X{:});
+    if  k > 1  % Reorder so that componets sits together.
+        gf = reshape(reshape(gf, [g.N, k])', [g.N*k, 1]);
+    end
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/evalOnScalarTest.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/evalOnScalarTest.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,118 @@
+function tests = evalOnScalarTest()
+    tests = functiontests(localfunctions);
+end
+
+function testInputConstant(testCase)
+    in  = {
+        0,
+        47,
+        1,
+        [1; 2],
+    };
+
+    out = {
+        [0; 0; 0],
+        [47; 47; 47],
+        [1; 1; 1],
+        [1; 2; 1; 2; 1; 2],
+    };
+
+    g = getTestGrid('1d');
+
+    for i = 1:length(in)
+        gf = grid.evalOnScalar(g,in{i});
+        testCase.verifyEqual(gf, out{i});
+    end
+end
+
+function testInputScalarFunction1d(testCase)
+    in  = {
+        @(x)1+x*0,
+        @(x)x,
+        @(x)x.*x,
+    };
+
+    out = {
+        [1; 1; 1],
+        [0; 1; 2],
+        [0; 1; 4],
+    };
+
+    g = getTestGrid('1d');
+
+    for i = 1:length(in)
+        gf = grid.evalOnScalar(g,in{i});
+        testCase.verifyEqual(gf, out{i});
+    end
+end
+
+function testInputScalarFunction2d(testCase)
+    in  = {
+        @(x,y)1+x*0,
+        @(x,y)x-y,
+        @(x,y)x./(1+y),
+    };
+
+    out = {
+        [1; 1; 1; 1; 1; 1; 1; 1; 1],
+        [0; -1; -2; 1; 0; -1; 2; 1; 0],
+        [0; 0; 0; 1; 1/2; 1/3; 2; 1; 2/3],
+    };
+
+    g = getTestGrid('2d');
+
+    for i = 1:length(in)
+        gf = grid.evalOnScalar(g, in{i});
+        testCase.verifyEqual(gf, out{i});
+    end
+end
+
+
+function testInputVectorFunction(testCase)
+    g = getTestGrid('1d');
+    in = @(x)[x; -2*x];
+    out = [0; 0; 1; -2; 2; -4];
+
+    gf = grid.evalOnScalar(g,in);
+    testCase.verifyEqual(gf, out);
+
+    g = getTestGrid('2d');
+    in = @(x,y)[x.^2; -2*y];
+    out = [
+        0;  0;
+        0; -2;
+        0; -4;
+        1;  0;
+        1; -2;
+        1; -4;
+        4;  0;
+        4; -2;
+        4; -4;
+    ];
+
+    gf = grid.evalOnScalar(g,in);
+    testCase.verifyEqual(gf, out);
+end
+
+
+function testInputErrorVectorValued(testCase)
+     in  = {
+        [1,2,3],
+        @(x,y)[x,-y];
+    };
+
+    g = getTestGrid('2d');
+
+    for i = 1:length(in)
+        testCase.verifyError(@()grid.evalOnScalar(g, in{i}),'grid:evalOnScalar:VectorValuedWrongDim',sprintf('in(%d) = %s',i,toString(in{i})));
+    end
+end
+
+function g = getTestGrid(d)
+    switch d
+        case '1d'
+            g = grid.equidistant(3,{0,2});
+        case '2d'
+            g = grid.equidistant([3,3],{0,2},{0,2});
+    end
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/evalOnTest.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/evalOnTest.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,133 @@
+function tests = evalOnTest()
+    tests = functiontests(localfunctions);
+end
+
+function testInputConstant(testCase)
+    in  = {
+        0,
+        47,
+        1,
+        [1; 2],
+    };
+
+    out = {
+        [0; 0; 0],
+        [47; 47; 47],
+        [1; 1; 1],
+        [1; 2; 1; 2; 1; 2],
+    };
+
+    g = getTestGrid('1d');
+
+    for i = 1:length(in)
+        gf = grid.evalOn(g,in{i});
+        testCase.verifyEqual(gf, out{i});
+    end
+end
+
+% evalOn should give and error if the number of inputs to func is not the same as
+% the number of dimensions of the grid.
+function testNumberOfInputs(testCase)
+    cases = {
+        {getTestGrid('1d'), @(x,y)x-y},
+        {getTestGrid('2d'), @(x)x    },
+    }
+
+    for i = 1:length(cases)
+        g = cases{i}{1};
+        f = cases{i}{2};
+        testCase.verifyError(@()grid.evalOn(g, f),'grid:evalOn:WrongNumberOfInputs',sprintf('in(%d) = %s',i,toString(f)));
+    end
+end
+
+function testInputScalarFunction1d(testCase)
+    in  = {
+        @(x)1+x*0,
+        @(x)x,
+        @(x)x.*x,
+    };
+
+    out = {
+        [1; 1; 1],
+        [0; 1; 2],
+        [0; 1; 4],
+    };
+
+    g = getTestGrid('1d');
+
+    for i = 1:length(in)
+        gf = grid.evalOn(g,in{i});
+        testCase.verifyEqual(gf, out{i});
+    end
+end
+
+function testInputScalarFunction2d(testCase)
+    in  = {
+        @(x,y)1+x*0,
+        @(x,y)x-y,
+        @(x,y)x./(1+y),
+    };
+
+    out = {
+        [1; 1; 1; 1; 1; 1; 1; 1; 1],
+        [0; -1; -2; 1; 0; -1; 2; 1; 0],
+        [0; 0; 0; 1; 1/2; 1/3; 2; 1; 2/3],
+    };
+
+    g = getTestGrid('2d');
+
+    for i = 1:length(in)
+        gf = grid.evalOn(g, in{i});
+        testCase.verifyEqual(gf, out{i});
+    end
+end
+
+
+function testInputVectorFunction(testCase)
+    g = getTestGrid('1d');
+    in = @(x)[x; -2*x];
+    out = [0; 0; 1; -2; 2; -4];
+
+    gf = grid.evalOn(g,in);
+    testCase.verifyEqual(gf, out);
+
+    g = getTestGrid('2d');
+    in = @(x,y)[x.^2; -2*y];
+    out = [
+        0;  0;
+        0; -2;
+        0; -4;
+        1;  0;
+        1; -2;
+        1; -4;
+        4;  0;
+        4; -2;
+        4; -4;
+    ];
+
+    gf = grid.evalOn(g,in);
+    testCase.verifyEqual(gf, out);
+end
+
+
+function testInputErrorVectorValued(testCase)
+     in  = {
+        [1,2,3],
+        @(x,y)[x,-y];
+    };
+
+    g = getTestGrid('2d');
+
+    for i = 1:length(in)
+        testCase.verifyError(@()grid.evalOn(g, in{i}),'grid:evalOn:VectorValuedWrongDim',sprintf('in(%d) = %s',i,toString(in{i})));
+    end
+end
+
+function g = getTestGrid(d)
+    switch d
+        case '1d'
+            g = grid.equidistant(3,{0,2});
+        case '2d'
+            g = grid.equidistant([3,3],{0,2},{0,2});
+    end
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/funcToComponents.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/funcToComponents.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,8 @@
+% funcToComponents converts a grid function to a N x k matrix, where
+% k is the number of vector components of the gridfunction and N is the
+% number of points in the grid.
+%
+% Takes a grid function and and a grid.
+function F = funcToComponents(g, gf);
+    F = reshapeRowMaj(gf, [g.N, length(gf)/g.N]);
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/funcToComponentsTest.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/funcToComponentsTest.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,23 @@
+function tests = funcToComponentsTest()
+    tests = functiontests(localfunctions);
+end
+
+
+function testScalarGf(testCase)
+    g = getTestGrid();
+    gf_in = [1; 2; 3];
+
+    testCase.verifyEqual(grid.funcToComponents(g, gf_in), gf_in);
+end
+
+function testVectorGf(testCase)
+    g = getTestGrid();
+    gf_in = [1; 2; 3; 4; 5; 6];
+    out = [1 2; 3 4; 5 6];
+
+    testCase.verifyEqual(grid.funcToComponents(g, gf_in), out);
+end
+
+function g = getTestGrid()
+    g = grid.equidistant(3,{0,2});
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/funcToMatrix.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/funcToMatrix.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,5 @@
+% Converts a gridfunction to a matrix
+% Takes a grid function and and a structured grid.
+function F = funcToMatrix(g, gf)
+    F = reshapeRowMaj(gf, g.size());
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/funcToPlotMatrix.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/funcToPlotMatrix.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,5 @@
+% Converts a gridfunction to a plot matrix
+% Takes a grid function and and a structured grid.
+function F = funcToPlotMatrix(g, gf)
+    F = reshapeToPlotMatrix(gf, g.size());
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/old/concat_curve.m
--- a/+grid/old/concat_curve.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-% Concatenate two curves g1 and g2 intop
-%   g = concat_curve(g1,g2)
-function g = concat_curve(g1,g2)
-    function v = g_fun(t)
-        if t < 1/2
-            v = g1(2*t);
-        else
-            v = g2(2*t-1);
-        end
-    end
-    g = @g_fun;
-end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/old/curve_discretise.m
--- a/+grid/old/curve_discretise.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-% Discretises the curve g with the smallest number of points such that all segments
-% are shorter than h. If do_plot is true the points of the discretisation and
-% the normals of the curve in those points are plotted.
-%
-%   [t,p,d] = curve_discretise(g,h,do_plot)
-%
-%   t is a vector of input values to g.
-%   p is a cector of points.
-%   d are the length of the segments.
-function [t,p,d] = curve_discretise(g,h,do_plot)
-    default_arg('do_plot',false)
-
-    n = 10;
-
-    [t,p,d] = curve_discretise_n(g,n);
-
-    % ni = 0;
-    while any(d>h)
-        [t,p,d] = curve_discretise_n(g,n);
-        n = ceil(n*d(1)/h);
-        % ni = ni+1;
-    end
-
-    % nj = 0;
-    while all(d<h)
-        [t,p,d] = curve_discretise_n(g,n);
-        n = n-1;
-        % nj = nj+1;
-    end
-    [t,p,d] = curve_discretise_n(g,n+1);
-
-    % fprintf('ni = %d, nj = %d\n',ni,nj);
-
-    if do_plot
-        fprintf('n:%d  max: %f min: %f\n', n, max(d),min(d));
-        p = grid.map_curve(g,t);
-        figure
-        show(g,t,h);
-    end
-
-end
-
-function [t,p,d] = curve_discretise_n(g,n)
-    t = linspace(0,1,n);
-    t = equalize_d(g,t);
-    d = D(g,t);
-    p = grid.map_curve(g,t);
-end
-
-function d = D(g,t)
-    p = grid.map_curve(g,t);
-
-    d = zeros(1,length(t)-1);
-    for i = 1:length(d)
-        d(i) = norm(p(:,i) - p(:,i+1));
-    end
-end
-
-function t = equalize_d(g,t)
-    d = D(g,t);
-    v = d-mean(d);
-    while any(abs(v)>0.01*mean(d))
-        dt = t(2:end)-t(1:end-1);
-        t(2:end) = t(2:end) - cumsum(dt.*v./d);
-
-        t = t/t(end);
-        d = D(g,t);
-        v = d-mean(d);
-    end
-end
-
-
-function show(g,t,hh)
-    p = grid.map_curve(g,t);
-
-
-
-    h = grid.plot_curve(g);
-    h.LineWidth = 2;
-    axis equal
-    hold on
-    h = plot(p(1,:),p(2,:),'.');
-    h.Color = [0.8500 0.3250 0.0980];
-    h.MarkerSize = 24;
-    hold off
-
-    n = grid.curve_normals(g,t);
-    hold on
-    for  i = 1:length(t)
-        p0 = p(:,i);
-        p1 = p0 + hh*n(:,i);
-        l = [p0, p1];
-        h = plot(l(1,:),l(2,:));
-        h.Color = [0.8500 0.3250 0.0980];
-    end
-
-end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/old/curve_interp.m
--- a/+grid/old/curve_interp.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-% Create a cubic spline from the points (x,y) using periodic conditions.
-%   g = curve_interp(x,y)
-function g = curve_interp(x,y)
-    default_arg('x',[0 2 2 1 1 0])
-    default_arg('y',[0 0 2 2 1 1])
-    % solve for xp and yp
-
-    % x(t) = at^4 + bt^2+ct+d
-
-    % a = xp1 -2x1 + 2x0 +  xp0
-    % b = 3x1 -xp1 - 3x0 + 2xp0
-    % c = xp0
-    % d = x0
-
-    assert(length(x) == length(y))
-    n = length(x);
-    A = spdiags(ones(n,1)*[2, 8, 2],-1:1,n,n);
-    A(n,1) = 2;
-    A(1,n) = 2;
-
-    bx = zeros(n,1);
-    for i = 2:n-1
-        bx(i) = -6*x(i-1)+6*x(i+1);
-    end
-    bx(1) = -6*x(n)+6*x(2);
-    bx(n) = -6*x(n-1)+6*x(1);
-
-    by = zeros(n,1);
-    for i = 2:n-1
-        by(i) = -6*y(i-1)+6*y(i+1);
-    end
-    by(1) = -6*y(n)+6*y(2);
-    by(n) = -6*y(n-1)+6*y(1);
-
-
-    xp = A\bx;
-    yp = A\by;
-
-    x(end+1) = x(1);
-    y(end+1) = y(1);
-
-    xp(end+1) = xp(1);
-    yp(end+1) = yp(1);
-
-    function v = g_fun(t)
-        t = mod(t,1);
-        i = mod(floor(t*n),n) + 1;
-        t = t * n -(i-1);
-        X = (2*x(i)-2*x(i+1)+xp(i)+xp(i+1))*t.^3 + (-3*x(i)+3*x(i+1)-2*xp(i)-xp(i+1))*t.^2 + (xp(i))*t + x(i);
-        Y = (2*y(i)-2*y(i+1)+yp(i)+yp(i+1))*t.^3 + (-3*y(i)+3*y(i+1)-2*yp(i)-yp(i+1))*t.^2 + (yp(i))*t + y(i);
-        v = [X;Y];
-    end
-
-    g = @g_fun;
-end
-
-
-
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/old/max_h.m
--- a/+grid/old/max_h.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-function [d_max, i1_max, j1_max, i2_max, j2_max] = max_h(X,Y)
-    ni = size(X,1);
-    nj = size(X,2);
-    d_max = 0;
-
-    i1_max = 0;
-    j1_max = 0;
-    i2_max = 0;
-    j2_max = 0;
-
-    D = {[0,-1],[1,0],[0,1],[-1,0]};
-
-    for i = 1:ni
-        for j = 1:nj
-            p1 = [X(i,j); Y(i,j)];
-            for k = 1:length(D)
-                i2 = i+D{k}(1);
-                j2 = j+D{k}(2);
-                if i2 >= 1 && i2 <= ni && j2 >= 1 && j2 <= nj
-                    p2 = [X(i2,j2); Y(i2,j2)];
-                    d = norm(p2-p1);
-                    if d > d_max;
-                        d_max = d;
-                        i1_max = i;
-                        j1_max = j;
-                        i2_max = i2;
-                        j2_max = j2;
-                    end
-                end
-            end
-        end
-    end
-end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/old/min_h.m
--- a/+grid/old/min_h.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-function [d_min, i1_min, j1_min, i2_min, j2_min] = min_h(X,Y)
-    ni = size(X,1);
-    nj = size(X,2);
-    d_min = norm([X(1,1);Y(1,1)] - [X(ni,nj);Y(ni,nj)]);
-
-    i1_min = 0;
-    j1_min = 0;
-    i2_min = 0;
-    j2_min = 0;
-
-    D = {[-1,-1],[0,-1],[1,-1],[1,0],[1,1],[0,1],[-1,1],[-1,0]};
-    % D = {[0,-1],[1,0],[0,1],[-1,0]};
-
-    for i = 1:ni
-        for j = 1:nj
-            p1 = [X(i,j); Y(i,j)];
-            for k = 1:length(D)
-                i2 = i+D{k}(1);
-                j2 = j+D{k}(2);
-                if i2 >= 1 && i2 <= ni && j2 >= 1 && j2 <= nj
-                    p2 = [X(i2,j2); Y(i2,j2)];
-                    d = norm(p2-p1);
-                    if d < d_min;
-                        d_min = d;
-                        i1_min = i;
-                        j1_min = j;
-                        i2_min = i2;
-                        j2_min = j2;
-                    end
-                end
-            end
-        end
-    end
-end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/old/plot_shape.m
--- a/+grid/old/plot_shape.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-% Plot a shape using n points. Returns cell array of plot handles.
-%   hs = plot_shape(s,n)
-function hs = plot_shape(s,n)
-    default_arg('n',100);
-
-    hs = {};
-    hold on
-    for i = 1:length(s)
-        hs{end+1} = grid.plot_curve(s{i},n);
-    end
-    hold off
-end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/old/shape.m
--- a/+grid/old/shape.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-% Creates a shape from a number of curves. A shape is a cell array of curves.
-function s = shape(varargin);
-    s = varargin;
-end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/old/shape_discretise.m
--- a/+grid/old/shape_discretise.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-% Discretises a shape such that points on the curves are no further than h appart.
-function p = shape_discretise(s,h)
-    p = [];
-    for i = 1:length(s)
-        [~,pt] = grid.curve_discretise(s{i},h);
-        p = [p, pt];
-    end
-end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/old/shape_linesegments.m
--- a/+grid/old/shape_linesegments.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-% Converts a shape into a cell array of linesegments shorter than h.
-function l = shape_linesegments(s,h)
-    l = {};
-
-    for i = 1:length(s)
-        t = grid.curve_discretise(s{i},h);
-        l = [l, grid.curve_linesegments(s{i},t)];
-    end
-end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/old/triang_interp.m
--- a/+grid/old/triang_interp.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-classdef triang_interp
-    properties
-        g1, g2 ,g3  % Curves encirling the tirangle in the positive direction.
-        A,B,C  % The corners of the triangle
-        Sa, Sb, Sc % Mappings from square with different sides collapsed
-    end
-
-    methods
-        function o = triang_interp(g1,g2,g3)
-            o.g1 = g1;
-            o.g2 = g2;
-            o.g3 = g3;
-            o.A = g1(0);
-            o.B = g2(0);
-            o.C = g3(0);
-            o.Sa = grid.triang_interp.square_to_triangle_interp(g2,g3,g1);
-            o.Sb = grid.triang_interp.square_to_triangle_interp(g3,g1,g2);
-            o.Sc = grid.triang_interp.square_to_triangle_interp(g1,g2,g3);
-        end
-
-
-        function show(o,N)
-            % Show the mapped meridians of the triangle.
-            % Might be used for the barycentric coordinates.
-            ma = @(t)o.Sa(1/2,1-t);
-            mb = @(t)o.Sb(1/2,1-t);
-            mc = @(t)o.Sc(1/2,1-t);
-
-            na = @(t)o.Sa(t,1/2);
-
-            ka = @(t)(o.g1(1-t)+o.g2(t))/2;
-
-            h = grid.plot_curve(ma);
-            h.Color = Color.blue;
-            h = grid.plot_curve(mb);
-            h.Color = Color.blue;
-            h = grid.plot_curve(mc);
-            h.Color = Color.blue;
-
-            h = grid.plot_curve(na);
-            h.Color = Color.red;
-
-            h = grid.plot_curve(ka);
-            h.Color = Color.red;
-
-            [a(1),a(2)] = ma(1/3);
-            [b(1),b(2)] = mb(1/3);
-            [c(1),c(2)] = mc(1/3);
-
-            d = ka(1-1/3);
-
-
-            grid.label_pt(a,b,c,d);
-
-
-            % t = linspace(0,1,N);
-            % for i = 1:N
-            %     sa = @(s)o.Sa(s,t(i));
-            %     sb = @(s)o.Sb(s,t(i));
-            %     sc = @(s)o.Sc(s,t(i));
-
-            %     h = grid.plot_curve(sa);
-            %     h.Color = Color.blue;
-            %     h = grid.plot_curve(sb);
-            %     h.Color = Color.blue;
-            %     h = grid.plot_curve(sc);
-            %     h.Color = Color.blue;
-            % end
-
-            h = grid.plot_curve(o.g1);
-            h.LineWidth = 2;
-            h.Color = Color.red;
-
-            h = grid.plot_curve(o.g2);
-            h.LineWidth = 2;
-            h.Color = Color.red;
-
-            h = grid.plot_curve(o.g3);
-            h.LineWidth = 2;
-            h.Color = Color.red;
-
-        end
-
-
-    end
-
-    methods(Static)
-        % Makes a mapping from the unit square to a triangle by collapsing
-        % one of the sides of the squares to a corner on the triangle
-        % The collapsed side is mapped to the corner oposite to g1.
-        % This is done such that for S(s,t), S(s,1) = g1(s)
-        function S = square_to_triangle_interp(g1,g2,g3)
-            corner = grid.line_segment(g3(0),g3(0));
-            S = grid.transfinite_interp(corner,g3,f(g1),f(g2))
-
-            % Function to flip a curve
-            function h = f(g)
-                h = @(t)g(1-t);
-            end
-        end
-    end
-
-end
-
-% % Return a mapping from u.v to x,y of the domain encircled by g1 g2 g3 in the the positive direction. created be using transfinite interpolation.
-% function S = triang_interp(g1,g2,g3)
-%     A = g1(0)
-%     B = g2(0)
-%     C = g3(0)
-
-%     function [x,y] = S_fun(u,v)
-%         w = sqrt((u-1)^2+v^2)/sqrt(2); % Parameter for g3
-%         v = v*(1-u-v)*g1(u) + u*(1-u-v)*g2(v) + u*v*g3(w) ...
-%             +(1-u)*(1-v)*A+u*(1-v)*B + (1-u)*v*C;
-%         x = v(1);
-%         y = v(2);
-%     end
-%     S = @S_fun;
-% end
-
-
-
-% function subsref(obj,S)
-%       if ~all(isnumeric(S.subs{:}))
-%         error('Only supports calling object with number')
-%       end
-%       if numel(S.subs{:}) > 1
-%         disp('You''ve called the object with more than one argument');
-%       else
-%         disp(['You called the object with argument = ',num2str(S.subs{:})]);
-%       end
-%     end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/old/triang_interp_pts.m
--- a/+grid/old/triang_interp_pts.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-% Creates a transfinite interpolation from connecting the four points wiht straight lines.
-function [S, g1, g2, g3] = triang_interp_pts(p1,p2,p3)
-    if size(p1) ~= [2 1]
-        error('p1 is strange!');
-    end
-
-    g1 = @(t)(p1 + t*(p2-p1));
-    g2 = @(t)(p2 + t*(p3-p2));
-    g3 = @(t)(p3 + t*(p1-p3));
-
-    S = grid.triang_interp(g1,g2,g3);
-end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/old/triang_map.m
--- a/+grid/old/triang_map.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-% Creates a grid [X,Y] from the mapping function S at points in vectors u,v
-function [X, Y] = traing_map(S,u,v)
-    error('not done')
-    if nargin == 2
-        v = u;
-    end
-
-    if isscalar(u)
-        u = linspace(0,1,u);
-    end
-
-    if isscalar(v)
-        v = linspace(0,1,v);
-    end
-
-    nu = length(u);
-    nv = length(v);
-
-    X = zeros(nu,nv);
-    Y = zeros(nu,nv);
-
-    for i = 1:nu
-        for j = 1:nv
-            [x,y] = S(u(i),v(j));
-            X(i,j) = x;
-            Y(i,j) = y;
-        end
-    end
-end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/old/triang_plot_interp.m
--- a/+grid/old/triang_plot_interp.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-% Plots a transfinite interpolation in x,y space using nu and nv curves along u and v axes.
-
-
-
-
-
-
-% Plots a interp of a triangle where one the interpolation is from a square
-% with one side collapsed to
-function h = triang_plot_interp_kindaworking(S,n)
-    u = linspace(0,1,n);
-    v = linspace(0,1,n);
-
-    m = 100;
-    m = 20;
-
-    Xl_curves = cell(n,1);
-    Xr_curves = cell(n,1);
-    Y_curves = cell(n,1);
-
-
-    function u = wierdness(v,d,N)
-        if N == 0
-            u = 0;
-        else
-            u = N*d./(1-v);
-        end
-    end
-
-
-    %Y curves
-    t = linspace(0,1,m);
-    for i = 1:n
-        x = []; y = [];
-        for j = 1:length(t)
-            [x(j),y(j)] = S(t(j),v(i));
-        end
-        Y_curves{i} = [x', y'];
-    end
-
-
-    % Right and left X curves
-    t = linspace(0,1,m);
-    d = u(2);
-    for i = 1:n
-        xl = []; yl = [];
-        xr = []; yr = [];
-        N = i-1;
-        t = linspace(0,1-N*d,m);
-        for j = 1:length(t)
-            w = wierdness(t(j),d,N);
-            [xr(j),yr(j)] = S(w,t(j));
-            [xl(j),yl(j)] = S(1-w,t(j));
-        end
-        Xl_curves{i} = [xl', yl'];
-        Xr_curves{i} = [xr', yr'];
-    end
-
-    for i = 1:n-1
-        line(Xl_curves{i}(:,1),Xl_curves{i}(:,2))
-        line(Xr_curves{i}(:,1),Xr_curves{i}(:,2))
-        line(Y_curves{i}(:,1),Y_curves{i}(:,2))
-    end
-end
-
-
-
-
-function h = triang_plot_interp_nonworking(S,n)
-
-    u = linspace(0,1,n);
-    v = linspace(0,1,n);
-
-    m = 100;
-
-    X_curves = cell(n-1,1);
-    Y_curves = cell(n-1,1);
-    K_curves = cell(n-1,1);
-
-
-    t = linspace(0,1,m);
-    for i = 1:n-1
-        x = []; y = [];
-        for j = find(t+u(i) <= 1)
-            [x(j),y(j)] = S(u(i),t(j));
-        end
-        X_curves{i} = [x', y'];
-    end
-
-    for i = 1:n-1
-        x = []; y = [];
-        for j = find(t+v(i) <= 1)
-            [x(j),y(j)] = S(t(j),v(i));
-        end
-        Y_curves{i} = [x', y'];
-    end
-
-    for i = 2:n
-        x = []; y = [];
-        for j = find(t<u(i))
-            [x(j),y(j)] = S(t(j), u(i)-t(j));
-        end
-        K_curves{i-1} = [x', y'];
-    end
-
-    for i = 1:n-1
-        line(X_curves{i}(:,1),X_curves{i}(:,2))
-        line(Y_curves{i}(:,1),Y_curves{i}(:,2))
-        line(K_curves{i}(:,1),K_curves{i}(:,2))
-    end
-
-    h = -1;
-    % h = plot(X_curves{:},Y_curves{:},K_curves{:});
-end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/old/triang_show.m
--- a/+grid/old/triang_show.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-% Show a grid as a matlab figure.
-function triang_show(S,n)
-
-    ih = ishold();
-
-    hold on
-    h_grid = grid.triang_plot_interp(S,n);
-    h_bord = grid.triang_plot_interp(S,2);
-
-    set(h_grid,'Color',[0 0.4470 0.7410]);
-    set(h_bord,'Color',[0.8500 0.3250 0.0980]);
-    set(h_bord,'LineWidth',2);
-
-    % axis auto
-    % axis equal
-    % axis square
-
-    if ih
-        hold on
-    else
-        hold off
-    end
-end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +grid/place_label.m
--- a/+grid/place_label.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-% 'left' | 'center' | 'right'
-% 'baseline' | 'top' | 'cap' | 'middle' | 'bottom'
-function place_label(pt,str,horzAl,vertAl)
-    default_arg('horzAl','center');
-    default_arg('vertAl', 'middle');
-
-    x = pt(1);
-    y = pt(2);
-    h = text(x,y,str);
-    h.HorizontalAlignment = horzAl;
-    h.VerticalAlignment = vertAl;
-end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +multiblock/BoundaryGroup.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+multiblock/BoundaryGroup.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,51 @@
+% BoundaryGroup defines a boundary grouping in a multiblock grid.
+classdef BoundaryGroup
+    properties
+        blockIDs
+        names
+    end
+
+    methods
+        function obj = BoundaryGroup(varargin)
+            % Input arguemnts are arbitrary number or 1x2 cell arrays
+            % representing each boundary in the group.
+            % The 1st element of the cell array is an integer defining which grid it belongs to.
+            % The 2nd element of the cell array is the name of the boundary within the block.
+            %
+            % Ex:
+            %   bg = multiblock.BoundaryGroup({1,'n'},{1,'s'},{2,'s'})
+
+
+            obj.blockIDs = [];
+            obj.names = {};
+            for i = 1:length(varargin)
+                if ~iscell(varargin{i}) || ~all(size(varargin{i}) == [1 2])
+                    error('multiblock:BoundaryGroup:BoundaryGroup:InvalidInput', 'Inputs must be 1x2 cell arrays');
+                end
+                obj.blockIDs(i) = varargin{i}{1};
+                obj.names{i} = varargin{i}{2};
+            end
+        end
+
+        function display(obj, name)
+
+            disp(' ')
+            disp([name, ' ='])
+            disp(' ')
+
+            if length(obj.names) == 1
+                fprintf('    {}\n\n')
+                return
+            end
+
+            fprintf('    {')
+
+            fprintf('%d:%s', obj.blockIDs(1), obj.names{1})
+            for i = 2:length(obj.names)
+                fprintf(', %d:%s', obj.blockIDs(i), obj.names{i});
+            end
+
+            fprintf('}\n\n')
+        end
+    end
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +multiblock/BoundaryGroupTest.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+multiblock/BoundaryGroupTest.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,30 @@
+function tests = BoundaryGroupTest()
+    tests = functiontests(localfunctions);
+end
+
+function testCreation(testCase)
+    in = {{3,'n'},{2,'hoho'},{1,'s'}};
+
+    blockIDs = [3 2 1];
+    names = {'n', 'hoho', 's'};
+
+    bg = multiblock.BoundaryGroup(in{:});
+    testCase.verifyEqual(bg.blockIDs, blockIDs);
+    testCase.verifyEqual(bg.names, names);
+end
+
+function testInputError(testCase)
+    in = {
+        {'n', 's'},
+        {{3,'n'},{2,2,'hoho'},{1,'s'}},
+    };
+
+    out = {
+        'multiblock:BoundaryGroup:BoundaryGroup:InvalidInput',
+        'multiblock:BoundaryGroup:BoundaryGroup:InvalidInput',
+    };
+
+    for i = 1:length(in)
+        testCase.verifyError(@()multiblock.BoundaryGroup(in{i}{:}), out{i});
+    end
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +multiblock/DiffOp.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+multiblock/DiffOp.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,190 @@
+classdef DiffOp < scheme.Scheme
+    properties
+        grid
+        order
+        diffOps
+        D
+        H
+
+        blockmatrixDiv
+    end
+
+    methods
+        function obj = DiffOp(doHand, grid, order, doParam)
+            %  doHand -- may either be a function handle or a cell array of
+            %            function handles for each grid. The function handle(s)
+            %            should be on the form do = doHand(grid, order, ...)
+            %            Additional parameters for each doHand may be provided in
+            %            the doParam input.
+            %    grid -- a multiblock grid
+            %   order -- integer specifying the order of accuracy
+            % doParam -- may either be a cell array or a cell array of cell arrays
+            %            for each block. If it is a cell array with length equal
+            %            to the number of blocks then each element is sent to the
+            %            corresponding function handle as extra parameters:
+            %            doHand(..., doParam{i}{:}) Otherwise doParam is sent as
+            %            extra parameters to all doHand: doHand(..., doParam{:})
+            default_arg('doParam', [])
+
+            [getHand, getParam] = parseInput(doHand, grid, doParam);
+
+            nBlocks = grid.nBlocks();
+
+            obj.order = order;
+
+            % Create the diffOps for each block
+            obj.diffOps = cell(1, nBlocks);
+            for i = 1:nBlocks
+                h = getHand(i);
+                p = getParam(i);
+                if ~iscell(p)
+                    p = {p};
+                end
+                obj.diffOps{i} = h(grid.grids{i}, order, p{:});
+            end
+
+
+            % Build the norm matrix
+            H = cell(nBlocks, nBlocks);
+            for i = 1:nBlocks
+                H{i,i} = obj.diffOps{i}.H;
+            end
+            obj.H = blockmatrix.toMatrix(H);
+
+
+            % Build the differentiation matrix
+            obj.blockmatrixDiv = {grid.Ns, grid.Ns};
+            D = blockmatrix.zero(obj.blockmatrixDiv);
+            for i = 1:nBlocks
+                D{i,i} = obj.diffOps{i}.D;
+            end
+
+            for i = 1:nBlocks
+                for j = 1:nBlocks
+                    intf = grid.connections{i,j};
+                    if isempty(intf)
+                        continue
+                    end
+
+
+                    [ii, ij] = obj.diffOps{i}.interface(intf{1}, obj.diffOps{j}, intf{2});
+                    D{i,i} = D{i,i} + ii;
+                    D{i,j} = D{i,j} + ij;
+
+                    [jj, ji] = obj.diffOps{j}.interface(intf{2}, obj.diffOps{i}, intf{1});
+                    D{j,j} = D{j,j} + jj;
+                    D{j,i} = D{j,i} + ji;
+                end
+            end
+            obj.D = blockmatrix.toMatrix(D);
+
+
+            function [getHand, getParam] = parseInput(doHand, grid, doParam)
+                if ~isa(grid, 'multiblock.Grid')
+                    error('multiblock:DiffOp:DiffOp:InvalidGrid', 'Requires a multiblock grid.');
+                end
+
+                if iscell(doHand) && length(doHand) == grid.nBlocks()
+                    getHand = @(i)doHand{i};
+                elseif isa(doHand, 'function_handle')
+                    getHand = @(i)doHand;
+                else
+                    error('multiblock:DiffOp:DiffOp:InvalidGridDoHand', 'doHand must be a function handle or a cell array of length grid.nBlocks');
+                end
+
+                if isempty(doParam)
+                    getParam = @(i){};
+                    return
+                end
+
+                if ~iscell(doParam)
+                    getParam = @(i)doParam;
+                    return
+                end
+
+                % doParam is a non-empty cell-array
+
+                if length(doParam) == grid.nBlocks() && all(cellfun(@iscell, doParam))
+                    % doParam is a cell-array of cell-arrays
+                    getParam = @(i)doParam{i};
+                    return
+                end
+
+                getParam = @(i)doParam;
+            end
+        end
+
+        function ops = splitOp(obj, op)
+            % Splits a matrix operator into a cell-matrix of matrix operators for
+            % each grid.
+            ops = sparse2cell(op, obj.NNN);
+        end
+
+        function op = getBoundaryOperator(obj, op, boundary)
+            if iscell(boundary)
+                localOpName = [op '_' boundary{2}];
+                blockId = boundary{1};
+                localOp = obj.diffOps{blockId}.(localOpName);
+
+                div = {obj.blockmatrixDiv{1}, size(localOp,2)};
+                blockOp = blockmatrix.zero(div);
+                blockOp{blockId,1} = localOp;
+                op = blockmatrix.toMatrix(blockOp);
+                return
+            else
+                % Boundary är en sträng med en boundary group i.
+            end
+        end
+
+        % Creates the closure and penalty matrix for a given boundary condition,
+        %    boundary -- the name of the boundary on the form {id,name} where
+        %                id is the number of a block and name is the name of a
+        %                boundary of that block example: {1,'s'} or {3,'w'}
+        function [closure, penalty] = boundary_condition(obj, boundary, type)
+            I = boundary{1};
+            name = boundary{2};
+
+            % Get the closure and penaly matrices
+            [blockClosure, blockPenalty] = obj.diffOps{I}.boundary_condition(name, type);
+
+            % Expand to matrix for full domain.
+            div = obj.blockmatrixDiv;
+            if ~iscell(blockClosure)
+                temp = blockmatrix.zero(div);
+                temp{I,I} = blockClosure;
+                closure = blockmatrix.toMatrix(temp);
+            else
+                for i = 1:length(blockClosure)
+                    temp = blockmatrix.zero(div);
+                    temp{I,I} = blockClosure{i};
+                    closure{i} = blockmatrix.toMatrix(temp);
+                end
+            end
+
+            div{2} = size(blockPenalty, 2); % Penalty is a column vector
+            if ~iscell(blockPenalty)
+                p = blockmatrix.zero(div);
+                p{I} = blockPenalty;
+                penalty = blockmatrix.toMatrix(p);
+            else
+                for i = 1:length(blockPenalty)
+                    p = blockmatrix.zero(div);
+                    p{I} = blockPenalty{i};
+                    penalty{i} = blockmatrix.toMatrix(p);
+                end
+            end
+        end
+
+        function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary)
+
+        end
+
+        % Size returns the number of degrees of freedom
+        function N = size(obj)
+            N = 0;
+            for i = 1:length(obj.diffOps)
+                N = N + obj.diffOps{i}.size();
+            end
+        end
+    end
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +multiblock/DiffOpTest.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+multiblock/DiffOpTest.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,59 @@
+function tests = DiffOpTest()
+    tests = functiontests(localfunctions);
+end
+
+function testCreation(testCase)
+    do = newMultiblockOp();
+end
+
+function testSplitOp(testCase)
+    testCase.verifyFail();
+end
+
+function testBoundary_condition(testCase)
+    testCase.verifyFail();
+end
+
+function testInterface(testCase)
+    testCase.verifyFail();
+end
+
+function testSize(testCase)
+    mbDo = newMultiblockOp();
+    testCase.verifyEqual(mbDo.size(), 15)
+end
+
+
+function do = mockDiffOp(size, bc, interface)
+    do.H = 1;
+    do.D = 1;
+
+    do.size = size;
+    do.boundary_condition = bc;
+    do.interface = interface;
+end
+
+
+function do = newMultiblockOp()
+    grids = {
+        grid.Cartesian([0 1 2], [3 4 5]);
+        grid.Cartesian([1 2 3], [10 20]);
+    };
+
+    conn = cell(2,2);
+    conn{1, 2} = {'s','n'};
+
+    mbGrid = multiblock.Grid(grids, conn);
+
+    function [c, p] = boundary_condition(~,~,~,~)
+        c = 1; p = 1;
+    end
+
+    function [c, p] = interface(~,~,~,~)
+        c = 1; p = 1;
+    end
+
+    doHand = @(grid,~)mockDiffOp(@(~)prod(grid.size()), @boundary_condition, @interface);
+
+    do = multiblock.DiffOp(doHand, mbGrid, 0);
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +multiblock/Grid.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+multiblock/Grid.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,120 @@
+classdef Grid < grid.Grid
+    properties
+        grids
+        connections
+        boundaryGroups
+
+        nPoints
+    end
+
+    % General multiblock grid
+    methods
+
+        % grids -- cell array of N grids
+        % connections -- NxN upper triangular cell matrix. connections{i,j}
+        %                specifies the connection between block i and j. If
+        %                it's empty there is no connection otherwise it's a 2
+        %                -cell-vector with strings naming the boundaries to be
+        %                connected. (inverted coupling?)
+        %% Should we have boundary groups at all? maybe it can be handled in a
+        %% cleaner way outside of the class.
+        function obj = Grid(grids, connections, boundaryGroups)
+            obj.grids = grids;
+            obj.connections = connections;
+
+            obj.nPoints = 0;
+            for i = 1:length(grids)
+                obj.nPoints = obj.nPoints + grids{i}.N();
+            end
+
+            % if iscell(boundaryGroups)
+        end
+
+        function n = size(obj)
+            n = length(obj.grids);
+        end
+
+        % N returns the number of points in the grid
+        function o = N(obj)
+            o = obj.nPoints;
+        end
+
+        % Ns returns the number of points in each sub grid as a vector
+        function o = Ns(obj)
+            ns = zeros(1,obj.nBlocks);
+            for i = 1:obj.nBlocks;
+                ns(i) = obj.grids{i}.N();
+            end
+            o = ns;
+        end
+
+        function n = nBlocks(obj)
+            n = length(obj.grids);
+        end
+
+        % d returns the spatial dimension of the grid
+        function o = D(obj)
+            o = obj.grids{1}.D();
+        end
+
+        % points returns a n x d matrix containing the coordinates for all points.
+        function X = points(obj)
+            X = [];
+            for i = 1:length(obj.grids)
+                X = [X; obj.grids{i}.points];
+            end
+        end
+
+        % Split a grid function on obj to a cell array of grid function on each block
+        function gfs = splitFunc(obj, gf)
+            nComponents = length(gf)/obj.nPoints;
+            nBlocks = length(obj.grids);
+
+            % Collect number of points in each block
+            N = zeros(1,nBlocks);
+            for i = 1:nBlocks
+                N(i) = obj.grids{i}.N();
+            end
+
+            gfs = mat2cell(gf, N, 1);
+        end
+
+        % Restricts the grid function gf on obj to the subgrid g.
+        function gf = restrictFunc(obj, gf, g)
+            gfs = obj.splitFunc(gf);
+
+            for i = 1:length(obj.grids)
+                gfs{i} = obj.grids{i}.restrictFunc(gfs{i}, g.grids{i});
+            end
+
+            gf = cell2mat(gfs);
+        end
+
+        % Projects the grid function gf on obj to the grid g.
+        function o = projectFunc(obj, gf, g)
+            error('not implemented')
+
+            p = g.points();
+            o = zeros(length(p),1);
+            for i = 1:length(p)
+                I = whatGrid(p(i));
+                o(i) = obj.grids{I}.projectFunc(gf, p(i));
+            end
+
+
+            function I = whatGrid(p)
+                % Find what grid a point lies on
+            end
+
+        end
+
+        function bs = getBoundaryNames(obj)
+            bs = [];
+        end
+
+        % Return coordinates for the given boundary
+        function b = getBoundary(obj, name)
+            b = [];
+        end
+    end
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +multiblock/GridTest.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+multiblock/GridTest.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,37 @@
+function tests = GridTest()
+    tests = functiontests(localfunctions);
+end
+
+function testCreation(testCase)
+    g = multiblock.Grid({},{});
+end
+
+function testMissing(testCase)
+    testCase.verifyFail();
+end
+
+function testGetBoundaryNames(testCase)
+    [grids, conn] = prepareAdjecentBlocks();
+
+    mbg = multiblock.Grid(grids, conn, multiblock.BoundaryGroup({1,'w'},{2,'w'}) );
+
+    testCase.verifyFail();
+end
+
+function testGetBoundary(testCase)
+    [grids, conn] = prepareAdjecentBlocks();
+
+    mbg = multiblock.Grid(grids, conn, multiblock.BoundaryGroup({1,'w'},{2,'w'}) );
+    testCase.verifyFail();
+end
+
+
+function [grids, conn] = prepareAdjecentBlocks()
+    grids = {
+        grid.Cartesian([0 1 2], [3 4 5]);
+        grid.Cartesian([1 2], [10 20]);
+    };
+
+    conn = cell(2,2);
+    conn{1, 2} = {'s','n'};
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +multiblock/gridVector1d.m
--- a/+multiblock/gridVector1d.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-function x = gridVector1d(schms)
-    n = length(schms);
-    x = cell(n,1);
-
-    for i = 1:n
-        x{i} = schms{i}.x;
-    end
-end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +multiblock/gridVector2d.m
--- a/+multiblock/gridVector2d.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-function [x,y] = gridVector2d(schms)
-    n = length(schms);
-    x = cell(n,1);
-    y = cell(n,1);
-
-    for i = 1:n
-        x{i} = schms{i}.x;
-        y{i} = schms{i}.y;
-    end
-end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +multiblock/solutionVector2cell.m
--- a/+multiblock/solutionVector2cell.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-function v_cell = solutionVector2cell(schms,v,components)
-    if nargin == 2
-        components = 1;
-    end
-
-    N = length(schms);
-    v_cell = cell(N,1);
-
-    i_start = 1;
-    for i =1:N
-        i_end = i_start + schms{i}.size()*components - 1;
-        v_cell{i} = v(i_start:i_end);
-        i_start = i_end+1;
-    end
-end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +multiblock/stitchSchemes.m
--- a/+multiblock/stitchSchemes.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+multiblock/stitchSchemes.m	Wed Jan 25 16:22:18 2017 +0100
@@ -11,24 +11,24 @@
 % Output parameters are cell arrays and cell matrices.
 %
 % Ex: [schms, D, H] = stitchSchemes(schmHand, order, schmParam, blocks, ms, conn, bound)
-function [schms, D, H] = stitchSchemes(schmHand, order, schmParam, blocks, ms, conn, bound)
+function [schms, D, H] = stitchSchemes(schmHand, order, schmParam, grids, conn, bound)
     default_arg('schmParam',[]);
 
-    n_blocks = numel(blocks);
+    n_blocks = numel(grids);
 
     % Creating Schemes
     for i = 1:n_blocks
         if isempty(schmParam);
-            schms{i} = schmHand(ms{i},blocks{i},order,[]);
+            schms{i} = schmHand(grids{i},order,[]);
         elseif ~iscell(schmParam)
             param = schmParam(i);
-            schms{i} = schmHand(ms{i},blocks{i},order,param);
+            schms{i} = schmHand(grids{i},order,param);
         else
             param = schmParam{i};
             if iscell(param)
-                schms{i} = schmHand(ms{i},blocks{i},order,param{:});
+                schms{i} = schmHand(grids{i},order,param{:});
             else
-                schms{i} = schmHand(ms{i},blocks{i},order,param);
+                schms{i} = schmHand(grids{i},order,param);
             end
         end
 
diff -r 0976e579a6f0 -r 026d8a3fdbfb +noname/animate.m
--- a/+noname/animate.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+noname/animate.m	Wed Jan 25 16:22:18 2017 +0100
@@ -5,10 +5,14 @@
 %      noname.animate(discr,1, [tstart tend],'my_mov', opt)
 
 function hand = animate(discretization, time_modifier, Tend, dirname, opt)
-    default_arg('time_modifier',1);
+    default_arg('time_modifier', 1);
     default_arg('Tend', Inf);
-    default_arg('dirname','');
-    default_arg('opt', []);
+    default_arg('dirname', '');
+
+    optDefault.plotType = 'animation';
+    optDefault.time = [];
+
+    default_struct('opt', optDefault);
 
 
     if time_modifier < 0
@@ -34,7 +38,7 @@
     fprintf('m        : %d\n',size(discretization));
 
 
-    ts = discretization.getTimestepper(opt);
+    ts = discretization.getTimestepper(opt.time);
 
     if numel(Tend) == 2
         Tstart = Tend(1);
@@ -50,7 +54,7 @@
         Tstart = start_solution.t;
     end
 
-    [update, figure_handle] = discretization.setupPlot('animation');
+    [update, figure_handle] = discretization.setupPlot(opt.plotType);
     if makemovies
         save_frame = anim.setup_fig_mov(figure_handle,dirname);
     end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +noname/calcSol.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+noname/calcSol.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,10 @@
+% Calculates the solution of a discr at a given time using aligned timesteps.
+% Returns the solution as a grid function as defined in +grid
+function gf = calculateSolution(discr, T, tsOpt)
+    k_max = discr.getTimestep(tsOpt);
+    [k,N] = alignedTimestep(k_max,T);
+    tsOpt.k = k;
+    ts = discr.getTimestepper(tsOpt);
+
+    gf = ts.stepN(N-ts.n);
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +noname/calculateSolution.m
--- a/+noname/calculateSolution.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+noname/calculateSolution.m	Wed Jan 25 16:22:18 2017 +0100
@@ -13,7 +13,7 @@
         fprintf('File ''%s'' already exist.',filename);
         do_append = yesnoQuestion('Do you want to append to it?');
         if ~do_append
-            fprintf('Exiting...\n');
+            fprintf('Exiting. No Solutions calculated.\n');
             return
         end
     end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +noname/convergence.m
--- a/+noname/convergence.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+noname/convergence.m	Wed Jan 25 16:22:18 2017 +0100
@@ -1,5 +1,5 @@
 % Reference is either a key or a function handle
-function [q, e, h, runtime] = convergence(filename, errorFunc, reference, method, order, m, T)
+function [q, e, h, runtime] = convergence(filename, errorFunc, reference, name, order, m, T)
     default_arg('errorFunc', @scheme.error1d);
 
     sf = SolutionFile(filename);
@@ -7,7 +7,7 @@
 
     % Generate convergence, error, and efficiency plots for each search key with more than one entry.
     for i = 1:length(m)
-        key.method = method;
+        key.name = name;
         key.order = order;
         key.m = m(i);
         key.T = T;
@@ -30,18 +30,11 @@
 
     % Get the reference solution vector
     if isa(reference,'function_handle');
-        x = v_repr.x;
+        x = v_repr.grid.points();
         v_ref = reference(x,T);
     else
         % Downsample the reference solution
-        x = v_repr.x;
-        x_ref = reference.x;
-
-        [~,I] = ismember(x,x_ref,'rows');
-        if any(I == 0)
-            error('Solution and reference solution seem to be on different grids.');
-        end
-        v_ref = reference.v(I);
+        v_ref = reference.grid.restrictFunc(reference.v, v_repr.grid);
     end
 
     e = errorFunc(discr,v, v_ref);
diff -r 0976e579a6f0 -r 026d8a3fdbfb +noname/plotSolutions.m
--- a/+noname/plotSolutions.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+noname/plotSolutions.m	Wed Jan 25 16:22:18 2017 +0100
@@ -10,7 +10,7 @@
         key = sf.keys{i};
         entry = sf.get(key);
 
-        method  = key.method;
+        name  = key.name;
         order   = key.order;
         m       = key.m;
         T       = key.T;
@@ -23,11 +23,11 @@
         update(repr);
 
         if save_figures
-            figname = sprintf('%s_%s_o%d_m%d_T%d',figename_prefix,method,order,m,i);
+            figname = sprintf('%s_%s_o%d_m%d_T%d',figename_prefix,name,order,m,i);
             fprintf('Saving figure to ''%s''\n',figname);
             saveeps(hand,figname);
         end
 
     end
 
-end
\ No newline at end of file
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +noname/testCfl.m
--- a/+noname/testCfl.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+noname/testCfl.m	Wed Jan 25 16:22:18 2017 +0100
@@ -27,29 +27,37 @@
         end
     end
 
+    if silentFlag
+        rsInterval = util.ReplaceableString('');
+    end
+
     % Use bisection to find sharp estimate
     while( (alpha0(2)-alpha0(1))/alpha0(1) > tol)
         alpha = mean(alpha0);
 
         if ~silentFlag
             fprintf('[%.3e,%.3e]: ', alpha0(1), alpha0(2));
+        else
+            rsInterval.update('[%.3e,%.3e]: ', alpha0(1), alpha0(2));
         end
 
         [ok, n_step, maxVal] = testAlpha(alpha);
 
         if ok
             alpha0(1) = alpha;
+            stability = 'STABLE';
         else
             alpha0(2) = alpha;
+            stability = 'UNSTABLE';
         end
 
         if ~silentFlag
-            fprintf('a = %.3e, n_step=%d  max = %.2e\n', alpha, n_step, maxVal);
+            fprintf('a = %.3e, n_step=%d %8s max = %.2e\n', alpha, n_step, stability, maxVal);
         end
     end
 
     if silentFlag
-        fprintf('Last calculated: a = %.3e, n_step=%d  max = %.2e\n', alpha, n_step, maxVal);
+        rsInterval = util.ReplaceableString('');
     end
 
     fprintf('T = %-3d dof = %-4d order = %d: clf = %.4e\n',T, discr.size(), discr.order, alpha0(1));
diff -r 0976e579a6f0 -r 026d8a3fdbfb +parametrization/Curve.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+parametrization/Curve.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,396 @@
+classdef Curve
+    properties
+        g
+        gp
+        transformation
+    end
+
+    methods
+        %TODO:
+        % Concatenation of curves
+        % Subsections of curves
+        % Stretching of curve parameter - done for arc length.
+        % Curve to cell array of linesegments
+
+        % Returns a curve object.
+        %   g -- curve parametrization for parameter between 0 and 1
+        %  gp -- parametrization of curve derivative
+        function obj = Curve(g,gp,transformation)
+            default_arg('gp',[]);
+            default_arg('transformation',[]);
+            p_test = g(0);
+            assert(all(size(p_test) == [2,1]), 'A curve parametrization must return a 2x1 vector.');
+
+            if ~isempty(transformation)
+                transformation.base_g = g;
+                transformation.base_gp = gp;
+                [g,gp] = parametrization.Curve.transform_g(g,gp,transformation);
+            end
+
+            obj.g = g;
+            obj.gp = gp;
+            obj.transformation = transformation;
+
+        end
+
+        function n = normal(obj,t)
+            assert(~isempty(obj.gp),'Curve has no derivative!');
+            deriv = obj.gp(t);
+            normalization = sqrt(sum(deriv.^2,1));
+            n = [-deriv(2,:)./normalization; deriv(1,:)./normalization];
+        end
+
+
+        % Plots a curve g(t) for 0<t<1, using n points. Returns a handle h to the plotted curve.
+        %   h = plot_curve(g,n)
+        function h = plot(obj,n)
+            default_arg('n',100);
+
+            t = linspace(0,1,n);
+            p = obj.g(t);
+            h = line(p(1,:),p(2,:));
+        end
+
+        function h= plot_normals(obj,l,n,m)
+            default_arg('l',0.1);
+            default_arg('n',10);
+            default_arg('m',100);
+            t_n = linspace(0,1,n);
+
+            normals = obj.normal(t_n)*l;
+
+            n0 = obj.g(t_n);
+            n1 = n0 + normals;
+
+            h = line([n0(1,:); n1(1,:)],[n0(2,:); n1(2,:)]);
+            set(h,'Color',Color.red);
+            obj.plot(m);
+        end
+
+        function h= show(obj,name)
+            default_arg('name', '')
+            p = obj.g(1/2);
+            n = obj.normal(1/2);
+            p = p + n*0.1;
+
+            % Add arrow
+
+
+            if ~isempty(name)
+                h = text(p(1),p(2),name);
+                h.HorizontalAlignment = 'center';
+                h.VerticalAlignment = 'middle';
+            end
+
+            h = obj.plot();
+        end
+            % Shows curve with name and arrow for direction.
+
+        % Length of arc from parameter t0 to t1 (which may be vectors).
+        % Computed using derivative.
+        function L = arcLength(obj,t0,t1)
+            assert(~isempty(obj.gp),'Curve has no derivative!');
+            speed = @(t) sqrt(sum(obj.gp(t).^2,1));
+            L =  integral_vec(speed,t0,t1);
+        end
+
+        % Creates the arc length parameterization of a curve.
+        %    N -- number of points used to approximate the arclength function
+        function curve = arcLengthParametrization(obj,N)
+            default_arg('N',100);
+            assert(~isempty(obj.gp),'Curve has no derivative!');
+
+            % Construct arcLength function using splines
+            tvec = linspace(0,1,N);
+            arcVec = obj.arcLength(0,tvec);
+            tFunc = spline(arcVec,tvec); % t as a function of arcLength
+            L = obj.arcLength(0,1);
+            arcPar = @(s) tFunc(s*L);
+
+            % New function and derivative
+            g_new = @(t)obj.g(arcPar(t));
+            gp_new = @(t) normalize(obj.gp(arcPar(t)));
+            curve = parametrization.Curve(g_new,gp_new);
+
+        end
+
+        % how to make it work for methods without returns
+        function p = subsref(obj,S)
+            %Should i add error checking here?
+            %Maybe if you want performance you fetch obj.g and then use that
+            switch S(1).type
+                case '()'
+                    p = obj.g(S.subs{1});
+                % case '.'
+
+                    % p = obj.(S.subs);
+                otherwise
+                    p = builtin('subsref',obj,S);
+                    % error()
+            end
+        end
+
+
+        %% TRANSFORMATION OF A CURVE
+        function D = reverse(C)
+            % g = C.g;
+            % gp = C.gp;
+            % D = parametrization.Curve(@(t)g(1-t),@(t)-gp(1-t));
+            D = C.transform([],[],-1);
+        end
+
+        function D = transform(C,A,b,flip)
+            default_arg('A',[1 0; 0 1]);
+            default_arg('b',[0; 0]);
+            default_arg('flip',1);
+            if isempty(C.transformation)
+                g  = C.g;
+                gp = C.gp;
+                transformation.A = A;
+                transformation.b = b;
+                transformation.flip = flip;
+            else
+                g  = C.transformation.base_g;
+                gp = C.transformation.base_gp;
+                A_old = C.transformation.A;
+                b_old = C.transformation.b;
+                flip_old = C.transformation.flip;
+
+                transformation.A = A*A_old;
+                transformation.b = A*b_old + b;
+                transformation.flip = flip*flip_old;
+            end
+
+            D = parametrization.Curve(g,gp,transformation);
+
+        end
+
+        function D = translate(C,a)
+            g = C.g;
+            gp = C.gp;
+
+            % function v = g_fun(t)
+            %     x = g(t);
+            %     v(1,:) = x(1,:)+a(1);
+            %     v(2,:) = x(2,:)+a(2);
+            % end
+
+            % D = parametrization.Curve(@g_fun,gp);
+
+            D = C.transform([],a);
+        end
+
+        function D = mirror(C, a, b)
+            assert_size(a,[2,1]);
+            assert_size(b,[2,1]);
+
+            g = C.g;
+            gp = C.gp;
+
+            l = b-a;
+            lx = l(1);
+            ly = l(2);
+
+
+            % fprintf('Singular?\n')
+
+            A = [lx^2-ly^2 2*lx*ly; 2*lx*ly ly^2-lx^2]/(l'*l);
+
+            % function v = g_fun(t)
+            %     % v = a + A*(g(t)-a)
+            %     x = g(t);
+
+            %     ax1 = x(1,:)-a(1);
+            %     ax2 = x(2,:)-a(2);
+            %     v(1,:) = a(1)+A(1,:)*[ax1;ax2];
+            %     v(2,:) = a(2)+A(2,:)*[ax1;ax2];
+            % end
+
+            % function v = gp_fun(t)
+            %     v = A*gp(t);
+            % end
+
+            % D = parametrization.Curve(@g_fun,@gp_fun);
+
+            % g = A(g-a)+a = Ag - Aa + a;
+            b = - A*a + a;
+            D = C.transform(A,b);
+
+        end
+
+        function D = rotate(C,a,rad)
+            assert_size(a, [2,1]);
+            assert_size(rad, [1,1]);
+            g = C.g;
+            gp = C.gp;
+
+
+            A = [cos(rad) -sin(rad); sin(rad) cos(rad)];
+
+            % function v = g_fun(t)
+            %     % v = a + A*(g(t)-a)
+            %     x = g(t);
+
+            %     ax1 = x(1,:)-a(1);
+            %     ax2 = x(2,:)-a(2);
+            %     v(1,:) = a(1)+A(1,:)*[ax1;ax2];
+            %     v(2,:) = a(2)+A(2,:)*[ax1;ax2];
+            % end
+
+            % function v = gp_fun(t)
+            %     v = A*gp(t);
+            % end
+
+            % D = parametrization.Curve(@g_fun,@gp_fun);
+
+
+             % g = A(g-a)+a = Ag - Aa + a;
+            b = - A*a + a;
+            D = C.transform(A,b);
+        end
+    end
+
+    methods (Static)
+
+        % Computes the derivative of g: R -> R^2 using an operator D1
+        function gp_out = numericalDerivative(g,D1)
+            m = length(D1);
+            t = linspace(0,1,m);
+            gVec = g(t)';
+            gpVec = (D1*gVec)';
+
+            gp1_fun = spline(t,gpVec(1,:));
+            gp2_fun = spline(t,gpVec(2,:));
+            gp_out = @(t) [gp1_fun(t);gp2_fun(t)];
+        end
+
+        function obj = line(p1, p2)
+
+            function v = g_fun(t)
+                v(1,:) = p1(1) + t.*(p2(1)-p1(1));
+                v(2,:) = p1(2) + t.*(p2(2)-p1(2));
+            end
+
+            function v = g_fun_deriv(t)
+                v(1,:) = t.*0 + (p2(1)-p1(1));
+                v(2,:) = t.*0 + (p2(2)-p1(2));
+            end
+
+            obj = parametrization.Curve(@g_fun, @g_fun_deriv);
+        end
+
+        function obj = circle(c,r,phi)
+            default_arg('phi',[0; 2*pi])
+            default_arg('c',[0; 0])
+            default_arg('r',1)
+
+            function v = g_fun(t)
+                w = phi(1)+t*(phi(2)-phi(1));
+                v(1,:) = c(1) + r*cos(w);
+                v(2,:) = c(2) + r*sin(w);
+            end
+
+            function v = g_fun_deriv(t)
+                w = phi(1)+t*(phi(2)-phi(1));
+                v(1,:) = -(phi(2)-phi(1))*r*sin(w);
+                v(2,:) =  (phi(2)-phi(1))*r*cos(w);
+            end
+
+            obj = parametrization.Curve(@g_fun,@g_fun_deriv);
+        end
+
+        function obj = bezier(p0, p1, p2, p3)
+            function v = g_fun(t)
+                v(1,:) = (1-t).^3*p0(1) + 3*(1-t).^2.*t*p1(1) + 3*(1-t).*t.^2*p2(1) + t.^3*p3(1);
+                v(2,:) = (1-t).^3*p0(2) + 3*(1-t).^2.*t*p1(2) + 3*(1-t).*t.^2*p2(2) + t.^3*p3(2);
+            end
+
+            function v = g_fun_deriv(t)
+                v(1,:) = 3*(1-t).^2*(p1(1)-p0(1)) + 6*(1-t).*t*(p2(1)-p1(1)) + 3*t.^2*(p3(1)-p2(1));
+                v(2,:) = 3*(1-t).^2*(p1(2)-p0(2)) + 6*(1-t).*t*(p2(2)-p1(2)) + 3*t.^2*(p3(2)-p2(2));
+            end
+
+            obj = parametrization.Curve(@g_fun,@g_fun_deriv);
+        end
+
+
+        function [g_out,gp_out] = transform_g(g,gp,tr)
+            A = tr.A;
+            b = tr.b;
+            flip = tr.flip;
+
+            function v = g_fun_noflip(t)
+                % v = A*g + b
+                x = g(t);
+
+                v(1,:) = A(1,:)*x+b(1);
+                v(2,:) = A(2,:)*x+b(2);
+            end
+
+            function v = g_fun_flip(t)
+                % v = A*g + b
+                x = g(1-t);
+
+                v(1,:) = A(1,:)*x+b(1);
+                v(2,:) = A(2,:)*x+b(2);
+            end
+
+
+            switch flip
+                case 1
+                    g_out  = @g_fun_noflip;
+                    gp_out = @(t)A*gp(t);
+                case -1
+                    g_out  = @g_fun_flip;
+                    gp_out = @(t)-A*gp(1-t);
+            end
+        end
+
+    end
+end
+
+
+
+function g_norm = normalize(g0)
+    g1 = g0(1,:);
+    g2 = g0(2,:);
+    normalization = sqrt(sum(g0.^2,1));
+    g_norm = [g1./normalization; g2./normalization];
+end
+
+function I = integral_vec(f,a,b)
+% Wrapper around the built-in function integral that
+% handles multiple limits.
+
+    Na = length(a);
+    Nb = length(b);
+    assert(Na == 1 || Nb == 1 || Na==Nb,...
+        'a and b must have same length, unless one is a scalar.');
+
+    if(Na>Nb);
+        I = zeros(size(a));
+        for i = 1:Na
+            I(i) = integral(f,a(i),b);
+        end
+    elseif(Nb>Na)
+        I = zeros(size(b));
+        for i = 1:Nb
+            I(i) = integral(f,a,b(i));
+        end
+    else
+        I = zeros(size(b));
+        for i = 1:Nb
+            I(i) = integral(f,a(i),b(i));
+        end
+    end
+end
+
+% Returns a function handle to the spline.
+function f = spline(tval,fval,spline_order)
+    default_arg('spline_order',4);
+    [m,~] = size(tval);
+    assert(m==1,'Need row vectors.');
+
+    f_spline = spapi( optknt(tval,spline_order), tval, fval );
+    f = @(t) fnval(f_spline,t);
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +parametrization/Ti.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+parametrization/Ti.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,233 @@
+classdef Ti
+    properties
+        gs % {4}Curve
+        S  % FunctionHandle(u,v)
+    end
+
+    methods
+        % TODO function to label boundary names.
+        %  function to find largest and smallest delta h in the grid. Maybe shouldnt live here
+        function obj = Ti(C1,C2,C3,C4)
+            obj.gs = {C1,C2,C3,C4};
+
+            g1 = C1.g;
+            g2 = C2.g;
+            g3 = C3.g;
+            g4 = C4.g;
+
+            A = g1(0);
+            B = g2(0);
+            C = g3(0);
+            D = g4(0);
+
+            function o = S_fun(u,v)
+                x1 = g1(u);
+                x2 = g2(v);
+                x3 = g3(1-u);
+                x4 = g4(1-v);
+                o1 = (1-v).*x1(1,:) + u.*x2(1,:) + v.*x3(1,:) + (1-u).*x4(1,:) ...
+                    -((1-u)*(1-v).*A(1,:) + u*(1-v).*B(1,:) + u*v.*C(1,:) + (1-u)*v.*D(1,:));
+                o2 = (1-v).*x1(2,:) + u.*x2(2,:) + v.*x3(2,:) + (1-u).*x4(2,:) ...
+                    -((1-u)*(1-v).*A(2,:) + u*(1-v).*B(2,:) + u*v.*C(2,:) + (1-u)*v.*D(2,:));
+
+                o = [o1;o2];
+            end
+
+            obj.S = @S_fun;
+        end
+
+        % Does this funciton make sense?
+        % Should it always be eval?
+        function [X,Y] = map(obj,u,v)
+            default_arg('v',u);
+
+            if isscalar(u)
+                u = linspace(0,1,u);
+            end
+
+            if isscalar(v)
+                v = linspace(0,1,v);
+            end
+
+            S = obj.S;
+
+            nu = length(u);
+            nv = length(v);
+
+            X = zeros(nv,nu);
+            Y = zeros(nv,nu);
+
+            u = rowVector(u);
+            v = rowVector(v);
+
+            for i = 1:nv
+                p = S(u,v(i));
+                X(i,:) = p(1,:);
+                Y(i,:) = p(2,:);
+            end
+        end
+
+        % Evaluate S for each pair of u and v,
+        % Return same shape as u
+        function [x, y] = eval(obj, u, v)
+            x = zeros(size(u));
+            y = zeros(size(u));
+
+            for i = 1:numel(u)
+                p = obj.S(u(i), v(i));
+                x(i) = p(1,:);
+                y(i) = p(2,:);
+            end
+        end
+
+        function h = plot(obj,nu,nv)
+            S = obj.S;
+
+            default_arg('nv',nu)
+
+            u = linspace(0,1,nu);
+            v = linspace(0,1,nv);
+
+            m = 100;
+
+            X = zeros(nu+nv,m);
+            Y = zeros(nu+nv,m);
+
+
+            t = linspace(0,1,m);
+            for i = 1:nu
+                p = S(u(i),t);
+                X(i,:) = p(1,:);
+                Y(i,:) = p(2,:);
+            end
+
+            for i = 1:nv
+                p = S(t,v(i));
+                X(i+nu,:) = p(1,:);
+                Y(i+nu,:) = p(2,:);
+            end
+
+            h = line(X',Y');
+        end
+
+
+        function h = show(obj,nu,nv)
+            default_arg('nv',nu)
+            S = obj.S;
+
+            if(nu>2 || nv>2)
+                h_grid = obj.plot(nu,nv);
+                set(h_grid,'Color',[0 0.4470 0.7410]);
+            end
+
+            h_bord = obj.plot(2,2);
+            set(h_bord,'Color',[0.8500 0.3250 0.0980]);
+            set(h_bord,'LineWidth',2);
+        end
+
+
+        % TRANSFORMATIONS
+        function ti = translate(obj,a)
+            gs = obj.gs;
+
+            for i = 1:length(gs)
+                new_gs{i} = gs{i}.translate(a);
+            end
+
+            ti = parametrization.Ti(new_gs{:});
+        end
+
+        % Mirrors the Ti so that the resulting Ti is still left handed.
+        %  (Corrected by reversing curves and switching e and w)
+        function ti = mirror(obj, a, b)
+            gs = obj.gs;
+
+            new_gs = cell(1,4);
+
+            new_gs{1} = gs{1}.mirror(a,b).reverse();
+            new_gs{3} = gs{3}.mirror(a,b).reverse();
+            new_gs{2} = gs{4}.mirror(a,b).reverse();
+            new_gs{4} = gs{2}.mirror(a,b).reverse();
+
+            ti = parametrization.Ti(new_gs{:});
+        end
+
+        function ti = rotate(obj,a,rad)
+            gs = obj.gs;
+
+            for i = 1:length(gs)
+                new_gs{i} = gs{i}.rotate(a,rad);
+            end
+
+            ti = parametrization.Ti(new_gs{:});
+        end
+
+        function ti = rotate_edges(obj,n);
+            new_gs = cell(1,4);
+            for i = 0:3
+                new_i = mod(i - n,4);
+                new_gs{new_i+1} = obj.gs{i+1};
+            end
+            ti = parametrization.Ti(new_gs{:});
+        end
+    end
+
+    methods(Static)
+        function obj = points(p1, p2, p3, p4)
+            g1 = parametrization.Curve.line(p1,p2);
+            g2 = parametrization.Curve.line(p2,p3);
+            g3 = parametrization.Curve.line(p3,p4);
+            g4 = parametrization.Curve.line(p4,p1);
+
+            obj = parametrization.Ti(g1,g2,g3,g4);
+        end
+
+        % Like the constructor but allows inputing line curves as 2-cell arrays:
+        %     example: parametrization.Ti.linesAndCurves(g1, g2, {a, b} g4)
+        function obj = linesAndCurves(C1, C2, C3, C4)
+            C = {C1, C2, C3, C4};
+            c = cell(1,4);
+
+            for i = 1:4
+                if ~iscell(C{i})
+                    c{i} = C{i};
+                else
+                    c{i} = parametrization.Curve.line(C{i}{:});
+                end
+            end
+
+            obj = parametrization.Ti(c{:});
+        end
+
+        function label(varargin)
+            if nargin == 2 && ischar(varargin{2})
+                label_impl(varargin{:});
+            else
+                for i = 1:length(varargin)
+                    label_impl(varargin{i},inputname(i));
+                end
+            end
+
+
+            function label_impl(ti,str)
+                S = ti.S;
+
+                pc = S(0.5,0.5);
+
+                margin = 0.1;
+                pw = S(  margin,      0.5);
+                pe = S(1-margin,      0.5);
+                ps = S(     0.5,   margin);
+                pn = S(     0.5, 1-margin);
+
+
+                ti.show(2,2);
+                parametrization.place_label(pc,str);
+                parametrization.place_label(pw,'w');
+                parametrization.place_label(pe,'e');
+                parametrization.place_label(ps,'s');
+                parametrization.place_label(pn,'n');
+            end
+        end
+    end
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +parametrization/equal_step_size.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+parametrization/equal_step_size.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,4 @@
+% Calculates M so that the stepsize m/M is as close to n/M as possible
+function M = equal_step_size(n,N,m)
+    M = round((m*(N-1)+n)/n);
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +parametrization/old/concat_curve.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+parametrization/old/concat_curve.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,12 @@
+% Concatenate two curves g1 and g2 intop
+%   g = concat_curve(g1,g2)
+function g = concat_curve(g1,g2)
+    function v = g_fun(t)
+        if t < 1/2
+            v = g1(2*t);
+        else
+            v = g2(2*t-1);
+        end
+    end
+    g = @g_fun;
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +parametrization/old/curve_discretise.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+parametrization/old/curve_discretise.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,97 @@
+% Discretises the curve g with the smallest number of points such that all segments
+% are shorter than h. If do_plot is true the points of the discretisation and
+% the normals of the curve in those points are plotted.
+%
+%   [t,p,d] = curve_discretise(g,h,do_plot)
+%
+%   t is a vector of input values to g.
+%   p is a cector of points.
+%   d are the length of the segments.
+function [t,p,d] = curve_discretise(g,h,do_plot)
+    default_arg('do_plot',false)
+
+    n = 10;
+
+    [t,p,d] = curve_discretise_n(g,n);
+
+    % ni = 0;
+    while any(d>h)
+        [t,p,d] = curve_discretise_n(g,n);
+        n = ceil(n*d(1)/h);
+        % ni = ni+1;
+    end
+
+    % nj = 0;
+    while all(d<h)
+        [t,p,d] = curve_discretise_n(g,n);
+        n = n-1;
+        % nj = nj+1;
+    end
+    [t,p,d] = curve_discretise_n(g,n+1);
+
+    % fprintf('ni = %d, nj = %d\n',ni,nj);
+
+    if do_plot
+        fprintf('n:%d  max: %f min: %f\n', n, max(d),min(d));
+        p = parametrization.map_curve(g,t);
+        figure
+        show(g,t,h);
+    end
+
+end
+
+function [t,p,d] = curve_discretise_n(g,n)
+    t = linspace(0,1,n);
+    t = equalize_d(g,t);
+    d = D(g,t);
+    p = parametrization.map_curve(g,t);
+end
+
+function d = D(g,t)
+    p = parametrization.map_curve(g,t);
+
+    d = zeros(1,length(t)-1);
+    for i = 1:length(d)
+        d(i) = norm(p(:,i) - p(:,i+1));
+    end
+end
+
+function t = equalize_d(g,t)
+    d = D(g,t);
+    v = d-mean(d);
+    while any(abs(v)>0.01*mean(d))
+        dt = t(2:end)-t(1:end-1);
+        t(2:end) = t(2:end) - cumsum(dt.*v./d);
+
+        t = t/t(end);
+        d = D(g,t);
+        v = d-mean(d);
+    end
+end
+
+
+function show(g,t,hh)
+    p = parametrization.map_curve(g,t);
+
+
+
+    h = parametrization.plot_curve(g);
+    h.LineWidth = 2;
+    axis equal
+    hold on
+    h = plot(p(1,:),p(2,:),'.');
+    h.Color = [0.8500 0.3250 0.0980];
+    h.MarkerSize = 24;
+    hold off
+
+    n = parametrization.curve_normals(g,t);
+    hold on
+    for  i = 1:length(t)
+        p0 = p(:,i);
+        p1 = p0 + hh*n(:,i);
+        l = [p0, p1];
+        h = plot(l(1,:),l(2,:));
+        h.Color = [0.8500 0.3250 0.0980];
+    end
+
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +parametrization/old/curve_interp.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+parametrization/old/curve_interp.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,58 @@
+% Create a cubic spline from the points (x,y) using periodic conditions.
+%   g = curve_interp(x,y)
+function g = curve_interp(x,y)
+    default_arg('x',[0 2 2 1 1 0])
+    default_arg('y',[0 0 2 2 1 1])
+    % solve for xp and yp
+
+    % x(t) = at^4 + bt^2+ct+d
+
+    % a = xp1 -2x1 + 2x0 +  xp0
+    % b = 3x1 -xp1 - 3x0 + 2xp0
+    % c = xp0
+    % d = x0
+
+    assert(length(x) == length(y))
+    n = length(x);
+    A = spdiags(ones(n,1)*[2, 8, 2],-1:1,n,n);
+    A(n,1) = 2;
+    A(1,n) = 2;
+
+    bx = zeros(n,1);
+    for i = 2:n-1
+        bx(i) = -6*x(i-1)+6*x(i+1);
+    end
+    bx(1) = -6*x(n)+6*x(2);
+    bx(n) = -6*x(n-1)+6*x(1);
+
+    by = zeros(n,1);
+    for i = 2:n-1
+        by(i) = -6*y(i-1)+6*y(i+1);
+    end
+    by(1) = -6*y(n)+6*y(2);
+    by(n) = -6*y(n-1)+6*y(1);
+
+
+    xp = A\bx;
+    yp = A\by;
+
+    x(end+1) = x(1);
+    y(end+1) = y(1);
+
+    xp(end+1) = xp(1);
+    yp(end+1) = yp(1);
+
+    function v = g_fun(t)
+        t = mod(t,1);
+        i = mod(floor(t*n),n) + 1;
+        t = t * n -(i-1);
+        X = (2*x(i)-2*x(i+1)+xp(i)+xp(i+1))*t.^3 + (-3*x(i)+3*x(i+1)-2*xp(i)-xp(i+1))*t.^2 + (xp(i))*t + x(i);
+        Y = (2*y(i)-2*y(i+1)+yp(i)+yp(i+1))*t.^3 + (-3*y(i)+3*y(i+1)-2*yp(i)-yp(i+1))*t.^2 + (yp(i))*t + y(i);
+        v = [X;Y];
+    end
+
+    g = @g_fun;
+end
+
+
+
diff -r 0976e579a6f0 -r 026d8a3fdbfb +parametrization/old/max_h.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+parametrization/old/max_h.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,33 @@
+function [d_max, i1_max, j1_max, i2_max, j2_max] = max_h(X,Y)
+    ni = size(X,1);
+    nj = size(X,2);
+    d_max = 0;
+
+    i1_max = 0;
+    j1_max = 0;
+    i2_max = 0;
+    j2_max = 0;
+
+    D = {[0,-1],[1,0],[0,1],[-1,0]};
+
+    for i = 1:ni
+        for j = 1:nj
+            p1 = [X(i,j); Y(i,j)];
+            for k = 1:length(D)
+                i2 = i+D{k}(1);
+                j2 = j+D{k}(2);
+                if i2 >= 1 && i2 <= ni && j2 >= 1 && j2 <= nj
+                    p2 = [X(i2,j2); Y(i2,j2)];
+                    d = norm(p2-p1);
+                    if d > d_max;
+                        d_max = d;
+                        i1_max = i;
+                        j1_max = j;
+                        i2_max = i2;
+                        j2_max = j2;
+                    end
+                end
+            end
+        end
+    end
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +parametrization/old/min_h.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+parametrization/old/min_h.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,34 @@
+function [d_min, i1_min, j1_min, i2_min, j2_min] = min_h(X,Y)
+    ni = size(X,1);
+    nj = size(X,2);
+    d_min = norm([X(1,1);Y(1,1)] - [X(ni,nj);Y(ni,nj)]);
+
+    i1_min = 0;
+    j1_min = 0;
+    i2_min = 0;
+    j2_min = 0;
+
+    D = {[-1,-1],[0,-1],[1,-1],[1,0],[1,1],[0,1],[-1,1],[-1,0]};
+    % D = {[0,-1],[1,0],[0,1],[-1,0]};
+
+    for i = 1:ni
+        for j = 1:nj
+            p1 = [X(i,j); Y(i,j)];
+            for k = 1:length(D)
+                i2 = i+D{k}(1);
+                j2 = j+D{k}(2);
+                if i2 >= 1 && i2 <= ni && j2 >= 1 && j2 <= nj
+                    p2 = [X(i2,j2); Y(i2,j2)];
+                    d = norm(p2-p1);
+                    if d < d_min;
+                        d_min = d;
+                        i1_min = i;
+                        j1_min = j;
+                        i2_min = i2;
+                        j2_min = j2;
+                    end
+                end
+            end
+        end
+    end
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +parametrization/old/plot_shape.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+parametrization/old/plot_shape.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,12 @@
+% Plot a shape using n points. Returns cell array of plot handles.
+%   hs = plot_shape(s,n)
+function hs = plot_shape(s,n)
+    default_arg('n',100);
+
+    hs = {};
+    hold on
+    for i = 1:length(s)
+        hs{end+1} = parametrization.plot_curve(s{i},n);
+    end
+    hold off
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +parametrization/old/shape.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+parametrization/old/shape.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,4 @@
+% Creates a shape from a number of curves. A shape is a cell array of curves.
+function s = shape(varargin);
+    s = varargin;
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +parametrization/old/shape_discretise.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+parametrization/old/shape_discretise.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,8 @@
+% Discretises a shape such that points on the curves are no further than h appart.
+function p = shape_discretise(s,h)
+    p = [];
+    for i = 1:length(s)
+        [~,pt] = parametrization.curve_discretise(s{i},h);
+        p = [p, pt];
+    end
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +parametrization/old/shape_linesegments.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+parametrization/old/shape_linesegments.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,9 @@
+% Converts a shape into a cell array of linesegments shorter than h.
+function l = shape_linesegments(s,h)
+    l = {};
+
+    for i = 1:length(s)
+        t = parametrization.curve_discretise(s{i},h);
+        l = [l, parametrization.curve_linesegments(s{i},t)];
+    end
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +parametrization/old/triang_interp.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+parametrization/old/triang_interp.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,132 @@
+classdef triang_interp
+    properties
+        g1, g2 ,g3  % Curves encirling the tirangle in the positive direction.
+        A,B,C  % The corners of the triangle
+        Sa, Sb, Sc % Mappings from square with different sides collapsed
+    end
+
+    methods
+        function o = triang_interp(g1,g2,g3)
+            o.g1 = g1;
+            o.g2 = g2;
+            o.g3 = g3;
+            o.A = g1(0);
+            o.B = g2(0);
+            o.C = g3(0);
+            o.Sa = parametrization.triang_interp.square_to_triangle_interp(g2,g3,g1);
+            o.Sb = parametrization.triang_interp.square_to_triangle_interp(g3,g1,g2);
+            o.Sc = parametrization.triang_interp.square_to_triangle_interp(g1,g2,g3);
+        end
+
+
+        function show(o,N)
+            % Show the mapped meridians of the triangle.
+            % Might be used for the barycentric coordinates.
+            ma = @(t)o.Sa(1/2,1-t);
+            mb = @(t)o.Sb(1/2,1-t);
+            mc = @(t)o.Sc(1/2,1-t);
+
+            na = @(t)o.Sa(t,1/2);
+
+            ka = @(t)(o.g1(1-t)+o.g2(t))/2;
+
+            h = parametrization.plot_curve(ma);
+            h.Color = Color.blue;
+            h = parametrization.plot_curve(mb);
+            h.Color = Color.blue;
+            h = parametrization.plot_curve(mc);
+            h.Color = Color.blue;
+
+            h = parametrization.plot_curve(na);
+            h.Color = Color.red;
+
+            h = parametrization.plot_curve(ka);
+            h.Color = Color.red;
+
+            [a(1),a(2)] = ma(1/3);
+            [b(1),b(2)] = mb(1/3);
+            [c(1),c(2)] = mc(1/3);
+
+            d = ka(1-1/3);
+
+
+            parametrization.label_pt(a,b,c,d);
+
+
+            % t = linspace(0,1,N);
+            % for i = 1:N
+            %     sa = @(s)o.Sa(s,t(i));
+            %     sb = @(s)o.Sb(s,t(i));
+            %     sc = @(s)o.Sc(s,t(i));
+
+            %     h = parametrization.plot_curve(sa);
+            %     h.Color = Color.blue;
+            %     h = parametrization.plot_curve(sb);
+            %     h.Color = Color.blue;
+            %     h = parametrization.plot_curve(sc);
+            %     h.Color = Color.blue;
+            % end
+
+            h = parametrization.plot_curve(o.g1);
+            h.LineWidth = 2;
+            h.Color = Color.red;
+
+            h = parametrization.plot_curve(o.g2);
+            h.LineWidth = 2;
+            h.Color = Color.red;
+
+            h = parametrization.plot_curve(o.g3);
+            h.LineWidth = 2;
+            h.Color = Color.red;
+
+        end
+
+
+    end
+
+    methods(Static)
+        % Makes a mapping from the unit square to a triangle by collapsing
+        % one of the sides of the squares to a corner on the triangle
+        % The collapsed side is mapped to the corner oposite to g1.
+        % This is done such that for S(s,t), S(s,1) = g1(s)
+        function S = square_to_triangle_interp(g1,g2,g3)
+            corner = parametrization.line_segment(g3(0),g3(0));
+            S = parametrization.transfinite_interp(corner,g3,f(g1),f(g2))
+
+            % Function to flip a curve
+            function h = f(g)
+                h = @(t)g(1-t);
+            end
+        end
+    end
+
+end
+
+% % Return a mapping from u.v to x,y of the domain encircled by g1 g2 g3 in the the positive direction. created be using transfinite interpolation.
+% function S = triang_interp(g1,g2,g3)
+%     A = g1(0)
+%     B = g2(0)
+%     C = g3(0)
+
+%     function [x,y] = S_fun(u,v)
+%         w = sqrt((u-1)^2+v^2)/sqrt(2); % Parameter for g3
+%         v = v*(1-u-v)*g1(u) + u*(1-u-v)*g2(v) + u*v*g3(w) ...
+%             +(1-u)*(1-v)*A+u*(1-v)*B + (1-u)*v*C;
+%         x = v(1);
+%         y = v(2);
+%     end
+%     S = @S_fun;
+% end
+
+
+
+% function subsref(obj,S)
+%       if ~all(isnumeric(S.subs{:}))
+%         error('Only supports calling object with number')
+%       end
+%       if numel(S.subs{:}) > 1
+%         disp('You''ve called the object with more than one argument');
+%       else
+%         disp(['You called the object with argument = ',num2str(S.subs{:})]);
+%       end
+%     end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +parametrization/old/triang_interp_pts.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+parametrization/old/triang_interp_pts.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,12 @@
+% Creates a transfinite interpolation from connecting the four points wiht straight lines.
+function [S, g1, g2, g3] = triang_interp_pts(p1,p2,p3)
+    if size(p1) ~= [2 1]
+        error('p1 is strange!');
+    end
+
+    g1 = @(t)(p1 + t*(p2-p1));
+    g2 = @(t)(p2 + t*(p3-p2));
+    g3 = @(t)(p3 + t*(p1-p3));
+
+    S = parametrization.triang_interp(g1,g2,g3);
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +parametrization/old/triang_map.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+parametrization/old/triang_map.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,29 @@
+% Creates a grid [X,Y] from the mapping function S at points in vectors u,v
+function [X, Y] = traing_map(S,u,v)
+    error('not done')
+    if nargin == 2
+        v = u;
+    end
+
+    if isscalar(u)
+        u = linspace(0,1,u);
+    end
+
+    if isscalar(v)
+        v = linspace(0,1,v);
+    end
+
+    nu = length(u);
+    nv = length(v);
+
+    X = zeros(nu,nv);
+    Y = zeros(nu,nv);
+
+    for i = 1:nu
+        for j = 1:nv
+            [x,y] = S(u(i),v(j));
+            X(i,j) = x;
+            Y(i,j) = y;
+        end
+    end
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +parametrization/old/triang_plot_interp.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+parametrization/old/triang_plot_interp.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,114 @@
+% Plots a transfinite interpolation in x,y space using nu and nv curves along u and v axes.
+
+
+
+
+
+
+% Plots a interp of a triangle where one the interpolation is from a square
+% with one side collapsed to
+function h = triang_plot_interp_kindaworking(S,n)
+    u = linspace(0,1,n);
+    v = linspace(0,1,n);
+
+    m = 100;
+    m = 20;
+
+    Xl_curves = cell(n,1);
+    Xr_curves = cell(n,1);
+    Y_curves = cell(n,1);
+
+
+    function u = wierdness(v,d,N)
+        if N == 0
+            u = 0;
+        else
+            u = N*d./(1-v);
+        end
+    end
+
+
+    %Y curves
+    t = linspace(0,1,m);
+    for i = 1:n
+        x = []; y = [];
+        for j = 1:length(t)
+            [x(j),y(j)] = S(t(j),v(i));
+        end
+        Y_curves{i} = [x', y'];
+    end
+
+
+    % Right and left X curves
+    t = linspace(0,1,m);
+    d = u(2);
+    for i = 1:n
+        xl = []; yl = [];
+        xr = []; yr = [];
+        N = i-1;
+        t = linspace(0,1-N*d,m);
+        for j = 1:length(t)
+            w = wierdness(t(j),d,N);
+            [xr(j),yr(j)] = S(w,t(j));
+            [xl(j),yl(j)] = S(1-w,t(j));
+        end
+        Xl_curves{i} = [xl', yl'];
+        Xr_curves{i} = [xr', yr'];
+    end
+
+    for i = 1:n-1
+        line(Xl_curves{i}(:,1),Xl_curves{i}(:,2))
+        line(Xr_curves{i}(:,1),Xr_curves{i}(:,2))
+        line(Y_curves{i}(:,1),Y_curves{i}(:,2))
+    end
+end
+
+
+
+
+function h = triang_plot_interp_nonworking(S,n)
+
+    u = linspace(0,1,n);
+    v = linspace(0,1,n);
+
+    m = 100;
+
+    X_curves = cell(n-1,1);
+    Y_curves = cell(n-1,1);
+    K_curves = cell(n-1,1);
+
+
+    t = linspace(0,1,m);
+    for i = 1:n-1
+        x = []; y = [];
+        for j = find(t+u(i) <= 1)
+            [x(j),y(j)] = S(u(i),t(j));
+        end
+        X_curves{i} = [x', y'];
+    end
+
+    for i = 1:n-1
+        x = []; y = [];
+        for j = find(t+v(i) <= 1)
+            [x(j),y(j)] = S(t(j),v(i));
+        end
+        Y_curves{i} = [x', y'];
+    end
+
+    for i = 2:n
+        x = []; y = [];
+        for j = find(t<u(i))
+            [x(j),y(j)] = S(t(j), u(i)-t(j));
+        end
+        K_curves{i-1} = [x', y'];
+    end
+
+    for i = 1:n-1
+        line(X_curves{i}(:,1),X_curves{i}(:,2))
+        line(Y_curves{i}(:,1),Y_curves{i}(:,2))
+        line(K_curves{i}(:,1),K_curves{i}(:,2))
+    end
+
+    h = -1;
+    % h = plot(X_curves{:},Y_curves{:},K_curves{:});
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +parametrization/old/triang_show.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+parametrization/old/triang_show.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,23 @@
+% Show a grid as a matlab figure.
+function triang_show(S,n)
+
+    ih = ishold();
+
+    hold on
+    h_grid = parametrization.triang_plot_interp(S,n);
+    h_bord = parametrization.triang_plot_interp(S,2);
+
+    set(h_grid,'Color',[0 0.4470 0.7410]);
+    set(h_bord,'Color',[0.8500 0.3250 0.0980]);
+    set(h_bord,'LineWidth',2);
+
+    % axis auto
+    % axis equal
+    % axis square
+
+    if ih
+        hold on
+    else
+        hold off
+    end
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +parametrization/place_label.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+parametrization/place_label.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,12 @@
+% 'left' | 'center' | 'right'
+% 'baseline' | 'top' | 'cap' | 'middle' | 'bottom'
+function place_label(pt,str,horzAl,vertAl)
+    default_arg('horzAl','center');
+    default_arg('vertAl', 'middle');
+
+    x = pt(1);
+    y = pt(2);
+    h = text(x,y,str);
+    h.HorizontalAlignment = horzAl;
+    h.VerticalAlignment = vertAl;
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/+implementations/d1_upwind_3.m
--- a/+sbp/+implementations/d1_upwind_3.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+sbp/+implementations/d1_upwind_3.m	Wed Jan 25 16:22:18 2017 +0100
@@ -1,12 +1,12 @@
 function [H, HI, Dp, Dm, e_1, e_m] = d1_upwind_3(m,h)
-    
+
     if(m<6)
         error('Operator requires at least 6 grid points');
     end
 
     Hv = ones(m,1);
     Hv(1:3) = [3/8; 7/6; 23/24];
-    Hv(m-2:m) = rot90(Hv(1:3),2);
+    Hv(m-2:m) = rot90(Hv(1:3), 2);
     Hv = Hv*h;
     H = spdiag(Hv,0);
     HI = spdiag(1./Hv,0);
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/+implementations/d1_upwind_4.m
--- a/+sbp/+implementations/d1_upwind_4.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+sbp/+implementations/d1_upwind_4.m	Wed Jan 25 16:22:18 2017 +0100
@@ -23,7 +23,7 @@
     ];
 
     Qp(1:4,1:4)=Q_U;
-    Qp(m-3:m,m-3:m)=rot90(Q_U,2)'; %%% This is different from standard SBP
+    Qp(m-3:m,m-3:m)=rot90(Q_U, 2)'; %%% This is different from standard SBP
 
     Qm=-Qp';
 
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/+implementations/d2_2.m
--- a/+sbp/+implementations/d2_2.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+sbp/+implementations/d2_2.m	Wed Jan 25 16:22:18 2017 +0100
@@ -1,5 +1,5 @@
 function [H, HI, D1, D2, e_1, e_m, M, Q, S_1, S_m] = d2_2(m,h)
-    
+
     BP = 1;
     if(m<2*BP)
         error(['Operator requires at least ' num2str(2*BP) ' grid points']);
@@ -11,33 +11,40 @@
     H=(speye(m,m));H(1,1)=0.5;H(m,m)=0.5;
     H=h*H;
     HI=inv(H);
-    
+
     diags   = -1:1;
     stencil = [-1/2 0 1/2];
     D1 = stripeMatrix(stencil, diags, m);
-    
-    D1(1,1)=-1;D1(1,2)=1;D1(m,m-1)=-1;D1(m,m)=1;
-    D1(m,m-1)=-1;D1(m,m)=1;
-    D1=D1/h;
+
+    D1(1,1) = -1;
+    D1(1,2) = 1;
 
-    Q=H*D1 + 1/2*(e_1*e_1') - 1/2*(e_m*e_m');
+    D1(m,m-1) = -1;
+    D1(m,m)   = 1;
+
+    D1 = D1/h;
+
+    Q = H*D1 + 1/2*(e_1*e_1') - 1/2*(e_m*e_m');
 
     diags   = -1:1;
     stencil = [1 -2 1];
     D2 = stripeMatrix(stencil, diags, m);
-    
-    D2(1,1)=1;D2(1,2)=-2;D2(1,3)=1;
-    D2(m,m-2)=1;D2(m,m-1)=-2;D2(m,m)=1;
-    D2=D2/h^2;
 
-    S_U=[-3/2, 2, -1/2]/h;
-    S_1=sparse(1,m);
-    S_1(1:3)=S_U;
-    S_m=sparse(1,m);
-    S_m(m-2:m)=fliplr(-S_U);
+    D2(1,1) = 1;
+    D2(1,2) = -2;
+    D2(1,3) = 1;
+    D2(m,m-2) = 1;
+    D2(m,m-1) = -2;
+    D2(m,m)   = 1;
+    D2 = D2/h^2;
 
+    S_U = [-3/2, 2, -1/2]/h;
+    S_1 = sparse(1,m);
+    S_1(1:3) = S_U;
+    S_m = sparse(1,m);
+    S_m(m-2:m) = fliplr(-S_U);
 
-    M=-H*D2-e_1*S_1+e_m*S_m;
+    M = -H*D2-e_1*S_1+e_m*S_m;
     S_1 = S_1';
     S_m = S_m';
 end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/+implementations/d2_4.m
--- a/+sbp/+implementations/d2_4.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+sbp/+implementations/d2_4.m	Wed Jan 25 16:22:18 2017 +0100
@@ -1,5 +1,5 @@
 function [H, HI, D1, D2, e_1, e_m, M, Q, S_1, S_m] = d2_4(m,h)
-    
+
     BP = 4;
     if(m<2*BP)
         error(['Operator requires at least ' num2str(2*BP) ' grid points']);
@@ -20,7 +20,12 @@
 
     Q=spdiags([e -8*e 0*e 8*e -e], -2:2, m, m)/12;
     %Q=(-1/12*diag(ones(m-2,1),2)+8/12*diag(ones(m-1,1),1)-8/12*diag(ones(m-1,1),-1)+1/12*diag(ones(m-2,1),-2));
-    Q_U = [0 0.59e2 / 0.96e2 -0.1e1 / 0.12e2 -0.1e1 / 0.32e2; -0.59e2 / 0.96e2 0 0.59e2 / 0.96e2 0; 0.1e1 / 0.12e2 -0.59e2 / 0.96e2 0 0.59e2 / 0.96e2; 0.1e1 / 0.32e2 0 -0.59e2 / 0.96e2 0;];
+    Q_U = [
+        0              0.59e2/0.96e2  -0.1e1/0.12e2  -0.1e1/0.32e2;
+        -0.59e2/0.96e2 0              0.59e2/0.96e2  0;
+        0.1e1/0.12e2   -0.59e2/0.96e2 0              0.59e2/0.96e2;
+        0.1e1/0.32e2   0              -0.59e2/0.96e2 0;
+    ];
     Q(1:4,1:4)=Q_U;
     Q(m-3:m,m-3:m)=rot90( -Q_U(1:4,1:4) ,2 );
 
@@ -30,13 +35,18 @@
 
     %M=-(-1/12*diag(ones(m-2,1),2)+16/12*diag(ones(m-1,1),1)+16/12*diag(ones(m-1,1),-1)-1/12*diag(ones(m-2,1),-2)-30/12*diag(ones(m,1),0));
 
-    M_U=[0.9e1 / 0.8e1 -0.59e2 / 0.48e2 0.1e1 / 0.12e2 0.1e1 / 0.48e2; -0.59e2 / 0.48e2 0.59e2 / 0.24e2 -0.59e2 / 0.48e2 0; 0.1e1 / 0.12e2 -0.59e2 / 0.48e2 0.55e2 / 0.24e2 -0.59e2 / 0.48e2; 0.1e1 / 0.48e2 0 -0.59e2 / 0.48e2 0.59e2 / 0.24e2;];
+    M_U=[
+        0.9e1/0.8e1 -0.59e2/0.48e2 0.1e1/0.12e2 0.1e1/0.48e2;
+        -0.59e2/0.48e2 0.59e2/0.24e2 -0.59e2/0.48e2 0;
+        0.1e1/0.12e2 -0.59e2/0.48e2 0.55e2/0.24e2 -0.59e2/0.48e2;
+        0.1e1/0.48e2 0 -0.59e2/0.48e2 0.59e2/0.24e2;
+    ];
     M(1:4,1:4)=M_U;
 
     M(m-3:m,m-3:m)=rot90(  M_U ,2 );
     M=M/h;
 
-    S_U=[-0.11e2 / 0.6e1 3 -0.3e1 / 0.2e1 0.1e1 / 0.3e1;]/h;
+    S_U=[-0.11e2/0.6e1 3 -0.3e1/0.2e1 0.1e1/0.3e1;]/h;
     S_1=sparse(sparse(1,m));
     S_1(1:4)=S_U;
     S_m=sparse(sparse(1,m));
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/+implementations/d2_variable_4.m
--- a/+sbp/+implementations/d2_variable_4.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+sbp/+implementations/d2_variable_4.m	Wed Jan 25 16:22:18 2017 +0100
@@ -1,6 +1,6 @@
 function [H, HI, D1, D2, e_l, e_r, d1_l, d1_r] = d2_variable_4(m,h)
 
-    BP = 4;
+    BP = 6;
     if(m<2*BP)
         error(['Operator requires at least ' num2str(2*BP) ' grid points']);
     end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/+implementations/d4_compatible_6.m
--- a/+sbp/+implementations/d4_compatible_6.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+sbp/+implementations/d4_compatible_6.m	Wed Jan 25 16:22:18 2017 +0100
@@ -25,7 +25,7 @@
 
     % Vi b?rjar med normen. Notera att alla SBP operatorer delar samma norm,
     % vilket ?r n?dv?ndigt f?r stabilitet
-    
+
     BP = 8;
     if(m<2*BP)
         error(['Operator requires at least ' num2str(2*BP) ' grid points']);
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/+implementations/d4_compatible_halfvariable_2.m
--- a/+sbp/+implementations/d4_compatible_halfvariable_2.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,0 @@
-% Returns D2 as a function handle
-function [H, HI, D1, D2, D3, D4, e_1, e_m, M4, Q, S2_1,...
-    S2_m, S3_1, S3_m, S_1, S_m] = d4_compatible_halfvariable_2(m,h)
-    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-    %%% 4:de ordn. SBP Finita differens         %%%
-    %%% operatorer framtagna av Ken Mattsson    %%%
-    %%%                                         %%%
-    %%% 6 randpunkter, diagonal norm            %%%
-    %%%                                         %%%
-    %%% Datum: 2013-11-11                       %%%
-    %%%                                         %%%
-    %%%                                         %%%
-    %%% H           (Normen)                    %%%
-    %%% D1          (approx f?rsta derivatan)   %%%
-    %%% D2          (approx andra derivatan)    %%%
-    %%% D3          (approx tredje derivatan)   %%%
-    %%% D2          (approx fj?rde derivatan)   %%%
-    %%%                                         %%%
-    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-    % M?ste ange antal punkter (m) och stegl?ngd (h)
-    % Notera att dessa opetratorer ?r framtagna f?r att anv?ndas n?r
-    % vi har 3de och 4de derivator i v?r PDE
-    % I annat fall anv?nd de "traditionella" som har noggrannare
-    % randsplutningar f?r D1 och D2
-
-    % Vi b?rjar med normen. Notera att alla SBP operatorer delar samma norm,
-    % vilket ?r n?dv?ndigt f?r stabilitet
-    
-    BP = 4;
-    if(m<2*BP)
-        error(['Operator requires at least ' num2str(2*BP) ' grid points']);
-    end
-
-    H=speye(m,m);H(1,1)=1/2;H(m,m)=1/2;
-
-
-    H=H*h;
-    HI=inv(H);
-
-
-    % First derivative SBP operator, 1st order accurate at first 6 boundary points
-
-    q1=1/2;
-%     Q=q1*(diag(ones(m-1,1),1)-diag(ones(m-1,1),-1));
-    stencil = [-q1,0,q1];
-    d = (length(stencil)-1)/2;
-    diags = -d:d;
-    Q = stripeMatrix(stencil, diags, m);
-
-    %Q=(-1/12*diag(ones(m-2,1),2)+8/12*diag(ones(m-1,1),1)-8/12*diag(ones(m-1,1),-1)+1/12*diag(ones(m-2,1),-2));
-
-
-    e_1=sparse(m,1);e_1(1)=1;
-    e_m=sparse(m,1);e_m(m)=1;
-
-
-    D1=HI*(Q-1/2*(e_1*e_1')+1/2*(e_m*e_m')) ;
-
-    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
-
-    % Second derivative, 1st order accurate at first boundary points
-
-    % below for constant coefficients
-    % m1=-1;m0=2;
-    % M=m1*(diag(ones(m-1,1),1)+diag(ones(m-1,1),-1))+m0*diag(ones(m,1),0);M(1,1)=1;M(m,m)=1;
-    % M=M/h;
-    %D2=HI*(-M-e_1*S_1+e_m*S_m);
-
-    % Below for variable coefficients
-    % Require a vector c with the koeffients
-
-    S_U=[-3/2 2 -1/2]/h;
-    S_1=sparse(1,m);
-    S_1(1:3)=S_U;
-    S_m=sparse(1,m);
-    S_m(m-2:m)=fliplr(-S_U);
-
-    S_1 = S_1';
-    S_m = S_m';
-
-    M=sparse(m,m);
-    e_1 = sparse(e_1);
-    e_m = sparse(e_m);
-    S_1 = sparse(S_1);
-    S_m = sparse(S_m);
-
-    scheme_width = 3;
-    scheme_radius = (scheme_width-1)/2;
-    r = (1+scheme_radius):(m-scheme_radius);
-
-    function D2 = D2_fun(c)
-
-        Mm1 = -c(r-1)/2 - c(r)/2;
-        M0  =  c(r-1)/2 + c(r)   + c(r+1)/2;
-        Mp1 =            -c(r)/2 - c(r+1)/2;
-
-        M(r,:) = spdiags([Mm1 M0 Mp1],0:2*scheme_radius,length(r),m);
-
-
-        M(1:2,1:2)=[c(1)/2 + c(2)/2 -c(1)/2 - c(2)/2; -c(1)/2 - c(2)/2 c(1)/2 + c(2) + c(3)/2;];
-        M(m-1:m,m-1:m)=[c(m-2)/2 + c(m-1) + c(m)/2 -c(m-1)/2 - c(m)/2; -c(m-1)/2 - c(m)/2 c(m-1)/2 + c(m)/2;];
-        M=M/h;
-
-        D2=HI*(-M-c(1)*e_1*S_1'+c(m)*e_m*S_m');
-    end
-    D2 = @D2_fun;
-
-
-
-
-
-    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
-
-    % Third derivative, 1st order accurate at first 6 boundary points
-
-    q2=1/2;q1=-1;
-%     Q3=q2*(diag(ones(m-2,1),2)-diag(ones(m-2,1),-2))+q1*(diag(ones(m-1,1),1)-diag(ones(m-1,1),-1));
-    stencil = [-q2,-q1,0,q1,q2];
-    d = (length(stencil)-1)/2;
-    diags = -d:d;
-    Q3 = stripeMatrix(stencil, diags, m);
-
-    %QQ3=(-1/8*diag(ones(m-3,1),3) + 1*diag(ones(m-2,1),2) - 13/8*diag(ones(m-1,1),1) +13/8*diag(ones(m-1,1),-1) -1*diag(ones(m-2,1),-2) + 1/8*diag(ones(m-3,1),-3));
-
-
-    Q3_U = [0 -0.13e2 / 0.16e2 0.7e1 / 0.8e1 -0.1e1 / 0.16e2; 0.13e2 / 0.16e2 0 -0.23e2 / 0.16e2 0.5e1 / 0.8e1; -0.7e1 / 0.8e1 0.23e2 / 0.16e2 0 -0.17e2 / 0.16e2; 0.1e1 / 0.16e2 -0.5e1 / 0.8e1 0.17e2 / 0.16e2 0;];
-    Q3(1:4,1:4)=Q3_U;
-    Q3(m-3:m,m-3:m)=rot90(  -Q3_U ,2 );
-    Q3=Q3/h^2;
-
-
-
-    S2_U=[1 -2 1;]/h^2;
-    S2_1=sparse(1,m);
-    S2_1(1:3)=S2_U;
-    S2_m=sparse(1,m);
-    S2_m(m-2:m)=fliplr(S2_U);
-    S2_1 = S2_1';
-    S2_m = S2_m';
-
-
-
-    D3=HI*(Q3 - e_1*S2_1' + e_m*S2_m' +1/2*(S_1*S_1') -1/2*(S_m*S_m') ) ;
-
-    % Fourth derivative, 0th order accurate at first 6 boundary points (still
-    % yield 4th order convergence if stable: for example u_tt=-u_xxxx
-
-    m2=1;m1=-4;m0=6;
-%     M4=m2*(diag(ones(m-2,1),2)+diag(ones(m-2,1),-2))+m1*(diag(ones(m-1,1),1)+diag(ones(m-1,1),-1))+m0*diag(ones(m,1),0);
-    stencil = [m2,m1,m0,m1,m2];
-    d = (length(stencil)-1)/2;
-    diags = -d:d;
-    M4 = stripeMatrix(stencil, diags, m);
-
-    %M4=(-1/6*(diag(ones(m-3,1),3)+diag(ones(m-3,1),-3) ) + 2*(diag(ones(m-2,1),2)+diag(ones(m-2,1),-2)) -13/2*(diag(ones(m-1,1),1)+diag(ones(m-1,1),-1)) + 28/3*diag(ones(m,1),0));
-
-    M4_U=[0.13e2 / 0.10e2 -0.12e2 / 0.5e1 0.9e1 / 0.10e2 0.1e1 / 0.5e1; -0.12e2 / 0.5e1 0.26e2 / 0.5e1 -0.16e2 / 0.5e1 0.2e1 / 0.5e1; 0.9e1 / 0.10e2 -0.16e2 / 0.5e1 0.47e2 / 0.10e2 -0.17e2 / 0.5e1; 0.1e1 / 0.5e1 0.2e1 / 0.5e1 -0.17e2 / 0.5e1 0.29e2 / 0.5e1;];
-
-
-    M4(1:4,1:4)=M4_U;
-
-    M4(m-3:m,m-3:m)=rot90(  M4_U ,2 );
-    M4=M4/h^3;
-
-    S3_U=[-1 3 -3 1;]/h^3;
-    S3_1=sparse(1,m);
-    S3_1(1:4)=S3_U;
-    S3_m=sparse(1,m);
-    S3_m(m-3:m)=fliplr(-S3_U);
-    S3_1 = S3_1';
-    S3_m = S3_m';
-
-    D4=HI*(M4-e_1*S3_1'+e_m*S3_m'  + S_1*S2_1'-S_m*S2_m');
-end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/+implementations/d4_compatible_halfvariable_4.m
--- a/+sbp/+implementations/d4_compatible_halfvariable_4.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,167 +0,0 @@
-function [H, HI, D2, D4, e_1, e_m, M4, S2_1, S2_m, S3_1,...
-    S3_m, S_1, S_m] = d4_compatible_halfvariable_4(m,h)
-    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-    %%% 4:de ordn. SBP Finita differens         %%%
-    %%%                                         %%%
-    %%% H           (Normen)                    %%%
-    %%% D1=H^(-1)Q  (approx f?rsta derivatan)   %%%
-    %%% D2          (approx andra derivatan)    %%%
-    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
-    %m=20; %problemstorlek
-    %h=1/(m-1);
-    %h=1;
-    
-    BP = 6;
-    if(m<2*BP)
-        error(['Operator requires at least ' num2str(2*BP) ' grid points']);
-    end
-
-%     c=ones(m,1);
-
-
-    H=speye(m,m);
-    H(1:4,1:4)=diag([17/48 59/48 43/48 49/48]);
-    H(m-3:m,m-3:m)=rot90(diag([17/48 59/48 43/48 49/48]),2);
-    H=H*h;
-    HI=inv(H);
-    HI = sparse(HI);
-
-
-
-%     Q=(-1/12*diag(ones(m-2,1),2)+8/12*diag(ones(m-1,1),1)-8/12*diag(ones(m-1,1),-1)+1/12*diag(ones(m-2,1),-2));
-      e=ones(m,1);
-%       Q=spdiags([e -8*e 0*e 8*e -e], -2:2, m, m)/12;
-%     Q_U = [0 0.59e2 / 0.96e2 -0.1e1 / 0.12e2 -0.1e1 / 0.32e2; -0.59e2 / 0.96e2 0 0.59e2 / 0.96e2 0; 0.1e1 / 0.12e2 -0.59e2 / 0.96e2 0 0.59e2 / 0.96e2; 0.1e1 / 0.32e2 0 -0.59e2 / 0.96e2 0;];
-%     Q(1:4,1:4)=Q_U;
-%     Q(m-3:m,m-3:m)=rot90( -Q_U(1:4,1:4) ,2 );
-
-    e_1=sparse(m,1);e_1(1)=1;
-    e_m=sparse(m,1);e_m(m)=1;
-
-%     D1=HI*(Q-1/2*(e_1*e_1')+1/2*(e_m*e_m')) ;
-
-    M_U=[0.9e1 / 0.8e1 -0.59e2 / 0.48e2 0.1e1 / 0.12e2 0.1e1 / 0.48e2; -0.59e2 / 0.48e2 0.59e2 / 0.24e2 -0.59e2 / 0.48e2 0; 0.1e1 / 0.12e2 -0.59e2 / 0.48e2 0.55e2 / 0.24e2 -0.59e2 / 0.48e2; 0.1e1 / 0.48e2 0 -0.59e2 / 0.48e2 0.59e2 / 0.24e2;];
-%     M=-(-1/12*diag(ones(m-2,1),2)+16/12*diag(ones(m-1,1),1)+16/12*diag(ones(m-1,1),-1)-1/12*diag(ones(m-2,1),-2)-30/12*diag(ones(m,1),0));
-    M=-spdiags([-e 16*e -30*e 16*e -e], -2:2, m, m)/12;
-
-    M(1:4,1:4)=M_U;
-
-    M(m-3:m,m-3:m)=rot90(  M_U ,2 );
-    M=M/h;
-
-    S_U=[-0.11e2 / 0.6e1 3 -0.3e1 / 0.2e1 0.1e1 / 0.3e1;]/h;
-    S_1=sparse(1,m);
-    S_1(1:4)=S_U;
-    S_m=sparse(1,m);
-    S_m(m-3:m)=fliplr(-S_U);
-    S_1 = S_1';
-    S_m = S_m';
-
-
-    M=sparse(m,m);
-    e_1 = sparse(e_1);
-    e_m = sparse(e_m);
-    S_1 = sparse(S_1);
-    S_m = sparse(S_m);
-
-
-    scheme_width = 5;
-    scheme_radius = (scheme_width-1)/2;
-    r = (1+scheme_radius):(m-scheme_radius);
-
-    function D2 = D2_fun(c)
-
-        % ALTERNATIVES %%%%%%%%%%%%%
-        % for i=4:m-3
-        %     M(i,i-2:i+2)=[-c(i-1) / 0.6e1 + c(i-2) / 0.8e1 + c(i) / 0.8e1 -c(i-2) / 0.6e1 - c(i+1) / 0.6e1 - c(i-1) / 0.2e1 - c(i) / 0.2e1 c(i-2) / 0.24e2 + 0.5e1 / 0.6e1 * c(i-1) + 0.5e1 / 0.6e1 * c(i+1) + c(i+2) / 0.24e2 + 0.3e1 / 0.4e1 * c(i) -c(i-1) / 0.6e1 - c(i+2) / 0.6e1 - c(i) / 0.2e1 - c(i+1) / 0.2e1 -c(i+1) / 0.6e1 + c(i) / 0.8e1 + c(i+2) / 0.8e1;];
-        % end
-        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-        % for i=4:m-3
-        %     M(i,i-2:i+2)= [
-        %      c(i-2) / 0.8e1 - c(i-1) / 0.6e1 + c(i)   / 0.8e1                                   ,
-        %     -c(i-2) / 0.6e1 - c(i-1) / 0.2e1 - c(i)   / 0.2e1 - c(i+1) / 0.6e1                  ,
-        %      c(i-2) / 2.4e1 + c(i-1) / 1.2e0 + c(i) * 0.3/0.4 + c(i+1) / 1.2e0 + c(i+2) / 2.4e1 ,
-        %                      -c(i-1) / 0.6e1 - c(i)   / 0.2e1 - c(i+1) / 0.2e1 - c(i+2) / 0.6e1 ,
-        %                                        c(i)   / 0.8e1 - c(i+1) / 0.6e1 + c(i+2) / 0.8e1 ,
-        %     ];
-        % end
-        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-        Mm2 =  c(r-2) / 0.8e1 - c(r-1) / 0.6e1 + c(r)   / 0.8e1                                  ;
-        Mm1 = -c(r-2) / 0.6e1 - c(r-1) / 0.2e1 - c(r)   / 0.2e1 - c(r+1) / 0.6e1                 ;
-        M0  =  c(r-2) / 2.4e1 + c(r-1) / 1.2e0 + c(r) * 0.3/0.4 + c(r+1) / 1.2e0 + c(r+2) / 2.4e1;
-        Mp1 =                  -c(r-1) / 0.6e1 - c(r)   / 0.2e1 - c(r+1) / 0.2e1 - c(r+2) / 0.6e1;
-        Mp2 =                                    c(r)   / 0.8e1 - c(r+1) / 0.6e1 + c(r+2) / 0.8e1;
-        % printSize(Mm2);
-        % scheme_radius
-        % m
-        M(r,:) = spdiags([Mm2 Mm1 M0 Mp1 Mp2],0:2*scheme_radius,length(r),m);
-        % M(r,:) = spdiags([Mm2 Mm1 M0 Mp1 Mp2],(-2:2)+scheme_radius,M(r,:)); % This is slower
-        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-        % %% Somthing is wrong here!!
-        % Mm2 =  c(r-2) / 0.8e1 - c(r-1) / 0.6e1 + c(r)   / 0.8e1                                  ;
-        % Mm1 = -c(r-2) / 0.6e1 - c(r-1) / 0.2e1 - c(r)   / 0.2e1 - c(r+1) / 0.6e1                 ;
-        % M0  =  c(r-2) / 2.4e1 + c(r-1) / 1.2e0 + c(r) * 0.3/0.4 + c(r+1) / 1.2e0 + c(r+2) / 2.4e1;
-        % Mp1 =                  -c(r-1) / 0.6e1 - c(r)   / 0.2e1 - c(r+1) / 0.2e1 - c(r+2) / 0.6e1;
-        % Mp2 =                                    c(r)   / 0.8e1 - c(r+1) / 0.6e1 + c(r+2) / 0.8e1;
-        % % printSize(M_diag_ind);
-        % % Mdiags = [Mm2 Mm1 M0  Mp1 Mp2];
-        % % printSize(Mdiags);
-        % M(M_diag_ind) = [Mm2 Mm1 M0  Mp1 Mp2]; % This is slightly faster
-        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-        % Kan man skriva det som en multiplikation av en 3-dim matris?
-        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
-
-
-        M(1:6,1:6)=[0.12e2 / 0.17e2 * c(1) + 0.59e2 / 0.192e3 * c(2) + 0.27010400129e11 / 0.345067064608e12 * c(3) + 0.69462376031e11 / 0.2070402387648e13 * c(4) -0.59e2 / 0.68e2 * c(1) - 0.6025413881e10 / 0.21126554976e11 * c(3) - 0.537416663e9 / 0.7042184992e10 * c(4) 0.2e1 / 0.17e2 * c(1) - 0.59e2 / 0.192e3 * c(2) + 0.213318005e9 / 0.16049630912e11 * c(4) + 0.2083938599e10 / 0.8024815456e10 * c(3) 0.3e1 / 0.68e2 * c(1) - 0.1244724001e10 / 0.21126554976e11 * c(3) + 0.752806667e9 / 0.21126554976e11 * c(4) 0.49579087e8 / 0.10149031312e11 * c(3) - 0.49579087e8 / 0.10149031312e11 * c(4) -c(4) / 0.784e3 + c(3) / 0.784e3; -0.59e2 / 0.68e2 * c(1) - 0.6025413881e10 / 0.21126554976e11 * c(3) - 0.537416663e9 / 0.7042184992e10 * c(4) 0.3481e4 / 0.3264e4 * c(1) + 0.9258282831623875e16 / 0.7669235228057664e16 * c(3) + 0.236024329996203e15 / 0.1278205871342944e16 * c(4) -0.59e2 / 0.408e3 * c(1) - 0.29294615794607e14 / 0.29725717938208e14 * c(3) - 0.2944673881023e13 / 0.29725717938208e14 * c(4) -0.59e2 / 0.1088e4 * c(1) + 0.260297319232891e15 / 0.2556411742685888e16 * c(3) - 0.60834186813841e14 / 0.1278205871342944e16 * c(4) -0.1328188692663e13 / 0.37594290333616e14 * c(3) + 0.1328188692663e13 / 0.37594290333616e14 * c(4) -0.8673e4 / 0.2904112e7 * c(3) + 0.8673e4 / 0.2904112e7 * c(4); 0.2e1 / 0.17e2 * c(1) - 0.59e2 / 0.192e3 * c(2) + 0.213318005e9 / 0.16049630912e11 * c(4) + 0.2083938599e10 / 0.8024815456e10 * c(3) -0.59e2 / 0.408e3 * c(1) - 0.29294615794607e14 / 0.29725717938208e14 * c(3) - 0.2944673881023e13 / 0.29725717938208e14 * c(4) c(1) / 0.51e2 + 0.59e2 / 0.192e3 * c(2) + 0.13777050223300597e17 / 0.26218083221499456e17 * c(4) + 0.564461e6 / 0.13384296e8 * c(5) + 0.378288882302546512209e21 / 0.270764341349677687456e21 * c(3) c(1) / 0.136e3 - 0.125059e6 / 0.743572e6 * c(5) - 0.4836340090442187227e19 / 0.5525802884687299744e19 * c(3) - 0.17220493277981e14 / 0.89177153814624e14 * c(4) -0.10532412077335e14 / 0.42840005263888e14 * c(4) + 0.1613976761032884305e19 / 0.7963657098519931984e19 * c(3) + 0.564461e6 / 0.4461432e7 * c(5) -0.960119e6 / 0.1280713392e10 * c(4) - 0.3391e4 / 0.6692148e7 * c(5) + 0.33235054191e11 / 0.26452850508784e14 * c(3); 0.3e1 / 0.68e2 * c(1) - 0.1244724001e10 / 0.21126554976e11 * c(3) + 0.752806667e9 / 0.21126554976e11 * c(4) -0.59e2 / 0.1088e4 * c(1) + 0.260297319232891e15 / 0.2556411742685888e16 * c(3) - 0.60834186813841e14 / 0.1278205871342944e16 * c(4) c(1) / 0.136e3 - 0.125059e6 / 0.743572e6 * c(5) - 0.4836340090442187227e19 / 0.5525802884687299744e19 * c(3) - 0.17220493277981e14 / 0.89177153814624e14 * c(4) 0.3e1 / 0.1088e4 * c(1) + 0.507284006600757858213e21 / 0.475219048083107777984e21 * c(3) + 0.1869103e7 / 0.2230716e7 * c(5) + c(6) / 0.24e2 + 0.1950062198436997e16 / 0.3834617614028832e16 * c(4) -0.4959271814984644613e19 / 0.20965546238960637264e20 * c(3) - c(6) / 0.6e1 - 0.15998714909649e14 / 0.37594290333616e14 * c(4) - 0.375177e6 / 0.743572e6 * c(5) -0.368395e6 / 0.2230716e7 * c(5) + 0.752806667e9 / 0.539854092016e12 * c(3) + 0.1063649e7 / 0.8712336e7 * c(4) + c(6) / 0.8e1; 0.49579087e8 / 0.10149031312e11 * c(3) - 0.49579087e8 / 0.10149031312e11 * c(4) -0.1328188692663e13 / 0.37594290333616e14 * c(3) + 0.1328188692663e13 / 0.37594290333616e14 * c(4) -0.10532412077335e14 / 0.42840005263888e14 * c(4) + 0.1613976761032884305e19 / 0.7963657098519931984e19 * c(3) + 0.564461e6 / 0.4461432e7 * c(5) -0.4959271814984644613e19 / 0.20965546238960637264e20 * c(3) - c(6) / 0.6e1 - 0.15998714909649e14 / 0.37594290333616e14 * c(4) - 0.375177e6 / 0.743572e6 * c(5) 0.8386761355510099813e19 / 0.128413970713633903242e21 * c(3) + 0.2224717261773437e16 / 0.2763180339520776e16 * c(4) + 0.5e1 / 0.6e1 * c(6) + c(7) / 0.24e2 + 0.280535e6 / 0.371786e6 * c(5) -0.35039615e8 / 0.213452232e9 * c(4) - c(7) / 0.6e1 - 0.13091810925e11 / 0.13226425254392e14 * c(3) - 0.1118749e7 / 0.2230716e7 * c(5) - c(6) / 0.2e1; -c(4) / 0.784e3 + c(3) / 0.784e3 -0.8673e4 / 0.2904112e7 * c(3) + 0.8673e4 / 0.2904112e7 * c(4) -0.960119e6 / 0.1280713392e10 * c(4) - 0.3391e4 / 0.6692148e7 * c(5) + 0.33235054191e11 / 0.26452850508784e14 * c(3) -0.368395e6 / 0.2230716e7 * c(5) + 0.752806667e9 / 0.539854092016e12 * c(3) + 0.1063649e7 / 0.8712336e7 * c(4) + c(6) / 0.8e1 -0.35039615e8 / 0.213452232e9 * c(4) - c(7) / 0.6e1 - 0.13091810925e11 / 0.13226425254392e14 * c(3) - 0.1118749e7 / 0.2230716e7 * c(5) - c(6) / 0.2e1 0.3290636e7 / 0.80044587e8 * c(4) + 0.5580181e7 / 0.6692148e7 * c(5) + 0.5e1 / 0.6e1 * c(7) + c(8) / 0.24e2 + 0.660204843e9 / 0.13226425254392e14 * c(3) + 0.3e1 / 0.4e1 * c(6);];
-
-        M(m-5:m,m-5:m)=[c(m-7) / 0.24e2 + 0.5e1 / 0.6e1 * c(m-6) + 0.5580181e7 / 0.6692148e7 * c(m-4) + 0.4887707739997e13 / 0.119037827289528e15 * c(m-3) + 0.3e1 / 0.4e1 * c(m-5) + 0.660204843e9 / 0.13226425254392e14 * c(m-2) + 0.660204843e9 / 0.13226425254392e14 * c(m-1) -c(m-6) / 0.6e1 - 0.1618585929605e13 / 0.9919818940794e13 * c(m-3) - c(m-5) / 0.2e1 - 0.1118749e7 / 0.2230716e7 * c(m-4) - 0.13091810925e11 / 0.13226425254392e14 * c(m-2) - 0.13091810925e11 / 0.13226425254392e14 * c(m-1) -0.368395e6 / 0.2230716e7 * c(m-4) + c(m-5) / 0.8e1 + 0.48866620889e11 / 0.404890569012e12 * c(m-3) + 0.752806667e9 / 0.539854092016e12 * c(m-2) + 0.752806667e9 / 0.539854092016e12 * c(m-1) -0.3391e4 / 0.6692148e7 * c(m-4) - 0.238797444493e12 / 0.119037827289528e15 * c(m-3) + 0.33235054191e11 / 0.26452850508784e14 * c(m-2) + 0.33235054191e11 / 0.26452850508784e14 * c(m-1) -0.8673e4 / 0.2904112e7 * c(m-2) - 0.8673e4 / 0.2904112e7 * c(m-1) + 0.8673e4 / 0.1452056e7 * c(m-3) -c(m-3) / 0.392e3 + c(m-2) / 0.784e3 + c(m-1) / 0.784e3; -c(m-6) / 0.6e1 - 0.1618585929605e13 / 0.9919818940794e13 * c(m-3) - c(m-5) / 0.2e1 - 0.1118749e7 / 0.2230716e7 * c(m-4) - 0.13091810925e11 / 0.13226425254392e14 * c(m-2) - 0.13091810925e11 / 0.13226425254392e14 * c(m-1) c(m-6) / 0.24e2 + 0.5e1 / 0.6e1 * c(m-5) + 0.3896014498639e13 / 0.4959909470397e13 * c(m-3) + 0.8386761355510099813e19 / 0.128413970713633903242e21 * c(m-2) + 0.280535e6 / 0.371786e6 * c(m-4) + 0.3360696339136261875e19 / 0.171218627618178537656e21 * c(m-1) -c(m-5) / 0.6e1 - 0.4959271814984644613e19 / 0.20965546238960637264e20 * c(m-2) - 0.375177e6 / 0.743572e6 * c(m-4) - 0.13425842714e11 / 0.33740880751e11 * c(m-3) - 0.193247108773400725e18 / 0.6988515412986879088e19 * c(m-1) -0.365281640980e12 / 0.1653303156799e13 * c(m-3) + 0.564461e6 / 0.4461432e7 * c(m-4) + 0.1613976761032884305e19 / 0.7963657098519931984e19 * c(m-2) - 0.198407225513315475e18 / 0.7963657098519931984e19 * c(m-1) -0.1328188692663e13 / 0.37594290333616e14 * c(m-2) + 0.2226377963775e13 / 0.37594290333616e14 * c(m-1) - 0.8673e4 / 0.363014e6 * c(m-3) c(m-3) / 0.49e2 + 0.49579087e8 / 0.10149031312e11 * c(m-2) - 0.256702175e9 / 0.10149031312e11 * c(m-1); -0.368395e6 / 0.2230716e7 * c(m-4) + c(m-5) / 0.8e1 + 0.48866620889e11 / 0.404890569012e12 * c(m-3) + 0.752806667e9 / 0.539854092016e12 * c(m-2) + 0.752806667e9 / 0.539854092016e12 * c(m-1) -c(m-5) / 0.6e1 - 0.4959271814984644613e19 / 0.20965546238960637264e20 * c(m-2) - 0.375177e6 / 0.743572e6 * c(m-4) - 0.13425842714e11 / 0.33740880751e11 * c(m-3) - 0.193247108773400725e18 / 0.6988515412986879088e19 * c(m-1) c(m-5) / 0.24e2 + 0.1869103e7 / 0.2230716e7 * c(m-4) + 0.507284006600757858213e21 / 0.475219048083107777984e21 * c(m-2) + 0.3e1 / 0.1088e4 * c(m) + 0.31688435395e11 / 0.67481761502e11 * c(m-3) + 0.27769176016102795561e20 / 0.712828572124661666976e21 * c(m-1) -0.125059e6 / 0.743572e6 * c(m-4) + c(m) / 0.136e3 - 0.23099342648e11 / 0.101222642253e12 * c(m-3) - 0.4836340090442187227e19 / 0.5525802884687299744e19 * c(m-2) + 0.193950157930938693e18 / 0.5525802884687299744e19 * c(m-1) 0.260297319232891e15 / 0.2556411742685888e16 * c(m-2) - 0.59e2 / 0.1088e4 * c(m) - 0.106641839640553e15 / 0.1278205871342944e16 * c(m-1) + 0.26019e5 / 0.726028e6 * c(m-3) -0.1244724001e10 / 0.21126554976e11 * c(m-2) + 0.3e1 / 0.68e2 * c(m) + 0.752806667e9 / 0.21126554976e11 * c(m-1); -0.3391e4 / 0.6692148e7 * c(m-4) - 0.238797444493e12 / 0.119037827289528e15 * c(m-3) + 0.33235054191e11 / 0.26452850508784e14 * c(m-2) + 0.33235054191e11 / 0.26452850508784e14 * c(m-1) -0.365281640980e12 / 0.1653303156799e13 * c(m-3) + 0.564461e6 / 0.4461432e7 * c(m-4) + 0.1613976761032884305e19 / 0.7963657098519931984e19 * c(m-2) - 0.198407225513315475e18 / 0.7963657098519931984e19 * c(m-1) -0.125059e6 / 0.743572e6 * c(m-4) + c(m) / 0.136e3 - 0.23099342648e11 / 0.101222642253e12 * c(m-3) - 0.4836340090442187227e19 / 0.5525802884687299744e19 * c(m-2) + 0.193950157930938693e18 / 0.5525802884687299744e19 * c(m-1) 0.564461e6 / 0.13384296e8 * c(m-4) + 0.470299699916357e15 / 0.952302618316224e15 * c(m-3) + 0.550597048646198778781e21 / 0.1624586048098066124736e22 * c(m-1) + c(m) / 0.51e2 + 0.378288882302546512209e21 / 0.270764341349677687456e21 * c(m-2) -0.59e2 / 0.408e3 * c(m) - 0.29294615794607e14 / 0.29725717938208e14 * c(m-2) - 0.2234477713167e13 / 0.29725717938208e14 * c(m-1) - 0.8673e4 / 0.363014e6 * c(m-3) -0.59e2 / 0.3136e4 * c(m-3) - 0.13249937023e11 / 0.48148892736e11 * c(m-1) + 0.2e1 / 0.17e2 * c(m) + 0.2083938599e10 / 0.8024815456e10 * c(m-2); -0.8673e4 / 0.2904112e7 * c(m-2) - 0.8673e4 / 0.2904112e7 * c(m-1) + 0.8673e4 / 0.1452056e7 * c(m-3) -0.1328188692663e13 / 0.37594290333616e14 * c(m-2) + 0.2226377963775e13 / 0.37594290333616e14 * c(m-1) - 0.8673e4 / 0.363014e6 * c(m-3) 0.260297319232891e15 / 0.2556411742685888e16 * c(m-2) - 0.59e2 / 0.1088e4 * c(m) - 0.106641839640553e15 / 0.1278205871342944e16 * c(m-1) + 0.26019e5 / 0.726028e6 * c(m-3) -0.59e2 / 0.408e3 * c(m) - 0.29294615794607e14 / 0.29725717938208e14 * c(m-2) - 0.2234477713167e13 / 0.29725717938208e14 * c(m-1) - 0.8673e4 / 0.363014e6 * c(m-3) 0.9258282831623875e16 / 0.7669235228057664e16 * c(m-2) + 0.3481e4 / 0.3264e4 * c(m) + 0.228389721191751e15 / 0.1278205871342944e16 * c(m-1) + 0.8673e4 / 0.1452056e7 * c(m-3) -0.6025413881e10 / 0.21126554976e11 * c(m-2) - 0.59e2 / 0.68e2 * c(m) - 0.537416663e9 / 0.7042184992e10 * c(m-1); -c(m-3) / 0.392e3 + c(m-2) / 0.784e3 + c(m-1) / 0.784e3 c(m-3) / 0.49e2 + 0.49579087e8 / 0.10149031312e11 * c(m-2) - 0.256702175e9 / 0.10149031312e11 * c(m-1) -0.1244724001e10 / 0.21126554976e11 * c(m-2) + 0.3e1 / 0.68e2 * c(m) + 0.752806667e9 / 0.21126554976e11 * c(m-1) -0.59e2 / 0.3136e4 * c(m-3) - 0.13249937023e11 / 0.48148892736e11 * c(m-1) + 0.2e1 / 0.17e2 * c(m) + 0.2083938599e10 / 0.8024815456e10 * c(m-2) -0.6025413881e10 / 0.21126554976e11 * c(m-2) - 0.59e2 / 0.68e2 * c(m) - 0.537416663e9 / 0.7042184992e10 * c(m-1) 0.3e1 / 0.3136e4 * c(m-3) + 0.27010400129e11 / 0.345067064608e12 * c(m-2) + 0.234566387291e12 / 0.690134129216e12 * c(m-1) + 0.12e2 / 0.17e2 * c(m);];
-
-        M=M/h;
-        D2=HI*(-M-c(1)*e_1*S_1'+c(m)*e_m*S_m');
-    end
-    D2 = @D2_fun;
-
-
-    S2_U=[2 -5 4 -1;]/h^2;
-    S2_1=sparse(1,m);
-    S2_1(1:4)=S2_U;
-    S2_m=sparse(1,m);
-    S2_m(m-3:m)=fliplr(S2_U);
-    S2_1 = S2_1';
-    S2_m = S2_m';
-
-    m3=-1/6;m2=2;m1=-13/2;m0=28/3;
-%     M4=m3*(diag(ones(m-3,1),3)+diag(ones(m-3,1),-3))+m2*(diag(ones(m-2,1),2)+diag(ones(m-2,1),-2))+m1*(diag(ones(m-1,1),1)+diag(ones(m-1,1),-1))+m0*diag(ones(m,1),0);
-    stencil = [m3,m2,m1,m0,m1,m2,m3];
-    d = (length(stencil)-1)/2;
-    diags = -d:d;
-    M4 = stripeMatrix(stencil, diags, m);
-
-    %M4=(-1/6*(diag(ones(m-3,1),3)+diag(ones(m-3,1),-3) ) + 2*(diag(ones(m-2,1),2)+diag(ones(m-2,1),-2)) -13/2*(diag(ones(m-1,1),1)+diag(ones(m-1,1),-1)) + 28/3*diag(ones(m,1),0));
-
-    M4_U=[0.5762947e7 / 0.2316384e7 -0.6374287e7 / 0.1158192e7 0.573947e6 / 0.165456e6 -0.124637e6 / 0.289548e6 0.67979e5 / 0.2316384e7 -0.60257e5 / 0.1158192e7; -0.6374287e7 / 0.1158192e7 0.30392389e8 / 0.2316384e7 -0.2735053e7 / 0.289548e6 0.273109e6 / 0.165456e6 0.83767e5 / 0.1158192e7 0.245549e6 / 0.2316384e7; 0.573947e6 / 0.165456e6 -0.2735053e7 / 0.289548e6 0.5266855e7 / 0.579096e6 -0.1099715e7 / 0.289548e6 0.869293e6 / 0.1158192e7 -0.10195e5 / 0.144774e6; -0.124637e6 / 0.289548e6 0.273109e6 / 0.165456e6 -0.1099715e7 / 0.289548e6 0.3259225e7 / 0.579096e6 -0.324229e6 / 0.72387e5 0.1847891e7 / 0.1158192e7; 0.67979e5 / 0.2316384e7 0.83767e5 / 0.1158192e7 0.869293e6 / 0.1158192e7 -0.324229e6 / 0.72387e5 0.2626501e7 / 0.330912e6 -0.7115491e7 / 0.1158192e7; -0.60257e5 / 0.1158192e7 0.245549e6 / 0.2316384e7 -0.10195e5 / 0.144774e6 0.1847891e7 / 0.1158192e7 -0.7115491e7 / 0.1158192e7 0.21383077e8 / 0.2316384e7;];
-
-    M4(1:6,1:6)=M4_U;
-
-    M4(m-5:m,m-5:m)=rot90(  M4_U ,2 );
-    M4=M4/h^3;
-
-    S3_U=[-1 3 -3 1;]/h^3;
-    S3_1=sparse(1,m);
-    S3_1(1:4)=S3_U;
-    S3_m=sparse(1,m);
-    S3_m(m-3:m)=fliplr(-S3_U);
-    S3_1 = S3_1';
-    S3_m = S3_m';
-
-    D4=HI*(M4-e_1*S3_1'+e_m*S3_m'  + S_1*S2_1'-S_m*S2_m');
-
-
-
-
-
-end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/+implementations/d4_compatible_halfvariable_6.m
--- a/+sbp/+implementations/d4_compatible_halfvariable_6.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +0,0 @@
-function [H, HI, D2, D4, e_1, e_m, M4, S2_1, S2_m, S3_1,...
-    S3_m, S_1, S_m] = d4_compatible_halfvariable_6(m,h)
-    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-    %%% 6:te ordn. SBP Finita differens         %%%
-    %%% operatorer med diagonal norm            %%%
-    %%% Extension to variable koeff             %%%
-    %%%                                         %%%
-    %%% H           (Normen)                    %%%
-    %%% D1=H^(-1)Q  (approx f?rsta derivatan)   %%%
-    %%% D2          (approx andra derivatan)    %%%
-    %%% D2=HI*(R+C*D*S                          %%%
-    %%%                                         %%%
-    %%% R=-D1'*H*C*D1-RR                        %%%
-    %%%                                         %%%
-    %%% RR ?r dissipation)                      %%%
-    %%% Dissipationen uppbyggd av D4:           %%%
-    %%% DI=D4*B*H*D4                            %%%
-    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
-    %m=10;          %problemstorlek
-    %h=1/(m-1);
-
-    % Variable koefficicients are stored in vector: c, size m,
-    % with the unknown stored as c(1), c(2), ..., c_m
-    % x=1:h:m*h;x=x';
-    % c=x.^0;
-    
-    BP = 8;
-    if(m<2*BP)
-        error(['Operator requires at least ' num2str(2*BP) ' grid points']);
-    end
-
-
-    H=speye(m,m);
-    H(1:6,1:6)=diag([13649/43200,12013/8640,2711/4320,5359/4320,7877/8640, ...
-    		 43801/43200]);
-    H(m-5:m,m-5:m)=rot90(diag([13649/43200,12013/8640, ...
-    		    2711/4320,5359/4320,7877/8640,43801/43200]),2);
-
-
-%     x1=0.70127127127127;
-
-
-%     D1=(1/60*diag(ones(m-3,1),3)-9/60*diag(ones(m-2,1),2)+45/60*diag(ones(m-1,1),1)-45/60*diag(ones(m-1,1),-1)+9/60*diag(ones(m-2,1),-2)-1/60*diag(ones(m-3,1),-3));
-% 
-% 
-% 
-%     D1(1:6,1:9)=[-21600/13649, 43200/13649*x1-7624/40947, -172800/13649*x1+ ...
-%     	     715489/81894, 259200/13649*x1-187917/13649, -172800/13649* ...
-%     	     x1+735635/81894, 43200/13649*x1-89387/40947, 0, 0, 0; ...
-%     	     -8640/12013*x1+7624/180195, 0, 86400/12013*x1-57139/12013, ...
-%     	     -172800/12013*x1+745733/72078, 129600/12013*x1-91715/12013, ...
-%     	     -34560/12013*x1+240569/120130, 0, 0, 0; ...
-%              17280/2711*x1-715489/162660, -43200/2711*x1+57139/5422, 0, ...
-%              86400/2711*x1-176839/8133, -86400/2711*x1+242111/10844, ...
-%              25920/2711*x1-182261/27110, 0, 0, 0; ...
-%              -25920/5359*x1+187917/53590, 86400/5359*x1-745733/64308, ...
-%              -86400/5359*x1+176839/16077, 0, 43200/5359*x1-165041/32154, ...
-%              -17280/5359*x1+710473/321540, 72/5359, 0, 0; ...
-%              34560/7877*x1-147127/47262, -129600/7877*x1+91715/7877, ...
-%              172800/7877*x1-242111/15754, -86400/7877*x1+165041/23631, ...
-%              0, 8640/7877*x1, -1296/7877, 144/7877, 0; ...
-%              -43200/43801*x1+89387/131403, 172800/43801*x1-240569/87602,...
-%              -259200/43801*x1+182261/43801, 172800/43801*x1-710473/262806, ...
-%              -43200/43801*x1, 0, 32400/43801, -6480/43801, 720/43801];
-%     D1(m-5:m,m-8:m)=rot90( -D1(1:6,1:9),2);
-%     D1=D1/h;
-
-    e_1=sparse(m,1);e_1(1)=1;
-    e_m=sparse(m,1);e_m(m)=1;
-
-    S_U=[-25/12, 4, -3, 4/3, -1/4]/h;
-    S_1=sparse(1,m);
-    S_1(1:5)=S_U;
-    S_m=sparse(1,m);
-    S_m(m-4:m)=fliplr(-S_U);
-    S_1 = S_1';
-    S_m = S_m';
-
-
-
-    %DS=sparse(m,m);
-    %DS(1,1:5)=-[-25/12, 4, -3, 4/3, -1/4];
-    %DS(m,m-4:m)=fliplr(-[-25/12, 4, -3, 4/3, -1/4]);
-    %DS=diag(c)*DS/h;
-
-
-    H=h*H;
-    HI=inv(H);
-
-
-    M=sparse(m,m);
-    e_1 = sparse(e_1);
-    e_m = sparse(e_m);
-    S_1 = sparse(S_1);
-    S_m = sparse(S_m);
-
-    scheme_width = 7;
-    scheme_radius = (scheme_width-1)/2;
-    r = (1+scheme_radius):(m-scheme_radius);
-
-    function D2 = D2_fun(c)
-
-        Mm3 =  c(r-2) / 0.40e2 + c(r-1) / 0.40e2 - 0.11e2 / 0.360e3 * c(r-3) - 0.11e2 / 0.360e3 * c(r);
-        Mm2 =  c(r-3) / 0.20e2 - 0.3e1 / 0.10e2 * c(r-1) + c(r+1) / 0.20e2 + 0.7e1 / 0.40e2 * c(r) + 0.7e1 / 0.40e2 * c(r-2);
-        Mm1 = -c(r-3) / 0.40e2 - 0.3e1 / 0.10e2 * c(r-2) - 0.3e1 / 0.10e2 * c(r+1) - c(r+2) / 0.40e2 - 0.17e2 / 0.40e2 * c(r) - 0.17e2 / 0.40e2 * c(r-1);
-        M0 =  c(r-3) / 0.180e3 + c(r-2) / 0.8e1 + 0.19e2 / 0.20e2 * c(r-1) + 0.19e2 / 0.20e2 * c(r+1) + c(r+2) / 0.8e1 + c(r+3) / 0.180e3 + 0.101e3 / 0.180e3 * c(r);
-        Mp1 = -c(r-2) / 0.40e2 - 0.3e1 / 0.10e2 * c(r-1) - 0.3e1 / 0.10e2 * c(r+2) - c(r+3) / 0.40e2 - 0.17e2 / 0.40e2 * c(r) - 0.17e2 / 0.40e2 * c(r+1);
-        Mp2 =  c(r-1) / 0.20e2 - 0.3e1 / 0.10e2 * c(r+1) + c(r+3) / 0.20e2 + 0.7e1 / 0.40e2 * c(r) + 0.7e1 / 0.40e2 * c(r+2);
-        Mp3 =  c(r+1) / 0.40e2 + c(r+2) / 0.40e2 - 0.11e2 / 0.360e3 * c(r) - 0.11e2 / 0.360e3 * c(r+3);
-
-        M(r,:) = spdiags([Mm3 Mm2 Mm1 M0 Mp1 Mp2 Mp3],0:2*scheme_radius,length(r),m);
-
-
-        M(1:9,1:9)=[0.7912667594695582093926295e0 * c(1) + 0.2968472090638000742888467e0 * c(2) + 0.3185519088796429015220016e-2 * c(3) + 0.1632404042590951953384672e-1 * c(4) + 0.3160302244094415087693968e-1 * c(5) + 0.3167964748016105299646518e-1 * c(6) + 0.3148577733947253920469418e-1 * c(7) -0.1016689339350338144430605e1 * c(1) - 0.2845627370491611369031341e-1 * c(3) - 0.4128029838349298819825156e-1 * c(4) - 0.1392281451620140507549866e0 * c(5) - 0.1195777325611201766551392e0 * c(6) - 0.1194267756529333410855186e0 * c(7) 0.7075642937243715046279337e-1 * c(1) - 0.1845476106024151050283847e0 * c(2) - 0.4364163147111892346990101e-1 * c(4) + 0.2432367907207732460874765e0 * c(5) + 0.1582127073537215443965653e0 * c(6) + 0.1602348578364786307613271e0 * c(7) 0.2251991532891353212689574e0 * c(1) - 0.1662748711097054895317080e0 * c(2) + 0.2710530961648671297733465e-1 * c(3) - 0.1916646185968439909125616e0 * c(5) - 0.7684117160199014594442072e-1 * c(6) - 0.8219586949831697575883635e-1 * c(7) -0.5224403464202056316702078e-1 * c(1) + 0.4440063948509876221050939e-1 * c(2) - 0.1023976547309387874453988e-2 * c(3) + 0.7403484645316174090533193e-1 * c(4) + 0.1241625568998496895352046e-1 * c(6) + 0.7188652847892601282652228e-1 * c(5) + 0.1379362997104735503447960e-1 * c(7) -0.1828896813877197352675410e-1 * c(1) + 0.9574633163221758060736592e-2 * c(2) - 0.8105784530576404277872603e-3 * c(3) - 0.7348845587775519698437916e-2 * c(4) + 0.1063601949723906997026904e-1 * c(5) - 0.1315967038382618382356495e-1 * c(6) - 0.2117936478838753524581943e-1 * c(7) 0.1911888563316170927411831e-2 * c(4) - 0.4068130355529149936100229e-1 * c(5) + 0.1319674981073749167009902e-1 * c(6) + 0.2557266518123783676349144e-1 * c(7) 0.1559652871136785763960685e-1 * c(5) - 0.6486184157331537899459796e-2 * c(6) - 0.9110344554036319740147054e-2 * c(7) 0.5593983696629863059347067e-3 * c(6) - 0.1384822535100796372263822e-2 * c(5) + 0.8254241654378100663291154e-3 * c(7); -0.1016689339350338144430605e1 * c(1) - 0.2845627370491611369031341e-1 * c(3) - 0.4128029838349298819825156e-1 * c(4) - 0.1392281451620140507549866e0 * c(5) - 0.1195777325611201766551392e0 * c(6) - 0.1194267756529333410855186e0 * c(7) 0.1306332157111667628555907e1 * c(1) + 0.2542001760457345743492403e0 * c(3) + 0.1043897828092562609502636e0 * c(4) + 0.6672328021032112950919876e0 * c(5) + 0.4681819359722749441073885e0 * c(6) + 0.4676415410195836920069412e0 * c(7) -0.9091410269992464604926176e-1 * c(1) + 0.1103611313171476425250639e0 * c(4) - 0.1290397544997518887000350e1 * c(5) - 0.6639605248735044787146222e0 * c(6) - 0.6615974464005206184151509e0 * c(7) -0.2893557395653431666593814e0 * c(1) - 0.2421320004064592721552708e0 * c(3) + 0.1187670255028031027693374e1 * c(5) + 0.3956598149904136332753521e0 * c(6) + 0.3860048921755800000681479e0 * c(7) 0.6712774475803763988977355e-1 * c(1) + 0.9147192682075630179962131e-2 * c(3) - 0.1872196143003808021730728e0 * c(4) - 0.1319358558853174530078498e0 * c(6) - 0.4871575736811911887376923e0 * c(5) - 0.1047516312275448138054418e0 * c(7) 0.2349927974590068869356781e-1 * c(1) + 0.7240905383565181316381731e-2 * c(3) + 0.1858378996391679448655070e-1 * c(4) - 0.9289616133938676174345208e-1 * c(5) + 0.1223513270418807666970488e0 * c(6) + 0.1113520320436295033894092e0 * c(7) -0.4834791406446907590553793e-2 * c(4) + 0.2310683832687820403062715e0 * c(5) - 0.1080774142196007991746827e0 * c(6) - 0.1181561776427343335410349e0 * c(7) -0.8368141434403455353724691e-1 * c(5) + 0.4093499466767054661591066e-1 * c(6) + 0.4274641967636400692133626e-1 * c(7) -0.3576545132696983143406173e-2 * c(6) + 0.7389399124121078682094445e-2 * c(5) - 0.3812853991424095538688273e-2 * c(7); 0.7075642937243715046279337e-1 * c(1) - 0.1845476106024151050283847e0 * c(2) - 0.4364163147111892346990101e-1 * c(4) + 0.2432367907207732460874765e0 * c(5) + 0.1582127073537215443965653e0 * c(6) + 0.1602348578364786307613271e0 * c(7) -0.9091410269992464604926176e-1 * c(1) + 0.1103611313171476425250639e0 * c(4) - 0.1290397544997518887000350e1 * c(5) - 0.6639605248735044787146222e0 * c(6) - 0.6615974464005206184151509e0 * c(7) 0.6327161147136873807796515e-2 * c(1) + 0.1147318200715868527529827e0 * c(2) + 0.1166740554279680007487795e0 * c(4) + 0.2766610808285444037240703e1 * c(5) + 0.1070920689960817104203947e1 * c(6) + 0.1013161391032973057171717e1 * c(7) 0.2013769413884797246646959e-1 * c(1) + 0.1033717994630886401730470e0 * c(2) - 0.2913221621151742724258117e1 * c(5) - 0.8755807343482262259774782e0 * c(6) - 0.6909957183488812426508351e0 * c(7) -0.4671751091575462868310238e-2 * c(1) - 0.2760353365637712827793337e-1 * c(2) - 0.1979290298620869974478871e0 * c(4) + 0.5402985338373433052255418e0 * c(6) + 0.1239177593031911077924537e1 * c(5) + 0.2628038050247358227280031e0 * c(7) -0.1635430866921887819487473e-2 * c(1) - 0.5952475275883259619711594e-2 * c(2) + 0.1964682777744275219350831e-1 * c(4) + 0.3236640012639046600590714e0 * c(5) - 0.4659516693228870973898560e0 * c(6) - 0.2217272720941736859420432e0 * c(7) -0.5111353189352474549563559e-2 * c(4) - 0.5355878163774754346032096e0 * c(5) + 0.3328335104489738933610597e0 * c(6) + 0.2078656591178540157917135e0 * c(7) 0.1824328174134289562208038e0 * c(5) - 0.1059816030196818445908057e0 * c(6) - 0.7645121439374711162999809e-1 * c(7) 0.9209089963443799485648361e-2 * c(6) - 0.1591502818872493167091475e-1 * c(5) + 0.6705938225281132185266388e-2 * c(7); 0.2251991532891353212689574e0 * c(1) - 0.1662748711097054895317080e0 * c(2) + 0.2710530961648671297733465e-1 * c(3) - 0.1916646185968439909125616e0 * c(5) - 0.7684117160199014594442072e-1 * c(6) - 0.8219586949831697575883635e-1 * c(7) -0.2893557395653431666593814e0 * c(1) - 0.2421320004064592721552708e0 * c(3) + 0.1187670255028031027693374e1 * c(5) + 0.3956598149904136332753521e0 * c(6) + 0.3860048921755800000681479e0 * c(7) 0.2013769413884797246646959e-1 * c(1) + 0.1033717994630886401730470e0 * c(2) - 0.2913221621151742724258117e1 * c(5) - 0.8755807343482262259774782e0 * c(6) - 0.6909957183488812426508351e0 * c(7) 0.6409299775987186986730499e-1 * c(1) + 0.9313657638804699948929701e-1 * c(2) + 0.2306367624634749229113646e0 * c(3) + 0.3689440308283716620260816e1 * c(5) + 0.1190550338687608873798462e1 * c(6) + 0.5912479546888856519443605e0 * c(7) -0.1486895819265604128572498e-1 * c(1) - 0.2487040599390160764166412e-1 * c(2) - 0.8712928907711754187084757e-2 * c(3) - 0.1263507837371824205693950e1 * c(6) - 0.3058317397843997326920898e0 * c(7) - 0.1470691926045802954795783e1 * c(5) -0.5205147429855955657625694e-2 * c(1) - 0.5363098747528542488971874e-2 * c(2) - 0.6897142765790609546343709e-2 * c(3) - 0.7857524521667450101721993e0 * c(5) + 0.2291148005423734600066709e0 * c(7) + 0.9977064356292750529201981e0 * c(6) 0.6697297488067662265210608e0 * c(5) - 0.5013247356072127938999311e0 * c(6) - 0.1795161243106645437322408e0 * c(7) -0.2022909060111751565150958e0 * c(5) + 0.1453421858063658498587377e0 * c(6) + 0.5694872020480930665635812e-1 * c(7) -0.1200429618441003833696998e-1 * c(6) - 0.4776915669385923841535432e-2 * c(7) + 0.1678121185379596217850541e-1 * c(5); -0.5224403464202056316702078e-1 * c(1) + 0.4440063948509876221050939e-1 * c(2) - 0.1023976547309387874453988e-2 * c(3) + 0.7403484645316174090533193e-1 * c(4) + 0.1241625568998496895352046e-1 * c(6) + 0.7188652847892601282652228e-1 * c(5) + 0.1379362997104735503447960e-1 * c(7) 0.6712774475803763988977355e-1 * c(1) + 0.9147192682075630179962131e-2 * c(3) - 0.1872196143003808021730728e0 * c(4) - 0.1319358558853174530078498e0 * c(6) - 0.4871575736811911887376923e0 * c(5) - 0.1047516312275448138054418e0 * c(7) -0.4671751091575462868310238e-2 * c(1) - 0.2760353365637712827793337e-1 * c(2) - 0.1979290298620869974478871e0 * c(4) + 0.5402985338373433052255418e0 * c(6) + 0.1239177593031911077924537e1 * c(5) + 0.2628038050247358227280031e0 * c(7) -0.1486895819265604128572498e-1 * c(1) - 0.2487040599390160764166412e-1 * c(2) - 0.8712928907711754187084757e-2 * c(3) - 0.1263507837371824205693950e1 * c(6) - 0.3058317397843997326920898e0 * c(7) - 0.1470691926045802954795783e1 * c(5) 0.3449455095910233625229891e-2 * c(1) + 0.6641183499427826101618457e-2 * c(2) + 0.3291545083271862858501887e-3 * c(3) + 0.3357721707576477199985656e0 * c(4) + 0.2096413329579026439044119e1 * c(6) + 0.2317323204183126854954203e0 * c(7) + 0.6107825764368264576481962e-2 * c(8) + 0.7109125850683376695640722e0 * c(5) 0.1207544072304193806052558e-2 * c(1) + 0.1432116665752147607469646e-2 * c(2) + 0.2605582646183255957264249e-3 * c(3) - 0.3332941113251635390801278e-1 * c(4) - 0.2808241697385532683612407e0 * c(7) - 0.2720908083525083608370563e-1 * c(8) + 0.1045865435682921987447929e0 * c(5) - 0.1348436986667115543203552e1 * c(6) 0.8671038084174692625075159e-2 * c(4) + 0.1736073411355428563685818e0 * c(6) + 0.5331362125287625412555844e-1 * c(8) - 0.2424935262404526301801157e0 * c(5) + 0.1569015257678588270609004e0 * c(7) -0.8631683980217122275970376e-1 * c(6) + 0.2698842360470999243492629e-1 * c(7) + 0.8098194147715651085292754e-1 * c(5) - 0.3276463639080639163926118e-1 * c(8) 0.7462059484530855073291365e-2 * c(6) - 0.8121640361668678949573496e-3 * c(7) + 0.5522702088127090209264064e-3 * c(8) - 0.7202165657176696199260422e-2 * c(5); -0.1828896813877197352675410e-1 * c(1) + 0.9574633163221758060736592e-2 * c(2) - 0.8105784530576404277872603e-3 * c(3) - 0.7348845587775519698437916e-2 * c(4) + 0.1063601949723906997026904e-1 * c(5) - 0.1315967038382618382356495e-1 * c(6) - 0.2117936478838753524581943e-1 * c(7) 0.2349927974590068869356781e-1 * c(1) + 0.7240905383565181316381731e-2 * c(3) + 0.1858378996391679448655070e-1 * c(4) - 0.9289616133938676174345208e-1 * c(5) + 0.1223513270418807666970488e0 * c(6) + 0.1113520320436295033894092e0 * c(7) -0.1635430866921887819487473e-2 * c(1) - 0.5952475275883259619711594e-2 * c(2) + 0.1964682777744275219350831e-1 * c(4) + 0.3236640012639046600590714e0 * c(5) - 0.4659516693228870973898560e0 * c(6) - 0.2217272720941736859420432e0 * c(7) -0.5205147429855955657625694e-2 * c(1) - 0.5363098747528542488971874e-2 * c(2) - 0.6897142765790609546343709e-2 * c(3) - 0.7857524521667450101721993e0 * c(5) + 0.2291148005423734600066709e0 * c(7) + 0.9977064356292750529201981e0 * c(6) 0.1207544072304193806052558e-2 * c(1) + 0.1432116665752147607469646e-2 * c(2) + 0.2605582646183255957264249e-3 * c(3) - 0.3332941113251635390801278e-1 * c(4) - 0.2808241697385532683612407e0 * c(7) - 0.2720908083525083608370563e-1 * c(8) + 0.1045865435682921987447929e0 * c(5) - 0.1348436986667115543203552e1 * c(6) 0.4227226173449345042468960e-3 * c(1) + 0.3088241944378964404772302e-3 * c(2) + 0.2062575706647430620228133e-3 * c(3) + 0.3308343404200968256656458e-2 * c(4) + 0.5828047016405001815804837e0 * c(5) + 0.8054174220366215473556835e0 * c(7) + 0.1338363233410033443348225e0 * c(8) + 0.5555555555555555555555556e-2 * c(9) + 0.1190362071861893051132274e1 * c(6) -0.8607044252686413302647675e-3 * c(4) - 0.1748074708673904989293256e0 * c(5) - 0.3132544850115050165022338e0 * c(8) - 0.2500000000000000000000000e-1 * c(9) - 0.3169166305310429271303167e0 * c(7) - 0.6691607091647929161078591e0 * c(6) 0.3354661791693352108660900e-1 * c(5) - 0.3343620022386971405018586e0 * c(7) + 0.5000000000000000000000000e-1 * c(9) + 0.2169790609807602750804271e0 * c(6) + 0.1838363233410033443348225e0 * c(8) 0.2912518476823004642951502e-1 * c(7) + 0.2279091916474916391629437e-1 * c(8) - 0.3068985997518740530511593e-1 * c(6) - 0.1781799513347360596249022e-2 * c(5) - 0.3055555555555555555555556e-1 * c(9); 0.1911888563316170927411831e-2 * c(4) - 0.4068130355529149936100229e-1 * c(5) + 0.1319674981073749167009902e-1 * c(6) + 0.2557266518123783676349144e-1 * c(7) -0.4834791406446907590553793e-2 * c(4) + 0.2310683832687820403062715e0 * c(5) - 0.1080774142196007991746827e0 * c(6) - 0.1181561776427343335410349e0 * c(7) -0.5111353189352474549563559e-2 * c(4) - 0.5355878163774754346032096e0 * c(5) + 0.3328335104489738933610597e0 * c(6) + 0.2078656591178540157917135e0 * c(7) 0.6697297488067662265210608e0 * c(5) - 0.5013247356072127938999311e0 * c(6) - 0.1795161243106645437322408e0 * c(7) 0.8671038084174692625075159e-2 * c(4) + 0.1736073411355428563685818e0 * c(6) + 0.5331362125287625412555844e-1 * c(8) - 0.2424935262404526301801157e0 * c(5) + 0.1569015257678588270609004e0 * c(7) -0.8607044252686413302647675e-3 * c(4) - 0.1748074708673904989293256e0 * c(5) - 0.3132544850115050165022338e0 * c(8) - 0.2500000000000000000000000e-1 * c(9) - 0.3169166305310429271303167e0 * c(7) - 0.6691607091647929161078591e0 * c(6) 0.2239223735771599178951297e-3 * c(4) + 0.1275437785430956673825710e0 * c(5) + 0.1011699483929608164601067e1 * c(6) + 0.9698817275172575247533506e0 * c(8) + 0.1250000000000000000000000e0 * c(9) + 0.5555555555555555555555556e-2 * c(10) + 0.4823177543031281500117826e0 * c(7) -0.3784113973033012949863031e-1 * c(5) - 0.2997556885134827361576001e0 * c(6) - 0.3000000000000000000000000e0 * c(9) - 0.2500000000000000000000000e-1 * c(10) - 0.3991486867446821178415359e0 * c(7) - 0.4382544850115050165022338e0 * c(8) 0.4698146218022683933926520e-1 * c(6) - 0.2966863787471237458744416e0 * c(8) + 0.5000000000000000000000000e-1 * c(10) + 0.1716355704146006481727960e0 * c(7) + 0.3069346152296258362380356e-2 * c(5) + 0.1750000000000000000000000e0 * c(9); 0.1559652871136785763960685e-1 * c(5) - 0.6486184157331537899459796e-2 * c(6) - 0.9110344554036319740147054e-2 * c(7) -0.8368141434403455353724691e-1 * c(5) + 0.4093499466767054661591066e-1 * c(6) + 0.4274641967636400692133626e-1 * c(7) 0.1824328174134289562208038e0 * c(5) - 0.1059816030196818445908057e0 * c(6) - 0.7645121439374711162999809e-1 * c(7) -0.2022909060111751565150958e0 * c(5) + 0.1453421858063658498587377e0 * c(6) + 0.5694872020480930665635812e-1 * c(7) -0.8631683980217122275970376e-1 * c(6) + 0.2698842360470999243492629e-1 * c(7) + 0.8098194147715651085292754e-1 * c(5) - 0.3276463639080639163926118e-1 * c(8) 0.3354661791693352108660900e-1 * c(5) - 0.3343620022386971405018586e0 * c(7) + 0.5000000000000000000000000e-1 * c(9) + 0.2169790609807602750804271e0 * c(6) + 0.1838363233410033443348225e0 * c(8) -0.3784113973033012949863031e-1 * c(5) - 0.2997556885134827361576001e0 * c(6) - 0.3000000000000000000000000e0 * c(9) - 0.2500000000000000000000000e-1 * c(10) - 0.3991486867446821178415359e0 * c(7) - 0.4382544850115050165022338e0 * c(8) 0.1230328942716804455358698e-1 * c(5) + 0.1183647529645898332481833e0 * c(6) + 0.9410511898227943334189628e0 * c(7) + 0.9500000000000000000000000e0 * c(9) + 0.1250000000000000000000000e0 * c(10) + 0.5555555555555555555555556e-2 * c(11) + 0.5699474344521144554459336e0 * c(8) -0.2308067892671916339568942e-1 * c(6) - 0.2986625053775149497180439e0 * c(7) - 0.3000000000000000000000000e0 * c(10) - 0.2500000000000000000000000e-1 * c(11) - 0.1047734860515050802561078e-2 * c(5) - 0.4272090808352508360837056e0 * c(8) - 0.4250000000000000000000000e0 * c(9); 0.5593983696629863059347067e-3 * c(6) - 0.1384822535100796372263822e-2 * c(5) + 0.8254241654378100663291154e-3 * c(7) -0.3576545132696983143406173e-2 * c(6) + 0.7389399124121078682094445e-2 * c(5) - 0.3812853991424095538688273e-2 * c(7) 0.9209089963443799485648361e-2 * c(6) - 0.1591502818872493167091475e-1 * c(5) + 0.6705938225281132185266388e-2 * c(7) -0.1200429618441003833696998e-1 * c(6) - 0.4776915669385923841535432e-2 * c(7) + 0.1678121185379596217850541e-1 * c(5) 0.7462059484530855073291365e-2 * c(6) - 0.8121640361668678949573496e-3 * c(7) + 0.5522702088127090209264064e-3 * c(8) - 0.7202165657176696199260422e-2 * c(5) 0.2912518476823004642951502e-1 * c(7) + 0.2279091916474916391629437e-1 * c(8) - 0.3068985997518740530511593e-1 * c(6) - 0.1781799513347360596249022e-2 * c(5) - 0.3055555555555555555555556e-1 * c(9) 0.4698146218022683933926520e-1 * c(6) - 0.2966863787471237458744416e0 * c(8) + 0.5000000000000000000000000e-1 * c(10) + 0.1716355704146006481727960e0 * c(7) + 0.3069346152296258362380356e-2 * c(5) + 0.1750000000000000000000000e0 * c(9) -0.2308067892671916339568942e-1 * c(6) - 0.2986625053775149497180439e0 * c(7) - 0.3000000000000000000000000e0 * c(10) - 0.2500000000000000000000000e-1 * c(11) - 0.1047734860515050802561078e-2 * c(5) - 0.4272090808352508360837056e0 * c(8) - 0.4250000000000000000000000e0 * c(9) 0.5139370221149109977041877e-2 * c(6) + 0.1247723215009422001393184e0 * c(7) + 0.9505522702088127090209264e0 * c(8) + 0.9500000000000000000000000e0 * c(10) + 0.1250000000000000000000000e0 * c(11) + 0.5555555555555555555555556e-2 * c(12) + 0.9159362465153641826887659e-4 * c(5) + 0.5611111111111111111111111e0 * c(9);];
-
-        M(m-8:m,m-8:m)=[0.5555555555555555555555556e-2 * c(m-11) + 0.1250000000000000000000000e0 * c(m-10) + 0.9500000000000000000000000e0 * c(m-9) + 0.9505522702088127090209264e0 * c(m-7) + 0.1247205076844361998744053e0 * c(m-6) + 0.5139370221149109977041877e-2 * c(m-5) + 0.5611111111111111111111111e0 * c(m-8) + 0.1434074411575366831819799e-3 * c(m-4) -0.2500000000000000000000000e-1 * c(m-10) - 0.3000000000000000000000000e0 * c(m-9) - 0.2980649679116425253322056e0 * c(m-6) - 0.2308067892671916339568942e-1 * c(m-5) - 0.4250000000000000000000000e0 * c(m-8) - 0.4272090808352508360837056e0 * c(m-7) - 0.1645272326387475188399322e-2 * c(m-4) 0.5000000000000000000000000e-1 * c(m-9) - 0.2966863787471237458744416e0 * c(m-7) + 0.4698146218022683933926520e-1 * c(m-5) + 0.1750000000000000000000000e0 * c(m-8) + 0.1700291833903489463825077e0 * c(m-6) + 0.4675733176547960152668626e-2 * c(m-4) 0.2279091916474916391629437e-1 * c(m-7) + 0.3097763128598982561225538e-1 * c(m-6) - 0.3055555555555555555555556e-1 * c(m-8) - 0.3068985997518740530511593e-1 * c(m-5) - 0.3634246031107139778989373e-2 * c(m-4) 0.5522702088127090209264064e-3 * c(m-7) - 0.3265435411305071914756373e-2 * c(m-6) + 0.7462059484530855073291365e-2 * c(m-5) - 0.4748894282038492179461399e-2 * c(m-4) 0.6272075574042975468177820e-3 * c(m-6) - 0.1200429618441003833696998e-1 * c(m-5) + 0.1137708862700574079015220e-1 * c(m-4) 0.9209089963443799485648361e-2 * c(m-5) - 0.3129629392354775191148163e-3 * c(m-6) - 0.8896127024208321966533544e-2 * c(m-4) -0.3576545132696983143406173e-2 * c(m-5) + 0.4335019854436220306755673e-3 * c(m-6) + 0.3143043147253361112730605e-2 * c(m-4) 0.5593983696629863059347067e-3 * c(m-5) - 0.1446656414398166805849327e-3 * c(m-6) - 0.4147327282231696253497740e-3 * c(m-4); -0.2500000000000000000000000e-1 * c(m-10) - 0.3000000000000000000000000e0 * c(m-9) - 0.2980649679116425253322056e0 * c(m-6) - 0.2308067892671916339568942e-1 * c(m-5) - 0.4250000000000000000000000e0 * c(m-8) - 0.4272090808352508360837056e0 * c(m-7) - 0.1645272326387475188399322e-2 * c(m-4) 0.5555555555555555555555556e-2 * c(m-10) + 0.1250000000000000000000000e0 * c(m-9) + 0.9500000000000000000000000e0 * c(m-8) + 0.9341601509609901526962449e0 * c(m-6) + 0.1183647529645898332481833e0 * c(m-5) + 0.1919432828897222527630486e-1 * c(m-4) + 0.5699474344521144554459336e0 * c(m-7) -0.2500000000000000000000000e-1 * c(m-9) - 0.3000000000000000000000000e0 * c(m-8) - 0.2997556885134827361576001e0 * c(m-5) - 0.5636663150858098975790317e-1 * c(m-4) - 0.4382544850115050165022338e0 * c(m-7) - 0.3806231949664312575822630e0 * c(m-6) 0.5000000000000000000000000e-1 * c(m-8) - 0.3557251496099816106154206e0 * c(m-6) + 0.5490976528821799120017102e-1 * c(m-4) + 0.1838363233410033443348225e0 * c(m-7) + 0.2169790609807602750804271e0 * c(m-5) 0.5528052133944605740009217e-1 * c(m-6) - 0.8631683980217122275970376e-1 * c(m-5) - 0.3276463639080639163926118e-1 * c(m-7) + 0.5268984374242044588776166e-1 * c(m-4) -0.5373770512016897565958305e-2 * c(m-6) + 0.1453421858063658498587377e0 * c(m-5) - 0.1399684152943489522927794e0 * c(m-4) -0.1059816030196818445908057e0 * c(m-5) + 0.1014880675788250237247178e0 * c(m-4) + 0.4493535440856820866087846e-2 * c(m-6) 0.4093499466767054661591066e-1 * c(m-5) - 0.3471075437892810033585296e-1 * c(m-4) - 0.6224240288742446280057699e-2 * c(m-6) -0.6486184157331537899459796e-2 * c(m-5) + 0.4409068609809831485979484e-2 * c(m-4) + 0.2077115547521706413480312e-2 * c(m-6); 0.5000000000000000000000000e-1 * c(m-9) - 0.2966863787471237458744416e0 * c(m-7) + 0.4698146218022683933926520e-1 * c(m-5) + 0.1750000000000000000000000e0 * c(m-8) + 0.1700291833903489463825077e0 * c(m-6) + 0.4675733176547960152668626e-2 * c(m-4) -0.2500000000000000000000000e-1 * c(m-9) - 0.3000000000000000000000000e0 * c(m-8) - 0.2997556885134827361576001e0 * c(m-5) - 0.5636663150858098975790317e-1 * c(m-4) - 0.4382544850115050165022338e0 * c(m-7) - 0.3806231949664312575822630e0 * c(m-6) 0.5555555555555555555555556e-2 * c(m-9) + 0.1250000000000000000000000e0 * c(m-8) + 0.9698817275172575247533506e0 * c(m-7) + 0.1011699483929608164601067e1 * c(m-5) + 0.1773466968705924819112984e0 * c(m-4) + 0.2239223735771599178951297e-3 * c(m-3) + 0.4325148359756313354830552e0 * c(m-6) -0.2500000000000000000000000e-1 * c(m-8) - 0.3132544850115050165022338e0 * c(m-7) - 0.2322389872063761557916742e0 * c(m-4) - 0.8607044252686413302647675e-3 * c(m-3) - 0.2594851141920572702679681e0 * c(m-6) - 0.6691607091647929161078591e0 * c(m-5) 0.5331362125287625412555844e-1 * c(m-7) + 0.1736073411355428563685818e0 * c(m-5) + 0.8671038084174692625075159e-2 * c(m-3) + 0.8084259844422177692569663e-1 * c(m-6) - 0.1664345989168155800449120e0 * c(m-4) -0.5013247356072127938999311e0 * c(m-5) + 0.5021853752328231128475915e0 * c(m-4) - 0.1197175073672143005877150e-1 * c(m-6) 0.3328335104489738933610597e0 * c(m-5) - 0.3179803804558436283847901e0 * c(m-4) - 0.5111353189352474549563559e-2 * c(m-3) - 0.9741776803777790426705996e-2 * c(m-6) -0.1080774142196007991746827e0 * c(m-5) + 0.9941834083648937298100811e-1 * c(m-4) - 0.4834791406446907590553793e-2 * c(m-3) + 0.1349386478955833378422842e-1 * c(m-6) 0.1319674981073749167009902e-1 * c(m-5) - 0.1060554802883657391328704e-1 * c(m-4) + 0.1911888563316170927411831e-2 * c(m-3) - 0.4503090345217088684223814e-2 * c(m-6); 0.2279091916474916391629437e-1 * c(m-7) + 0.3097763128598982561225538e-1 * c(m-6) - 0.3055555555555555555555556e-1 * c(m-8) - 0.3068985997518740530511593e-1 * c(m-5) - 0.3634246031107139778989373e-2 * c(m-4) 0.5000000000000000000000000e-1 * c(m-8) - 0.3557251496099816106154206e0 * c(m-6) + 0.5490976528821799120017102e-1 * c(m-4) + 0.1838363233410033443348225e0 * c(m-7) + 0.2169790609807602750804271e0 * c(m-5) -0.2500000000000000000000000e-1 * c(m-8) - 0.3132544850115050165022338e0 * c(m-7) - 0.2322389872063761557916742e0 * c(m-4) - 0.8607044252686413302647675e-3 * c(m-3) - 0.2594851141920572702679681e0 * c(m-6) - 0.6691607091647929161078591e0 * c(m-5) 0.5555555555555555555555556e-2 * c(m-8) + 0.1338363233410033443348225e0 * c(m-7) + 0.7391887916719206077121040e0 * c(m-6) + 0.6490333320052011212240632e0 * c(m-4) + 0.3308343404200968256656458e-2 * c(m-3) + 0.2062575706647430620228133e-3 * c(m-2) + 0.3088241944378964404772302e-3 * c(m-1) + 0.4227226173449345042468960e-3 * c(m) + 0.1190362071861893051132274e1 * c(m-5) -0.2720908083525083608370563e-1 * c(m-7) - 0.1931148612480615118957263e0 * c(m-6) - 0.3332941113251635390801278e-1 * c(m-3) + 0.2605582646183255957264249e-3 * c(m-2) + 0.1432116665752147607469646e-2 * c(m-1) + 0.1207544072304193806052558e-2 * c(m) - 0.1348436986667115543203552e1 * c(m-5) + 0.1687723507780044227927853e-1 * c(m-4) 0.3590669644811151307464697e-1 * c(m-6) - 0.5925443480724830632401754e0 * c(m-4) - 0.6897142765790609546343709e-2 * c(m-2) - 0.5363098747528542488971874e-2 * c(m-1) - 0.5205147429855955657625694e-2 * c(m) + 0.9977064356292750529201981e0 * c(m-5) 0.7272438906214475928744770e-1 * c(m-4) + 0.1964682777744275219350831e-1 * c(m-3) - 0.5952475275883259619711594e-2 * c(m-1) - 0.1635430866921887819487473e-2 * c(m) + 0.2921234010758621482958052e-1 * c(m-6) - 0.4659516693228870973898560e0 * c(m-5) 0.5891947149681041048896399e-1 * c(m-4) + 0.1858378996391679448655070e-1 * c(m-3) + 0.7240905383565181316381731e-2 * c(m-2) + 0.2349927974590068869356781e-1 * c(m) - 0.4046360079256766884300687e-1 * c(m-6) + 0.1223513270418807666970488e0 * c(m-5) -0.2404661162020836566908542e-1 * c(m-4) - 0.7348845587775519698437916e-2 * c(m-3) - 0.8105784530576404277872603e-3 * c(m-2) + 0.9574633163221758060736592e-2 * c(m-1) - 0.1828896813877197352675410e-1 * c(m) + 0.1350326632905990039353503e-1 * c(m-6) - 0.1315967038382618382356495e-1 * c(m-5); 0.5522702088127090209264064e-3 * c(m-7) - 0.3265435411305071914756373e-2 * c(m-6) + 0.7462059484530855073291365e-2 * c(m-5) - 0.4748894282038492179461399e-2 * c(m-4) 0.5528052133944605740009217e-1 * c(m-6) - 0.8631683980217122275970376e-1 * c(m-5) - 0.3276463639080639163926118e-1 * c(m-7) + 0.5268984374242044588776166e-1 * c(m-4) 0.5331362125287625412555844e-1 * c(m-7) + 0.1736073411355428563685818e0 * c(m-5) + 0.8671038084174692625075159e-2 * c(m-3) + 0.8084259844422177692569663e-1 * c(m-6) - 0.1664345989168155800449120e0 * c(m-4) -0.2720908083525083608370563e-1 * c(m-7) - 0.1931148612480615118957263e0 * c(m-6) - 0.3332941113251635390801278e-1 * c(m-3) + 0.2605582646183255957264249e-3 * c(m-2) + 0.1432116665752147607469646e-2 * c(m-1) + 0.1207544072304193806052558e-2 * c(m) - 0.1348436986667115543203552e1 * c(m-5) + 0.1687723507780044227927853e-1 * c(m-4) 0.6107825764368264576481962e-2 * c(m-7) + 0.1155752633643216628010304e0 * c(m-6) + 0.2096413329579026439044119e1 * c(m-5) + 0.3357721707576477199985656e0 * c(m-3) + 0.3291545083271862858501887e-3 * c(m-2) + 0.6641183499427826101618457e-2 * c(m-1) + 0.3449455095910233625229891e-2 * c(m) + 0.8270696421223286922584620e0 * c(m-4) -0.4995827370863505253765970e-1 * c(m-6) - 0.1263507837371824205693950e1 * c(m-5) - 0.8712928907711754187084757e-2 * c(m-2) - 0.2487040599390160764166412e-1 * c(m-1) - 0.1486895819265604128572498e-1 * c(m) - 0.1726565392121567634950213e1 * c(m-4) 0.5402985338373433052255418e0 * c(m-5) - 0.1979290298620869974478871e0 * c(m-3) - 0.2760353365637712827793337e-1 * c(m-1) - 0.4671751091575462868310238e-2 * c(m) - 0.6952587985456154591014641e-1 * c(m-6) + 0.1571507277911208446562686e1 * c(m-4) -0.1319358558853174530078498e0 * c(m-5) - 0.1872196143003808021730728e0 * c(m-3) + 0.9147192682075630179962131e-2 * c(m-2) + 0.6712774475803763988977355e-1 * c(m) + 0.9630407686703666967100804e-1 * c(m-6) - 0.6882132817757726722141421e0 * c(m-4) 0.1241625568998496895352046e-1 * c(m-5) + 0.7403484645316174090533193e-1 * c(m-3) - 0.1023976547309387874453988e-2 * c(m-2) + 0.4440063948509876221050939e-1 * c(m-1) - 0.5224403464202056316702078e-1 * c(m) - 0.3213800979246298453953842e-1 * c(m-6) + 0.1178181682424363524005403e0 * c(m-4); 0.6272075574042975468177820e-3 * c(m-6) - 0.1200429618441003833696998e-1 * c(m-5) + 0.1137708862700574079015220e-1 * c(m-4) -0.5373770512016897565958305e-2 * c(m-6) + 0.1453421858063658498587377e0 * c(m-5) - 0.1399684152943489522927794e0 * c(m-4) -0.5013247356072127938999311e0 * c(m-5) + 0.5021853752328231128475915e0 * c(m-4) - 0.1197175073672143005877150e-1 * c(m-6) 0.3590669644811151307464697e-1 * c(m-6) - 0.5925443480724830632401754e0 * c(m-4) - 0.6897142765790609546343709e-2 * c(m-2) - 0.5363098747528542488971874e-2 * c(m-1) - 0.5205147429855955657625694e-2 * c(m) + 0.9977064356292750529201981e0 * c(m-5) -0.4995827370863505253765970e-1 * c(m-6) - 0.1263507837371824205693950e1 * c(m-5) - 0.8712928907711754187084757e-2 * c(m-2) - 0.2487040599390160764166412e-1 * c(m-1) - 0.1486895819265604128572498e-1 * c(m) - 0.1726565392121567634950213e1 * c(m-4) 0.2760393423824887721078848e-1 * c(m-6) + 0.1190550338687608873798462e1 * c(m-5) + 0.4253084328734353394994388e1 * c(m-4) + 0.2306367624634749229113646e0 * c(m-2) + 0.9313657638804699948929701e-1 * c(m-1) + 0.6409299775987186986730499e-1 * c(m) -0.8755807343482262259774782e0 * c(m-5) - 0.3645285178085761821545207e1 * c(m-4) + 0.1033717994630886401730470e0 * c(m-1) + 0.2013769413884797246646959e-1 * c(m) + 0.4106783858513785463625543e-1 * c(m-6) 0.3956598149904136332753521e0 * c(m-5) + 0.1630560443616104907615866e1 * c(m-4) - 0.2421320004064592721552708e0 * c(m-2) - 0.2893557395653431666593814e0 * c(m) - 0.5688529641249387985434413e-1 * c(m-6) -0.7684117160199014594442072e-1 * c(m-5) - 0.2928439026361256842196229e0 * c(m-4) + 0.2710530961648671297733465e-1 * c(m-2) - 0.1662748711097054895317080e0 * c(m-1) + 0.2251991532891353212689574e0 * c(m) + 0.1898341454096471754822498e-1 * c(m-6); 0.9209089963443799485648361e-2 * c(m-5) - 0.3129629392354775191148163e-3 * c(m-6) - 0.8896127024208321966533544e-2 * c(m-4) -0.1059816030196818445908057e0 * c(m-5) + 0.1014880675788250237247178e0 * c(m-4) + 0.4493535440856820866087846e-2 * c(m-6) 0.3328335104489738933610597e0 * c(m-5) - 0.3179803804558436283847901e0 * c(m-4) - 0.5111353189352474549563559e-2 * c(m-3) - 0.9741776803777790426705996e-2 * c(m-6) 0.7272438906214475928744770e-1 * c(m-4) + 0.1964682777744275219350831e-1 * c(m-3) - 0.5952475275883259619711594e-2 * c(m-1) - 0.1635430866921887819487473e-2 * c(m) + 0.2921234010758621482958052e-1 * c(m-6) - 0.4659516693228870973898560e0 * c(m-5) 0.5402985338373433052255418e0 * c(m-5) - 0.1979290298620869974478871e0 * c(m-3) - 0.2760353365637712827793337e-1 * c(m-1) - 0.4671751091575462868310238e-2 * c(m) - 0.6952587985456154591014641e-1 * c(m-6) + 0.1571507277911208446562686e1 * c(m-4) -0.8755807343482262259774782e0 * c(m-5) - 0.3645285178085761821545207e1 * c(m-4) + 0.1033717994630886401730470e0 * c(m-1) + 0.2013769413884797246646959e-1 * c(m) + 0.4106783858513785463625543e-1 * c(m-6) 0.1070920689960817104203947e1 * c(m-5) + 0.3717418466925056542408153e1 * c(m-4) + 0.1166740554279680007487795e0 * c(m-3) + 0.1147318200715868527529827e0 * c(m-1) + 0.6327161147136873807796515e-2 * c(m) + 0.6235373239336055200426697e-1 * c(m-6) -0.6639605248735044787146222e0 * c(m-5) - 0.1865625445986772763641423e1 * c(m-4) + 0.1103611313171476425250639e0 * c(m-3) - 0.9091410269992464604926176e-1 * c(m) - 0.8636954541126674177407762e-1 * c(m-6) 0.1582127073537215443965653e0 * c(m-5) + 0.3746489300753517635549495e0 * c(m-4) - 0.4364163147111892346990101e-1 * c(m-3) - 0.1845476106024151050283847e0 * c(m-1) + 0.7075642937243715046279337e-1 * c(m) + 0.2882271848190011329385407e-1 * c(m-6); -0.3576545132696983143406173e-2 * c(m-5) + 0.4335019854436220306755673e-3 * c(m-6) + 0.3143043147253361112730605e-2 * c(m-4) 0.4093499466767054661591066e-1 * c(m-5) - 0.3471075437892810033585296e-1 * c(m-4) - 0.6224240288742446280057699e-2 * c(m-6) -0.1080774142196007991746827e0 * c(m-5) + 0.9941834083648937298100811e-1 * c(m-4) - 0.4834791406446907590553793e-2 * c(m-3) + 0.1349386478955833378422842e-1 * c(m-6) 0.5891947149681041048896399e-1 * c(m-4) + 0.1858378996391679448655070e-1 * c(m-3) + 0.7240905383565181316381731e-2 * c(m-2) + 0.2349927974590068869356781e-1 * c(m) - 0.4046360079256766884300687e-1 * c(m-6) + 0.1223513270418807666970488e0 * c(m-5) -0.1319358558853174530078498e0 * c(m-5) - 0.1872196143003808021730728e0 * c(m-3) + 0.9147192682075630179962131e-2 * c(m-2) + 0.6712774475803763988977355e-1 * c(m) + 0.9630407686703666967100804e-1 * c(m-6) - 0.6882132817757726722141421e0 * c(m-4) 0.3956598149904136332753521e0 * c(m-5) + 0.1630560443616104907615866e1 * c(m-4) - 0.2421320004064592721552708e0 * c(m-2) - 0.2893557395653431666593814e0 * c(m) - 0.5688529641249387985434413e-1 * c(m-6) -0.6639605248735044787146222e0 * c(m-5) - 0.1865625445986772763641423e1 * c(m-4) + 0.1103611313171476425250639e0 * c(m-3) - 0.9091410269992464604926176e-1 * c(m) - 0.8636954541126674177407762e-1 * c(m-6) 0.4681819359722749441073885e0 * c(m-5) + 0.1015239189167790053447110e1 * c(m-4) + 0.1043897828092562609502636e0 * c(m-3) + 0.2542001760457345743492403e0 * c(m-2) + 0.1306332157111667628555907e1 * c(m) + 0.1196351539550049336518187e0 * c(m-6) -0.1195777325611201766551392e0 * c(m-5) - 0.2187310061229745694542609e0 * c(m-4) - 0.4128029838349298819825156e-1 * c(m-3) - 0.2845627370491611369031341e-1 * c(m-2) - 0.1016689339350338144430605e1 * c(m) - 0.3992391469197282238624438e-1 * c(m-6); 0.5593983696629863059347067e-3 * c(m-5) - 0.1446656414398166805849327e-3 * c(m-6) - 0.4147327282231696253497740e-3 * c(m-4) -0.6486184157331537899459796e-2 * c(m-5) + 0.4409068609809831485979484e-2 * c(m-4) + 0.2077115547521706413480312e-2 * c(m-6) 0.1319674981073749167009902e-1 * c(m-5) - 0.1060554802883657391328704e-1 * c(m-4) + 0.1911888563316170927411831e-2 * c(m-3) - 0.4503090345217088684223814e-2 * c(m-6) -0.2404661162020836566908542e-1 * c(m-4) - 0.7348845587775519698437916e-2 * c(m-3) - 0.8105784530576404277872603e-3 * c(m-2) + 0.9574633163221758060736592e-2 * c(m-1) - 0.1828896813877197352675410e-1 * c(m) + 0.1350326632905990039353503e-1 * c(m-6) - 0.1315967038382618382356495e-1 * c(m-5) 0.1241625568998496895352046e-1 * c(m-5) + 0.7403484645316174090533193e-1 * c(m-3) - 0.1023976547309387874453988e-2 * c(m-2) + 0.4440063948509876221050939e-1 * c(m-1) - 0.5224403464202056316702078e-1 * c(m) - 0.3213800979246298453953842e-1 * c(m-6) + 0.1178181682424363524005403e0 * c(m-4) -0.7684117160199014594442072e-1 * c(m-5) - 0.2928439026361256842196229e0 * c(m-4) + 0.2710530961648671297733465e-1 * c(m-2) - 0.1662748711097054895317080e0 * c(m-1) + 0.2251991532891353212689574e0 * c(m) + 0.1898341454096471754822498e-1 * c(m-6) 0.1582127073537215443965653e0 * c(m-5) + 0.3746489300753517635549495e0 * c(m-4) - 0.4364163147111892346990101e-1 * c(m-3) - 0.1845476106024151050283847e0 * c(m-1) + 0.7075642937243715046279337e-1 * c(m) + 0.2882271848190011329385407e-1 * c(m-6) -0.1195777325611201766551392e0 * c(m-5) - 0.2187310061229745694542609e0 * c(m-4) - 0.4128029838349298819825156e-1 * c(m-3) - 0.2845627370491611369031341e-1 * c(m-2) - 0.1016689339350338144430605e1 * c(m) - 0.3992391469197282238624438e-1 * c(m-6) 0.3167964748016105299646518e-1 * c(m-5) + 0.4976563420877041544013670e-1 * c(m-4) + 0.1632404042590951953384672e-1 * c(m-3) + 0.3185519088796429015220016e-2 * c(m-2) + 0.2968472090638000742888467e0 * c(m-1) + 0.7912667594695582093926295e0 * c(m) + 0.1332316557164627464149716e-1 * c(m-6);];
-
-        M(5,10)=M(10,5);
-        M(m-4,m-9)=M(m-9,m-4);
-
-        M=M/h;
-
-        D2=HI*(-M-diag(c)*e_1*S_1'+diag(c)*e_m*S_m');
-    end
-    D2 = @D2_fun;
-
-    S2_U=[0.35e2 / 0.12e2 -0.26e2 / 0.3e1 0.19e2 / 0.2e1 -0.14e2 / 0.3e1 0.11e2 / 0.12e2;]/h^2;
-    S2_1=sparse(1,m);
-    S2_1(1:5)=S2_U;
-    S2_m=sparse(1,m);
-    S2_m(m-4:m)=fliplr(S2_U);
-    S2_1 = S2_1';
-    S2_m = S2_m';
-
-
-
-
-
-    % Fourth derivative, 1th order accurate at first 8 boundary points (still
-    % yield 5th order convergence if stable: for example u_tt=-u_xxxx
-
-    m4=7/240;m3=-2/5;m2=169/60;m1=-122/15;m0=91/8;
-%     M4=m4*(diag(ones(m-4,1),4)+diag(ones(m-4,1),-4))+m3*(diag(ones(m-3,1),3)+diag(ones(m-3,1),-3))+m2*(diag(ones(m-2,1),2)+diag(ones(m-2,1),-2))+m1*(diag(ones(m-1,1),1)+diag(ones(m-1,1),-1))+m0*diag(ones(m,1),0);
-    stencil = [m4,m3,m2,m1,m0,m1,m2,m3,m4];
-    d = (length(stencil)-1)/2;
-    diags = -d:d;
-    M4 = stripeMatrix(stencil, diags, m);
-
-    %M4=(-1/6*(diag(ones(m-3,1),3)+diag(ones(m-3,1),-3) ) + 2*(diag(ones(m-2,1),2)+diag(ones(m-2,1),-2)) -13/2*(diag(ones(m-1,1),1)+diag(ones(m-1,1),-1)) + 28/3*diag(ones(m,1),0));
-
-    M4_U=[0.1394226315049e13 / 0.367201486080e12 -0.1137054563243e13 / 0.114750464400e12 0.16614189027367e14 / 0.1836007430400e13 -0.1104821700277e13 / 0.306001238400e12 0.1355771086763e13 / 0.1836007430400e13 -0.27818686453e11 / 0.459001857600e12 -0.40671054239e11 / 0.1836007430400e13 0.5442887371e10 / 0.306001238400e12; -0.1137054563243e13 / 0.114750464400e12 0.70616795535409e14 / 0.2570410402560e13 -0.173266854731041e15 / 0.6426026006400e13 0.28938615291031e14 / 0.2570410402560e13 -0.146167361863e12 / 0.71400288960e11 0.2793470836571e13 / 0.12852052012800e14 0.6219558097e10 / 0.428401733760e12 -0.7313844559e10 / 0.166909766400e12; 0.16614189027367e14 / 0.1836007430400e13 -0.173266854731041e15 / 0.6426026006400e13 0.378613061504779e15 / 0.12852052012800e14 -0.9117069604217e13 / 0.642602600640e12 0.632177582849e12 / 0.233673672960e12 -0.1057776382577e13 / 0.6426026006400e13 0.443019868399e12 / 0.4284017337600e13 -0.3707981e7 / 0.2318191200e10; -0.1104821700277e13 / 0.306001238400e12 0.28938615291031e14 / 0.2570410402560e13 -0.9117069604217e13 / 0.642602600640e12 0.5029150721885e13 / 0.514082080512e12 -0.5209119714341e13 / 0.1285205201280e13 0.12235427457469e14 / 0.12852052012800e14 -0.13731270505e11 / 0.64260260064e11 0.2933596129e10 / 0.40800165120e11; 0.1355771086763e13 / 0.1836007430400e13 -0.146167361863e12 / 0.71400288960e11 0.632177582849e12 / 0.233673672960e12 -0.5209119714341e13 / 0.1285205201280e13 0.14871726798559e14 / 0.2570410402560e13 -0.7504337615347e13 / 0.1606506501600e13 0.310830296467e12 / 0.171360693504e12 -0.55284274391e11 / 0.183600743040e12; -0.27818686453e11 / 0.459001857600e12 0.2793470836571e13 / 0.12852052012800e14 -0.1057776382577e13 / 0.6426026006400e13 0.12235427457469e14 / 0.12852052012800e14 -0.7504337615347e13 / 0.1606506501600e13 0.106318657014853e15 / 0.12852052012800e14 -0.14432772918527e14 / 0.2142008668800e13 0.58102695589e11 / 0.22666758400e11; -0.40671054239e11 / 0.1836007430400e13 0.6219558097e10 / 0.428401733760e12 0.443019868399e12 / 0.4284017337600e13 -0.13731270505e11 / 0.64260260064e11 0.310830296467e12 / 0.171360693504e12 -0.14432772918527e14 / 0.2142008668800e13 0.27102479467823e14 / 0.2570410402560e13 -0.1216032192203e13 / 0.153000619200e12; 0.5442887371e10 / 0.306001238400e12 -0.7313844559e10 / 0.166909766400e12 -0.3707981e7 / 0.2318191200e10 0.2933596129e10 / 0.40800165120e11 -0.55284274391e11 / 0.183600743040e12 0.58102695589e11 / 0.22666758400e11 -0.1216032192203e13 / 0.153000619200e12 0.20799922829107e14 / 0.1836007430400e13;];
-
-    M4(1:8,1:8)=M4_U;
-
-    M4(m-7:m,m-7:m)=rot90(  M4_U ,2 );
-    M4=M4/h^3;
-
-    S3_U=[-0.5e1 / 0.2e1 9 -12 7 -0.3e1 / 0.2e1;]/h^3;
-    S3_1=sparse(1,m);
-    S3_1(1:5)=S3_U;
-    S3_m=sparse(1,m);
-    S3_m(m-4:m)=fliplr(-S3_U);
-    S3_1 = S3_1';
-    S3_m = S3_m';
-
-    D4=HI*(M4-e_1*S3_1'+e_m*S3_m'  + S_1*S2_1'-S_m*S2_m');
-
-end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/+implementations/d4_lonely_4_min_boundary_points.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+sbp/+implementations/d4_lonely_4_min_boundary_points.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,81 @@
+function [H, HI, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = d4_variable_4_min_boundary_points(m,h)
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    %%% 4:de ordn. SBP Finita differens         %%%
+    %%% operatorer framtagna av Mark Carpenter  %%%
+    %%%                                         %%%
+    %%% H           (Normen)                    %%%
+    %%% D1=H^(-1)Q  (approx f?rsta derivatan)   %%%
+    %%% D2          (approx andra derivatan)    %%%
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    %H?r med endast 4 randpunkter
+
+
+    BP = 4;
+    if(m<2*BP)
+        error(['Operator requires at least ' num2str(2*BP) ' grid points']);
+    end
+
+
+    % Norm
+    Hv = ones(m,1);
+    Hv(1:4) = [17/48 59/48 43/48 49/48];
+    Hv(m-3:m) = rot90(Hv(1:4),2);
+    Hv = h*Hv;
+    H = spdiag(Hv, 0);
+    HI = spdiag(1./Hv, 0);
+
+
+    % Boundary operators
+    e_l = sparse(m,1);
+    e_l(1) = 1;
+    e_r = rot90(e_l, 2);
+
+    d1_l = sparse(m,1);
+    d1_l(1:4) = 1/h*[-11/6 3 -3/2 1/3];
+    d1_r = -rot90(d1_l, 2);
+
+    d2_l = sparse(m,1);
+    d2_l(1:4) = 1/h^2*[2 -5 4 -1];
+    d2_r = rot90(d2_l, 2);
+
+    d3_l = sparse(m,1);
+    d3_l(1:4) = 1/h^3*[-1 3 -3 1];
+    d3_r = -rot90(d3_l, 2);
+
+
+    % First derivative
+    stencil = [1/12 -2/3 0 2/3 -1/12];
+    diags = [-1 0 1];
+
+    Q_U = [
+        0 0.59e2/0.96e2 -0.1e1/0.12e2 -0.1e1/0.32e2;
+         -0.59e2/0.96e2 0 0.59e2/0.96e2 0;
+         0.1e1/0.12e2 -0.59e2/0.96e2 0 0.59e2/0.96e2;
+         0.1e1/0.32e2 0 -0.59e2/0.96e2 0;
+    ];
+
+    Q = stripeMatrix(stencil, diags, m);
+    Q(1:4,1:4)=Q_U;
+    Q(m-3:m,m-3:m) = -rot90(Q_U, 2);
+
+    D1 = HI*(Q - 1/2*e_l*e_l' + 1/2*e_r*e_r');
+
+    % Fourth derivative
+    stencil = [-1/6, 2, -13/2, 28/3, -13/2, 2, -1/6];
+    diags = -3:3;
+    M4 = stripeMatrix(stencil, diags, m);
+
+    M4_U=[
+        0.8e1/0.3e1 -0.37e2/0.6e1 0.13e2/0.3e1 -0.5e1/0.6e1;
+        -0.37e2/0.6e1 0.47e2/0.3e1 -13 0.11e2/0.3e1;
+        0.13e2/0.3e1 -13 0.44e2/0.3e1 -0.47e2/0.6e1;
+        -0.5e1/0.6e1 0.11e2/0.3e1 -0.47e2/0.6e1 0.29e2/0.3e1;
+    ];
+
+
+    M4(1:4,1:4) = M4_U;
+    M4(m-3:m,m-3:m) = rot90(M4_U, 2);
+    M4 = 1/h^3*M4;
+
+    D4=HI*(M4 - e_l*d3_l'+e_r*d3_r' + d1_l*d2_l'-d1_r*d2_r');
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/+implementations/d4_lonely_6_2.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+sbp/+implementations/d4_lonely_6_2.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,76 @@
+function [H, HI, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = d4_variable_6_2(m,h)
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    %%% 6:te ordn. SBP Finita differens         %%%
+    %%% operatorer med diagonal norm            %%%
+    %%% Extension to variable koeff             %%%
+    %%%                                         %%%
+    %%% H           (Normen)                    %%%
+    %%% D1=H^(-1)Q  (approx f?rsta derivatan)   %%%
+    %%% D2          (approx andra derivatan)    %%%
+    %%% D2=HI*(R+C*D*S                          %%%
+    %%%                                         %%%
+    %%% R=-D1'*H*C*D1-RR                        %%%
+    %%%                                         %%%
+    %%% RR ?r dissipation)                      %%%
+    %%% Dissipationen uppbyggd av D4:           %%%
+    %%% DI=D4*B*H*D4                            %%%
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+    % H?r med 6 RP ist?llet f?r 8 f?r D4 operatorn, dock samma randderivator
+    % Denna ?r noggrannare, och har 2a ordningens randdslutning och b?r ge 6te
+    % ordningens konvergens. Hade dock ingen fri parameter att optimera
+
+    BP = 6;
+    if(m<2*BP)
+        error(['Operator requires at least ' num2str(2*BP) ' grid points']);
+    end
+
+    % Norm
+    Hv = ones(m,1);
+    Hv(1:6) = [0.181e3/0.576e3, 0.1343e4/0.960e3, 0.293e3/0.480e3, 0.1811e4/0.1440e4, 0.289e3/0.320e3, 0.65e2/0.64e2];
+    Hv(m-5:m) = rot90(Hv(1:6),2);
+    Hv = h*Hv;
+    H = spdiag(Hv, 0);
+    HI = spdiag(1./Hv, 0);
+
+
+    % Boundary operators
+    e_l = sparse(m,1);
+    e_l(1) = 1;
+    e_r = rot90(e_l, 2);
+
+    d1_l = sparse(m,1);
+    d1_l(1:6) = [-0.137e3/0.60e2 5 -5 0.10e2/0.3e1 -0.5e1/0.4e1 0.1e1/0.5e1;]/h;
+    d1_r = -rot90(d1_l, 2);
+
+    d2_l = sparse(m,1);
+    d2_l(1:6) = [0.15e2/0.4e1 -0.77e2/0.6e1 0.107e3/0.6e1 -13 0.61e2/0.12e2 -0.5e1/0.6e1;]/h^2;
+    d2_r = rot90(d2_l, 2);
+
+    d3_l = sparse(m,1);
+    d3_l(1:6) = [-0.17e2/0.4e1 0.71e2/0.4e1 -0.59e2/0.2e1 0.49e2/0.2e1 -0.41e2/0.4e1 0.7e1/0.4e1;]/h^3;
+    d3_r = -rot90(d3_l, 2);
+
+
+    % Fourth derivative, 1th order accurate at first 8 boundary points (still
+    % yield 5th order convergence if stable: for example u_tt = -u_xxxx
+    stencil = [7/240, -2/5, 169/60, -122/15, 91/8, -122/15, 169/60, -2/5, 7/240];
+    diags = -4:4;
+    M4 = stripeMatrix(stencil, diags, m);
+
+    M4_U = [
+        0.1009e4/0.192e3 -0.7657e4/0.480e3 0.9307e4/0.480e3 -0.509e3/0.40e2 0.4621e4/0.960e3 -0.25e2/0.32e2;
+        -0.7657e4/0.480e3 0.49513e5/0.960e3 -0.4007e4/0.60e2 0.21799e5/0.480e3 -0.8171e4/0.480e3 0.2657e4/0.960e3;
+        0.9307e4/0.480e3 -0.4007e4/0.60e2 0.1399e4/0.15e2 -0.2721e4/0.40e2 0.12703e5/0.480e3 -0.521e3/0.120e3;
+        -0.509e3/0.40e2 0.21799e5/0.480e3 -0.2721e4/0.40e2 0.3349e4/0.60e2 -0.389e3/0.15e2 0.559e3/0.96e2;
+        0.4621e4/0.960e3 -0.8171e4/0.480e3 0.12703e5/0.480e3 -0.389e3/0.15e2 0.17857e5/0.960e3 -0.1499e4/0.160e3;
+        -0.25e2/0.32e2 0.2657e4/0.960e3 -0.521e3/0.120e3 0.559e3/0.96e2 -0.1499e4/0.160e3 0.2225e4/0.192e3;
+    ];
+
+
+    M4(1:6,1:6) = M4_U;
+    M4(m-5:m,m-5:m) = rot90(M4_U, 2);
+    M4 = 1/h^3*M4;
+
+    D4=HI*(M4 - e_l*d3_l'+e_r*d3_r' + d1_l*d2_l'-d1_r*d2_r');
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/+implementations/d4_lonely_6_3.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+sbp/+implementations/d4_lonely_6_3.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,70 @@
+function [H, HI, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = d4_variable_6_3(m,h)
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    %%% 6:te ordn. SBP Finita differens         %%%
+    %%% operatorer med diagonal norm            %%%
+    %%% Extension to variable koeff             %%%
+    %%%                                         %%%
+    %%% H           (Normen)                    %%%
+    %%% D1=H^(-1)Q  (approx f?rsta derivatan)   %%%
+    %%% D2          (approx andra derivatan)    %%%
+    %%% D2=HI*(R+C*D*S                          %%%
+    %%%                                         %%%
+    %%% R=-D1'*H*C*D1-RR                        %%%
+    %%%                                         %%%
+    %%% RR ?r dissipation)                      %%%
+    %%% Dissipationen uppbyggd av D4:           %%%
+    %%% DI=D4*B*H*D4                            %%%
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+    % H?r med 7 RP ist?llet f?r 8 f?r D4 operatorn, dock samma randderivator
+    % Denna ?r noggrannare, och har 2a ordningens randdslutning och b?r ge 6te
+    % ordningens konvergens. Hade 2 fria parametrar att optimera
+
+    % Norm
+    Hv = ones(m,1);
+    Hv(1:7) = [0.414837907e9/0.1191965760e10, 0.475278367e9/0.397321920e9, 0.13872751e8/0.12416310e8, 0.346739027e9/0.595982880e9, 0.560227469e9/0.397321920e9, 0.322971631e9/0.397321920e9, 0.616122491e9/0.595982880e9];
+    Hv(m-6:m) = rot90(Hv(1:7),2);
+    Hv = h*Hv;
+    H = spdiag(Hv, 0);
+    HI = spdiag(1./Hv, 0);
+
+
+    % Boundary operators
+    e_l = sparse(m,1);
+    e_l(1) = 1;
+    e_r = rot90(e_l, 2);
+
+    d1_l = sparse(m,1);
+    d1_l(1:6) = [-0.137e3/0.60e2 5 -5 0.10e2/0.3e1 -0.5e1/0.4e1 0.1e1/0.5e1;]/h;
+    d1_r = -rot90(d1_l, 2);
+
+    d2_l = sparse(m,1);
+    d2_l(1:6) = [0.15e2/0.4e1 -0.77e2/0.6e1 0.107e3/0.6e1 -13 0.61e2/0.12e2 -0.5e1/0.6e1;]/h^2;
+    d2_r = rot90(d2_l, 2);
+
+    d3_l = sparse(m,1);
+    d3_l(1:6) = [-0.17e2/0.4e1 0.71e2/0.4e1 -0.59e2/0.2e1 0.49e2/0.2e1 -0.41e2/0.4e1 0.7e1/0.4e1;]/h^3;
+    d3_r = -rot90(d3_l, 2);
+
+
+    % Fourth derivative, 1th order accurate at first 8 boundary points
+    stencil = [7/240, -2/5, 169/60, -122/15, 91/8, -122/15, 169/60, -2/5, 7/240];
+    diags = -4:4;
+    M4 = stripeMatrix(stencil, diags, m);
+
+    M4_U = [
+        0.1399708478939e13/0.263487168000e12 -0.13482796013041e14/0.834376032000e12 0.344344095859e12/0.17565811200e11 -0.3166261424681e13/0.250312809600e12 0.1508605165681e13/0.333750412800e12 -0.486270829441e12/0.834376032000e12 -0.221976356359e12/0.5006256192000e13;
+        -0.13482796013041e14/0.834376032000e12 0.7260475818391e13/0.139062672000e12 -0.27224036353e11/0.406022400e9 0.1847477458951e13/0.41718801600e11 -0.848984558161e12/0.55625068800e11 0.247494925991e12/0.139062672000e12 0.165585445559e12/0.834376032000e12;
+        0.344344095859e12/0.17565811200e11 -0.27224036353e11/0.406022400e9 0.2044938640393e13/0.22250027520e11 -0.1071086785417e13/0.16687520640e11 0.502199537033e12/0.22250027520e11 -0.143589154441e12/0.55625068800e11 -0.88181965559e11/0.333750412800e12;
+        -0.3166261424681e13/0.250312809600e12 0.1847477458951e13/0.41718801600e11 -0.1071086785417e13/0.16687520640e11 0.628860435593e12/0.12515640480e11 -0.73736245829e11/0.3337504128e10 0.195760572271e12/0.41718801600e11 -0.81156046361e11/0.250312809600e12;
+        0.1508605165681e13/0.333750412800e12 -0.848984558161e12/0.55625068800e11 0.502199537033e12/0.22250027520e11 -0.73736245829e11/0.3337504128e10 0.76725285869e11/0.4450005504e10 -0.3912429433e10/0.406022400e9 0.53227370659e11/0.17565811200e11;
+        -0.486270829441e12/0.834376032000e12 0.247494925991e12/0.139062672000e12 -0.143589154441e12/0.55625068800e11 0.195760572271e12/0.41718801600e11 -0.3912429433e10/0.406022400e9 0.1699707221791e13/0.139062672000e12 -0.6959018412841e13/0.834376032000e12;
+        -0.221976356359e12/0.5006256192000e13 0.165585445559e12/0.834376032000e12 -0.88181965559e11/0.333750412800e12 -0.81156046361e11/0.250312809600e12 0.53227370659e11/0.17565811200e11 -0.6959018412841e13/0.834376032000e12 0.3012195053939e13/0.263487168000e12;
+    ];
+
+    M4(1:7,1:7) = M4_U;
+    M4(m-6:m,m-6:m) = rot90(M4_U, 2);
+    M4 = 1/h^3*M4;
+
+    D4=HI*(M4 - e_l*d3_l'+e_r*d3_r' + d1_l*d2_l'-d1_r*d2_r');
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/+implementations/d4_lonely_6_min_boundary_points.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+sbp/+implementations/d4_lonely_6_min_boundary_points.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,74 @@
+function [H, HI, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = d4_variable_6_min_boundary_points(m,h)
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    %%% 6:te ordn. SBP Finita differens         %%%
+    %%% operatorer med diagonal norm            %%%
+    %%% Extension to variable koeff             %%%
+    %%%                                         %%%
+    %%% H           (Normen)                    %%%
+    %%% D1=H^(-1)Q  (approx f?rsta derivatan)   %%%
+    %%% D2          (approx andra derivatan)    %%%
+    %%% D2=HI*(R+C*D*S                          %%%
+    %%%                                         %%%
+    %%% R=-D1'*H*C*D1-RR                        %%%
+    %%%                                         %%%
+    %%% RR ?r dissipation)                      %%%
+    %%% Dissipationen uppbyggd av D4:           %%%
+    %%% DI=D4*B*H*D4                            %%%
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+    % H?r med 6 RP ist?llet f?r 8 f?r D4 operatorn, dock samma randderivator
+
+    BP = 6;
+    if(m<2*BP)
+        error(['Operator requires at least ' num2str(2*BP) ' grid points']);
+    end
+
+    % Norm
+    Hv = ones(m,1);
+    Hv(1:6) = [13649/43200,12013/8640,2711/4320,5359/4320,7877/8640, 43801/43200];
+    Hv(m-5:m) = rot90(Hv(1:6),2);
+    Hv = h*Hv;
+    H = spdiag(Hv, 0);
+    HI = spdiag(1./Hv, 0);
+
+
+    % Boundary operators
+    e_l = sparse(m,1);
+    e_l(1) = 1;
+    e_r = rot90(e_l, 2);
+
+    d1_l = sparse(m,1);
+    d1_l(1:5) = [-25/12, 4, -3, 4/3, -1/4]/h;
+    d1_r = -rot90(d1_l, 2);
+
+    d2_l = sparse(m,1);
+    d2_l(1:5) = [0.35e2/0.12e2 -0.26e2/0.3e1 0.19e2/0.2e1 -0.14e2/0.3e1 0.11e2/0.12e2;]/h^2;
+    d2_r = rot90(d2_l, 2);
+
+    d3_l = sparse(m,1);
+    d3_l(1:5) = [-0.5e1/0.2e1 9 -12 7 -0.3e1/0.2e1;]/h^3;
+    d3_r = -rot90(d3_l, 2);
+
+
+    % Fourth derivative, 1th order accurate at first 8 boundary points (still
+    % yield 5th order convergence if stable: for example u_tt=-u_xxxx
+
+    stencil = [7/240, -2/5, 169/60, -122/15, 91/8, -122/15, 169/60, -2/5, 7/240];
+    diags = -4:4;
+    M4 = stripeMatrix(stencil, diags, m);
+
+    M4_U=[
+        0.3504379e7/0.907200e6 -0.4613983e7/0.453600e6 0.4260437e7/0.453600e6 -0.418577e6/0.113400e6 0.524579e6/0.907200e6 0.535e3/0.18144e5;
+        -0.4613983e7/0.453600e6 0.5186159e7/0.181440e6 -0.81121e5/0.2835e4 0.218845e6/0.18144e5 -0.159169e6/0.90720e5 -0.94669e5/0.907200e6;
+        0.4260437e7/0.453600e6 -0.81121e5/0.2835e4 0.147695e6/0.4536e4 -0.384457e6/0.22680e5 0.339653e6/0.90720e5 -0.18233e5/0.113400e6;
+        -0.418577e6/0.113400e6 0.218845e6/0.18144e5 -0.384457e6/0.22680e5 0.65207e5/0.4536e4 -0.22762e5/0.2835e4 0.1181753e7/0.453600e6;
+        0.524579e6/0.907200e6 -0.159169e6/0.90720e5 0.339653e6/0.90720e5 -0.22762e5/0.2835e4 0.2006171e7/0.181440e6 -0.3647647e7/0.453600e6;
+        0.535e3/0.18144e5 -0.94669e5/0.907200e6 -0.18233e5/0.113400e6 0.1181753e7/0.453600e6 -0.3647647e7/0.453600e6 0.10305271e8/0.907200e6;
+    ];
+
+    M4(1:6,1:6) = M4_U;
+    M4(m-5:m,m-5:m) = rot90(M4_U, 2);
+    M4 = 1/h^3*M4;
+
+    D4=HI*(M4 - e_l*d3_l'+e_r*d3_r' + d1_l*d2_l'-d1_r*d2_r');
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/+implementations/d4_lonely_8_higher_boundary_order.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+sbp/+implementations/d4_lonely_8_higher_boundary_order.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,76 @@
+function [H, HI, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = d4_variable_8_higher_boundary_order(m,h)
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    %%% 8:te ordn. SBP Finita differens         %%%
+    %%% operatorer med diagonal norm            %%%
+    %%%                                         %%%
+    %%%                                         %%%
+    %%% H           (Normen)                    %%%
+    %%% D1=H^(-1)Q  (approx f?rsta derivatan)   %%%
+    %%% D2          (approx andra derivatan)    %%%
+    %%% D2=HI*(R+C*D*S                          %%%
+    %%%                                         %%%
+    %%% R=-D1'*H*C*D1-RR                        %%%
+    %%%                                         %%%
+    %%% RR ?r dissipation)                      %%%
+    %%% Dissipationen uppbyggd av D4:           %%%
+    %%% DI=D4*B*H*D4                            %%%
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    %This is 3rd order accurate at the boundary. Not same norm as D1 operator
+
+    BP = 8;
+    if(m<2*BP)
+        error(['Operator requires at least ' num2str(2*BP) ' grid points']);
+    end
+
+    % Norm
+    Hv = ones(m,1);
+    Hv(1:8) = [0.7488203e7/0.25401600e8, 0.5539027e7/0.3628800e7, 0.308923e6/0.1209600e7, 0.1307491e7/0.725760e6, 0.59407e5/0.145152e6, 0.1548947e7/0.1209600e7, 0.3347963e7/0.3628800e7, 0.25641187e8/0.25401600e8];
+    Hv(m-7:m) = rot90(Hv(1:8),2);
+    Hv = h*Hv;
+    H = spdiag(Hv, 0);
+    HI = spdiag(1./Hv, 0);
+
+
+    % Boundary operators
+    e_l = sparse(m,1);
+    e_l(1) = 1;
+    e_r = rot90(e_l, 2);
+
+    d1_l = sparse(m,1);
+    d1_l(1:7) = [-0.49e2/0.20e2 6 -0.15e2/0.2e1 0.20e2/0.3e1 -0.15e2/0.4e1 0.6e1/0.5e1 -0.1e1/0.6e1]/h;
+    d1_r = -rot90(d1_l, 2);
+
+    d2_l = sparse(m,1);
+    d2_l(1:7) = [0.203e3/0.45e2 -0.87e2/0.5e1 0.117e3/0.4e1 -0.254e3/0.9e1 0.33e2/0.2e1 -0.27e2/0.5e1 0.137e3/0.180e3]/h^2;
+    d2_r = rot90(d2_l, 2);
+
+    d3_l = sparse(m,1);
+    d3_l(1:7) = [-0.49e2/0.8e1 29 -0.461e3/0.8e1 62 -0.307e3/0.8e1 13 -0.15e2/0.8e1]/h^3;
+    d3_r = -rot90(d3_l, 2);
+
+
+
+    % Fourth derivative, 1th order accurate at first 8 boundary points (still
+    % yield 5th order convergence if stable: for example u_tt = -u_xxxx
+
+    stencil = [-0.41e2/0.7560e4, 0.1261e4/0.15120e5, -0.541e3/0.840e3, 0.4369e4/0.1260e4, -0.1669e4/0.180e3, 0.1529e4/0.120e3, -0.1669e4/0.180e3, 0.4369e4/0.1260e4, -0.541e3/0.840e3, 0.1261e4/0.15120e5,-0.41e2/0.7560e4];
+    diags = -5:5;
+    M4 = stripeMatrix(stencil, diags, m);
+
+    M4_U = [
+        0.1031569831e10/0.155675520e9 -0.32874237931e11/0.1452971520e10 0.3069551773e10/0.90810720e8 -0.658395212131e12/0.21794572800e11 0.31068454007e11/0.1816214400e10 -0.39244130657e11/0.7264857600e10 0.1857767503e10/0.2724321600e10 0.1009939e7/0.49420800e8;
+        -0.32874237931e11/0.1452971520e10 0.12799022387e11/0.155675520e9 -0.134456503627e12/0.1037836800e10 0.15366749479e11/0.129729600e9 -0.207640325549e12/0.3113510400e10 0.5396424073e10/0.259459200e9 -0.858079351e9/0.345945600e9 -0.19806607e8/0.170270100e9;
+        0.3069551773e10/0.90810720e8 -0.134456503627e12/0.1037836800e10 0.6202056779e10/0.28828800e8 -0.210970327081e12/0.1037836800e10 0.2127730129e10/0.18532800e8 -0.4048692749e10/0.115315200e9 0.1025943959e10/0.259459200e9 0.71054663e8/0.290594304e9;
+        -0.658395212131e12/0.21794572800e11 0.15366749479e11/0.129729600e9 -0.210970327081e12/0.1037836800e10 0.31025293213e11/0.155675520e9 -0.1147729001e10/0.9884160e7 0.1178067773e10/0.32432400e8 -0.13487255581e11/0.3113510400e10 -0.231082547e9/0.1816214400e10;
+        0.31068454007e11/0.1816214400e10 -0.207640325549e12/0.3113510400e10 0.2127730129e10/0.18532800e8 -0.1147729001e10/0.9884160e7 0.11524865123e11/0.155675520e9 -0.29754506009e11/0.1037836800e10 0.14231221e8/0.2316600e7 -0.15030629699e11/0.21794572800e11;
+        -0.39244130657e11/0.7264857600e10 0.5396424073e10/0.259459200e9 -0.4048692749e10/0.115315200e9 0.1178067773e10/0.32432400e8 -0.29754506009e11/0.1037836800e10 0.572247737e9/0.28828800e8 -0.11322059051e11/0.1037836800e10 0.3345834083e10/0.908107200e9;
+        0.1857767503e10/0.2724321600e10 -0.858079351e9/0.345945600e9 0.1025943959e10/0.259459200e9 -0.13487255581e11/0.3113510400e10 0.14231221e8/0.2316600e7 -0.11322059051e11/0.1037836800e10 0.10478882597e11/0.778377600e9 -0.68446325191e11/0.7264857600e10;
+        0.1009939e7/0.49420800e8 -0.19806607e8/0.170270100e9 0.71054663e8/0.290594304e9 -0.231082547e9/0.1816214400e10 -0.15030629699e11/0.21794572800e11 0.3345834083e10/0.908107200e9 -0.68446325191e11/0.7264857600e10 0.9944747557e10/0.778377600e9;
+    ];
+
+    M4(1:8,1:8) = M4_U;
+    M4(m-7:m,m-7:m) = rot90(M4_U, 2);
+    M4 = 1/h^3*M4;
+
+    D4=HI*(M4 - e_l*d3_l'+e_r*d3_r' + d1_l*d2_l'-d1_r*d2_r');
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/+implementations/d4_lonely_8_min_boundary_points.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+sbp/+implementations/d4_lonely_8_min_boundary_points.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,73 @@
+function [H, HI, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = d4_variable_8_min_boundary_points(m,h)
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    %%% 8:te ordn. SBP Finita differens         %%%
+    %%% operatorer med diagonal norm            %%%
+    %%%                                         %%%
+    %%%                                         %%%
+    %%% H           (Normen)                    %%%
+    %%% D1=H^(-1)Q  (approx f?rsta derivatan)   %%%
+    %%% D2          (approx andra derivatan)    %%%
+    %%% D2=HI*(R+C*D*S                          %%%
+    %%%                                         %%%
+    %%% R=-D1'*H*C*D1-RR                        %%%
+    %%%                                         %%%
+    %%% RR ?r dissipation)                      %%%
+    %%% Dissipationen uppbyggd av D4:           %%%
+    %%% DI=D4*B*H*D4                            %%%
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+    BP = 8;
+    if(m<2*BP)
+        error(['Operator requires at least ' num2str(2*BP) ' grid points']);
+    end
+
+    % Norm
+    Hv = ones(m,1);
+    Hv(1:8) = [1498139/5080320, 1107307/725760, 20761/80640, 1304999/725760, 299527/725760, 103097/80640, 670091/725760, 5127739/5080320];
+    Hv(m-7:m) = rot90(Hv(1:8),2);
+    Hv = h*Hv;
+    H = spdiag(Hv, 0);
+    HI = spdiag(1./Hv, 0);
+
+
+    % Boundary operators
+    e_l = sparse(m,1);
+    e_l(1) = 1;
+    e_r = rot90(e_l, 2);
+
+    d1_l = sparse(m,1);
+    d1_l(1:6) = [-0.137e3/0.60e2 5 -5 0.10e2/0.3e1 -0.5e1/0.4e1 0.1e1/0.5e1;]/h;
+    d1_r = -rot90(d1_l, 2);
+
+    d2_l = sparse(m,1);
+    d2_l(1:6) = [0.15e2/0.4e1 -0.77e2/0.6e1 0.107e3/0.6e1 -13 0.61e2/0.12e2 -0.5e1/0.6e1;]/h^2;
+    d2_r = rot90(d2_l, 2);
+
+    d3_l = sparse(m,1);
+    d3_l(1:6) = [-0.17e2/0.4e1 0.71e2/0.4e1 -0.59e2/0.2e1 0.49e2/0.2e1 -0.41e2/0.4e1 0.7e1/0.4e1;]/h^3;
+    d3_r = -rot90(d3_l, 2);
+
+
+    % Fourth derivative, 1th order accurate at first 8 boundary points
+
+    stencil = [-0.41e2/0.7560e4, 0.1261e4/0.15120e5,-0.541e3/0.840e3,0.4369e4/0.1260e4,-0.1669e4/0.180e3,0.1529e4/0.120e3,-0.1669e4/0.180e3,0.4369e4/0.1260e4,-0.541e3/0.840e3, 0.1261e4/0.15120e5,-0.41e2/0.7560e4];
+    diags = -5:5;
+    M4 = stripeMatrix(stencil, diags, m);
+
+    M4_U = [
+        0.151705142321e12/0.29189160000e11 -0.25643455801727e14/0.1634592960000e13 0.286417898677e12/0.15135120000e11 -0.4038072020317e13/0.326918592000e12 0.96455968907e11/0.20432412000e11 -0.151076916769e12/0.181621440000e12 0.14511526363e11/0.408648240000e12 -0.196663079e9/0.33359040000e11;
+         -0.25643455801727e14/0.1634592960000e13 0.735383382473e12/0.14594580000e11 -0.5035391734409e13/0.77837760000e11 0.20392440917e11/0.467026560e9 -0.109540902413e12/0.6671808000e10 0.2488686539e10/0.884520000e9 -0.2798067539e10/0.33359040000e11 0.6433463591e10/0.408648240000e12;
+         0.286417898677e12/0.15135120000e11 -0.5035391734409e13/0.77837760000e11 0.145019791981e12/0.1621620000e10 -0.333577111061e12/0.5189184000e10 0.18928722391e11/0.778377600e9 -0.93081704557e11/0.25945920000e11 -0.372660319e9/0.3243240000e10 0.2861399869e10/0.544864320000e12;
+         -0.4038072020317e13/0.326918592000e12 0.20392440917e11/0.467026560e9 -0.333577111061e12/0.5189184000e10 0.59368471277e11/0.1167566400e10 -0.201168708569e12/0.9340531200e10 0.1492314487e10/0.432432000e9 0.1911896257e10/0.9340531200e10 0.24383341e8/0.2554051500e10;
+         0.96455968907e11/0.20432412000e11 -0.109540902413e12/0.6671808000e10 0.18928722391e11/0.778377600e9 -0.201168708569e12/0.9340531200e10 0.1451230301e10/0.106142400e9 -0.103548247007e12/0.15567552000e11 0.27808437809e11/0.11675664000e11 -0.36870830713e11/0.65383718400e11;
+         -0.151076916769e12/0.181621440000e12 0.2488686539e10/0.884520000e9 -0.93081704557e11/0.25945920000e11 0.1492314487e10/0.432432000e9 -0.103548247007e12/0.15567552000e11 0.1229498243e10/0.115830000e9 -0.32222519717e11/0.3706560000e10 0.470092704233e12/0.136216080000e12;
+         0.14511526363e11/0.408648240000e12 -0.2798067539e10/0.33359040000e11 -0.372660319e9/0.3243240000e10 0.1911896257e10/0.9340531200e10 0.27808437809e11/0.11675664000e11 -0.32222519717e11/0.3706560000e10 0.11547819313e11/0.912161250e9 -0.15187033999199e14/0.1634592960000e13;
+         -0.196663079e9/0.33359040000e11 0.6433463591e10/0.408648240000e12 0.2861399869e10/0.544864320000e12 0.24383341e8/0.2554051500e10 -0.36870830713e11/0.65383718400e11 0.470092704233e12/0.136216080000e12 -0.15187033999199e14/0.1634592960000e13 0.33832994693e11/0.2653560000e10;
+    ];
+
+    M4(1:8,1:8) = M4_U;
+    M4(m-7:m,m-7:m) = rot90(M4_U, 2);
+    M4 = 1/h^3*M4;
+
+    D4=HI*(M4 - e_l*d3_l'+e_r*d3_r' + d1_l*d2_l'-d1_r*d2_r');
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/+implementations/d4_variable_2.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+sbp/+implementations/d4_variable_2.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,89 @@
+% Returns D2 as a function handle
+function [H, HI, D1, D2, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = d4_variable_2(m,h)
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    %%% 4:de ordn. SBP Finita differens         %%%
+    %%% operatorer framtagna av Ken Mattsson    %%%
+    %%%                                         %%%
+    %%% 6 randpunkter, diagonal norm            %%%
+    %%%                                         %%%
+    %%% Datum: 2013-11-11                       %%%
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+    BP = 2;
+    if(m < 2*BP)
+        error('Operator requires at least %d grid points', 2*BP);
+    end
+
+    % Norm
+    Hv = ones(m,1);
+    Hv(1) = 1/2;
+    Hv(m) = 1/2;
+    Hv = h*Hv;
+    H = spdiag(Hv, 0);
+    HI = spdiag(1./Hv, 0);
+
+    % Boundary operators
+    e_l = sparse(m,1);
+    e_l(1) = 1;
+    e_r = rot90(e_l, 2);
+
+    d1_l = sparse(m,1);
+    d1_l(1:3) = 1/h*[-3/2 2 -1/2];
+    d1_r = -rot90(d1_l, 2);
+
+    d2_l = sparse(m,1);
+    d2_l(1:3) = 1/h^2*[1 -2 1];
+    d2_r = rot90(d2_l, 2);
+
+    d3_l = sparse(m,1);
+    d3_l(1:4) = 1/h^3*[-1 3 -3 1];
+    d3_r = -rot90(d3_l, 2);
+
+
+    % First derivative SBP operator, 1st order accurate at first 6 boundary points
+    stencil = [-1/2, 0, 1/2];
+    diags = [-1 0 1];
+    Q = stripeMatrix(stencil, diags, m);
+
+    D1 = HI*(Q - 1/2*e_l*e_l' + 1/2*e_r*e_r');
+
+    % Second derivative, 1st order accurate at first boundary points
+    M = sparse(m,m);
+
+    scheme_width = 3;
+    scheme_radius = (scheme_width-1)/2;
+    r = (1+scheme_radius):(m-scheme_radius);
+
+    function D2 = D2_fun(c)
+        Mm1 = -c(r-1)/2 - c(r)/2;
+        M0  =  c(r-1)/2 + c(r)   + c(r+1)/2;
+        Mp1 =            -c(r)/2 - c(r+1)/2;
+
+        M(r,:) = spdiags([Mm1 M0 Mp1],0:2*scheme_radius,length(r),m);
+
+        M(1:2,1:2) = [c(1)/2 + c(2)/2 -c(1)/2 - c(2)/2; -c(1)/2 - c(2)/2 c(1)/2 + c(2) + c(3)/2;];
+        M(m-1:m,m-1:m) = [c(m-2)/2 + c(m-1) + c(m)/2 -c(m-1)/2 - c(m)/2; -c(m-1)/2 - c(m)/2 c(m-1)/2 + c(m)/2;];
+        M = 1/h*M;
+
+        D2 = HI*(-M - c(1)*e_l*d1_l' + c(m)*e_r*d1_r');
+    end
+    D2 = @D2_fun;
+
+    % Fourth derivative, 0th order accurate at first 6 boundary points
+    stencil = [1, -4, 6, -4, 1];
+    diags = -2:2;
+    M4 = stripeMatrix(stencil, diags, m);
+
+    M4_U = [
+         0.13e2/0.10e2 -0.12e2/0.5e1   0.9e1/0.10e2   0.1e1/0.5e1;
+        -0.12e2/0.5e1   0.26e2/0.5e1  -0.16e2/0.5e1   0.2e1/0.5e1;
+         0.9e1/0.10e2  -0.16e2/0.5e1   0.47e2/0.10e2 -0.17e2/0.5e1;
+         0.1e1/0.5e1    0.2e1/0.5e1   -0.17e2/0.5e1   0.29e2/0.5e1;
+    ];
+
+    M4(1:4,1:4) = M4_U;
+    M4(m-3:m,m-3:m) = rot90(M4_U, 2);
+    M4 = 1/h^3*M4;
+
+    D4=HI*(M4 - e_l*d3_l'+e_r*d3_r' + d1_l*d2_l'-d1_r*d2_r');
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/+implementations/d4_variable_4.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+sbp/+implementations/d4_variable_4.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,171 @@
+function [H, HI, D1, D2, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = d4_variable_4(m,h)
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    %%% 4:de ordn. SBP Finita differens         %%%
+    %%%                                         %%%
+    %%% H           (Normen)                    %%%
+    %%% D1=H^(-1)Q  (approx f?rsta derivatan)   %%%
+    %%% D2          (approx andra derivatan)    %%%
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+    BP = 6;
+    if(m<2*BP)
+        error(['Operator requires at least ' num2str(2*BP) ' grid points']);
+    end
+
+    % Norm
+    Hv = ones(m,1);
+    Hv(1:4) = [17/48 59/48 43/48 49/48];
+    Hv(m-3:m) = rot90(Hv(1:4),2);
+    Hv = h*Hv;
+    H = spdiag(Hv, 0);
+    HI = spdiag(1./Hv, 0);
+
+
+    % Boundary operators
+    e_l = sparse(m,1);
+    e_l(1) = 1;
+    e_r = rot90(e_l, 2);
+
+    d1_l = sparse(m,1);
+    d1_l(1:4) = 1/h*[-11/6 3 -3/2 1/3];
+    d1_r = -rot90(d1_l, 2);
+
+    d2_l = sparse(m,1);
+    d2_l(1:4) = 1/h^2*[2 -5 4 -1];
+    d2_r = rot90(d2_l, 2);
+
+    d3_l = sparse(m,1);
+    d3_l(1:4) = 1/h^3*[-1 3 -3 1];
+    d3_r = -rot90(d3_l, 2);
+
+
+    % First derivative SBP operator,
+    stencil = [1/12 -2/3 0 2/3 -1/12];
+    diags = -2:2;
+
+    Q_U = [
+        0 0.59e2/0.96e2 -0.1e1/0.12e2 -0.1e1/0.32e2;
+        -0.59e2/0.96e2 0 0.59e2/0.96e2 0;
+        0.1e1/0.12e2 -0.59e2/0.96e2 0 0.59e2/0.96e2;
+        0.1e1/0.32e2 0 -0.59e2/0.96e2 0;
+    ];
+
+    Q = stripeMatrix(stencil, diags, m);
+    Q(1:4,1:4)=Q_U;
+    Q(m-3:m,m-3:m) = -rot90(Q_U, 2);
+
+    D1 = HI*(Q - 1/2*e_l*e_l' + 1/2*e_r*e_r');
+
+
+    % Second derivative
+    M = sparse(m,m);
+
+    scheme_width = 5;
+    scheme_radius = (scheme_width-1)/2;
+    r = (1+scheme_radius):(m-scheme_radius);
+
+    function D2 = D2_fun(c)
+        Mm2 =  c(r-2)/0.8e1 - c(r-1)/0.6e1 + c(r)    /0.8e1                                  ;
+        Mm1 = -c(r-2)/0.6e1 - c(r-1)/0.2e1 - c(r)    /0.2e1 - c(r+1)/0.6e1                 ;
+        M0  =  c(r-2)/2.4e1 + c(r-1)/1.2e0 + c(r)*0.3/0.4   + c(r+1)/1.2e0 + c(r+2)/2.4e1;
+        Mp1 =                -c(r-1)/0.6e1 - c(r)    /0.2e1 - c(r+1)/0.2e1 - c(r+2)/0.6e1;
+        Mp2 =                                c(r)    /0.8e1 - c(r+1)/0.6e1 + c(r+2)/0.8e1;
+
+        M(r,:) = spdiags([Mm2 Mm1 M0 Mp1 Mp2],0:2*scheme_radius,length(r),m);
+
+        M(1:6,1:6) = [
+            0.12e2/0.17e2 * c(1) + 0.59e2/0.192e3 * c(2) + 0.27010400129e11/0.345067064608e12 * c(3) + 0.69462376031e11/0.2070402387648e13 * c(4) -0.59e2/0.68e2 * c(1) - 0.6025413881e10/0.21126554976e11 * c(3) - 0.537416663e9/0.7042184992e10 * c(4) 0.2e1/0.17e2 * c(1) - 0.59e2/0.192e3 * c(2) + 0.213318005e9/0.16049630912e11 * c(4) + 0.2083938599e10/0.8024815456e10 * c(3) 0.3e1/0.68e2 * c(1) - 0.1244724001e10/0.21126554976e11 * c(3) + 0.752806667e9/0.21126554976e11 * c(4) 0.49579087e8/0.10149031312e11 * c(3) - 0.49579087e8/0.10149031312e11 * c(4) -c(4)/0.784e3 + c(3)/0.784e3;
+            -0.59e2/0.68e2 * c(1) - 0.6025413881e10/0.21126554976e11 * c(3) - 0.537416663e9/0.7042184992e10 * c(4) 0.3481e4/0.3264e4 * c(1) + 0.9258282831623875e16/0.7669235228057664e16 * c(3) + 0.236024329996203e15/0.1278205871342944e16 * c(4) -0.59e2/0.408e3 * c(1) - 0.29294615794607e14/0.29725717938208e14 * c(3) - 0.2944673881023e13/0.29725717938208e14 * c(4) -0.59e2/0.1088e4 * c(1) + 0.260297319232891e15/0.2556411742685888e16 * c(3) - 0.60834186813841e14/0.1278205871342944e16 * c(4) -0.1328188692663e13/0.37594290333616e14 * c(3) + 0.1328188692663e13/0.37594290333616e14 * c(4) -0.8673e4/0.2904112e7 * c(3) + 0.8673e4/0.2904112e7 * c(4);
+            0.2e1/0.17e2 * c(1) - 0.59e2/0.192e3 * c(2) + 0.213318005e9/0.16049630912e11 * c(4) + 0.2083938599e10/0.8024815456e10 * c(3) -0.59e2/0.408e3 * c(1) - 0.29294615794607e14/0.29725717938208e14 * c(3) - 0.2944673881023e13/0.29725717938208e14 * c(4) c(1)/0.51e2 + 0.59e2/0.192e3 * c(2) + 0.13777050223300597e17/0.26218083221499456e17 * c(4) + 0.564461e6/0.13384296e8 * c(5) + 0.378288882302546512209e21/0.270764341349677687456e21 * c(3) c(1)/0.136e3 - 0.125059e6/0.743572e6 * c(5) - 0.4836340090442187227e19/0.5525802884687299744e19 * c(3) - 0.17220493277981e14/0.89177153814624e14 * c(4) -0.10532412077335e14/0.42840005263888e14 * c(4) + 0.1613976761032884305e19/0.7963657098519931984e19 * c(3) + 0.564461e6/0.4461432e7 * c(5) -0.960119e6/0.1280713392e10 * c(4) - 0.3391e4/0.6692148e7 * c(5) + 0.33235054191e11/0.26452850508784e14 * c(3);
+            0.3e1/0.68e2 * c(1) - 0.1244724001e10/0.21126554976e11 * c(3) + 0.752806667e9/0.21126554976e11 * c(4) -0.59e2/0.1088e4 * c(1) + 0.260297319232891e15/0.2556411742685888e16 * c(3) - 0.60834186813841e14/0.1278205871342944e16 * c(4) c(1)/0.136e3 - 0.125059e6/0.743572e6 * c(5) - 0.4836340090442187227e19/0.5525802884687299744e19 * c(3) - 0.17220493277981e14/0.89177153814624e14 * c(4) 0.3e1/0.1088e4 * c(1) + 0.507284006600757858213e21/0.475219048083107777984e21 * c(3) + 0.1869103e7/0.2230716e7 * c(5) + c(6)/0.24e2 + 0.1950062198436997e16/0.3834617614028832e16 * c(4) -0.4959271814984644613e19/0.20965546238960637264e20 * c(3) - c(6)/0.6e1 - 0.15998714909649e14/0.37594290333616e14 * c(4) - 0.375177e6/0.743572e6 * c(5) -0.368395e6/0.2230716e7 * c(5) + 0.752806667e9/0.539854092016e12 * c(3) + 0.1063649e7/0.8712336e7 * c(4) + c(6)/0.8e1;
+            0.49579087e8/0.10149031312e11 * c(3) - 0.49579087e8/0.10149031312e11 * c(4) -0.1328188692663e13/0.37594290333616e14 * c(3) + 0.1328188692663e13/0.37594290333616e14 * c(4) -0.10532412077335e14/0.42840005263888e14 * c(4) + 0.1613976761032884305e19/0.7963657098519931984e19 * c(3) + 0.564461e6/0.4461432e7 * c(5) -0.4959271814984644613e19/0.20965546238960637264e20 * c(3) - c(6)/0.6e1 - 0.15998714909649e14/0.37594290333616e14 * c(4) - 0.375177e6/0.743572e6 * c(5) 0.8386761355510099813e19/0.128413970713633903242e21 * c(3) + 0.2224717261773437e16/0.2763180339520776e16 * c(4) + 0.5e1/0.6e1 * c(6) + c(7)/0.24e2 + 0.280535e6/0.371786e6 * c(5) -0.35039615e8/0.213452232e9 * c(4) - c(7)/0.6e1 - 0.13091810925e11/0.13226425254392e14 * c(3) - 0.1118749e7/0.2230716e7 * c(5) - c(6)/0.2e1;
+            -c(4)/0.784e3 + c(3)/0.784e3 -0.8673e4/0.2904112e7 * c(3) + 0.8673e4/0.2904112e7 * c(4) -0.960119e6/0.1280713392e10 * c(4) - 0.3391e4/0.6692148e7 * c(5) + 0.33235054191e11/0.26452850508784e14 * c(3) -0.368395e6/0.2230716e7 * c(5) + 0.752806667e9/0.539854092016e12 * c(3) + 0.1063649e7/0.8712336e7 * c(4) + c(6)/0.8e1 -0.35039615e8/0.213452232e9 * c(4) - c(7)/0.6e1 - 0.13091810925e11/0.13226425254392e14 * c(3) - 0.1118749e7/0.2230716e7 * c(5) - c(6)/0.2e1 0.3290636e7/0.80044587e8 * c(4) + 0.5580181e7/0.6692148e7 * c(5) + 0.5e1/0.6e1 * c(7) + c(8)/0.24e2 + 0.660204843e9/0.13226425254392e14 * c(3) + 0.3e1/0.4e1 * c(6);
+        ];
+
+        M(m-5:m,m-5:m) = [
+            c(m-7)/0.24e2 + 0.5e1/0.6e1 * c(m-6) + 0.5580181e7/0.6692148e7 * c(m-4) + 0.4887707739997e13/0.119037827289528e15 * c(m-3) + 0.3e1/0.4e1 * c(m-5) + 0.660204843e9/0.13226425254392e14 * c(m-2) + 0.660204843e9/0.13226425254392e14 * c(m-1) -c(m-6)/0.6e1 - 0.1618585929605e13/0.9919818940794e13 * c(m-3) - c(m-5)/0.2e1 - 0.1118749e7/0.2230716e7 * c(m-4) - 0.13091810925e11/0.13226425254392e14 * c(m-2) - 0.13091810925e11/0.13226425254392e14 * c(m-1) -0.368395e6/0.2230716e7 * c(m-4) + c(m-5)/0.8e1 + 0.48866620889e11/0.404890569012e12 * c(m-3) + 0.752806667e9/0.539854092016e12 * c(m-2) + 0.752806667e9/0.539854092016e12 * c(m-1) -0.3391e4/0.6692148e7 * c(m-4) - 0.238797444493e12/0.119037827289528e15 * c(m-3) + 0.33235054191e11/0.26452850508784e14 * c(m-2) + 0.33235054191e11/0.26452850508784e14 * c(m-1) -0.8673e4/0.2904112e7 * c(m-2) - 0.8673e4/0.2904112e7 * c(m-1) + 0.8673e4/0.1452056e7 * c(m-3) -c(m-3)/0.392e3 + c(m-2)/0.784e3 + c(m-1)/0.784e3;
+             -c(m-6)/0.6e1 - 0.1618585929605e13/0.9919818940794e13 * c(m-3) - c(m-5)/0.2e1 - 0.1118749e7/0.2230716e7 * c(m-4) - 0.13091810925e11/0.13226425254392e14 * c(m-2) - 0.13091810925e11/0.13226425254392e14 * c(m-1) c(m-6)/0.24e2 + 0.5e1/0.6e1 * c(m-5) + 0.3896014498639e13/0.4959909470397e13 * c(m-3) + 0.8386761355510099813e19/0.128413970713633903242e21 * c(m-2) + 0.280535e6/0.371786e6 * c(m-4) + 0.3360696339136261875e19/0.171218627618178537656e21 * c(m-1) -c(m-5)/0.6e1 - 0.4959271814984644613e19/0.20965546238960637264e20 * c(m-2) - 0.375177e6/0.743572e6 * c(m-4) - 0.13425842714e11/0.33740880751e11 * c(m-3) - 0.193247108773400725e18/0.6988515412986879088e19 * c(m-1) -0.365281640980e12/0.1653303156799e13 * c(m-3) + 0.564461e6/0.4461432e7 * c(m-4) + 0.1613976761032884305e19/0.7963657098519931984e19 * c(m-2) - 0.198407225513315475e18/0.7963657098519931984e19 * c(m-1) -0.1328188692663e13/0.37594290333616e14 * c(m-2) + 0.2226377963775e13/0.37594290333616e14 * c(m-1) - 0.8673e4/0.363014e6 * c(m-3) c(m-3)/0.49e2 + 0.49579087e8/0.10149031312e11 * c(m-2) - 0.256702175e9/0.10149031312e11 * c(m-1);
+             -0.368395e6/0.2230716e7 * c(m-4) + c(m-5)/0.8e1 + 0.48866620889e11/0.404890569012e12 * c(m-3) + 0.752806667e9/0.539854092016e12 * c(m-2) + 0.752806667e9/0.539854092016e12 * c(m-1) -c(m-5)/0.6e1 - 0.4959271814984644613e19/0.20965546238960637264e20 * c(m-2) - 0.375177e6/0.743572e6 * c(m-4) - 0.13425842714e11/0.33740880751e11 * c(m-3) - 0.193247108773400725e18/0.6988515412986879088e19 * c(m-1) c(m-5)/0.24e2 + 0.1869103e7/0.2230716e7 * c(m-4) + 0.507284006600757858213e21/0.475219048083107777984e21 * c(m-2) + 0.3e1/0.1088e4 * c(m) + 0.31688435395e11/0.67481761502e11 * c(m-3) + 0.27769176016102795561e20/0.712828572124661666976e21 * c(m-1) -0.125059e6/0.743572e6 * c(m-4) + c(m)/0.136e3 - 0.23099342648e11/0.101222642253e12 * c(m-3) - 0.4836340090442187227e19/0.5525802884687299744e19 * c(m-2) + 0.193950157930938693e18/0.5525802884687299744e19 * c(m-1) 0.260297319232891e15/0.2556411742685888e16 * c(m-2) - 0.59e2/0.1088e4 * c(m) - 0.106641839640553e15/0.1278205871342944e16 * c(m-1) + 0.26019e5/0.726028e6 * c(m-3) -0.1244724001e10/0.21126554976e11 * c(m-2) + 0.3e1/0.68e2 * c(m) + 0.752806667e9/0.21126554976e11 * c(m-1);
+             -0.3391e4/0.6692148e7 * c(m-4) - 0.238797444493e12/0.119037827289528e15 * c(m-3) + 0.33235054191e11/0.26452850508784e14 * c(m-2) + 0.33235054191e11/0.26452850508784e14 * c(m-1) -0.365281640980e12/0.1653303156799e13 * c(m-3) + 0.564461e6/0.4461432e7 * c(m-4) + 0.1613976761032884305e19/0.7963657098519931984e19 * c(m-2) - 0.198407225513315475e18/0.7963657098519931984e19 * c(m-1) -0.125059e6/0.743572e6 * c(m-4) + c(m)/0.136e3 - 0.23099342648e11/0.101222642253e12 * c(m-3) - 0.4836340090442187227e19/0.5525802884687299744e19 * c(m-2) + 0.193950157930938693e18/0.5525802884687299744e19 * c(m-1) 0.564461e6/0.13384296e8 * c(m-4) + 0.470299699916357e15/0.952302618316224e15 * c(m-3) + 0.550597048646198778781e21/0.1624586048098066124736e22 * c(m-1) + c(m)/0.51e2 + 0.378288882302546512209e21/0.270764341349677687456e21 * c(m-2) -0.59e2/0.408e3 * c(m) - 0.29294615794607e14/0.29725717938208e14 * c(m-2) - 0.2234477713167e13/0.29725717938208e14 * c(m-1) - 0.8673e4/0.363014e6 * c(m-3) -0.59e2/0.3136e4 * c(m-3) - 0.13249937023e11/0.48148892736e11 * c(m-1) + 0.2e1/0.17e2 * c(m) + 0.2083938599e10/0.8024815456e10 * c(m-2);
+             -0.8673e4/0.2904112e7 * c(m-2) - 0.8673e4/0.2904112e7 * c(m-1) + 0.8673e4/0.1452056e7 * c(m-3) -0.1328188692663e13/0.37594290333616e14 * c(m-2) + 0.2226377963775e13/0.37594290333616e14 * c(m-1) - 0.8673e4/0.363014e6 * c(m-3) 0.260297319232891e15/0.2556411742685888e16 * c(m-2) - 0.59e2/0.1088e4 * c(m) - 0.106641839640553e15/0.1278205871342944e16 * c(m-1) + 0.26019e5/0.726028e6 * c(m-3) -0.59e2/0.408e3 * c(m) - 0.29294615794607e14/0.29725717938208e14 * c(m-2) - 0.2234477713167e13/0.29725717938208e14 * c(m-1) - 0.8673e4/0.363014e6 * c(m-3) 0.9258282831623875e16/0.7669235228057664e16 * c(m-2) + 0.3481e4/0.3264e4 * c(m) + 0.228389721191751e15/0.1278205871342944e16 * c(m-1) + 0.8673e4/0.1452056e7 * c(m-3) -0.6025413881e10/0.21126554976e11 * c(m-2) - 0.59e2/0.68e2 * c(m) - 0.537416663e9/0.7042184992e10 * c(m-1);
+             -c(m-3)/0.392e3 + c(m-2)/0.784e3 + c(m-1)/0.784e3 c(m-3)/0.49e2 + 0.49579087e8/0.10149031312e11 * c(m-2) - 0.256702175e9/0.10149031312e11 * c(m-1) -0.1244724001e10/0.21126554976e11 * c(m-2) + 0.3e1/0.68e2 * c(m) + 0.752806667e9/0.21126554976e11 * c(m-1) -0.59e2/0.3136e4 * c(m-3) - 0.13249937023e11/0.48148892736e11 * c(m-1) + 0.2e1/0.17e2 * c(m) + 0.2083938599e10/0.8024815456e10 * c(m-2) -0.6025413881e10/0.21126554976e11 * c(m-2) - 0.59e2/0.68e2 * c(m) - 0.537416663e9/0.7042184992e10 * c(m-1) 0.3e1/0.3136e4 * c(m-3) + 0.27010400129e11/0.345067064608e12 * c(m-2) + 0.234566387291e12/0.690134129216e12 * c(m-1) + 0.12e2/0.17e2 * c(m);
+        ];
+
+        M = M/h;
+        D2 = HI*(-M - c(1)*e_l*d1_l' + c(m)*e_r*d1_r');
+    end
+    D2 = @D2_fun;
+
+
+    % Fourth derivative
+    stencil = [-1/6,2,-13/2, 28/3,-13/2,2,-1/6];
+    diags = -3:3;
+    M4 = stripeMatrix(stencil, diags, m);
+
+    M4_U = [
+        0.5762947e7/0.2316384e7 -0.6374287e7/0.1158192e7 0.573947e6/0.165456e6 -0.124637e6/0.289548e6 0.67979e5/0.2316384e7 -0.60257e5/0.1158192e7;
+        -0.6374287e7/0.1158192e7 0.30392389e8/0.2316384e7 -0.2735053e7/0.289548e6 0.273109e6/0.165456e6 0.83767e5/0.1158192e7 0.245549e6/0.2316384e7;
+        0.573947e6/0.165456e6 -0.2735053e7/0.289548e6 0.5266855e7/0.579096e6 -0.1099715e7/0.289548e6 0.869293e6/0.1158192e7 -0.10195e5/0.144774e6;
+        -0.124637e6/0.289548e6 0.273109e6/0.165456e6 -0.1099715e7/0.289548e6 0.3259225e7/0.579096e6 -0.324229e6/0.72387e5 0.1847891e7/0.1158192e7;
+        0.67979e5/0.2316384e7 0.83767e5/0.1158192e7 0.869293e6/0.1158192e7 -0.324229e6/0.72387e5 0.2626501e7/0.330912e6 -0.7115491e7/0.1158192e7;
+        -0.60257e5/0.1158192e7 0.245549e6/0.2316384e7 -0.10195e5/0.144774e6 0.1847891e7/0.1158192e7 -0.7115491e7/0.1158192e7 0.21383077e8/0.2316384e7;
+    ];
+
+    M4(1:6,1:6) = M4_U;
+    M4(m-5:m,m-5:m) = rot90(M4_U, 2);
+    M4 = 1/h^3*M4;
+
+    D4=HI*(M4 - e_l*d3_l'+e_r*d3_r' + d1_l*d2_l'-d1_r*d2_r');
+end
+
+
+% Alternatives for variable 2nd derivative
+        % % ALTERNATIVES %%%%%%%%%%%%%
+        % % for i=4:m-3
+        % %     M(i,i-2:i+2)=[-c(i-1)/0.6e1 + c(i-2)/0.8e1 + c(i)/0.8e1 -c(i-2)/0.6e1 - c(i+1)/0.6e1 - c(i-1)/0.2e1 - c(i)/0.2e1 c(i-2)/0.24e2 + 0.5e1/0.6e1 * c(i-1) + 0.5e1/0.6e1 * c(i+1) + c(i+2)/0.24e2 + 0.3e1/0.4e1 * c(i) -c(i-1)/0.6e1 - c(i+2)/0.6e1 - c(i)/0.2e1 - c(i+1)/0.2e1 -c(i+1)/0.6e1 + c(i)/0.8e1 + c(i+2)/0.8e1;];
+        % % end
+        % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+        % % for i=4:m-3
+        % %     M(i,i-2:i+2)= [
+        % %      c(i-2)/0.8e1 - c(i-1)/0.6e1 + c(i)  /0.8e1                                   ,
+        % %     -c(i-2)/0.6e1 - c(i-1)/0.2e1 - c(i)  /0.2e1 - c(i+1)/0.6e1                  ,
+        % %      c(i-2)/2.4e1 + c(i-1)/1.2e0 + c(i) * 0.3/0.4 + c(i+1)/1.2e0 + c(i+2)/2.4e1 ,
+        % %                      -c(i-1)/0.6e1 - c(i)  /0.2e1 - c(i+1)/0.2e1 - c(i+2)/0.6e1 ,
+        % %                                        c(i)  /0.8e1 - c(i+1)/0.6e1 + c(i+2)/0.8e1 ,
+        % %     ];
+        % % end
+        % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+        % Mm2 =  c(r-2)/0.8e1 - c(r-1)/0.6e1 + c(r)  /0.8e1                                  ;
+        % Mm1 = -c(r-2)/0.6e1 - c(r-1)/0.2e1 - c(r)  /0.2e1 - c(r+1)/0.6e1                 ;
+        % M0  =  c(r-2)/2.4e1 + c(r-1)/1.2e0 + c(r) * 0.3/0.4 + c(r+1)/1.2e0 + c(r+2)/2.4e1;
+        % Mp1 =                  -c(r-1)/0.6e1 - c(r)  /0.2e1 - c(r+1)/0.2e1 - c(r+2)/0.6e1;
+        % Mp2 =                                    c(r)  /0.8e1 - c(r+1)/0.6e1 + c(r+2)/0.8e1;
+
+        % M(r,:) = spdiags([Mm2 Mm1 M0 Mp1 Mp2],0:2*scheme_radius,length(r),m);
+        % % M(r,:) = spdiags([Mm2 Mm1 M0 Mp1 Mp2],(-2:2)+scheme_radius,M(r,:)); % This is slower
+        % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+        % % %% Somthing is wrong here!!
+        % % Mm2 =  c(r-2)/0.8e1 - c(r-1)/0.6e1 + c(r)  /0.8e1                                  ;
+        % % Mm1 = -c(r-2)/0.6e1 - c(r-1)/0.2e1 - c(r)  /0.2e1 - c(r+1)/0.6e1                 ;
+        % % M0  =  c(r-2)/2.4e1 + c(r-1)/1.2e0 + c(r) * 0.3/0.4 + c(r+1)/1.2e0 + c(r+2)/2.4e1;
+        % % Mp1 =                  -c(r-1)/0.6e1 - c(r)  /0.2e1 - c(r+1)/0.2e1 - c(r+2)/0.6e1;
+        % % Mp2 =                                    c(r)  /0.8e1 - c(r+1)/0.6e1 + c(r+2)/0.8e1;
+        % % % printSize(M_diag_ind);
+        % % % Mdiags = [Mm2 Mm1 M0  Mp1 Mp2];
+        % % % printSize(Mdiags);
+        % % M(M_diag_ind) = [Mm2 Mm1 M0  Mp1 Mp2]; % This is slightly faster
+        % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+        % % Kan man skriva det som en multiplikation av en 3-dim matris?
+        % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+
+
+
+
+
+
+
+
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/+implementations/d4_variable_6.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+sbp/+implementations/d4_variable_6.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,158 @@
+function [H, HI, D1, D2, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = d4_variable_6(m,h)
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    %%% 6:te ordn. SBP Finita differens         %%%
+    %%% operatorer med diagonal norm            %%%
+    %%% Extension to variable koeff             %%%
+    %%%                                         %%%
+    %%% H           (Normen)                    %%%
+    %%% D1=H^(-1)Q  (approx f?rsta derivatan)   %%%
+    %%% D2          (approx andra derivatan)    %%%
+    %%% D2=HI*(R+C*D*S                          %%%
+    %%%                                         %%%
+    %%% R=-D1'*H*C*D1-RR                        %%%
+    %%%                                         %%%
+    %%% RR ?r dissipation)                      %%%
+    %%% Dissipationen uppbyggd av D4:           %%%
+    %%% DI=D4*B*H*D4                            %%%
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+    BP = 9;
+    if(m<2*BP)
+        error(['Operator requires at least ' num2str(2*BP) ' grid points']);
+    end
+
+    % Norm
+    Hv = ones(m,1);
+    Hv(1:6) = [13649/43200,12013/8640,2711/4320,5359/4320,7877/8640, 43801/43200];
+    Hv(m-5:m) = rot90(Hv(1:6),2);
+    Hv = h*Hv;
+    H = spdiag(Hv, 0);
+    HI = spdiag(1./Hv, 0);
+
+
+    % Boundary operators
+    e_l = sparse(m,1);
+    e_l(1) = 1;
+    e_r = rot90(e_l, 2);
+
+    d1_l = sparse(m,1);
+    d1_l(1:5) = [-25/12, 4, -3, 4/3, -1/4]/h;
+    d1_r = -rot90(d1_l, 2);
+
+    d2_l = sparse(m,1);
+    d2_l(1:5) = [0.35e2/0.12e2 -0.26e2/0.3e1 0.19e2/0.2e1 -0.14e2/0.3e1 0.11e2/0.12e2;]/h^2;
+    d2_r = rot90(d2_l, 2);
+
+    d3_l = sparse(m,1);
+    d3_l(1:5) = [-5/2 9 -12 7 -3/2]/h^3;
+    d3_r = -rot90(d3_l, 2);
+
+
+    % First derivtive
+    x1=0.70127127127127;
+
+
+    D1=(1/60*diag(ones(m-3,1),3)-9/60*diag(ones(m-2,1),2)+45/60*diag(ones(m-1,1),1)-45/60*diag(ones(m-1,1),-1)+9/60*diag(ones(m-2,1),-2)-1/60*diag(ones(m-3,1),-3));
+
+
+
+    D1(1:6,1:9)=[-21600/13649, 43200/13649*x1-7624/40947, -172800/13649*x1+ ...
+    	     715489/81894, 259200/13649*x1-187917/13649, -172800/13649* ...
+    	     x1+735635/81894, 43200/13649*x1-89387/40947, 0, 0, 0; ...
+    	     -8640/12013*x1+7624/180195, 0, 86400/12013*x1-57139/12013, ...
+    	     -172800/12013*x1+745733/72078, 129600/12013*x1-91715/12013, ...
+    	     -34560/12013*x1+240569/120130, 0, 0, 0; ...
+             17280/2711*x1-715489/162660, -43200/2711*x1+57139/5422, 0, ...
+             86400/2711*x1-176839/8133, -86400/2711*x1+242111/10844, ...
+             25920/2711*x1-182261/27110, 0, 0, 0; ...
+             -25920/5359*x1+187917/53590, 86400/5359*x1-745733/64308, ...
+             -86400/5359*x1+176839/16077, 0, 43200/5359*x1-165041/32154, ...
+             -17280/5359*x1+710473/321540, 72/5359, 0, 0; ...
+             34560/7877*x1-147127/47262, -129600/7877*x1+91715/7877, ...
+             172800/7877*x1-242111/15754, -86400/7877*x1+165041/23631, ...
+             0, 8640/7877*x1, -1296/7877, 144/7877, 0; ...
+             -43200/43801*x1+89387/131403, 172800/43801*x1-240569/87602,...
+             -259200/43801*x1+182261/43801, 172800/43801*x1-710473/262806, ...
+             -43200/43801*x1, 0, 32400/43801, -6480/43801, 720/43801];
+    D1(m-5:m,m-8:m)=rot90( -D1(1:6,1:9),2);
+    D1=D1/h;
+
+
+    % Second derivative
+    M=sparse(m,m);
+
+    scheme_width = 7;
+    scheme_radius = (scheme_width-1)/2;
+    r = (1+scheme_radius):(m-scheme_radius);
+
+    function D2 = D2_fun(c)
+
+        Mm3 =  c(r-2)/0.40e2 + c(r-1)/0.40e2 - 0.11e2/0.360e3 * c(r-3) - 0.11e2/0.360e3 * c(r);
+        Mm2 =  c(r-3)/0.20e2 - 0.3e1/0.10e2 * c(r-1) + c(r+1)/0.20e2 + 0.7e1/0.40e2 * c(r) + 0.7e1/0.40e2 * c(r-2);
+        Mm1 = -c(r-3)/0.40e2 - 0.3e1/0.10e2 * c(r-2) - 0.3e1/0.10e2 * c(r+1) - c(r+2)/0.40e2 - 0.17e2/0.40e2 * c(r) - 0.17e2/0.40e2 * c(r-1);
+        M0 =  c(r-3)/0.180e3 + c(r-2)/0.8e1 + 0.19e2/0.20e2 * c(r-1) + 0.19e2/0.20e2 * c(r+1) + c(r+2)/0.8e1 + c(r+3)/0.180e3 + 0.101e3/0.180e3 * c(r);
+        Mp1 = -c(r-2)/0.40e2 - 0.3e1/0.10e2 * c(r-1) - 0.3e1/0.10e2 * c(r+2) - c(r+3)/0.40e2 - 0.17e2/0.40e2 * c(r) - 0.17e2/0.40e2 * c(r+1);
+        Mp2 =  c(r-1)/0.20e2 - 0.3e1/0.10e2 * c(r+1) + c(r+3)/0.20e2 + 0.7e1/0.40e2 * c(r) + 0.7e1/0.40e2 * c(r+2);
+        Mp3 =  c(r+1)/0.40e2 + c(r+2)/0.40e2 - 0.11e2/0.360e3 * c(r) - 0.11e2/0.360e3 * c(r+3);
+
+        M(r,:) = spdiags([Mm3 Mm2 Mm1 M0 Mp1 Mp2 Mp3],0:2*scheme_radius,length(r),m);
+
+
+        M(1:9,1:9)=[
+            0.7912667594695582093926295e0 * c(1) + 0.2968472090638000742888467e0 * c(2) + 0.3185519088796429015220016e-2 * c(3) + 0.1632404042590951953384672e-1 * c(4) + 0.3160302244094415087693968e-1 * c(5) + 0.3167964748016105299646518e-1 * c(6) + 0.3148577733947253920469418e-1 * c(7) -0.1016689339350338144430605e1 * c(1) - 0.2845627370491611369031341e-1 * c(3) - 0.4128029838349298819825156e-1 * c(4) - 0.1392281451620140507549866e0 * c(5) - 0.1195777325611201766551392e0 * c(6) - 0.1194267756529333410855186e0 * c(7) 0.7075642937243715046279337e-1 * c(1) - 0.1845476106024151050283847e0 * c(2) - 0.4364163147111892346990101e-1 * c(4) + 0.2432367907207732460874765e0 * c(5) + 0.1582127073537215443965653e0 * c(6) + 0.1602348578364786307613271e0 * c(7) 0.2251991532891353212689574e0 * c(1) - 0.1662748711097054895317080e0 * c(2) + 0.2710530961648671297733465e-1 * c(3) - 0.1916646185968439909125616e0 * c(5) - 0.7684117160199014594442072e-1 * c(6) - 0.8219586949831697575883635e-1 * c(7) -0.5224403464202056316702078e-1 * c(1) + 0.4440063948509876221050939e-1 * c(2) - 0.1023976547309387874453988e-2 * c(3) + 0.7403484645316174090533193e-1 * c(4) + 0.1241625568998496895352046e-1 * c(6) + 0.7188652847892601282652228e-1 * c(5) + 0.1379362997104735503447960e-1 * c(7) -0.1828896813877197352675410e-1 * c(1) + 0.9574633163221758060736592e-2 * c(2) - 0.8105784530576404277872603e-3 * c(3) - 0.7348845587775519698437916e-2 * c(4) + 0.1063601949723906997026904e-1 * c(5) - 0.1315967038382618382356495e-1 * c(6) - 0.2117936478838753524581943e-1 * c(7) 0.1911888563316170927411831e-2 * c(4) - 0.4068130355529149936100229e-1 * c(5) + 0.1319674981073749167009902e-1 * c(6) + 0.2557266518123783676349144e-1 * c(7) 0.1559652871136785763960685e-1 * c(5) - 0.6486184157331537899459796e-2 * c(6) - 0.9110344554036319740147054e-2 * c(7) 0.5593983696629863059347067e-3 * c(6) - 0.1384822535100796372263822e-2 * c(5) + 0.8254241654378100663291154e-3 * c(7);
+            -0.1016689339350338144430605e1 * c(1) - 0.2845627370491611369031341e-1 * c(3) - 0.4128029838349298819825156e-1 * c(4) - 0.1392281451620140507549866e0 * c(5) - 0.1195777325611201766551392e0 * c(6) - 0.1194267756529333410855186e0 * c(7) 0.1306332157111667628555907e1 * c(1) + 0.2542001760457345743492403e0 * c(3) + 0.1043897828092562609502636e0 * c(4) + 0.6672328021032112950919876e0 * c(5) + 0.4681819359722749441073885e0 * c(6) + 0.4676415410195836920069412e0 * c(7) -0.9091410269992464604926176e-1 * c(1) + 0.1103611313171476425250639e0 * c(4) - 0.1290397544997518887000350e1 * c(5) - 0.6639605248735044787146222e0 * c(6) - 0.6615974464005206184151509e0 * c(7) -0.2893557395653431666593814e0 * c(1) - 0.2421320004064592721552708e0 * c(3) + 0.1187670255028031027693374e1 * c(5) + 0.3956598149904136332753521e0 * c(6) + 0.3860048921755800000681479e0 * c(7) 0.6712774475803763988977355e-1 * c(1) + 0.9147192682075630179962131e-2 * c(3) - 0.1872196143003808021730728e0 * c(4) - 0.1319358558853174530078498e0 * c(6) - 0.4871575736811911887376923e0 * c(5) - 0.1047516312275448138054418e0 * c(7) 0.2349927974590068869356781e-1 * c(1) + 0.7240905383565181316381731e-2 * c(3) + 0.1858378996391679448655070e-1 * c(4) - 0.9289616133938676174345208e-1 * c(5) + 0.1223513270418807666970488e0 * c(6) + 0.1113520320436295033894092e0 * c(7) -0.4834791406446907590553793e-2 * c(4) + 0.2310683832687820403062715e0 * c(5) - 0.1080774142196007991746827e0 * c(6) - 0.1181561776427343335410349e0 * c(7) -0.8368141434403455353724691e-1 * c(5) + 0.4093499466767054661591066e-1 * c(6) + 0.4274641967636400692133626e-1 * c(7) -0.3576545132696983143406173e-2 * c(6) + 0.7389399124121078682094445e-2 * c(5) - 0.3812853991424095538688273e-2 * c(7);
+            0.7075642937243715046279337e-1 * c(1) - 0.1845476106024151050283847e0 * c(2) - 0.4364163147111892346990101e-1 * c(4) + 0.2432367907207732460874765e0 * c(5) + 0.1582127073537215443965653e0 * c(6) + 0.1602348578364786307613271e0 * c(7) -0.9091410269992464604926176e-1 * c(1) + 0.1103611313171476425250639e0 * c(4) - 0.1290397544997518887000350e1 * c(5) - 0.6639605248735044787146222e0 * c(6) - 0.6615974464005206184151509e0 * c(7) 0.6327161147136873807796515e-2 * c(1) + 0.1147318200715868527529827e0 * c(2) + 0.1166740554279680007487795e0 * c(4) + 0.2766610808285444037240703e1 * c(5) + 0.1070920689960817104203947e1 * c(6) + 0.1013161391032973057171717e1 * c(7) 0.2013769413884797246646959e-1 * c(1) + 0.1033717994630886401730470e0 * c(2) - 0.2913221621151742724258117e1 * c(5) - 0.8755807343482262259774782e0 * c(6) - 0.6909957183488812426508351e0 * c(7) -0.4671751091575462868310238e-2 * c(1) - 0.2760353365637712827793337e-1 * c(2) - 0.1979290298620869974478871e0 * c(4) + 0.5402985338373433052255418e0 * c(6) + 0.1239177593031911077924537e1 * c(5) + 0.2628038050247358227280031e0 * c(7) -0.1635430866921887819487473e-2 * c(1) - 0.5952475275883259619711594e-2 * c(2) + 0.1964682777744275219350831e-1 * c(4) + 0.3236640012639046600590714e0 * c(5) - 0.4659516693228870973898560e0 * c(6) - 0.2217272720941736859420432e0 * c(7) -0.5111353189352474549563559e-2 * c(4) - 0.5355878163774754346032096e0 * c(5) + 0.3328335104489738933610597e0 * c(6) + 0.2078656591178540157917135e0 * c(7) 0.1824328174134289562208038e0 * c(5) - 0.1059816030196818445908057e0 * c(6) - 0.7645121439374711162999809e-1 * c(7) 0.9209089963443799485648361e-2 * c(6) - 0.1591502818872493167091475e-1 * c(5) + 0.6705938225281132185266388e-2 * c(7);
+            0.2251991532891353212689574e0 * c(1) - 0.1662748711097054895317080e0 * c(2) + 0.2710530961648671297733465e-1 * c(3) - 0.1916646185968439909125616e0 * c(5) - 0.7684117160199014594442072e-1 * c(6) - 0.8219586949831697575883635e-1 * c(7) -0.2893557395653431666593814e0 * c(1) - 0.2421320004064592721552708e0 * c(3) + 0.1187670255028031027693374e1 * c(5) + 0.3956598149904136332753521e0 * c(6) + 0.3860048921755800000681479e0 * c(7) 0.2013769413884797246646959e-1 * c(1) + 0.1033717994630886401730470e0 * c(2) - 0.2913221621151742724258117e1 * c(5) - 0.8755807343482262259774782e0 * c(6) - 0.6909957183488812426508351e0 * c(7) 0.6409299775987186986730499e-1 * c(1) + 0.9313657638804699948929701e-1 * c(2) + 0.2306367624634749229113646e0 * c(3) + 0.3689440308283716620260816e1 * c(5) + 0.1190550338687608873798462e1 * c(6) + 0.5912479546888856519443605e0 * c(7) -0.1486895819265604128572498e-1 * c(1) - 0.2487040599390160764166412e-1 * c(2) - 0.8712928907711754187084757e-2 * c(3) - 0.1263507837371824205693950e1 * c(6) - 0.3058317397843997326920898e0 * c(7) - 0.1470691926045802954795783e1 * c(5) -0.5205147429855955657625694e-2 * c(1) - 0.5363098747528542488971874e-2 * c(2) - 0.6897142765790609546343709e-2 * c(3) - 0.7857524521667450101721993e0 * c(5) + 0.2291148005423734600066709e0 * c(7) + 0.9977064356292750529201981e0 * c(6) 0.6697297488067662265210608e0 * c(5) - 0.5013247356072127938999311e0 * c(6) - 0.1795161243106645437322408e0 * c(7) -0.2022909060111751565150958e0 * c(5) + 0.1453421858063658498587377e0 * c(6) + 0.5694872020480930665635812e-1 * c(7) -0.1200429618441003833696998e-1 * c(6) - 0.4776915669385923841535432e-2 * c(7) + 0.1678121185379596217850541e-1 * c(5);
+            -0.5224403464202056316702078e-1 * c(1) + 0.4440063948509876221050939e-1 * c(2) - 0.1023976547309387874453988e-2 * c(3) + 0.7403484645316174090533193e-1 * c(4) + 0.1241625568998496895352046e-1 * c(6) + 0.7188652847892601282652228e-1 * c(5) + 0.1379362997104735503447960e-1 * c(7) 0.6712774475803763988977355e-1 * c(1) + 0.9147192682075630179962131e-2 * c(3) - 0.1872196143003808021730728e0 * c(4) - 0.1319358558853174530078498e0 * c(6) - 0.4871575736811911887376923e0 * c(5) - 0.1047516312275448138054418e0 * c(7) -0.4671751091575462868310238e-2 * c(1) - 0.2760353365637712827793337e-1 * c(2) - 0.1979290298620869974478871e0 * c(4) + 0.5402985338373433052255418e0 * c(6) + 0.1239177593031911077924537e1 * c(5) + 0.2628038050247358227280031e0 * c(7) -0.1486895819265604128572498e-1 * c(1) - 0.2487040599390160764166412e-1 * c(2) - 0.8712928907711754187084757e-2 * c(3) - 0.1263507837371824205693950e1 * c(6) - 0.3058317397843997326920898e0 * c(7) - 0.1470691926045802954795783e1 * c(5) 0.3449455095910233625229891e-2 * c(1) + 0.6641183499427826101618457e-2 * c(2) + 0.3291545083271862858501887e-3 * c(3) + 0.3357721707576477199985656e0 * c(4) + 0.2096413329579026439044119e1 * c(6) + 0.2317323204183126854954203e0 * c(7) + 0.6107825764368264576481962e-2 * c(8) + 0.7109125850683376695640722e0 * c(5) 0.1207544072304193806052558e-2 * c(1) + 0.1432116665752147607469646e-2 * c(2) + 0.2605582646183255957264249e-3 * c(3) - 0.3332941113251635390801278e-1 * c(4) - 0.2808241697385532683612407e0 * c(7) - 0.2720908083525083608370563e-1 * c(8) + 0.1045865435682921987447929e0 * c(5) - 0.1348436986667115543203552e1 * c(6) 0.8671038084174692625075159e-2 * c(4) + 0.1736073411355428563685818e0 * c(6) + 0.5331362125287625412555844e-1 * c(8) - 0.2424935262404526301801157e0 * c(5) + 0.1569015257678588270609004e0 * c(7) -0.8631683980217122275970376e-1 * c(6) + 0.2698842360470999243492629e-1 * c(7) + 0.8098194147715651085292754e-1 * c(5) - 0.3276463639080639163926118e-1 * c(8) 0.7462059484530855073291365e-2 * c(6) - 0.8121640361668678949573496e-3 * c(7) + 0.5522702088127090209264064e-3 * c(8) - 0.7202165657176696199260422e-2 * c(5);
+            -0.1828896813877197352675410e-1 * c(1) + 0.9574633163221758060736592e-2 * c(2) - 0.8105784530576404277872603e-3 * c(3) - 0.7348845587775519698437916e-2 * c(4) + 0.1063601949723906997026904e-1 * c(5) - 0.1315967038382618382356495e-1 * c(6) - 0.2117936478838753524581943e-1 * c(7) 0.2349927974590068869356781e-1 * c(1) + 0.7240905383565181316381731e-2 * c(3) + 0.1858378996391679448655070e-1 * c(4) - 0.9289616133938676174345208e-1 * c(5) + 0.1223513270418807666970488e0 * c(6) + 0.1113520320436295033894092e0 * c(7) -0.1635430866921887819487473e-2 * c(1) - 0.5952475275883259619711594e-2 * c(2) + 0.1964682777744275219350831e-1 * c(4) + 0.3236640012639046600590714e0 * c(5) - 0.4659516693228870973898560e0 * c(6) - 0.2217272720941736859420432e0 * c(7) -0.5205147429855955657625694e-2 * c(1) - 0.5363098747528542488971874e-2 * c(2) - 0.6897142765790609546343709e-2 * c(3) - 0.7857524521667450101721993e0 * c(5) + 0.2291148005423734600066709e0 * c(7) + 0.9977064356292750529201981e0 * c(6) 0.1207544072304193806052558e-2 * c(1) + 0.1432116665752147607469646e-2 * c(2) + 0.2605582646183255957264249e-3 * c(3) - 0.3332941113251635390801278e-1 * c(4) - 0.2808241697385532683612407e0 * c(7) - 0.2720908083525083608370563e-1 * c(8) + 0.1045865435682921987447929e0 * c(5) - 0.1348436986667115543203552e1 * c(6) 0.4227226173449345042468960e-3 * c(1) + 0.3088241944378964404772302e-3 * c(2) + 0.2062575706647430620228133e-3 * c(3) + 0.3308343404200968256656458e-2 * c(4) + 0.5828047016405001815804837e0 * c(5) + 0.8054174220366215473556835e0 * c(7) + 0.1338363233410033443348225e0 * c(8) + 0.5555555555555555555555556e-2 * c(9) + 0.1190362071861893051132274e1 * c(6) -0.8607044252686413302647675e-3 * c(4) - 0.1748074708673904989293256e0 * c(5) - 0.3132544850115050165022338e0 * c(8) - 0.2500000000000000000000000e-1 * c(9) - 0.3169166305310429271303167e0 * c(7) - 0.6691607091647929161078591e0 * c(6) 0.3354661791693352108660900e-1 * c(5) - 0.3343620022386971405018586e0 * c(7) + 0.5000000000000000000000000e-1 * c(9) + 0.2169790609807602750804271e0 * c(6) + 0.1838363233410033443348225e0 * c(8) 0.2912518476823004642951502e-1 * c(7) + 0.2279091916474916391629437e-1 * c(8) - 0.3068985997518740530511593e-1 * c(6) - 0.1781799513347360596249022e-2 * c(5) - 0.3055555555555555555555556e-1 * c(9);
+            0.1911888563316170927411831e-2 * c(4) - 0.4068130355529149936100229e-1 * c(5) + 0.1319674981073749167009902e-1 * c(6) + 0.2557266518123783676349144e-1 * c(7) -0.4834791406446907590553793e-2 * c(4) + 0.2310683832687820403062715e0 * c(5) - 0.1080774142196007991746827e0 * c(6) - 0.1181561776427343335410349e0 * c(7) -0.5111353189352474549563559e-2 * c(4) - 0.5355878163774754346032096e0 * c(5) + 0.3328335104489738933610597e0 * c(6) + 0.2078656591178540157917135e0 * c(7) 0.6697297488067662265210608e0 * c(5) - 0.5013247356072127938999311e0 * c(6) - 0.1795161243106645437322408e0 * c(7) 0.8671038084174692625075159e-2 * c(4) + 0.1736073411355428563685818e0 * c(6) + 0.5331362125287625412555844e-1 * c(8) - 0.2424935262404526301801157e0 * c(5) + 0.1569015257678588270609004e0 * c(7) -0.8607044252686413302647675e-3 * c(4) - 0.1748074708673904989293256e0 * c(5) - 0.3132544850115050165022338e0 * c(8) - 0.2500000000000000000000000e-1 * c(9) - 0.3169166305310429271303167e0 * c(7) - 0.6691607091647929161078591e0 * c(6) 0.2239223735771599178951297e-3 * c(4) + 0.1275437785430956673825710e0 * c(5) + 0.1011699483929608164601067e1 * c(6) + 0.9698817275172575247533506e0 * c(8) + 0.1250000000000000000000000e0 * c(9) + 0.5555555555555555555555556e-2 * c(10) + 0.4823177543031281500117826e0 * c(7) -0.3784113973033012949863031e-1 * c(5) - 0.2997556885134827361576001e0 * c(6) - 0.3000000000000000000000000e0 * c(9) - 0.2500000000000000000000000e-1 * c(10) - 0.3991486867446821178415359e0 * c(7) - 0.4382544850115050165022338e0 * c(8) 0.4698146218022683933926520e-1 * c(6) - 0.2966863787471237458744416e0 * c(8) + 0.5000000000000000000000000e-1 * c(10) + 0.1716355704146006481727960e0 * c(7) + 0.3069346152296258362380356e-2 * c(5) + 0.1750000000000000000000000e0 * c(9);
+            0.1559652871136785763960685e-1 * c(5) - 0.6486184157331537899459796e-2 * c(6) - 0.9110344554036319740147054e-2 * c(7) -0.8368141434403455353724691e-1 * c(5) + 0.4093499466767054661591066e-1 * c(6) + 0.4274641967636400692133626e-1 * c(7) 0.1824328174134289562208038e0 * c(5) - 0.1059816030196818445908057e0 * c(6) - 0.7645121439374711162999809e-1 * c(7) -0.2022909060111751565150958e0 * c(5) + 0.1453421858063658498587377e0 * c(6) + 0.5694872020480930665635812e-1 * c(7) -0.8631683980217122275970376e-1 * c(6) + 0.2698842360470999243492629e-1 * c(7) + 0.8098194147715651085292754e-1 * c(5) - 0.3276463639080639163926118e-1 * c(8) 0.3354661791693352108660900e-1 * c(5) - 0.3343620022386971405018586e0 * c(7) + 0.5000000000000000000000000e-1 * c(9) + 0.2169790609807602750804271e0 * c(6) + 0.1838363233410033443348225e0 * c(8) -0.3784113973033012949863031e-1 * c(5) - 0.2997556885134827361576001e0 * c(6) - 0.3000000000000000000000000e0 * c(9) - 0.2500000000000000000000000e-1 * c(10) - 0.3991486867446821178415359e0 * c(7) - 0.4382544850115050165022338e0 * c(8) 0.1230328942716804455358698e-1 * c(5) + 0.1183647529645898332481833e0 * c(6) + 0.9410511898227943334189628e0 * c(7) + 0.9500000000000000000000000e0 * c(9) + 0.1250000000000000000000000e0 * c(10) + 0.5555555555555555555555556e-2 * c(11) + 0.5699474344521144554459336e0 * c(8) -0.2308067892671916339568942e-1 * c(6) - 0.2986625053775149497180439e0 * c(7) - 0.3000000000000000000000000e0 * c(10) - 0.2500000000000000000000000e-1 * c(11) - 0.1047734860515050802561078e-2 * c(5) - 0.4272090808352508360837056e0 * c(8) - 0.4250000000000000000000000e0 * c(9);
+            0.5593983696629863059347067e-3 * c(6) - 0.1384822535100796372263822e-2 * c(5) + 0.8254241654378100663291154e-3 * c(7) -0.3576545132696983143406173e-2 * c(6) + 0.7389399124121078682094445e-2 * c(5) - 0.3812853991424095538688273e-2 * c(7) 0.9209089963443799485648361e-2 * c(6) - 0.1591502818872493167091475e-1 * c(5) + 0.6705938225281132185266388e-2 * c(7) -0.1200429618441003833696998e-1 * c(6) - 0.4776915669385923841535432e-2 * c(7) + 0.1678121185379596217850541e-1 * c(5) 0.7462059484530855073291365e-2 * c(6) - 0.8121640361668678949573496e-3 * c(7) + 0.5522702088127090209264064e-3 * c(8) - 0.7202165657176696199260422e-2 * c(5) 0.2912518476823004642951502e-1 * c(7) + 0.2279091916474916391629437e-1 * c(8) - 0.3068985997518740530511593e-1 * c(6) - 0.1781799513347360596249022e-2 * c(5) - 0.3055555555555555555555556e-1 * c(9) 0.4698146218022683933926520e-1 * c(6) - 0.2966863787471237458744416e0 * c(8) + 0.5000000000000000000000000e-1 * c(10) + 0.1716355704146006481727960e0 * c(7) + 0.3069346152296258362380356e-2 * c(5) + 0.1750000000000000000000000e0 * c(9) -0.2308067892671916339568942e-1 * c(6) - 0.2986625053775149497180439e0 * c(7) - 0.3000000000000000000000000e0 * c(10) - 0.2500000000000000000000000e-1 * c(11) - 0.1047734860515050802561078e-2 * c(5) - 0.4272090808352508360837056e0 * c(8) - 0.4250000000000000000000000e0 * c(9) 0.5139370221149109977041877e-2 * c(6) + 0.1247723215009422001393184e0 * c(7) + 0.9505522702088127090209264e0 * c(8) + 0.9500000000000000000000000e0 * c(10) + 0.1250000000000000000000000e0 * c(11) + 0.5555555555555555555555556e-2 * c(12) + 0.9159362465153641826887659e-4 * c(5) + 0.5611111111111111111111111e0 * c(9);
+        ];
+
+        M(m-8:m,m-8:m)=[
+            0.5555555555555555555555556e-2 * c(m-11) + 0.1250000000000000000000000e0 * c(m-10) + 0.9500000000000000000000000e0 * c(m-9) + 0.9505522702088127090209264e0 * c(m-7) + 0.1247205076844361998744053e0 * c(m-6) + 0.5139370221149109977041877e-2 * c(m-5) + 0.5611111111111111111111111e0 * c(m-8) + 0.1434074411575366831819799e-3 * c(m-4) -0.2500000000000000000000000e-1 * c(m-10) - 0.3000000000000000000000000e0 * c(m-9) - 0.2980649679116425253322056e0 * c(m-6) - 0.2308067892671916339568942e-1 * c(m-5) - 0.4250000000000000000000000e0 * c(m-8) - 0.4272090808352508360837056e0 * c(m-7) - 0.1645272326387475188399322e-2 * c(m-4) 0.5000000000000000000000000e-1 * c(m-9) - 0.2966863787471237458744416e0 * c(m-7) + 0.4698146218022683933926520e-1 * c(m-5) + 0.1750000000000000000000000e0 * c(m-8) + 0.1700291833903489463825077e0 * c(m-6) + 0.4675733176547960152668626e-2 * c(m-4) 0.2279091916474916391629437e-1 * c(m-7) + 0.3097763128598982561225538e-1 * c(m-6) - 0.3055555555555555555555556e-1 * c(m-8) - 0.3068985997518740530511593e-1 * c(m-5) - 0.3634246031107139778989373e-2 * c(m-4) 0.5522702088127090209264064e-3 * c(m-7) - 0.3265435411305071914756373e-2 * c(m-6) + 0.7462059484530855073291365e-2 * c(m-5) - 0.4748894282038492179461399e-2 * c(m-4) 0.6272075574042975468177820e-3 * c(m-6) - 0.1200429618441003833696998e-1 * c(m-5) + 0.1137708862700574079015220e-1 * c(m-4) 0.9209089963443799485648361e-2 * c(m-5) - 0.3129629392354775191148163e-3 * c(m-6) - 0.8896127024208321966533544e-2 * c(m-4) -0.3576545132696983143406173e-2 * c(m-5) + 0.4335019854436220306755673e-3 * c(m-6) + 0.3143043147253361112730605e-2 * c(m-4) 0.5593983696629863059347067e-3 * c(m-5) - 0.1446656414398166805849327e-3 * c(m-6) - 0.4147327282231696253497740e-3 * c(m-4);
+            -0.2500000000000000000000000e-1 * c(m-10) - 0.3000000000000000000000000e0 * c(m-9) - 0.2980649679116425253322056e0 * c(m-6) - 0.2308067892671916339568942e-1 * c(m-5) - 0.4250000000000000000000000e0 * c(m-8) - 0.4272090808352508360837056e0 * c(m-7) - 0.1645272326387475188399322e-2 * c(m-4) 0.5555555555555555555555556e-2 * c(m-10) + 0.1250000000000000000000000e0 * c(m-9) + 0.9500000000000000000000000e0 * c(m-8) + 0.9341601509609901526962449e0 * c(m-6) + 0.1183647529645898332481833e0 * c(m-5) + 0.1919432828897222527630486e-1 * c(m-4) + 0.5699474344521144554459336e0 * c(m-7) -0.2500000000000000000000000e-1 * c(m-9) - 0.3000000000000000000000000e0 * c(m-8) - 0.2997556885134827361576001e0 * c(m-5) - 0.5636663150858098975790317e-1 * c(m-4) - 0.4382544850115050165022338e0 * c(m-7) - 0.3806231949664312575822630e0 * c(m-6) 0.5000000000000000000000000e-1 * c(m-8) - 0.3557251496099816106154206e0 * c(m-6) + 0.5490976528821799120017102e-1 * c(m-4) + 0.1838363233410033443348225e0 * c(m-7) + 0.2169790609807602750804271e0 * c(m-5) 0.5528052133944605740009217e-1 * c(m-6) - 0.8631683980217122275970376e-1 * c(m-5) - 0.3276463639080639163926118e-1 * c(m-7) + 0.5268984374242044588776166e-1 * c(m-4) -0.5373770512016897565958305e-2 * c(m-6) + 0.1453421858063658498587377e0 * c(m-5) - 0.1399684152943489522927794e0 * c(m-4) -0.1059816030196818445908057e0 * c(m-5) + 0.1014880675788250237247178e0 * c(m-4) + 0.4493535440856820866087846e-2 * c(m-6) 0.4093499466767054661591066e-1 * c(m-5) - 0.3471075437892810033585296e-1 * c(m-4) - 0.6224240288742446280057699e-2 * c(m-6) -0.6486184157331537899459796e-2 * c(m-5) + 0.4409068609809831485979484e-2 * c(m-4) + 0.2077115547521706413480312e-2 * c(m-6);
+            0.5000000000000000000000000e-1 * c(m-9) - 0.2966863787471237458744416e0 * c(m-7) + 0.4698146218022683933926520e-1 * c(m-5) + 0.1750000000000000000000000e0 * c(m-8) + 0.1700291833903489463825077e0 * c(m-6) + 0.4675733176547960152668626e-2 * c(m-4) -0.2500000000000000000000000e-1 * c(m-9) - 0.3000000000000000000000000e0 * c(m-8) - 0.2997556885134827361576001e0 * c(m-5) - 0.5636663150858098975790317e-1 * c(m-4) - 0.4382544850115050165022338e0 * c(m-7) - 0.3806231949664312575822630e0 * c(m-6) 0.5555555555555555555555556e-2 * c(m-9) + 0.1250000000000000000000000e0 * c(m-8) + 0.9698817275172575247533506e0 * c(m-7) + 0.1011699483929608164601067e1 * c(m-5) + 0.1773466968705924819112984e0 * c(m-4) + 0.2239223735771599178951297e-3 * c(m-3) + 0.4325148359756313354830552e0 * c(m-6) -0.2500000000000000000000000e-1 * c(m-8) - 0.3132544850115050165022338e0 * c(m-7) - 0.2322389872063761557916742e0 * c(m-4) - 0.8607044252686413302647675e-3 * c(m-3) - 0.2594851141920572702679681e0 * c(m-6) - 0.6691607091647929161078591e0 * c(m-5) 0.5331362125287625412555844e-1 * c(m-7) + 0.1736073411355428563685818e0 * c(m-5) + 0.8671038084174692625075159e-2 * c(m-3) + 0.8084259844422177692569663e-1 * c(m-6) - 0.1664345989168155800449120e0 * c(m-4) -0.5013247356072127938999311e0 * c(m-5) + 0.5021853752328231128475915e0 * c(m-4) - 0.1197175073672143005877150e-1 * c(m-6) 0.3328335104489738933610597e0 * c(m-5) - 0.3179803804558436283847901e0 * c(m-4) - 0.5111353189352474549563559e-2 * c(m-3) - 0.9741776803777790426705996e-2 * c(m-6) -0.1080774142196007991746827e0 * c(m-5) + 0.9941834083648937298100811e-1 * c(m-4) - 0.4834791406446907590553793e-2 * c(m-3) + 0.1349386478955833378422842e-1 * c(m-6) 0.1319674981073749167009902e-1 * c(m-5) - 0.1060554802883657391328704e-1 * c(m-4) + 0.1911888563316170927411831e-2 * c(m-3) - 0.4503090345217088684223814e-2 * c(m-6);
+            0.2279091916474916391629437e-1 * c(m-7) + 0.3097763128598982561225538e-1 * c(m-6) - 0.3055555555555555555555556e-1 * c(m-8) - 0.3068985997518740530511593e-1 * c(m-5) - 0.3634246031107139778989373e-2 * c(m-4) 0.5000000000000000000000000e-1 * c(m-8) - 0.3557251496099816106154206e0 * c(m-6) + 0.5490976528821799120017102e-1 * c(m-4) + 0.1838363233410033443348225e0 * c(m-7) + 0.2169790609807602750804271e0 * c(m-5) -0.2500000000000000000000000e-1 * c(m-8) - 0.3132544850115050165022338e0 * c(m-7) - 0.2322389872063761557916742e0 * c(m-4) - 0.8607044252686413302647675e-3 * c(m-3) - 0.2594851141920572702679681e0 * c(m-6) - 0.6691607091647929161078591e0 * c(m-5) 0.5555555555555555555555556e-2 * c(m-8) + 0.1338363233410033443348225e0 * c(m-7) + 0.7391887916719206077121040e0 * c(m-6) + 0.6490333320052011212240632e0 * c(m-4) + 0.3308343404200968256656458e-2 * c(m-3) + 0.2062575706647430620228133e-3 * c(m-2) + 0.3088241944378964404772302e-3 * c(m-1) + 0.4227226173449345042468960e-3 * c(m) + 0.1190362071861893051132274e1 * c(m-5) -0.2720908083525083608370563e-1 * c(m-7) - 0.1931148612480615118957263e0 * c(m-6) - 0.3332941113251635390801278e-1 * c(m-3) + 0.2605582646183255957264249e-3 * c(m-2) + 0.1432116665752147607469646e-2 * c(m-1) + 0.1207544072304193806052558e-2 * c(m) - 0.1348436986667115543203552e1 * c(m-5) + 0.1687723507780044227927853e-1 * c(m-4) 0.3590669644811151307464697e-1 * c(m-6) - 0.5925443480724830632401754e0 * c(m-4) - 0.6897142765790609546343709e-2 * c(m-2) - 0.5363098747528542488971874e-2 * c(m-1) - 0.5205147429855955657625694e-2 * c(m) + 0.9977064356292750529201981e0 * c(m-5) 0.7272438906214475928744770e-1 * c(m-4) + 0.1964682777744275219350831e-1 * c(m-3) - 0.5952475275883259619711594e-2 * c(m-1) - 0.1635430866921887819487473e-2 * c(m) + 0.2921234010758621482958052e-1 * c(m-6) - 0.4659516693228870973898560e0 * c(m-5) 0.5891947149681041048896399e-1 * c(m-4) + 0.1858378996391679448655070e-1 * c(m-3) + 0.7240905383565181316381731e-2 * c(m-2) + 0.2349927974590068869356781e-1 * c(m) - 0.4046360079256766884300687e-1 * c(m-6) + 0.1223513270418807666970488e0 * c(m-5) -0.2404661162020836566908542e-1 * c(m-4) - 0.7348845587775519698437916e-2 * c(m-3) - 0.8105784530576404277872603e-3 * c(m-2) + 0.9574633163221758060736592e-2 * c(m-1) - 0.1828896813877197352675410e-1 * c(m) + 0.1350326632905990039353503e-1 * c(m-6) - 0.1315967038382618382356495e-1 * c(m-5);
+            0.5522702088127090209264064e-3 * c(m-7) - 0.3265435411305071914756373e-2 * c(m-6) + 0.7462059484530855073291365e-2 * c(m-5) - 0.4748894282038492179461399e-2 * c(m-4) 0.5528052133944605740009217e-1 * c(m-6) - 0.8631683980217122275970376e-1 * c(m-5) - 0.3276463639080639163926118e-1 * c(m-7) + 0.5268984374242044588776166e-1 * c(m-4) 0.5331362125287625412555844e-1 * c(m-7) + 0.1736073411355428563685818e0 * c(m-5) + 0.8671038084174692625075159e-2 * c(m-3) + 0.8084259844422177692569663e-1 * c(m-6) - 0.1664345989168155800449120e0 * c(m-4) -0.2720908083525083608370563e-1 * c(m-7) - 0.1931148612480615118957263e0 * c(m-6) - 0.3332941113251635390801278e-1 * c(m-3) + 0.2605582646183255957264249e-3 * c(m-2) + 0.1432116665752147607469646e-2 * c(m-1) + 0.1207544072304193806052558e-2 * c(m) - 0.1348436986667115543203552e1 * c(m-5) + 0.1687723507780044227927853e-1 * c(m-4) 0.6107825764368264576481962e-2 * c(m-7) + 0.1155752633643216628010304e0 * c(m-6) + 0.2096413329579026439044119e1 * c(m-5) + 0.3357721707576477199985656e0 * c(m-3) + 0.3291545083271862858501887e-3 * c(m-2) + 0.6641183499427826101618457e-2 * c(m-1) + 0.3449455095910233625229891e-2 * c(m) + 0.8270696421223286922584620e0 * c(m-4) -0.4995827370863505253765970e-1 * c(m-6) - 0.1263507837371824205693950e1 * c(m-5) - 0.8712928907711754187084757e-2 * c(m-2) - 0.2487040599390160764166412e-1 * c(m-1) - 0.1486895819265604128572498e-1 * c(m) - 0.1726565392121567634950213e1 * c(m-4) 0.5402985338373433052255418e0 * c(m-5) - 0.1979290298620869974478871e0 * c(m-3) - 0.2760353365637712827793337e-1 * c(m-1) - 0.4671751091575462868310238e-2 * c(m) - 0.6952587985456154591014641e-1 * c(m-6) + 0.1571507277911208446562686e1 * c(m-4) -0.1319358558853174530078498e0 * c(m-5) - 0.1872196143003808021730728e0 * c(m-3) + 0.9147192682075630179962131e-2 * c(m-2) + 0.6712774475803763988977355e-1 * c(m) + 0.9630407686703666967100804e-1 * c(m-6) - 0.6882132817757726722141421e0 * c(m-4) 0.1241625568998496895352046e-1 * c(m-5) + 0.7403484645316174090533193e-1 * c(m-3) - 0.1023976547309387874453988e-2 * c(m-2) + 0.4440063948509876221050939e-1 * c(m-1) - 0.5224403464202056316702078e-1 * c(m) - 0.3213800979246298453953842e-1 * c(m-6) + 0.1178181682424363524005403e0 * c(m-4);
+            0.6272075574042975468177820e-3 * c(m-6) - 0.1200429618441003833696998e-1 * c(m-5) + 0.1137708862700574079015220e-1 * c(m-4) -0.5373770512016897565958305e-2 * c(m-6) + 0.1453421858063658498587377e0 * c(m-5) - 0.1399684152943489522927794e0 * c(m-4) -0.5013247356072127938999311e0 * c(m-5) + 0.5021853752328231128475915e0 * c(m-4) - 0.1197175073672143005877150e-1 * c(m-6) 0.3590669644811151307464697e-1 * c(m-6) - 0.5925443480724830632401754e0 * c(m-4) - 0.6897142765790609546343709e-2 * c(m-2) - 0.5363098747528542488971874e-2 * c(m-1) - 0.5205147429855955657625694e-2 * c(m) + 0.9977064356292750529201981e0 * c(m-5) -0.4995827370863505253765970e-1 * c(m-6) - 0.1263507837371824205693950e1 * c(m-5) - 0.8712928907711754187084757e-2 * c(m-2) - 0.2487040599390160764166412e-1 * c(m-1) - 0.1486895819265604128572498e-1 * c(m) - 0.1726565392121567634950213e1 * c(m-4) 0.2760393423824887721078848e-1 * c(m-6) + 0.1190550338687608873798462e1 * c(m-5) + 0.4253084328734353394994388e1 * c(m-4) + 0.2306367624634749229113646e0 * c(m-2) + 0.9313657638804699948929701e-1 * c(m-1) + 0.6409299775987186986730499e-1 * c(m) -0.8755807343482262259774782e0 * c(m-5) - 0.3645285178085761821545207e1 * c(m-4) + 0.1033717994630886401730470e0 * c(m-1) + 0.2013769413884797246646959e-1 * c(m) + 0.4106783858513785463625543e-1 * c(m-6) 0.3956598149904136332753521e0 * c(m-5) + 0.1630560443616104907615866e1 * c(m-4) - 0.2421320004064592721552708e0 * c(m-2) - 0.2893557395653431666593814e0 * c(m) - 0.5688529641249387985434413e-1 * c(m-6) -0.7684117160199014594442072e-1 * c(m-5) - 0.2928439026361256842196229e0 * c(m-4) + 0.2710530961648671297733465e-1 * c(m-2) - 0.1662748711097054895317080e0 * c(m-1) + 0.2251991532891353212689574e0 * c(m) + 0.1898341454096471754822498e-1 * c(m-6);
+            0.9209089963443799485648361e-2 * c(m-5) - 0.3129629392354775191148163e-3 * c(m-6) - 0.8896127024208321966533544e-2 * c(m-4) -0.1059816030196818445908057e0 * c(m-5) + 0.1014880675788250237247178e0 * c(m-4) + 0.4493535440856820866087846e-2 * c(m-6) 0.3328335104489738933610597e0 * c(m-5) - 0.3179803804558436283847901e0 * c(m-4) - 0.5111353189352474549563559e-2 * c(m-3) - 0.9741776803777790426705996e-2 * c(m-6) 0.7272438906214475928744770e-1 * c(m-4) + 0.1964682777744275219350831e-1 * c(m-3) - 0.5952475275883259619711594e-2 * c(m-1) - 0.1635430866921887819487473e-2 * c(m) + 0.2921234010758621482958052e-1 * c(m-6) - 0.4659516693228870973898560e0 * c(m-5) 0.5402985338373433052255418e0 * c(m-5) - 0.1979290298620869974478871e0 * c(m-3) - 0.2760353365637712827793337e-1 * c(m-1) - 0.4671751091575462868310238e-2 * c(m) - 0.6952587985456154591014641e-1 * c(m-6) + 0.1571507277911208446562686e1 * c(m-4) -0.8755807343482262259774782e0 * c(m-5) - 0.3645285178085761821545207e1 * c(m-4) + 0.1033717994630886401730470e0 * c(m-1) + 0.2013769413884797246646959e-1 * c(m) + 0.4106783858513785463625543e-1 * c(m-6) 0.1070920689960817104203947e1 * c(m-5) + 0.3717418466925056542408153e1 * c(m-4) + 0.1166740554279680007487795e0 * c(m-3) + 0.1147318200715868527529827e0 * c(m-1) + 0.6327161147136873807796515e-2 * c(m) + 0.6235373239336055200426697e-1 * c(m-6) -0.6639605248735044787146222e0 * c(m-5) - 0.1865625445986772763641423e1 * c(m-4) + 0.1103611313171476425250639e0 * c(m-3) - 0.9091410269992464604926176e-1 * c(m) - 0.8636954541126674177407762e-1 * c(m-6) 0.1582127073537215443965653e0 * c(m-5) + 0.3746489300753517635549495e0 * c(m-4) - 0.4364163147111892346990101e-1 * c(m-3) - 0.1845476106024151050283847e0 * c(m-1) + 0.7075642937243715046279337e-1 * c(m) + 0.2882271848190011329385407e-1 * c(m-6);
+            -0.3576545132696983143406173e-2 * c(m-5) + 0.4335019854436220306755673e-3 * c(m-6) + 0.3143043147253361112730605e-2 * c(m-4) 0.4093499466767054661591066e-1 * c(m-5) - 0.3471075437892810033585296e-1 * c(m-4) - 0.6224240288742446280057699e-2 * c(m-6) -0.1080774142196007991746827e0 * c(m-5) + 0.9941834083648937298100811e-1 * c(m-4) - 0.4834791406446907590553793e-2 * c(m-3) + 0.1349386478955833378422842e-1 * c(m-6) 0.5891947149681041048896399e-1 * c(m-4) + 0.1858378996391679448655070e-1 * c(m-3) + 0.7240905383565181316381731e-2 * c(m-2) + 0.2349927974590068869356781e-1 * c(m) - 0.4046360079256766884300687e-1 * c(m-6) + 0.1223513270418807666970488e0 * c(m-5) -0.1319358558853174530078498e0 * c(m-5) - 0.1872196143003808021730728e0 * c(m-3) + 0.9147192682075630179962131e-2 * c(m-2) + 0.6712774475803763988977355e-1 * c(m) + 0.9630407686703666967100804e-1 * c(m-6) - 0.6882132817757726722141421e0 * c(m-4) 0.3956598149904136332753521e0 * c(m-5) + 0.1630560443616104907615866e1 * c(m-4) - 0.2421320004064592721552708e0 * c(m-2) - 0.2893557395653431666593814e0 * c(m) - 0.5688529641249387985434413e-1 * c(m-6) -0.6639605248735044787146222e0 * c(m-5) - 0.1865625445986772763641423e1 * c(m-4) + 0.1103611313171476425250639e0 * c(m-3) - 0.9091410269992464604926176e-1 * c(m) - 0.8636954541126674177407762e-1 * c(m-6) 0.4681819359722749441073885e0 * c(m-5) + 0.1015239189167790053447110e1 * c(m-4) + 0.1043897828092562609502636e0 * c(m-3) + 0.2542001760457345743492403e0 * c(m-2) + 0.1306332157111667628555907e1 * c(m) + 0.1196351539550049336518187e0 * c(m-6) -0.1195777325611201766551392e0 * c(m-5) - 0.2187310061229745694542609e0 * c(m-4) - 0.4128029838349298819825156e-1 * c(m-3) - 0.2845627370491611369031341e-1 * c(m-2) - 0.1016689339350338144430605e1 * c(m) - 0.3992391469197282238624438e-1 * c(m-6);
+            0.5593983696629863059347067e-3 * c(m-5) - 0.1446656414398166805849327e-3 * c(m-6) - 0.4147327282231696253497740e-3 * c(m-4) -0.6486184157331537899459796e-2 * c(m-5) + 0.4409068609809831485979484e-2 * c(m-4) + 0.2077115547521706413480312e-2 * c(m-6) 0.1319674981073749167009902e-1 * c(m-5) - 0.1060554802883657391328704e-1 * c(m-4) + 0.1911888563316170927411831e-2 * c(m-3) - 0.4503090345217088684223814e-2 * c(m-6) -0.2404661162020836566908542e-1 * c(m-4) - 0.7348845587775519698437916e-2 * c(m-3) - 0.8105784530576404277872603e-3 * c(m-2) + 0.9574633163221758060736592e-2 * c(m-1) - 0.1828896813877197352675410e-1 * c(m) + 0.1350326632905990039353503e-1 * c(m-6) - 0.1315967038382618382356495e-1 * c(m-5) 0.1241625568998496895352046e-1 * c(m-5) + 0.7403484645316174090533193e-1 * c(m-3) - 0.1023976547309387874453988e-2 * c(m-2) + 0.4440063948509876221050939e-1 * c(m-1) - 0.5224403464202056316702078e-1 * c(m) - 0.3213800979246298453953842e-1 * c(m-6) + 0.1178181682424363524005403e0 * c(m-4) -0.7684117160199014594442072e-1 * c(m-5) - 0.2928439026361256842196229e0 * c(m-4) + 0.2710530961648671297733465e-1 * c(m-2) - 0.1662748711097054895317080e0 * c(m-1) + 0.2251991532891353212689574e0 * c(m) + 0.1898341454096471754822498e-1 * c(m-6) 0.1582127073537215443965653e0 * c(m-5) + 0.3746489300753517635549495e0 * c(m-4) - 0.4364163147111892346990101e-1 * c(m-3) - 0.1845476106024151050283847e0 * c(m-1) + 0.7075642937243715046279337e-1 * c(m) + 0.2882271848190011329385407e-1 * c(m-6) -0.1195777325611201766551392e0 * c(m-5) - 0.2187310061229745694542609e0 * c(m-4) - 0.4128029838349298819825156e-1 * c(m-3) - 0.2845627370491611369031341e-1 * c(m-2) - 0.1016689339350338144430605e1 * c(m) - 0.3992391469197282238624438e-1 * c(m-6) 0.3167964748016105299646518e-1 * c(m-5) + 0.4976563420877041544013670e-1 * c(m-4) + 0.1632404042590951953384672e-1 * c(m-3) + 0.3185519088796429015220016e-2 * c(m-2) + 0.2968472090638000742888467e0 * c(m-1) + 0.7912667594695582093926295e0 * c(m) + 0.1332316557164627464149716e-1 * c(m-6);
+        ];
+
+        M(5,10)=M(10,5);
+        M(m-4,m-9)=M(m-9,m-4);
+
+        M=M/h;
+
+        D2 = HI*(-M - c(1)*e_l*d1_l' + c(m)*e_r*d1_r');
+    end
+    D2 = @D2_fun;
+
+    % Fourth derivative, 1th order accurate at first 8 boundary points (still
+    % yield 5th order convergence if stable: for example u_tt=-u_xxxx
+    stencil = [7/240, -2/5, 169/60, -122/15, 91/8, -122/15, 169/60, -2/5, 7/240];
+    diags = -4:4;
+    M4 = stripeMatrix(stencil, diags, m);
+
+    M4_U = [
+        0.1394226315049e13/0.367201486080e12 -0.1137054563243e13/0.114750464400e12 0.16614189027367e14/0.1836007430400e13 -0.1104821700277e13/0.306001238400e12 0.1355771086763e13/0.1836007430400e13 -0.27818686453e11/0.459001857600e12 -0.40671054239e11/0.1836007430400e13 0.5442887371e10/0.306001238400e12;
+        -0.1137054563243e13/0.114750464400e12 0.70616795535409e14/0.2570410402560e13 -0.173266854731041e15/0.6426026006400e13 0.28938615291031e14/0.2570410402560e13 -0.146167361863e12/0.71400288960e11 0.2793470836571e13/0.12852052012800e14 0.6219558097e10/0.428401733760e12 -0.7313844559e10/0.166909766400e12;
+        0.16614189027367e14/0.1836007430400e13 -0.173266854731041e15/0.6426026006400e13 0.378613061504779e15/0.12852052012800e14 -0.9117069604217e13/0.642602600640e12 0.632177582849e12/0.233673672960e12 -0.1057776382577e13/0.6426026006400e13 0.443019868399e12/0.4284017337600e13 -0.3707981e7/0.2318191200e10;
+        -0.1104821700277e13/0.306001238400e12 0.28938615291031e14/0.2570410402560e13 -0.9117069604217e13/0.642602600640e12 0.5029150721885e13/0.514082080512e12 -0.5209119714341e13/0.1285205201280e13 0.12235427457469e14/0.12852052012800e14 -0.13731270505e11/0.64260260064e11 0.2933596129e10/0.40800165120e11;
+        0.1355771086763e13/0.1836007430400e13 -0.146167361863e12/0.71400288960e11 0.632177582849e12/0.233673672960e12 -0.5209119714341e13/0.1285205201280e13 0.14871726798559e14/0.2570410402560e13 -0.7504337615347e13/0.1606506501600e13 0.310830296467e12/0.171360693504e12 -0.55284274391e11/0.183600743040e12;
+        -0.27818686453e11/0.459001857600e12 0.2793470836571e13/0.12852052012800e14 -0.1057776382577e13/0.6426026006400e13 0.12235427457469e14/0.12852052012800e14 -0.7504337615347e13/0.1606506501600e13 0.106318657014853e15/0.12852052012800e14 -0.14432772918527e14/0.2142008668800e13 0.58102695589e11/0.22666758400e11;
+        -0.40671054239e11/0.1836007430400e13 0.6219558097e10/0.428401733760e12 0.443019868399e12/0.4284017337600e13 -0.13731270505e11/0.64260260064e11 0.310830296467e12/0.171360693504e12 -0.14432772918527e14/0.2142008668800e13 0.27102479467823e14/0.2570410402560e13 -0.1216032192203e13/0.153000619200e12;
+        0.5442887371e10/0.306001238400e12 -0.7313844559e10/0.166909766400e12 -0.3707981e7/0.2318191200e10 0.2933596129e10/0.40800165120e11 -0.55284274391e11/0.183600743040e12 0.58102695589e11/0.22666758400e11 -0.1216032192203e13/0.153000619200e12 0.20799922829107e14/0.1836007430400e13;
+    ];
+
+    M4(1:8,1:8) = M4_U;
+    M4(m-7:m,m-7:m) = rot90(  M4_U ,2 );
+    M4 = M4/h^3;
+
+
+
+    D4=HI*(M4 - e_l*d3_l'+e_r*d3_r' + d1_l*d2_l'-d1_r*d2_r');
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/D2Variable.m
--- a/+sbp/D2Variable.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+sbp/D2Variable.m	Wed Jan 25 16:22:18 2017 +0100
@@ -18,7 +18,7 @@
 
     methods
         function obj = D2Variable(m,lim,order)
-            
+
             x_l = lim{1};
             x_r = lim{2};
             L = x_r-x_l;
@@ -30,7 +30,7 @@
                     [obj.H, obj.HI, obj.D1, obj.D2, obj.e_l,...
                         obj.e_r, obj.d1_l, obj.d1_r] = ...
                         sbp.implementations.d2_variable_4(m,obj.h);
-                    obj.borrowing.M.S = 0.2505765857;
+                    obj.borrowing.M.d1 = 0.2505765857;
                 otherwise
                     error('Invalid operator order %d.',order);
             end
@@ -39,8 +39,13 @@
             obj.M = [];
 
         end
+
+        function str = string(obj)
+            str = [class(obj) '_' num2str(obj.order)];
+        end
     end
 
+
 end
 
 
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/D4CompatibleVariable.m
--- a/+sbp/D4CompatibleVariable.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-classdef D4CompatibleVariable < sbp.OpSet
-    properties
-        D1 % SBP operator approximating first derivative
-        H % Norm matrix
-        HI % H^-1
-        Q % Skew-symmetric matrix
-        e_l % Left boundary operator
-        e_r % Right boundary operator
-        D2 % SBP operator for second derivative
-        M % Norm matrix, second derivative
-        d1_l % Left boundary first derivative
-        d1_r % Right boundary first derivative
-        D3 % SBP operator for third derivative
-        Q3 % Skew-symmetric matrix in third derivative
-        d2_l % Left boundary second derivative
-        d2_r % Right boundary second derivative
-        D4 % SBP operator for fourth derivative
-        M4 % Norm matrix, fourth derivative
-        d3_l % Left boundary third derivative
-        d3_r % Right boundary third derivative
-        m % Number of grid points.
-        h % Step size
-        x % grid
-        borrowing % Struct with borrowing limits for different norm matrices
-    end
-
-
-
-    methods
-        function obj = D4CompatibleVariable(m,lim,order)
-            
-            x_l = lim{1};
-            x_r = lim{2};
-            L = x_r-x_l;
-            obj.h = L/(m-1);
-            obj.x = linspace(x_l,x_r,m)';
-
-            if order == 2
-                [obj.H, obj.HI, ~, obj.D2, ~, obj.D4, obj.e_l, obj.e_r,...
-                 obj.M4, ~, obj.d2_l, obj.d2_r, obj.d3_l,...
-                    obj.d3_r, obj.d1_l, obj.d1_r] =...
-                    sbp.implementations.d4_compatible_halfvariable_2(m,obj.h);
-                obj.borrowing.N.S2 = 1.2500;
-                obj.borrowing.N.S3 = 0.4000;
-            elseif order == 4
-                [obj.H, obj.HI, obj.D2, obj.D4, obj.e_l, obj.e_r, obj.M4,...
-                 obj.d2_l, obj.d2_r, obj.d3_l, obj.d3_r, obj.d1_l,...
-                    obj.d1_r] =...
-                    sbp.implementations.d4_compatible_halfvariable_4(m,obj.h);
-                obj.borrowing.N.S2 = 0.5055;
-                obj.borrowing.N.S3 = 0.9290;
-            elseif order == 6
-                [obj.H, obj.HI, obj.D2, obj.D4, obj.e_l, obj.e_r, obj.M4,...
-                 obj.d2_l, obj.d2_r, obj.d3_l, obj.d3_r, obj.d1_l,...
-                    obj.d1_r] =...
-                    sbp.implementations.d4_compatible_halfvariable_6(m,obj.h);
-                obj.borrowing.N.S2 = 0.3259;
-                obj.borrowing.N.S3 = 0.1580;
-            else
-                error('Invalid operator order.');
-            end
-
-            obj.m = m;
-            
-            obj.D1 = [];
-            obj.D3 = [];
-
-
-        end
-    end
-
-
-
-end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/D4Lonely.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+sbp/D4Lonely.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,124 @@
+classdef D4Lonely < sbp.OpSet
+    properties
+        m    % Number of grid points.
+        h    % Step size
+        x    % grid
+        H    % Norm matrix
+        HI   % H^-1
+        D4   % SBP operator for fourth derivative
+        M4   % Norm matrix, fourth derivative
+        e_l,  e_r  % Left and right boundary operator
+        d1_l, d1_r % Left and right boundary first derivative
+        d2_l, d2_r % Left and right boundary second derivative
+        d3_l, d3_r % Left and right boundary third derivative
+        borrowing % Struct with borrowing limits for different norm matrices
+        opt
+        order
+    end
+
+    methods
+        function obj = D4Lonely(m, lim, order, opt)
+            default_arg('opt', '')
+
+            obj.opt = opt;
+            obj.order = order;
+
+            x_l = lim{1};
+            x_r = lim{2};
+            L = x_r-x_l;
+            obj.h = L/(m-1);
+            obj.x = linspace(x_l, x_r,m)';
+
+            if order == 2
+                switch opt
+                    case ''
+                        [H, HI, D1, D2, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = ...
+                            sbp.implementations.d4_variable_2(m, obj.h);
+                        obj.borrowing.N.S2 = 1.2500;
+                        obj.borrowing.N.S3 = 0.4000;
+                    otherwise
+                        error('Invalid operator option.');
+                end
+
+            elseif order == 4
+                switch opt
+                    case 'min_boundary_points'
+                        [H, HI, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = ...
+                            sbp.implementations.d4_lonely_4_min_boundary_points(m, obj.h);
+                        obj.borrowing.N.S2 = 0.6244;
+                        obj.borrowing.N.S3 = 1.3961;
+                    case ''
+                        [H, HI, D1, D2, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = ...
+                            sbp.implementations.d4_variable_4(m, obj.h);
+                        obj.borrowing.N.S2 = 0.5055;
+                        obj.borrowing.N.S3 = 0.9290;
+                    otherwise
+                        error('Invalid operator option.');
+                end
+
+            elseif order == 6
+                switch opt
+                    case '2'
+                        [H, HI, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = ...
+                            sbp.implementations.d4_lonely_6_2(m, obj.h);
+                        obj.borrowing.N.S2 = 0.2931;
+                        obj.borrowing.N.S3 = 0.0807;
+                    case '3'
+                        [H, HI, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = ...
+                            sbp.implementations.d4_lonely_6_3(m, obj.h);
+                        obj.borrowing.N.S2 = 0.2842;
+                        obj.borrowing.N.S3 = 0.0709;
+                    case 'min_boundary_points'
+                        [H, HI, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = ...
+                            sbp.implementations.d4_lonely_6_min_boundary_points(m, obj.h);
+                        obj.borrowing.N.S2 = 0.3569;
+                        obj.borrowing.N.S3 = 0.1908;
+                    case ''
+                        [H, HI, D1, D2, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = ...
+                            sbp.implementations.d4_variable_6(m, obj.h);
+                        obj.borrowing.N.S2 = 0.3259;
+                        obj.borrowing.N.S3 = 0.1580;
+                    otherwise
+                        error('Invalid operator option.');
+                end
+
+            elseif order == 8
+                switch opt
+                    case 'min_boundary_points'
+                        [H, HI, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = ...
+                            sbp.implementations.d4_lonely_8_min_boundary_points(m, obj.h);
+                        obj.borrowing.N.S2 = 0.2804;
+                        obj.borrowing.N.S3 = 0.0740;
+                    case ''
+                        [H, HI, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = ...
+                            sbp.implementations.d4_lonely_8_higher_boundary_order(m, obj.h);
+                        obj.borrowing.N.S2 = 0.2475;
+                        obj.borrowing.N.S3 = 0.0401;
+                    otherwise
+                        error('Invalid operator option.');
+                    end
+            else
+                error('Invalid operator order.');
+            end
+
+            obj.m = m;
+
+            obj.H    = H;
+            obj.HI   = HI;
+            obj.D4   = D4;
+            obj.M4   = M4;
+            obj.e_l  = e_l;
+            obj.e_r  = e_r;
+            obj.d1_l = d1_l;
+            obj.d1_r = d1_r;
+            obj.d2_l = d2_l;
+            obj.d2_r = d2_r;
+            obj.d3_l = d3_l;
+            obj.d3_r = d3_r;
+        end
+
+        function str = string(obj)
+            str = [class(obj) '_' num2str(obj.order) '_' obj.opt];
+        end
+    end
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/D4Variable.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+sbp/D4Variable.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,75 @@
+classdef D4Variable < sbp.OpSet
+    properties
+        m    % Number of grid points.
+        h    % Step size
+        x    % grid
+        H    % Norm matrix
+        HI   % H^-1
+        D1   % SBP operator approximating first derivative
+        D2   % SBP operator for second derivative
+        D4   % SBP operator for fourth derivative
+        Q    % Skew-symmetric matrix
+        M    % Norm matrix, second derivative
+        M4   % Norm matrix, fourth derivative
+        e_l,  e_r  % Left and right boundary operator
+        d1_l, d1_r % Left and right boundary first derivative
+        d2_l, d2_r % Left and right boundary second derivative
+        d3_l, d3_r % Left and right boundary third derivative
+        borrowing % Struct with borrowing limits for different norm matrices
+        order
+    end
+
+    methods
+        function obj = D4Variable(m, lim, order)
+            x_l = lim{1};
+            x_r = lim{2};
+            L = x_r-x_l;
+            obj.h = L/(m-1);
+            obj.x = linspace(x_l, x_r,m)';
+
+            if order == 2
+                [H, HI, D1, D2, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = ...
+                    sbp.implementations.d4_variable_2(m, obj.h);
+                obj.borrowing.M.d1 = 0.4000;
+                obj.borrowing.N.S2 = 1.2500;
+                obj.borrowing.N.S3 = 0.4000;
+            elseif order == 4
+                [H, HI, D1, D2, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = ...
+                    sbp.implementations.d4_variable_4(m, obj.h);
+                obj.borrowing.M.d1 = 0.2508;
+                obj.borrowing.N.S2 = 0.5055;
+                obj.borrowing.N.S3 = 0.9290;
+            elseif order == 6
+                [H, HI, D1, D2, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = ...
+                    sbp.implementations.d4_variable_6(m, obj.h);
+                obj.borrowing.M.d1 = 0.1878;
+                obj.borrowing.N.S2 = 0.3259;
+                obj.borrowing.N.S3 = 0.1580;
+            else
+                error('Invalid operator order.');
+            end
+
+            obj.m = m;
+            obj.order = order;
+
+            obj.H    = H;
+            obj.HI   = HI;
+            obj.D1   = D1;
+            obj.D2   = D2;
+            obj.D4   = D4;
+            obj.M4   = M4;
+            obj.e_l  = e_l;
+            obj.e_r  = e_r;
+            obj.d1_l = d1_l;
+            obj.d1_r = d1_r;
+            obj.d2_l = d2_l;
+            obj.d2_r = d2_r;
+            obj.d3_l = d3_l;
+            obj.d3_r = d3_r;
+        end
+
+        function str = string(obj)
+            str = [class(obj) '_' num2str(obj.order)];
+        end
+    end
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +sbp/OpSet.m
--- a/+sbp/OpSet.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+sbp/OpSet.m	Wed Jan 25 16:22:18 2017 +0100
@@ -6,4 +6,9 @@
         x % Grid
     end
 
+    methods (Abstract)
+        % Returns a string representation of the type of operator.
+        str = string(obj)
+    end
+
 end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +scheme/Beam.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+scheme/Beam.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,222 @@
+classdef Beam < scheme.Scheme
+    properties
+        order % Order accuracy for the approximation
+        grid
+
+        D % non-stabalized scheme operator
+        alpha
+
+        h
+        H % Discrete norm
+        Hi
+
+        e_l,  e_r
+        d1_l, d1_r
+        d2_l, d2_r
+        d3_l, d3_r
+        gamm
+        delt
+        alphaII
+        alphaIII
+
+        opt
+    end
+
+    methods
+        function obj = Beam(grid, order, alpha, opsGen, opt)
+            default_arg('alpha', -1);
+
+            % default_arg('opsGen', @sbp.D4);
+            default_arg('opsGen', @sbp.D4Variable); % Supposed to be better
+
+            opt_default.interface_l.tuning = 1.1;
+            opt_default.interface_l.tau = [];
+            opt_default.interface_l.sig = [];
+            opt_default.interface_r.tuning = 1.1;
+            opt_default.interface_r.tau = [];
+            opt_default.interface_r.sig = [];
+            default_struct('opt', opt_default);
+
+            if ~isa(grid, 'grid.Cartesian') || grid.D() ~= 1
+                error('Grid must be 1d cartesian');
+            end
+
+            obj.grid = grid;
+            obj.order = order;
+            obj.alpha = alpha;
+
+            m = grid.m;
+            h = grid.scaling();
+
+            x_lim = {grid.x{1}(1), grid.x{1}(end)};
+            ops = opsGen(m, x_lim, order);
+
+            D4       = ops.D4;
+            obj.H    = ops.H;
+            obj.Hi   = ops.HI;
+            obj.e_l  = ops.e_l;
+            obj.e_r  = ops.e_r;
+            obj.d1_l = ops.d1_l;
+            obj.d1_r = ops.d1_r;
+            obj.d2_l = ops.d2_l;
+            obj.d2_r = ops.d2_r;
+            obj.d3_l = ops.d3_l;
+            obj.d3_r = ops.d3_r;
+
+            obj.D = alpha*D4;
+
+            alphaII  = ops.borrowing.N.S2/2;
+            alphaIII = ops.borrowing.N.S3/2;
+
+            obj.gamm = h*alphaII;
+            obj.delt = h^3*alphaIII;
+            obj.alphaII = alphaII;
+            obj.alphaIII = alphaIII;
+            obj.h = h;
+            obj.opt = opt;
+        end
+
+
+        % Closure functions return the opertors applied to the own doamin to close the boundary
+        % Penalty functions return the opertors to force the solution. In the case of an interface it returns the operator applied to the other doamin.
+        %       boundary            is a string specifying the boundary e.g. 'l','r' or 'e','w','n','s'.
+        %       type                is a string specifying the type of boundary condition if there are several.
+        %       neighbour_scheme    is an instance of Scheme that should be interfaced to.
+        %       neighbour_boundary  is a string specifying which boundary to interface to.
+        function [closure, penalty] = boundary_condition(obj,boundary,type)
+            default_arg('type','dn');
+
+            [e, d1, d2, d3, s] = obj.get_boundary_ops(boundary);
+            gamm = obj.gamm;
+            delt = obj.delt;
+
+            switch type
+                case {'dn', 'clamped'} % Dirichlet-neumann boundary condition
+                    alpha = obj.alpha;
+
+                    % tau1 < -alpha^2/gamma
+                    % tuning = 2;
+                    tuning = 1.1;
+
+                    tau1 = tuning * alpha/delt;
+                    tau4 = s*alpha;
+
+                    sig2 = tuning * alpha/gamm;
+                    sig3 = -s*alpha;
+
+                    tau = tau1*e+tau4*d3;
+                    sig = sig2*d1+sig3*d2;
+
+                    closure = obj.Hi*(tau*e' + sig*d1');
+
+                    penalty{1} = -obj.Hi*tau;
+                    penalty{2} = -obj.Hi*sig;
+
+
+                case {'free'}
+                    a = obj.alpha;
+
+                    tau =  s*a*d1;
+                    sig = -s*a*e;
+
+                    closure = obj.Hi*(tau*d2' + sig*d3');
+                    penalty{1} = -obj.Hi*tau;
+                    penalty{1} = -obj.Hi*sig;
+
+
+                otherwise % Unknown, boundary condition
+                    error('No such boundary condition: type = %s',type);
+            end
+        end
+
+        function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary)
+            % u denotes the solution in the own domain
+            % v denotes the solution in the neighbour domain
+            [e_u,d1_u,d2_u,d3_u,s_u] = obj.get_boundary_ops(boundary);
+            [e_v,d1_v,d2_v,d3_v,s_v] = neighbour_scheme.get_boundary_ops(neighbour_boundary);
+
+
+            alpha_u = obj.alpha;
+            alpha_v = neighbour_scheme.alpha;
+
+
+            switch boundary
+                case 'l'
+                    interface_opt = obj.opt.interface_l;
+                case 'r'
+                    interface_opt = obj.opt.interface_r;
+            end
+
+
+            if isempty(interface_opt.tau) && isempty(interface_opt.sig)
+                gamm_u = obj.gamm;
+                delt_u = obj.delt;
+
+                gamm_v = neighbour_scheme.gamm;
+                delt_v = neighbour_scheme.delt;
+
+                tuning = interface_opt.tuning;
+
+                tau1 = ((alpha_u/2)/delt_u + (alpha_v/2)/delt_v)/2*tuning;
+                sig2 = ((alpha_u/2)/gamm_u + (alpha_v/2)/gamm_v)/2*tuning;
+            else
+                h_u = obj.h;
+                h_v = neighbour_scheme.h;
+
+                switch neighbour_boundary
+                    case 'l'
+                        neighbour_interface_opt = neighbour_scheme.opt.interface_l;
+                    case 'r'
+                        neighbour_interface_opt = neighbour_scheme.opt.interface_r;
+                end
+
+                tau_u = interface_opt.tau;
+                sig_u = interface_opt.sig;
+                tau_v = neighbour_interface_opt.tau;
+                sig_v = neighbour_interface_opt.sig;
+
+                tau1 = tau_u/h_u^3 + tau_v/h_v^3;
+                sig2 = sig_u/h_u   + sig_v/h_v;
+            end
+
+            tau4 = s_u*alpha_u/2;
+            sig3 = -s_u*alpha_u/2;
+            phi2 = s_u*1/2;
+            psi1 = -s_u*1/2;
+
+            tau = tau1*e_u  +                     tau4*d3_u;
+            sig =           sig2*d1_u + sig3*d2_u          ;
+            phi =           phi2*d1_u                      ;
+            psi = psi1*e_u                                 ;
+
+            closure =  obj.Hi*(tau*e_u' + sig*d1_u' + phi*alpha_u*d2_u' + psi*alpha_u*d3_u');
+            penalty = -obj.Hi*(tau*e_v' + sig*d1_v' + phi*alpha_v*d2_v' + psi*alpha_v*d3_v');
+        end
+
+        % Returns the boundary ops and sign for the boundary specified by the string boundary.
+        % The right boundary is considered the positive boundary
+        function [e, d1, d2, d3, s] = get_boundary_ops(obj,boundary)
+            switch boundary
+                case 'l'
+                    e  = obj.e_l;
+                    d1 = obj.d1_l;
+                    d2 = obj.d2_l;
+                    d3 = obj.d3_l;
+                    s = -1;
+                case 'r'
+                    e  = obj.e_r;
+                    d1 = obj.d1_r;
+                    d2 = obj.d2_r;
+                    d3 = obj.d3_r;
+                    s = 1;
+                otherwise
+                    error('No such boundary: boundary = %s',boundary);
+            end
+        end
+
+        function N = size(obj)
+            N = obj.grid.N;
+        end
+
+    end
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +scheme/Beam2d.m
--- a/+scheme/Beam2d.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+scheme/Beam2d.m	Wed Jan 25 16:22:18 2017 +0100
@@ -1,10 +1,6 @@
 classdef Beam2d < scheme.Scheme
     properties
-        m % Number of points in each direction, possibly a vector
-        N % Number of points total
-        h % Grid spacing
-        u,v % Grid
-        x,y % Values of x and y for each grid point
+        grid
         order % Order accuracy for the approximation
 
         D % non-stabalized scheme operator
@@ -27,21 +23,23 @@
 
     methods
         function obj = Beam2d(m,lim,order,alpha,opsGen)
+            default_arg('alpha',1);
             default_arg('opsGen',@sbp.Higher);
-            default_arg('a',1);
 
-            if length(m) == 1
-                m = [m m];
+            if ~isa(grid, 'grid.Cartesian') || grid.D() ~= 2
+                error('Grid must be 2d cartesian');
             end
 
-            m_x = m(1);
-            m_y = m(2);
+            obj.grid = grid;
+            obj.alpha = alpha;
+            obj.order = order;
 
-            xlim = lim{1};
-            ylim = lim{2};
+            m_x = grid.m(1);
+            m_y = grid.m(2);
 
-            [x, h_x] = util.get_grid(xlim{:},m_x);
-            [y, h_y] = util.get_grid(ylim{:},m_y);
+            h = grid.scaling();
+            h_x = h(1);
+            h_y = h(2);
 
             ops_x = opsGen(m_x,h_x,order);
             ops_y = opsGen(m_y,h_y,order);
@@ -49,9 +47,6 @@
             I_x = speye(m_x);
             I_y = speye(m_y);
 
-
-
-
             D4_x = sparse(ops_x.derivatives.D4);
             H_x =  sparse(ops_x.norms.H);
             Hi_x = sparse(ops_x.norms.HI);
@@ -105,16 +100,7 @@
             obj.d3_s = kr(I_x,d3_l_y);
             obj.d3_n = kr(I_x,d3_r_y);
 
-            obj.m = m;
-            obj.h = [h_x h_y];
-            obj.order = order;
-
-            obj.alpha = alpha;
             obj.D = alpha*D4;
-            obj.u = x;
-            obj.v = y;
-            obj.x = kr(x,ones(m_y,1));
-            obj.y = kr(ones(m_x,1),y);
 
             obj.gamm_x = h_x*ops_x.borrowing.N.S2/2;
             obj.delt_x = h_x^3*ops_x.borrowing.N.S3/2;
diff -r 0976e579a6f0 -r 026d8a3fdbfb +scheme/Scheme.m
--- a/+scheme/Scheme.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+scheme/Scheme.m	Wed Jan 25 16:22:18 2017 +0100
@@ -1,42 +1,44 @@
-% Start with all matrix returns. When that works see how we should generalize to non-matrix stuff/nonlinear
+% Start with all matrix returns. When that works see how we should generalize
+% to non-matrix stuff/nonlinear
 classdef Scheme < handle
     properties (Abstract)
-        m % Number of points in each direction, possibly a vector
         order % Order accuracy for the approximation
 
-        % vectors u,v,w depending on dim that gives were gridpoints are in each dimension
-        % vectors x,y,z containing the x,y,z values corresponding to each grid point
-        % matrices X,Y,Z with point coordinates as multi dimensional vectors
+        grid
 
         D % non-stabalized scheme operator
         H % Discrete norm
-
-        % Should also containg:
-        % the grid points used
-        % the grid spacing
     end
 
     methods (Abstract)
-        % Closure functions return the opertors applied to the own doamin to close the boundary
-        % Penalty functions return the opertors to force the solution. In the case of an interface it returns the operator applied to the other doamin.
-        %       boundary            is a string specifying the boundary e.g. 'l','r' or 'e','w','n','s'.
-        %       type                is a string specifying the type of boundary condition if there are several.
-        %       data                is a function returning the data that should be applied at the boundary.
-        %       neighbour_scheme    is an instance of Scheme that should be interfaced to.
-        %       neighbour_boundary  is a string specifying which boundary to interface to.
-        m = boundary_condition(obj,boundary,type,data)
-        m = interface(obj,boundary,neighbour_scheme,neighbour_boundary)
-        N = size(obj) % Returns the number of degrees of freedom.
+        % Closure functions return the opertors applied to the own doamin to
+        % close the boundary Penalty functions return the opertors to force
+        % the solution. In the case of an interface it returns the operator
+        % applied to the other doamin. In some cases the penalty return value
+        % can be ommited and the closure function take care of both parts.
+        %       boundary            is a string specifying the boundary e.g.
+        %                           'l','r' or 'e','w','n','s'.
+        %       type                is a string specifying the type of
+        %                           boundary condition if there are several.
+        %       neighbour_scheme    is an instance of Scheme that should be
+        %                           interfaced to.
+        %       neighbour_boundary  is a string specifying which boundary to
+        %                           interface to.
+        %       penalty  may be a cell array if there are several penalties with different weights
+        [closure, penalty] = boundary_condition(obj,boundary,type)
+        [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary)
 
+        % Returns the number of degrees of freedom.
+        N = size(obj)
     end
 
     methods(Static)
-        % Calculates the matrcis need for the inteface coupling between boundary bound_u of scheme schm_u
-        % and bound_v of scheme schm_v.
-        %   [uu, uv, vv, vu] = inteface_couplong(A,'r',B,'l')
+        % Calculates the matrcis need for the inteface coupling between
+        % boundary bound_u of scheme schm_u and bound_v of scheme schm_v.
+        %   [uu, uv, vv, vu] = inteface_coupling(A,'r',B,'l')
         function [uu, uv, vv, vu] = interface_coupling(schm_u,bound_u,schm_v,bound_v)
             [uu,uv] = schm_u.interface(bound_u,schm_v,bound_v);
             [vv,vu] = schm_v.interface(bound_v,schm_u,bound_u);
         end
     end
-end
\ No newline at end of file
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +scheme/Wave2dCurve.m
--- a/+scheme/Wave2dCurve.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+scheme/Wave2dCurve.m	Wed Jan 25 16:22:18 2017 +0100
@@ -2,9 +2,9 @@
     properties
         m % Number of points in each direction, possibly a vector
         h % Grid spacing
-        u,v % Grid
-        x,y % Values of x and y for each grid point
-        X,Y % Grid point locations as matrices
+
+        grid
+
         order % Order accuracy for the approximation
 
         D % non-stabalized scheme operator
@@ -26,24 +26,28 @@
         du_n, dv_n
         gamm_u, gamm_v
         lambda
+
+        x_u
+        x_v
+        y_u
+        y_v
     end
 
     methods
-        function obj = Wave2dCurve(m,ti,order,c,opSet)
+        function obj = Wave2dCurve(g ,order, c, opSet)
             default_arg('opSet',@sbp.D2Variable);
             default_arg('c', 1);
 
-            if length(m) == 1
-                m = [m m];
-            end
+            assert(isa(g, 'grid.Curvilinear'))
 
+            m = g.size();
             m_u = m(1);
             m_v = m(2);
-            m_tot = m_u*m_v;
+            m_tot = g.N();
 
-            [u, h_u] = util.get_grid(0, 1, m_u);
-            [v, h_v] = util.get_grid(0, 1, m_v);
-
+            h = g.scaling();
+            h_u = h(1);
+            h_v = h(2);
 
             % Operators
             ops_u = opSet(m_u, {0, 1}, order);
@@ -52,66 +56,64 @@
             I_u = speye(m_u);
             I_v = speye(m_v);
 
-            D1_u = sparse(ops_u.D1);
+            D1_u = ops_u.D1;
             D2_u = ops_u.D2;
-            H_u =  sparse(ops_u.H);
-            Hi_u = sparse(ops_u.HI);
-            % M_u =  sparse(ops_u.M);
-            e_l_u = sparse(ops_u.e_l);
-            e_r_u = sparse(ops_u.e_r);
-            d1_l_u = sparse(ops_u.d1_l);
-            d1_r_u = sparse(ops_u.d1_r);
+            H_u =  ops_u.H;
+            Hi_u = ops_u.HI;
+            e_l_u = ops_u.e_l;
+            e_r_u = ops_u.e_r;
+            d1_l_u = ops_u.d1_l;
+            d1_r_u = ops_u.d1_r;
 
-            D1_v = sparse(ops_v.D1);
+            D1_v = ops_v.D1;
             D2_v = ops_v.D2;
-            H_v =  sparse(ops_v.H);
-            Hi_v = sparse(ops_v.HI);
-            % M_v =  sparse(ops_v.M);
-            e_l_v = sparse(ops_v.e_l);
-            e_r_v = sparse(ops_v.e_r);
-            d1_l_v = sparse(ops_v.d1_l);
-            d1_r_v = sparse(ops_v.d1_r);
+            H_v =  ops_v.H;
+            Hi_v = ops_v.HI;
+            e_l_v = ops_v.e_l;
+            e_r_v = ops_v.e_r;
+            d1_l_v = ops_v.d1_l;
+            d1_r_v = ops_v.d1_r;
+
+            Du = kr(D1_u,I_v);
+            Dv = kr(I_u,D1_v);
 
             % Metric derivatives
-            [X,Y] = ti.map(u,v);
+            coords = g.points();
+            x = coords(:,1);
+            y = coords(:,2);
 
-            [x_u,x_v] = gridDerivatives(X,D1_u,D1_v);
-            [y_u,y_v] = gridDerivatives(Y,D1_u,D1_v);
-
-
+            x_u = Du*x;
+            x_v = Dv*x;
+            y_u = Du*y;
+            y_v = Dv*y;
 
             J = x_u.*y_v - x_v.*y_u;
-            a11 =  1./J .* (x_v.^2  + y_v.^2);  %% GÖR SOM MATRISER
+            a11 =  1./J .* (x_v.^2  + y_v.^2);
             a12 = -1./J .* (x_u.*x_v + y_u.*y_v);
             a22 =  1./J .* (x_u.^2  + y_u.^2);
             lambda = 1/2 * (a11 + a22 - sqrt((a11-a22).^2 + 4*a12.^2));
 
-            dof_order = reshape(1:m_u*m_v,m_v,m_u);
+            % Assemble full operators
+            L_12 = spdiags(a12, 0, m_tot, m_tot);
+            Duv = Du*L_12*Dv;
+            Dvu = Dv*L_12*Du;
 
             Duu = sparse(m_tot);
             Dvv = sparse(m_tot);
+            ind = grid.funcToMatrix(g, 1:m_tot);
 
             for i = 1:m_v
-                D = D2_u(a11(i,:));
-                p = dof_order(i,:);
+                D = D2_u(a11(ind(:,i)));
+                p = ind(:,i);
                 Duu(p,p) = D;
             end
 
             for i = 1:m_u
-                D = D2_v(a22(:,i));
-                p = dof_order(:,i);
+                D = D2_v(a22(ind(i,:)));
+                p = ind(i,:);
                 Dvv(p,p) = D;
             end
 
-            L_12 = spdiags(a12(:),0,m_tot,m_tot);
-            Du = kr(D1_u,I_v);
-            Dv = kr(I_u,D1_v);
-
-            Duv = Du*L_12*Dv;
-            Dvu = Dv*L_12*Du;
-
-
-
             obj.H = kr(H_u,H_v);
             obj.Hi = kr(Hi_u,Hi_v);
             obj.Hu  = kr(H_u,I_v);
@@ -119,7 +121,6 @@
             obj.Hiu = kr(Hi_u,I_v);
             obj.Hiv = kr(I_u,Hi_v);
 
-            % obj.M = kr(M_u,H_v)+kr(H_u,M_v);
             obj.e_w  = kr(e_l_u,I_v);
             obj.e_e  = kr(e_r_u,I_v);
             obj.e_s  = kr(I_u,e_l_v);
@@ -133,28 +134,27 @@
             obj.du_n = (obj.e_n'*Du)';
             obj.dv_n = kr(I_u,d1_r_v);
 
+            obj.x_u = x_u;
+            obj.x_v = x_v;
+            obj.y_u = y_u;
+            obj.y_v = y_v;
+
             obj.m = m;
             obj.h = [h_u h_v];
             obj.order = order;
-
+            obj.grid = g;
 
             obj.c = c;
-            obj.J = spdiags(J(:),0,m_tot,m_tot);
-            obj.Ji = spdiags(1./J(:),0,m_tot,m_tot);
+            obj.J = spdiags(J, 0, m_tot, m_tot);
+            obj.Ji = spdiags(1./J, 0, m_tot, m_tot);
             obj.a11 = a11;
             obj.a12 = a12;
             obj.a22 = a22;
             obj.D = obj.Ji*c^2*(Duu + Duv + Dvu + Dvv);
-            obj.u = u;
-            obj.v = v;
-            obj.X = X;
-            obj.Y = Y;
-            obj.x = X(:);
-            obj.y = Y(:);
             obj.lambda = lambda;
 
-            obj.gamm_u = h_u*ops_u.borrowing.M.S;
-            obj.gamm_v = h_v*ops_v.borrowing.M.S;
+            obj.gamm_u = h_u*ops_u.borrowing.M.d1;
+            obj.gamm_v = h_v*ops_v.borrowing.M.d1;
         end
 
 
@@ -165,12 +165,11 @@
         %       data                is a function returning the data that should be applied at the boundary.
         %       neighbour_scheme    is an instance of Scheme that should be interfaced to.
         %       neighbour_boundary  is a string specifying which boundary to interface to.
-        function [closure, penalty] = boundary_condition(obj,boundary,type,data)
+        function [closure, penalty] = boundary_condition(obj, boundary, type, parameter)
             default_arg('type','neumann');
-            default_arg('data',0);
+            default_arg('parameter', []);
 
-            [e, d_n, d_t, coeff_n, coeff_t, s, gamm, halfnorm_inv] = obj.get_boundary_ops(boundary);
-
+            [e, d_n, d_t, coeff_n, coeff_t, s, gamm, halfnorm_inv  ,              ~,          ~, ~, scale_factor] = obj.get_boundary_ops(boundary);
             switch type
                 % Dirichlet boundary condition
                 case {'D','d','dirichlet'}
@@ -190,28 +189,19 @@
                     b2 = gamm*u.lambda./u.a22.^2;
 
                     tau  = -1./b1 - 1./b2;
-                    tau = tuning * spdiag(tau(:));
-                    sig1 = 1/2;
+                    tau = tuning * spdiag(tau);
+                    sig1 = 1;
 
                     penalty_parameter_1 = halfnorm_inv_n*(tau + sig1*halfnorm_inv_t*F*e'*halfnorm_t)*e;
 
                     closure = obj.Ji*obj.c^2 * penalty_parameter_1*e';
-                    pp = -obj.Ji*obj.c^2 * penalty_parameter_1;
-                    switch class(data)
-                        case 'double'
-                            penalty = pp*data;
-                        case 'function_handle'
-                            penalty = @(t)pp*data(t);
-                        otherwise
-                            error('Weird data argument!')
-                    end
+                    penalty = -obj.Ji*obj.c^2 * penalty_parameter_1;
 
 
                 % Neumann boundary condition
                 case {'N','n','neumann'}
                     c = obj.c;
 
-
                     a_n = spdiags(coeff_n,0,length(coeff_n),length(coeff_n));
                     a_t = spdiags(coeff_t,0,length(coeff_t),length(coeff_t));
                     d = (a_n * d_n' + a_t*d_t')';
@@ -221,16 +211,23 @@
                     tau = c.^2 * obj.Ji*(tau1*e + tau2*d);
 
                     closure = halfnorm_inv*tau*d';
+                    penalty = -halfnorm_inv*tau;
 
-                    pp = halfnorm_inv*tau;
-                    switch class(data)
-                        case 'double'
-                            penalty = pp*data;
-                        case 'function_handle'
-                            penalty = @(t)pp*data(t);
-                        otherwise
-                            error('Weird data argument!')
-                    end
+                % Characteristic boundary condition
+                case {'characteristic', 'char', 'c'}
+                    default_arg('parameter', 1);
+                    beta = parameter;
+                    c = obj.c;
+
+                    a_n = spdiags(coeff_n,0,length(coeff_n),length(coeff_n));
+                    a_t = spdiags(coeff_t,0,length(coeff_t),length(coeff_t));
+                    d = s*(a_n * d_n' + a_t*d_t')'; % outward facing normal derivative
+
+                    tau = -c.^2 * 1/beta*obj.Ji*e;
+
+                    closure{1} = halfnorm_inv*tau/c*spdiag(scale_factor)*e';
+                    closure{2} = halfnorm_inv*tau*beta*d';
+                    penalty = -halfnorm_inv*tau;
 
                 % Unknown, boundary condition
                 otherwise
@@ -263,7 +260,7 @@
             b2_v = gamm_v*v.lambda(I_v)./v.a22(I_v).^2;
 
             tau = -1./(4*b1_u) -1./(4*b1_v) -1./(4*b2_u) -1./(4*b2_v);
-            tau = tuning * spdiag(tau(:));
+            tau = tuning * spdiag(tau);
             sig1 = 1/2;
             sig2 = -1/2;
 
@@ -279,10 +276,12 @@
         % The right boundary is considered the positive boundary
         %
         %  I -- the indecies of the boundary points in the grid matrix
-        function [e, d_n, d_t, coeff_n, coeff_t, s, gamm, halfnorm_inv_n, halfnorm_inv_t, halfnorm_t, I] = get_boundary_ops(obj,boundary)
+        function [e, d_n, d_t, coeff_n, coeff_t, s, gamm, halfnorm_inv_n, halfnorm_inv_t, halfnorm_t, I, scale_factor] = get_boundary_ops(obj, boundary)
 
-            gridMatrix = zeros(obj.m(2),obj.m(1));
-            gridMatrix(:) = 1:numel(gridMatrix);
+            % gridMatrix = zeros(obj.m(2),obj.m(1));
+            % gridMatrix(:) = 1:numel(gridMatrix);
+
+            ind = grid.funcToMatrix(obj.grid, 1:prod(obj.m));
 
             switch boundary
                 case 'w'
@@ -291,36 +290,40 @@
                     d_t = obj.dv_w;
                     s = -1;
 
-                    I = gridMatrix(:,1);
+                    I = ind(1,:);
                     coeff_n = obj.a11(I);
                     coeff_t = obj.a12(I);
+                    scale_factor = sqrt(obj.x_v(I).^2 + obj.y_v(I).^2);
                 case 'e'
                     e = obj.e_e;
                     d_n = obj.du_e;
                     d_t = obj.dv_e;
                     s = 1;
 
-                    I = gridMatrix(:,end);
+                    I = ind(end,:);
                     coeff_n = obj.a11(I);
                     coeff_t = obj.a12(I);
+                    scale_factor = sqrt(obj.x_v(I).^2 + obj.y_v(I).^2);
                 case 's'
                     e = obj.e_s;
                     d_n = obj.dv_s;
                     d_t = obj.du_s;
                     s = -1;
 
-                    I = gridMatrix(1,:)';
+                    I = ind(:,1)';
                     coeff_n = obj.a22(I);
                     coeff_t = obj.a12(I);
+                    scale_factor = sqrt(obj.x_u(I).^2 + obj.y_u(I).^2);
                 case 'n'
                     e = obj.e_n;
                     d_n = obj.dv_n;
                     d_t = obj.du_n;
                     s = 1;
 
-                    I = gridMatrix(end,:)';
+                    I = ind(:,end)';
                     coeff_n = obj.a22(I);
                     coeff_t = obj.a12(I);
+                    scale_factor = sqrt(obj.x_u(I).^2 + obj.y_u(I).^2);
                 otherwise
                     error('No such boundary: boundary = %s',boundary);
             end
@@ -343,15 +346,6 @@
             N = prod(obj.m);
         end
 
-    end
 
-    methods(Static)
-        % Calculates the matrcis need for the inteface coupling between boundary bound_u of scheme schm_u
-        % and bound_v of scheme schm_v.
-        %   [uu, uv, vv, vu] = inteface_couplong(A,'r',B,'l')
-        function [uu, uv, vv, vu] = interface_coupling(schm_u,bound_u,schm_v,bound_v)
-            [uu,uv] = schm_u.interface(bound_u,schm_v,bound_v);
-            [vv,vu] = schm_v.interface(bound_v,schm_u,bound_u);
-        end
     end
 end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +time/Cdiff.m
--- a/+time/Cdiff.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+time/Cdiff.m	Wed Jan 25 16:22:18 2017 +0100
@@ -12,22 +12,20 @@
 
 
     methods
+        % Solves u_tt = Du + Eu_t + S
+        % D, E, S can either all be constants or all be function handles,
+        % They can also be omitted by setting them equal to the empty matrix.
+        % Cdiff(D, E, S, k, t0, n0, v, v_prev)
         function obj = Cdiff(D, E, S, k, t0, n0, v, v_prev)
-            % Cdiff(D, E, S, k, t0, n0, v, v_prev)
-            m = size(D,1);
+            m = length(v);
             default_arg('E',sparse(m,m));
             default_arg('S',sparse(m,1));
 
-            if ~(issparse(D) && issparse(E) && issparse(S))
-                warning('One of the matrices D, E, S is not sparse!')
-                print_issparse(D)
-                print_issparse(E)
-                print_issparse(S)
-            end
-
             obj.D = D;
             obj.E = E;
             obj.S = S;
+
+
             obj.k = k;
             obj.t = t0;
             obj.n = n0;
diff -r 0976e579a6f0 -r 026d8a3fdbfb +time/CdiffImplicit.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+time/CdiffImplicit.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,150 @@
+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,1);
+            end
+
+            if isempty(f1)
+                f1 = sparse(m,1);
+            end
+
+            if isempty(f2)
+                f2 = sparse(m,1);
+            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 = 1;
+            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)
+            % Calculate next time step to be able to do centered diff.
+            v_next = zeros(size(obj.v));
+            b = obj.G(obj.t) - obj.BB*obj.v - obj.CC*obj.v_prev;
+
+            y = obj.L\b(obj.p);
+            z = obj.U\y;
+            v_next(obj.q) = z;
+
+
+            vt = (v_next-obj.v_prev)/(2*obj.k);
+            t = obj.t;
+        end
+
+        function obj = step(obj)
+            b = obj.G(obj.t) - obj.BB*obj.v - obj.CC*obj.v_prev;
+            obj.v_prev = obj.v;
+
+            % % Backslash
+            % obj.v = obj.AA\b;
+
+            % LU with column pivot
+            y = obj.L\b(obj.p);
+            z = obj.U\y;
+            obj.v(obj.q) = z;
+
+            % Update time
+            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
+
diff -r 0976e579a6f0 -r 026d8a3fdbfb +time/CdiffTimeDep.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+time/CdiffTimeDep.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,51 @@
+classdef CdiffTimeDep < time.Timestepper
+    properties
+        D
+        E
+        S
+        k
+        t
+        v
+        v_prev
+        n
+    end
+
+
+    methods
+        % Solves u_tt = Du + E(t)u_t + S(t)
+        % D, E, S can either all be constants or all be function handles,
+        % They can also be omitted by setting them equal to the empty matrix.
+        % CdiffTimeDep(D, E, S, k, t0, n0, v, v_prev)
+        function obj = CdiffTimeDep(D, E, S, k, t0, n0, v, v_prev)
+            m = length(v);
+            default_arg('E', @(t)sparse(m,m));
+            default_arg('S', @(t)sparse(m,1));
+
+            obj.D = D;
+            obj.E = E;
+            obj.S = S;
+
+            obj.k = k;
+            obj.t = t0;
+            obj.n = n0;
+            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; % Could be improved using u_tt = f(u))
+            t = obj.t;
+        end
+
+        function obj = step(obj)
+            [obj.v, obj.v_prev] = time.cdiff.cdiff(obj.v, obj.v_prev, obj.k, obj.D, obj.E(obj.t), obj.S(obj.t));
+            obj.t = obj.t + obj.k;
+            obj.n = obj.n + 1;
+        end
+    end
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb +time/Rungekutta4SecondOrder.m
--- a/+time/Rungekutta4SecondOrder.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+time/Rungekutta4SecondOrder.m	Wed Jan 25 16:22:18 2017 +0100
@@ -15,6 +15,9 @@
 
 
     methods
+        % Solves u_tt = Du + Eu_t + S
+        % D, E, S can either all be constants or all be function handles,
+        % They can also be omitted by setting them equal to the empty matrix.
         function obj = Rungekutta4SecondOrder(D, E, S, k, t0, v0, v0t)
             obj.D = D;
             obj.E = E;
@@ -22,21 +25,63 @@
             obj.m = length(v0);
             obj.n = 0;
 
-            I = speye(obj.m);
-            O = sparse(obj.m,obj.m);
-            obj.M = [O, I; D, E*I]; % Multiply with I to allow 0 as input.
+
+            if isa(D, 'function_handle') || isa(E, 'function_handle') || isa(S, 'function_handle')
+                default_arg('D', @(t)sparse(obj.m, obj.m));
+                default_arg('E', @(t)sparse(obj.m, obj.m));
+                default_arg('S', @(t)sparse(obj.m, 1)    );
+
+                if ~isa(D, 'function_handle')
+                    D = @(t)D;
+                end
+                if ~isa(E, 'function_handle')
+                    E = @(t)E;
+                end
+                if ~isa(S, 'function_handle')
+                    S = @(t)S;
+                end
 
-            if S == 0
-                obj.C = zeros(2*obj.m,1);
+                I = speye(obj.m);
+                O = sparse(obj.m,obj.m);
+
+                obj.M = @(t)[
+                       O,    I;
+                    D(t), E(t);
+                ];
+                obj.C = @(t)[
+                    zeros(obj.m,1);
+                              S(t);
+                ];
+
+                obj.k = k;
+                obj.t = t0;
+                obj.w = [v0; v0t];
+
+                obj.F = @(w,t)(obj.M(t)*w + obj.C(t));
             else
-                obj.C = [zeros(obj.m,1), S];
-            end
+
+                default_arg('D', sparse(obj.m, obj.m));
+                default_arg('E', sparse(obj.m, obj.m));
+                default_arg('S', sparse(obj.m, 1)    );
+
+                I = speye(obj.m);
+                O = sparse(obj.m,obj.m);
 
-            obj.k = k;
-            obj.t = t0;
-            obj.w = [v0; v0t];
+                obj.M = [
+                    O, I;
+                    D, E;
+                ];
+                obj.C = [
+                    zeros(obj.m,1);
+                                 S;
+                ];
 
-            obj.F = @(w,t)(obj.M*w + obj.C);
+                obj.k = k;
+                obj.t = t0;
+                obj.w = [v0; v0t];
+
+                obj.F = @(w,t)(obj.M*w + obj.C);
+            end
         end
 
         function [v,t] = getV(obj)
diff -r 0976e579a6f0 -r 026d8a3fdbfb +time/Rungekutta4proper.m
--- a/+time/Rungekutta4proper.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+time/Rungekutta4proper.m	Wed Jan 25 16:22:18 2017 +0100
@@ -10,6 +10,7 @@
 
 
     methods
+        % Timesteps v_t = F(v,t), using RK4 fromt t = t0 with timestep k and initial conditions v = v0
         function obj = Rungekutta4proper(F, k, t0, v0)
             obj.F = F;
             obj.k = k;
diff -r 0976e579a6f0 -r 026d8a3fdbfb +time/Timestepper.m
--- a/+time/Timestepper.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+time/Timestepper.m	Wed Jan 25 16:22:18 2017 +0100
@@ -60,6 +60,13 @@
             s = util.replace_string(s,'');
         end
 
+
+        function [v, t] = stepTo(obj, n, progress_bar)
+            default_arg('progress_bar',false);
+
+            [v, t] = obj.stepN(n-obj.n, progress_bar);
+        end
+
         function [v,t] = evolve(obj, tend, progress_bar)
             default_arg('progress_bar',false)
             if ~progress_bar
diff -r 0976e579a6f0 -r 026d8a3fdbfb +util/ReplaceableString.m
--- a/+util/ReplaceableString.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+util/ReplaceableString.m	Wed Jan 25 16:22:18 2017 +0100
@@ -34,10 +34,20 @@
             obj.display();
         end
 
+        function show(obj, varargin)
+            obj.param = varargin;
+            obj.display();
+        end
+
+        function remove(obj)
+            obj.update('');
+        end
+
         function display(obj)
             reverseStr = repmat(sprintf('\b'), 1, obj.n);
-            newStr = padStr(sprintf(obj.fmt, obj.param{:}),obj.n);
-            fprintf([reverseStr, newStr]);
+            cleareStr = repmat(sprintf(' '), 1, obj.n);
+            newStr = sprintf(obj.fmt, obj.param{:});
+            fprintf([reverseStr, cleareStr, reverseStr, newStr]);
 
             obj.n = length(newStr);
         end
diff -r 0976e579a6f0 -r 026d8a3fdbfb +util/calc_borrowing.m
--- a/+util/calc_borrowing.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/+util/calc_borrowing.m	Wed Jan 25 16:22:18 2017 +0100
@@ -1,97 +1,241 @@
+function calc_borrowing(m, h)
+    default_arg('m',100);
+    default_arg('h',1);
 
-m = 100;
-h = 1;
+    operators = {
+        {
+            'd4_lonely', getM4_lonely, {
+                {4, 'min_boundary_points'},
+                {6, 'min_boundary_points'},
+                {6, '2'},
+                {6, '3'},
+                {8, 'min_boundary_points'},
+                {8, 'higher_boundary_order'},
+            }
+        }, {
+            'd4_variable', {
+                {2},
+                {4},
+                {6},
+            }
+        }
+        % BORKEN BAD IDEA
+    }
+
+
+    for i = 1:operators
+        baseName = operators{i}{1};
+        postFixes = operators{i}{2};
+        for pf = postFixes
+            [a2, a3] = borrowFromD4(m, h, l{:});
+        end
+    end
 
 
-%% 4th order non-compatible
-[H, HI, D1, D2, D3, D4, e_1, e_m, M, M4,Q, Q3, S2_1, S2_m, S3_1, S3_m, S_1, S_m] = sbp.higher4(m,h);
-S1 = S_1*S_1'  + S_m*S_m';
-S2 = S2_1*S2_1' + S2_m*S2_m';
-S3 = S3_1*S3_1' + S3_m*S3_m';
+
+    lonely = {
+        {4, 'min_boundary_points'},
+        {6, 'min_boundary_points'},
+        {6, '2'},
+        {6, '3'},
+        {8, 'min_boundary_points'},
+        {8, 'higher_boundary_order'},
+    };
 
-alpha_I  = util.matrixborrow(M4, h^-1*S1  );
-alpha_II  = util.matrixborrow(M4, h*S2  );
-alpha_III = util.matrixborrow(M4, h^3*S3);
-fprintf('4th order non-compatible\n')
-fprintf('alpha_I1:  %.10f\n',alpha_I)
-fprintf('alpha_II:  %.10f\n',alpha_II)
-fprintf('alpha_III: %.10f\n',alpha_III)
-fprintf('\n')
-
+    for i = 1:length(lonely)
+        l = lonely{i};
+        [a2, a3] = d4_lonely(m, h, l{:});
+        fprintf('d4_lonely %d %s\n', l{:})
+        fprintf('\t  alpha_II = %f\n', a2)
+        fprintf('\t alpha_III = %f\n', a3)
+        fprintf('\n')
+    end
 
-%% 6th order non-compatible
-[H, HI, D1, D2, D3, D4, e_1, e_m, M, M4,Q, Q3, S2_1, S2_m, S3_1, S3_m, S_1, S_m] = sbp.higher6(m,h);
-S1 = S_1*S_1'  + S_m*S_m';
-S2 = S2_1*S2_1' + S2_m*S2_m';
-S3 = S3_1*S3_1' + S3_m*S3_m';
+    variable = {
+        {2},
+        {4},
+        {6},
+    };
 
-alpha_II  = util.matrixborrow(M4, h*S2  );
-alpha_III = util.matrixborrow(M4, h^3*S3);
-fprintf('6th order non-compatible\n')
-fprintf('alpha_II:  %.10f\n',alpha_II)
-fprintf('alpha_III: %.10f\n',alpha_III)
-fprintf('\n')
+    for i = 1:length(variable)
+        l = variable{i};
+        [a2, a3] = d4_variable(m, h, l{:});
+        fprintf('d4_variable %d\n', l{:})
+        fprintf('\t  alpha_II = %f\n', a2)
+        fprintf('\t alpha_III = %f\n', a3)
+        fprintf('\n')
+    end
 
 
-%% 2nd order compatible
-[H, HI, D1, D4, e_1, e_m, M4, Q, S2_1, S2_m, S3_1, S3_m, S_1, S_m] = sbp.higher_compatible2(m,h);
-S1 = S_1*S_1'  + S_m*S_m';
-S2 = S2_1*S2_1' + S2_m*S2_m';
-S3 = S3_1*S3_1' + S3_m*S3_m';
+    %% 4th order non-compatible
+    [H, HI, D1, D2, D3, D4, e_1, e_m, M, M4,Q, Q3, S2_1, S2_m, S3_1, S3_m, S_1, S_m] = sbp.higher4(m,h);
+    S1 = S_1*S_1'  + S_m*S_m';
+    S2 = S2_1*S2_1' + S2_m*S2_m';
+    S3 = S3_1*S3_1' + S3_m*S3_m';
 
-alpha_II  = util.matrixborrow(M4, h*S2  );
-alpha_III = util.matrixborrow(M4, h^3*S3);
-fprintf('2nd order compatible\n')
-fprintf('alpha_II:  %.10f\n',alpha_II)
-fprintf('alpha_III: %.10f\n',alpha_III)
-fprintf('\n')
+    alpha_I  = util.matrixborrow(M4, h^-1*S1  );
+    alpha_II  = util.matrixborrow(M4, h*S2  );
+    alpha_III = util.matrixborrow(M4, h^3*S3);
+    fprintf('4th order non-compatible\n')
+    fprintf('alpha_I1:  %.10f\n',alpha_I)
+    fprintf('alpha_II:  %.10f\n',alpha_II)
+    fprintf('alpha_III: %.10f\n',alpha_III)
+    fprintf('\n')
+
+
+    %% 6th order non-compatible
+    [H, HI, D1, D2, D3, D4, e_1, e_m, M, M4,Q, Q3, S2_1, S2_m, S3_1, S3_m, S_1, S_m] = sbp.higher6(m,h);
+    S1 = S_1*S_1'  + S_m*S_m';
+    S2 = S2_1*S2_1' + S2_m*S2_m';
+    S3 = S3_1*S3_1' + S3_m*S3_m';
+
+    alpha_II  = util.matrixborrow(M4, h*S2  );
+    alpha_III = util.matrixborrow(M4, h^3*S3);
+    fprintf('6th order non-compatible\n')
+    fprintf('alpha_II:  %.10f\n',alpha_II)
+    fprintf('alpha_III: %.10f\n',alpha_III)
+    fprintf('\n')
 
 
-%% 4th order compatible
-[H, HI, D1, D4, e_1, e_m, M4, Q, S2_1, S2_m, S3_1, S3_m, S_1, S_m] = sbp.higher_compatible4(m,h);
-S1 = S_1*S_1'  + S_m*S_m';
-S2 = S2_1*S2_1' + S2_m*S2_m';
-S3 = S3_1*S3_1' + S3_m*S3_m';
+    %% 2nd order compatible
+    [H, HI, D1, D4, e_1, e_m, M4, Q, S2_1, S2_m, S3_1, S3_m, S_1, S_m] = sbp.higher_compatible2(m,h);
+    S1 = S_1*S_1'  + S_m*S_m';
+    S2 = S2_1*S2_1' + S2_m*S2_m';
+    S3 = S3_1*S3_1' + S3_m*S3_m';
 
-alpha_II  = util.matrixborrow(M4, h*S2  );
-alpha_III = util.matrixborrow(M4, h^3*S3);
-fprintf('4th order compatible\n')
-fprintf('alpha_II:  %.10f\n',alpha_II)
-fprintf('alpha_III: %.10f\n',alpha_III)
-fprintf('\n')
+    alpha_II  = util.matrixborrow(M4, h*S2  );
+    alpha_III = util.matrixborrow(M4, h^3*S3);
+    fprintf('2nd order compatible\n')
+    fprintf('alpha_II:  %.10f\n',alpha_II)
+    fprintf('alpha_III: %.10f\n',alpha_III)
+    fprintf('\n')
+
+
+    %% 4th order compatible
+    [H, HI, D1, D4, e_1, e_m, M4, Q, S2_1, S2_m, S3_1, S3_m, S_1, S_m] = sbp.higher_compatible4(m,h);
+    S1 = S_1*S_1'  + S_m*S_m';
+    S2 = S2_1*S2_1' + S2_m*S2_m';
+    S3 = S3_1*S3_1' + S3_m*S3_m';
 
-%% 6th order compatible
-[H, HI, D1, D4, e_1, e_m, M4, Q, S2_1, S2_m, S3_1, S3_m, S_1, S_m] = sbp.higher_compatible6(m,h);
-S1 = S_1*S_1'  + S_m*S_m';
-S2 = S2_1*S2_1' + S2_m*S2_m';
-S3 = S3_1*S3_1' + S3_m*S3_m';
+    alpha_II  = util.matrixborrow(M4, h*S2  );
+    alpha_III = util.matrixborrow(M4, h^3*S3);
+    fprintf('4th order compatible\n')
+    fprintf('alpha_II:  %.10f\n',alpha_II)
+    fprintf('alpha_III: %.10f\n',alpha_III)
+    fprintf('\n')
 
-alpha_II  = util.matrixborrow(M4, h*S2  );
-alpha_III = util.matrixborrow(M4, h^3*S3);
-fprintf('6th order compatible\n')
-fprintf('alpha_II:  %.10f\n',alpha_II)
-fprintf('alpha_III: %.10f\n',alpha_III)
-fprintf('\n')
+    %% 6th order compatible
+    [H, HI, D1, D4, e_1, e_m, M4, Q, S2_1, S2_m, S3_1, S3_m, S_1, S_m] = sbp.higher_compatible6(m,h);
+    S1 = S_1*S_1'  + S_m*S_m';
+    S2 = S2_1*S2_1' + S2_m*S2_m';
+    S3 = S3_1*S3_1' + S3_m*S3_m';
+
+    alpha_II  = util.matrixborrow(M4, h*S2  );
+    alpha_III = util.matrixborrow(M4, h^3*S3);
+    fprintf('6th order compatible\n')
+    fprintf('alpha_II:  %.10f\n',alpha_II)
+    fprintf('alpha_III: %.10f\n',alpha_III)
+    fprintf('\n')
 
 
 
 
 
-% Ordinary
+    % Ordinary
+
+    for order = [2 4 6 8 10]
+        op = sbp.Ordinary(m,h, order);
+
+        S_1 = op.boundary.S_1;
+        S_m = op.boundary.S_m;
+
+        M = op.norms.M;
 
-for order = [2 4 6 8 10]
-    op = sbp.Ordinary(m,h, order);
+        S1 = S_1*S_1'  + S_m*S_m';
+        alpha  = util.matrixborrow(M, h*S1);
+        fprintf('%dth order Ordinary\n', order)
+        fprintf('alpha:  %.10f\n', alpha)
+        fprintf('\n')
+    end
 
-    S_1 = op.boundary.S_1;
-    S_m = op.boundary.S_m;
+
+
+
+end
 
-    M = op.norms.M;
+function [alpha_II, alpha_III] = d4_lonely(m, h, order, modifier)
+    default_arg('modifier', [])
+    func = sprintf('sbp.implementations.d4_lonely_%d', order);
+    if ~isempty(modifier)
+        func = sprintf('%s_%s', func, modifier);
+    end
+    funcCall = sprintf('%s(%s,%s)', func, toString(m), toString(h));
+    [H, HI, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = eval(funcCall);
+
+    d2d2 = d2_l*d2_l' + d2_r*d2_r';
+    alpha_II  = util.matrixborrow(M4, h*d2d2);
+
+    d3d3 = d3_l*d3_l' + d3_r*d3_r';
+    alpha_III = util.matrixborrow(M4, h^3*d3d3);
+end
 
-    S1 = S_1*S_1'  + S_m*S_m';
-    alpha  = util.matrixborrow(M, h*S1);
-    fprintf('%dth order Ordinary\n', order)
-    fprintf('alpha:  %.10f\n', alpha)
-    fprintf('\n')
+function [alpha_II, alpha_III] = d4_variable(m, h, order)
+    default_arg('modifier', [])
+    func = sprintf('sbp.implementations.d4_variable_%d', order);
+
+    funcCall = sprintf('%s(%s,%s)', func, toString(m), toString(h));
+    [H, HI, D1, D2, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = eval(funcCall);
+
+    d2d2 = d2_l*d2_l' + d2_r*d2_r';
+    alpha_II  = util.matrixborrow(M4, h*d2d2);
+
+    d3d3 = d3_l*d3_l' + d3_r*d3_r';
+    alpha_III = util.matrixborrow(M4, h^3*d3d3);
+end
+
+function [d2_l, d2_r, d3_l, d3_r, M4] = getM4_lonely(m, h, order, modifier)
+    fStr = getFunctionCallStr('d4_lonely', {order, modifier}, {m ,h});
+    [H, HI, D4, e_l, e_r, M4, d2_l, d2_r, d3_l, d3_r, d1_l, d1_r] = eval(funcCall);
 end
 
 
+% Calculates the borrowing constants for a D4 operator.
+% getM4 is a function handle on the form
+%  [d2_l, d2_r, d3_l, d3_r, M4] = getM4(m,h)
+function [a2, a3] = borrowFromD4(m, h, getM4)
+    [d2_l, d2_r, d3_l, d3_r, M4] = getM4(m, h);
+
+    d2d2 = d2_l*d2_l' + d2_r*d2_r';
+    a2  = util.matrixborrow(M4, h*d2d2);
+
+    d3d3 = d3_l*d3_l' + d3_r*d3_r';
+    a3 = util.matrixborrow(M4, h^3*d3d3);
+end
+
+
+function funcCallStr = getFunctionCallStr(baseName, postFix, parameters)
+    default_arg('postFix', [])
+    default_arg('parameters', [])
+
+    funcCallStr = sprintf('sbp.implementations.%s', baseName);
+
+    for i = 1:length(postFix)
+        if ischar(postFix{i})
+            funcCallStr = [funcCallStr '_' postFix{i}];
+        else
+            funcCallStr = [funcCallStr '_' toString(postFix{i})];
+        end
+    end
+
+    if isempty(parameters)
+        return
+    end
+
+    funcCallStr = [funcCallStr '(' toString(parameters{1})];
+
+    for i = 2:length(parameters)
+        funcCallStr = [funcCallStr ', ' toString(parameters{i})];
+    end
+
+    funcCallStr = [funcCallStr ')';
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb Dictionary.m
--- a/Dictionary.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/Dictionary.m	Wed Jan 25 16:22:18 2017 +0100
@@ -98,14 +98,11 @@
         % Should probably use mat2str with some kind of normalization to make all variables valied fieldname
         %  and make it possible to recover the value
         function fName = getFieldname(obj, val)
-            if isnumeric(val)
-                valStr = num2str(val);
-            elseif ischar(val)
-                valStr = val;
-            else
-                error('Dont know what to do with val!');
+            if ~ischar(val)
+                val = toString(val);
             end
-            fName = sprintf('f%s',valStr);
+
+            fName = matlab.lang.makeValidName(val);
         end
     end
 end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb cell2sparse.m
--- a/cell2sparse.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-function A = cell2sparse(C)
-
-    if isempty(C)
-        A = sparse([]);
-        return
-    end
-
-    n = row_height(C);
-    m = col_width(C);
-
-    N = sum(n);
-    M = sum(m);
-
-    A = sparse(N,M);
-
-    n_ind = [0 cumsum(n)];
-    m_ind = [0 cumsum(m)];
-
-    for i = 1:size(C,1)
-        for j = 1:size(C,2)
-            if ~has_matrix(C{i,j})
-                continue
-            end
-            A(n_ind(i)+1:n_ind(i+1),m_ind(j)+1:m_ind(j+1)) = C{i,j};
-        end
-    end
-
-end
-
-function m = col_width(C)
-    for j = 1:size(C,2)
-        for i = 1:size(C,1)
-            if ~has_matrix(C{i,j})
-                continue
-            end
-            m(j) = size(C{i,j},2);
-        end
-    end
-end
-
-function n = row_height(C)
-    for i = 1:size(C,1)
-        for j = 1:size(C,2)
-            if ~has_matrix(C{i,j})
-                continue
-            end
-            n(i) = size(C{i,j},1);
-        end
-    end
-end
-
-function b = has_matrix(c)
-    b = ~(isempty(c) || (numel(c)==1 && c == 0));
-end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb cell2vector.m
--- a/cell2vector.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-% cell2vector accepts a column cell array of column vectors and returns a columnvector
-% with the input concatenated. It also returns the number of elements in each vector.
-%   cv -- column cell array with column vectors
-%   v  -- vector of the concatenated vectors
-%   n  -- number of elements in each vector before concatenation. Can be used with vector2cell().
-function [v, n] = cell2vector(cv)
-    v = [];
-    n = zeros(length(cv),1);
-
-    for i = 1:length(cv)
-        n(i) = length(cv{i});
-        v = [v; cv{i}];
-    end
-end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb copyWithDefault.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/copyWithDefault.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,31 @@
+% Copy the struct src to dest with default values from default
+%   dest = copyWithDefault(src, default)
+function dest = copyWithDefault(src, default)
+    % src does not have a value => use default
+    if isempty(src)
+        dest = default;
+        return
+    end
+
+    % src has a value and is not a struct => use src
+    % src has a value and default is not a struct => use src
+    if ~isstruct(src) || ~isstruct(default)
+        dest = src;
+        return
+    end
+
+
+    % src has a value and is a struct => add all default fields
+    dest = src;
+
+    fn = fieldnames(default);
+    for i = 1:length(fn)
+        if isfield(src, fn{i})
+            srcField = src.(fn{i});
+        else
+            srcField = [];
+        end
+
+        dest.(fn{i}) = copyWithDefault(srcField, default.(fn{i}));
+    end
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb default_struct.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/default_struct.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,10 @@
+function default_struct(s, val)
+    if evalin('caller',sprintf('~exist(''%s'',''var'')',s))
+        given = [];
+    else
+        given = evalin('caller', s);
+    end
+
+    final = copyWithDefault(given, val);
+    assignin('caller', s, final);
+end
diff -r 0976e579a6f0 -r 026d8a3fdbfb findZeros.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/findZeros.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,30 @@
+% findZeros looks for solutions to the equation f(x)==0 within
+% the limits lim with a granularity of h.
+% Returns a sorted list of unique solutions.
+function z = findZeros(f, lim, h)
+    n = ceil((lim(2)-lim(1))/h);
+    z0 = linspace(lim(1), lim(2), n);
+
+    z = zeros(1,n);
+
+    for i = 1:n
+        zt(i) = fzero(f, z0(i));
+    end
+
+    zt = sort(zt);
+
+    z = [];
+    for i = 1:n
+        if zt(i)  < lim(1) || zt(i) > lim(2)
+            continue
+        end
+
+        if ~isempty(z) && abs(z(end) - zt(i)) < 1e-6
+            continue
+        end
+
+        z = [z zt(i)];
+    end
+
+    % z = unique(z);
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb minors.m
--- a/minors.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/minors.m	Wed Jan 25 16:22:18 2017 +0100
@@ -1,4 +1,5 @@
-function [minor, sub] = minors(A)
+function [minor, sub] = minors(A, verbose)
+    default_arg('verbose', true);
     [n, m] = size(A);
 
     if n ~= m
@@ -18,8 +19,10 @@
     end
 
     for i = 1:length(sub)
-        fprintf('%d:\n', ks{i});
-        disp(sub{i})
+        if verbose
+            fprintf('%d:\n', ks{i});
+            disp(sub{i})
+        end
 
         minor(i) = det(sub{i});
     end
diff -r 0976e579a6f0 -r 026d8a3fdbfb reshapeRowMaj.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/reshapeRowMaj.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,12 @@
+% Reshapes a matrix as if it was stored in row major order.
+function B = reshapeRowMaj(A, m)
+    D = length(m);
+
+    if D == 1
+        m = [m 1];
+        D = 2;
+    end
+
+    % Reshape and reverse order of indecies
+    B = permute(reshape(permute(A, ndims(A):-1:1), rot90(m,2)), D:-1:1);
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb reshapeRowMajTest.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/reshapeRowMajTest.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,113 @@
+function tests = reshapeRowMajTest()
+    tests = functiontests(localfunctions);
+end
+
+function test1D(testCase)
+    in = {
+        {5,[1; 2; 3; 4; 5]},
+        {5,[1 2 3 4 5]},
+    };
+    out = {
+        [1; 2; 3; 4; 5],
+        [1; 2; 3; 4; 5],
+    };
+    for i = 1:length(in)
+        testCase.verifyEqual(reshapeRowMaj(in{i}{2}, in{i}{1}),out{i});
+    end
+end
+
+
+function testIdentity(testCase)
+     in = {
+        {[2,2], magic(2)},
+        {[3,3], magic(3)},
+        {[2,3], [1 2 3; 4 5 6]},
+    };
+
+    for i = 1:length(in)
+        testCase.verifyEqual(reshapeRowMaj(in{i}{2}, in{i}{1}),in{i}{2});
+    end
+end
+
+function test2D(testCase)
+    in = {
+        {[2,2],[11; 12; 21; 22]},
+        {[3,2],[1 2 3; 4 5 6]},
+        {[6 1],[1 2 3; 4 5 6]},
+        {[1 6],[1 2 3; 4 5 6]},
+    };
+
+    out{1}(1,1) = 11;
+    out{1}(1,2) = 12;
+    out{1}(2,1) = 21;
+    out{1}(2,2) = 22;
+
+    out{2} = [1 2; 3 4; 5 6];
+    out{3} = [1; 2; 3; 4; 5; 6];
+    out{4} = [1 2 3 4 5 6];
+
+    for i = 1:length(in)
+        testCase.verifyEqual(reshapeRowMaj(in{i}{2}, in{i}{1}),out{i});
+    end
+end
+
+function test3D(testCase)
+    in = {
+        {[2, 2, 2], [111; 112; 121; 122; 211; 212; 221; 222]},
+        {[8 1], cat(3,[1 2; 3 4],[5 6; 7 8])},
+        {[1 8], cat(3,[1 2; 3 4],[5 6; 7 8])},
+        {[2 4], cat(3,[1 2; 3 4],[5 6; 7 8])},
+        {[4 2], cat(3,[1 2; 3 4],[5 6; 7 8])},
+    };
+
+    out{1}(1,1,1) = 111;
+    out{1}(1,1,2) = 112;
+    out{1}(1,2,1) = 121;
+    out{1}(1,2,2) = 122;
+    out{1}(2,1,1) = 211;
+    out{1}(2,1,2) = 212;
+    out{1}(2,2,1) = 221;
+    out{1}(2,2,2) = 222;
+
+    out{2} = [1; 5; 2; 6; 3; 7; 4; 8];
+    out{3} = [1  5  2  6  3  7  4  8];
+    out{4} = [1  5  2  6;  3  7  4  8];
+    out{5} = [1  5;  2  6;  3  7;  4  8];
+
+    for i = 1:length(in)
+        testCase.verifyEqual(reshapeRowMaj(in{i}{2}, in{i}{1}),out{i});
+    end
+end
+
+function testNonSquare(testCase)
+    in = {
+        {[2, 3, 4],[111; 112; 113; 114; 121; 122; 123; 124; 131; 132; 133; 134; 211; 212; 213; 214; 221; 222; 223; 224; 231; 232; 233; 234]},
+    };
+    out{1}(1,1,1) = 111;
+    out{1}(1,1,2) = 112;
+    out{1}(1,1,3) = 113;
+    out{1}(1,1,4) = 114;
+    out{1}(1,2,1) = 121;
+    out{1}(1,2,2) = 122;
+    out{1}(1,2,3) = 123;
+    out{1}(1,2,4) = 124;
+    out{1}(1,3,1) = 131;
+    out{1}(1,3,2) = 132;
+    out{1}(1,3,3) = 133;
+    out{1}(1,3,4) = 134;
+    out{1}(2,1,1) = 211;
+    out{1}(2,1,2) = 212;
+    out{1}(2,1,3) = 213;
+    out{1}(2,1,4) = 214;
+    out{1}(2,2,1) = 221;
+    out{1}(2,2,2) = 222;
+    out{1}(2,2,3) = 223;
+    out{1}(2,2,4) = 224;
+    out{1}(2,3,1) = 231;
+    out{1}(2,3,2) = 232;
+    out{1}(2,3,3) = 233;
+    out{1}(2,3,4) = 234;
+    for i = 1:length(in)
+        testCase.verifyEqual(reshapeRowMaj(in{i}{2}, in{i}{1}),out{i});
+    end
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb reshapeToPlotMatrix.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/reshapeToPlotMatrix.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,17 @@
+% Takes a grid function and reshapes it into a matrix of shape m for plotting.
+function F = reshapeToPlotMatrix(gf, m)
+    D = length(m);
+
+    switch D
+        case 1
+            F = gf;
+        case 2
+            F = reshape(gf, rot90(m,2));
+        case 3
+            % After the reshape the indecies will be M(z,y,x). Plot need them to be M(y,x,z)
+            p = [2 3 1]; % Permuation
+            F = permute(reshape(gf,rot90(m,2)), p);
+        otherwise
+            error('reshapeToPlotMatrix:NotImplemented','Grid function to matrix is not implemented for dimension = %d', length(m));
+    end
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb reshapeToPlotMatrixTest.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/reshapeToPlotMatrixTest.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,48 @@
+function tests = reshapeToPlotMatrixTest()
+    tests = functiontests(localfunctions);
+end
+
+function test1D(testCase)
+    inGf = [1 2 3 4 5]';
+    inM = 5;
+    out = [1 2 3 4 5]';
+    testCase.verifyEqual(reshapeToPlotMatrix(inGf, inM),out);
+end
+
+function test2D(testCase)
+    x = 1:2;
+    y = 1:3;
+
+    f = @(x,y) x + y*10;
+
+    xx = [1; 1; 1; 2; 2; 2];
+    yy = [1; 2; 3; 1; 2; 3];
+    inGf = f(xx,yy);
+
+    [X,Y] = meshgrid(x,y);
+    out = f(X,Y);
+
+    inM = [2, 3];
+
+    testCase.verifyEqual(reshapeToPlotMatrix(inGf, inM),out);
+end
+
+function test3D(testCase)
+    x = 1:2;
+    y = 1:3;
+    z = 1:4;
+
+    f = @(x,y,z) x + y*10 + z*100;
+
+    xx = [repmat(1, [12, 1]); repmat(2, [12, 1])];
+    yy = repmat([1; 1; 1; 1; 2; 2; 2; 2; 3; 3; 3; 3], [2, 1]);
+    zz = repmat([1; 2; 3; 4], [6, 1]);
+    inGf = f(xx,yy,zz);
+
+    [X,Y,Z] = meshgrid(x,y,z);
+    out = f(X,Y,Z);
+
+    inM = [2, 3, 4];
+
+    testCase.verifyEqual(reshapeToPlotMatrix(inGf, inM),out);
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb runtestsPackage.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/runtestsPackage.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,4 @@
+function res = runtestsPackage(pkgName)
+    ts = matlab.unittest.TestSuite.fromPackage(pkgName);
+    res = ts.run();
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb saveFigureSize.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/saveFigureSize.m	Wed Jan 25 16:22:18 2017 +0100
@@ -0,0 +1,6 @@
+function saveFigurePosition()
+    defaultPosition = get(0,'defaultfigureposition');
+    f = gcf;
+    defaultPosition(3:4) = f.Position(3:4);
+    set(0,'defaultfigureposition',defaultPosition);
+end
\ No newline at end of file
diff -r 0976e579a6f0 -r 026d8a3fdbfb semiDefIneq.m
--- a/semiDefIneq.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/semiDefIneq.m	Wed Jan 25 16:22:18 2017 +0100
@@ -1,5 +1,6 @@
-function ineq = semiDefIneq(A)
-    [m, sub] = minors(A);
+function ineq = semiDefIneq(A, verbose)
+    default_arg('verbose', true);
+    [m, sub] = minors(A, verbose);
 
     ineqsys = true;
     for i = 1:length(m)
diff -r 0976e579a6f0 -r 026d8a3fdbfb timeTask.m
--- a/timeTask.m	Wed Jan 25 16:21:14 2017 +0100
+++ b/timeTask.m	Wed Jan 25 16:22:18 2017 +0100
@@ -1,5 +1,5 @@
-function done = timeTask(taskName)
-    fprintf('%s', taskName);
+function done = timeTask(fmt, varargin)
+    fprintf(fmt, varargin{:});
     tStart = tic;
 
     function done_fun()
diff -r 0976e579a6f0 -r 026d8a3fdbfb vector2cell.m
--- a/vector2cell.m	Wed Jan 25 16:21:14 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-% Splits column vector v into segments of length n and returns the result as a column cell array.
-%   v  -- column vector to be split
-%   n  -- number of elements in each part
-%
-%   cv -- cell array of vectors with lenght n(i)
-function cv = vector2cell(v,n)
-    cv = cell(length(n),1);
-
-    ind = [0; cumsum(n)];
-    for i = 1:length(n)
-        ind_i = (ind(i)+1):ind(i+1);
-        cv{i} = v(ind_i);
-    end
-end
\ No newline at end of file