Newer
Older
classdef SCDclass_algo
%SCD algorithm handling object
% The class holds all information and
% methods for handling a Simulink
% algorithm
properties (Access = private)
modelname % Name of the model
mdscontainer % Container class for MDS+ interface objects
taskcontainer % Container class for init and term tasks
exportedtps % List of tunable parameters variable to be exported
datadictionary % Name of the used data dictionary
stdinits % Standard inits scripts for fixed parameters
timing % Timing info structure

Cristian Galperti
committed
exportedtpsdefaults % default tunable parameters defining functions
% Empty algorithm constructor
obj.modelname=name;
obj.mdscontainer = SCDclass_mdsobjcontainer;
obj.taskcontainer = SCDclass_taskcontainer;
obj.exportedtps = {};

Cristian Galperti
committed
obj.exportedtpsdefaults = {};
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
60
61
62
63
64
65
66
67
obj.stdinits = {};
obj.datadictionary = '';
obj.timing.t_start=0;
obj.timing.t_stop=1;
obj.timing.dt=1e-3;
% Standard data dictionary equal to algorithm name,
% overriddable by the setter method
obj=obj.setdatadictionary([name '.sldd']);
end
%% Print infos
function printinfo(obj)
fprintf('*****************************************************\n');
fprintf('* SCD algorithm: ''%s''\n',obj.modelname);
fprintf('*****************************************************\n');
if(~isempty(obj.datadictionary))
fprintf('* Data dictionary:\n %s\n',obj.datadictionary);
else
fprintf('* Data dictionary:\n base workspace\n');
end
if numel(obj.exportedtps)>0
fprintf('* Tunable params structs:\n');
for ii=1:numel(obj.exportedtps)
fprintf(' %s\n',obj.exportedtps{ii});
end
end
fprintf('* Tunable params objects:\n')
obj.printparameters;
fprintf('* Wavegen objects:\n');
obj.printwavegens;
fprintf('* Tasks objects:\n');
obj.printtasks;
fprintf('* Fixed parameters inits:\n');
obj.printinits;
fprintf('*****************************************************\n');
end
%% Setup
function setup(obj)
% setup()
%
% calls updatetemplatetp and
% buildworkspacetpstruct
%
% an algorithm block diagram
% should pass ctrl-d (instandalone opening)
% after this call

Cristian Galperti
committed
obj.updatetemplatetp;
obj.buildworkspacetpstruct;
end
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
%% General purpose getters
function out = getname(obj)
out=obj.modelname;
end
function out = getmdscontainer(obj)
out=obj.mdscontainer;
end
function out = gettaskcontainer(obj)
out=obj.taskcontainer;
end
function out = gettiming(obj)
out=obj.timing;
end
function out = getinits(obj)
out=obj.stdinits;
end
%% Data dictionary setter and getter
function obj = setdatadictionary(obj, datadict)
obj.datadictionary=datadict;
end
function out = getdatadictionary(obj)
out = obj.datadictionary;
end
function out = opendatadictionarydesigndata(obj)
ddname = obj.getdatadictionary;
dict = Simulink.data.dictionary.open(ddname);
out=getSection(dict, 'Design Data');
end
%% Tunable parameters structures handling functions
function out = getexportedtps(obj)
out = obj.exportedtps;
end

Cristian Galperti
committed
function obj = addtunparamstruct(obj, structname, varargin)
% obj = addtunparamstruct(structname, varargin)

Cristian Galperti
committed
%
% adds a tunable parameter to the algo object
% inputs:
% structname: name of the tunable param (string)
% varargin{1}: a function handle to get
% its default value, this function takes no arguments
% and must return either a struct or a Simulink.Parameter
%
% example: obj=obj.addtunparamstruct('SCDalgo_doublet_tp',
% @()SCDalgo_doublet_loadtp());
if(~ismember(structname, obj.exportedtps))
obj.exportedtps{end+1}=structname;
else
error('SCDclass_algo:addtunparamsstruct','Tunable parameter struct already present, cannot add!');

Cristian Galperti
committed
end
if nargin==3
if ~isa(varargin{1}, 'function_handle')
error('SCDclass_algo:addtunparamstruct', 'third argument, if present, must be a function handle');
else
obj.exportedtpsdefaults{end+1} = varargin{1};
end
% % sets default tunable parameter structure in data dictionary
% TP=varargin{1};
% if ~isa(TP,'Simulink.Parameter')
% assert(isstruct(TP),'default must be a structure');
% P = Simulink.Parameter;
% P.Value = TP;
% else
% P = TP;
% end
% obj.exportedtpsdefaults{end+1} = P;

