ODEs across a series of rows
2 次查看(过去 30 天)
显示 更早的评论
Hey, so I'm trying to integrate across a series of rows. Currently, my code spits out an array (Cu_int{1,1}) that has a conditional variable among it. This one graphs perfectly.
However, subsequent arrays (Cu_int{1,2} and (Cu_int{1,3})), do not. Cu_int{1,2} is dependent on the second column of Cu_int{1,1} as the initial value of C_in, that is: Cu_int{1,1}(1,2) = Cu_in for (k1 = 2), which gives a value of Cu_int{1,2}(1,2), which is = Cu_in for (k1 = 3), giving Cu_int{1,3}(1,2).
Thus, Cu_int{1,1}(2,2) to calculate for Cu_int{1,2}(2,2) to calculate for Cu_int{1,3}(2,2).
Sorry for the poor explanation, but I can't seem to wrap my head around getting this loop to work.
Thanks!
clearvars;
close all;
Funderin = [1.7153, 1.052, 0.7085];
Funderout = [1.052, 0.7085, 0.4813];
Fsep = [0.6633, 0.3435, 0.2272];
MassUnders = [14.73, 9.918, 6.738];
StartTime = 0
TimeStep = 0.1
InjectionTime = 3
FinalTime = 50
%tv = linspace(0, 3); %time vector
tv = StartTime:TimeStep:InjectionTime;
Cu_in = 0.9717 %tracer flow rate kgTr/s
Cui = 0; %initial concentration
Cu_int = [];
rhs = @(t,Cu,Cu_in,Fin,Fout,Fsp,MassU) (Fin* Cu_in - Fout*Cu - Fsp*Cu)/MassU; %creates "call" function for ode
for k1 = 1:1
%Start first half of the integration (inlets)
%Cu_int{k1} = []; %this creates the array?
tspan = tv;
[t,Cu] = ode45( @(t,Cu) rhs(t,Cu,Cu_in,Funderin(k1),Funderout(k1),Fsep(k1),MassUnders(k1)), tspan, Cui);
%Start second half of the integration (outlets)
Cu_int{k1} = [t, Cu];
Cu_in = 0;
Cui = Cu(end); %Cuin uses conc from last
%tspan = tv + t(end);
tspan = (InjectionTime + TimeStep):TimeStep:FinalTime
[t,Cu] = ode45( @(t,Cu) rhs(t,Cu,Cu_in,Funderin(k1),Funderout(k1),Fsep(k1),MassUnders(k1)), tspan, Cui);
Cui = 0;
Cu_in = Cu(end); % ‘Cu_in’ Assignment ?
Cu_int{k1} = [Cu_int{k1}; t, Cu];
end
for k1 = 2:length(Funderin)
tspan = StartTime:TimeStep:FinalTime;
[t, Cu] = ode45( @(t,Cu) rhs(t,Cu,Cu_in,Funderin(k1),Funderout(k1),Fsep(k1),MassUnders(k1)), tspan, Cui);
for p = 1:(size(Cu_int{1,1},1))
Cu_in = Cu_int{1,k1-1}(p,2);
end
Cu_int{k1} = [t, Cu]; %this creates the array
end
figure(1)
plot(Cu_int{1}(:,1),Cu_int{1}(:,2));
hold on
for k1 = 2:length(Funderin)
plot(Cu_int{k1}(:,1),Cu_int{k1}(:,2));
end
hold off
xlabel('Time'); ylabel('Cu');
回答(1 个)
Star Strider
2016-9-8
Lose the loop! You have a system of ordinary differential equations, so you have to solve them as that system. This is easy with ode45.
This is as close as I can get to your desired solution:
Funderin = [1.7153, 1, 0.5];
Funderout = [1, 0.5, 0.2];
Fsep = [0.9406, 0.2, 0.1];
MassUnders = [12.0069, 8, 5];
tspan = linspace(0, 50, 250);
t = 0;
Cu_in = 0.9717 %tracer flow
Cui = 0; %initial concentration
rhs = @(t,Cu,Cu_in,Fin,Fout,Fsp,MassU) [(Fin(1)*Cu(1)/MassU(1) - Fout(1)*Cu(1) - Fsp(1)*Cu(1))/MassU(1); (Fin(2)*Cu(1) - Fout(2)*Cu(2) - Fsp(2)*Cu(2))/MassU(2); (Fin(3)*Cu(2) - Fout(3)*Cu(3) - Fsp(3)*Cu(3))/MassU(3)];
[t,Cu] = ode45( @(t,Cu) rhs(t,Cu,Cu_in,Funderin,Funderout,Fsep,MassUnders), tspan, [Cu_in; 0; 0]);
figure(1)
plot(t, Cu)
grid
xlabel('Time (\mus)')
ylabel('[C_u] (n\itM\rm)')
legend('Compartment #1', 'Compartment #2', 'Compartment #3', 'Location','NE')
It’s missing the initial concentration ‘step’, since I modeled it as a ‘delta’ function instead of a step for convenience. I will defer to you to modeling the step and getting the concentrations to agree with those in your other simulation. Consider adding an initial compartment to model the initial step.
The plot:

This should get you started.
I’ve done compartmental kinetics, specifically with respect to drug and hormone concentration simulations in pharmacokinetic models, but not exactly what you’re doing.
2 个评论
Star Strider
2016-9-8
Thank you.
You can do this with a loop, however the loop must be within the ‘rhs’ function. You would have to create a function file to do that, since an anonymous function would only allow the sort of system I used here. A system of 300 ODEs would create an enormous anonymous function.
Each iteration of the loop (one iteration for each ‘tank’ ODE) would correspond to a row of my anonymous function. An easy way to do this would be to use a single anonymous function and then call it in each loop iteration with new constants and the concentrations from the previous calculation. I would set up a different ODE function for the first compartment (since it has to incorporate the tracer injection dynamics), and then use an if block to use it in the first iteration and skip over it in subsequent iterations. This would set up the system of ODEs you need to use to simulate the dynamics of your connected tanks. Your initial conditions vector would have to match the number of compartments you’re modeling, so use the zeros function for all but the first tank.
Yours could easily become a ‘stiff’ system, so using ode15s or one of the other ‘stiff’ solvers would likely work better than ode45.
Your project reminds me of compartmental modeling, although in compartmental modeling the equations are usually set up differently because the dynamics are different.
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Ordinary Differential Equations 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!


