0% found this document useful (0 votes)
87 views9 pages

Ode 15 S

This document contains code for numerically solving differential equations using an adaptive step size method. It initializes variables, computes steps, evaluates the solution, and adjusts the step size and order as needed based on error estimates. If a step fails, it reduces the step size or order and retries the step.

Uploaded by

砂糖yumeko
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
87 views9 pages

Ode 15 S

This document contains code for numerically solving differential equations using an adaptive step size method. It initializes variables, computes steps, evaluates the solution, and adjusts the step size and order as needed based on error estimates. If a step fails, it reduces the step size or order and retries the step.

Uploaded by

砂糖yumeko
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

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

You might also like