1

I'm trying to solve differential equation using the ode45 function. Consider the following code,

[t1,X2] = ode45(@(t,x)fun(t,x,C1,C2,C3,C4),t0,X01);

where parameters C1, C2, C3 and C4 are column vectors, which should be available to the function that ode45 is referring to (fun.m). I want the values to change after every iteration, so for example, at the beginning the entry of C1 I want in is C1(1), in the next iteration it's C1(2), etc.

How can I implement that?

Dev-iL
  • 23,742
  • 7
  • 57
  • 99
Gladi
  • 137
  • 2
  • 13
  • What is this "iteration" you speak about? Are you aware that the Dormand-Prince Runge-Kutta scheme is a 7 stage method, that is, using 6+1 function calls per step? (The last function call can be re-used in the nest step.) Are you aware that all Matlab solvers use, unless explicitly stated, variable, adapted step sizes? See my answer in https://stackoverflow.com/questions/56212498/how-to-use-one-value-of-a-matrix-for-each-time-step-inside-ode-solver for a possible solution. – Lutz Lehmann May 20 '19 at 08:13
  • This is possibly an XY problem (as is often the case when you start hacking interna of standard methods), meaning that you are trying to solve Y for your idea of solving X, so only describe Y. However, your idea of solving X might be sub-optimal, a better solution of X might not require Y or require a modified version of Y. Please tell more of the greater picture of problem X. – Lutz Lehmann May 20 '19 at 08:27

1 Answers1

1

You may have noticed that the official docs are not too helpful in this scenario (as they pretty much force you to use global variables - which is doable, but discouraged). Instead, I'll show you how this can be done with classes and function handles. Consider the following:

classdef SimpleQueue < handle
  %SIMPLEQUEUE A simple FIFO data structure.

  properties (Access = private)
    data
    position
  end

  methods (Access = public)
    function obj = SimpleQueue(inputData)
      %SIMPLEQUEUE Construct an instance of this class
      obj.data = inputData;
      rewind(obj);
    end % constructor

    function out = pop(obj, howMany)
      %POP return the next howMany elements.
      if nargin < 2 
        howMany = 1; % default amount of values to return
      end
      finalPosition = obj.position + howMany;
      if finalPosition > numel(obj.data)
        error('Too many elements requested!');
      end      
      out = obj.data(obj.position + 1 : obj.position + howMany);
      obj.position = finalPosition;      
    end % pop

    function [] = rewind(obj)
      %REWIND restarts the element tracking
      % Subsequent calls to pop() shall return elements from the beginning.
      obj.position = 0;
    end % rewind
  end % methods  
end % classdef

How to use this? Simple:

C1q = SimpleQueue(C1);
C2q = SimpleQueue(C2);
C3q = SimpleQueue(C3);
C4q = SimpleQueue(C4);

[t1,X2] = ode45(@(t,x)fun(t,x,@C1q.pop,@C2q.pop,@C3q.pop,@C4q.pop),t0,X01);

As you can see, inside fun we use C1q() instead of C1.

Dev-iL
  • 23,742
  • 7
  • 57
  • 99
  • This probably provides a solution to a problem OP never had. As I understand it (using my crystal ball, or a common sense interpretation of the vague formulation), the constants are fixed on specific time intervals, not changing with every function evaluation. With your solution, the ODE solver will go into random noise generator mode. – Lutz Lehmann May 20 '19 at 08:18
  • @LutzL I agree that the OP requirement is quite strange and it's unclear what they're trying to achieve. However, the OP asked for values to change "after every iteration" which is what happens here... ¯\\_(ツ)_/¯ – Dev-iL May 20 '19 at 08:49
  • With ode45, the constants then change 6 times per "iteration", if that means a time step. It also is not clear from the outset how many time steps there will be for a given time interval, making the result utterly unpredictable (without letting the specific integrator implementation run). – Lutz Lehmann May 20 '19 at 08:53