QDO charge densities

libMBD can evaluate the charge density of the quantum Drude oscillators (QDOs) that underlie the MBD model, both without the dipole coupling (nonint_density()) and with it (int_density()). Both take a set of points and the QDO parameters and return the density at those points, so plotting is just a matter of choosing a grid. The underlying derivation is given in J. Hermann, Towards unified density-functional model of van der Waals interactions, PhD thesis, Humboldt-Universität zu Berlin, 2018, doi:10.18452/18706, Ch. 4, §4.3.1 (charge density) and §4.3.2 (first-order perturbation correction).

The QDO parameters follow from the vdW parameters via \(\omega_A=\tfrac43 C_{6,A}/\alpha_{0,A}^2\) and \(\alpha_{0,A}=q_A^2/(m_A\omega_A^2)\). The MBD convention sets \(m_A=1\), which gives \(q_A=\omega_A\sqrt{\alpha_{0,A}}\). The interacting density additionally needs the coupled MBD normal modes, obtained from a geometry constructed with get_spectrum=True. Both densities integrate to \(\sum_A q_A\).

The following minimal example evaluates both densities of an argon dimer along the bond axis and plots the non-interacting density together with the change induced by the coupling, using Matplotlib:

import numpy as np
import matplotlib.pyplot as plt

from pymbd import ang, from_volumes
from pymbd.fortran import MBDGeom

# argon dimer along z, 4 Å apart
coords = np.array([[0.0, 0.0, 0.0], [0.0, 0.0, 4 * ang]])
alpha_0, C6, R_vdw = from_volumes(['Ar', 'Ar'], [1.0, 1.0])

# QDO parameters (mass = 1 convention)
omega = 4 / 3 * C6 / alpha_0**2
m = np.ones_like(alpha_0)
q = omega * np.sqrt(alpha_0 * m)

# line of points along the bond axis
z = np.linspace(-3, 7, 500) * ang
pts = np.stack([np.zeros_like(z), np.zeros_like(z), z], axis=1)

# non-interacting density
rho_0 = MBDGeom(coords).nonint_density(pts, q, m, omega)

# interacting density, needs the coupled MBD modes
geom = MBDGeom(coords, get_spectrum=True)
_, eigs, modes = geom.mbd_energy(alpha_0, C6, R_vdw, beta=0.83)
rho = geom.int_density(pts, q, m, np.sqrt(eigs), modes)

# the coupling effect is tiny, so plot it against the non-interacting
# density on a separate axis
fig, ax = plt.subplots()
l1, = ax.plot(z / ang, rho_0, color='C0', label='non-interacting')
ax.set_xlabel(r'$z$ (Å)')
ax.set_ylabel(r'$n_0(z)$ (a.u.)', color='C0')
ax.tick_params(axis='y', labelcolor='C0')

ax2 = ax.twinx()
l2, = ax2.plot(z / ang, rho - rho_0, color='C1',
               label='interacting − non-interacting')
ax2.set_ylabel(r'$n(z) - n_0(z)$ (a.u.)', color='C1')
ax2.tick_params(axis='y', labelcolor='C1')

ax.legend(handles=[l1, l2], loc='lower center',
          bbox_to_anchor=(0.5, 1.0), ncol=2, frameon=False)
fig.tight_layout()
plt.show()

which produces:

Non-interacting QDO charge density of an argon dimer and the change induced by the dipole coupling, along the bond axis

Non-interacting QDO charge density of an argon dimer (left axis) and the change induced by the dipole coupling (right axis), along the bond axis.

For a weakly bound system such as the argon dimer the coupling barely perturbs the density — note the four-orders-of-magnitude difference between the two axes. The coupling depletes density at the oscillator centers and shifts it into the bond region; the effect grows for more polarizable, strongly coupled systems.