|
861 | 861 |
|
862 | 862 | Main iteration loop for calculating circulation distribution. |
863 | 863 |
|
| 864 | +The NONLIN solver is a Newton iteration on the fixed-point residual |
| 865 | +`F(gamma) - gamma` with a finite-difference Jacobian, backtracking along each step |
| 866 | +until it reduces the residual. |
| 867 | +
|
864 | 868 | When `solver.is_with_artificial_viscosity` is set, the LOOP solver replaces the |
865 | 869 | explicit target `F(gamma)` with the implicit Li/Gaunaa solution |
866 | 870 | `(I - diag(mu) L) gamma = F(gamma)` before relaxation, stabilizing post-stall |
@@ -960,35 +964,45 @@ function gamma_loop!( |
960 | 964 |
|
961 | 965 | _, _, info = LinearAlgebra.LAPACK.getrf!(jac, ipiv; check=false) |
962 | 966 | info == 0 || break |
| 967 | + residual_norm = maximum(abs, residual) |
963 | 968 | LinearAlgebra.LAPACK.getrs!('N', jac, ipiv, residual) |
964 | 969 |
|
965 | | - max_step = 0.0 |
| 970 | + # Past stall the full Newton step overshoots into a cycle, so take the |
| 971 | + # largest of 1, 1/2 ... 1/64 of it that brings the residual down. |
| 972 | + step_fraction = 1.0 |
| 973 | + for _ in 1:7 |
| 974 | + @inbounds for i in 1:n_panels |
| 975 | + gamma_perturbed[i] = gamma_iter[i] - step_fraction * residual[i] |
| 976 | + end |
| 977 | + update_gamma_candidate!( |
| 978 | + residual_perturbed, gamma_perturbed, solver, panels, n_panels, |
| 979 | + AIC_x, AIC_y, AIC_z, |
| 980 | + velocity_view_x, velocity_view_y, velocity_view_z, |
| 981 | + va_array, induced_velocity_all, relative_velocity_array, |
| 982 | + y_airf_array, relative_velocity_crossz, v_acrossz_array, |
| 983 | + z_airf_array, x_airf_array, |
| 984 | + v_normal_array, v_tangential_array, |
| 985 | + va_magw_array, cl_dist, chord_array, |
| 986 | + ) |
| 987 | + @inbounds for i in 1:n_panels |
| 988 | + residual_perturbed[i] -= gamma_perturbed[i] |
| 989 | + end |
| 990 | + maximum(abs, residual_perturbed) < residual_norm && break |
| 991 | + step_fraction /= 2 |
| 992 | + end |
| 993 | + |
| 994 | + max_step = maximum(abs, residual) |
966 | 995 | ref = solver.tol_reference_error |
967 | 996 | @inbounds for i in 1:n_panels |
968 | | - s = abs(residual[i]) |
969 | | - s > max_step && (max_step = s) |
970 | | - gamma_iter[i] -= residual[i] |
| 997 | + gamma_iter[i] = gamma_perturbed[i] |
| 998 | + residual[i] = residual_perturbed[i] |
971 | 999 | g = abs(gamma_iter[i]) |
972 | 1000 | g > ref && (ref = g) |
973 | 1001 | end |
974 | 1002 | if max_step < solver.atol + solver.rtol * ref |
975 | 1003 | solver.lr.converged = true |
976 | 1004 | break |
977 | 1005 | end |
978 | | - |
979 | | - update_gamma_candidate!( |
980 | | - residual, gamma_iter, solver, panels, n_panels, |
981 | | - AIC_x, AIC_y, AIC_z, |
982 | | - velocity_view_x, velocity_view_y, velocity_view_z, |
983 | | - va_array, induced_velocity_all, relative_velocity_array, |
984 | | - y_airf_array, relative_velocity_crossz, v_acrossz_array, |
985 | | - z_airf_array, x_airf_array, |
986 | | - v_normal_array, v_tangential_array, |
987 | | - va_magw_array, cl_dist, chord_array, |
988 | | - ) |
989 | | - @inbounds for i in 1:n_panels |
990 | | - residual[i] -= gamma_iter[i] |
991 | | - end |
992 | 1006 | end |
993 | 1007 |
|
994 | 1008 | gamma .= gamma_iter |
|
0 commit comments