Optimisation for 3-element Windkessel Model Not Working - Using Least Squares Method and fminsearch. Advice? Should I use other optimisation algorithms?
2 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
Hussam
el 24 de Mzo. de 2024
Comentada: Hussam
el 25 de Mzo. de 2024
So I am trying to optimise the parameters (R1, R2, C) for the 3-element windkessel model for the aorta. I am supplying it with tabular data for the Pressure and Flow (Q), but neither of the models are doing anything, and not giving any errors either. Kindly advise.
My code is as follows:
clear all
close all
clc
%% Inputs
R1 = 4.4e+6;
R2 = 1.05e+8;
C = 1.31e-8;
% L = 6.799e+5;
TimeStep = 0.001;
Beta = TimeStep / (C*R2);
%Initial conditions for WK-3 parameters
IC = [C, R1, R2];
%% Importing flow and pressure data
RefPQWK = readtable('Ref_P_Q_WK_No-Osc_1-Cycle.csv');
t=RefPQWK.t;
Q=RefPQWK.Q;
P=RefPQWK.P;
P0=RefPQWK.P(1);
Q0=RefPQWK.Q(1);
dt = TimeStep;
t_0 = 0:dt:t(end);
Q = smooth(interp1(t, Q, t_0), 50);
P = smooth(interp1(t, P, t_0), 50);
%Initial conditions
IC_Q = Q(1);
IC_P = P(1);
dP = diff(P)./dt;
dP(end+1) = dP(end);
dQ = diff(Q)./dt;
dQ(end+1) = dQ(end);
%dqdt = derivative(Q,t_0);
%% Curve fitting using the method of least squares
LB = [1e-10 1 1]; UB = [1 1e10 1e10]; % Lower and Upper bounds
options = optimoptions('lsqcurvefit', 'Algorithm', 'levenberg-marquardt', 'StepTolerance', 1e-100,'FunctionTolerance', 1e-10,'Display','iter');
%options = optimoptions('lsqcurvefit', 'Algorithm', 'levenberg-marquardt', 'MaxFunctionEvaluations', 1e100, 'MaxIterations', 1e4, 'StepTolerance',1e-300, 'Display','iter');
%options =optimoptions('lsqcurvefit','MaxFunctionEvaluations', 1e100, 'MaxIterations', 1e100,'Display','iter');
f = @(x, t_0)fun_lsq(x, t_0, dt, P, Q, dQ, IC_P);
%ydata=zeros(1, height(P))';
sol = lsqcurvefit(f, IC, t_0, P, LB, UB, options);
C_optim = sol(1); Rp_optim = sol(2); Rd_optim = sol(3);
%% Curve fitting using the fminsearch
% options = optimset('Display','iter','PlotFcns',@optimplotfval);
%
% f = @(x)fun_fmin(x, t_0, dt, P, Q, dQ, IC_P);
% sol = fminsearch(f,IC);
%% Solving and Plotting ODE for P
tspan = [t_0(1):dt:t_0(end)]; %Time interval of the integration
funP = @(t,y_P) P_odefcn(t, y_P, C, R1, R2, t_0, Q, dQ);
[t,y_P] = ode78(funP, tspan, IC_P);
funP_opt = @(t,y_P_opt) P_odefcn(t, y_P_opt, C, R1, R2, t_0, Q, dQ);
[t,y_P_opt] = ode78(funP, tspan, IC_P);
% y_Q = smooth(interp1(t, y_Q, t_0), 50);
y_P = smooth(interp1(t, y_P, t_0), 50);
y_P_opt = smooth(interp1(t, y_P, t_0), 50);
figure(1), plot(t_0, P), hold on, plot(t_0, y_P); hold on, plot(t_0, y_P_opt);
xlabel('Time'); ylabel('P')
legend('Actual', 'Stergiopoulos', 'Optimised')
%% Function for lsq optimisation
function f = fun_lsq(x, time, dt, P_in, Q_out, dQ_out, IC_p)
%Renaming the constants
C = x(1); R1 = x(2); R2 = x(3);
tspan = [0:dt:time(end)]; %Time interval of the integration
%Solving the ODEs
fun2 = @(t,y) P_odefcn(t, y, C, R1, R2, time, Q_out, dQ_out);
[t,y] = ode78(fun2, tspan, IC_p);
P = y(:,1);
%Q=interp1(t, Q, time);
f = P-P_in;
end
%% Function for fminsearch optimisation
function f = fun_fmin(x, time, dt, P_in, Q_out, dQ_out, IC_p)
%Renaming the constants
C = x(1); R1 = x(2); R2 = x(3);
tspan = [0:dt:time(end)]; %Time interval of the integration
%Solving the ODEs
fun2 = @(t,y) P_odefcn(t, y, C, R1, R2, time, Q_out, dQ_out);
[t,y] = ode78(fun2, tspan, IC_p);
P = y(:,1);
%Q=interp1(t, Q, time);
f = sqrt(sum((P-P_in).^2));
end
%% Function for ODE
function dPdt = P_odefcn(t, y, C, Rp, Rd, time, Q_in, dQ_in)
dPdt = zeros(1,1); %Initializing the output vector
%Determine the closest point to the current time
[d, closestIndex]=min(abs(time-t));
Q = Q_in(closestIndex);
dQ = dQ_in(closestIndex);
dPdt(1) =(Q/C)*(1+Rp/Rd) + Rp*dQ - y(1)/(C*Rd);
end
Both results look like this:
I do get the following for the LSQ method though:
6 comentarios
Torsten
el 24 de Mzo. de 2024
If you use "lsqcurvefit", you must return
f = P;
not
f = P-P_in;
Don't you have a separate equation for Q so that you wouldn't need to differentiate your measurement data ?
[d, closestIndex]=min(abs(time-t));
Q = Q_in(closestIndex);
dQ = dQ_in(closestIndex);
Respuesta aceptada
Torsten
el 24 de Mzo. de 2024
Movida: Torsten
el 24 de Mzo. de 2024
I'd try to continue with the code below.
It seems that a variation of your initial parameters does not cause a change in P such that the initial values for C, R1 and R2 are returned by the solver.
Unfortunately, I do not have an equation for Q, since it is the output of a simulation, I can try to formulate one though - would that make a difference?
The difference is that the inputs to the differential equation for P would become smooth which is usually necessary for the integrators to succeed.
%% Inputs
R1 = 4.4e+6;
R2 = 1.05e+8;
C = 1.31e-8;
%Initial conditions for WK-3 parameters
IC = [C, R1, R2];
%% Importing flow and pressure data
RefPQWK = readtable('Ref_P_Q_WK_No-Osc_1-Cycle.csv');
t=RefPQWK.t;
Q=RefPQWK.Q;
P=RefPQWK.P;
P0=RefPQWK.P(1);
Q0=RefPQWK.Q(1);
%Initial conditions
IC_P = P(1);
%% Curve fitting using the method of least squares
LB = [1e-10 1 1]; UB = [1 1e10 1e10]; % Lower and Upper bounds
options = optimoptions('lsqcurvefit', 'Algorithm', 'levenberg-marquardt', 'MaxFunEvals',10000,'MaxIter',10000,'Display','iter');
f = @(x, t)fun_lsq(x, t, P, Q, IC_P);
sol = lsqcurvefit(f, IC, t, P, LB, UB, options);
C_optim = sol(1)
Rp_optim = sol(2)
Rd_optim = sol(3)
%% Solving and Plotting ODE for P
[t,Psim] = integration(C_optim,Rp_optim,Rd_optim,t,Q,IC_P);
hold on
plot(t,P)
plot(t,Psim)
hold off
%% Function for lsq optimisation
function f = fun_lsq(x, time, P_in, Q_out, IC_p)
%Renaming the constants
C = x(1); R1 = x(2); R2 = x(3);
[t,y] = integration(C,R1,R2,time,Q_out,IC_p);
P = y(:,1);
f = P;
end
function [t,y] = integration(C,R1,R2,time,Q_out,IC_p)
fun2 = @(t,y) P_odefcn(t, y, C, R1, R2, time, Q_out);
[t,y] = ode45(fun2, time, IC_p);
end
%% Function for ODE
function dPdt = P_odefcn(t, y, C, Rp, Rd, time, Q_in)
dPdt = zeros(1,1); %Initializing the output vector
%Determine the closest point to the current time
%[d, closestIndex]=min(abs(time-t));
Q = interp1(time,Q_in,t);
for i = 1:numel(time)
if time(i+1) >= t
dQ = (Q_in(i+1)-Q_in(i))/(time(i+1)-time(i));
break
end
end
%dQ = dQ_in(closestIndex);
dPdt(1) =(Q/C)*(1+Rp/Rd) + Rp*dQ - y(1)/(C*Rd);
end
8 comentarios
Torsten
el 25 de Mzo. de 2024
In my opinion, setting p_out = 0 is simply wrong because measurements and model have different asymptotic behavior (measurements tend to P(1), model tends to 0).
In your objective function for fminsearch, you should replace
f = sqrt(sum((P-P_in).^2))
by
f = sum((P-P_in).^2);
The sqrt makes your objective function non-differentiable at 0.
Más respuestas (0)
Ver también
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!