comparison scripts/ode/private/integrate_adaptive.m @ 20584:eb9e2d187ed2

maint: Use Octave coding conventions in scripts/ode/private dir. * AbsRel_Norm.m, fuzzy_compare.m, hermite_quartic_interpolation.m, integrate_adaptive.m, integrate_const.m, integrate_n_steps.m, kahan.m, ode_struct_value_check.m, odepkg_event_handle.m, odepkg_structure_check.m, runge_kutta_45_dorpri.m, starting_stepsize.m: Wrap long lines to < 80 chars. Use double quotes rather than single quotes where possible. Use ';' at end of keywords "return;" and "break;" Use '##" for stand-alone comments and '#' for end-of-line comments. Use two spaces after period before starting new sentence. Use '!' instead of '~' for logical negation. Use specific form of end (endif, endfor, etc.). Don't use line continuation marker '...' unless necessary.
author Rik <rik@octave.org>
date Sun, 04 Oct 2015 22:18:54 -0700
parents 25623ef2ff4f
children b7ac1e94266e
comparison
equal deleted inserted replaced
20583:d746695bf494 20584:eb9e2d187ed2
59 ## 59 ##
60 ## @seealso{integrate_const, integrate_n_steps} 60 ## @seealso{integrate_const, integrate_n_steps}
61 61
62 function solution = integrate_adaptive (stepper, order, func, tspan, x0, options) 62 function solution = integrate_adaptive (stepper, order, func, tspan, x0, options)
63 63
64 solution = struct; 64 solution = struct ();
65 65
66 ## first values for time and solution 66 ## first values for time and solution
67 t = tspan(1); 67 t = tspan(1);
68 x = x0(:); 68 x = x0(:);
69 69
76 if (sign (dt) != vdirection) 76 if (sign (dt) != vdirection)
77 dt = -dt; 77 dt = -dt;
78 endif 78 endif
79 dt = vdirection * min (abs (dt), options.MaxStep); 79 dt = vdirection * min (abs (dt), options.MaxStep);
80 80
81 ## set parameters 81 ## Set parameters
82 k = length (tspan); 82 k = length (tspan);
83 counter = 2; 83 counter = 2;
84 comp = 0.0; 84 comp = 0.0;
85 tk = tspan(1); 85 tk = tspan(1);
86 options.comp = comp; 86 options.comp = comp;
87 87
88 ## factor multiplying the stepsize guess 88 ## Factor multiplying the stepsize guess
89 facmin = 0.8; 89 facmin = 0.8;
90 fac = 0.38^(1/(order+1)); ## formula taken from Hairer 90 fac = 0.38^(1/(order+1)); # formula taken from Hairer
91 t_caught = false; 91 t_caught = false;
92 92
93 93
94 ## Initialize the OutputFcn 94 ## Initialize the OutputFcn
95 if (options.vhaveoutputfunction) 95 if (options.vhaveoutputfunction)
120 k_vals = []; 120 k_vals = [];
121 121
122 while (counter <= k) 122 while (counter <= k)
123 facmax = 1.5; 123 facmax = 1.5;
124 124
125 ## compute integration step from t to t+dt 125 ## Compute integration step from t to t+dt
126 if (isempty (k_vals)) 126 if (isempty (k_vals))
127 [s, y, y_est, new_k_vals] = stepper (func, z(end), u(:,end), 127 [s, y, y_est, new_k_vals] = stepper (func, z(end), u(:,end),
128 dt, options); 128 dt, options);
129 else 129 else
130 [s, y, y_est, new_k_vals] = stepper (func, z(end), u(:,end), 130 [s, y, y_est, new_k_vals] = stepper (func, z(end), u(:,end),
142 endif 142 endif
143 143
144 err = AbsRel_Norm (y(:,end), u(:,end), options.AbsTol, options.RelTol, 144 err = AbsRel_Norm (y(:,end), u(:,end), options.AbsTol, options.RelTol,
145 options.vnormcontrol, y_est(:,end)); 145 options.vnormcontrol, y_est(:,end));
146 146
147 ## solution accepted only if the error is less or equal to 1.0 147 ## Solution accepted only if the error is less or equal to 1.0
148 if (err <= 1) 148 if (err <= 1)
149 149
150 [tk, comp] = kahan (tk, comp, dt); 150 [tk, comp] = kahan (tk, comp, dt);
151 options.comp = comp; 151 options.comp = comp;
152 s(end) = tk; 152 s(end) = tk;
160 if ((z(end) == tspan(counter)) 160 if ((z(end) == tspan(counter))
161 || (abs (z(end) - tspan(counter)) / 161 || (abs (z(end) - tspan(counter)) /
162 (max (abs (z(end)), abs (tspan(counter)))) < 8*eps) ) 162 (max (abs (z(end)), abs (tspan(counter)))) < 8*eps) )
163 counter++; 163 counter++;
164 164
165 ## if there is an element in time vector at which the solution is required 165 ## if there is an element in time vector at which the solution is
166 ## the program must compute this solution before going on with next steps 166 ## required the program must compute this solution before going on with
167 ## next steps
167 elseif (vdirection * z(end) > vdirection * tspan(counter)) 168 elseif (vdirection * z(end) > vdirection * tspan(counter))
168 169
169 ## initialize counter for the following cycle 170 ## initialize counter for the following cycle
170 i = 2; 171 i = 2;
171 while (i <= length (z)) 172 while (i <= length (z))
231 ## f_half = feval (func, t+1/2*dt, u_half, 232 ## f_half = feval (func, t+1/2*dt, u_half,
232 ## options.vfunarguments{:}); 233 ## options.vfunarguments{:});
233 ## u_interp = 234 ## u_interp =
234 ## hermite_quintic_interpolation ([z(i-1) z(i)], 235 ## hermite_quintic_interpolation ([z(i-1) z(i)],
235 ## [u(:,i-1) u_half u(:,i)], 236 ## [u(:,i-1) u_half u(:,i)],
236 ## [k_vals(:,1) f_half k_vals(:,end)], 237 ## [k_vals(:,1) f_half ...
238 ## k_vals(:,end)],
237 ## tspan(counter)); 239 ## tspan(counter));
238 otherwise 240 otherwise
239 warning ("High order interpolation not yet implemented: ", 241 warning ("High order interpolation not yet implemented: ",
240 "using cubic iterpolation instead"); 242 "using cubic interpolation instead");
241 der(:,1) = feval (func, z(i-1) , u(:,i-1), 243 der(:,1) = feval (func, z(i-1) , u(:,i-1),
242 options.vfunarguments{:}); 244 options.vfunarguments{:});
243 der(:,2) = feval (func, z(i) , u(:,i), 245 der(:,2) = feval (func, z(i) , u(:,i),
244 options.vfunarguments{:}); 246 options.vfunarguments{:});
245 u_interp = ... 247 u_interp = ...
279 endif 281 endif
280 solution.vcntloop = solution.vcntloop + 1; 282 solution.vcntloop = solution.vcntloop + 1;
281 vcntiter = 0; 283 vcntiter = 0;
282 284
283 ## Call plot only if a valid result has been found, therefore this 285 ## Call plot only if a valid result has been found, therefore this
284 ## code fragment has moved here. Stop integration if plot function 286 ## code fragment has moved here. Stop integration if plot function
285 ## returns false 287 ## returns false
286 if (options.vhaveoutputfunction) 288 if (options.vhaveoutputfunction)
287 for vcnt = 0:options.Refine # Approximation between told and t 289 for vcnt = 0:options.Refine # Approximation between told and t
288 if (options.vhaverefine) # Do interpolation 290 if (options.vhaverefine) # Do interpolation
289 vapproxtime = (vcnt + 1) / (options.Refine + 2); 291 vapproxtime = (vcnt + 1) / (options.Refine + 2);
298 vapproxvals = vapproxvals(options.OutputSel); 300 vapproxvals = vapproxvals(options.OutputSel);
299 endif 301 endif
300 vpltret = feval (options.OutputFcn, vapproxtime, 302 vpltret = feval (options.OutputFcn, vapproxtime,
301 vapproxvals, [], options.vfunarguments{:}); 303 vapproxvals, [], options.vfunarguments{:});
302 if (vpltret) # Leave refinement loop 304 if (vpltret) # Leave refinement loop
303 break 305 break;
304 endif 306 endif
305 endfor 307 endfor
306 if (vpltret) # Leave main loop 308 if (vpltret) # Leave main loop
307 solution.vunhandledtermination = false; 309 solution.vunhandledtermination = false;
308 break 310 break;
309 endif 311 endif
310 endif 312 endif
311 313
312 ## Call event only if a valid result has been found, therefore this 314 ## Call event only if a valid result has been found, therefore this
313 ## code fragment has moved here. Stop integration if veventbreak is 315 ## code fragment has moved here. Stop integration if veventbreak is
314 ## true 316 ## true
315 if (options.vhaveeventfunction) 317 if (options.vhaveeventfunction)
316 solution.vevent = odepkg_event_handle (options.Events, t(end), 318 solution.vevent = odepkg_event_handle (options.Events, t(end),
317 x(:,end), [], options.vfunarguments{:}); 319 x(:,end), [],
320 options.vfunarguments{:});
318 if (! isempty (solution.vevent{1}) 321 if (! isempty (solution.vevent{1})
319 && solution.vevent{1} == 1) 322 && solution.vevent{1} == 1)
320 t(solution.vcntloop-1,:) = solution.vevent{3}(end,:); 323 t(solution.vcntloop-1,:) = solution.vevent{3}(end,:);
321 x(:,solution.vcntloop-1) = solution.vevent{4}(end,:)'; 324 x(:,solution.vcntloop-1) = solution.vevent{4}(end,:)';
322 solution.vunhandledtermination = false; 325 solution.vunhandledtermination = false;
323 break 326 break;
324 endif 327 endif
325 endif 328 endif
326 329
327 else 330 else
328 331
335 dt = dt * min (facmax, 338 dt = dt * min (facmax,
336 max (facmin, fac * (1 / err)^(1 / (order + 1)))); 339 max (facmin, fac * (1 / err)^(1 / (order + 1))));
337 dt = vdirection * min (abs (dt), options.MaxStep); 340 dt = vdirection * min (abs (dt), options.MaxStep);
338 341
339 ## Update counters that count the number of iteration cycles 342 ## Update counters that count the number of iteration cycles
340 solution.vcntcycles = solution.vcntcycles + 1; # Needed for cost statistics 343 solution.vcntcycles += 1; # Needed for cost statistics
341 vcntiter = vcntiter + 1; # Needed to find iteration problems 344 vcntiter += 1; # Needed to find iteration problems
342 345
343 ## Stop solving because in the last 1000 steps no successful valid 346 ## Stop solving because in the last 1000 steps no successful valid
344 ## value has been found 347 ## value has been found
345 if (vcntiter >= 5000) 348 if (vcntiter >= 5000)
346 error (["Solving has not been successful. The iterative", 349 error (["Solving has not been successful. The iterative",
347 " integration loop exited at time t = %f before endpoint at", 350 " integration loop exited at time t = %f before endpoint at",
348 " tend = %f was reached. This happened because the iterative", 351 " tend = %f was reached. This happened because the iterative",
349 " integration loop does not find a valid solution at this time", 352 " integration loop does not find a valid solution at this time",
350 " stamp. Try to reduce the value of ''InitialStep'' and/or", 353 " stamp. Try to reduce the value of 'InitialStep' and/or",
351 " ''MaxStep'' with the command ''odeset''.\n"], 354 " 'MaxStep' with the command 'odeset'.\n"],
352 s(end), tspan(end)); 355 s(end), tspan(end));
353 endif 356 endif
354 357
355 ## if this is the last iteration, save the length of last interval 358 ## if this is the last iteration, save the length of last interval
356 if (counter > k) 359 if (counter > k)
360 363
361 ## Check if integration of the ode has been successful 364 ## Check if integration of the ode has been successful
362 if (vdirection * z(end) < vdirection * tspan(end)) 365 if (vdirection * z(end) < vdirection * tspan(end))
363 if (solution.vunhandledtermination == true) 366 if (solution.vunhandledtermination == true)
364 error ("OdePkg:InvalidArgument", 367 error ("OdePkg:InvalidArgument",
365 ["Solving has not been successful. The iterative", 368 ["Solving has not been successful. The iterative",
366 " integration loop exited at time t = %f", 369 " integration loop exited at time t = %f",
367 " before endpoint at tend = %f was reached. This may", 370 " before endpoint at tend = %f was reached. This may",
368 " happen if the stepsize grows smaller than defined in", 371 " happen if the stepsize grows smaller than defined in",
369 " vminstepsize. Try to reduce the value of ''InitialStep''", 372 " vminstepsize. Try to reduce the value of 'InitialStep'",
370 " and/or ''MaxStep'' with the command ''odeset''.\n"], 373 " and/or 'MaxStep' with the command 'odeset'.\n"],
371 z(end), tspan(end)); 374 z(end), tspan(end));
372 else 375 else
373 warning ("OdePkg:InvalidArgument", 376 warning ("OdePkg:InvalidArgument",
374 ["Solver has been stopped by a call of ''break'' in the main", 377 ["Solver has been stopped by a call of 'break' in the main",
375 " iteration loop at time t = %f before endpoint at tend = %f ", 378 " iteration loop at time t = %f before endpoint at tend = %f ",
376 " was reached. This may happen because the @odeplot function", 379 " was reached. This may happen because the @odeplot function",
377 " returned ''true'' or the @event function returned", 380 " returned 'true' or the @event function returned",
378 " ''true''.\n"], 381 " 'true'.\n"],
379 z(end), tspan(end)); 382 z(end), tspan(end));
380 endif 383 endif
381 endif 384 endif
382 385
383 ## Compute how many values are out of time inerval 386 ## Compute how many values are out of time inerval
387 ## Remove not-requested values of time and solution 390 ## Remove not-requested values of time and solution
388 solution.t = t(1:end-f); 391 solution.t = t(1:end-f);
389 solution.x = x(:,1:end-f)'; 392 solution.x = x(:,1:end-f)';
390 393
391 endfunction 394 endfunction
395