3-Element Windkessel Model (Optimizing against flow (Q)): Why is my code so slow? It does not reach the optimizations.
16 views (last 30 days)
Show older comments
Hi, so I've wrote this code to optimize the parameters of a 3-element windkessel model. It was working when I was optimizing against the pressure (P), but when I switched it to flow (Q), it gets stuck calculating 'ppval' - it does not even reach the optimisation. Please advise. I have added the code and profiler results below. Is it the ODE function? I am suspecting that the ODE for Q is stiff, whereas for P it was not (even though it is the same equation)? How can I overcome this? Should I attempt the ODE solvers for stiff problems (e.g. ode15s) or for more accurate nonstiff problems (e.g. ode78)? Thanks!
The Windkessel model (P_out = 0):
%% Code to Optimize Parameters for Aorta 3-Element Windkessel Model
%%
clear all
close all
clc
%% Inputs
% For mmHg
% R1 * (0.000001/133.322);
% R2 * (0.000001/133.322);
% C * (133.322/0.000001);
R1 = 4.40e+06;
R2 = 1.05e+08;
C = 1.31e-08;
% Initial conditions for WK-3 parameters
IC = [C, R1, R2];
Q_peak = 5e-4; % Peak flow
t_s = 0.28; % Systolic Time
t_c = 0.84; % Cycle Time
dt=0.0001; % (CFD/FSI) Simulation Time Step
%% Importing flow and pressure data
RefQWK = readtable('Ref_P_Q_WK_No-Osc.csv');
RefPWK = readtable('Ref_P_Q_WK_No-Osc.csv');
P_ref=RefPWK.P; % multiply by 0.00750062 for mmHg
P0_ref=RefPWK.P(1); % multiply by 0.00750062 for mmHg
t_ref=RefPWK.t;
t=0:dt:t_ref(end);
P_smooth = smooth(interp1(t_ref, P_ref, t), 50);
P_spline = spline(t,P_smooth);
P_spline_dot = fnder(P_spline);
P=@(t) ppval(P_spline,t);
dPdt=@(t) ppval(P_spline_dot,t);
%Initial P condition
P0 = P(0);
%% Activate for flow data:
% Q_ref=RefQWK.Q; % multiply by e+6 for mL/s
% Q0_ref=RefQWK.Q(1);
% Q_smooth = smooth(interp1(t_ref, Q_ref, t), 50);
% Q_spline = spline(t,Q_smooth);
% Q_spline_dot = fnder(Q_spline);
%
% Q=@(t) ppval(Q_spline,t);
% dPdt=@(t) ppval(Q_spline_dot,t);
%
%Initial P condition
% Q0 = P(0);
%Activate for flow equation:
Q_eq = @(t)Q_peak*sin((pi*t)./t_s).^2.*(t>=0).*(t<=t_s);
Q = @(t)Q_eq(mod(t,t_c));
%Initial P condition
Q0 = Q(0);
%% Curve fitting using the method of least squares
LB = [1e-15 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, dPdt, Q0);
sol = lsqcurvefit(f, IC, t, Q(t), LB, UB, options);
C_optim_lsq = sol(1)
R1_optim_lsq = sol(2)
R2_optim_lsq = sol(3)
%% Curve fitting using the fminsearch
options = optimset('MaxFunEvals', 1e100, 'TolX', 1e-16, 'TolFun', 1e-16, 'Display','iter','PlotFcns',@optimplotfval);
f = @(x) fun_fmin(x, t, Q(t), P, dPdt, Q0);
sol = fminsearch(f,IC,options);
C_optim_fmin = sol(1)
R1_optim_fmin = sol(2)
R2_optim_fmin = sol(3)
%% Solving and Plotting ODE for Q
[t,Qsim_sterg] = integration(1.31e-8,4.4e+6,1.05e+8,t,P,dPdt,Q0);
[t,Qsim_lsq] = integration_data(C_optim_lsq,R1_optim_lsq,R2_optim_lsq,t,P,dPdt,Q0);
[t,Qsim_fmin] = integration_data(C_optim_fmin,R1_optim_fmin,R2_optim_fmin,t,P,dPdt,Q0);
[t,Qsim_fmin_manual] = integration_data(C,R1,R2,t,P,dPdt,Q0);
% PWK for FV
[t_FV_fmin, P_FV_fmin] = PWK_FV(C_optim_fmin, R1_optim_fmin, R2_optim_fmin, P0, Q(t), dt, t);
[t_FV_lsq, P_FV_lsq] = PWK_FV(C_optim_lsq, R1_optim_lsq, R2_optim_lsq, P0, Q(t), dt);
figure(1)
subplot(2,1,1)
plot(t,P(t),'DisplayName',strcat('Actual'))
plot(t_FV_lsq, P_FV_lsq, 'DisplayName',strcat('FlowVision lsq'))
plot(t_FV_fmin, P_FV_fmin, 'DisplayName',strcat('FlowVision fmin'))
title('PWK')
xlabel('Time (s)')
ylabel('Pressure (Pa)')
legend show
legend('Location', 'southeast', 'FontSize', 7)
subplot(2,1,2)
plot(t,Q(t), 'DisplayName',strcat('Actual'))
hold on
plot(t,Qsim_sterg,'DisplayName',strcat('Stergiopulos, C = 1.31E-8, R1 = 4.4E+6, R2 = 1.05E+8'))
plot(t,Qsim_lsq,'DisplayName',strcat('Sim LSQ, C =', num2str(C_optim_lsq, '%.3E'), ', R1 = ', num2str(R1_optim_lsq, '%.3E'), ', R2 = ', num2str(R2_optim_lsq, '%.3E')))
plot(t,Qsim_fmin,'DisplayName',strcat('Sim fmin, C =', num2str(C_optim_fmin, '%.3E'), ', R1 = ', num2str(R1_optim_fmin, '%.3E'), ', R2 = ', num2str(R2_optim_fmin, '%.3E')))
plot(t,Qsim_fmin_manual,'DisplayName',strcat('Sim manual, C =', num2str(C, '%.3E'), ', R1 = ', num2str(R1, '%.3E'), ', R2 = ', num2str(R2, '%.3E')))
hold off
title('QWK')
xlabel('Time (s)')
ylabel('Flow (m^{3}/s)')
legend show
legend('Location', 'southeast', 'FontSize', 7)
%% Function for lsq optimisation
function f = fun_lsq(x, time, P, dPdt, Q0)
%Renaming the constants
C = x(1); R1 = x(2); R2 = x(3);
[~,y] = integration(C,R1,R2,time,P,dPdt,Q0);
Q = y(:,1);
f = Q;
end
%% Function for fminsearch optimisation
function f = fun_fmin(x, time, Q_in, P, dPdt, Q0)
%Renaming the constants
C = x(1); R1 = x(2); R2 = x(3);
[~,y] = integration(C,R1,R2,time,P,dPdt,Q0);
Q = y(:,1);
f = sum((Q-Q_in).^2);
end
%% Function for ODE Integration using equation
function [t,y] = integration(C,R1,R2,time,P,dPdt,Q0)
ode_fun = @(t,y)((P(t)/(C*R1*R2)) + (dPdt(t)/R1) - (y(1)*(1/C*R1 + 1/C*R2)));
[t,y] = ode45(ode_fun, time, Q0);
end
%% Function for FV PWK
function [t_FV,P_FV] = PWK_FV(C_FV, R1_FV, R2_FV, P_FV_i, Q_FV, timestep, total_time)
t_FV=0:timestep:total_time(end);
P_FV=zeros(numel(t_FV):1);
P_FV(1) = P_FV_i;
for i=2:width(t_FV)
Beta = timestep / (C_FV*R2_FV);
Num1 = Q_FV(i)*( (Beta*R2_FV) + (Beta*R1_FV) + R1_FV );
Num2 = R1_FV*Q_FV(i-1);
Num3 = P_FV(i-1);
Num = Num1 - Num2 + Num3;
Den = 1 + Beta;
P_FV(i) = Num / Den;
end
end
I even tried to get rid of the equation for pressure and use tabular data (and reduced the data to 1 cycle), reduced the dt (timestep) to 0.01, as below, but it still gets stuck in the ODE function. Should I try another ode solver than ode45, maybe ode78?
%% Code to Optimize Parameters for Aorta 3-Element Windkessel Model
%%
clear all
close all
clc
%% Inputs
% For mmHg
% R1 * (0.000001/133.322);
% R2 * (0.000001/133.322);
% C * (133.322/0.000001);
R1 = 4.40e+06;
R2 = 1.05e+08;
C = 1.31e-08;
% Initial conditions for WK-3 parameters
IC = [C, R1, R2];
Q_peak = 5e-4; % Peak flow
t_s = 0.28; % Systolic Time
t_c = 0.84; % Cycle Time
dt=0.01; % (CFD/FSI) Simulation Time Step
%% Importing flow and pressure data
RefQWK = readtable('Ref_P_Q_WK_No-Osc_1-Cycle.csv');
RefPWK = readtable('Ref_P_Q_WK_No-Osc_1-Cycle.csv');
P_ref=RefPWK.P; % multiply by 0.00750062 for mmHg
P0_ref=RefPWK.P(1); % multiply by 0.00750062 for mmHg
t_ref=RefPWK.t;
t=0:dt:t_ref(end);
P0=P0_ref; %Initial P condition
P = smooth(interp1(t_ref, P_ref, t), 50);
dPdt = diff(P)./dt;
dPdt(end+1) = dPdt(end);
P0=P(1);
% P_smooth = smooth(interp1(t_ref, P_ref, t), 50);
% P_spline = spline(t,P_smooth);
% P_spline_dot = fnder(P_spline);
% P=@(t) ppval(P_spline,t);
% dPdt=@(t) ppval(P_spline_dot,t);
%Initial P condition for P equation
% P0 = P(0);
%% Activate for flow data:
% Q_ref=RefQWK.Q; % multiply by e+6 for mL/s
% Q0_ref=RefQWK.Q(1);
% Q_smooth = smooth(interp1(t_ref, Q_ref, t), 50);
% Q_spline = spline(t,Q_smooth);
% Q_spline_dot = fnder(Q_spline);
%
% Q=@(t) ppval(Q_spline,t);
% dQdt=@(t) ppval(Q_spline_dot,t);
%
%Initial Q condition
% Q0 = Q(0);
%Activate for flow equation:
Q_eq = @(t)Q_peak*sin((pi*t)./t_s).^2.*(t>=0).*(t<=t_s);
Q = @(t)Q_eq(mod(t,t_c));
%Initial P condition
Q0 = Q(0);
%% Curve fitting using the method of least squares
LB = [1e-15 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, dPdt, Q0);
sol = lsqcurvefit(f, IC, t_ref, Q(t), LB, UB, options);
C_optim_lsq = sol(1)
R1_optim_lsq = sol(2)
R2_optim_lsq = sol(3)
%% Curve fitting using the fminsearch
% options = optimset('MaxFunEvals', 1e100, 'TolX', 1e-16, 'TolFun', 1e-16, 'Display','iter','PlotFcns',@optimplotfval);
options = optimset('MaxFunEvals',10000,'MaxIter',10000, 'Display','iter','PlotFcns',@optimplotfval);
f = @(x) fun_fmin(x, t, Q(t), P, dPdt, Q0);
sol = fminsearch(f,IC,options);
C_optim_fmin = sol(1)
R1_optim_fmin = sol(2)
R2_optim_fmin = sol(3)
%% Solving and Plotting ODE for Q
[t,Qsim_sterg] = integration(1.31e-8,4.4e+6,1.05e+8,t,P,dPdt,Q0);
[t,Qsim_lsq] = integration_data(C_optim_lsq,R1_optim_lsq,R2_optim_lsq,t,P,dPdt,Q0);
[t,Qsim_fmin] = integration_data(C_optim_fmin,R1_optim_fmin,R2_optim_fmin,t,P,dPdt,Q0);
[t,Qsim_fmin_manual] = integration_data(C,R1,R2,t,P,dPdt,Q0);
% PWK for FV
[t_FV_fmin, P_FV_fmin] = PWK_FV(C_optim_fmin, R1_optim_fmin, R2_optim_fmin, P0, Q(t), dt, t);
[t_FV_lsq, P_FV_lsq] = PWK_FV(C_optim_lsq, R1_optim_lsq, R2_optim_lsq, P0, Q(t), dt);
figure(1)
subplot(2,1,1)
plot(t,P(t),'DisplayName',strcat('Actual'))
plot(t_FV_lsq, P_FV_lsq, 'DisplayName',strcat('FlowVision lsq'))
plot(t_FV_fmin, P_FV_fmin, 'DisplayName',strcat('FlowVision fmin'))
title('PWK')
xlabel('Time (s)')
ylabel('Pressure (Pa)')
legend show
legend('Location', 'southeast', 'FontSize', 7)
subplot(2,1,2)
plot(t,Q(t), 'DisplayName',strcat('Actual'))
hold on
plot(t,Qsim_sterg,'DisplayName',strcat('Stergiopulos, C = 1.31E-8, R1 = 4.4E+6, R2 = 1.05E+8'))
% plot(t,Qsim_lsq,'DisplayName',strcat('Sim LSQ, C =', num2str(C_optim_lsq, '%.3E'), ', R1 = ', num2str(R1_optim_lsq, '%.3E'), ', R2 = ', num2str(R2_optim_lsq, '%.3E')))
plot(t,Qsim_fmin,'DisplayName',strcat('Sim fmin, C =', num2str(C_optim_fmin, '%.3E'), ', R1 = ', num2str(R1_optim_fmin, '%.3E'), ', R2 = ', num2str(R2_optim_fmin, '%.3E')))
plot(t,Qsim_fmin_manual,'DisplayName',strcat('Sim manual, C =', num2str(C, '%.3E'), ', R1 = ', num2str(R1, '%.3E'), ', R2 = ', num2str(R2, '%.3E')))
hold off
title('QWK')
xlabel('Time (s)')
ylabel('Flow (m^{3}/s)')
legend show
legend('Location', 'southeast', 'FontSize', 7)
%% Function for lsq optimisation
function f = fun_lsq(x, time, P, dPdt, Q0)
%Renaming the constants
C = x(1); R1 = x(2); R2 = x(3);
[~,y] = integration(C,R1,R2,time,P,dPdt,Q0);
Q = y(:,1);
f = Q;
end
%% Function for fminsearch optimisation
function f = fun_fmin(x, time, Q_in, P, dPdt, Q0)
%Renaming the constants
C = x(1); R1 = x(2); R2 = x(3);
[~,y] = integration(C,R1,R2,time,P,dPdt,Q0);
Q = y(:,1);
f = sum((Q-Q_in).^2);
end
%% Function for ODE Integration using equation
function [t,y] = integration(C,R1,R2,time,P,dPdt,Q0)
% For P data
ode_fun = @(t,y) Q_odefcn(t, y, C, R1, R2, time, P, dPdt);
% For P equation:
% ode_fun = @(t,y)((P(t)/(C*R1*R2)) + (dPdt(t)/R1) - ((y(1)*(1 + R1/R2))/C*R1));
[t,y] = ode45(ode_fun, time, Q0);
end
%% Function for ODE using flow tabular data
function dQdt = Q_odefcn(t, y, C, R1, R2, time, P_in, dPdt_in)
% dQdt = zeros(1,1); %Initializing the output vector
% Determine the closest point to the current time
% [d, closestIndex]=min(abs(time-t));
% P = interp1(time,P_in,t);
% for i = 1:numel(time)
% if time(i+1) >= t
% dPdt = (P_in(i+1)-P_in(i))/(time(i+1)-time(i));
% break
% end
% end
%dQ = dQ_in(closestIndex);
dQdt = zeros(1,1); %Initializing the output vector
%Determine the closest point to the current time
[~, closestIndex]=min(abs(time-t));
P = P_in(closestIndex);
dPdt = dPdt_in(closestIndex);
dQdt(1) = P/(C*R1*R2) + (dPdt/R1) - y(1)*(1/C*R1 + 1/C*R2);
end
%% Function for FV PWK
function [t_FV,P_FV] = PWK_FV(C_FV, R1_FV, R2_FV, P_FV_i, Q_FV, timestep, total_time)
t_FV=0:timestep:total_time(end);
P_FV=zeros(numel(t_FV):1);
P_FV(1) = P_FV_i;
for i=2:width(t_FV)
Beta = timestep / (C_FV*R2_FV);
Num1 = Q_FV(i)*( (Beta*R2_FV) + (Beta*R1_FV) + R1_FV );
Num2 = R1_FV*Q_FV(i-1);
Num3 = P_FV(i-1);
Num = Num1 - Num2 + Num3;
Den = 1 + Beta;
P_FV(i) = Num / Den;
end
end
15 Comments
Torsten
on 30 Mar 2024
Edited: Torsten
on 30 Mar 2024
I thought you try to reproduce the pressure or flow curves you supply in the .csv files. Here, pressure converges asymptotically not against 0, but against atmospheric pressure, and that's what your model equations should reflect. Or is there an iterative procedure between MATLAB and CFD ?
In CFD calculations, you often solve the equations for pressure above atmospheric pressure p'. The "real" pressure is then p = p' + p_atmospheric. Maybe you set p' = p_atmospheric when the solver diverges, thus an overpressure of 1.013 bar. But it's only speculation.
Answers (0)
See Also
Categories
Find more on Quadratic Programming and Cone Programming in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!