1 while ~done
2
3 hmin = 16*eps(t);
4 absh = min(hmax, max(hmin, absh));
5 if absh == hmin
6 if at_hmin
7 absh = abshlast; % required by stepsize recovery
8 end
9 at_hmin = true;
10 else
11 at_hmin = false;
12 end
13 h = tdir * absh;
14
15 % Stretch the step if within 10% of tfinal-t.
16 if 1.1*absh >= abs(tfinal - t)
17 h = tfinal - t;
18 absh = abs(h);
19 done = true;
20 end
21
22 if (absh ~= abshlast) || (k ~= klast)
23 difRU = cumprod((kI - 1 - kJ*(absh/abshlast)) ./ kI) * difU;
24 dif(:,K) = dif(:,K) * difRU(K,K);
25
26 hinvGak = h * invGa(k);
27 nconhk = 0;
28 Miter = Mt - hinvGak * dfdy;
29 if Mtype == 4
30 Miter = Miter + dMpsidy;
31 end
32 if DAE
33 RowScale = 1 ./ max(abs(Miter),[],2);
34 Miter = sparse(one2neq,one2neq,RowScale) * Miter;
35 end
36 if issparse(Miter)
37 [L,U,P,Q,R] = lu(Miter);
38 else
39 [L,U,p] = lu(Miter,'vector');
40 end
41 ndecomps = ndecomps + 1;
42 havrate = false;
43 end
44
45 % LOOP FOR ADVANCING ONE STEP.
46 nofailed = true; % no failed attempts
47 while true % Evaluate the formula.
48
49 gotynew = false; % is ynew evaluated yet?
50 while ~gotynew
51
52 % Compute the constant terms in the equation for ynew.
53 psi = dif(:,K) * (G(K) * invGa(k));
54
55 % Predict a solution at t+h.
56 tnew = t + h;
57 if done
58 tnew = tfinal; % Hit end point exactly.
59 end
60 h = tnew - t; % Purify h.
61 pred = y + sum(dif(:,K),2);
62 ynew = pred;
63
64 % The difference, difkp1, between pred and the final accepted
65 % ynew is equal to the backward difference of ynew of order
66 % k+1. Initialize to zero for the iteration to compute ynew.
67 difkp1 = zeros(neq,1);
68 if normcontrol
69 normynew = norm(ynew);
70 invwt = 1 / max(max(normy,normynew),threshold);
71 minnrm = 100*eps*(normynew * invwt);
72 else
73 invwt = 1 ./ max(max(abs(y),abs(ynew)),threshold);
74 minnrm = 100*eps*norm(ynew .* invwt,inf);
75 end
76
77 % Mtnew is required in the RHS function evaluation.
78 if Mtype == 2 % state-independent
79 if FcnHandlesUsed
80 Mtnew = feval(Mfun,tnew,Margs{:}); % mass(t,p1,p2...)
81 else
82 Mtnew = feval(Mfun,tnew,ynew,Margs{:}); % mass(t,y,'mass',p1,p2...)
83 end
84 end
85
86 % Iterate with simplified Newton method.
87 tooslow = false;
88 for iter = 1:maxit
89 if Mtype >= 3
90 Mtnew = feval(Mfun,tnew,ynew,Margs{:}); % state-dependent
91 end
92 rhs = hinvGak*feval(odeFcn,tnew,ynew,odeArgs{:}) - Mtnew*(psi+difkp1);
93 if DAE % Account for row scaling.
94 rhs = RowScale .* rhs;
95 end
96
97 [lastmsg,lastid] = lastwarn('');
98 warning(warnoff);
99 if issparse(Miter)
100 del = Q * (U \ (L \ (P * (R \ rhs))));
101 else
102 del = U \ (L \ rhs(p));
103 end
104 warning(warnstat);
105
106 % If no new warnings or a muted warning, restore previous lastwarn.
107 [msg,msgid] = lastwarn;
108 if isempty(msg) || any(strcmp(msgid,warnoffId))
109 lastwarn(lastmsg,lastid);
110 end
111
112 if normcontrol
113 newnrm = norm(del) * invwt;
114 else
115 newnrm = norm(del .* invwt,inf);
116 end
117 difkp1 = difkp1 + del;
118 ynew = pred + difkp1;
119
120 if newnrm <= minnrm
121 gotynew = true;
122 break;
123 elseif iter == 1
124 if havrate
125 errit = newnrm * rate / (1 - rate);
126 if errit <= 0.05*rtol % More stringent when using old rate.
127 gotynew = true;
128 break;
129 end
130 else
131 rate = 0;
132 end
133 elseif newnrm > 0.9*oldnrm
134 tooslow = true;
135 break;
136 else
137 rate = max(0.9*rate, newnrm / oldnrm);
138 havrate = true;
139 errit = newnrm * rate / (1 - rate);
140 if errit <= 0.5*rtol
141 gotynew = true;
142 break;
143 elseif iter == maxit
144 tooslow = true;
145 break;
146 elseif 0.5*rtol < errit*rate^(maxit-iter)
147 tooslow = true;
148 break;
149 end
150 end
151
152 oldnrm = newnrm;
153 end % end of Newton loop
154 nfevals = nfevals + iter;
155 nsolves = nsolves + iter;
156
157 if tooslow
158 nfailed = nfailed + 1;
159 % Speed up the iteration by forming new linearization or reducing h.
160 if ~Jcurrent || ~Mcurrent
161 if ~Jcurrent
162 if Janalytic
163 dfdy = feval(Jac,t,y,Jargs{:});
164 else
165 f0 = feval(odeFcn,t,y,odeArgs{:});
166 [dfdy,Joptions.fac,nF] = odenumjac(odeFcn, {t,y,odeArgs{:}}, f0,
Joptions);
167 nfevals = nfevals + nF + 1;
168 end
169 npds = npds + 1;
170 Jcurrent = true;
171 end
172 if ~Mcurrent
173 Mt = feval(Mfun,t,y,Margs{:});
174 Mcurrent = true;
175 if Mtype == 4
176 [dMpsidy,dMoptions.fac] = odenumjac(@odemxv, {Mfun,t,y,psi,Margs{:}},
Mt*psi, ...
177 dMoptions);
178 end
179 end
180 elseif absh <= hmin
181 warning(message('MATLAB:ode15s:IntegrationTolNotMet', sprintf( '%e', t ),
sprintf( '%e', hmin )));
182 solver_output = odefinalize(solver_name, sol,...
183 outputFcn, outputArgs,...
184 printstats, [nsteps, nfailed, nfevals,...
185 npds, ndecomps, nsolves],...
186 nout, tout, yout,...
187 haveEventFcn, teout, yeout, ieout,...
188 {kvec,dif3d,idxNonNegative});
189 if nargout > 0
190 varargout = solver_output;
191 end
192 return;
193 else
194 abshlast = absh;
195 absh = max(0.3 * absh, hmin);
196 h = tdir * absh;
197 done = false;
198
199 difRU = cumprod((kI - 1 - kJ*(absh/abshlast)) ./ kI) * difU;
200 dif(:,K) = dif(:,K) * difRU(K,K);
201
202 hinvGak = h * invGa(k);
203 nconhk = 0;
204 end
205 Miter = Mt - hinvGak * dfdy;
206 if Mtype == 4
207 Miter = Miter + dMpsidy;
208 end
209 if DAE
210 RowScale = 1 ./ max(abs(Miter),[],2);
211 Miter = sparse(one2neq,one2neq,RowScale) * Miter;
212 end
213 if issparse(Miter)
214 [L,U,P,Q,R] = lu(Miter);
215 else
216 [L,U,p] = lu(Miter,'vector');
217 end
218 ndecomps = ndecomps + 1;
219 havrate = false;
220 end
221 end % end of while loop for getting ynew
222
223 % difkp1 is now the backward difference of ynew of order k+1.
224 if normcontrol
225 err = (norm(difkp1) * invwt) * erconst(k);
226 else
227 err = norm(difkp1 .* invwt,inf) * erconst(k);
228 end
229 if nonNegative && (err <= rtol) && any(ynew(idxNonNegative)<0)
230 if normcontrol
231 errNN = norm( max(0,-ynew(idxNonNegative)) ) * invwt;
232 else
233 errNN = norm( max(0,-ynew(idxNonNegative)) ./ thresholdNonNegative, inf);
234 end
235 if errNN > rtol
236 err = errNN;
237 end
238 end
239
240 if err > rtol % Failed step
241 nfailed = nfailed + 1;
242 if absh <= hmin
243 warning(message('MATLAB:ode15s:IntegrationTolNotMet', sprintf( '%e', t ),
sprintf( '%e', hmin )));
244 solver_output = odefinalize(solver_name, sol,...
245 outputFcn, outputArgs,...
246 printstats, [nsteps, nfailed, nfevals,...
247 npds, ndecomps, nsolves],...
248 nout, tout, yout,...
249 haveEventFcn, teout, yeout, ieout,...
250 {kvec,dif3d,idxNonNegative});
251 if nargout > 0
252 varargout = solver_output;
253 end
254 return;
255 end
256
257 abshlast = absh;
258 if nofailed
259 nofailed = false;
260 hopt = absh * max(0.1, 0.833*(rtol/err)^(1/(k+1))); % 1/1.2
261 if k > 1
262 if normcontrol
263 errkm1 = (norm(dif(:,k) + difkp1) * invwt) * erconst(k-1);
264 else
265 errkm1 = norm((dif(:,k) + difkp1) .* invwt,inf) * erconst(k-1);
266 end
267 hkm1 = absh * max(0.1, 0.769*(rtol/errkm1)^(1/k)); % 1/1.3
268 if hkm1 > hopt
269 hopt = min(absh,hkm1); % don't allow step size increase
270 k = k - 1;
271 K = 1:k;
272 end
273 end
274 absh = max(hmin, hopt);
275 else
276 absh = max(hmin, 0.5 * absh);
277 end
278 h = tdir * absh;
279 if absh < abshlast
280 done = false;
281 end
282
283 difRU = cumprod((kI - 1 - kJ*(absh/abshlast)) ./ kI) * difU;
284 dif(:,K) = dif(:,K) * difRU(K,K);
285
286 hinvGak = h * invGa(k);
287 nconhk = 0;
288 Miter = Mt - hinvGak * dfdy;
289 if Mtype == 4
290 Miter = Miter + dMpsidy;
291 end
292 if DAE
293 RowScale = 1 ./ max(abs(Miter),[],2);
294 Miter = sparse(one2neq,one2neq,RowScale) * Miter;
295 end
296 if issparse(Miter)
297 [L,U,P,Q,R] = lu(Miter);
298 else
299 [L,U,p] = lu(Miter,'vector');
300 end
301 ndecomps = ndecomps + 1;
302 havrate = false;
303
304 else % Successful step
305 break;
306
307 end
308 end % while true
309 nsteps = nsteps + 1;
310
311 dif(:,k+2) = difkp1 - dif(:,k+1);
312 dif(:,k+1) = difkp1;
313 for j = k:-1:1
314 dif(:,j) = dif(:,j) + dif(:,j+1);
315 end
316
317 NNreset_dif = false;
318 if nonNegative && any(ynew(idxNonNegative) < 0)
319 NNidx = idxNonNegative(ynew(idxNonNegative) < 0); % logical indexing
320 ynew(NNidx) = 0;
321 if normcontrol
322 normynew = norm(ynew);
323 end
324 NNreset_dif = true;
325 end
326
327 if haveEventFcn
328 [te,ye,ie,valt,stop] = odezero(@ntrp15s,eventFcn,eventArgs,valt,...
329 t,y,tnew,ynew,t0,h,dif,k,idxNonNegative);
330 if ~isempty(te)
331 if output_sol || (nargout > 2)
332 teout = [teout, te];
333 yeout = [yeout, ye];
334 ieout = [ieout, ie];
335 end
336 if stop % Stop on a terminal event.
337 % Adjust the interpolation data to [t te(end)].
338 taux = te(end) - (0:k)*(te(end) - t);
339 yaux = ntrp15s(taux,t,y,tnew,ynew,h,dif,k,idxNonNegative);
340 for j=2:k+1
341 yaux(:,j:k+1) = yaux(:,j-1:k) - yaux(:,j:k+1);
342 end
343 dif(:,1:k) = yaux(:,2:k+1);
344 tnew = te(end);
345 ynew = ye(:,end);
346 h = tnew - t;
347 done = true;
348 end
349 end
350 end
351
352 if output_sol
353 nout = nout + 1;
354 if nout > length(tout)
355 tout = [tout, zeros(1,chunk)]; % requires chunk >= refine
356 yout = [yout, zeros(neq,chunk)];
357 kvec = [kvec, zeros(1,chunk)];
358 dif3d = cat(3,dif3d, zeros(neq,maxk+2,chunk));
359 end
360 tout(nout) = tnew;
361 yout(:,nout) = ynew;
362 kvec(nout) = k;
363 dif3d(:,:,nout) = dif;
364 end
365
366 if output_ty || haveOutputFcn
367 switch outputAt
368 case 'SolverSteps' % computed points, no refinement
369 nout_new = 1;
370 tout_new = tnew;
371 yout_new = ynew;
372 case 'RefinedSteps' % computed points, with refinement
373 tref = t + (tnew-t)*S;
374 nout_new = refine;
375 tout_new = [tref, tnew];
376 yout_new = [ntrp15s(tref,[],[],tnew,ynew,h,dif,k,idxNonNegative), ynew];
377 case 'RequestedPoints' % output only at tspan points
378 nout_new = 0;
379 tout_new = [];
380 yout_new = [];
381 while next <= ntspan
382 if tdir * (tnew - tspan(next)) < 0
383 if haveEventFcn && stop % output tstop,ystop
384 nout_new = nout_new + 1;
385 tout_new = [tout_new, tnew];
386 yout_new = [yout_new, ynew];
387 end
388 break;
389 end
390 nout_new = nout_new + 1;
391 tout_new = [tout_new, tspan(next)];
392 if tspan(next) == tnew
393 yout_new = [yout_new, ynew];
394 else
395 yout_new = [yout_new, ntrp15s(tspan(next),[],[],tnew,ynew,h,dif,k,...
396 idxNonNegative)];
397 end
398 next = next + 1;
399 end
400 end
401
402 if nout_new > 0
403 if output_ty
404 oldnout = nout;
405 nout = nout + nout_new;
406 if nout > length(tout)
407 tout = [tout, zeros(1,chunk)]; % requires chunk >= refine
408 yout = [yout, zeros(neq,chunk)];
409 end
410 idx = oldnout+1:nout;
411 tout(idx) = tout_new;
412 yout(:,idx) = yout_new;
413 end
414 if haveOutputFcn
415 stop = feval(outputFcn,tout_new,yout_new(outputs,:),'',outputArgs{:});
416 if stop
417 done = true;
418 end
419 end
420 end
421 end
422
423 if done
424 break
425 end
426
427 klast = k;
428 abshlast = absh;
429 nconhk = min(nconhk+1,maxk+2);
430 if nconhk >= k + 2
431 temp = 1.2*(err/rtol)^(1/(k+1));
432 if temp > 0.1
433 hopt = absh / temp;
434 else
435 hopt = 10*absh;
436 end
437 kopt = k;
438 if k > 1
439 if normcontrol
440 errkm1 = (norm(dif(:,k)) * invwt) * erconst(k-1);
441 else
442 errkm1 = norm(dif(:,k) .* invwt,inf) * erconst(k-1);
443 end
444 temp = 1.3*(errkm1/rtol)^(1/k);
445 if temp > 0.1
446 hkm1 = absh / temp;
447 else
448 hkm1 = 10*absh;
449 end
450 if hkm1 > hopt
451 hopt = hkm1;
452 kopt = k - 1;
453 end
454 end
455 if k < maxk
456 if normcontrol
457 errkp1 = (norm(dif(:,k+2)) * invwt) * erconst(k+1);
458 else
459 errkp1 = norm(dif(:,k+2) .* invwt,inf) * erconst(k+1);
460 end
461 temp = 1.4*(errkp1/rtol)^(1/(k+2));
462 if temp > 0.1
463 hkp1 = absh / temp;
464 else
465 hkp1 = 10*absh;
466 end
467 if hkp1 > hopt
468 hopt = hkp1;
469 kopt = k + 1;
470 end
471 end
472 if hopt > absh
473 absh = hopt;
474 if k ~= kopt
475 k = kopt;
476 K = 1:k;
477 end
478 end
479 end
480
481 % Advance the integration one step.
482 t = tnew;
483 y = ynew;
484 if NNreset_dif
485 % Used dif for unperturbed solution to select order and interpolate.
486 % In perturbing ynew, defined NNidx. Use now to reset dif to move along
487 % constraint.
488 dif(NNidx,:) = 0;
489 end
490 if normcontrol
491 normy = normynew;
492 end
493 Jcurrent = Jconstant;
494 switch Mtype
495 case {0,1}
496 Mcurrent = true; % Constant mass matrix I or M.
497 case 2
498 % M(t) has already been evaluated at tnew in Mtnew.
499 Mt = Mtnew;
500 Mcurrent = true;
501 case {3,4} % state dependent
502 % M(t,y) has not yet been evaluated at the accepted ynew.
503 Mcurrent = false;
504 end
505
506 end % while ~done