changeset 154:c7b2f645101f feature/grids

Added classes and functions for Cartesian and equidistant grids.
author Jonatan Werpers <jonatan@werpers.com>
date Thu, 18 Feb 2016 16:46:02 +0100
parents 7aee9eba3bb8
children cf748f33cd5b
files +grid/Cartesian.m +grid/CartesianTest.m +grid/equidistant.m +grid/equidistantTest.m
diffstat 4 files changed, 253 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
diff -r 7aee9eba3bb8 -r c7b2f645101f +grid/Cartesian.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/Cartesian.m	Thu Feb 18 16:46:02 2016 +0100
@@ -0,0 +1,78 @@
+classdef Cartesian < grid.Grid
+    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.
+    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
+        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
+
+        % 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
+
+        % coordVectors()
+        % coordMatrices()
+    end
+end
\ No newline at end of file
diff -r 7aee9eba3bb8 -r c7b2f645101f +grid/CartesianTest.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/CartesianTest.m	Thu Feb 18 16:46:02 2016 +0100
@@ -0,0 +1,98 @@
+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 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
\ No newline at end of file
diff -r 7aee9eba3bb8 -r c7b2f645101f +grid/equidistant.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/equidistant.m	Thu Feb 18 16:46:02 2016 +0100
@@ -0,0 +1,27 @@
+% 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 = {};
+    for i = 1:length(m)
+        X{i} = util.get_grid(varargin{i}{:},m(i));
+    end
+
+    g = grid.Cartesian(X{:});
+end
\ No newline at end of file
diff -r 7aee9eba3bb8 -r c7b2f645101f +grid/equidistantTest.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/equidistantTest.m	Thu Feb 18 16:46:02 2016 +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
\ No newline at end of file