Integration speed
Here is a pyinstrument profile of make_jump(). It looks like SciPy's rk_step() function is one of the bottlenecks and should be easy to speed up.
In [2]: from safeskijump.functions import make_jump
In [3]: from pyinstrument import Profiler; profiler = Profiler(); profiler.start(); make_jump(-30, 0.0, 30.0, 20.0, 0.5); profiler.stop()
/home/moorepants/miniconda3/envs/safeskijump/lib/python3.6/site-packages/numpy/lib/function_base.py:1772: RuntimeWarning: divide by zero encountered in true_divide
a = -(dx2)/(dx1 * (dx1 + dx2))
/home/moorepants/miniconda3/envs/safeskijump/lib/python3.6/site-packages/numpy/lib/function_base.py:1773: RuntimeWarning: divide by zero encountered in true_divide
b = (dx2 - dx1) / (dx1 * dx2)
/home/moorepants/miniconda3/envs/safeskijump/lib/python3.6/site-packages/numpy/lib/function_base.py:1774: RuntimeWarning: divide by zero encountered in true_divide
c = dx1 / (dx2 * (dx1 + dx2))
/home/moorepants/miniconda3/envs/safeskijump/lib/python3.6/site-packages/numpy/lib/function_base.py:1780: RuntimeWarning: invalid value encountered in add
out[slice1] = a * f[slice2] + b * f[slice3] + c * f[slice4]
INFO:root:Integrating...
INFO:root:Integrating done.
In [4]: print(profiler.output_text(unicode=True, color=True))
1.655 make_jump safeskijump/functions.py:9
├─ 1.599 __init__ safeskijump/classes.py:566
│ └─ 1.599 create_safe_surface safeskijump/classes.py:600
│ └─ 1.594 solve_ivp scipy/integrate/_ivp/ivp.py:157
│ └─ 1.580 step scipy/integrate/_ivp/base.py:160
│ └─ 1.579 _step_impl scipy/integrate/_ivp/rk.py:105
│ └─ 1.577 rk_step scipy/integrate/_ivp/rk.py:15
│ └─ 1.567 fun scipy/integrate/_ivp/base.py:137
│ └─ 1.566 fun_wrapped scipy/integrate/_ivp/base.py:20
│ └─ 1.566 rhs safeskijump/classes.py:602
│ └─ 1.550 speed_to_land_at safeskijump/classes.py:875
│ ├─ 1.441 fly_to safeskijump/classes.py:747
│ │ ├─ 1.408 solve_ivp scipy/integrate/_ivp/ivp.py:157
│ │ │ ├─ 0.581 step scipy/integrate/_ivp/base.py:160
│ │ │ │ └─ 0.564 _step_impl scipy/integrate/_ivp/rk.py:105
│ │ │ │ ├─ 0.411 rk_step scipy/integrate/_ivp/rk.py:15
│ │ │ │ │ └─ 0.171 fun scipy/integrate/_ivp/base.py:137
│ │ │ │ │ └─ 0.151 fun_wrapped scipy/integrate/_ivp/base.py:20
│ │ │ │ │ ├─ 0.079 asarray numpy/core/numeric.py:463
│ │ │ │ │ └─ 0.061 rhs safeskijump/classes.py:772
│ │ │ │ │ └─ 0.028 drag_force safeskijump/classes.py:716
│ │ │ │ └─ 0.047 norm scipy/integrate/_ivp/common.py:51
│ │ │ │ └─ 0.034 norm numpy/linalg/linalg.py:2014
│ │ │ ├─ 0.275 handle_events scipy/integrate/_ivp/ivp.py:81
│ │ │ │ └─ 0.246 solve_event_equation scipy/integrate/_ivp/ivp.py:53
│ │ │ │ └─ 0.240 brentq scipy/optimize/zeros.py:395
│ │ │ │ └─ 0.239 <lambda> scipy/integrate/_ivp/ivp.py:77
│ │ │ │ └─ 0.215 __call__ scipy/integrate/_ivp/base.py:236
│ │ │ │ └─ 0.195 _call_impl scipy/integrate/_ivp/rk.py:366
│ │ │ │ ├─ 0.088 tile numpy/lib/shape_base.py:826
│ │ │ │ └─ 0.024 cumprod numpy/core/fromnumeric.py:2521
│ │ │ │ └─ 0.022 _wrapfunc numpy/core/fromnumeric.py:55
│ │ │ ├─ 0.191 __init__ scipy/integrate/_ivp/rk.py:91
│ │ │ │ ├─ 0.102 select_initial_step scipy/integrate/_ivp/common.py:56
│ │ │ │ │ └─ 0.059 norm scipy/integrate/_ivp/common.py:51
│ │ │ │ │ └─ 0.044 norm numpy/linalg/linalg.py:2014
│ │ │ │ ├─ 0.043 __init__ scipy/integrate/_ivp/base.py:116
│ │ │ │ │ └─ 0.026 check_arguments scipy/integrate/_ivp/base.py:5
│ │ │ │ ├─ 0.021 validate_tol scipy/integrate/_ivp/common.py:35
│ │ │ │ └─ 0.017 fun scipy/integrate/_ivp/base.py:137
│ │ │ ├─ 0.130 __call__ scipy/integrate/_ivp/base.py:236
│ │ │ │ └─ 0.121 _call_impl scipy/integrate/_ivp/rk.py:366
│ │ │ │ ├─ 0.042 tile numpy/lib/shape_base.py:826
│ │ │ │ └─ 0.029 cumprod numpy/core/fromnumeric.py:2521
│ │ │ │ └─ 0.027 _wrapfunc numpy/core/fromnumeric.py:55
│ │ │ ├─ 0.062 find_active_events scipy/integrate/_ivp/ivp.py:131
│ │ │ ├─ 0.023 dense_output scipy/integrate/_ivp/base.py:193
│ │ │ │ └─ 0.022 _dense_output_impl scipy/integrate/_ivp/rk.py:161
│ │ │ └─ 0.020 any numpy/core/fromnumeric.py:1886
│ │ └─ 0.021 linspace numpy/core/function_base.py:25
│ ├─ 0.049 __init__ scipy/interpolate/interpolate.py:427
│ └─ 0.039 __call__ scipy/interpolate/polyint.py:62
│ └─ 0.018 _evaluate scipy/interpolate/interpolate.py:627
└─ 0.031 end_speed_on safeskijump/classes.py:858
└─ 0.031 slide_on safeskijump/classes.py:807
└─ 0.031 solve_ivp scipy/integrate/_ivp/ivp.py:157
└─ 0.023 step scipy/integrate/_ivp/base.py:160
└─ 0.023 _step_impl scipy/integrate/_ivp/rk.py:105
└─ 0.019 rk_step scipy/integrate/_ivp/rk.py:15
└─ 0.018 fun scipy/integrate/_ivp/base.py:137
└─ 0.018 fun_wrapped scipy/integrate/_ivp/base.py:20
└─ 0.017 rhs safeskijump/classes.py:820