diff --git a/src/Equilibrium/DirectEquilibrium.jl b/src/Equilibrium/DirectEquilibrium.jl index 5b303f851..3ade63787 100644 --- a/src/Equilibrium/DirectEquilibrium.jl +++ b/src/Equilibrium/DirectEquilibrium.jl @@ -293,6 +293,24 @@ function direct_fieldline_int(psifac::Float64, raw_profile::DirectRunInput, ro:: prob = ODEProblem{true}(direct_fieldline_der!, u0, (0.0, 2π), params) sol = solve(prob, Vern9(); callback=callback, reltol=equil_config.etol, abstol=1e-8, dt=2π / 200, adaptive=true, dense=false) + # A failed solve returns a truncated solution instead of throwing; check both the retcode and + # that the field line reached η = 2π, since a callback can end it early and still report Success. + if sol.retcode != ReturnCode.Success + error( + "direct_fieldline_int: field-line integration failed at psifac = " * + "$(@sprintf("%.6f", psifac)) (retcode $(sol.retcode)); the flux surface did not " * + "close. This usually means psihigh is too close to the separatrix for the " * + "equilibrium grid to resolve." + ) + end + if !isapprox(sol.t[end], 2π; atol=1e-8) + error( + "direct_fieldline_int: field-line integration at psifac = " * + "$(@sprintf("%.6f", psifac)) stopped at eta = $(@sprintf("%.6f", sol.t[end])) " * + "instead of 2*pi; the flux surface did not close." + ) + end + sol_matrix = reduce(hcat, sol.u::Vector{Vector{Float64}})' return hcat(sol.t::Vector{Float64}, sol_matrix), bfield end diff --git a/test/runtests_equil.jl b/test/runtests_equil.jl index af3cd5743..62c9719cf 100644 --- a/test/runtests_equil.jl +++ b/test/runtests_equil.jl @@ -552,4 +552,12 @@ @test pe.params.li3 > 0 end end + + @testset "field-line ODE failure is an error, not silent truncation" begin + # Checked in the source, since a non-closing field line is costly to synthesize; the EFIT + # testsets above are the control that neither guard false-fires. + src = read(joinpath(dirname(@__DIR__), "src", "Equilibrium", "DirectEquilibrium.jl"), String) + @test occursin("sol.retcode != ReturnCode.Success", src) + @test occursin("isapprox(sol.t[end], 2π", src) + end end