matlabparametersiterationanonymous-functionode45

Passing additional iteration-dependent inputs to ode45


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?


Solution

  • 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.