At Mark 22: | nwkjac and njcpvt were removed from the interface; neq was made optional |
. . . [...] = d02nv(...); [...] = d02nu(...); [..., ifail] = d02nd(...); if (ifail ~= 1 and ifail < 14) [...] = d02nx(...); [...] = d02ny(...); end . . .The linear algebra setup function nag_ode_ivp_stiff_sparjac_setup (d02nu) and one of the integrator setup functions, nag_ode_ivp_stiff_bdf (d02nv) or nag_ode_ivp_stiff_blend (d02nw), must be called prior to the call of nag_ode_ivp_stiff_exp_sparjac (d02nd). Either or both of the integrator diagnostic function nag_ode_ivp_stiff_integ_diag (d02ny), or the sparse matrix linear algebra diagnostic function nag_ode_ivp_stiff_sparjac_diag (d02nx), may be called after the call to nag_ode_ivp_stiff_exp_sparjac (d02nd). There is also a function, nag_ode_ivp_stiff_contin (d02nz), designed to permit you to change step size on a continuation call to nag_ode_ivp_stiff_exp_sparjac (d02nd) without restarting the integration process.
Input Parameters
Output Parameters
Input Parameters
Output Parameters
Input Parameters
[errloc, ifail] = d02za(acor(1:neq,2), acor(1:neq,1)); % Check ifail before proceeding
Output Parameters
Cases prefixed with W are classified as warnings and do not generate an error of type NAG:error_n. See nag_issue_warnings.
Open in the MATLAB editor: d02nd_example
function d02nd_example fprintf('d02nd example results\n\n'); % For communication with monitr2. global ncall ykeep tkeep tout % For communication with interp. global xout rwork % Initialize setup variables and arrays. neq = int64(3); neqmax = int64(neq); maxord = int64(5); sdysav = int64(maxord+1); maxstp = int64(200); mxhnil = int64(5); h0 = 0; hmax = 10; hmin = 1.0e-10; tcrit = 0; petzld = false; const = zeros(6, 1); rwork = zeros(50+4*neqmax, 1); % d02nv is a setup routine to be called prior to d02nd. [const, rwork, ifail] = ... d02nv( ... neqmax, sdysav, maxord, 'Newton', petzld, ... const, tcrit, hmin, hmax, h0, maxstp, mxhnil, 'Average-L2', rwork); nelts = 8; nia = int64(neq+1); nja = int64(nelts); ia = int64([1; 3; 6; 9]); ja = int64([1; 2; 1; 2; 3; 1; 2; 3]); njcpvt = int64(150); nwkjac = int64(50); eta = 1.0e-4; u = 0.1; sens = 0.0; lblock = true; % d02nu is a setup routine for sparse Jacobian to be called prior to d02nd. [jacpvt, rwork, ifail] = ... d02nu( ... neq, neqmax, 'Numerical', nwkjac, ia, ja, ... njcpvt, sens, u, eta, lblock, rwork, 'nia', nia, 'nja', nja); % Initialize integration variables and arrays. inform(1:23) = int64(0); wkjac = zeros(nwkjac, 1); ysave = zeros(neq, sdysav); % First case. % Integrate to tout by overshooting (itask=1) using using BDF with Newton. % Scalar relative and absolute tolerances. % Numerical Jacobian. t = 0; tout = 10.0; itask = int64(1); itrace = int64(0); y = [1; 0; 0]; itol = int64(1); rtol = [1e-4]; atol = [1e-7]; isplit = int64(0); % Output initial condition. fprintf('Numerical Jacobian, structure not supplied\n\n'); fprintf(' x y_1 y_2 y_3\n'); fprintf('%8.3f %8.5f %8.5f %8.5f\n',t,y); xout = 2.0; % Numerical Jacobian (d02ndz) with monitoring (monitr1). [t, y, ydot, rwork, inform, ysave, wkjac, jacpvt,ifail] = ... d02nd( ... t, tout, y, rwork, rtol, atol, itol, inform, @fcn, ysave, ... 'd02ndz', wkjac, jacpvt, @monitr1, itask, itrace); % d02ny is an integrator diagnostic routine which can be called after d02nd. [hu, h, tcur, tolsf, nst, nre, nje, nqu, nq, niter, imxer, algequ, ifail] ... = d02ny( ... neq, neqmax, rwork, inform); % Output diagnostics. fprintf('\nDiagnostic information\n integration status:\n'); fprintf(' last and next step sizes = %8.5f, %8.5f\n',hu, h); fprintf(' integration stopped at x = %8.5f\n',tcur); fprintf(' algorithm statistics:\n'); fprintf(' number of time-steps and Newton iterations = %5d %5d\n',nst,niter); fprintf(' number of residual and jacobian evaluations = %5d %5d\n',nre,nje); fprintf(' order of method last used and next to use = %5d %5d\n',nqu,nq); fprintf(' component with largest error = %5d\n',imxer); % d02nx is an optional output routine which can be called after d02nd. icall = int64(0); [liwreq, liwusd, lrwreq, lrwusd, nlu, nz, ngp, isplit, igrow, nblock] ... = d02nx( ... icall, lblock, inform); % Output diagnostics. fprintf(' sparse jacobian statistics:\n'); fprintf(' njcpvt - required = %3d, used = %3d\n',liwreq,liwusd); fprintf(' nwkjac - required = %3d, used = %3d)\n',lrwreq,lrwusd); fprintf(' No. of LU-decomps = %3d, No. of nonzeros = %3d\n',nlu,nz); fprintf([' No. of function calls to form Jacobian = %3d, try ', ... 'isplit = %3d\n'], ngp, isplit); fprintf([' Growth estimate = %d, No. of blocks on diagonal %3d\n\n'], ... igrow, nblock); % Second case. % As first case but using known structure of Jacobian. t = 0; y = [1; 0; 0]; isplit = int64(0); % Prepare to store results for plotting. This gets done in monitr2. ncall = int64(1); tkeep = t; ykeep = y; [const, rwork, ifail] = d02nv( ... neqmax, sdysav, maxord, 'Newton', petzld, ... const, tcrit, hmin, hmax, h0, maxstp, ... mxhnil, 'Average-L2', rwork); [jacpvt, rwork, ifail] = d02nu( ... neq, neqmax, 'Structural', nwkjac, ia, ja, ... njcpvt, sens, u, eta, lblock, rwork, 'nia', ... nia, 'nja', nja); fprintf('Numerical Jacobian, structure supplied\n\n'); fprintf(' x y_1 y_2 y_3\n'); fprintf('%8.3f %8.5f %8.5f %8.5f\n',t,y); xout = 2.0; [t, y, ydot, rwork, inform, ysave, wkjac, jacpvt,ifail] = ... d02nd( ... t, tout, y, rwork, rtol, atol, itol, inform, @fcn, ysave, ... 'd02ndz', wkjac, jacpvt, @monitr2, itask, itrace); [hu, h, tcur, tolsf, nst, nre, nje, nqu, nq, niter, imxer, algequ, ifail] ... = d02ny( ... neq, neqmax, rwork, inform); fprintf('\nDiagnostic information\n integration status:\n'); fprintf(' last and next step sizes = %8.5f, %8.5f\n',hu, h); fprintf(' integration stopped at x = %8.5f\n',tcur); fprintf(' algorithm statistics:\n'); fprintf(' number of time-steps and Newton iterations = %5d %5d\n',nst,niter); fprintf(' number of residual and jacobian evaluations = %5d %5d\n',nre,nje); fprintf(' order of method last used and next to use = %5d %5d\n',nqu,nq); fprintf(' component with largest error = %5d\n',imxer); [liwreq, liwusd, lrwreq, lrwusd, nlu, nz, ngp, isplit, igrow, nblock] = ... d02nx( ... icall, lblock, inform); fprintf(' sparse jacobian statistics:\n'); fprintf(' njcpvt - required = %3d, used = %3d\n',liwreq,liwusd); fprintf(' nwkjac - required = %3d, used = %3d\n',lrwreq,lrwusd); fprintf(' No. of LU-decomps = %3d, No. of nonzeros = %3d\n',nlu,nz); fprintf([' No. of function calls to form Jacobian = %3d, try ', ... 'isplit = %3d\n'], ngp, isplit); fprintf([' Growth estimate = %d, No. of blocks on diagonal %3d\n\n'], ... igrow, nblock); % Plot results. fig1 = figure; display_plot(tkeep,ykeep) function [hnext, y, imon, inln, hmin, hmax] = ... monitr1(neq, neqmax, t, hlast, hnext, y, ydot, ysave, ... r, acor, imon, hmin, hmax, nqu) % Print out solution at intermediate point if passed at this step. [imon] = interp(neq, t, hlast, hnext, ysave, imon, nqu); inln = int64(0); function [hnext, y, imon, inln, hmin, hmax] = ... monitr2( neq, neqmax, t, hlast, hnext, y, ydot, ysave, ... r, acor, imon, hmin, hmax, nqu) % Like monitr1 but also stores the current results for plotting later. % For communication with main routine. global ncall ykeep tkeep tout if (imon == 1 && t>0.00001 && t<tout) ncall = ncall + 1; ykeep(:,ncall) = y; tkeep (ncall) = t; end [imon] = interp(neq, t, hlast, hnext, ysave, imon, nqu); inln = int64(0); function [imon] = interp(neq, t, hlast, hnext, ysave, imon, nqu) % This routine prints out intermediate values by interpolating. % For communication with main routine. global xout rwork dims = size(ysave); lbeg = dims(1) + 50 + 1; lend = lbeg + neq - 1; lw(1:neq) = rwork(lbeg:lend); % Print intermediate result if integration has passed it at this step. while (xout <= 10.0 && t-hlast < xout && xout <= t) % d02xk interpolates components of the solution of a system of ODEs, % as provided by (e.g.) d02nd. [sol, ifail] = d02xk(xout, neq, ysave, lw, t, nqu, hlast, hnext); fprintf('%8.3f %13.5f %13.5f %13.5f\n', xout, sol(1:3)); xout = xout + 2; end function [f, ires] = fcn(neq, t, y, ires) % Evaluate derivative vector. f = zeros(3,1); f(1) = -0.04d0*y(1) + 1.0d4*y(2)*y(3); f(2) = 0.04d0*y(1) - 1.0d4*y(2)*y(3) - 3.0d7*y(2)*y(2); f(3) = 3.0d7*y(2)*y(2); function display_plot(tkeep,ykeep) % Plot one of the curves and then add the other two. hline3 = plot(tkeep,ykeep(3,:)); hold on; [haxes, hline1, hline2] = plotyy(tkeep,ykeep(1,:), tkeep,ykeep(2,:)); % Set the axis limits and the tick specifications to beautify the plot. set(haxes(1), 'YLim', [0 1.2]); set(haxes(1), 'XMinorTick', 'on', 'YMinorTick', 'on'); set(haxes(1), 'YTick', [0:0.2:1]); set(haxes(2), 'YLim', [0 4e-5]); set(haxes(2), 'YMinorTick', 'on'); set(haxes(2), 'YTick', [5e-6:5e-6:3.5e-5]); set(haxes(1), 'XLim', [-0.1 10]); set(haxes(2), 'XLim', [-0.1 10]); % Add title. ht = title({'Stiff Robertson Problem: BDF Method', ... 'Jacobian: Sparse with Structure Supplied'}); set(ht,'Position',[5,1.05,0.0]); % Label the x axis, and both y axes. xlabel('x'); ylabel(haxes(1),'Solution (a,c)'); ylabel(haxes(2),'Solution (b)'); % Add a legend. legend('c','a','b','Location','West'); % Set some features of the lines. set(hline1,'Linewidth',0.5,'Marker','+','LineStyle','-','Color','red'); set(hline2,'Linewidth',0.5,'Marker','*','LineStyle',':','Color','blue'); set(hline3,'Linewidth',0.5,'Marker','x','LineStyle','--','Color','green'); hold off;
d02nd example results Numerical Jacobian, structure not supplied x y_1 y_2 y_3 0.000 1.00000 0.00000 0.00000 2.000 0.94161 0.00003 0.05836 4.000 0.90552 0.00002 0.09446 6.000 0.87927 0.00002 0.12072 8.000 0.85855 0.00002 0.14144 10.000 0.84137 0.00002 0.15863 Diagnostic information integration status: last and next step sizes = 0.90236, 0.90236 integration stopped at x = 10.76936 algorithm statistics: number of time-steps and Newton iterations = 55 78 number of residual and jacobian evaluations = 136 16 order of method last used and next to use = 4 4 component with largest error = 3 sparse jacobian statistics: njcpvt - required = 100, used = 150 nwkjac - required = 29, used = 50) No. of LU-decomps = 16, No. of nonzeros = 7 No. of function calls to form Jacobian = 3, try isplit = 73 Growth estimate = 1108, No. of blocks on diagonal 1 Numerical Jacobian, structure supplied x y_1 y_2 y_3 0.000 1.00000 0.00000 0.00000 2.000 0.94161 0.00003 0.05837 4.000 0.90551 0.00002 0.09446 6.000 0.87926 0.00002 0.12072 8.000 0.85854 0.00002 0.14144 10.000 0.84135 0.00002 0.15863 Diagnostic information integration status: last and next step sizes = 0.90178, 0.90178 integration stopped at x = 10.76621 algorithm statistics: number of time-steps and Newton iterations = 55 78 number of residual and jacobian evaluations = 129 16 order of method last used and next to use = 4 4 component with largest error = 3 sparse jacobian statistics: njcpvt - required = 106, used = 150 nwkjac - required = 31, used = 50 No. of LU-decomps = 16, No. of nonzeros = 8 No. of function calls to form Jacobian = 3, try isplit = 73 Growth estimate = 277504, No. of blocks on diagonal 1