Changing numeric variables based on symbolic variables in a set of differential equations.
16 views (last 30 days)
Show older comments
Hannah Goldblatt
on 18 Sep 2023
Commented: Star Strider
on 20 Sep 2023
I am implementing a mathematical model of the cardiovascular system based on a paper by Burkhoff and Tyberg.
Below is my code, with screenshots of the equations in the paper that I am attempting to represent. Any variable that is not symbolic is a constant parameter that is set at the start of the code (not shown).
%create symbols
syms V_lv(t) V_rv(t) V_C_as(t) V_C_vs(t) V_C_ap(t) V_C_vp(t) e(t)
tAll = [];
yAll = [];
tPool = [0 2*T_es T]; % time periods in the cardiac cycle
yInit = [12 16 32 23 40 50]; % initial conditions (volumes)
%initialise ejection/filling coefficients
alpha_rv = 0;
alpha_lv = 1;
beta_rv = 0;
beta_lv = 1;
for k = 1:numel(tPool) - 1
%ventricles (time varying elastance)
P_es_lv = E_es_lv*(V_lv - V_0); % LV ESPVR
P_ed_lv = A*(exp(B_lv*(V_lv - V_0)) - 1); % LV EDPVR
P_es_rv = E_es_rv*(V_rv - V_0); % RV ESPVR
P_ed_rv = A*(exp(B_rv*(V_rv - V_0)) - 1); %RV EDPVR
switch k
case 1
e = 0.5*(1-cos(2*pi*t/T_es));
case 2
e = 0;
case 3
e = 0;
end
P_lv = (P_es_lv - P_ed_lv)*e + P_ed_lv; %left ventricular pressure
P_rv = (P_es_rv - P_ed_rv)*e + P_ed_rv; %right ventricular pressure
The above code represents this section (except that I have implemented a simpler version of the piecewise e(t) function:

%systemic and pulmonary circulation
P_C_as = V_C_as/C_as; % systemic arteries
P_C_vs = V_C_vs/C_vs; % systemic veins
P_C_ap = V_C_ap/C_ap; % pulmonary arteries
P_C_vp = V_C_vp/C_vp; % pulmonary veins
The above code represents this section:

%blood volume
V_T = V_C_as + V_C_vs + V_C_ap + V_C_vp + V_U + V_lv + V_rv;
%differential equations
ode1 = diff(V_lv) == ((P_C_vp - P_lv)/R_vp)*alpha_lv - ((P_lv - P_C_as)/R_cs)*beta_lv;
ode2 = diff(V_rv) == ((P_C_vs - P_rv)/R_vp)*alpha_rv - ((P_rv - P_C_ap)/R_cp)*beta_rv;
ode3 = diff(V_C_as) == ((P_lv - P_C_as)/R_cs)*beta_lv - ((P_C_as - P_C_vs)/R_as);
ode4 = diff(V_C_vs) == ((P_C_as - P_C_vs)/R_as) - ((P_C_vs - P_rv)/R_vs)*alpha_rv;
ode5 = diff(V_C_ap) == ((P_rv - P_C_ap)/R_cp)*beta_rv - ((P_C_ap - P_C_vp)/R_ap);
ode6 = diff(V_C_vp) == ((P_C_ap - P_C_vp)/R_ap) - ((P_C_vp - P_lv)/R_vp)*alpha_lv;
odes = [ode1; ode2; ode3; ode4; ode5; ode6];
[VF, Sbs] = odeToVectorField(odes);
%solve numerically
M = matlabFunction(VF,'vars',{'t','Y'});
[T, Y] = ode45(M, [tPool(k:k+1)], yInit);
tAll = cat(1, tAll, T); % Append new solution to total solution
yAll = cat(1, yAll, Y);
yInit = Y(end, :); % Update the initial value
The above code represents this section:

%set ejection/filling coefficients
end
plot(tAll, yAll)
As seen in equations A11 to A16, there are four coefficients that are set to either 1 or 0 depending on whether ventricular ejection or filling is occuring:

I know that I can't compare these pressure values directly as they are symbolic. I have tried using subs, but that only works for the pressures that don't contain time-varying terms. For example:
test1 = subs(P_lv, V_lv, Y(end, 1))
test2 = subs(P_C_vp, V_C_vp, Y(end, 6))

test1 can be converted into a double, but test2 can't.
I implemented the piecewise e(t) function based on an answer from this post, but I can't figure out how to change the values of alpha and beta at each t value based on logical comparisons of symbolic variables.
Any help is appreciated.
0 Comments
Accepted Answer
Star Strider
on 18 Sep 2023
test1 = vpa(subs(P_lv, V_lv, Y(end, 1)), 8)
test2 = vpa(subs(P_C_vp, V_C_vp, Y(end, 6)), 8)
however something is missing here, so I cannot run the code —
%create symbols
syms V_lv(t) V_rv(t) V_C_as(t) V_C_vs(t) V_C_ap(t) V_C_vp(t) e(t)
tAll = [];
yAll = [];
tPool = [0 2*T_es T]; % time periods in the cardiac cycle
yInit = [12 16 32 23 40 50]; % initial conditions (volumes)
%initialise ejection/filling coefficients
alpha_rv = 0;
alpha_lv = 1;
beta_rv = 0;
beta_lv = 1;
for k = 1:numel(tPool) - 1
%ventricles (time varying elastance)
P_es_lv = E_es_lv*(V_lv - V_0); % LV ESPVR
P_ed_lv = A*(exp(B_lv*(V_lv - V_0)) - 1); % LV EDPVR
P_es_rv = E_es_rv*(V_rv - V_0); % RV ESPVR
P_ed_rv = A*(exp(B_rv*(V_rv - V_0)) - 1); %RV EDPVR
switch k
case 1
e = 0.5*(1-cos(2*pi*t/T_es));
case 2
e = 0;
case 3
e = 0;
end
P_lv = (P_es_lv - P_ed_lv)*e + P_ed_lv; %left ventricular pressure
P_rv = (P_es_rv - P_ed_rv)*e + P_ed_rv; %right ventricular pressure
%set ejection/filling coefficients
end
plot(tAll, yAll)
test1 = vpa(subs(P_lv, V_lv, Y(end, 1)), 8)
test2 = vpa(subs(P_C_vp, V_C_vp, Y(end, 6)), 8)
.
8 Comments
Star Strider
on 20 Sep 2023
Thank you!
I’m interestied in physiological models. I wasn’t aware of this one.
More Answers (0)
See Also
Categories
Find more on Cardiology in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!




