1function [xvec_it, xvec_t, t, iter] = solver_fluid_iteration(sn, N, Mu, Phi, PH,
P, S, xvec_it, ydefault, slowrate, Tstart, max_time, options)
2% [XVEC_IT, XVEC_T, T, ITER] = SOLVER_FLUID_ITERATION(QN, N, MU, PHI, PH,
P, S, YMEAN, YDEFAULT, SLOWRATE, TSTART, MAX_TIME, OPTIONS)
4% Copyright (c) 2012-2026, Imperial College London
7iter_max = options.iter_max;
8verbose = options.verbose;
10iter_tol = options.iter_tol;
12timespan = options.timespan;
14goon =
true; % max stiff solver
21% heuristic to select stiff or non-stiff ODE solver
22nonZeroRates = slowrate(:);
23nonZeroRates = nonZeroRates( nonZeroRates >tol );
25nonZeroRates = nonZeroRates(isfinite(nonZeroRates));
26if isempty(nonZeroRates)
27 nonZeroRates = 1; % fallback when all rates are zero or infinite
29%rategap = log10(max(nonZeroRates)/min(nonZeroRates)); %
if the max rate
is InfRate and the min
is 1, then rategap = 6
32[ode_h, ~] = solver_fluid_odes(sn, N, Mu, Phi, PH,
P, S, sn.sched, sn.schedparam, options);
35odeopt = odeset(
'AbsTol', tol,
'RelTol', tol,
'NonNegative', 1:length(xvec_it{1}));
37while (isfinite(timespan(2)) && T < timespan(2)) || (goon && iter < iter_max)
39 if toc(Tstart) > max_time
44 % determine entry state vector in e
45 y0 = xvec_it{iter-1 +1};
47 if iter == 1 % first iteration
48 T = min(timespan(2),abs(10/min(nonZeroRates))); % solve ode until T = 1
event with slowest exit rate
50 T = min(timespan(2),abs(10*iter/min(nonZeroRates)));
56 [t_iter, ymean_t_iter] = ode_solve_stiff(ode_h, trange, y0, odeopt, options);
58 [t_iter, ymean_t_iter] = ode_solve(ode_h, trange, y0, odeopt, options);
61 line_printf(
'\nThe initial point is invalid, Fluid solver switching to default initialization.');
62 odeopt = odeset(
'AbsTol', tol,
'RelTol', tol,
'NonNegative', 1:length(ydefault));
63 [t_iter, ymean_t_iter] = ode_solve(ode_h, trange, ydefault, odeopt, options);
65 xvec_t(end+1:end+size(ymean_t_iter,1),:) = ymean_t_iter;
66 t(end+1:end+size(t_iter,1),:) = t_iter;
67 xvec_it{iter +1} = xvec_t(end,:);
68 movedMassRatio = norm(xvec_it{iter +1} - xvec_it{iter-1 +1}, 1) / 2 / sum(xvec_it{iter-1 +1});
69 T0 = T; %
for next iteration
75 allt = [allt; allt(end)+t];
77 ally = [ally; xvec_t];
80 % check termination condition
83 llmsg = length(lastmsg);
91 if movedMassRatio < iter_tol % converged
92 % stop only
if this is not a transient analysis, in which
case keep
93 % going until the specified end time