changeset 907:c0652621bd69 feature/utux2D

Add new class multiblock.InterfaceOptions whose instances are passed to multiblock.DiffOp.
author Martin Almquist <malmquist@stanford.edu>
date Fri, 23 Nov 2018 20:12:54 -0800
parents 0499239496cf
children ecfccf236af0
files +multiblock/DiffOp.m +multiblock/InterfaceOptions.m
diffstat 2 files changed, 147 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/+multiblock/DiffOp.m	Fri Nov 23 20:07:13 2018 -0800
+++ b/+multiblock/DiffOp.m	Fri Nov 23 20:12:54 2018 -0800
@@ -10,7 +10,7 @@
     end
 
     methods
-        function obj = DiffOp(doHand, grid, order, doParam, interfaceType)
+        function obj = DiffOp(doHand, grid, order, doParam, interfaceOptions)
             %  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, ...)
@@ -25,18 +25,20 @@
             %            doHand(..., doParam{i}{:}) Otherwise doParam is sent as
             %            extra parameters to all doHand: doHand(..., doParam{:})
             %
-            % interfaceType -- nBlocks x nBlocks cell array of types that specify
-            %                  that particular block-coupling is handled. (Could
-            %                  be non-conforming interface, etc.)
-            %                  Default: empty cell array.
+            % interfaceOptions (optional) -- An instance of class multiblock.InterfaceOptions
+            %                                               OR
+            %                                 nBlocks x nBlocks cell array of opts for
+            %                                 every interface.
             default_arg('doParam', [])
+            default_arg('interfaceOptions', multiblock.InterfaceOptions(grid) ); % Empty options
+            if isa(interfaceOptions, 'multiblock.InterfaceOptions');
+                interfaceOptions = interfaceOptions.getOptions;
+            end
 
             [getHand, getParam] = parseInput(doHand, grid, doParam);
 
+            obj.order = order;
             nBlocks = grid.nBlocks();
-            default_arg('interfaceType', cell(nBlocks, nBlocks));
-
-            obj.order = order;
 
             % Create the diffOps for each block
             obj.diffOps = cell(1, nBlocks);
@@ -72,11 +74,13 @@
                         continue
                     end
 
-                    [ii, ij] = obj.diffOps{i}.interface(intf{1}, obj.diffOps{j}, intf{2}, interfaceType{i,j});
+                    intfOpts = interfaceOptions{i,j};
+
+                    [ii, ij] = obj.diffOps{i}.interface(intf{1}, obj.diffOps{j}, intf{2}, intfOpts{1});
                     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}, interfaceType{j,i});
+                    [jj, ji] = obj.diffOps{j}.interface(intf{2}, obj.diffOps{i}, intf{1}, intfOpts{2});
                     D{j,j} = D{j,j} + jj;
                     D{j,i} = D{j,i} + ji;
                 end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/+multiblock/InterfaceOptions.m	Fri Nov 23 20:12:54 2018 -0800
@@ -0,0 +1,133 @@
+% An object of class InterfaceOptions can be passed as argument to multiblock.Diffop
+% to specify details of the interface couplings.
+%
+% An InterfaceOptions object is essentially a cell array of options,
+% equipped with methods that make it easier to change options.
+classdef InterfaceOptions < handle
+    properties
+        % optsCell -- nBlocks x nBlocks cell array (same size as grid.connections)
+        %             Must have the same sparsity pattern as grid.connections
+        optsCell
+    end
+
+    methods
+
+        % grid          --  mutliblock.grid
+        % intialOpts    --  cell array of interface options
+        function obj = InterfaceOptions(grid, initialOpts)
+
+            default_arg('initialOpts', []);
+
+            % If no initialOpts are given, create empty options cell.
+            % The cell matrix is non-empty where connections is non-empty.
+            if isempty(initialOpts)
+                opts = grid.connections;
+                for i = 1:numel(grid.connections)
+                    if ~isempty(grid.connections{i})
+                        opts{i} = cell(1, 2);
+                        opts{i}{1} = struct;
+                        opts{i}{2} = struct;
+                    end
+                end
+
+            % If no grid is given, assume that initialOpts is correct and use it.
+            elseif isempty(grid)
+                opts = initialOpts;
+
+            % Check that grid.connections and initialOpts match, and then use initialOpts.
+            else
+                assert(numel(grid.connections) == numel(initialOpts),...
+                     'InterfaceOptions: grid.connections and initialOpts do not match');
+                opts = initialOpts;
+            end
+            obj.optsCell = opts;
+        end
+
+        % Returns the cell matrix that contains the options
+        function opts = getOptions(obj)
+            opts = obj.optsCell;
+        end
+
+
+        % Sets the option optStr to val, for the coupling berween blocks i and j
+        % If i and j are omitted, all couplings get optStr = val.
+        %
+        % optStr  -- string
+        % val     -- anything
+        % i,j     -- integers
+        function setOption(obj, optStr, val, i ,j)
+            default_arg('i',[]);
+            default_arg('j',[]);
+
+            opts = obj.optsCell;
+
+            if isempty(i) && ~isempty(j)
+                error('If i is empty, j must also be empty.');
+
+            elseif isempty(j) && ~isempty(i)
+                error('If j is empty, i must also be empty.');
+
+            % If i and j are empty, set the option for all interfaces
+            elseif isempty(i) && isempty(j)
+                for k = 1:numel(opts)
+                    if ~isempty(opts{k})
+                        opts{k}{1} = setfield(opts{k}{1}, optStr, val);
+                        opts{k}{2} = setfield(opts{k}{2}, optStr, val);
+                    end
+                end
+
+            % Both i and j are nonempty, set property only for that interface
+            else
+                opts{i,j}{1} = setfield(opts{i,j}{1}, optStr, val);
+                opts{i,j}{2} = setfield(opts{i,j}{2}, optStr, val);
+            end
+
+            obj.optsCell = opts;
+        end
+
+
+        % Constructs the union of two InterfaceOptions
+        function union(obj, obj2)
+            localOpts = obj.optsCell;
+            remoteOpts = obj2.optsCell;
+
+            assert( numel(localOpts) == numel(remoteOpts), ...
+                    'multiblock.InterfaceOptions: The two InterfaceOptions do not have the same dimension.');
+
+            for i = 1:numel(localOpts)
+                if ~isempty(remoteOpts{i})
+                    if isempty(localOpts{i})
+                        error('multiblock.InterfaceOptions: The two InterfaceOptions must have the same interface connections');
+                    else
+                        for j = 1:2
+                            remoteStruct = remoteOpts{i}{j};
+                            localStruct = localOpts{i}{j};
+                            localFields = fieldnames(localStruct);
+
+                            % Assert the we don't have any identical field names, which would lead to overwriting
+                            for k = 1:numel(localFields)
+                                if isfield(remoteStruct, localFields{k})
+                                    error('multiblock.InterfaceOptions: Cannot perform union of InterfaceOptions with common options');
+                                end
+                            end
+
+                            % Take fields from remote and deal to local
+                            remoteFields = fieldnames(remoteStruct);
+                            for k = 1:numel(remoteFields)
+                                name = remoteFields{k};
+                                val = getfield(remoteStruct, name);
+                                localStruct = setfield(localStruct, name, val);
+                            end
+
+                            localOpts{i}{j} = localStruct;
+                        end
+                    end
+                end
+            end
+
+            obj.optsCell = localOpts;
+        end
+
+
+    end
+end