diff scripts/ode/private/integrate_adaptive.m @ 20575:3339c9bdfe6a

Activate FSAL property in dorpri timestepper * scripts/ode/private/runge_kutta_45_dorpri.m: don't compute first stage if values from previous iteration are passed. * scripts/ode/private/integrate_adaptive.m: do not update cmputed stages if timestep is rejected.
author Carlo de Falco <carlo.defalco@polimi.it>
date Sat, 03 Oct 2015 07:32:50 +0200
parents 6256f6e366ac
children 25623ef2ff4f
line wrap: on
line diff
--- a/scripts/ode/private/integrate_adaptive.m	Fri Oct 02 15:07:37 2015 -0400
+++ b/scripts/ode/private/integrate_adaptive.m	Sat Oct 03 07:32:50 2015 +0200
@@ -69,7 +69,7 @@
   ## first values for time and solution
   t = tspan(1);
   x = x0(:);
-
+  
   ## get first initial timestep
   dt = odeget (options, "InitialStep",
                starting_stepsize (order, func, t, x, options.AbsTol,
@@ -120,15 +120,20 @@
   z = t;
   u = x;
 
-  k_vals = feval (func, t , x, options.vfunarguments{:});
-
+  k_vals = []; 
+  
   while (counter <= k)
     facmax = 1.5;
 
     ## compute integration step from t to t+dt
-    [s, y, y_est, k_vals] = stepper (func, z(end), u(:,end),
-                                     dt, options, k_vals);
-
+    if (isempty (k_vals))
+      [s, y, y_est, new_k_vals] = stepper (func, z(end), u(:,end),
+                                           dt, options);
+    else
+      [s, y, y_est, new_k_vals] = stepper (func, z(end), u(:,end),
+                                           dt, options, k_vals);
+    endif
+    
     if (options.vhavenonnegative)
       x(options.NonNegative,end) = abs (x(options.NonNegative,end));
       y(options.NonNegative,end) = abs (y(options.NonNegative,end));
@@ -141,27 +146,29 @@
 
     err = AbsRel_Norm (y(:,end), u(:,end), options.AbsTol, options.RelTol,
                        options.vnormcontrol, y_est(:,end));
-
+    
     ## solution accepted only if the error is less or equal to 1.0
     if (err <= 1)
-
+      
       [tk, comp] = kahan (tk, comp, dt);
       options.comp = comp;
       s(end) = tk;
 
       ## values on this interval for time and solution
-      z = [z(end);s];
-      u = [u(:,end),y];
-
+      z = [z(end); s];
+      u = [u(:,end), y];
+      k_vals = new_k_vals;
+      
       ## if next tspan value is caught, update counter
       if ((z(end) == tspan(counter))
           || (abs (z(end) - tspan(counter)) /
               (max (abs (z(end)), abs (tspan(counter)))) < 8*eps) )
         counter++;
-  
-      ## if there is an element in time vector at which the solution is required
-      ## the program must compute this solution before going on with next steps
+        
+        ## if there is an element in time vector at which the solution is required
+        ## the program must compute this solution before going on with next steps
       elseif (vdirection * z(end) > vdirection * tspan(counter))
+
         ## initialize counter for the following cycle
         i = 2;
         while (i <= length (z))
@@ -179,9 +186,9 @@
             ## choose interpolation scheme according to order of the solver
             switch order
               case 1
-               u_interp = linear_interpolation ([z(i-1) z(i)],
-                                                [u(:,i-1) u(:,i)],
-                                                tspan(counter));
+                u_interp = linear_interpolation ([z(i-1) z(i)],
+                                                 [u(:,i-1) u(:,i)],
+                                                 tspan(counter));
               case 2
                 if (! isempty (k_vals))
                   der = k_vals(:,1);
@@ -194,10 +201,10 @@
                                                     der, tspan(counter));
               case 3
                 u_interp = ...
-                  hermite_cubic_interpolation ([z(i-1) z(i)],
-                                               [u(:,i-1) u(:,i)],
-                                               [k_vals(:,1) k_vals(:,end)],
-                                               tspan(counter));
+                hermite_cubic_interpolation ([z(i-1) z(i)],
+                                             [u(:,i-1) u(:,i)],
+                                             [k_vals(:,1) k_vals(:,end)],
+                                             tspan(counter));
               case 4
                 ## if ode45 is used without local extrapolation this function
                 ## doesn't require a new function evaluation.
@@ -217,10 +224,10 @@
                                    - (1776094331/19743644256) * k_vals(:,6)
                                    + (11237099/235043384) * k_vals(:,7));
                 u_interp = ...
-                  hermite_quartic_interpolation ([z(i-1) z(i)],
-                                                 [u(:,i-1) u_half u(:,i)],
-                                                 [k_vals(:,1) k_vals(:,end)],
-                                                 tspan(counter));
+                hermite_quartic_interpolation ([z(i-1) z(i)],
+                                               [u(:,i-1) u_half u(:,i)],
+                                               [k_vals(:,1) k_vals(:,end)],
+                                               tspan(counter));
 
                 ## it is also possible to do a new function evaluation and use
                 ## the quintic hermite interpolator
@@ -239,16 +246,16 @@
                 der(:,2) = feval (func, z(i) , u(:,i),
                                   options.vfunarguments{:});
                 u_interp = ...
-                  hermite_cubic_interpolation ([z(i-1) z(i)],
-                                               [u(:,i-1) u(:,i)],
-                                               der, tspan(counter));
+                hermite_cubic_interpolation ([z(i-1) z(i)],
+                                             [u(:,i-1) u(:,i)],
+                                             der, tspan(counter));
             endswitch
 
             ## add the interpolated value of the solution
             u = [u(:,1:i-1), u_interp, u(:,i:end)];
             
             ## add the time requested
-            z = [z(1:i-1);tspan(counter);z(i:end)];
+            z = [z(1:i-1); tspan(counter); z(i:end)];
 
             ## update counters
             counter++;
@@ -310,7 +317,7 @@
       ## true
       if (options.vhaveeventfunction)
         solution.vevent = odepkg_event_handle (options.Events, t(end),
-            x(:,end), [], options.vfunarguments{:});
+                                               x(:,end), [], options.vfunarguments{:});
         if (! isempty (solution.vevent{1})
             && solution.vevent{1} == 1)
           t(solution.vcntloop-1,:) = solution.vevent{3}(end,:);
@@ -321,13 +328,15 @@
       endif
       
     else
+      
       facmax = 1.0;
+      
     endif
     
     ## Compute next timestep, formula taken from Hairer
     err += eps;    # adding an eps to avoid divisions by zero
-    dt = dt * min (facmax, max (facmin,
-                                fac * (1 / err)^(1 / (order + 1))));
+    dt = dt * min (facmax,
+                   max (facmin, fac * (1 / err)^(1 / (order + 1))));
     dt = vdirection * min (abs (dt), options.MaxStep);
     
     ## Update counters that count the number of iteration cycles
@@ -383,7 +392,3 @@
   solution.x = x(:,1:end-f)';
   
 endfunction
-
-## Local Variables: ***
-## mode: octave ***
-## End: ***