changeset 535:b52ea450f4c3 feature/grids

Merge feature/boundaryGroup
author Jonatan Werpers <jonatan@werpers.com>
date Mon, 07 Aug 2017 09:56:01 +0200
parents 3011f9a28ac8 (current diff) 55a7777dfcd0 (diff)
children 6c6a3040a678
files +multiblock/BoundaryGroupTest.m +multiblock/boundaryIdentifier.txt
diffstat 7 files changed, 100 insertions(+), 99 deletions(-) [+]
line wrap: on
line diff
--- a/+grid/Grid.m	Wed Aug 02 19:26:39 2017 +0200
+++ b/+grid/Grid.m	Mon Aug 07 09:56:01 2017 +0200
@@ -16,7 +16,7 @@
         % 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.
+        % Return the grid.boundaryIdentifiers of all boundaries in a cell array.
         bs = getBoundaryNames(obj)
 
         % Return coordinates for the given boundary
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+grid/boundaryIdentifier.txt	Mon Aug 07 09:56:01 2017 +0200
@@ -0,0 +1,5 @@
+A grid.boundaryIdentifier identifies a boundary of a grid.
+For a Cartesian grid it is simply 's', 'n', 'w', 'e'.
+For a multiblock grid it might be something like {1, 's'}.
+For some other grid it will be up to the developer to chose
+a good way to identify boundaries.
--- a/+multiblock/BoundaryGroup.m	Wed Aug 02 19:26:39 2017 +0200
+++ b/+multiblock/BoundaryGroup.m	Mon Aug 07 09:56:01 2017 +0200
@@ -1,30 +1,10 @@
 % BoundaryGroup defines a boundary grouping in a multiblock grid.
-classdef BoundaryGroup
-    properties
-        blockIDs
-        names
-    end
-
+% It workds like a cell array and collects boundary identifiers
+% Within the multiblock package a BoundaryGroup is a valid boundary identifier as well.
+classdef BoundaryGroup < Cell
     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
+        function obj = BoundaryGroup(data)
+            obj = obj@Cell(data);
         end
 
         function display(obj, name)
@@ -33,19 +13,7 @@
             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')
+            fprintf('    BoundaryGroup%s\n\n', toString(obj.data));
         end
     end
-end
\ No newline at end of file
+end
--- a/+multiblock/BoundaryGroupTest.m	Wed Aug 02 19:26:39 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-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
--- a/+multiblock/DiffOp.m	Wed Aug 02 19:26:39 2017 +0200
+++ b/+multiblock/DiffOp.m	Mon Aug 07 09:56:01 2017 +0200
@@ -120,27 +120,54 @@
             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);
+        % Get a boundary operator specified by opName for the given boundary/BoundaryGroup
+        function op = getBoundaryOperator(obj, opName, boundary)
+            switch class(boundary)
+                case 'cell'
+                    localOpName = [opName '_' 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.
+                    div = {obj.blockmatrixDiv{1}, size(localOp,2)};
+                    blockOp = blockmatrix.zero(div);
+                    blockOp{blockId,1} = localOp;
+                    op = blockmatrix.toMatrix(blockOp);
+                    return
+                case 'multiblock.BoundaryGroup'
+                    op = [];
+                    for i = 1:length(boundary)
+                        op = [op, obj.getBoundaryOperator(opName, boundary{i})];
+                    end
+                otherwise
+                    error('Unknown boundary indentifier')
             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'}
+        %                boundary of that block example: {1,'s'} or {3,'w'}. It
+        %                can also be a boundary group
         function [closure, penalty] = boundary_condition(obj, boundary, type)
+            switch class(boundary)
+                case 'cell'
+                    [closure, penalty] = obj.singleBoundaryCondition(boundary, type);
+                case 'multiblock.BoundaryGroup'
+                    [n,m] = size(obj.D);
+                    closure = sparse(n,m);
+                    penalty = [];
+                    for i = 1:length(boundary)
+                        [closurePart, penaltyPart] = obj.boundary_condition(boundary{i}, type);
+                        closure = closure + closurePart;
+                        penalty = [penalty, penaltyPart];
+                    end
+                otherwise
+                    error('Unknown boundary indentifier')
+            end
+
+        end
+
+        function [closure, penalty] = singleBoundaryCondition(obj, boundary, type)
             I = boundary{1};
             name = boundary{2};
 
--- a/+multiblock/Grid.m	Wed Aug 02 19:26:39 2017 +0200
+++ b/+multiblock/Grid.m	Mon Aug 07 09:56:01 2017 +0200
@@ -9,16 +9,19 @@
 
     % 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. Maybe the grid class doesn't need to care at all. All boundaryGroup interaction is in DiffOp?
+        % 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?)
+        % boundaryGroups -- A struct of BoundaryGroups. The field names of the
+        %                   struct are the names of each boundary group.
+        %                   The boundary groups can be used to collect block
+        %                   boundaries into physical boundaries to simplify
+        %                   getting boundary operators and setting boundary conditions
         function obj = Grid(grids, connections, boundaryGroups)
+            default_arg('boundaryGroups', struct());
             obj.grids = grids;
             obj.connections = connections;
 
@@ -27,7 +30,7 @@
                 obj.nPoints = obj.nPoints + grids{i}.N();
             end
 
-            % if iscell(boundaryGroups)
+            obj.boundaryGroups = boundaryGroups;
         end
 
         function n = size(obj)
@@ -121,13 +124,43 @@
 
         end
 
+        % Find all non interface boundaries of all blocks.
+        % Return their grid.boundaryIdentifiers in a cell array.
         function bs = getBoundaryNames(obj)
-            bs = [];
+            bs = {};
+            for i = 1:obj.nBlocks()
+                candidates = obj.grids{i}.getBoundaryNames();
+                for j = 1:obj.nBlocks()
+                    if ~isempty(obj.connections{i,j})
+                        candidates = setdiff(candidates, obj.connections{i,j}{1});
+                    end
+
+                    if ~isempty(obj.connections{j,i})
+                        candidates = setdiff(candidates, obj.connections{j,i}{2});
+                    end
+                end
+
+                for k = 1:length(candidates)
+                    bs{end+1} = {i, candidates{k}};
+                end
+            end
         end
 
-        % Return coordinates for the given boundary
-        function b = getBoundary(obj, name)
-            b = [];
+        % Return coordinates for the given boundary/boundaryGroup
+        function b = getBoundary(obj, boundary)
+            switch class(boundary)
+                case 'cell'
+                    I = boundary{1};
+                    name = boundary{2};
+                    b = obj.grids{I}.getBoundary(name);
+                case 'multiblock.BoundaryGroup'
+                    b = [];
+                    for i = 1:length(boundary)
+                        b = [b; obj.getBoundary(boundary{i})];
+                    end
+                otherwise
+                    error('Unknown boundary indentifier')
+            end
         end
     end
 end
--- a/+multiblock/boundaryIdentifier.txt	Wed Aug 02 19:26:39 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-% TODO: Add documentation for boundary identifiers here
-{1, 's'}
\ No newline at end of file