Thermodynamic Consistency

Some Closures have free parameters that can be tuned to obtain the most accurate bridge functions. For example, the famous Rogers-Young closure RogersYoung interpolates between the Percus-Yevick closure and the Hypernetted Chain one with a free parameter $\alpha$. While this parameter can be chosen freely, it is usually chosen such that the solutions satisfy thermodynamic consistency.

Free choice of $\alpha$

To warm up, let's solve a 3D hard-sphere system for $\alpha=0.5$

using OrnsteinZernike, Plots
M = 5000
ρ = 0.6 * sqrt(2)
dr = 20.0/M
kBT = 1.0
dims = 3
α = 0.5
pot = HardSpheres(1.0)
system = SimpleLiquid(dims, ρ, kBT, pot)
method = NgIteration(M=M, dr=dr, verbose=false)
solRY = solve(system, RogersYoung(α), method)
solPY = solve(system, PercusYevick(), method)
solHNC = solve(system, HypernettedChain(), method)

plot(solRY.r, solRY.gr, label="Rogers-Young")
plot!(solPY.r, solPY.gr, label="Percus-Yevick")
plot!(solHNC.r, solHNC.gr, label="Hypernetted Chain")
plot!(xlims=(0.9,2.3), xlabel="r", ylabel="g(r)")
Example block output

Here, we can see, that indeed, the Rogers-Young closure finds a middle ground between the two others.

Using thermodynamics

There are a number of thermodynamic relations that allow a consistent choice of $\alpha$. Here we opt for the requirement $\frac{1}{\rho\chi_T}=\left(\frac{\partial p}{\partial \rho}\right)_T$, which physically means that we require the virial and compressibility route of obtaining the pressure to give the same results. For simplicity, we use finite differences to obtain the derivative of the pressure. See the Theory section for more details. Subsequently, we use the bisection method from Roots.jl to find the optimal parameter. The results can be compared to Table 1 in Ref. 1.

using OrnsteinZernike, Plots
import Roots
function find_self_consistent_solution(ρ, kBT, M, dr, dims, pot)

    function RY_inconsistency(ρ, α)
        system1 = SimpleLiquid(dims, ρ, kBT, pot)
        method = NgIteration(M=M, dr=dr, verbose=false)
        sol1 = solve(system1, RogersYoung(α), method)
        p1 = compute_virial_pressure(sol1, system1)

        dρ = sqrt(eps(ρ))
        system2 = SimpleLiquid(dims, ρ+dρ, kBT, pot)
        sol2 = solve(system2, RogersYoung(α), method)
        p2 = compute_virial_pressure(sol2, system2)
        dpdρ = (p2-p1)/dρ

        χ = compute_compressibility(sol1, system1)
        inconsistency = dpdρ - 1/(ρ*χ)
        return inconsistency
    end

    # we need to find α such that the inconsistency is zero.
    func = α ->  RY_inconsistency(ρ, α)
    α =  Roots.find_zero(func, (0.001,50.0), Roots.Bisection(), atol=0.0001)
    system = SimpleLiquid(dims, ρ, kBT, pot)
    method = NgIteration(M=M, dr=dr, verbose=false)
    sol = solve(system, RogersYoung(α), method)
    return system, sol, α
end

for ρstar = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.654]
    ρ = ρstar*sqrt(2)
    M = 1000
    dr = 10.0/M
    kBT = 1.0
    dims = 3
    pot = HardSpheres(1.0)
    system, sol, α = find_self_consistent_solution(ρ, kBT, M, dr, dims, pot)
    P = compute_virial_pressure(sol, system)/ρ/kBT - 1
    gmax = maximum(sol.gr)
    println("At ρ/√2 = $(ρstar), we find α = $(round(α,digits=2)), and βp/ρ - 1 = $(round(P,digits=4)).")
end
At ρ/√2 = 0.1, we find α = 0.21, and βp/ρ - 1 = 0.3592.
At ρ/√2 = 0.2, we find α = 0.23, and βp/ρ - 1 = 0.8861.
At ρ/√2 = 0.3, we find α = 0.25, and βp/ρ - 1 = 1.6714.
At ρ/√2 = 0.4, we find α = 0.26, and βp/ρ - 1 = 2.8665.
At ρ/√2 = 0.5, we find α = 0.26, and βp/ρ - 1 = 4.7362.
At ρ/√2 = 0.6, we find α = 0.26, and βp/ρ - 1 = 7.7674.
At ρ/√2 = 0.654, we find α = 0.25, and βp/ρ - 1 = 10.1957.

References:

  1. Rogers, Forrest J., and David A. Young. "New, thermodynamically consistent, integral equation for simple fluids." Physical Review A 30.2 (1984): 999.