Take an arbitrary Runge-Kutta step and estimate error. Args: func: Function to evaluate like `func(y, t)` to compute the time derivative of `y`. y0: Tensor initial value for the state. f0: Tensor initial value for the derivative, computed from `func(y0, t0)`. t0: float64 sca
(func,
y0,
f0,
t0,
dt,
tableau=_DORMAND_PRINCE_TABLEAU,
name=None)
| 84 | |
| 85 | |
| 86 | def _runge_kutta_step(func, |
| 87 | y0, |
| 88 | f0, |
| 89 | t0, |
| 90 | dt, |
| 91 | tableau=_DORMAND_PRINCE_TABLEAU, |
| 92 | name=None): |
| 93 | """Take an arbitrary Runge-Kutta step and estimate error. |
| 94 | |
| 95 | Args: |
| 96 | func: Function to evaluate like `func(y, t)` to compute the time derivative |
| 97 | of `y`. |
| 98 | y0: Tensor initial value for the state. |
| 99 | f0: Tensor initial value for the derivative, computed from `func(y0, t0)`. |
| 100 | t0: float64 scalar Tensor giving the initial time. |
| 101 | dt: float64 scalar Tensor giving the size of the desired time step. |
| 102 | tableau: optional _ButcherTableau describing how to take the Runge-Kutta |
| 103 | step. |
| 104 | name: optional name for the operation. |
| 105 | |
| 106 | Returns: |
| 107 | Tuple `(y1, f1, y1_error, k)` giving the estimated function value after |
| 108 | the Runge-Kutta step at `t1 = t0 + dt`, the derivative of the state at `t1`, |
| 109 | estimated error at `t1`, and a list of Runge-Kutta coefficients `k` used for |
| 110 | calculating these terms. |
| 111 | """ |
| 112 | with ops.name_scope(name, 'runge_kutta_step', [y0, f0, t0, dt]) as scope: |
| 113 | y0 = ops.convert_to_tensor(y0, name='y0') |
| 114 | f0 = ops.convert_to_tensor(f0, name='f0') |
| 115 | t0 = ops.convert_to_tensor(t0, name='t0') |
| 116 | dt = ops.convert_to_tensor(dt, name='dt') |
| 117 | dt_cast = math_ops.cast(dt, y0.dtype) |
| 118 | |
| 119 | k = [f0] |
| 120 | for alpha_i, beta_i in zip(tableau.alpha, tableau.beta): |
| 121 | ti = t0 + alpha_i * dt |
| 122 | yi = y0 + _scaled_dot_product(dt_cast, beta_i, k) |
| 123 | k.append(func(yi, ti)) |
| 124 | |
| 125 | if not (tableau.c_sol[-1] == 0 and tableau.c_sol[:-1] == tableau.beta[-1]): |
| 126 | # This property (true for Dormand-Prince) lets us save a few FLOPs. |
| 127 | yi = y0 + _scaled_dot_product(dt_cast, tableau.c_sol, k) |
| 128 | |
| 129 | y1 = array_ops.identity(yi, name='%s/y1' % scope) |
| 130 | f1 = array_ops.identity(k[-1], name='%s/f1' % scope) |
| 131 | y1_error = _scaled_dot_product( |
| 132 | dt_cast, tableau.c_error, k, name='%s/y1_error' % scope) |
| 133 | return (y1, f1, y1_error, k) |
| 134 | |
| 135 | |
| 136 | def _interp_fit(y0, y1, y_mid, f0, f1, dt): |
no test coverage detected