MATLAB: How to use lsqcurvefit to optimize a series of Simulink outputs

Curve Fitting ToolboxlsqcurvefitParallel Computing Toolboxsimulink

I have a series of data points for which I have experimental data. I also have a complex simulink model that can take each data point and calculate the theoretical result based on a range of parameters. I'd like to use lsqcurvefit to match the simulink calculations to the experimental data.
My approach is to create a function block that calls the simulink model from within a for loop so that the model can be run for each data point. I then use a script to call lsqcurvefit to match the output of the function looping the simulink model to the real world data. The problem I am having is that if a use set_param to change more than one variable within the simulink model lsqcurvefit ceases to function properly and returns the initial guess as an optimal fit.
I've whittled the model and program down to a basic scenario that shows how changing one parameter disrupts lsqcurvefit.
My function for looping the simulink model is:
if true
function [Output]=Test_Model2(Variables,X_Data)
Variables
model = 'Test_Sim';
load_system(model);
idx=1;
for idx=1:length(X_Data);
set_param([model '/X_Data'],'Value',num2str(X_Data(idx)));
% set_param([model '/Gain'],'Gain',num2str(Variables(1)));
simout(idx)=sim(model, 'SimulationMode', 'normal','SrcWorkspace','current');
Time_Data(idx)=simout(idx).get('simout');
Output(idx,:)=Time_Data(idx).Data(1,[1:length(Variables)]);
end
set_param([model '/X_Data'],'Value','X_Data');
set_param([model '/Gain'],'Gain','Variables');
close_system(model, 0);
% Output=Variables(1)*X_Data;
Output
end
And the code for calling lsqcurvefit is
if true
clear
Y_Data = [10];
X_Data = [3.11];
X0 = [23];
[x]=lsqcurvefit(@Test_Model2,X0,X_Data,Test_Model2([Y_Data],X_Data));
end
The Test_Sim.mdl is attached. This function works just fine as it is.
However, if I uncomment the second set_param command in Test_Model2 then lsqcurvefit ceases to find the optimal solution and says the initial guess is optimal.
My overall goal will be to change the for loop into a parfor loop eventually to make use of the parallel computing toolbox.
Any suggestions?
Kind regards,
Matt

Best Answer

  • The answer turned out to be a simple one.
    The default precision num2str uses is lower than the perturbation size used by lsqcurvefit. By controlling the precision of the num2str function (say num2str(X_Data(idx),17) ) the scripts work perfectly.
    With the set_param commands functioning as expected I can remove the 'SrcWorkspace','current' option on the sim function and configure the model looping function to run parallel loops of the model using parfor. This significantly drops the processing time even on this simple model.
    Cheers!
    Matt