Electrometry¶
The electrometry subpackage computes local electric fields from gate-bias voltages and screened disorder charges, and evaluates the resulting ODMR frequency shifts across a 2-D scan area.
SpinDefectSim.electrometry.efield¶
Low-level E-field building blocks.
E_gate_bias¶
from SpinDefectSim.electrometry.efield import E_gate_bias
def E_gate_bias(
r_obs_xyz: tuple,
E0=(0, 0, 0),
grad=None,
) -> np.ndarray
Return the gate-bias electric field (uniform + optional linear gradient) at a single observation point.
Parameters:
| Name | Type | Description |
|---|---|---|
r_obs_xyz |
(x, y, z) |
Observation point (m) |
E0 |
array_like (3,) |
Uniform field components (Ex, Ey, Ez) in V/m |
grad |
np.ndarray (2,2) \| None |
In-plane gradient tensor [[∂Ex/∂x, ∂Ex/∂y], [∂Ey/∂x, ∂Ey/∂y]] in V/m² |
Returns: np.ndarray shape (3,) in V/m
Example:
from SpinDefectSim.electrometry.efield import E_gate_bias
import numpy as np
E = E_gate_bias((0, 0, 0.34e-9), E0=(0, 0, 2e6))
# → array([0., 0., 2e6]) V/m
E_disorder_point_charges¶
from SpinDefectSim.electrometry.efield import E_disorder_point_charges
def E_disorder_point_charges(
r_obs_xyz: tuple,
charges_xyzq: np.ndarray,
*,
epsilon_eff: float,
screening_model: Optional[str],
lambda_screen: float,
d_gate: float,
n_images: int,
r_min: float = 0.2e-9,
) -> np.ndarray
Compute the E-field at a single observation point due to a set of static point charges, using the selected screened Coulomb model.
Parameters:
| Name | Type | Description |
|---|---|---|
r_obs_xyz |
(x, y, z) |
Observation point (m) |
charges_xyzq |
np.ndarray (M, 4) |
Charge positions and values [x, y, z, q] in SI units |
epsilon_eff |
float |
Effective dielectric constant |
screening_model |
str \| None |
None (bare 1/r), "yukawa", or "dual_gate" |
lambda_screen |
float |
Yukawa screening length (m) |
d_gate |
float |
Dual-gate separation (m) |
n_images |
int |
Number of image-charge terms |
r_min |
float |
Minimum distance regulariser (m) |
Returns: np.ndarray shape (3,) in V/m
apply_dielectric_transmission¶
from SpinDefectSim.electrometry.efield import apply_dielectric_transmission
def apply_dielectric_transmission(
E: np.ndarray,
eps_layer: float,
eps_host: float,
) -> np.ndarray
Scale an E-field by the quasi-static planar dielectric transmission factor:
Parameters:
| Name | Type | Description |
|---|---|---|
E |
np.ndarray |
Input E-field, any shape ending in (..., 3) |
eps_layer |
float |
Dielectric constant of the layer |
eps_host |
float |
Dielectric constant of the host |
Returns: np.ndarray same shape as E
ElectricFieldBuilder¶
Combines gate-bias and disorder charge contributions into a single total() call. Inherits PhysicalParams.
Constructor¶
total¶
def total(
defect_xyz: tuple,
*,
E0_gate=(0, 0, 0),
gate_grad=None,
disorder_xyzq=None,
) -> tuple[np.ndarray, dict]
Compute the total E-field at defect_xyz.
Parameters:
| Name | Type | Description |
|---|---|---|
defect_xyz |
(x, y, z) |
Defect position (m) |
E0_gate |
array_like (3,) |
Uniform gate field (V/m) |
gate_grad |
np.ndarray \| None |
Gate-field gradient tensor |
disorder_xyzq |
np.ndarray (M, 4) \| None |
Disorder charges |
Returns: (E_tot, components) where E_tot is a (3,) array (V/m) and components is a dict with keys "gate" and "disorder".
SpinDefectSim.electrometry.electrometry¶
ElectrometryExperiment¶
Computes ODMR observables at one point or across a 2-D scan grid from a known distribution of static charges and/or gate bias.
Inherits: PhysicalParams
Constructor¶
ElectrometryExperiment(
charges_xyzq: np.ndarray,
defaults: Optional[Defaults] = None,
*,
z_defect: Optional[float] = None,
E0_gate=(0, 0, 0),
gate_grad=None,
epsilon_eff: Optional[float] = None,
screening_model: Optional[str] = None,
lambda_screen: Optional[float] = None,
d_gate: Optional[float] = None,
n_images: Optional[int] = None,
bias_B_T=None,
)
Parameters:
| Name | Type | Description |
|---|---|---|
charges_xyzq |
np.ndarray (M, 4) |
Disorder charges [x, y, z, q] in SI units |
defaults |
Defaults \| None |
Global defaults |
z_defect |
float \| None |
Defect height above the charge plane (m); uses defaults.z_defect if None |
E0_gate |
array_like (3,) |
Uniform gate-bias field (V/m) |
gate_grad |
np.ndarray \| None |
Gate-field gradient tensor (V/m²) |
epsilon_eff |
float \| None |
Effective dielectric (overrides defaults.epsilon_eff) |
screening_model |
str \| None |
None, "yukawa", or "dual_gate" |
lambda_screen |
float \| None |
Yukawa length (m) |
d_gate |
float \| None |
Gate separation (m) |
n_images |
int \| None |
Image-charge sum length |
bias_B_T |
array_like (3,) \| None |
Bias B-field vector (T) to use when computing ODMR frequencies |
E_field¶
Total E-field at a single observation point.
Parameters:
| Name | Type | Description |
|---|---|---|
x_obs |
float |
x position (m) |
y_obs |
float |
y position (m) |
z_obs |
float \| None |
z position (m); if None, uses self.z_defect |
Returns: np.ndarray shape (3,) in V/m
transition_frequencies¶
def transition_frequencies(
x_obs: float,
y_obs: float,
z_obs: Optional[float] = None,
) -> np.ndarray
ODMR transition frequencies at a single point.
Returns: np.ndarray float64, shape (2S,), sorted ascending, in Hz
E_field_map¶
def E_field_map(
x_obs: np.ndarray,
y_obs: np.ndarray,
z_obs: Optional[float] = None,
) -> np.ndarray
Compute the total E-field on a 2-D grid. x_obs and y_obs define 1-D coordinate arrays; the result is computed on their outer product mesh.
Parameters:
| Name | Type | Description |
|---|---|---|
x_obs |
np.ndarray |
1-D x coordinates (m) |
y_obs |
np.ndarray |
1-D y coordinates (m) |
z_obs |
float \| None |
z height (m) |
Returns: np.ndarray shape (Ny, Nx, 3) in V/m
E_z_map¶
Ez component on a 2-D grid.
Returns: np.ndarray shape (Ny, Nx) in V/m
transition_frequency_map¶
def transition_frequency_map(
x_obs: np.ndarray,
y_obs: np.ndarray,
z_obs: Optional[float] = None,
) -> np.ndarray
ODMR transition frequencies on a 2-D scan grid.
Returns: np.ndarray shape (Ny, Nx, 2S) in Hz
Example:
import numpy as np
from SpinDefectSim.electrometry.electrometry import ElectrometryExperiment
# Single trapped electron charge
charges = np.array([[0., 0., 0., 1.6e-19]])
exp = ElectrometryExperiment(
charges_xyzq=charges,
z_defect=0.34e-9,
screening_model="dual_gate",
d_gate=15e-9,
)
x = np.linspace(-100e-9, 100e-9, 50)
y = np.linspace(-100e-9, 100e-9, 50)
freq_map = exp.transition_frequency_map(x, y)
# Frequency of the lower transition, in GHz
lower_freq_GHz = freq_map[:, :, 0] / 1e9