@@ -163,21 +163,29 @@ function solve_at_z(eos, p0_ads, T_ads, x0_ads, μ_bulk::M, Ψ::M, alg::A; verbo
163163 f = create_res_func (eos, T_ads, μ_bulk, Ψ)
164164 P_result = Roots. find_zero (x -> to_newton (f, x), p0_ads, Roots. Newton (), abstol = abstol, reltol = reltol, verbose = verbose)
165165 _1 = one (T_ads)
166- return _1/ volume (eos, P_result, T_ads, x0_ads, :stable ), P_result
166+ ρ = _1/ volume (eos, P_result, T_ads, x0_ads, :stable )
167+
168+ # For single component, always return true for convergence (Roots.jl will throw if it doesn't converge)
169+ return ρ, P_result, true
167170end
168171
169172function solve_at_z (eos, p0_ads, T_ads, x0_ads:: M , μ_bulk:: M , Ψ:: M , alg:: A ; verbose = true ) where {M <: AbstractVector , A <: ChemPotentialMethod }
170173 f! = create_res_func (eos, T_ads, μ_bulk, Ψ)
171174 x0 = [p0_ads; x0_ads... ]
172- # δ = similar(x0)
173- # f!(δ, x0)
174175 abstol = alg. abstol
175176 reltol = alg. reltol
176- options = NEqOptions (f_abstol = abstol, f_reltol = reltol, maxiter = 1000 )
177+ options = NEqOptions (f_abstol = abstol, f_reltol = reltol, maxiter = 10_000 )
177178 sol = nlsolve (f!, x0, options = options)
178179 _1 = one (T_ads)
179180 p, x = sol. info. solution[1 ], sol. info. solution[2 : end ]
180- return _1/ volume (eos, p, T_ads, x, :unknown ).* x, p
181+ ρ = _1/ volume (eos, p, T_ads, x, :unknown ).* x
182+
183+ # Check convergence: norm of residual should be small
184+ res_norm = norm (sol. info. best_residual)
185+ converged = res_norm < abstol || res_norm < reltol * norm (sol. info. ρF0)
186+
187+ # Return density, pressure, and convergence flag
188+ return ρ, p, converged
181189end
182190
183191function solve_PTAProblem (prob:: PR , alg:: A ; verbose = true ) where {PR <: PTAProblem , A <: ChemPotentialMethod }
@@ -194,7 +202,16 @@ function solve_PTAProblem(prob::PR, alg::A; verbose = true) where {PR <: PTAProb
194202 for i ∈ reverse (eachindex (sol. z))
195203 z = sol. z[i]
196204 Ψ = potential (_potential, z)
197- ρᵢ, Pᵢ = solve_at_z (eos, Pᵢ, T, xᵢ, μ_bulk, Ψ, alg, verbose = false )
205+ ρᵢ, Pᵢ, converged = solve_at_z (eos, Pᵢ, T, xᵢ, μ_bulk, Ψ, alg, verbose = false )
206+
207+ # Warn if not converged - indicates potential issue with solution at this point
208+ # Note: ChemPotentialMethod can converge to incorrect solutions at very high potentials
209+ # (near the wall) when using previous point as initial guess. FugacityCoefficientMethod
210+ # is more robust for such cases.
211+ if ! converged && verbose
212+ @warn " solve_at_z did not converge at i=$i (z=$z , Ψ=$Ψ ). Solution at this point may be inaccurate."
213+ end
214+
198215 xᵢ = ρᵢ ./ sum (ρᵢ)
199216 sol. ρ[i, :] .= ρᵢ
200217 sol. P[i, 1 ] = Pᵢ
@@ -234,7 +251,7 @@ mutable struct FugacityCoefficientMethod{T <: Real}
234251end
235252
236253function FugacityCoefficientMethod (; abstol= 1e-7 , reltol= 1e-7 ,
237- maxiter_outer= 50 , maxiter_inner= 10 ,
254+ maxiter_outer= 150 , maxiter_inner= 100 ,
238255 x0= nothing , detect_phase_transition= false )
239256 FugacityCoefficientMethod (abstol, reltol, maxiter_outer, maxiter_inner,
240257 x0, detect_phase_transition)
0 commit comments