changeset 170:62b5f3c34bcb feature/grids

Implemented Curvilinear and equdistantCurvilinear.
author Jonatan Werpers <jonatan@werpers.com>
date Thu, 25 Feb 2016 11:10:25 +0100
parents ba8adcaf4681
children 0e56192f6459
files +grid/Curvilinear.m +grid/CurvilinearTest.m +grid/Mapped.m +grid/equidistantCurvilinear.m +grid/equidistantCurvilinearTest.m
diffstat 5 files changed, 213 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/+grid/Curvilinear.m	Wed Feb 24 15:04:22 2016 +0100
+++ b/+grid/Curvilinear.m	Thu Feb 25 11:10:25 2016 +0100
@@ -1,10 +1,96 @@
-classdef Curvilinear < grid.Structured
-    % General grid mapping
-    methods (Abstract)
-        % baseGrid returns the domain grid of the mapping.
-        g = baseGrid(obj);
+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 matrix or a cell array with physical coordinates.
+        %                   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)
+                if ~isequal(size(mapping),[1 D])
+                    error('grid:Curvilinear:Curvilinear','The cell array must be a row array.');
+                end
+
+                if isequal(size(mapping{1}),[N 1])
+                    obj.coords = cell2mat(mapping);
+                elseif isequal(size(mapping{1}), obj.logic.m)
+                    for i = 1:length(mapping)
+                        obj.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(obj.logic.m));
+                end
+
+            elseif isnumeric(mapping)
+                if isequal(size(mapping), [N, D])
+                    obj.coords = mapping;
+                elseif isequal(size(mapping), [N*D, 1])
+                    obj.coords = reshapeRowMaj(mapping,[N D]);
+                else
+                    error('grid:Curvilinear:Curvilinear','A matrix mapping must be of size [N D] or [N*D 1].');
+                end
+            else
+                error('grid:Curvilinear:Curvilinear','mapping must be 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
-        m = mapping(obj);
+        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.baseGrid());
+        end
+
+        % Projects the grid function gf on obj to the grid g.
+        function gf = projectFunc(obj, gf, g)
+            gf = obj.logic.projectFunc(gf,g.baseGrid());
+        end
     end
 end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/CurvilinearTest.m	Thu Feb 25 11:10:25 2016 +0100
@@ -0,0 +1,71 @@
+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.assumeFail();
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/Mapped.m	Thu Feb 25 11:10:25 2016 +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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/equidistantCurvilinear.m	Thu Feb 25 11:10:25 2016 +0100
@@ -0,0 +1,33 @@
+% 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 = {};
+    for i = 1:length(m)
+        X{i} = util.get_grid(varargin{i}{:},m(i));
+    end
+
+    g = grid.Curvilinear(mapping, X{:});
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/equidistantCurvilinearTest.m	Thu Feb 25 11:10:25 2016 +0100
@@ -0,0 +1,7 @@
+function tests = equdistantCurvilinearTest()
+    tests = functiontests(localfunctions);
+end
+
+function testNoTests(testCase)
+    testCase.assumeFail();
+end
\ No newline at end of file