def _integrate_backward(self, q, y_of_t, normA, normB, i0, k_ab4, dt_ab4): """ Use AB4 to integrate backward in time, starting at index i0. k_ab4 is [dydt(i0 + 3), dydt(i0 + 2), dydt(i0 + 1)] dt_ab4 is [t(i0 + 3) - t(i0 + 2), t(i0 + 2) - t(i0 + 1), t(i0 + 1) - t(i0)] """ if i0 > len(self.t) - 7: raise Exception("i0 must be <= len(self.t) - 7") # Setup AB4 k1, k2, k3 = k_ab4 dt1, dt2, dt3 = dt_ab4 # Setup dt array, removing the half steps dt_array = np.append(2 * self.diff_t[:6:2], self.diff_t[6:]) for i_output in range(i0)[::-1]: node_index = i_output + 4 if i_output < 2: node_index = 2 + 2 * i_output dt4 = dt_array[i_output] k4 = self.get_time_deriv_from_index(node_index, q, y_of_t[i_output + 1]) ynext = y_of_t[i_output + 1] - _utils.ab4_dy( k1, k2, k3, k4, dt1, dt2, dt3, dt4) y_of_t[i_output] = _utils.normalize_y(ynext, normA, normB) # Setup for next iteration k1, k2, k3 = k2, k3, k4 dt1, dt2, dt3 = dt2, dt3, dt4 return y_of_t
def _integrate_forward(self, q, y_of_t, normA, normB, i0, k_ab4, dt_ab4): """ Use AB4 to integrate forward in time, starting at index i0. i0 refers to the index of y_of_t, which should be the latest index at which we already have the solution; typically i0=3 after three steps of RK4. k_ab4 is [dydt(i0 - 3), dydt(i0 - 2), dydt(i0 - 1)] dt_ab4 is [t(i0 - 2) - t(i0 - 3), t(i0 - 1) - t(i0 - 2), t(i0) - t(i0 - 1)] where for both k_ab4 and dt_ab4 the indices correspond to y_of_t nodes and skip fractional nodes. """ if i0 < 3: raise Exception("i0 must be at least 3!") # Setup AB4 k1, k2, k3 = k_ab4 dt1, dt2, dt3 = dt_ab4 # Run AB4 (i0+3 due to 3 half time steps) for i, dt4 in enumerate(self.diff_t[i0 + 3:]): i_output = i0 + i k4 = self.get_time_deriv_from_index(i_output + 3, q, y_of_t[i_output]) ynext = y_of_t[i_output] + _utils.ab4_dy(k1, k2, k3, k4, dt1, dt2, dt3, dt4) y_of_t[i_output + 1] = _utils.normalize_y(ynext, normA, normB) # Setup for next iteration k1, k2, k3 = k2, k3, k4 dt1, dt2, dt3 = dt2, dt3, dt4 return y_of_t