Skip to content

Coulomb Kernels

The coulomb subpackage provides screened Coulomb Green's functions used for computing electric fields from point-charge disorder in 2-D heterostructures.

Three screening models are supported:

Model screening_model value Description
Bare Coulomb None Unscreened 1/r potential
Yukawa "yukawa" Exponentially screened with screening length λ
Dual-gate image charges "dual_gate" Metallic top and bottom gates modelled via method-of-images

SpinDefectSim.coulomb.kernels


G_rho

from SpinDefectSim.coulomb.kernels import G_rho

def G_rho(
    screening_model: Optional[str],
    rho: np.ndarray,
    *,
    lambda_screen: float = 5e-9,
    d_gate: float = 5e-9,
    n_images: int = 50,
    r_min: float = 1e-12,
) -> np.ndarray

In-plane screened 2-D Coulomb kernel G(ρ) for a source and observer both in the same plane (z = 0).

This is the scalar Green's function such that:

\[\phi(ρ) = \frac{q}{4\pi\varepsilon_0\varepsilon_\text{eff}} \cdot G(\rho)\]

Parameters:

Name Type Description
screening_model str \| None None (bare), "yukawa", or "dual_gate"
rho np.ndarray In-plane distance(s) ρ (m); any shape
lambda_screen float Yukawa screening length λ (m)
d_gate float Gate-to-plane separation d (m) for dual-gate model
n_images int Number of image-charge terms in the dual-gate sum
r_min float Minimum distance regulariser (m) to avoid divergence at ρ = 0

Returns: np.ndarray — same shape as rho

Model formulas:

\[G(\rho) = \frac{1}{\rho}\]
\[G(\rho) = \frac{e^{-\rho/\lambda}}{\rho}\]

$\(G(\rho) = \sum_{n=-\infty}^{+\infty} \frac{(-1)^n}{\sqrt{\rho^2 + (2nd)^2}}\)$ truncated at ±n_images terms

Example:

import numpy as np
from SpinDefectSim.coulomb.kernels import G_rho

rho = np.linspace(1e-9, 100e-9, 200)

G_bare = G_rho(None, rho)
G_yukawa = G_rho("yukawa", rho, lambda_screen=10e-9)
G_dg = G_rho("dual_gate", rho, d_gate=15e-9, n_images=30)

import matplotlib.pyplot as plt
plt.loglog(rho * 1e9, G_bare, label="bare")
plt.loglog(rho * 1e9, G_yukawa, label="Yukawa λ=10 nm")
plt.loglog(rho * 1e9, G_dg, label="dual-gate d=15 nm")
plt.xlabel("ρ (nm)")
plt.ylabel("G(ρ)  (m⁻¹)")
plt.legend()
plt.title("Screened Coulomb kernels")
plt.show()


G_rz

from SpinDefectSim.coulomb.kernels import G_rz

def G_rz(
    screening_model: Optional[str],
    rho: np.ndarray,
    z_obs: float,
    *,
    lambda_screen: float = 5e-9,
    d_gate: float = 5e-9,
    n_images: int = 50,
    r_min: float = 1e-12,
) -> np.ndarray

3-D screened Coulomb kernel G(ρ, z_obs) for a source charge at z = 0 and an observer at height z_obs above the plane.

Parameters:

Name Type Description
screening_model str \| None None, "yukawa", or "dual_gate"
rho np.ndarray In-plane distance(s) ρ (m)
z_obs float Observer height above source plane (m)
lambda_screen float Yukawa λ (m)
d_gate float Gate separation d (m)
n_images int Image-charge sum truncation
r_min float Regulariser (m)

Returns: np.ndarray same shape as rho

Model formulas:

\[G(\rho, z) = \frac{1}{\sqrt{\rho^2 + z^2}}\]
\[G(\rho, z) = \frac{e^{-r/\lambda}}{r}, \quad r = \sqrt{\rho^2 + z^2}\]
\[G(\rho, z) = \sum_{n} \frac{(-1)^n}{\sqrt{\rho^2 + (z - 2nd)^2}}\]

Example — E-field from a point charge at the VB⁻ height:

import numpy as np
from SpinDefectSim.coulomb.kernels import G_rz

rho = np.linspace(1e-9, 200e-9, 300)
z_defect = 0.34e-9   # VB⁻ height above charge plane (m)

G = G_rz("dual_gate", rho, z_obs=z_defect, d_gate=15e-9, n_images=30)

# E_rho = q / (4π ε₀ ε_eff) * dG/dρ   (radial E-field component)


Choosing a screening model

Scenario Recommended model
Isolated 2-D material, no gates "yukawa" with λ set to the Thomas-Fermi screening length
Dual-gated heterostructure (e.g. hBN/graphene/hBN) "dual_gate" with d_gate = gate separation
Theory benchmarking / unscreened limit None (bare Coulomb)

Tip: The Defaults object exposes coulomb_kwargs() which packs the right parameters for passing directly to these functions:

from SpinDefectSim.base.params import Defaults

d = Defaults(screening_model="dual_gate", d_gate=15e-9, n_images=30)
kwargs = d.coulomb_kwargs()
# → {"epsilon_eff": 7.0, "screening_model": "dual_gate",
#    "lambda_screen": 10e-9, "d_gate": 15e-9, "n_images": 30, "r_min": 2e-10}

G = G_rho(kwargs["screening_model"], rho,
          lambda_screen=kwargs["lambda_screen"],
          d_gate=kwargs["d_gate"],
          n_images=kwargs["n_images"])