changeset 31495:4cb81dcc5cc5 stable

Add BIST for OutputSel option in ode23, ode23s, ode45 (bug #63229) * ode23.m, ode23s.m, ode45.m: Add a BIST test function to be called within odeset to ensure the odeXX function call passes the correct elements to the output monitoring function. Add BISTs that call test function in scalar and vector forms.
author Ken Marek <marek_ka@mercer.edu>
date Wed, 16 Nov 2022 23:07:58 -0500
parents c05ef94a2bbc
children 3ccd6628a6f4 55f0173e4f08
files scripts/ode/ode23.m scripts/ode/ode23s.m scripts/ode/ode45.m
diffstat 3 files changed, 120 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/ode/ode23.m	Mon Nov 21 08:46:07 2022 +0100
+++ b/scripts/ode/ode23.m	Wed Nov 16 23:07:58 2022 -0500
@@ -365,6 +365,35 @@
 %!    error ("fout: invalid flag <%s>", flag);
 %!  endif
 %!endfunction
+%!function stop_solve = OutputSel_test (t, y, flag, x)
+%!  ## x == 1: select y(1)
+%!  ## x == 2: select y(2)
+%!  ## x == 3: select y([1,2])
+%!  persistent y_last
+%!  if strcmp (flag, "init")
+%!    y_last = y;
+%!    if ((x == 1) || (x == 2))
+%!      assert (length (y) == 1);
+%!    elseif (x == 3)
+%!      assert (length (y) == 2);
+%!    endif
+%!  elseif strcmp (flag, "done")
+%!    y_exp = fref ().';
+%!    if (x < 3)
+%!      assert (y_last, y_exp(x), 5e-4);
+%!    else
+%!      assert (y_last, y_exp, 5e-4);
+%!    endif
+%!  else # flag == ""
+%!    y_last = y(:, end);
+%!    if ((x == 1) || (x == 2))
+%!      assert (length (t) == length (y));
+%!    else
+%!      assert (2 * length (t) == length (y(:)));
+%!    endif
+%!  endif
+%!  stop_solve = 0;
+%!endfunction
 %!
 %!test  # two output arguments
 %! [t, y] = ode23 (@fpol, [0 2], [2 0]);
@@ -442,8 +471,17 @@
 %! opt = odeset ("NonNegative", 2);
 %! sol = ode23 (@fpol, [0 2], [2 0], opt);
 %! assert ([sol.x(end); sol.y(:,end)], [2; 2; 0], 1e-1);
-%!test  # Details of OutputSel can't be tested
-%! opt = odeset ("OutputFcn", @fout, "OutputSel", 1);
+%!test  # OutputSel 1 (see function OutputSel_test for asserts)
+%! opt = odeset ("OutputFcn", @(t, y, flag) OutputSel_test (t, y, flag, 1), ...
+%!               "OutputSel", 1);
+%! sol = ode23 (@fpol, [0 2], [2 0], opt);
+%!test  # OutputSel 2 (see function OutputSel_test for asserts)
+%! opt = odeset ("OutputFcn", @(t, y, flag) OutputSel_test (t, y, flag, 2), ...
+%!               "OutputSel", 2);
+%! sol = ode23 (@fpol, [0 2], [2 0], opt);
+%!test  # OutputSel [1,2] (see function OutputSel_test for asserts)
+%! opt = odeset ("OutputFcn", @(t, y, flag) OutputSel_test (t, y, flag, 3), ...
+%!               "OutputSel", [1, 2]);
 %! sol = ode23 (@fpol, [0 2], [2 0], opt);
 %!test  # Stats must add further elements in sol
 %! opt = odeset ("Stats", "on");
--- a/scripts/ode/ode23s.m	Mon Nov 21 08:46:07 2022 +0100
+++ b/scripts/ode/ode23s.m	Wed Nov 16 23:07:58 2022 -0500
@@ -399,6 +399,35 @@
 %!    error ("fout: invalid flag <%s>", flag);
 %!  endif
 %!endfunction
+%!function stop_solve = OutputSel_test (t, y, flag, x)
+%!  ## x == 1: select y(1)
+%!  ## x == 2: select y(2)
+%!  ## x == 3: select y([1,2])
+%!  persistent y_last
+%!  if strcmp (flag, "init")
+%!    y_last = y;
+%!    if ((x == 1) || (x == 2))
+%!      assert (length (y) == 1);
+%!    elseif (x == 3)
+%!      assert (length (y) == 2);
+%!    endif
+%!  elseif strcmp (flag, "done")
+%!    y_exp = fref ().';
+%!    if (x < 3)
+%!      assert (y_last, y_exp(x), 1e-4);
+%!    else
+%!      assert (y_last, y_exp, 1e-4);
+%!    endif
+%!  else # flag == ""
+%!    y_last = y(:,end);
+%!    if ((x == 1) || (x == 2))
+%!      assert (length (t) == length (y));
+%!    else
+%!      assert (2 * length (t) == length (y(:)));
+%!    endif
+%!  endif
+%!  stop_solve = 0;
+%!endfunction
 %!
 %!test  # two output arguments
 %! [t, y] = ode23s (@fpol, [0 2], [2 0]);
@@ -442,8 +471,17 @@
 %! opt = odeset ("RelTol", 1e-8, "NormControl", "on");
 %! sol = ode23s (@fpol, [0 2], [2 0], opt);
 %! assert ([sol.x(end); sol.y(:,end)], [2; fref'], 1e-4);
-%!test  # Details of OutputSel can't be tested
-%! opt = odeset ("OutputFcn", @fout, "OutputSel", 1);
+%!test  # OutputSel 1 (see function OutputSel_test for asserts)
+%! opt = odeset ("OutputFcn", @(t, y, flag) OutputSel_test (t, y, flag, 1), ...
+%!               "OutputSel", 1);
+%! sol = ode23s (@fpol, [0 2], [2 0], opt);
+%!test  # OutputSel 2 (see function OutputSel_test for asserts)
+%! opt = odeset ("OutputFcn", @(t, y, flag) OutputSel_test (t, y, flag, 2), ...
+%!               "OutputSel", 2);
+%! sol = ode23s (@fpol, [0 2], [2 0], opt);
+%!test  # OutputSel [1,2] (see function OutputSel_test for asserts)
+%! opt = odeset ("OutputFcn", @(t, y, flag) OutputSel_test (t, y, flag, 3), ...
+%!               "OutputSel", [1, 2]);
 %! sol = ode23s (@fpol, [0 2], [2 0], opt);
 %!test  # Stats must add further elements in sol
 %! opt = odeset ("Stats", "on");
--- a/scripts/ode/ode45.m	Mon Nov 21 08:46:07 2022 +0100
+++ b/scripts/ode/ode45.m	Wed Nov 16 23:07:58 2022 -0500
@@ -364,6 +364,35 @@
 %!    error ("fout: invalid flag <%s>", flag);
 %!  endif
 %!endfunction
+%!function stop_solve = OutputSel_test (t, y, flag, x)
+%!  ## x == 1: select y(1)
+%!  ## x == 2: select y(2)
+%!  ## x == 3: select y([1,2])
+%!  persistent y_last
+%!  if strcmp (flag, "init")
+%!    y_last = y;
+%!    if ((x == 1) || (x == 2))
+%!      assert (length (y) == 1);
+%!    elseif (x == 3)
+%!      assert (length (y) == 2);
+%!    endif
+%!  elseif strcmp (flag, "done")
+%!    y_exp = fref ().';
+%!    if (x < 3)
+%!      assert (y_last, y_exp(x), 1e-4);
+%!    else
+%!      assert (y_last, y_exp, 1e-4);
+%!    endif
+%!  else # flag == ""
+%!    y_last = y(:,end);
+%!    if ((x == 1) || (x == 2))
+%!      assert (length (t) == length (y));
+%!    else
+%!      assert (2 * length (t) == length (y(:)));
+%!    endif
+%!  endif
+%!  stop_solve = 0;
+%!endfunction
 %!
 %!test  # two output arguments
 %! [t, y] = ode45 (@fpol, [0 2], [2 0]);
@@ -453,8 +482,17 @@
 %! opt = odeset ("NonNegative", 2);
 %! sol = ode45 (@fpol, [0 2], [2 0], opt);
 %! assert ([sol.x(end); sol.y(:,end)], [2; 2; 0], 0.5);
-%!test  # Details of OutputSel can't be tested
-%! opt = odeset ("OutputFcn", @fout, "OutputSel", 1);
+%!test  # OutputSel 1 (see function OutputSel_test for asserts)
+%! opt = odeset ("OutputFcn", @(t, y, flag) OutputSel_test (t, y, flag, 1), ...
+%!               "OutputSel", 1);
+%! sol = ode45 (@fpol, [0 2], [2 0], opt);
+%!test  # OutputSel 2 (see function OutputSel_test for asserts)
+%! opt = odeset ("OutputFcn", @(t, y, flag) OutputSel_test (t, y, flag, 2), ...
+%!               "OutputSel", 2);
+%! sol = ode45 (@fpol, [0 2], [2 0], opt);
+%!test  # OutputSel [1,2] (see function OutputSel_test for asserts)
+%! opt = odeset ("OutputFcn", @(t, y, flag) OutputSel_test (t, y, flag, 3), ...
+%!               "OutputSel", [1,2]);
 %! sol = ode45 (@fpol, [0 2], [2 0], opt);
 %!test  # Stats must add further elements in sol
 %! opt = odeset ("Stats", "on");