@@ -141,9 +141,11 @@ sol::VSMSolution = VSMSolution(): The result of calling [solve!](@ref)
141141 relaxation_factor:: Float64 = 0.03
142142
143143 # Nonlin solver fields
144- prob:: Union{NonlinearProblem, Nothing} = nothing
145- nonlin_cache:: Union{NonlinearSolveFirstOrder.GeneralizedFirstOrderAlgorithmCache, Nothing} = nothing
146144 atol:: Float64 = 1e-5
145+ nonlin_jac:: Matrix{Float64} = zeros (P, P)
146+ nonlin_residual:: MVector{P, Float64} = zeros (P)
147+ nonlin_residual_perturbed:: MVector{P, Float64} = zeros (P)
148+ nonlin_gamma_perturbed:: MVector{P, Float64} = zeros (P)
147149
148150 # Damping settings
149151 is_with_artificial_damping:: Bool = false
733735 return nothing
734736end
735737
738+ @inline function lu_solve_inplace! (
739+ A:: AbstractMatrix{Float64} ,
740+ b:: AbstractVector{Float64} ,
741+ n:: Int ,
742+ )
743+ @inbounds for k in 1 : n
744+ amax = abs (A[k, k])
745+ pivot_row = k
746+ for i in (k + 1 ): n
747+ v = abs (A[i, k])
748+ if v > amax
749+ amax = v
750+ pivot_row = i
751+ end
752+ end
753+ amax == 0.0 && return false
754+ if pivot_row != k
755+ for j in 1 : n
756+ tmp = A[k, j]
757+ A[k, j] = A[pivot_row, j]
758+ A[pivot_row, j] = tmp
759+ end
760+ tmp = b[k]
761+ b[k] = b[pivot_row]
762+ b[pivot_row] = tmp
763+ end
764+ inv_pivot = 1.0 / A[k, k]
765+ for i in (k + 1 ): n
766+ factor = A[i, k] * inv_pivot
767+ A[i, k] = factor
768+ for j in (k + 1 ): n
769+ A[i, j] -= factor * A[k, j]
770+ end
771+ b[i] -= factor * b[k]
772+ end
773+ end
774+ @inbounds for k in n: - 1 : 1
775+ s = b[k]
776+ for j in (k + 1 ): n
777+ s -= A[k, j] * b[j]
778+ end
779+ b[k] = s / A[k, k]
780+ end
781+ return true
782+ end
783+
736784"""
737- gamma_loop!(solver::Solver, AIC_x::Matrix{Float64},
785+ gamma_loop!(solver::Solver, AIC_x::Matrix{Float64},
738786 AIC_y::Matrix{Float64}, AIC_z::Matrix{Float64},
739787 panels::Vector{Panel}, relaxation_factor::Float64; log=true)
740788
@@ -778,63 +826,82 @@ function gamma_loop!(
778826 velocity_view_z = @view induced_velocity_all[:, 3 ]
779827
780828 if solver. solver_type == NONLIN
781- prob = solver. prob
782- if isnothing (prob)
783- function f_nonlin! (d_gamma, gamma, _p)
829+ gamma_iter = solver. lr. gamma_new
830+ residual = solver. nonlin_residual
831+ residual_perturbed = solver. nonlin_residual_perturbed
832+ gamma_perturbed = solver. nonlin_gamma_perturbed
833+ jac = solver. nonlin_jac
834+ relstep = sqrt (eps (Float64))
835+ abstep = sqrt (eps (Float64))
836+
837+ solver. lr. converged = false
838+ for iter in 1 : solver. max_iterations
839+ update_gamma_candidate! (
840+ residual, gamma_iter, solver, panels, n_panels,
841+ AIC_x, AIC_y, AIC_z,
842+ velocity_view_x, velocity_view_y, velocity_view_z,
843+ va_array, induced_velocity_all, relative_velocity_array,
844+ y_airf_array, relative_velocity_crossz, v_acrossz_array,
845+ z_airf_array, x_airf_array,
846+ v_normal_array, v_tangential_array,
847+ va_magw_array, cl_dist, chord_array,
848+ )
849+ max_residual = 0.0
850+ @inbounds for i in 1 : n_panels
851+ residual[i] -= gamma_iter[i]
852+ a = abs (residual[i])
853+ a > max_residual && (max_residual = a)
854+ end
855+ if max_residual < solver. atol
856+ solver. lr. converged = true
857+ break
858+ end
859+
860+ @inbounds for j in 1 : n_panels
861+ for i in 1 : n_panels
862+ gamma_perturbed[i] = gamma_iter[i]
863+ end
864+ step = max (abstep, relstep * abs (gamma_iter[j]))
865+ gamma_perturbed[j] += step
784866 update_gamma_candidate! (
785- solver. lr. gamma_new,
786- gamma,
787- solver,
788- panels,
789- n_panels,
790- AIC_x,
791- AIC_y,
792- AIC_z,
793- velocity_view_x,
794- velocity_view_y,
795- velocity_view_z,
796- va_array,
797- induced_velocity_all,
798- relative_velocity_array,
799- y_airf_array,
800- relative_velocity_crossz,
801- v_acrossz_array,
802- z_airf_array,
803- x_airf_array,
804- v_normal_array,
805- v_tangential_array,
806- va_magw_array,
807- cl_dist,
808- chord_array,
867+ residual_perturbed, gamma_perturbed, solver, panels, n_panels,
868+ AIC_x, AIC_y, AIC_z,
869+ velocity_view_x, velocity_view_y, velocity_view_z,
870+ va_array, induced_velocity_all, relative_velocity_array,
871+ y_airf_array, relative_velocity_crossz, v_acrossz_array,
872+ z_airf_array, x_airf_array,
873+ v_normal_array, v_tangential_array,
874+ va_magw_array, cl_dist, chord_array,
809875 )
810- d_gamma .= solver. lr. gamma_new .- gamma
811- nothing
876+ inv_step = 1.0 / step
877+ for i in 1 : n_panels
878+ residual_perturbed[i] -= gamma_perturbed[i]
879+ jac[i, j] = (residual_perturbed[i] - residual[i]) * inv_step
880+ end
881+ end
882+
883+ lu_solve_inplace! (jac, residual, n_panels) || break
884+
885+ @inbounds for i in 1 : n_panels
886+ gamma_iter[i] -= residual[i]
812887 end
813- prob = NonlinearProblem (f_nonlin!, solver. lr. gamma_new, SciMLBase. NullParameters ())
814- solver. prob = prob
815- end
816- prob = prob:: NonlinearProblem
817-
818- nonlin_cache = solver. nonlin_cache
819- if isnothing (nonlin_cache)
820- alg = NewtonRaphson (; autodiff= AutoFiniteDiff ())
821- nonlin_cache = SciMLBase. init (
822- prob,
823- alg;
824- abstol = solver. atol,
825- reltol = solver. rtol,
826- )
827- solver. nonlin_cache = nonlin_cache
828- else
829- SciMLBase. reinit! (
830- nonlin_cache, solver. lr. gamma_new;
831- p= SciMLBase. NullParameters (),
832- )
833888 end
834- sol = NonlinearSolve. solve! (nonlin_cache)
835- gamma .= sol. u
836- solver. lr. gamma_new .= sol. u
837- solver. lr. converged = SciMLBase. successful_retcode (sol)
889+
890+ # Refresh side-effect state (alpha_dist, v_a_dist, cl_dist, ...) at the
891+ # converged iterate; the inner FD loop left them set at the last
892+ # perturbed gamma.
893+ update_gamma_candidate! (
894+ residual, gamma_iter, solver, panels, n_panels,
895+ AIC_x, AIC_y, AIC_z,
896+ velocity_view_x, velocity_view_y, velocity_view_z,
897+ va_array, induced_velocity_all, relative_velocity_array,
898+ y_airf_array, relative_velocity_crossz, v_acrossz_array,
899+ z_airf_array, x_airf_array,
900+ v_normal_array, v_tangential_array,
901+ va_magw_array, cl_dist, chord_array,
902+ )
903+
904+ gamma .= gamma_iter
838905 return nothing
839906 end
840907
0 commit comments