# Simulate ODE models described in Excel

15 views (last 30 days)
Robert Gregg on 12 Sep 2017
Answered: Rajesh Balagam on 14 Sep 2017
I have an ODE system described in an Excel spreadsheet, and I want to simulate it with Matlab. The attached spreadsheet has an example set up and runs fine with the code below:
function Solver
%Import and format data (xlsread or whatever)
%End up with the following variables:
Rates = {'k1f*A' , 'k2f*B - k2r*C'};
Constants = struct('k1f',1,'k2f',2,'k2r',0.5);
Rate_Matrix = [-1 0 ; 1 -1; 0 1];
Initial = {'A',1;'B',2;'C',3};
%The method of storing the information is somewhat arbitrary
%Begin Setting up the ODE solver
%Time Span to run simulation
t0 = [0, 10];
%Species being solved for
Species = Initial(:,1);
%Initial Amounts
x0 = [Initial{:,2}];
%Run the simulation, passing additional needed variables
[t,x]=ode45(@Model,t0,x0,[],Rates,Constants,Rate_Matrix);
%plot the results
plot(t,x)
legend(Species)
function dx = Model(t,x,Rates,Constants,Rate_Matrix)
%Unpack species vector and Constants
A = x(1);
B = x(2);
C = x(3);
k1f = Constants.k1f;
k2f = Constants.k2f;
k2r = Constants.k2r;
%Evaluate Rates at current values
rates = cellfun(@eval,Rates);
%Calculate the change in each species
dx = Rate_Matrix * rates';
end
end
The code works, but I don't want to have to hard-code anything into the solver/Model function like "k1f = Constants.k1f;" because the excel file might change. I might add another rate equation or change a constant value. I also would like to avoid using the cellfun(@eval,...) construct because it's slow and not recommended for use.
I've been having a lot of trouble with static work-spaces and passing variables through the ODE function, so any help would be appreciated.

Rajesh Balagam on 14 Sep 2017
You can create all the rate constants from Excel sheet as shown below.
[~,~,raw] = xlsread('Model_Summary.xls','Rates','C3:D5') % remove empty rows in Excel sheet
for i = 1:size(raw,1)
eval(sprintf('%s = %d',raw{i,1},raw{i,2}));
end
or create a structure dynamically as below
for i=1:size(raw,1)
const.(raw{i,1}) = raw{i,2};
end
For alternative approaches to "eval" you can look at the following documentation page.
However, here rate expressions are interpreted as strings from Excel, we cannot eliminate usage of eval.
You can use eval function once, to create rate expressions as function handles and pass the cell array of function handles to the Model function
rate_expr{2} = eval(sprintf('@(k1f, k2f, k2r, A, B, C) %s', 'k2f*B - k2r*C')) % rate expression comes from Excel sheet
But you need to pass all the variables as parameters to each function handle as we do not know which parameters being used in the rate expression.