There has a lot been written on this, so you might want to just read the docs on it.
https://diffeq.sciml.ai/stable/basics/common_solver_opts/#Miscellaneous
isoutofdomain
: Specifies a functionisoutofdomain(u,p,t)
where, when it returns true, it will reject the timestep. Disabled by default.
https://diffeq.sciml.ai/stable/features/callback_library/#PositiveDomain
If these “fail”, see
https://diffeq.sciml.ai/stable/basics/faq see " My ODE goes negative but should stay positive, what tools can help?".
Also,