Loading...
Searching...
No Matches
marzari_vanderbilt.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * MarzariVanderbiltSmearing — "cold smearing" occupation function.
5 *
6 * Implements the cold-smearing scheme of Marzari, Vanderbilt, De Vita &
7 * Payne, Phys. Rev. Lett. 82, 3296 (1999). The two closed forms below follow
8 * by elementary integration of that paper's smearing delta: the occupation
9 * is the integral of delta, the entropy weight the integral of t*delta.
10 * Cold smearing is a sibling of, not a member of, the Hermite expansion of
11 * Methfessel & Paxton, Phys. Rev. B 40, 3616 (1989) — that expansion is
12 * indexed by order N >= 0 and has no N = -1 term; "n = -1" is only the
13 * dispatch index some codes use to select this scheme. Cross-checked
14 * numerically against Quantum ESPRESSO, whose
15 * internal smearing variable is x_QE = -x (x = (E-E_F)/sigma, the convention
16 * used throughout this codebase). That sign relation is confirmed by the
17 * existing Gaussian and Fermi-Dirac schemes, which already match QE exactly
18 * under the same substitution. Letting y = x + 1/sqrt(2):
19 *
20 * occupation(x) = (1/2) erfc(y) + exp(-y^2) / sqrt(2*pi)
21 * entropy_weight(x) = -y * exp(-y^2) / sqrt(2*pi)
22 *
23 * Unlike plain Methfessel-Paxton, this is not symmetric about x=0 and its
24 * occupation numbers are not confined to [0, 1] either. The overshoot is a
25 * single smooth lobe, and both its size and its location follow from the
26 * closed form above rather than from any boundedness assumption: setting
27 * d/dy [(1/2) erfc(y) + exp(-y^2)/sqrt(2*pi)] = 0 gives y = -1/sqrt(2),
28 * i.e. x = -sqrt(2) = -1.41421, where occupation(x) = 1.0833155 — an 8.33%
29 * overshoot, well away from the Fermi level. The QE comparison (Cu FCC,
30 * matched degauss) corroborates the scheme end to end; it is not what
31 * establishes these two numbers.
32 */
33
34#include <cmath>
35
37
38namespace q3 {
39
40/// Marzari-Vanderbilt ("cold") smearing.
42 public:
45
46 [[nodiscard]] Real occupation(Real x) const override {
47 const Real inverse_sqrt2 = 1.0 / std::sqrt(2.0);
48 Real y = x + inverse_sqrt2;
49 return 0.5 * std::erfc(y) + std::exp(-y * y) / std::sqrt(2.0 * constants::pi);
50 }
51
52 [[nodiscard]] Real entropy_weight(Real x) const override {
53 const Real inverse_sqrt2 = 1.0 / std::sqrt(2.0);
54 Real y = x + inverse_sqrt2;
55 return -y * std::exp(-y * y) / std::sqrt(2.0 * constants::pi);
56 }
57
58 [[nodiscard]] std::string name() const override {
59 return "marzari-vanderbilt";
60 }
61};
62
63} // namespace q3
Marzari-Vanderbilt ("cold") smearing.
std::string name() const override
MarzariVanderbiltSmearing(Real smearing_width=0.0)
Real entropy_weight(Real x) const override
Compute the entropy contribution δ(x) weight.
Real occupation(Real x) const override
Compute the occupation f(x) where x = (E - E_F) / σ.
Abstract interface for electronic smearing schemes.
Definition init.hpp:19
Real smearing_width() const
Smearing width σ (degauss) in Ry.
Definition init.hpp:33
constexpr Real pi
Definition constants.hpp:24
double Real