I'm frequently asked about my default sampler, "DPM++ 2M Karras Sharp v1", so I figured I'd just write an article about so I could link to it.
Some background:
A while back, it was discovered that there was a bug in the DPM++ 2M Karras algorithm that was causing it not to resolve pictures as clearly as they could be, so someone created a fix and posted it on the automatic1111 github, here:
https://github.com/AUTOMATIC1111/stable-diffusion-webui/discussions/8457
People complained that the fix washed out the image colors slightly, so the sampler was revised to address that issue, and in the revision, it lost some of that sharpness. The original, sharp revision is now hidden away in the March 9th edit of the top comment (which you can find by clicking on the tiny "edited" dropdown in the top right corner of the comment). Because I prefer the extra sharpness and detail even with the slight loss of color (which can easily be restored in any modern photo processing program, whereas additional detail cannot be), I dug out the original version and implemented it myself.
Here are some images to compare. I recommend opening them in new tabs and then switching between them so you can see the changes directly. (Unfortunately, the low resolution that articles save images with doesn't really do it justice. It's pretty striking at high resolution, so I recommend comparing it yourself.)
Anyway, I'm running vladmandic's fork, so YMMV on this, but it will probably work on automatic1111's original fork as well. First, to the end of repositories\k-diffusion\k_diffusion\sampling.py, add this function:
@torch.no_grad()
def sample_dpmpp_2m_v1(model, x, sigmas, extra_args=None, callback=None, disable=None):
"""DPM-Solver++(2M)."""
extra_args = {} if extra_args is None else extra_args
s_in = x.new_ones([x.shape[0]])
sigma_fn = lambda t: t.neg().exp()
t_fn = lambda sigma: sigma.log().neg()
old_denoised = None
for i in trange(len(sigmas) - 1, disable=disable):
denoised = model(x, sigmas[i] * s_in, **extra_args)
if callback is not None:
callback({'x': x, 'i': i, 'sigma': sigmas[i], 'sigma_hat': sigmas[i], 'denoised': denoised})
t, t_next = t_fn(sigmas[i]), t_fn(sigmas[i + 1])
h = t_next - t
if old_denoised is None or sigmas[i + 1] == 0:
x = (sigma_fn(t_next) / sigma_fn(t)) * x - (-h).expm1() * denoised
else:
h_last = t - t_fn(sigmas[i - 1])
r = h_last / h
denoised_d = (1 + 1 / (2 * r)) * denoised - (1 / (2 * r)) * old_denoised
x = (sigma_fn(t_next) / sigma_fn(t)) * x - (-h).expm1() * denoised_d
sigma_progress = i / len(sigmas)
adjustment_factor = 1 + (0.15 * (sigma_progress * sigma_progress))
old_denoised = denoised * adjustment_factor
return x
Then, in modules/sd_samplers_kdiffusion.py, add the following line to the end of the samplers_k_diffusion variable definition near the top of the file:
('DPM++ 2M Karras Sharp v1', 'sample_dpmpp_2m_v1', ['k_dpmpp_2m_ka_v1'], {'scheduler': 'karras'}),
After that, restart your web interface and reload the page, and go to the settings page and type "Karras" into the search bar. You should see a list of checkboxes that enable samplers in the select list. Click the DPM++ 2M Karras Sharp v1 checkbox, then save your settings. Restart the program again and reload the page, and the sampler should be selectable on in the samplers pull-down along with the others.
Note: I'm writing these steps basically from memory, so let me know if something doesn't work and I'll update this article.