How the "Automatic" scheduler sentinel is defined, resolved, and executed.
"Automatic" is the first entry in the schedulers list (modules/sd_schedulers.py:268), with function=None:
schedulers = [
Scheduler("automatic", "Automatic", None), # index 0, function=None
Scheduler("karras", "Karras", ...),
...
]function=None is the sentinel that tells downstream code to resolve the actual schedule elsewhere.
get_sampler_and_scheduler() (modules/sd_samplers.py:113) parses sampler strings like "Euler a Karras" into ("Euler a", "Karras") and handles the convert_automatic flag (default True):
# if the found scheduler is already the sampler's own built-in default, revert to "Automatic"
if convert_automatic and sampler.options.get("scheduler", None) == found_scheduler.name:
found_scheduler = sd_schedulers.schedulers[0] # → AutomaticThis keeps the UI and infotext showing "Automatic" rather than the redundant explicit name when the sampler's default is in use. Called with convert_automatic=False when the actual resolved name is needed (e.g. fix_p_invalid_sampler_and_scheduler, line 139).
KDiffusionSampler.get_sigmas() (modules/sd_samplers_kdiffusion.py:80) resolves "Automatic" at runtime:
scheduler_name = (p.hr_scheduler if p.is_hr_pass else p.scheduler) or "Automatic"
if scheduler_name == "Automatic":
if dynamic_args.klein:
scheduler_name = "Flux2" # Klein model special-case
else:
scheduler_name = self.config.options.get("scheduler", None) # sampler's declared defaultResolution priority:
- User's explicit scheduler choice
- If
"Automatic"+ Klein model →"Flux2" - If
"Automatic"+ other → sampler's ownoptions["scheduler"] - If that is also
None→ fall through toself.model_wrap.get_sigmas(steps)(the model's native schedule)
The "Schedule type" key is intentionally omitted from extra_generation_params when "Automatic" is in effect, so it does not appear in saved infotext unless a non-default scheduler was actually used.
When no scheduler function is found (case 4 above), sd_samplers_kdiffusion.py:97 calls:
sigmas = self.model_wrap.get_sigmas(steps)self.model_wrap is a ForgeScheduleLinker (modules_forge/packages/k_diffusion/external.py:28):
def get_sigmas(self, n=None):
t_max = len(self.sigmas) - 1 # e.g. 999 for a 1000-step model
t = torch.linspace(t_max, 0, n, device=...) # n evenly-spaced timestep indices
return append_zero(self.t_to_sigma(t)) # map to sigma values, append 0This linearly spaces n timestep indices from t_max down to 0, maps them to sigma values via predictor.sigma(t), then appends a trailing zero (the fully-denoised endpoint).
The predictor is one of the Prediction* classes in backend/modules/k_prediction.py, chosen at model load time:
| Class | Used by | sigma(t) |
|---|---|---|
Prediction |
SD1.5, SDXL | Log-linear interpolation in a log_sigmas table built from the beta schedule: sigmas = sqrt((1 - αbar) / αbar) |
PredictionEDM |
EDM models | exp(t / 0.25) |
PredictionContinuousEDM |
EDM continuous | exp(t / 0.25) with a log-linear sigma table |
PredictionContinuousV |
V-prediction continuous | tan(t · π/2) |
PredictionFlow |
SD3-like | time_snr_shift(shift, t / multiplier) |
PredictionFlux |
Flux.1-dev/schnell | Identity (sigma == timestep); table pre-shifted by mu via FlowMatchEulerDiscreteScheduler._time_shift_exponential |
PredictionFlux2 |
Flux2-Klein | exp(mu) / (exp(mu) + (1/t - 1)^sigma) |
PredictionDiscreteFlow |
Wan, others | time_snr_shift(shift, t / multiplier) |
Prediction.register_schedule builds a 1000-entry sigma table from the linear beta schedule:
betas = make_beta_schedule("linear", 1000, linear_start=0.00085, linear_end=0.012)
alphas_cumprod = cumprod(1 - betas)
sigmas = sqrt((1 - alphas_cumprod) / alphas_cumprod) # ≈ 0.029 … 14.6sigma(t) then does log-linear interpolation between adjacent entries so fractional indices get smooth values. Linearly spacing the indices produces a schedule that is uniform in the model's own timestep space — roughly uniform in log-sigma. This is essentially what the named "Uniform" scheduler does explicitly; "Automatic" reads it directly off the model's baked-in table instead of recomputing it.