1
votes

I hope I am on topic here. I'm asking here since it said on the faq page: a question concerning (among others) a software algorithm :) So here it goes:

I need to solve a system of ODEs (like $ \dot x = A(t) x$. The Matrix A may change and is given as a string in the function call (Calc_EDS_v2('Sys_EDS_a',...)
Then I'm using ode45 in a loop to find my x:

function [intervals, testing] = EDS_calc_v2(smA,options,debug)  
[..]
for t=t_start:t_step:t_end)
    [Te,Qe]=func_int(@intQ_2_v2,[t,t+t_step],q);
    q=Qe(end,:);
    [..]
end
[..]

with func_int being ode45 and @intQ_2_v2 my m-file. q is given back to the call as the starting vector. As you can see I'm just using ode45 on the intervall [t, t+t_step]. That's because my system matrix A can force ode45 to use a lot of steps, leading it to hit the AbsTol or RelTol very fast.

Now my A is something like B(t)*Q(t), so in the m-file intQ_2_v2.m I need to evaluate both B and Q at the times t. I first done it like so: (v1 -file, so function name is different)

function q=intQ_2_v1(t,X)  
[..] 
B(1)=...; ...   B(4)=...;
Q(1)=...; ...

than that is naturally only with the assumption that A is a 2x2 matrix. With that setup it took a basic system somewhere between 10 and 15 seconds to compute.

Instead of the above I now use the files B1.m to B4.m and Q1.m to B4.m (I know that that's not elegant, but I need to use quadgk on B later and quadgk doesn't support matrix functions.)

function q=intQ_2_v2(t,X)  
[..]
global funcnameQ, funcnameB, d
for k=1:d
Q(k)=feval(str2func([funcnameQ,int2str(k)]),t);
B(k)=feval(str2func([funcnameB,int2str(k)]),t);
end
[..]

funcname (string) referring to B or Q (with added k) and d is dimension of the system.

Now I knew that it would cost me more time than the first version but I'm seeing the computing times are ten times as high! (getting 150 to 160 seconds) I do understand that opening 4 files and evaluate roughly 40 times per ode-loop is costly... and I also can't pre-evalute B and Q, since ode45 uses adaptive step sizes...

Is there a way to not use that last loop?

Mostly I'm interested in a solution to drive down the computing times. I do have a feeling that I'm missing something... but can't really put my finger on it. With that one taking nearly three minutes instead of 10 seconds I can get a coffee in between each testrun now... (plz don't tell me to get a faster computer)

(sorry for such a long question )

1

1 Answers

1
votes

I'm not sure that I fully understand what you're doing here, but I can offer a few tips.

  1. Use the profiler, it will help you understand exactly where the bottlenecks are.

  2. Using feval is slower than using function handles directly, especially when using str2func to build the handle each time. There is also a slowdown from using the global variables (and it's a good habit to avoid these unless absolutely necessary). Each of these really adds up when using them repeatedly (as it looks like here). Store function handles to each of your mfiles in a cell array and either pass them directly to the function or use nested function for the optimization so that the cell array of handles is visible to the function being optimized. Personally, I prefer the nested method, but passing is better if you will use those mfiles elsewhere.

I expect this will get your runtime back to close to what the first method gave. Be sure to tell us if this was the problem or if you found another solution.