Commit 14bab8de authored by Ferdinand Fischer's avatar Ferdinand Fischer
Browse files

Some changes:

*) Allow to set empty quantity.Discrete objects with certain size
*) added the isConstant property for the quantity.Discrete
*) Implemented a cast to the quantity.Operator object
*) Implemented a cast of empty quantity.Discretes to quantity.Symbolics
*) Fixed bug in "on()" for constant quantities
*) Fixed some functions to work with empty quantities
*) Added a settings object to use global settings
*) plot function returns now an array of the figure handles
*) Re-implementation of the quantity.Operator object
parent d94fec26
classdef BasicVariable < quantity.Function
%GEVREYFUNCTION class for desription of basic variables
% The basic variable can be of the form
% g(t) = [phi_1(t); phi(2); ... ]
%
properties
% The constant gain of the Gevrey-function
K double = 1;
% Shifts the evaluation of the derivative of the Gevrey-function.
% Can be used if the series, computed using the gevrey function,
% should not start at the 0-th derivative.
diffShift double {mustBeNonnegative, mustBeInteger};
% Offset to raise the whole Gevrey-function g_ = g + offset.
offset double;
% Number of discretization points for the time variable at which
% the Gevrey-function is evaluated.
N_t double;
% Number of derivatives that need to be considered for this gevrey
% function
N_diff double;
% Length of the time interval the Gevrey-function is defined on.
T double = -1;
% Gevrey-order
order double = -1;
end
properties (Dependent)
sigma;
dt;
end
methods
%% CONSTRUCTOR
function obj = BasicVariable(valueContinuous, varargin)
parentVarargin = {};
if nargin > 0
% make default grid:
preParser = misc.Parser();
preParser.addParameter('T', 1);
preParser.addParameter('N_t', 101);
preParser.addParameter('dt', []);
preParser.addParameter('N_diff', 1);
preParser.parse(varargin{:});
if ~isempty(preParser.Results.dt)
N_t = quantity.BasicVariable.setDt(preParser.Results.T, preParser.Results.dt);
preResults.T = preParser.Results.T;
preResults.dt = preParser.Results.dt;
preResults.N_diff = preParser.Results.N_diff;
else
N_t = preParser.Results.N_t;
preResults.T = preParser.Results.T;
preResults.N_t = preParser.Results.N_t;
preResults.N_diff = preParser.Results.N_diff;
end
grid = {linspace(0, preParser.Results.T, N_t)'};
varargin = [varargin{:}, 'grid', {grid}];
parentVarargin = {valueContinuous, varargin{:}, 'gridName', {'t'}};
end
obj@quantity.Function(parentVarargin{:});
if nargin > 0
% first parser
p1 = misc.Parser();
p1.addParameter('K', 1);
p1.addParameter('diffShift', 0);
p1.addParameter('offset', 0);
p1.addParameter('order', 1.5);
p1.parse(varargin{:});
for parameter = fieldnames(p1.Results)'
obj.(parameter{1}) = p1.Results.(parameter{1});
end
for parameter = fieldnames(preResults)'
obj.(parameter{1}) = preParser.Results.(parameter{1});
end
end
end
function n = nargin(obj)
n = 1;
end
function D = diff(obj, K)
if nargin == 1
i = 1;
end
for i = 1:numel(K)
% create a new object for the derivative of obj:
D(:,i) = obj.copy();
[D.name] = deal(['d/dt (' num2str(K(i)) ') ']);
[D.valueDiscrete] = deal([]);
for l = 1:numel(obj)
D(l,i).diffShift = D(l, 1).diffShift + K(i);
end
end
end
%% PROPERTIES
function dt = get.dt(obj)
dt = obj.T / obj.N_t;
end
function set.dt(obj, dt)
obj.N_t = quantity.BasicVariable.setDt(obj.T, dt);
end
function obj = set.diffShift(obj, n)
obj.diffShift = n;
obj.valueDiscrete = [];
end
function s = get.sigma(obj)
s = 1 / ( obj.order - 1);
end
function obj = set.sigma(obj, s)
obj.order = 1 + 1/s;
end
function obj = set.order(obj, order)
obj.order = obj.set_order(order);
end
function order = get.order(obj)
order = obj.get_order(obj.order);
end
function obj = set.N_t(obj, value)
obj.N_t = obj.set_N_t(value);
end
function N = get.N_t(obj)
N = obj.get_N_t(obj.N_t);
end
function obj = set.T(obj, value)
obj.T = obj.set_T(value);
end
function T = get.T(obj)
T = obj.get_T(obj.T);
end
function b = copy_K(obj, K)
b = obj.copy();
b.valueDiscrete = K / obj.K * obj.valueDiscrete();
b.K = K;
end
end
methods (Access = protected)
function f = getValueContinuous(obj, f)
f = @(z) obj.K * f(z, obj.diffShift, obj.T, obj.sigma);
end
function order = set_order(obj, order)
end
function order = get_order(obj, order)
end
function T = get_T(obj, T)
end
function T = set_T(obj, T)
end
function n = get_n(obj, n)
end
function n = set_n(obj, n)
end
function N = get_N_t(obj, N)
end
function N = set_N_t(obj, N)
end
end
methods (Access = protected, Static)
function Nt = setDt(T, dt)
t = 0:dt:T;
Nt = length(t);
if ~numeric.near(t(end), T)
warning(['Sampling with dt=' num2str(dt) ' leads to t(end)= ' num2str(t(end))]);
end
end
end
methods (Static)
function b = makeBasicVariable(b0, K)
for k = 1:numel(K)
for l = 1:size(b0, 2)
b(k, l) = b0(l).copy_K(K(k));
end
end
end
end
%BasicVariable class for desription of basic variables
% The basic variable can be of the form
% g(t) = [phi_1(t); phi(2); ... ]
%
properties
% The constant gain of the Gevrey-function
K double = 1;
% Shifts the evaluation of the derivative of the Gevrey-function.
% Can be used if the series, computed using the gevrey function,
% should not start at the 0-th derivative.
diffShift double {mustBeNonnegative, mustBeInteger};
% Offset to raise the whole Gevrey-function g_ = g + offset.
offset double;
% Number of discretization points for the time variable at which
% the Gevrey-function is evaluated.
N_t double;
% Number of derivatives that need to be considered for this gevrey
% function
N_diff double;
% Length of the time interval the Gevrey-function is defined on.
T double = -1;
% Gevrey-order
order double = -1;
end
properties (Dependent)
sigma;
dt;
end
methods
%% CONSTRUCTOR
function obj = BasicVariable(valueContinuous, varargin)
parentVarargin = {};
if nargin > 0
% make default grid:
preParser = misc.Parser();
preParser.addParameter('T', 1);
preParser.addParameter('N_t', 101);
preParser.addParameter('dt', []);
preParser.addParameter('N_diff', 1);
preParser.parse(varargin{:});
if ~isempty(preParser.Results.dt)
N_t = quantity.BasicVariable.setDt(preParser.Results.T, preParser.Results.dt);
preResults.T = preParser.Results.T;
preResults.dt = preParser.Results.dt;
preResults.N_diff = preParser.Results.N_diff;
else
N_t = preParser.Results.N_t;
preResults.T = preParser.Results.T;
preResults.N_t = preParser.Results.N_t;
preResults.N_diff = preParser.Results.N_diff;
end
grid = {linspace(0, preParser.Results.T, N_t)'};
varargin = [varargin{:}, 'grid', {grid}];
parentVarargin = {valueContinuous, varargin{:}, 'gridName', {'t'}};
end
obj@quantity.Function(parentVarargin{:});
if nargin > 0
% first parser
p1 = misc.Parser();
p1.addParameter('K', 1);
p1.addParameter('diffShift', 0);
p1.addParameter('offset', 0);
p1.addParameter('order', 1.5);
p1.parse(varargin{:});
for parameter = fieldnames(p1.Results)'
obj.(parameter{1}) = p1.Results.(parameter{1});
end
for parameter = fieldnames(preResults)'
obj.(parameter{1}) = preParser.Results.(parameter{1});
end
end
end
function n = nargin(obj)
n = 1;
end
function D = diff(obj, K)
if nargin == 1
i = 1;
end
for i = 1:numel(K)
% create a new object for the derivative of obj:
D(:,i) = obj.copy();
[D.name] = deal(['d/dt (' num2str(K(i)) ') ']);
[D.valueDiscrete] = deal([]);
for l = 1:numel(obj)
D(l,i).diffShift = D(l, 1).diffShift + K(i);
end
end
end
%% PROPERTIES
function dt = get.dt(obj)
dt = obj.T / obj.N_t;
end
function set.dt(obj, dt)
obj.N_t = quantity.BasicVariable.setDt(obj.T, dt);
end
function obj = set.diffShift(obj, n)
obj.diffShift = n;
obj.valueDiscrete = [];
end
function s = get.sigma(obj)
s = 1 / ( obj.order - 1);
end
function obj = set.sigma(obj, s)
obj.order = 1 + 1/s;
end
function obj = set.order(obj, order)
obj.order = obj.set_order(order);
end
function order = get.order(obj)
order = obj.get_order(obj.order);
end
function obj = set.N_t(obj, value)
obj.N_t = obj.set_N_t(value);
end
function N = get.N_t(obj)
N = obj.get_N_t(obj.N_t);
end
function obj = set.T(obj, value)
obj.T = obj.set_T(value);
end
function T = get.T(obj)
T = obj.get_T(obj.T);
end
function b = copy_K(obj, K)
b = obj.copy();
b.valueDiscrete = K / obj.K * obj.valueDiscrete();
b.K = K;
end
end
methods (Access = protected)
function f = getValueContinuous(obj, f)
f = @(z) obj.K * f(z, obj.diffShift, obj.T, obj.sigma);
end
function order = set_order(obj, order)
end
function order = get_order(obj, order)
end
function T = get_T(obj, T)
end
function T = set_T(obj, T)
end
function n = get_n(obj, n)
end
function n = set_n(obj, n)
end
function N = get_N_t(obj, N)
end
function N = set_N_t(obj, N)
end
end
methods (Access = protected, Static)
function Nt = setDt(T, dt)
t = 0:dt:T;
Nt = length(t);
if ~numeric.near(t(end), T)
warning(['Sampling with dt=' num2str(dt) ' leads to t(end)= ' num2str(t(end))]);
end
end
end
methods (Static)
function b = makeBasicVariable(b0, K)
for k = 1:numel(K)
for l = 1:size(b0, 2)
b(k, l) = b0(l).copy_K(K(k));
end
end
end
end
end
\ No newline at end of file
......@@ -59,7 +59,13 @@ classdef (InferiorClasses = {?quantity.Symbolic, ?quantity.Operator}) Discrete
valueOriginalSize = size(valueOriginal);
S = num2cell(valueOriginalSize);
if any(valueOriginalSize == 0)
obj = quantity.Discrete.empty(S{:});
% If the size is specified in the arguements, it should
% be chosen instead of the default size from the
% valueOriginal.
myParser = misc.Parser();
myParser.addParameter('size', [S{:}]);
myParser.parse(varargin{:});
obj = quantity.Discrete.empty(myParser.Results.size);
return;
end
......@@ -151,7 +157,12 @@ classdef (InferiorClasses = {?quantity.Symbolic, ?quantity.Operator}) Discrete
%---------------------------
% --- getter and setters ---
%---------------------------
%---------------------------
function i = isConstant(obj)
% the quantity is interpreted as constant if it has no grid or
% it has a grid that is only one point.
i = isempty(obj.gridSize) || prod(obj.gridSize) == 1;
end
function doNotCopy = get.doNotCopy(obj)
doNotCopy = obj.doNotCopyPropertiesName();
end
......@@ -178,7 +189,7 @@ classdef (InferiorClasses = {?quantity.Symbolic, ?quantity.Operator}) Discrete
end
obj.gridName = name;
end
function set.grid(obj, grid)
if ~iscell(grid)
grid = {grid};
......@@ -203,6 +214,21 @@ classdef (InferiorClasses = {?quantity.Symbolic, ?quantity.Operator}) Discrete
function d = double(obj)
d = obj.on();
end
function o = quantity.Operator(obj)
for k = 1:size(obj, 3)
A{k} = obj(:,:,k);
end
o = quantity.Operator(A, 'grid', obj(1).grid);
end
function o = quantity.Symbolic(obj)
if isempty(obj)
o = quantity.Symbolic.empty(size(obj));
else
error('Not yet implemented')
end
end
end
methods (Access = public)
......@@ -241,6 +267,9 @@ classdef (InferiorClasses = {?quantity.Symbolic, ?quantity.Operator}) Discrete
tempInterpolant = numeric.interpolant(...
[obj(1).grid, indexGrid{:}], value);
value = tempInterpolant.evaluate(myGrid{:}, indexGrid{:});
elseif obj.isConstant
value = repmat(value, [cellfun(@(v) numel(v), myGrid), ones(1, length(size(obj)))]);
gridPermuteIdx = 1:numel(myGrid);
end
value = permute(reshape(value, [cellfun(@(v) numel(v), myGrid), size(obj)]), ...
[gridPermuteIdx, numel(gridPermuteIdx)+(1:ndims(obj))]);
......@@ -252,8 +281,13 @@ classdef (InferiorClasses = {?quantity.Symbolic, ?quantity.Operator}) Discrete
% further quantites are inputs via varargin, it is verified if
% that quantity has same grid and gridName as quantity a
% as well.
referenceGridName = a(1).gridName;
referenceGrid= a(1).grid;
if isempty(a)
referenceGridName = '';
referenceGrid = {};
else
referenceGridName = a(1).gridName;
referenceGrid= a(1).grid;
end
for it = 1 : numel(a)
assert(isequal(referenceGridName, a(it).gridName), ...
'All elements of a quantity must have same gridNames');
......@@ -279,10 +313,21 @@ classdef (InferiorClasses = {?quantity.Symbolic, ?quantity.Operator}) Discrete
function [referenceGrid, referenceGridName] = getFinestGrid(a, varargin)
% find the finest grid of all input quantities by comparing
% gridSize for each iteratively.
referenceGridName = a(1).gridName;
referenceGrid = a(1).grid;
referenceGridSize = a(1).gridSize(referenceGridName);
if isempty(a)
referenceGridName = '';
referenceGrid = {};
referenceGridSize = [];
else
referenceGridName = a(1).gridName;
referenceGrid = a(1).grid;
referenceGridSize = a(1).gridSize(referenceGridName);
end
for it = 1 : numel(varargin)
if isempty(varargin{it})
continue;
end
assert(numel(referenceGridName) == numel(varargin{it}(1).gridName), ...
['For getFinestGrid, the gridName of all objects must be equal', ...
'. Maybe gridJoin() does what you want?']);
......@@ -416,7 +461,7 @@ classdef (InferiorClasses = {?quantity.Symbolic, ?quantity.Operator}) Discrete
% Copyright 1984-2005 The MathWorks, Inc.
% Built-in function.
if nargin == 1
objCell = {a};
objCell = {a};
else
objCell = [{a}, varargin(:)'];
......@@ -599,6 +644,9 @@ classdef (InferiorClasses = {?quantity.Symbolic, ?quantity.Operator}) Discrete
if nargin == 1 || isempty(gridName2Replace)
% if gridName2Replace is empty, then nothing must be done.
solution = obj;
elseif isempty(obj);
% if the object is empty, nothing must be done.
solution = obj;
else
% input checks
assert(nargin == 3, ['Wrong number of input arguments. ', ...
......@@ -776,21 +824,23 @@ classdef (InferiorClasses = {?quantity.Symbolic, ?quantity.Operator}) Discrete
end
end
function h = plot(obj, varargin)
function H = plot(obj, varargin)
H = [];
p = misc.Parser();
p.addParameter('fig', []);
p.addParameter('dock', false);
p.addParameter('dock', quantity.Settings.instance().dockThePlot);
p.parse(varargin{:});
%misc.struct2ws(p.Results);
additionalPlotOptions = misc.struct2namevaluepair(p.Unmatched);
fig = p.Results.fig;
dock = p.Results.dock;
for figureIdx = 1:size(obj, 3)
if isempty(p.Results.fig)
h = figure();
else
h = figure(fig + figureIdx - 1);
h = figure(fig + figureIdx - 1);
end
H = [H, h];
if dock
set(h, 'WindowStyle', 'Docked');
......@@ -805,6 +855,11 @@ classdef (InferiorClasses = {?quantity.Symbolic, ?quantity.Operator}) Discrete
i = 1: numel(obj(:,:,figureIdx));
i = reshape(i, size(obj, 2), size(obj, 1))';
if obj.gridSize == 1
additionalPlotOptions = [additionalPlotOptions(:)', ...
{'x'}];
end
for rowIdx = subplotRowIdx
for columnIdx = subpotColumnIdx
subplot(size(obj, 1), size(obj, 2), i(rowIdx, columnIdx));
......@@ -813,11 +868,13 @@ classdef (InferiorClasses = {?quantity.Symbolic, ?quantity.Operator}) Discrete
plot(...
obj(rowIdx, columnIdx, figureIdx).grid{1}(:), ...
obj(rowIdx, columnIdx, figureIdx).valueDiscrete );
obj(rowIdx, columnIdx, figureIdx).valueDiscrete, ...
additionalPlotOptions{:});
elseif obj.nargin() == 2
misc.isurf(obj(rowIdx, columnIdx, figureIdx).grid{1}(:), ...
obj(rowIdx, columnIdx, figureIdx).grid{2}(:), ...
obj(rowIdx, columnIdx, figureIdx).valueDiscrete);
obj(rowIdx, columnIdx, figureIdx).valueDiscrete, ...
additionalPlotOptions{:});
ylabel(labelHelper(2), 'Interpreter','latex');
else
error('number inputs not supported');
......@@ -854,7 +911,6 @@ classdef (InferiorClasses = {?quantity.Symbolic, ?quantity.Operator}) Discrete
myText = strrep(myText, 'gamma', '\gamma');
myText = strrep(myText, 'Delta', '\Delta');
myText = strrep(myText, 'delta', '\delta');
myText = strrep(myText, 'int', '\int');
if ~contains(myText, '\zeta') && ~contains(myText, '\Zeta')
myText = strrep(myText, 'eta', '\eta');
end
......@@ -900,6 +956,9 @@ classdef (InferiorClasses = {?quantity.Symbolic, ?quantity.Operator}) Discrete
% change the grid of the obj quantity. The order of grid and
% gridName in the obj properties remains unchanged, only the
% data points are exchanged.
if isempty(obj)
return;
end
gridIndexNew = obj(1).gridIndex(gridNameNew);
myGrid = cell(1, numel(obj(1).grid));
myGridName = cell(1, numel(obj(1).grid));
......@@ -966,6 +1025,18 @@ classdef (InferiorClasses = {?quantity.Symbolic, ?quantity.Operator}) Discrete
ftr = false;