Solve an ODE for `odeint` using method='dopri5'.
(func,
y0,
t,
rtol,
atol,
full_output=False,
first_step=None,
safety=0.9,
ifactor=10.0,
dfactor=0.2,
max_num_steps=1000,
name=None)
| 301 | |
| 302 | |
| 303 | def _dopri5(func, |
| 304 | y0, |
| 305 | t, |
| 306 | rtol, |
| 307 | atol, |
| 308 | full_output=False, |
| 309 | first_step=None, |
| 310 | safety=0.9, |
| 311 | ifactor=10.0, |
| 312 | dfactor=0.2, |
| 313 | max_num_steps=1000, |
| 314 | name=None): |
| 315 | """Solve an ODE for `odeint` using method='dopri5'.""" |
| 316 | |
| 317 | if first_step is None: |
| 318 | # at some point, we might want to switch to picking the step size |
| 319 | # automatically |
| 320 | first_step = 1.0 |
| 321 | |
| 322 | with ops.name_scope(name, 'dopri5', [ |
| 323 | y0, t, rtol, atol, safety, ifactor, dfactor, max_num_steps |
| 324 | ]) as scope: |
| 325 | |
| 326 | first_step = ops.convert_to_tensor( |
| 327 | first_step, dtype=t.dtype, name='first_step') |
| 328 | safety = ops.convert_to_tensor(safety, dtype=t.dtype, name='safety') |
| 329 | ifactor = ops.convert_to_tensor(ifactor, dtype=t.dtype, name='ifactor') |
| 330 | dfactor = ops.convert_to_tensor(dfactor, dtype=t.dtype, name='dfactor') |
| 331 | max_num_steps = ops.convert_to_tensor( |
| 332 | max_num_steps, dtype=dtypes.int32, name='max_num_steps') |
| 333 | |
| 334 | def adaptive_runge_kutta_step(rk_state, history, n_steps): |
| 335 | """Take an adaptive Runge-Kutta step to integrate the ODE.""" |
| 336 | y0, f0, _, t0, dt, interp_coeff = rk_state |
| 337 | with ops.name_scope('assertions'): |
| 338 | check_underflow = control_flow_ops.Assert(t0 + dt > t0, |
| 339 | ['underflow in dt', dt]) |
| 340 | check_max_num_steps = control_flow_ops.Assert( |
| 341 | n_steps < max_num_steps, ['max_num_steps exceeded']) |
| 342 | check_numerics = control_flow_ops.Assert( |
| 343 | math_ops.reduce_all(math_ops.is_finite(abs(y0))), |
| 344 | ['non-finite values in state `y`', y0]) |
| 345 | with ops.control_dependencies( |
| 346 | [check_underflow, check_max_num_steps, check_numerics]): |
| 347 | y1, f1, y1_error, k = _runge_kutta_step(func, y0, f0, t0, dt) |
| 348 | |
| 349 | with ops.name_scope('error_ratio'): |
| 350 | # We use the same approach as the dopri5 fortran code. |
| 351 | error_tol = atol + rtol * math_ops.maximum(abs(y0), abs(y1)) |
| 352 | tensor_error_ratio = _abs_square(y1_error) / _abs_square(error_tol) |
| 353 | # Could also use reduce_maximum here. |
| 354 | error_ratio = math_ops.sqrt(math_ops.reduce_mean(tensor_error_ratio)) |
| 355 | accept_step = error_ratio <= 1 |
| 356 | |
| 357 | with ops.name_scope('update/rk_state'): |
| 358 | # If we don't accept the step, the _RungeKuttaState will be useless |
| 359 | # (covering a time-interval of size 0), but that's OK, because in such |
| 360 | # cases we always immediately take another Runge-Kutta step. |
no test coverage detected