11# ── Phase 3: ODE simulation with DifferentialEquations / MTK ──────────────────
22
3- import DifferentialEquations: solve, Rodas5P, ReturnCode
3+ import DifferentialEquations: init, solve, ReturnCode
4+ import OrdinaryDiffEqBDF
45import Logging
56import ModelingToolkit
67import Printf: @sprintf
78
89"""
910 run_simulate(ode_prob, model_dir, model; cmp_signals, csv_max_size_mb) → (success, time, error, sol)
1011
11- Solve `ode_prob` with Rodas5P (stiff solver). On success, also writes the
12+ Solve `ode_prob` with FBDF (stiff solver). On success, also writes the
1213solution as a CSV file `<Short>_sim.csv` in `model_dir`.
1314Writes a `<model>_sim.log` file in `model_dir`.
1415Returns `nothing` as the fourth element on failure.
@@ -24,17 +25,18 @@ function run_simulate(ode_prob, model_dir::String,
2425 model:: String ;
2526 cmp_signals :: Vector{String} = String[],
2627 csv_max_size_mb:: Int = CSV_MAX_SIZE_MB):: Tuple{Bool,Float64,String,Any}
27- sim_success = false
28- sim_time = 0.0
29- sim_error = " "
30- sol = nothing
28+ sim_success = false
29+ sim_time = 0.0
30+ sim_error = " "
31+ sol = nothing
32+ solver_settings_string = " "
3133
3234 log_file = open (joinpath (model_dir, " $(model) _sim.log" ), " w" )
3335 println (log_file, " Model: $model " )
3436 logger = Logging. SimpleLogger (log_file, Logging. Debug)
3537 t0 = time ()
3638 try
37- # Rodas5P handles stiff DAE-like systems well.
39+ # FBDF handles stiff DAE-like systems and purely algebraic systems well.
3840 # Redirect all library log output (including Symbolics/MTK warnings)
3941 # to the log file so they don't clutter stdout.
4042 sol = Logging. with_logger (logger) do
@@ -46,7 +48,22 @@ function run_simulate(ode_prob, model_dir::String,
4648 saveat = isempty (ModelingToolkit. unknowns (sys)) ?
4749 collect (range (ode_prob. tspan[1 ], ode_prob. tspan[end ]; length = 500 )) :
4850 Float64[]
49- solve (ode_prob, Rodas5P (); saveat = saveat, dense = true )
51+ kwargs = (saveat = saveat, dense = true )
52+
53+ # Log solver settings
54+ initializedSolver = init (ode_prob, OrdinaryDiffEqBDF. FBDF (); kwargs... )
55+ solver_settings_string =
56+ """
57+ OrdinaryDiffEqBDF.FBDF()
58+ saveat: $(let sv = initializedSolver. opts. saveat; isempty (sv) ? " []" : " $(length (sv)) points in [$(first (sv)) , $(last (sv)) ]" end )
59+ abstol: $(@sprintf (" %.2e" , initializedSolver. opts. abstol))
60+ reltol: $(@sprintf (" %.2e" , initializedSolver. opts. reltol))
61+ adaptive: $(initializedSolver. opts. adaptive)
62+ dense: $(initializedSolver. opts. dense)
63+ """
64+
65+ # Solve
66+ solve (ode_prob, OrdinaryDiffEqBDF. FBDF (); kwargs... )
5067 end
5168 sim_time = time () - t0
5269 if sol. retcode == ReturnCode. Success
@@ -67,7 +84,8 @@ function run_simulate(ode_prob, model_dir::String,
6784 sim_time = time () - t0
6885 sim_error = sprint (showerror, e, catch_backtrace ())
6986 end
70- println (log_file, " Time: $(round (sim_time; digits= 3 )) s" )
87+ println (log_file, " Solver settings: $solver_settings_string " )
88+ println (log_file, " Time: $(round (sim_time; digits= 3 )) s" )
7189 println (log_file, " Success: $sim_success " )
7290 isempty (sim_error) || println (log_file, " \n --- Error ---\n $sim_error " )
7391 close (log_file)
0 commit comments