Defining your own potentials

Creating your own potentials type is very easy. We can do this by making use of the CustomPotential

Example

We want to implement the interaction potential $u(r) = \epsilon \left(\frac{\sigma}{r}\right)^6.$

To do this, first we define the function. This function should take two arguments, r::Number and p, the latter of which contains optional parameters that the function uses. For example:

function my_pot(r, p)
    return p.ϵ * (p.σ / r)^6
end
my_pot (generic function with 1 method)

Now we can instantiate the CustomPotential, using e.g. a NamedTuple to pass in the parameters:

using OrnsteinZernike
p = (ϵ = 1.0, σ = 1.0)
potential = CustomPotential(my_pot, p)
CustomPotential{typeof(Main.my_pot), @NamedTuple{ϵ::Float64, σ::Float64}}(Main.my_pot, (ϵ = 1.0, σ = 1.0))

And use the potential as any other

dims = 3 # we consider a 3D system
ρ = 0.6 # number density
kBT = 1.0 # thermal energy
system = SimpleLiquid(dims, ρ, kBT, potential)
closure = HypernettedChain()
sol = solve(system, closure)
using Plots
plot(sol.r, sol.gr, xlims=(0,5), xlabel="r", ylabel="g(r)")
Example block output

Mixtures

In the case of multicomponent systems, instead of a number the function should return a StaticMatrix from the StaticArrays package containing values for $u_{ij}$.

Example

Suppose we want to implement the same potential for the multicomponent case: $u_{ij}(r) = \epsilon_{ij} (\frac{\sigma_{ij}}{r_{ij}})^6.$

While one could implement this in one line with broadcasting, here the function is written out fully for clarity:

using OrnsteinZernike, StaticArrays

function mypotential(r, p)
    # we can construct a mutable sized matrix first
    Nspecies = size(p.ϵ, 1)
    out = MMatrix{Nspecies, Nspecies, Float64, Nspecies*Nspecies}(undef)
    for species2 = 1:Nspecies
        for species1 = 1:Nspecies
            out[species1, species2] = p.ϵ[species1, species2] * (p.σ[species1, species2] / r) ^ 6
        end
    end
    # and convert it to an immutable variant
    return SMatrix(out)
end
mypotential (generic function with 1 method)

and now we can use it:

ϵ = SMatrix{2,2}([1.0 2.0; 0.4 0.9])
σ = SMatrix{2,2}([1.0 1.0; 1.0 0.8])
p = (ϵ = ϵ, σ = σ)
dims = 3 # we consider a 3D system
potential = CustomPotential(mypotential, p)
ρ = [0.25, 0.25] # number density
kBT = 1.0 # thermal energy
system = SimpleLiquid(dims, ρ, kBT, potential)
closure = HypernettedChain()
sol = solve(system, closure)
using Plots
plot(sol.r, sol.gr[:, 1, 1], xlims=(0,5), xlabel="r", ylabel="g(r)", label="g11(r)")
plot!(sol.r, sol.gr[:, 1, 2], xlims=(0,5), xlabel="r", ylabel="g(r)", label="g12(r)")
plot!(sol.r, sol.gr[:, 2, 2], xlims=(0,5), xlabel="r", ylabel="g(r)", label="g22(r)")
Example block output