diff +multiblock/InterfaceOptions.m @ 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
children ab1759166a8c
line wrap: on
line diff
--- /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