Cristian Galperti
committed
obj.exportedtpsdefaults{end+1} = [];
end
end
function obj = updatetemplatetp(obj)
% obj = updatetemplatetp()

Cristian Galperti
committed
%
% For every configured tunparams structure
% if a default value function is present it is

Cristian Galperti
committed
% updated in the template version of the tun params
% in the algo data dictionary.
% The default value function of a tunparams can be given

Cristian Galperti
committed
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
% as an optional third argument of addtunparamstruct
% method
DD = obj.opendatadictionarydesigndata;
for ii=1:numel(obj.exportedtps)
if ~isempty(obj.exportedtpsdefaults{ii})
% get current value of parameters from the function
% handle
fprintf('%s: calling %s\n', obj.getname, char(obj.exportedtpsdefaults{ii}));
TP=obj.exportedtpsdefaults{ii}();
if ~isa(TP,'Simulink.Parameter')
assert(isstruct(TP),'default function must return either a Simulink.Parameter or a structure');
P = Simulink.Parameter;
P.Value = TP;
else
P = TP;
end
% updates default tunable parameters structure in data dictionary
tmplname = sprintf('%s_tmpl',obj.exportedtps{ii});
if DD.exist(tmplname)
replace = false;
oldEntry = DD.getEntry(tmplname);
try
if isequal(oldEntry.getValue.Value,P.Value)
%fprintf('%s: keep old template %s since not changed\n',obj.getname,tmplname);
continue;
else
replace=true;
end
catch ME
replace=true;
end
if replace
DD.deleteEntry(tmplname); fprintf('%s: deleted previous entry, ', obj.getname);
fprintf('added new %s\n',tmplname);
DD.addEntry(tmplname,P);
end
else
fprintf('%s: added new %s\n',obj.getname, tmplname);
DD.addEntry(tmplname,P);
end
end
function obj = buildworkspacetpstruct(obj)

Cristian Galperti
committed
% obj = buildworkspacetpstruct(obj)
%
% this funtion builds a workspace structures containing
% replicas of all tunable parameters structurea in the data
% dictionaries, this structure is the one actually used

