Mercurial > repos > public > sbplib
changeset 211:3c4ffbfbfb84 feature/beams
Merged feature/grid into feature/beams
author | Jonatan Werpers <jonatan@werpers.com> |
---|---|
date | Thu, 16 Jun 2016 10:56:47 +0200 |
parents | ef41fde95ac4 (current diff) 39b7dcb2c724 (diff) |
children | 15d604e4e1a1 |
files | cell2sparse.m cell2vector.m sparse2cell.m sparse2cellTest.m vector2cell.m |
diffstat | 19 files changed, 614 insertions(+), 176 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/+blockmatrix/fromMatrix.m Thu Jun 16 10:56:47 2016 +0200 @@ -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} = []; + else + bm{i,j} = Asub; + end + J = J + d2(j); + end + I = I + d1(i); + end +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/+blockmatrix/fromMatrixTest.m Thu Jun 16 10:56:47 2016 +0200 @@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/+blockmatrix/getDivision.m Thu Jun 16 10:56:47 2016 +0200 @@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/+blockmatrix/getDivisionTest.m Thu Jun 16 10:56:47 2016 +0200 @@ -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 + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/+blockmatrix/isBlockmatrix.m Thu Jun 16 10:56:47 2016 +0200 @@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/+blockmatrix/isBlockmatrixTest.m Thu Jun 16 10:56:47 2016 +0200 @@ -0,0 +1,63 @@ +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. + }, + }; + + 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/+blockmatrix/isDivision.m Thu Jun 16 10:56:47 2016 +0200 @@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/+blockmatrix/isDivisionTest.m Thu Jun 16 10:56:47 2016 +0200 @@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/+blockmatrix/toMatrix.m Thu Jun 16 10:56:47 2016 +0200 @@ -0,0 +1,26 @@ +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 + A(n_ind(i)+1:n_ind(i+1),m_ind(j)+1:m_ind(j+1)) = bm{i,j}; + end + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/+blockmatrix/toMatrixTest.m Thu Jun 16 10:56:47 2016 +0200 @@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/+blockmatrix/zero.m Thu Jun 16 10:56:47 2016 +0200 @@ -0,0 +1,16 @@ +% Creates a block matrix according to the division with zeros everywhere. +function bm = zero(div) + 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/+blockmatrix/zeroTest.m Thu Jun 16 10:56:47 2016 +0200 @@ -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
--- a/+multiblock/DiffOp.m Mon Jun 13 16:59:02 2016 +0200 +++ b/+multiblock/DiffOp.m Thu Jun 16 10:56:47 2016 +0200 @@ -5,6 +5,8 @@ diffOps D H + + blockmatrixDiv end methods @@ -35,7 +37,7 @@ for i = 1:nBlocks h = getHand(i); p = getParam(i); - obj.diffOps{i} = h(grid.grid{i}, order, p{:}); + obj.diffOps{i} = h(grid.grids{i}, order, p{:}); end @@ -44,7 +46,7 @@ for i = 1:nBlocks H{i,i} = obj.diffOps{i}.H; end - obj.H = cell2sparse(H); + obj.H = blockmatrix.toMatrix(H); % Build the differentiation matrix @@ -60,18 +62,18 @@ continue end - [ii, ij] = obj.diffOps{i}.inteface_coupling(intf{1}, obj.diffOps{j}, intf{2}); + [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}.inteface_coupling(intf{2}, obj.diffOps{i}, intf{1}); + [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 = cell2sparse(D); + obj.D = blockmatrix.toMatrix(D); - % end + obj.blockmatrixDiv = blockmatrix.getDivision(D); function [getHand, getParam] = parseInput(doHand, grid, doParam) if ~isa(grid, 'multiblock.Grid') @@ -102,19 +104,40 @@ ops = sparse2cell(op, obj.NNN); end - function m = boundary_condition(obj,boundary,type,data) + % Creates the closere 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: 1s or 3w + function [closure, penalty] = boundary_condition(obj,boundary,type,data) + I = boundary(1) + name = boundary(2:end); + + % Get the closure and penaly matrices + [blockClosure, blockPenalty] = obj.diffOps{I}.boundary_condition(name, type, data); + + % Expand to matrix for full domain. + div = obj.blockmatrixDiv; + closure = blockmatrix.zero(div); + closure{I,I} = blockClosure; + + div{2} = 1; % Penalty is a column vector + penalty = blockmatrix.zero(div); + penalty{I} = blockPenalty; + + % Convert to matrix + closure = blockmatrix.toMatrix(closure); + penalty = blockmatrix.toMatrix(closure); + end + + function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary) end - function m = 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(diffOps) - N = N + diffOps.size(); + for i = 1:length(obj.diffOps) + N = N + obj.diffOps{i}.size(); end end end
--- a/+multiblock/DiffOpTest.m Mon Jun 13 16:59:02 2016 +0200 +++ b/+multiblock/DiffOpTest.m Thu Jun 16 10:56:47 2016 +0200 @@ -3,18 +3,57 @@ end function testCreation(testCase) - g = multiblock.Grid({},{}); - doHand = @(grid,order)[]; - order = 0; - do = multiblock.DiffOp(doHand, g, order); + do = newMultiblockOp(); end -function testMissing(testCase) +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() -% do.H = 1; -% do.D = 1; -% end \ No newline at end of file + +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
--- a/cell2sparse.m Mon Jun 13 16:59:02 2016 +0200 +++ /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
--- a/cell2vector.m Mon Jun 13 16:59:02 2016 +0200 +++ /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
--- a/sparse2cell.m Mon Jun 13 16:59:02 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -% sparse2cell breaks a sparse matrix up into a cell matrix of sparse matrices. -% any zero submatrix creates a empty cell in the cell matrix. -% A -- NxM sparse matrix -% d1, d2 -- vectors of sub matrix sizes for each dimensions. Must have sum(di) == Ni. -% Example: -% C = sparse2cell(A,[5 10], [10 5]) -function C = sparse2cell(A, d1, d2) - [n, m] = size(A); - if n ~= sum(d1) || m ~= sum(d2) - error('sparse2cell:NonMatchingDim','The elements of d1 and d2 must sum to N and M.'); - end - - C = 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 - C{i,j} = []; - else - C{i,j} = Asub; - end - J = J + d2(j); - end - I = I + d1(i); - end -end
--- a/sparse2cellTest.m Mon Jun 13 16:59:02 2016 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -function tests = sparse2cellTest() - 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(@()sparse2cell(in{i}{:}),'sparse2cell:NonMatchingDim'); - end -end - -function testOutput(testCase) - in = {}; - out = {}; - in{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]; - in{1}{2} = [1 4]; - in{1}{3} = [2 3]; - - out{1} = { - [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]; - }; - - in{1}{1} = [17 24 1 8 15; 23 5 0 0 0; 4 6 0 0 0; 10 12 0 0 0; 11 18 0 0 0]; - in{1}{2} = [1 4]; - in{1}{3} = [2 3]; - - out{1} = { - [17 24], [1 8 15]; - [23 5; 4 6; 10 12; 11 18], []; - }; - - for i = 1:length(in) - testCase.verifyEqual(sparse2cell(in{i}{:}), out{i}); - end -end \ No newline at end of file
--- a/vector2cell.m Mon Jun 13 16:59:02 2016 +0200 +++ /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