Function.m 4.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
classdef Function < quantity.Discrete
	
	properties
		valueContinuous (1, 1);	% function_handle or double
	end
	
	methods
		%--------------------
		% --- Constructor ---
		%--------------------
		function obj = Function(valueOriginal, varargin)
			parentVarargin = {};	% by default the parent-class is called 
									% with no input.
			
			% only do something if there are some paremters. otherwise an
			% empty object will be returned. This is important to allow the
			% initialization as object array.
			if nargin > 0
				sizeValue = size(valueOriginal);
				fun = cell(sizeValue);
				
				% modification of some input parameters to allow the
				% initialization of the object array
				for k = 1:numel(valueOriginal)
					if iscell(valueOriginal)
						fun{k} = valueOriginal{k};
					elseif isnumeric(valueOriginal)
						fun{k} = valueOriginal(k);
					elseif isa(valueOriginal, 'function_handle')
						fun{k} = valueOriginal;
					elseif isa(valueOriginal, 'sym')
						fun{k} = matlabFunction(valueOriginal);
					else
						error('Type of valueContinuous not supported')
					end
				end
				
				myParser = misc.Parser();
				myParser.addParameter('grid', {linspace(0, 1, 101).'});
				if isempty(fun)
					gridNameDefault = {};
				else
					gridNameDefault = misc.getInputNamesOfFunctionHandle(fun{1});
				end
				myParser.addParameter('gridName', gridNameDefault);
				myParser.parse(varargin{:});
				unmatched = misc.struct2namevaluepair(myParser.Unmatched);
				
				parentVarargin = {cell(sizeValue), 'grid', myParser.Results.grid, ...
					'gridName', myParser.Results.gridName, unmatched{:}};
			end
			
			obj@quantity.Discrete(parentVarargin{:});
			if nargin > 0
				for it = 1:numel(obj)
					obj(it).valueContinuous = fun{it};
				end
			end
		end%Function constructor
60

61
62
		function f = function_handle(obj)
			
63
64
65
66
67
68
69
70
			if numel(obj) == 1
				f = @obj.valueContinuous;
			else
				for k = 1:numel(obj)
					F{k} = @(varargin) obj(k).valueContinuous(varargin{:});
				end

				f = @(varargin) reshape((cellfun( @(c) c(varargin{:}), F)), size(obj));
71
72
73
			end
		end
		
74
75
76
		%-----------------------------
		% --- overloaded functions ---
		%-----------------------------
77
		function value = obj2value(obj, myDomain, recalculate)
78

79
80
81
82
83
			% check if the domain for the evaluation has changed. If not
			% we can use the stored values in valueDiscrete:
			if nargin < 3
				recalculate = false;
			end
84
			if ~recalculate && isequal(myDomain, obj(1).domain)
85
				value = obj2value@quantity.Discrete(obj);
86
87
88
			else
				% otherwise the function has to be evaluated on the new
				% domain
89
				value = cell(size(obj));
90
				ndGrd = myDomain.ndgrid;
91
92
				for k = 1:numel(obj)
					tmp = obj(k).evaluateFunction( ndGrd{:} );
93
					value{k} = tmp(:);
94
				end					
95
				value = reshape( cell2mat(value), [ gridLength(myDomain), size(obj)]);
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
			end
		end
		
		function n = nargin(obj)
			% FIXME: check if all funtions in this object have the same
			% number of input values.
			n = numel(obj(1).grid);
		end
	end
	
	% -------------
	% --- Mathe ---
	%--------------
	methods
		function mObj = uminus(obj)
			mObj = obj.copy();
			
			for k = 1:numel(obj)
114
				mObj(k).valueContinuous = @(varargin) - obj(k).valueContinuous(varargin{:});
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
				mObj(k).valueDiscrete = - obj(k).valueDiscrete;
			end
			
			[mObj.name] = deal(['-' obj.name]);
		end
		
		function p = inner(A, B)
			
			AB = A * B;
			
			n = size(A, 1);
			m = size(B, 2);
			p = zeros(n, m);
			
			z0 = A(1).grid{1}(1);
			z1 = A(1).grid{1}(end);
			
			for k = 1 : n*m
				p(k) = AB(k).int(z0, z1);
			end
			
		end
		
		function I = int(S, a, b)
			I = zeros(size(S));
			for k = 1:numel(S)
141
				I(k) = integral(@(varargin)S(k).evaluateFunction(varargin{:}), a, b, 'AbsTol', 1e-9);
142
143
			end
		end
Ferdinand Fischer's avatar
Ferdinand Fischer committed
144

145
146
147
148
149
	end
	
	methods (Access = protected)
		function v = evaluateFunction(obj, varargin)
			v = obj.valueContinuous(varargin{:});
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
		end
	end
	
	methods (Static)%, Access = protected)
		function [o] = zero(varargin)
			% ZERO creates an array containing only zeros with the same
			% dimensions as input ndgrids. This is needed for, function
			% handles that return a constant value and should be able to be
			% called on a ndgrid.
			if nargin >= 1
				o = zeros(size(varargin{1}));
			elseif nargin == 0
				o = 0;
			end
		end
	end
	
end