function [pOpt, Info] = parameterEstimationSdoBattery(p)
%PARAMETERESTIMATIONSDOBATTERY
%
% Solve a parameter estimation problem for the sdoBattery model.
%
% The function returns estimated parameter values, pOpt,
% and estimation termination information, Info.
%
% The input argument, p, defines the model parameters to estimate,
% if omitted the parameters specified in the function body are estimated.
%
% Modify the function to include or exclude new experiments, or
% to change the estimation options.
%
% Auto-generated by SPETOOL on 09-Jan-2020 13:57:40.
%

%% Open the model.
open_system('sdoBattery')

%% Specify Model Parameters to Estimate
%
if nargin < 1 || isempty(p)
    p = sdo.getParameterFromModel('sdoBattery',{'K','Loss','Q0','Qmax','V'});
    p(1).Value = 0.32;
    p(1).Free = 0;
    p(2).Value = 0.012;
    p(2).Free = 0;
    p(3).Value = 150;
    p(3).Minimum = 0;
    p(3).Scale = 256;
    p(4).Value = 250;
    p(4).Minimum = 0;
    p(4).Scale = 256;
    p(5).Value = 400;
    p(5).Free = 0;
end

%% Define the Estimation Experiments
%

Exper = sdo.Experiment('sdoBattery');

%%
% Specify the experiment input data used to generate the output.
Exper_Sig_Input = Simulink.SimulationData.Signal;
Exper_Sig_Input.Values    = getData('Exper_Sig_Input_Value');
Exper_Sig_Input.BlockPath = 'sdoBattery/Current';
Exper_Sig_Input.PortType  = 'outport';
Exper_Sig_Input.PortIndex = 1;
Exper_Sig_Input.Name      = 'Current';
Exper.InputData = Exper_Sig_Input;

%%
% Specify the measured experiment output data.
Exper_Sig_Output = Simulink.SimulationData.Signal;
Exper_Sig_Output.Values    = getData('Exper_Sig_Output_Value');
Exper_Sig_Output.BlockPath = 'sdoBattery/SOC -> Voltage';
Exper_Sig_Output.PortType  = 'outport';
Exper_Sig_Output.PortIndex = 1;
Exper_Sig_Output.Name      = 'sdoBattery/SOC -> Voltage:1';
Exper.OutputData = Exper_Sig_Output;

%%
% Create a model simulator from an experiment
Simulator = createSimulator(Exper);

%% Create Estimation Objective Function
%
% Create a function that is called at each optimization iteration
% to compute the estimation cost.
%
% Use an anonymous function with one argument that calls sdoBattery_optFcn.
optimfcn = @(P) sdoBattery_optFcn(P,Simulator,Exper);

%% Optimization Options
%
% Specify optimization options.
Options = sdo.OptimizeOptions;
Options.Method = 'lsqnonlin';
Options.OptimizedModel = Simulator;

%% Estimate the Parameters
%
% Call sdo.optimize with the estimation objective function handle,
% parameters to estimate, and options.
[pOpt,Info] = sdo.optimize(optimfcn,p,Options);

%%
% Update the experiments with the estimated parameter values.
Exper = setEstimatedValues(Exper,pOpt);

%% Update Model
%
% Update the model with the optimized parameter values.
sdo.setValueInModel('sdoBattery',pOpt);
end

function Vals = sdoBattery_optFcn(P,Simulator,Exper)
%SDOBATTERY_OPTFCN
%
% Function called at each iteration of the estimation problem.
%
% The function is called with a set of parameter values, P, and returns
% the estimation cost, Vals, to the optimization solver.
%
% See the sdoExampleCostFunction function and sdo.optimize for a more
% detailed description of the function signature.
%

%%
% Define a signal tracking requirement to compute how well the model
% output matches the experiment data.
r = sdo.requirements.SignalTracking(...
    'Method', 'Residuals');
%%
% Update the experiment(s) with the estimated parameter values.
Exper = setEstimatedValues(Exper,P);

%%
% Simulate the model and compare model outputs with measured experiment
% data.

F_r = [];
Simulator = createSimulator(Exper,Simulator);
strOT = mat2str(Exper.OutputData(1).Values.Time);
Simulator = sim(Simulator, 'OutputOption', 'AdditionalOutputTimes', 'OutputTimes', strOT);

SimLog = find(Simulator.LoggedData,get_param('sdoBattery','SignalLoggingName'));
Sig = find(SimLog,Exper.OutputData.Name);

Error = evalRequirement(r,Sig.Values,Exper.OutputData.Values);
F_r = [F_r; Error(:)];

%% Return Values.
%
% Return the evaluated estimation cost in a structure to the
% optimization solver.
Vals.F = F_r;
end

function Data = getData(DataID)
%GETDATA
%
% Helper function to store data used by parameterEstimation_sdoBattery.
%
% The input, DataID, specifies the name of the data to retrieve. The output,
% Data, contains the requested data.
%

SaveData = load('parameterEstimation_sdoBattery_Data');
Data = SaveData.Data.(DataID);
end
