|
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