Getting results until the point of nonconvergence in DAE system

Hello,
I’m trying to simulate a DAE system with Sundials IDA solver. I implemented my controlvector with callbacks and it works just fine. However, depending on the controls I run into infeasible regions and the solver does not converge (which is expected and desired). My problem is, that I can not figure out how to save the results up until that point.
I tried try-catch, but solve only returns the final result, so the catch part never comes into play.
Is there any kwarg I’m missing?
I guess I could get the timepoint of non-convergence and run the simulation until that point again, but that seems very inefficient.

Thank you in advance!

SOL = nothing
try
    SOL = solve(DAE_Problem, IDA(), callback=cb, tstops=timevector; saveat=0.01)
    save_results(SOL, variables_name)
    println("Simulation completed successfully")
catch e
    @warn "Error during simulation: $(e)"
    if SOL !== nothing
        @warn "Partial results available with return code: $(SOL.retcode)"
        save_results(SOL, variables_name)
    end
end

If you don’t use saveat and instead let it save adaptively then it’ll save every point and you can use the interpolation afterwards to get it in 0.1 increments and also have the final time it was at

thank you for the fast response.
The problem is, that solve throws an error, and does not return any results.

I change the controls every 10 seconds, and say after 39 s the system becomes unsolvable. IDA throws an error and does not save anything. I want to access the trajectories until that point.

Cheers

What error is being thrown?

The error is:

ERROR: LoadError: DomainError with -3.0253720071336128:
Exponentiation yielding a complex result requires a complex argument.

This error is not surprising. The model has an implicit region of feasibility, so the solver does not converge, when it is left. There is no physical solution to the problem at some point in time.
I’m interested in the trajectories of the state variables up until that point.

To illustrate:
Imagine a dynamic tank of water, where the control variable defines the outlet flow. Once the tank is empty, it doesn’t make any sense to have an outlet flow anymore. However, up until that point, the trajectories hold valuable information, which I want to access.

I just found SavingCallback and think it might solve my problem.

Instead of ^, use NaNMath.^ so it NaNs instead of errors.

1 Like

This didn’t work for me. But that might be my mistake.

Anyways, I solved the issue with the following code. It’s probably inefficient to always halt the integrator, but it’s still fast enough for me.

timevector_savetimes = collect(t_start:0.1:t_end)
saved_data = Vector{Tuple{Float64,Float64}}()

function save_affect!(integrator)
    t = integrator.t
    u1 = integrator.u[1]
    push!(saved_data, (t, u1))
    return nothing
end

save_cb = PresetTimeCallback(timevector_savetimes, save_affect!)

SOL = solve(DAE_Problem, IDA(), callback=CallbackSet(cb, save_cb), tstops=timevector_savetimes[1:end])

Did you add the NaNMath.jl package and import it?