changeset 23079:17dc6c7ef427

Ignore ODE event function at t==0 for Matlab compatibility (bug #49919). * integrate_adaptive.m: new variable have_EventFcn to make code more readable. * ode_event_handler.m: New persistent variable firstrun. Set to true when called with 'init'. Toggled back to false after one normal invocation. Ignore terminating the ODE integration if it occurs on the first time step.
author Rik <rik@octave.org>
date Sat, 21 Jan 2017 16:19:38 -0800
parents 6f4569690de1
children c56d30ea6cd4
files scripts/ode/private/integrate_adaptive.m scripts/ode/private/ode_event_handler.m
diffstat 2 files changed, 16 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/ode/private/integrate_adaptive.m	Sat Jan 21 16:02:38 2017 -0800
+++ b/scripts/ode/private/integrate_adaptive.m	Sat Jan 21 16:19:38 2017 -0800
@@ -101,7 +101,9 @@
   endif
 
   ## Initialize the EventFcn
+  have_EventFcn = false;
   if (! isempty (options.Events))
+    have_EventFcn  = true;
     ode_event_handler (options.Events, tspan(1), x,
                        "init", options.funarguments{:});
   endif
@@ -162,7 +164,7 @@
 
           ## Call Events function only if a valid result has been found.
           ## Stop integration if eventbreak is true.
-          if (! isempty (options.Events))
+          if (have_EventFcn)
             break_loop = false;
             for idenseout = 1:numel (t_caught)
               id = t_caught(idenseout);
@@ -224,7 +226,7 @@
 
         ## Call Events function only if a valid result has been found.
         ## Stop integration if eventbreak is true.
-        if (! isempty (options.Events))
+        if (have_EventFcn)
           solution.event = ...
             ode_event_handler (options.Events, t(istep), x(:, istep), [],
                                options.funarguments{:});
--- a/scripts/ode/private/ode_event_handler.m	Sat Jan 21 16:02:38 2017 -0800
+++ b/scripts/ode/private/ode_event_handler.m	Sat Jan 21 16:19:38 2017 -0800
@@ -72,6 +72,7 @@
   ## evtcnt  the counter for how often this function has been called
   persistent evtold told yold retcell;
   persistent evtcnt = 1;   # Don't remove.  Required for Octave parser.
+  persistent firstrun = true;
 
   if (isempty (flag))
     ## Process the event, i.e.,
@@ -109,7 +110,12 @@
       ## Create new output values if a valid index has been found
       if (! isempty (idx))
         ## Change the persistent result cell array
-        retcell{1} = any (term(idx));     # Stop integration or not
+        if (firstrun)
+          ## Matlab compatibility requires ignoring condition on first run.
+          retcell{1} = false;
+        else
+          retcell{1} = any (term(idx));     # Stop integration or not
+        endif
         retcell{2}(evtcnt,1) = idx(1,1);  # Take first event found
         ## Calculate the time stamp when the event function returned 0 and
         ## calculate new values for the integration results, we do both by
@@ -122,6 +128,8 @@
       endif
 
     endif
+
+    firstrun = false;
     evtold = evt; told = t; yold = y;
     retval = retcell;
 
@@ -130,6 +138,8 @@
     ## initialize the internal variables of the event function and to get
     ## a value for evtold.
 
+    firstrun = true;
+
     if (! iscell (y))
       inpargs = {evtfun, t, y};
     else
@@ -148,6 +158,7 @@
 
   elseif (strcmp (flag, "done"))
     ## Clear this event handling function
+    firstrun = true;
     evtold = told = yold = evtcnt = [];
     retval = retcell = cell (1,4);