Cristian Galperti
committed
% for loading simulation data from MDS
% It is better not to use directly data dictionaries structures
% to avoid flooding dds with big sim data sets (and

Cristian Galperti
committed
% consequently the SCD GIT itself
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
if(isempty(obj.datadictionary))
warning('SCDclass_algo:buildworkspacetpstruct','Methods ignored for this object, data dictionary isn''t configured');
return;
end
dd=SCDconf_getdatadict(obj.datadictionary);
for ii=1:numel(obj.exportedtps)
simstructnamedd=sprintf('%s_tmpl',char(obj.exportedtps(ii)));
simstructnamews=char(obj.exportedtps(ii));
simstruct=dd.getEntry(simstructnamedd).getValue;
assignstr=sprintf('%s=temp;',simstructnamews);
assignin('base','temp',simstruct);
evalin('base',assignstr);
end
evalin('base','clear temp;');
end
%% MDS container methods forwarders
function obj = addparameter(obj, param)
obj.mdscontainer=obj.mdscontainer.addparameter(param);
obj.mdscontainer=obj.mdscontainer.bindlastparameter(obj.modelname, obj.datadictionary, obj.exportedtps);
end
function obj = printparameters(obj)
obj.mdscontainer=obj.mdscontainer.printparameters;
end
function obj = actualizeparameters(obj, shot)
obj.mdscontainer=obj.mdscontainer.actualizeparameters(shot);
end
function obj = addwavegen(obj, wavegen)
obj.mdscontainer=obj.mdscontainer.addwavegen(wavegen);
obj.mdscontainer=obj.mdscontainer.bindlastwavegen(obj.modelname, obj.datadictionary, obj.timing);
end
function obj = printwavegens(obj)
obj.mdscontainer=obj.mdscontainer.printwavegens;
end
function obj = actualizewavegens(obj, shot)
obj.mdscontainer=obj.mdscontainer.actualizewavegens(shot);
end
function obj = cleanwavegens(obj)
obj.mdscontainer=obj.mdscontainer.cleanwavegens;
end
%function obj = bindparameters(obj)
% obj.mdscontainer=obj.mdscontainer.bindparameters(obj.modelname, obj.datadictionary, obj.exportedtps);
%end
% This method has only sense in the expcode context
%function obj = buildworkspacesimstruct(obj)
% obj.mdscontainer=obj.mdscontainer.buildworkspacesimstruct;
%end
%% Task container methods forwarders
function obj = addtask(obj, task)
obj.taskcontainer=obj.taskcontainer.addtask(task);
obj.taskcontainer=obj.taskcontainer.bindlasttask(obj.modelname, obj.datadictionary);
end
function obj = printtasks(obj)
obj.taskcontainer=obj.taskcontainer.printtasks;
end
%% Wavegen timing structure setters
% function obj = setwavegentimingsources(obj, tstart, dt, tstop)
% assert(ischar(tstart), 'SCDclass_algo.setwavegentimingsources first parameter must be a char array');
% assert(ischar(dt), 'SCDclass_algo.setwavegentimingsources first parameter must be a char array');
% assert(ischar(tstop), 'SCDclass_algo.setwavegentimingsources first parameter must be a char array');
%
% obj.wavegentiming.t_start=tstart;
% obj.wavegentiming.dt=dt;
% obj.wavegentiming.t_stop=tstop;
% end
%% Timing information
function obj = settiming(obj, t_start, dt, t_stop)
obj.timing.t_start=t_start;
obj.timing.dt=dt;
obj.timing.t_stop=t_stop;
end
%% Fixed inits
function obj = addfpinitfcn(obj, fcnname, targetstruct,targetworkspace)
if nargin<3
targetstruct = '';
end
if nargin<4
targetworkspace = 'global'; % default: global workspace (assigninGlobal)
end
if ~iscell(targetstruct) && ~isempty(targetstruct)
targetstruct = {targetstruct};
end
if(~isempty(obj.stdinits))
for ii=1:numel(obj.stdinits)
if ~isempty(targetstruct) && contains(obj.stdinits{ii}{2},targetstruct)
warning('SCDclass_algo:addfpinitfcn','A function defining the structure %s has already been added, ignoring.\d',targetstruct)
return
% FF question to CG: why is this a cell and not a struct?
temp=cell(10,1);
temp{1}=fcnname;
temp{2}=targetstruct;
temp{3}=targetworkspace;
obj.stdinits{end+1}=temp;
end
function printinits(obj)
if(~isempty(obj.stdinits))
for ii=1:numel(obj.stdinits)
fprintf('%s -> %s in workspace %s \n',char(obj.stdinits{ii}{1}),char(obj.stdinits{ii}{2}{1}),char(obj.stdinits{ii}{3}));
function callinits(obj)
% call initialization functions that set fixed parameters
if ~isempty(obj.stdinits)
for ii=1:numel(obj.stdinits)
initfunction = obj.stdinits{ii}{1};
targetnames = obj.stdinits{ii}{2};
workspace = obj.stdinits{ii}{3};
nout = numel(targetnames);
fprintf('Calling init function ''%s'', assigning its output to ''%s'' ...\n',...
char(initfunction),cell2mat(targetnames));
if ischar(initfunction)
initcmd=sprintf('%s(obj);', initfunction);
[value{1:nout}] = eval(initcmd);
elseif isa(initfunction,'function_handle')
if nargin(initfunction)==1
elseif nargin(initfunction)==0
else
error('unexpected number of input arguments for function %s',func2str(initfunction));
end
[value{1:nout}] = initfunction(argins{:}); % function has an input argument
else
error('initfunction must be a string or a function handle')
end
% assigns in base workspace or datadictionary depending
% on target workspace
for iout = 1:nout
% cycle over number of output arguments of the function
val = value{iout};
target = targetnames{iout};
if strcmp(workspace,'global')
Simulink.data.assigninGlobal(obj.modelname, target, val);
elseif strcmp(workspace,'base')
assignin('base',target,val)
end
end
function compile(obj)
try
eval(sprintf('%s([],[],[],''compile'')',obj.modelname));
catch
eval(sprintf('%s([],[],[],''term'')',obj.modelname));
end
eval(sprintf('%s([],[],[],''term'')',obj.modelname));
end
function sim(obj)
sim(obj.modelname);
end
function open(obj)
open(obj.modelname)
end