getelec.potential_barrier
Potential Barrier Simulation Module.
This module defines abstract and concrete classes to model the spatial profile of potential energy barriers at electron-emitting interfaces. It includes standard planar models with image-charge corrections (Schottky effect), localized curvature models suitable for nano-emitter tips with small radii, and the pure triangular barrier with no image charge.
Dependencies
numpy : Array manipulation and vectorized math operations. abc : Base structure handling for abstract classes. getelec.constants : Physical constants library containing electrostatic parameters.
Position below which the image term makes the potential unphysical, in nm.
-k_e/(4x) diverges at the surface, so the barrier has to be cut off
somewhere. The right place is where the potential first crosses zero on the
way up -- the inner root of E_F + phi - F x - k_e/(4x) = 0,
x_c = (W - sqrt(W^2 - k_e F)) / (2F), W = E_F + phi .
Below it the expression is negative only because of the divergence; above it, any negative value is the real barrier falling away past its outer turning point and must be kept.
Parameters
fermi_level, work_function, electric_field : float eV, eV, V/nm.
Returns
float
Abstract base class for potential barriers.
Defines the shared structural interface for computing spatial potential energy profiles relative to an emitting surface boundary.
Calculate the potential energy profile along spatial coordinates.
Parameters
x_points : numpy.ndarray 1D array containing spatial distance coordinates relative to the surface (typically in nm).
Returns
potential : numpy.ndarray 1D array containing the corresponding potential energy values (typically in eV).
Every parameter a barrier's shape depends on, as a hashable tuple.
Read from the instance's own attributes rather than a fixed list, so a subclass that introduces a new parameter is distinguished automatically. A fixed list silently collided: two barriers differing only in a new attribute produced the same cache key, and the solver returned the first one's potential for both.
Barriers that compute their profile from something other than plain
attributes should override parameters to include it.
Planar surface potential model with Schottky image-charge correction.
Models the classical combination of a material's inherent work function barrier, a uniform linear applied external electric field, and the image-charge reduction term felt by a departing electron outside a planar conductive surface.
Parameters
fermi_level : float, default 9.5 The interior Fermi energy level of the material system. work_function : float, default 4.5 The inherent work function barrier of the surface. electric_field : float, default 3.0 The applied external electric field magnitude acting on the interface.
Attributes
fermi_level : float Stored value for the material chemical potential. work_function : float Stored value for the inherent surface work function. electric_field : float Stored value for the active external electric field.
Initialize the SchottkyPotential boundary model.
Evaluate the planar Schottky potential profile across a spatial coordinate array.
Computes the classical image-charge curve for positions outside the emitter and protects against potential energy divergences near the raw boundary layer by floor-clamping negative artifact outputs near the surface.
Parameters
x_points : numpy.ndarray 1D array containing spatial distance coordinates where potential is to be evaluated.
Returns
potential : numpy.ndarray 1D array containing computed potential energy values across the input domain.
Examples
>>> barrier = SchottkyPotential(fermi_level=9.5, work_function=4.5, electric_field=3.0)
>>> distances = np.array([-0.5, 0.0, 1.0, 2.0])
>>> barrier.get_potential(distances)
Curved surface potential model for localized nano-emitter geometries.
Accounts for field enhancement and modified image-force interactions experienced at the boundary tips of high-curvature nanostructures (such as field emission needles), incorporating a tip radius and geometric scaling parameter ($\gamma$).
Parameters
fermi_level : float, default 9.5
The interior Fermi energy level of the material system.
work_function : float, default 4.5
The inherent work function barrier of the surface.
electric_field : float, default 3.0
The macroscopic baseline applied external electric field.
radius : float, default 20.0
The physical radius of curvature of the micro/nano-emitter tip, in nm.
The barrier is valid for 20-1000 nm (RADIUS_VALIDITY); outside
that range the class warns.
gamma : float, default 100
Geometric field enhancement/correction multiplier coefficient.
Attributes
fermi_level : float Stored value for the material chemical potential. work_function : float Stored value for the inherent surface work function. electric_field : float Stored value for the active baseline electric field. radius : float Stored value for the apex radius of curvature. gamma : float Stored value for the geometric enhancement tracking constant.
Notes
Across its valid range the potential is close to the planar
Schottky-Nordheim barrier of SchottkyPotential: at R = 20 nm it
lies within 0.3 eV of it across the barrier at the Fermi level (under 7% of
the work function) at 3-8 V/nm, for gamma = 100 and E_F + phi = 12 eV. The
current depends exponentially on the barrier, so it is not close: at
R = 20 nm it is 0.22, 0.57 and 0.79 times the planar current density at 3,
5 and 8 V/nm, and at 50 nm 0.56, 0.80 and 0.91 times. The difference falls
as 1/R; at 1000 nm, the top of the range, it is 2.8%, 1.1% and 0.6% at 3,
5 and 7 V/nm.
On the axis the applied term is exact to second order in x/R: its curvature is the one Laplace's equation requires at an apex of radius R. The third-order term, c3 F x^3 / R^2, is set by the shape of the emitter away from its apex, which radius and gamma do not describe: c3 = 4/3 for an ellipsoidal tip of any aspect ratio, about 1.05 for a hemisphere on a cylindrical post at gamma = 100, and gamma / (gamma - 1) here. The current density is sensitive to it, most of all near the outer turning point. Against the exact electrostatics of the two shapes (gamma = 100, phi = 4.5 eV, 300 K) this barrier under-predicts the current density at R = 20 nm by 3.3%, 0.7% and 0.26% at 3, 5 and 7 V/nm for an ellipsoidal tip, and by at most 0.5% for a hemisphere on a post; at R = 10 nm the ellipsoidal figures are 16%, 3.1% and 1.1%. The difference grows roughly as phi^(7/2) / (F^3 R^2), which is why the class warns below 20 nm.
Initialize the SmallRadiiPotential boundary model.
Evaluate the non-planar curvature-corrected potential profile across spatial points.
Modifies standard linear field drops and planar image laws into hyperbolic or spherically-weighted components to faithfully map emission barriers near nanoscale apex points.
Parameters
x_points : numpy.ndarray 1D array containing spatial distance coordinates where potential is to be evaluated.
Returns
potential : numpy.ndarray 1D array containing computed potential energy values across the input domain.
Examples
>>> tip_barrier = SmallRadiiPotential(radius=20.0, gamma=50)
>>> coordinates = np.array([0.5, 1.0, 5.0])
>>> tip_barrier.get_potential(coordinates)
Planar triangular barrier: the vacuum level tilted by the field, with no image charge.
The barrier of Fowler and Nordheim (1928),
V(x) = E_F + phi - F x for x > 0, V(x) = 0 inside the metal.
Without the image term there is no Schottky lowering: the maximum is the
full E_F + phi, at the surface, and the barrier is taller and wider than
SchottkyPotential at the same field, so it emits less. Past the
outer turning point the potential keeps falling below zero, as the applied
field makes it; nothing is clamped.
Parameters
fermi_level : float, default 9.5 The interior Fermi energy level of the material system, in eV. work_function : float, default 4.5 The inherent work function barrier of the surface, in eV. electric_field : float, default 3.0 The applied external electric field, in V/nm.
Attributes
fermi_level : float Stored value for the material chemical potential. work_function : float Stored value for the inherent surface work function. electric_field : float Stored value for the active external electric field.
Notes
This is the one barrier with a closed-form transmission:
~getelec.transmission_solutions.AiryTriangular (method="airy")
is exact for it, below and above the barrier top. The analytic
~getelec.transmission_solutions.WKB solver is the
Schottky-Nordheim form and does not describe this barrier.
The potential jumps by E_F + phi at the surface, which a grid solver
resolves only to first order in its step -- by an amount set by where the
surface falls between two grid points, so a node landing on the surface
costs 1.3% in current density at h = 1e-3 nm. The Noumerov grid puts
the surface halfway between two nodes, the placement that cancels the
first-order term: against the exact solution the current density is within
1e-5 at the default step and the transmission within 6e-5, measured for
E_F + phi = 5 to 13.5 eV, 1-12 V/nm and 300-2000 K.
Initialize the TriangularPotential boundary model.
Evaluate the triangular potential profile across a spatial coordinate array.
Parameters
x_points : numpy.ndarray 1D array containing spatial distance coordinates where potential is to be evaluated, in nm.
Returns
potential : numpy.ndarray 1D array containing computed potential energy values across the input domain, in eV.
Examples
>>> barrier = TriangularPotential(fermi_level=7.5, work_function=4.5, electric_field=5.0)
>>> barrier.get_potential(np.array([-0.5, 0.0, 1.0, 3.0]))
array([ 0., 0., 7., -3.])
The keyword names a callable will accept, past its first argument.
Returns "any" for a callable taking **kwargs, None when the
signature cannot be read (a C callable), and otherwise the set of names.
The first positional parameter is left out: it is the position array.
Barrier built from a potential the user supplies.
Takes either a callable V(x) or a tabulated profile and presents it to
the solvers exactly as the shipped barriers do, so a potential worked out
elsewhere -- a screened or self-consistent one, a profile from another code,
measured points -- can be run through the same transmission solvers,
emitters and distributions without subclassing anything.
Parameters
potential : callable or array_like
Either V(x), taking positions in nm and returning energies in eV
pointwise (same shape in, same shape out), or an array of potential
values to be interpolated, in which case positions is required.
positions : array_like, optional
Sample positions for a tabulated potential, nm, strictly increasing.
Not accepted for a callable, which is evaluated wherever the solver
asks.
fermi_level, work_function, electric_field, temperature : float, optional
eV, eV, V/nm and K. Not used to build the potential -- that is entirely
the user's -- but passed to the callable if it takes parameters of
those names, and the first three are what
~getelec.transmission_solver.Noumerov reads to size its
integration domain (auto_domain). Without them the domain falls
back to the solver's max_barrier_width, 3 nm by default, which is
too short for a low field. These four are the parameters
update_params sets on every component at once, so handing this
barrier to ~getelec.metal_emitter() replaces them with that
call's arguments -- which is what keeps a barrier that depends on the
temperature from disagreeing with the supply function about it.
~getelec.semiconductor_emitter() sets none of them: give them
here.
zero_inside : bool, default True
Hold the potential at 0 for x <= 0 and evaluate the user's
potential only outside, which is the convention of every other barrier
here: the energy zero is the bottom of the conduction band, the metal
is flat, and the vacuum level at the surface is E_F + phi. Set it
to False only if the potential describes the metal side itself; the
solver still needs it flat over the last two nodes of the metal, where
the plane-wave match is made.
**extra_parameters
Any further named parameters of the callable, kept on the barrier and
passed at every evaluation. A name the callable will not accept is an
error, not a value silently dropped.
Attributes
potential_function : callable or None The user's callable, or None for a tabulated potential. table_positions, table_potential : numpy.ndarray or None The tabulated profile, or None for a callable. fermi_level, work_function, electric_field, temperature : float or None Stored values, passed to the callable and used to size the domain. zero_inside : bool Whether the metal side is held at zero. extra_parameters : dict The further parameters passed to the callable.
Notes
Units are this package's throughout: x in nm, V in eV, measured from the same zero as the other barriers (0 inside the metal).
The potential must fall below the emitted energies before the end of the
solver's grid. A barrier still above them at the last node is not solved
slightly wrongly, it is meaningless -- that is what auto_domain
protects against for the shipped barriers, and it needs the three
parameters above.
Nothing is clamped near the surface. A potential that diverges there -- an
unscreened image term -- has to be cut off by the caller;
get_image_cutoff() is the position the shipped barriers use.
Only the grid solvers read the barrier. method="wkb" and
method="airy" build their transmission from E_F, phi and F alone, so
with a barrier of your own they return the Schottky-Nordheim and triangular
answers, not yours. Use method="noumerov", the default.
The solvers cache the profile against the barrier's parameters, so a callable is evaluated once per grid rather than once per energy. Its result must therefore depend only on its arguments: a callable reading a global that changes between calls returns the first profile again.
Examples
>>> triangular = Customised(
... lambda x, fermi_level, work_function, electric_field:
... fermi_level + work_function - electric_field * x,
... fermi_level=7.5, work_function=4.5, electric_field=5.0)
>>> triangular.get_potential(np.array([-0.5, 1.0, 3.0]))
array([ 0., 7., -3.])
Initialize the Customised boundary model.
What the profile depends on, for get_barrier_parameters().
The extra parameters are flattened out of their dict so that an array
among them enters the cache key by its contents, as it would if it were
an attribute; a dict enters by repr, which abbreviates a long array
to ... and so collides. The serial number keeps two instances
distinct whatever they hold.
Evaluate the user's potential across a spatial coordinate array.
Parameters
x_points : numpy.ndarray 1D array containing spatial distance coordinates where potential is to be evaluated, in nm.
Returns
potential : numpy.ndarray 1D array containing computed potential energy values across the input domain, in eV.
Raises
ValueError If the potential does not come back pointwise, or is not finite everywhere on the grid -- which a solver would otherwise turn into silent NaNs in the transmission.
Examples
>>> tabulated = Customised(np.array([0.0, 5.0, 2.0]),
... np.array([0.0, 1.0, 2.0]))
>>> tabulated.get_potential(np.array([-1.0, 0.5, 1.5]))
array([0. , 2.5, 3.5])