Can scipy.integrate.solve_ivp reject a step to avoid evaluating the RHS with an invalid state?

66 Views Asked by At

My code is much more complex, but I can reproduce the issue with the following example:

import numpy as np
from scipy.integrate import solve_ivp


def funct(t, y):
    return -np.sqrt(y)


def event(t, y):
    return y[0]-0.1


if __name__ == '__main__':
    event.terminal = True
    sol = solve_ivp(funct, t_span=[0, 3], y0=[1], events=event)

In this example, the solver overshoots the event and calls funct with y < 0. As one can expect, funct raises a warning and returns NaN. In this specific example, solve_ivp recovers and a solution is still found. However, my real funct uses a third-party package that raises an error when funct is evaluated at an invalid argument, and solve_ivp fails.

Now, I know that the event is computed via an iterative method, so my question would be: is it possible for solve_ivp to detect whether the value of y is going below a given threshold and avoid the error/warning? So, something like "if y < 0 then reject the step" or something similar?

2

There are 2 best solutions below

0
Matt Haberland On

IIUC, the problem here is that funct gets called with y=[0.14553212] (before the event) and y=[-0.01227461] (after the event) in successive iterations because the step size is too large. In this MRE, funct returns NaN when y is negative, and solve_ivp is able to recover, find the event, terminate, and return the solution up until the event. In your real code, however, funct raises an error when called with invalid input, so solve_ivp is not able to recover.

How about wrapping funct, detecting the condition that causes the error, and returning a reasonable value (that won't change the solution) rather than calling funct? Alternatively, try calling funct, except return some reasonable value if an error gets raised?

def wrapped(t, y):
    # alternatively, `try` and `except` if `funct` raises an error
    if y[0] <= 0:
        return [0]  # or maybe NaN; since that works in this example
    return funct(t, y)

sol = solve_ivp(wrapped, t_span=[0, 3], y0=[1], events=event)
sol  # no warning is raised

#  message: A termination event occurred.
#  success: True
#   status: 1
#        t: [ 0.000e+00  1.000e-01  9.784e-01  1.368e+00]
#        y: [[ 1.000e+00  9.025e-01  2.610e-01  1.000e-01]]
#      sol: None
# t_events: [array([ 1.368e+00])]
# y_events: [array([[ 1.000e-01]])]
#     nfev: 32
#     njev: 0
#      nlu: 0

If this doesn't work for some reason, you can probably "reject the step" and try a smaller step if you're willing to use the OdeSolver objects directly as solve_ivp does. But no, solve_ivp doesn't have a mechanism to implement that logic.

1
Technonews On

In addressing the query regarding handling negative values of � y during the iteration process in event handling within the context of solve_ivp function from scipy.integrate module, it's crucial to explore methods to prevent the occurrence of these negative values to avoid errors or warnings. By discussing strategies to circumvent this issue, we aim to ensure smooth execution of third-party packages reliant on solve_ivp and enhance the robustness of numerical computations involving differential equations.

One effective approach to mitigate negative values of � y during iterations is by employing a custom event handler that halts the iteration when � y approaches zero from the negative side. By implementing a mechanism to reject steps when y falls below a specified threshold, we can prevent the occurrence of errors or warnings caused by negative values. Let's delve into the implementation details and explore its advantages through examples and insights.

> 
> import numpy as np from scipy.integrate import solve_ivp def funct(t,
> y):
>     return -np.sqrt(y) def event(t, y):
>     return y[0] - 0.1 def custom_event(t, y):
>     return y[0] + 1e-6  # Threshold to avoid negative values if __name__ == '__main__':
>     custom_event.terminal = True
>     sol = solve_ivp(funct, t_span=[0, 3], y0=[1], events=custom_event)

In this modified version of the code, we introduce a custom_event function that acts as a modified event handler. Instead of directly comparing y to zero, we set a small positive threshold (in this case, 1×10−6 1×10−6 ) to ensure that the iteration halts when y approaches zero from the negative side, effectively preventing negative values. By adjusting the threshold, we can fine-tune the sensitivity of the event detection mechanism to suit specific requirements.

Implementing a custom event handler offers several advantages. Firstly, it provides greater control over the event detection process, allowing for tailored solutions to handle specific scenarios such as avoiding negative values of y. This flexibility enhances the robustness of numerical computations and mitigates potential errors or warnings arising from unexpected behavior during iteration.

Moreover, custom event handlers empower users to incorporate domain-specific knowledge into the event detection mechanism, enabling more intelligent decision-making during iteration. By setting appropriate thresholds or conditions based on the characteristics of the problem domain, users can ensure the reliability and accuracy of the numerical solution while avoiding undesirable outcomes such as negative values.

Furthermore, by proactively addressing potential issues such as negative values of y during iteration, custom event handling contributes to the overall efficiency and stability of numerical computations. By preventing unnecessary iterations or errors, it streamlines the computational process and improves the performance of algorithms reliant on solve_ivp function, thereby facilitating smoother execution of scientific simulations and analyses.

Overall, leveraging custom event handlers to prevent negative values of y during iteration in event handling offers a robust and flexible solution to enhance the reliability, accuracy, and efficiency of numerical computations involving differential equations. By incorporating domain-specific knowledge and fine-tuning event detection mechanisms, users can ensure the smooth execution of third-party packages and optimize the performance of scientific simulations and analyses.