[sundials-users] [LLNL/sundials] CVode does not return CV_TOO_CLOSE when initial step size is set (Issue #722)

3 views
Skip to first unread message

Eliott Tixier

unread,
Jun 21, 2025, 2:08:43 AMJun 21
to SUNDIAL...@listserv.llnl.gov
eltix created an issue (LLNL/sundials#722)

Issue description

To illustrate our questions, here is a MWE in the form of a simple one-equation ODE system:

$$\begin{aligned} & \dot y = \mathrm{mod}(t, 1)\\\ & y(t=0) = 0 \\\ & 0 \le t \le 10 \end{aligned}$$

where $\mathrm{mod}(t, 1)$ stands for the fractional part of $t$.
The exact solution is a piece-wise parabola and we are mostly interested in the value at t=10 which is $y(t=10)=5$.

How we solved this problem using CVode

See the example code in the "To replicate" section below.

  1. By default, CVode may give incorrect results because the ODE RHS is not continuous and therefore the solver may "step over" the discontinuity should it take a large enough step.

  2. This is expected so we added a root function which triggers at each discontinuity of the RHS, that is for $t = k, k \in \mathbb N$:

static int root_fn(sunrealtype t, N_Vector y, sunrealtype *gout, void *user_data) {
  sunrealtype y1, b;

  y1 = Ith(y, 1);
  b = SUN_RCONST(1);

  // a jig-saw function which has roots at t = k, k being any integer
  *gout = fabs( fmod(t-b/2, 2*b) - b) - b/2;
  return 0;
}

But now CVode() returns CV_TOO_CLOSE:

[ERROR][rank 0][/build/sundials-7.2.1/src/cvode/cvode.c:3710][cvHandleFailure] tout too close to t0 to start integration.
At t_out = 1.00e+01 t = 1.000000e+01 y1 = 5.0e+00 tcur = 1.0e+01 step = 0.0e+00 order = 0 err1 = -8.8e-07 
retval = -27, return 1
  1. This is somewhat expected since the root time coincides exactly with the asked time t=10. So we special cased CV_TOO_CLOSE. At this point, if you're trying to reproduce the issue, you should uncomment this block at lines 153-159:
    else if (retval == CV_TOO_CLOSE) {
      /* This happens if tout is too close to t. In such a case, no solving was required; just continue as if solving succeeded. 
      However, if the init step is set using CVodeSetInitStep, CVode DOES NOT RETURN CV_TOO_CLOSE, see below
      */
      printf("retval == CV_TOO_CLOSE\n");
      iout++;
    }
  1. Up until now, the init step size was not set. Let's set it (uncomment lines 109-110):
  retval = CVodeSetInitStep(cvode_mem, INITSTEP);
  if (check_retval(&retval, "CVodeSetInitStep", 1)) { return (1); }

Now we have an infinite loop because CVode() no longer returns CV_TOO_CLOSE!

  1. This is where things get interesting and we are seeking guidance. To prevent the infinite loop, we wrote an additional safeguard (uncomment lines 160-167):
    else if (retval == CV_ROOT_RETURN && t == tout) {
      /* See the above
         if the init step is set using CVodeSetInitStep, CVode DOES NOT RETURN CV_TOO_CLOSE when tout is too close to t
         In such a case, pretend that the root didn't happen, lest we keep handling it forever. 
      */
      printf("t == tout && retval == CV_ROOT_RETURN\n");
      iout++;
    }

This seems to work but the results are actually incorrect since we have y(t=10) = 0.5 instead of 5:

At t_out = 1.00e+01 t = 1.000000e+01 y1 = 5.0e-01 tcur = 1.0e+01 step = 1.0e+00 order = 1 err1 = 0.0e+00

The questions

  1. Is it expected that CVode() does not return CV_TOO_CLOSE when init step size is set?
  2. In general, how should handle cases where the root finding function triggers on a time that coincides with a requested solution time?

To replicate

  1. Sundials version: 7.2.1

  2. example.zip contains an example.c source file which you can compile with

gcc example.c -lsundials_cvode -lsundials_core -lm

and then run with

./a.out


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <LLNL/sundials/issues/722@github.com>



To unsubscribe from the SUNDIALS-USERS list: write to: mailto:SUNDIALS-USERS-...@LISTSERV.LLNL.GOV

Eliott Tixier

unread,
Jun 26, 2025, 2:04:25 PMJun 26
to SUNDIAL...@listserv.llnl.gov
eltix left a comment (LLNL/sundials#722)

@sundials-users-github-account

Dear Alan, thank you for your answer

  1. Since the discontinuities in the RHS function occur at known times, the use of rootfinding is the wrong fix

The above was just an example, in general we do not know when the roots trigger, hence the need to use root finding. For fixed-time events (where we know in advance at what time they occur), we simply stop and re-init the solver as you explained.

  1. before restarting, the root function should be reset so that the same root is not seen twice

This is the part we were missing, thank you very much

  1. If the initial step is supplied, that error return is avoided. Perhaps this should be changed.

Since this was a surprise from a user perspective, I would say that indeed the same error should be returned when the initial step is supplied such that the behavior is consistent.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you were mentioned.Message ID: <LLNL/sundials/issues/722/3007525949@github.com>

Reply all
Reply to author
Forward
0 new messages