|
10 | 10 | # de Swart proposes 0.067 for s=3.
|
11 | 11 | KAPPA = 1 # factor of the smooth limiter
|
12 | 12 |
|
13 |
| -# UNKNOWN_VELOCITIES = False |
14 |
| -UNKNOWN_VELOCITIES = True |
15 |
| - |
16 | 13 |
|
17 | 14 | def butcher_tableau(s):
|
18 | 15 | """
|
@@ -133,112 +130,7 @@ def radau_constants(s):
|
133 | 130 | return A, A_inv, c, T, TI, P, P2, b_hat1_implicit, v_implicit, v_explicit, MU_REAL, MU_COMPLEX, b_hat_implicit, b_hat_explicit, p
|
134 | 131 |
|
135 | 132 |
|
136 |
| -def solve_collocation_system_Z(fun, t, y, h, Z0, scale, tol, |
137 |
| - LU_real, LU_complex, solve_lu, |
138 |
| - C, T, TI, A, A_inv, newton_max_iter): |
139 |
| - """Solve the collocation system. |
140 |
| -
|
141 |
| - Parameters |
142 |
| - ---------- |
143 |
| - fun : callable |
144 |
| - Right-hand side of the system. |
145 |
| - t : float |
146 |
| - Current time. |
147 |
| - y : ndarray, shape (n,) |
148 |
| - Current state. |
149 |
| - h : float |
150 |
| - Step to try. |
151 |
| - Z0 : ndarray, shape (s, n) |
152 |
| - Initial guess for the solution. It determines new values of `y` at |
153 |
| - ``t + h * C`` as ``y + Z0``, where ``C`` is the Radau method constants. |
154 |
| - scale : ndarray, shape (n) |
155 |
| - Problem tolerance scale, i.e. ``rtol * abs(y) + atol``. |
156 |
| - tol : float |
157 |
| - Tolerance to which solve the system. This value is compared with |
158 |
| - the normalized by `scale` error. |
159 |
| - LU_real, LU_complex |
160 |
| - LU decompositions of the system Jacobians. |
161 |
| - solve_lu : callable |
162 |
| - Callable which solves a linear system given a LU decomposition. The |
163 |
| - signature is ``solve_lu(LU, b)``. |
164 |
| - C : ndarray, shape (s,) |
165 |
| - Array containing the Radau IIA nodes. |
166 |
| - T, TI : ndarray, shape (s, s) |
167 |
| - Transformation matrix and inverse of the methods coefficient matrix A. |
168 |
| - A_inv : ndarray, shape (s, s) |
169 |
| - Inverse the methods coefficient matrix A. |
170 |
| -
|
171 |
| - Returns |
172 |
| - ------- |
173 |
| - converged : bool |
174 |
| - Whether iterations converged. |
175 |
| - n_iter : int |
176 |
| - Number of completed iterations. |
177 |
| - Z : ndarray, shape (3, n) |
178 |
| - Found solution. |
179 |
| - rate : float |
180 |
| - The rate of convergence. |
181 |
| - """ |
182 |
| - s, n = Z0.shape |
183 |
| - ncs = s // 2 |
184 |
| - tau = t + h * C |
185 |
| - |
186 |
| - Z = Z0 |
187 |
| - W = TI.dot(Z0) |
188 |
| - Yp = (A_inv / h) @ Z |
189 |
| - Y = y + Z |
190 |
| - |
191 |
| - F = np.empty((s, n)) |
192 |
| - |
193 |
| - dW_norm_old = None |
194 |
| - dW = np.empty_like(W) |
195 |
| - converged = False |
196 |
| - rate = None |
197 |
| - for k in range(newton_max_iter): |
198 |
| - for i in range(s): |
199 |
| - F[i] = fun(tau[i], Y[i], Yp[i]) |
200 |
| - |
201 |
| - if not np.all(np.isfinite(F)): |
202 |
| - break |
203 |
| - |
204 |
| - U = TI @ F |
205 |
| - f_real = -U[0] |
206 |
| - f_complex = np.empty((ncs, n), dtype=complex) |
207 |
| - for i in range(ncs): |
208 |
| - f_complex[i] = -(U[2 * i + 1] + 1j * U[2 * i + 2]) |
209 |
| - |
210 |
| - dW_real = solve_lu(LU_real, f_real) |
211 |
| - dW_complex = np.empty_like(f_complex) |
212 |
| - for i in range(ncs): |
213 |
| - dW_complex[i] = solve_lu(LU_complex[i], f_complex[i]) |
214 |
| - |
215 |
| - dW[0] = dW_real |
216 |
| - for i in range(ncs): |
217 |
| - dW[2 * i + 1] = dW_complex[i].real |
218 |
| - dW[2 * i + 2] = dW_complex[i].imag |
219 |
| - |
220 |
| - dW_norm = norm(dW / scale) |
221 |
| - if dW_norm_old is not None: |
222 |
| - rate = dW_norm / dW_norm_old |
223 |
| - |
224 |
| - if (rate is not None and (rate >= 1 or rate ** (newton_max_iter - k) / (1 - rate) * dW_norm > tol)): |
225 |
| - break |
226 |
| - |
227 |
| - W += dW |
228 |
| - Z = T.dot(W) |
229 |
| - Yp = (A_inv / h) @ Z |
230 |
| - Y = y + Z |
231 |
| - |
232 |
| - if (dW_norm == 0 or rate is not None and rate / (1 - rate) * dW_norm < tol): |
233 |
| - converged = True |
234 |
| - break |
235 |
| - |
236 |
| - dW_norm_old = dW_norm |
237 |
| - |
238 |
| - return converged, k + 1, Y, Yp, Z, rate |
239 |
| - |
240 |
| - |
241 |
| -def solve_collocation_system_Yp(fun, t, y, h, Yp0, scale, tol, |
| 133 | +def solve_collocation_system(fun, t, y, h, Yp0, scale, tol, |
242 | 134 | LU_real, LU_complex, solve_lu,
|
243 | 135 | C, T, TI, A, newton_max_iter):
|
244 | 136 | s, n = Yp0.shape
|
@@ -629,43 +521,27 @@ def _step_impl(self):
|
629 | 521 | h_abs = np.abs(h)
|
630 | 522 |
|
631 | 523 | if self.sol is None:
|
632 |
| - if UNKNOWN_VELOCITIES: |
633 |
| - Yp0 = np.tile(yp, s).reshape(s, -1) |
634 |
| - else: |
635 |
| - Z0 = np.zeros((s, y.shape[0])) |
| 524 | + Yp0 = np.tile(yp, s).reshape(s, -1) |
636 | 525 | else:
|
637 |
| - if UNKNOWN_VELOCITIES: |
638 |
| - # note: this only works when we extrapolate the derivative |
639 |
| - # of the collocation polynomial but do not use the sth order |
640 |
| - # collocation polynomial for the derivatives as well. |
641 |
| - Yp0 = self.sol(t + h * C)[1].T |
642 |
| - # # Zp0 = self.sol(t + h * C)[1].T - yp |
643 |
| - # Z0 = self.sol(t + h * C)[0].T - y |
644 |
| - # Yp0 = (1 / h) * A_inv @ Z0 |
645 |
| - else: |
646 |
| - Z0 = self.sol(t + h * C)[0].T - y |
| 526 | + # note: this only works when we extrapolate the derivative |
| 527 | + # of the collocation polynomial but do not use the sth order |
| 528 | + # collocation polynomial for the derivatives as well. |
| 529 | + Yp0 = self.sol(t + h * C)[1].T |
| 530 | + # # Zp0 = self.sol(t + h * C)[1].T - yp |
| 531 | + # Z0 = self.sol(t + h * C)[0].T - y |
| 532 | + # Yp0 = (1 / h) * A_inv @ Z0 |
647 | 533 | scale = atol + np.abs(y) * rtol
|
648 | 534 |
|
649 | 535 | converged = False
|
650 | 536 | while not converged:
|
651 | 537 | if LU_real is None or LU_complex is None:
|
652 |
| - if UNKNOWN_VELOCITIES: |
653 |
| - LU_real = self.lu(Jyp + h * MU_REAL * Jy) |
654 |
| - LU_complex = [self.lu(Jyp + h * MU * Jy) for MU in MU_COMPLEX] |
655 |
| - else: |
656 |
| - LU_real = self.lu(1 / (MU_REAL * h) * Jyp + Jy) |
657 |
| - LU_complex = [self.lu(1 / (MU * h) * Jyp + Jy) for MU in MU_COMPLEX] |
658 |
| - |
659 |
| - if UNKNOWN_VELOCITIES: |
660 |
| - converged, n_iter, Y, Yp, Z, rate = solve_collocation_system_Yp( |
661 |
| - self.fun, t, y, h, Yp0, scale, newton_tol, |
662 |
| - LU_real, LU_complex, self.solve_lu, |
663 |
| - C, T, TI, A, newton_max_iter) |
664 |
| - else: |
665 |
| - converged, n_iter, Y, Yp, Z, rate = solve_collocation_system_Z( |
666 |
| - self.fun, t, y, h, Z0, scale, newton_tol, |
667 |
| - LU_real, LU_complex, self.solve_lu, |
668 |
| - C, T, TI, A, A_inv, newton_max_iter) |
| 538 | + LU_real = self.lu(Jyp + h * MU_REAL * Jy) |
| 539 | + LU_complex = [self.lu(Jyp + h * MU * Jy) for MU in MU_COMPLEX] |
| 540 | + |
| 541 | + converged, n_iter, Y, Yp, Z, rate = solve_collocation_system( |
| 542 | + self.fun, t, y, h, Yp0, scale, newton_tol, |
| 543 | + LU_real, LU_complex, self.solve_lu, |
| 544 | + C, T, TI, A, newton_max_iter) |
669 | 545 |
|
670 | 546 | if not converged:
|
671 | 547 | if current_jac:
|
@@ -699,21 +575,15 @@ def _step_impl(self):
|
699 | 575 | # R(z) = b_hat1 / b_hats2 = DAMPING_RATIO_ERROR_ESTIMATE for z -> oo
|
700 | 576 | yp_hat_new = (v_implicit @ Yp - b_hat1_implicit * yp) / MU_REAL
|
701 | 577 | F = self.fun(t_new, y_new, yp_hat_new)
|
702 |
| - if UNKNOWN_VELOCITIES: |
703 |
| - error_embedded = -h * MU_REAL * self.solve_lu(LU_real, F) |
704 |
| - else: |
705 |
| - error_embedded = -self.solve_lu(LU_real, F) |
| 578 | + error_embedded = -h * MU_REAL * self.solve_lu(LU_real, F) |
706 | 579 | else:
|
707 | 580 | # compute implicit embedded method with `newton_iter_embedded` iterations
|
708 | 581 | yp_hat_new0 = -(y / h + b_hat1_implicit * yp + self.b_hat_implicit @ Yp) / MU_REAL
|
709 | 582 | y_hat_new = y_new.copy() # initial guess
|
710 | 583 | for _ in range(self.newton_iter_embedded):
|
711 | 584 | yp_hat_new = yp_hat_new0 + y_hat_new / (h * MU_REAL)
|
712 | 585 | F = self.fun(t_new, y_hat_new, yp_hat_new)
|
713 |
| - if UNKNOWN_VELOCITIES: |
714 |
| - y_hat_new -= h * MU_REAL * self.solve_lu(LU_real, F) |
715 |
| - else: |
716 |
| - y_hat_new -= self.solve_lu(LU_real, F) |
| 586 | + y_hat_new -= h * MU_REAL * self.solve_lu(LU_real, F) |
717 | 587 |
|
718 | 588 | error_embedded = y_hat_new - y_new
|
719 | 589 |
|
|
0 commit comments