classdef SCDclass_algo %SCD algorithm handling object % The class holds all information and % methods for handling a Simulink % algorithm properties (SetAccess = private, Hidden=false) modelname % Name of the model modelslx % slx model file name folder % folder containing algorithm datadictionary % Name of the used data dictionary end properties (SetAccess = private,Hidden=true) mdscontainer % Container class for MDS+ interface objects taskcontainer % Container class for init and term tasks exportedtps % fList of tunable parameters variable to be exported refdatadictionaries % Cell array of referenced data dictionaries refddparentalgo % Parent algorithm of referenced data dictionaries stdinits % General initialization scripts fpinits % inits scripts for fixed parameters timing % Timing info structure exportedtpsdefaults % default tunable parameters defining functions exportedtpspermiss % tunable parameters loading error permissivity rule buslist % list of buses and their sources defaulttunparampermissivity % default tunparams loading permissivity wavegenbasestruct % base struct name of the next added wavegen exportedwgstructs % list of exported waveforms structs end properties SCDBusdd_path % location of folder for datadictionary containing SCDsignal buses end properties(Hidden=true, Constant) SCDBusdd_name = 'SCDBuses.sldd'; % name of datadictionary contining SCD signal buses end methods function obj=SCDclass_algo(name) %% Constructor % Empty algorithm constructor obj.modelname=name; obj.mdscontainer = SCDclass_mdsobjcontainer; obj.taskcontainer = SCDclass_taskcontainer; obj.exportedtps = {}; obj.exportedtpsdefaults = {}; obj.exportedtpspermiss = {}; obj.stdinits = {}; obj.fpinits = {}; obj.datadictionary = ''; obj.refdatadictionaries = {}; obj.timing.t_start = 0 ; obj.timing.t_stop = 1 ; obj.timing.dt = 1e-3; obj.buslist = []; obj.defaulttunparampermissivity = true; obj.wavegenbasestruct = ''; obj.exportedwgstructs = {}; % Buses obj.modelslx = [obj.modelname,'.slx']; % files % algo path depending on .slx location assert(~isempty(which(obj.modelslx)),'can''t find slx model %s',obj.modelslx); obj.folder = fileparts(which(obj.modelslx)); % bus where to store SCDbus data dictionary same as algo by % default obj.SCDBusdd_path = obj.folder; % default % 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('* Buses: \n'); obj.printbuslist; fprintf('*****************************************************\n'); end function printinits(obj) fprintf('****** Registered initialization functions ******* \n') if(~isempty(obj.fpinits)) for ii=1:numel(obj.fpinits) if isempty(obj.fpinits{ii}{2}) fprintf('%s : init function with no outputs\n',char(obj.fpinits{ii}{1})); else fprintf('%s -> %s in workspace %s \n',char(obj.fpinits{ii}{1}),char(obj.fpinits{ii}{2}{1}),char(obj.fpinits{ii}{3})); end end end end function printMARTe2parconfig(obj, shot) %obj.mdscontainer.modeltogenerate=obj.modelname; obj.mdscontainer.modeltogenerate='all'; obj.mdscontainer.printMARTe2parconfig(shot); end function printMARTe2wgbusconfig(obj, shot, busname, frequency, varargin) % printMARTe2wgbusconfig(obj, shot, busname, frequency, varargin) % % prints cfg file for loading busname Simulink.Bus % as a wavegen (or a set of them) in MARTe2 % shot can be -1 or a fixed shot (usually -1), but currently % the Shot= entry is populated by a fixed macro % frequency is the frequency of signal generation in MARTe2 % the optional parameter 'ddname' can be given to specify % the data dictionary where the bus definition is, if omitted % the default expcode level data dicationary is used p=inputParser; addParameter(p,'ddname',obj.datadictionary,@(x) ischar(x)); parse(p,varargin{:}); myddname = p.Results.ddname; obj.mdscontainer.printMARTe2wgbusconfig(shot, myddname, busname, frequency); end %% 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 [stdinits, fpinits] = getinits(obj) stdinits = obj.stdinits; fpinits = obj.fpinits; end function refdd = getrefdd(obj) refdd = obj.refdatadictionaries; end function refddparent = getrefddparentalgo(obj) refddparent = obj.refddparentalgo; end %% Setup functions setter and getter function obj = addstdinitfcn(obj,fcnhandle) if ischar(fcnhandle) fcnhandle = str2func(fcnhandle); end assert(isa(fcnhandle,'function_handle'),'stdinit function must be a function handle'); assert(nargout(fcnhandle)<=0,'stdinit functions may not have output arguments') obj.stdinits{end+1} = fcnhandle; end function obj = addfpinitfcn(obj, fcnname, targetstruct,targetworkspace) if nargin < 4 targetworkspace = 'datadictionary'; end if ~iscell(targetstruct) && ~isempty(targetstruct) targetstruct = {targetstruct}; end for ii=1:numel(obj.fpinits) for istruct = 1:numel(targetstruct) mytarget = targetstruct{istruct}; if ~isempty(mytarget) && contains(obj.fpinits{ii}{2},mytarget) warning('SCDclass_algo:addfpinitfcn',... 'A function defining the structure %s has already been added, ignoring.\n',mytarget) return end end end % 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.fpinits{end+1}=temp; end %% Bus setter and getter function obj = addbus(obj,name,source) assert(~isequal(name,source),'bus source file and name may not be the same') % Register a bus from a file to be added to dd ii = numel(obj.buslist)+1; obj.buslist(ii).name = name; obj.buslist(ii).source = source; end function list = getbuslist(obj) list = obj.buslist; end function printbuslist(obj) list = getbuslist(obj); fprintf('******* Registered bus definitions files for %s: *****\n',obj.modelname) fprintf('%-25s %-15s %-50s\n','Name','Type','Source') for ii=1:numel(list) if isa(list(ii).source,'function_handle') type = 'function handle'; fcs = functions(list(ii).source); source = fcs.file; name = 'DEFINED IN FILE'; else type = 'file'; name = list(ii).name; source = which([list(ii).source,'.m']); end if isempty(source), source='NOT FOUND'; end fprintf('%-25s %-15s %-50s\n',name,type,source); end fprintf('\n'); end %% Data dictionary setter and getter function obj = setdatadictionary(obj, datadict) obj.datadictionary=datadict; end function out = getdatadictionary(obj) out = obj.datadictionary; end function obj = addrefdd(obj,refdd,parentalgo) % refdd: name of referenced data dictionary % parentalgo: (optional), SCDclass_algo object of algorithm % generating this data dicationary. if nargin<3, parentalgo=''; end assert(isequal(refdd(end-4:end),'.sldd'),'refdd must end in .sldd') obj.refddparentalgo{end+1} = parentalgo; obj.refdatadictionaries{end+1} = refdd; end %% Wavegens setter and getters function obj = addwavegenbasetruct(obj, basestruct) obj.exportedwgstructs{end+1}=basestruct; end %% Data dictionary manipulation manipulations function addbusestodd(obj) % Add buses to data dictionary from .m file descriptions dictionaryObj = Simulink.data.dictionary.open(obj.getdatadictionary); designDataObj = getSection(dictionaryObj, 'Design Data'); SCDBusdd_populated = false; % flag to signal whether SCDBus data dictionary was populated busList = obj.getbuslist; for ii=1:numel(busList) mybusSource = busList(ii).source; busName = busList(ii).name; if ischar(mybusSource) % User specified a file that contains a bus definition % (typically exported from bus editor) fprintf('Adding bus %s from %s to %s\n',busName,mybusSource,obj.getdatadictionary); assert(logical(exist(mybusSource,'file')),'%s does not exist',mybusSource) eval(mybusSource); % eval bus script here assert(exist(busName,'var')~=0,... 'no variable %s found despite running script %s',busName,which(mybusSource)) names{1} = busName; buses{1} = eval(busName); sourcename = mybusSource; elseif isa(mybusSource,'function_handle') % user specified a function that returns cell arrays of % bus names and bus objects. busNames is ignored in this case [names,buses] = mybusSource(); sourcename = func2str(mybusSource); else error('don''t know how to handle %s',class(mybusSource)) end for jj=1:numel(buses) % loop over buses to be added if startsWith(names{jj},'SCDBus_') if ~SCDBusdd_populated % first call obj.createdatadictionary(obj.SCDBusdd_name,obj.SCDBusdd_path); dictionaryObj_SCDbus = Simulink.data.dictionary.open(obj.SCDBusdd_name); designDataObj_SCDbus = getSection(dictionaryObj_SCDbus, 'Design Data'); % add link to algo dictionary if necessary if ~ismember(obj.SCDBusdd_name,dictionaryObj.DataSources) % does not exist, try to add fprintf('adding referenced data dictionary %s to %s \n',obj.SCDBusdd_name,obj.getdatadictionary) dictionaryObj.addDataSource(obj.SCDBusdd_name); end SCDBusdd_populated = true; end % If SCDBus, add to general SCDbus data dictionary dd_target = obj.SCDBusdd_name; designDataObj_target = designDataObj_SCDbus; dictionaryObj_target = dictionaryObj_SCDbus; else % add to algo dd dd_target = obj.getdatadictionary; designDataObj_target = designDataObj; dictionaryObj_target = dictionaryObj; end fprintf('adding bus %25s from function %s to %s\n',... names{jj},sourcename,dd_target) obj.replaceorcreateddentry(designDataObj_target,names{jj},buses{jj}); end end if dictionaryObj.HasUnsavedChanges dictionaryObj.saveChanges; end % Save if necessary if SCDBusdd_populated && dictionaryObj_SCDbus.HasUnsavedChanges dictionaryObj_target.saveChanges; end % Save if necessary end function addrefddtodd(obj) % other optional data dictionaries (e.g. used by lower-level components of an algorithm) % specified in refdatadictionaries dictionaryObj = Simulink.data.dictionary.open(obj.getdatadictionary); %refddlist = [obj.refdatadictionaries,'configurations.sldd']; % list of referenced dds refddlist = obj.refdatadictionaries; % list of referenced dds for ii=1:numel(refddlist) refdd = refddlist{ii}; if ~ismember(refdd,dictionaryObj.DataSources) % does not exist, try to add fprintf('adding referenced data dictionary %s to %s \n',refdd,obj.getdatadictionary) refddpath = which(refdd); if isempty(refddpath) % data dictionary to link does not exist, try to generate it parentalgo = obj.refddparentalgo{ii}; if isempty(parentalgo) error('Data dictionary %s was not found but no parent algorithm is specified',refdd{ii}) else fprintf('Data dictionary %s was not found, running init of parent algorithm %s to create it\n',parentalgo.getname) parentalgo.SCDBusdd_path = obj.SCDBusdd_path; % use same SCDbusdd path as parent % run parent algo init parentalgo.init; % check expected dd now exists refddpath = which(refdd); assert(~isempty(refddpath),... 'Data dictionary still not found despite running %s init, aborting',parentalgo.getname) end end fprintf('Adding referenced data dictionary %s to %s\n',refdd,obj.getdatadictionary) dictionaryObj.addDataSource(refdd); else % already exists fprintf('Data dictionary %s is already referenced in algo data dictionary, not adding\n',refdd); end end if dictionaryObj.HasUnsavedChanges, dictionaryObj.saveChanges; end end function replaceorcreateddentry(obj,designDataObj,entry,value) if designDataObj.exist(entry) oldEntry = designDataObj.getEntry(entry); assert(numel(oldEntry)==1,'multiple entries found for %s',entry) if isequal(oldEntry.getValue,value) fprintf('%s: keep old value of %s since not changed\n',obj.getname,entry); else oldEntry.setValue(value); % replace fprintf('%s: replaced value of %s since it changed\n',obj.getname,entry); end else fprintf(' %s: added new %s\n',obj.getname, entry); designDataObj.addEntry(entry,value); end end %% Tunable parameters structures handling functions function out = getexportedtps(obj) out = obj.exportedtps; end function obj = addtunparamstruct(obj, structname, default_function, load_permissive) % obj = addtunparamstruct(structname, varargin) % % adds a tunable parameter to the algo object % inputs: % structname: name of the tunable param (string) % default_function: a function handle to get % its default value, this function takes no arguments % and must return either a struct or a Simulink.Parameter % load_permissive: a boolean value, if true any failing % loading attemp to this structure (via a loading function) % will return a warning, otherwise an error. Default: true. % % 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!'); end if nargin>=3 assert(isa(default_function, 'function_handle'),'SCDclass_algo:addtunparamstruct', 'third argument, if present, must be a function handle'); obj.exportedtpsdefaults{end+1} = default_function; % add defaults to list else obj.exportedtpsdefaults{end+1} = []; % empty, no default assigned for this tp end if nargin==4 assert(isa(load_permissive,'logical'),'SCDclass_algo:addtunparamstruct','fourth argument, if present, must be boolean'); obj.exportedtpspermiss{end+1} = load_permissive; else obj.exportedtpspermiss{end+1} = true; end end function obj = updatetemplatetp(obj) % obj = updatetemplatetp() % % For every configured tunparams structure % if a default value function is present it is % updated in the template version of the tun params % in the algo data dictionary. % The default value function of a tunparams can be given % as an optional third argument of addtunparamstruct % method dict = Simulink.data.dictionary.open(obj.getdatadictionary); designDataobj = getSection(dict, 'Design Data'); 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 P.CoderInfo.StorageClass='ExportedGlobal'; % updates default tunable parameters structure in data dictionary tmplname = sprintf('%s_tmpl',obj.exportedtps{ii}); if designDataobj.exist(tmplname) oldEntry = designDataobj.getEntry(tmplname); % isequal does not detect type changes %if isequal(oldEntry.getValue.Value,P.Value) % fprintf('%s: keep old template %s since not changed\n',obj.getname,tmplname); % continue; %else % % replace % oldEntry.setValue(P); % fprintf('%s: replaced value of template %s since it changed\n',obj.getname,tmplname) %end oldEntry.setValue(P); fprintf('%s: replaced value of template %s\n',obj.getname,tmplname) else fprintf(' %s: added new %s\n',obj.getname, tmplname); designDataobj.addEntry(tmplname,P); end end end end function buildworkspacetpstruct(obj) % buildworkspacetpstruct(obj) % % This funtion builds workspace structures containing % replicas of all tunable parameters structures in the data % dictionaries, this structure is the one actually used % 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 % consequently the SCD GIT itself 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) tp_name = obj.exportedtps{ii}; hasdefault = ~isempty(obj.exportedtpsdefaults); if hasdefault tp_tmpl_name=sprintf('%s_tmpl',tp_name); try tp_value = dd.getEntry(tp_tmpl_name).getValue; catch ME fprintf('error getting %s from dd %s\n',tp_tmpl_name,obj.datadictionary) rethrow(ME) end assignstr=sprintf('%s=temp;',tp_name); assignin('base','temp',tp_value); evalin('base',assignstr); else % no default template defined, define from generating function handle fprintf('no default defined for %s\n',tp_name) end end evalin('base','clear temp;'); %cleanup end function buildworkspacesimdata(obj) % buildworkspacesimdata(obj) % % This function builds a SCDsimdata structure % containing the necessary timeseries to support % a standalone simulation of the algorithm % % Currently it prepares a timeseries structure % to be filled with the wavegens configured within % the algorithm simdata = struct; numwavegens=obj.mdscontainer.getnumwavegens(); if numwavegens>0 %obj.mdscontainer=obj.mdscontainer.setwavegenbasestruct([obj.getname '_simdata']); for wgidx=1:numwavegens wg=obj.mdscontainer.mdswavegens(wgidx); eval(['simdata.' wg.gettarget '=timeseries(wg.castdata([0;0]),[0;1]);']); assignin('base',wg.getbasestruct,simdata); end %assignin('base',wg.getbasestruct,simdata); else warning('SCDclass_algo:buildworkspacesimdata','No wavegens configured for this algo, nothing to do.'); return; end end %% MDS container methods forwarders function obj = addparameter(obj, params) % obj = addparameter(obj, params) % % this method offers the way to add tunable % parameters description to the object. % params must resolve to a SCDDS loader class % object % % assume this parameter is bound to last exported tp on the % % example: % % obj=obj.addtunparamstruct('algo_template_tp', @()algo_template_loadtp()); % obj=obj.addparameter(SCDclass_mdsparnumeric('ks1','gain' ); % % the couples of lines before first add a tunable parameter % structure and the a numeric type loader class. % The final result is that this logical link between % the source param and dest Simulink.Parameter object % will be put in place: % % algo_template_tp.gain <-> ks1 if ~isempty(obj.exportedtps), tpname = obj.exportedtps{end}; else, tpname = ''; end if ~isempty(obj.exportedtpspermiss), permiss = obj.exportedtpspermiss{end}; else, permiss = obj.defaulttunparampermissivity; end % bind parameter(s) to algoobj's name, dictionary and exportedtp params = params.bind(obj.modelname, obj.datadictionary, tpname, permiss); % add params to mdscontainer obj.mdscontainer=obj.mdscontainer.addparameter(params); 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) if ~isempty(obj.exportedwgstructs), wgbasename = obj.exportedwgstructs{end}; else, wgbasename = ''; end % bind wavegen to modelname, dd, algo timing and base struicture % name for ii=1:numel(wavegen) wavegen(ii) = wavegen(ii).bind(obj.modelname,obj.datadictionary,obj.timing,wgbasename); end % add to algo's mds object container obj.mdscontainer=obj.mdscontainer.addwavegen(wavegen); % set default wavegen base structure name % if isempty(obj.wavegenbasestruct) % obj.mdscontainer=obj.mdscontainer.setwavegenbasestruct([obj.getname '_simdata']); % else % obj.mdscontainer=obj.mdscontainer.setwavegenbasestruct([obj.wavegenbasestruct '_simdata']); % end 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 actualize(obj, shot) % actualize(shot) % % this method actualizes (fetches from source % and updates values) all defined % tunable parameteres (previously added % with the addparameter method) and % waveforms (previously added via the addwavegen % method) actualizeparameters(obj, shot); actualizewavegens(obj, shot); 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 %% 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 %% Initializations function initdd(obj) % setup data dictionary % generate data dictionary if it does not exist yet obj.createdatadictionary(obj.getdatadictionary,obj.folder); % link data dictionary to model and enable access to base obj.load; % call fixed parameter setup functions obj.callfpinits; % populate with template tunable parameters obj.updatetemplatetp; % add referenced data dictionaries to obj data dictionary obj.addrefddtodd % add buses obj.addbusestodd; end function callinits(obj) for ii=1:numel(obj.stdinits) fprintf('calling standard init function %s\n',func2str(obj.stdinits{ii})); initfunction = obj.stdinits{ii}; initfunction(); % call it end end function callfpinits(obj) % call initialization functions that set fixed parameters if ~isempty(obj.fpinits) for ii=1:numel(obj.fpinits) initfunction = obj.fpinits{ii}{1}; targetnames = obj.fpinits{ii}{2}; workspace = obj.fpinits{ii}{3}; nout = numel(targetnames); if ~isempty(targetnames) fprintf('Calling fixed parameter init function ''%s'', assigning its output to ''%s'' in %s...\n',... char(initfunction),cell2mat(targetnames),workspace); end if ischar(initfunction) initcmd=sprintf('%s(obj);', initfunction); [value{1:nout}] = eval(initcmd); elseif isa(initfunction,'function_handle') if nargin(initfunction)==1 argins={obj}; elseif nargin(initfunction)==0 argins = {}; 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 target datadictionary depending % on target workspace fprintf('opening %s\n',obj.getdatadictionary); dictionaryObj = Simulink.data.dictionary.open(obj.getdatadictionary); dd = getSection(dictionaryObj, 'Design Data'); for iout = 1:nout % cycle over number of output arguments of the function val = value{iout}; target = targetnames{iout}; if strcmp(workspace,'datadictionary') % assign in associated data dictionary obj.replaceorcreateddentry(dd,target,val); elseif strcmp(workspace,'base') % assign in base workspace assignin('base',target,val) end end if dictionaryObj.HasUnsavedChanges, dictionaryObj.saveChanges; end end end end function callrefmodelinits(obj,modelname) % call initialization functions of referenced models in hierarchy refmodels = find_mdlrefs(modelname); for model = refmodels mymodel = model{:}; load_system(mymodel); if isequal(mymodel,modelname) % only init if model itself hws = get_param(mymodel,'modelworkspace'); if isequal(hws.DataSource,'MATLAB File') fprintf('\n**Initializing model workspace for %s from file %s **\n',mymodel,hws.FileName) hws.reload; % reload workspace data from file end else obj.callrefmodelinits(mymodel); % recursive call to go down the hierarchy end end end %% generic operation methods function init(obj) SCDconf_setConf('SIM'); obj.callinits; % call generic algorithm init functions obj.initdd; % setup data dictionary obj.callrefmodelinits(obj.getname); % setup workspaces for referenced models end function setup(obj) % setup() % % calls updatetemplatetp % buildworkspacetpstruct % buildworkspacesimdata % % an algorithm block diagram % should pass ctrl-d (instandalone opening) % after this call obj.updatetemplatetp; obj.buildworkspacetpstruct; obj.buildworkspacesimdata; SCDconf_setConf('sim'); end function compile(obj) try eval(sprintf('%s([],[],[],''compile'')',obj.modelname)); catch ME try eval(sprintf('%s([],[],[],''term'')',obj.modelname)); % terminate if necessary catch rethrow(ME); % rethrow error so we can see it end end eval(sprintf('%s([],[],[],''term'')',obj.modelname)); % terminate is successful end function sim(obj) sim(obj.modelname); end function test_harness(obj) harnessname = sprintf('%s_harness_run',obj.getname); if ~exist(harnessname,'file') warning('no harness %s found, skipping test',harnessname); return else fprintf('running test harness %s\n',harnessname); run(sprintf('%s(obj)',harnessname)); % input_init + sim + check_result % add tests to check output result somehow (TBD) end end function open(obj) open(obj.modelname) end function load(obj) load_system(obj.modelname); end function updatemds(obj, shot) %if shot~=-1 % error('SCDclass_expcode:updatemds','update permitted only on the model shot'); %end % % first update algorithm tunparams default locally % for ii=1:numel(obj.algonamelist) % if strcmp(algo, obj.algonamelist{ii}) % obj.algos{ii}.updatetemplatetp(); % end % end % % then update mds obj.mdscontainer.modeltogenerate=obj.modelname; obj.mdscontainer.autopopulateMDSparams(shot); obj.mdscontainer.autopopulateMDSwavegens(shot); end end methods(Static,Hidden=true) function createdatadictionary(ddname,folder) % Create data dictionary in path folder/ddname dd_fullpath = fullfile(folder,ddname); % Close this model's data dictionary if contains(Simulink.data.dictionary.getOpenDictionaryPaths,ddname) Simulink.data.dictionary.closeAll(ddname); end % Create if not existing already if isempty(which(dd_fullpath)) fprintf('generating data dictionary %s\n',dd_fullpath); Simulink.data.dictionary.create(dd_fullpath); ddname=Simulink.data.dictionary.open(dd_fullpath); ddname.EnableAccessToBaseWorkspace=1; end end end end