pynitride.core.mesh module

Meshing, submeshing, and manipulating functions defined on meshes.

pynitride.core.mesh.DeltaFunction(mesh, z, integral=1, i=None, pos='node')

A function which is only non-zero at a single location

Parameters:
  • mesh – the mesh on which this function is defined

  • z – the location of the delta function (index nearest this point will be used)

  • integral – the integrated value of this delta function (ie prefactor)

  • i – if specified, z will be ignored and i is the exact index where the delta will be placed

  • pos – build on a node mesh or mid mesh

Returns:

the delta function as a Function

class pynitride.core.mesh.Function(mesh, pos, value=nan, dtype='float', empty=False)

Bases: ndarray

Represents a generic function defined on a Mesh.

This classes subclasses Numpy’s ndarray so vectorized math should just work. Functions are arbitrarily shaped/dimensioned ndarray’s, with the constraint that the last dimension matches the length of the (point or mid) mesh on which it is defined.

A Function can be initialized via the value or empty parameter in numerous ways:

  • if the empty argument is supplied, an empty (ie values uninitialized) array will be constructed with the shape specified as a tuple to empty

  • if value is an array whose last dimension matches the mesh already, this function will just be a view of value.

  • if value is a number (or generally, a non-iterable), it will be repeated to the length of the mesh.

  • if value is one-dimensional but doesn’t match the mesh, it will be converted to two-dimensional and tiled along the trival axis to the length of the node mesh.

Parameters:
  • mesh – the Mesh on which this function is defined

  • value – (see above) the default value to initialize this array with

  • dtype

    the Numpy data type of the array (See ndarray.)

  • empty – (see above) False to use value, or shape tuple to construct an array.

differentiate(fill_value=nan)

Central-difference derivative

Differentiate, accounting for the appropriate potentially non-uniform mesh spacing. Note that the derivative of a node function is a mid function, and vice-versa.

Parameters:

fill_value – when differentiating a mid-function to a node-function, the central-difference derivative at the boundary is not defined, this parameter provides a way to fill those boundary points in.

Returns:

a Function representing the derivative.

integrate(flipped=False, definite=False)

Cumulative integral in either direction, or definite integral

Integrate, accounting for the appropriate potentially non-uniform mesh spacing Note that the integral of a node function is a mid function, and vice-versa. When integrating a node function to a mid function, the last point is ignored. When integrating a mid function to a node function, the first point is zero.

Parameters:
  • flipped – If True, integrate from \(+z\) to \(-z\), rather than the default \(-z\) to \(+z\)

  • definite – give just the total integral rather than computing the cumulative. Note that, when integrating a mid function, this the last point of the cumulative result, but that’s not true for a node function.

Returns:

a Function or, if definite, just a number

plot(*args, **kwargs)

Convenience function to plot this function versus mesh positions via matplotlib.

*args and **kwargs are passed directly to matplotlib’s plot() (See Matplotlib docs.)

restrict(submesh)

Returns a view of this function restricted to the given submesh.

Parameters:

submesh – the submesh on which this function is needed

Returns:

a Function of the same type, which shares, not copies, data with the original

tmf(interp='z')

Ensure that a Function is defined on the node mesh.

Parameters:

interp'z' for a linear interpolation which accounts for non-uniform point spacing (and boundaries by extrapolation). 'unweighted' for a straightforward average of adjacent points (and boundaries are the boundaries of the mid mesh).

Returns:

a node function (which is the original if its already a node function)

tnf(interp='z')

Ensure that a Function is defined on the node mesh.

Parameters:

interp'z' for a linear interpolation which accounts for non-uniform point spacing (and boundaries by extrapolation). 'unweighted' for a straightforward average of adjacent points (and boundaries are the boundaries of the mid mesh).

Returns:

a node function (which is the original if its already a node function)

tpf(interp='z')
class pynitride.core.mesh.GradedLayer(name, thickness, **kwargs)

Bases: Layer

A uniform chunk of simulation domain which will be guaranteed to end on node-points

That is to say, the properties specified by kwargs will be uniform

Parameters:
  • name – an arbitrary name for the layer

  • thickness – the thickness of the layer

  • kwargs – any other properties specified uniformly in the region

place(mesh)

Places the layer onto the mesh (called by MaterialBlock.place, filling in uniform values.

class pynitride.core.mesh.Layer(name, thickness)

Bases: object

A chunk of simulation domain which will be guaranteed to end on node-points

Parameters:
  • name – an arbitrary name for the layer

  • thickness – the thickness of the layer

property matblock

The material block which contains this layer

property mesh

The submesh owned by this layer

place(mesh)

Places the layer onto the mesh (called by MaterialBlock.place

pynitride.core.mesh.LinearFunction(mesh, vstart, vstop, pos='node')

A function which is only non-zero at a single location

Parameters:
  • mesh – the mesh on which this function is defined

  • vstart – the value at the start (first z) of the function

  • vstop – the value at the end (last z) of the function

  • pos – build on a node mesh or mid mesh

Returns:

a linear function from vstart to vstop as a Function

class pynitride.core.mesh.MaterialBlock(name, matsys, layers)

Bases: object

Represents a region of the simulation consisting of one material system

Parameters:
  • name – arbitrary name for this region

  • matsys – the MaterialSystem

  • layers – a list of layers inside this block As a convenience for supplying stacks, layers of thickness=0 can be supplied without causing issues; they will just be silently filtered out on initialization.

get(item, destmesh=None, destfunc=None)

Returns the requested function retrieving from the material if necessary.

Typical use with no destmesh or destfunc: If the function is already defined on this mesh, returns it. Otherwise, if it’s available from the material system, regturn it

Other use (internal by Mesh): If a destfunc is supplied, the results will be filled into the proper slice of destfunc, and destfunc will be returned.

If a destfunc is not supplied, but destmesh is (and that destmesh is not the mesh of this block), a function will be created matching the dtype found for this key on destmesh, and the values will be filled into the proper slice, and the function will be returned

Parameters:
  • item – the key (string) sought

  • destmesh – (see above)

  • destfunc – (see above)

Returns:

a Function

property mesh

The submesh owned by this material block.

place(mesh, interface_indices)

Places the block onto the submesh, and places all its layers

Parameters:
  • mesh – the submesh assigned to this block

  • interface_indices – list of interfaces (including start and end) along which the layers will be placed

update(destmesh, reason)
pynitride.core.mesh.MaterialFunction(mesh, prop, default=None, dtype='float', pos='mid')

Creates a Function by a piecewise-constant-over-materials definition.

Parameters:
  • mesh – the mesh on which the function is defined.

  • prop – either (1) a function which will be called separately for each layer with the relevant pynitride.paramdb.Material as the sole argument or (2) a property key which will be requested from each dictionary eg “electron.mdos”.

  • default – passed to MidFunction()

  • pos – passed to MidFunction()

Returns:

a MidFunction()

class pynitride.core.mesh.Mesh(stack, max_dz, refinements=[], uniform=False, boundary=['GenericMetal', 'thick'])

Bases: object

Generates and manages a dual, potentially non-uniform mesh and functions defined on it.

See Meshing Scheme for a discussion of the defintion and properties of the mesh.

The algorithm to create the mesh is to step through the regions one-by-one and build the mesh point-by-point. At a point \(z\), the mesh will be extended by adding a maximal \(dz\) which satisfies all the refinement criteria (as a simplification, the criteria are evaluated at \(z\), but not \(z+dz\)). When the mesh being constructed passes an interface, the entire mesh built since the last interface is shrunk uniformly so that the most recent mesh point matches that interface.

Refinement criteria are given as a max spacing \(dz^p_0\) near a refinement point \(z_0\), and an exponential growth rate for that \(dz\). This makes it easy to evaluate at any \(z\) what is the maximal allowed \(dz\). As mentioned, when the mesh is built, the criteria are evaluated at the most recent point z, not at \(z+dz\). So it is possible that \(dz\) may be slightly larger than the refinement criteria if the limiting refinement is to the right. If the mesh is sufficiently dense, the refinement criteria will be approximately satisfied. But, because of this detail, note that these criteria are targets (which will be nearly hit), not guarantees.

Parameters:
  • stack – the EpiStack representing the device

  • max_dz – (number) the maximum mesh spacing allowed globally.

  • refinements – a list of spots where the mesh should be refined. Each element is a triple \((z^p_0,dz^p_0,r)\), where \(z_0\) is the location that should be refined, \(dz^p_0\) is the target mesh spacing in the region of \(z_0\), and \(r\) is the target rate at which the mesh spacing is allowed to exponentially increase moving away from \(z_0\). ie each refinement enforces a constraint of the form \(dz \lesssim dz^p_0 r^{|z-z_0|}\). Note that, when creating a uniform mesh, the only effect of this argument is to reduce max_dz if a refinement with dz^p_0 tighter than max_dz is included.

  • uniform – if True, keep the spacing uniform instead of applying the complicated meshing above

  • boundary – a two-tuple of boundary conditions. At present, the second element must be “thick”, but the first element can be the name of a metal which which the top material knows its Schottky barrier, or can be a number directly specifying the barrier

Nm

Number of mid points

Nn

Number of node points

property dzm

the spacing between locations in the mid mesh as a numpy array

property dzn

the spacing between locations in the node mesh as a numpy array

ensure_function_exists(func, value=nan, dim=(), pos='node', dtype='float')

If it doesn’t exist, make it in the global mesh, if it does, check the dim/pos.

Propagates the function upward to supermeshes.

Parameters:
Returns:

None

get(key)

Get by name a function defined on this mesh.

Search order: (1) if the function is already defined on this mesh, return it. (2) If any material block seems to have the variable, ask all material blocks to fill it in. If they can’t ALL fill it in, an exception will be raised.

Note: if the function is defined on submeshes but not on the global mesh, this method will not find it, but you can call py:func:pynitride.mesh.globalize to bring it onto the global mesh.

get_globalmesh()

Returns the global mesh to which this submesh belongs directly or indirectly.

globalize(func, default=None, submeshes=None)

Finds the function func on submeshes and expands it to a function on the full mesh, ensuring that the functions on submeshes are just restricted views of the full mesh function (no longer independent).

If the function is defined on multiple submeshes in incompatible ways (ie different shapes) or a default is supplied which is incompatible with the way this function is defined on some submesh, the results are not defined and errors may be raised.

Parameters:
  • func – (str) the function name to look for

  • default – a default value to fill into the function where not defined on a submesh

Returns:

the function

has_submesh(submesh)

Looks for submesh

If submesh is a direct child of this mesh, returns True. If submesh is a child of this mesh somewhere down the line, returns the direct child submesh of this mesh under which submesh can be found. Otherwise returns False.

indexm(zm)

Finds the index of the mid mesh location nearest to zm.

Parameters:

zm\(z\) position

Returns:

an index into the mid mesh

indexn(zn)

Finds the index of the node mesh location nearest to zn.

Parameters:

zn\(z\) position

Returns:

an index into the node mesh

property interfaces_mid

list of interfaces and adjacent Layer’s on the mid mesh.

Returns:

each element is a tuple of the form (index_to_left, index_to_right, layer_to_left, layer_to_right)

property interfaces_node

list of interfaces and adjacent Layer’s on the node mesh.

Returns:

each element is a tuple of the form (index, layer_to_left, layer_to_right)

matblock(name)

Returns the material block with the given name (error if not found)

ones_mid

A 1-D all-ones mid function on this mesh

ones_nod

A 1-D all-ones node function on this mesh

plot_mesh(xlim=None)

Plots a 1-D representation of the mesh for visual inspection.

read(filename)

Reads the mesh functions from a file (a numpy .npz)

Mesh should match the one saved from.

Parameters:

filename – path at which to save

restore(data)
save(filename, keys=None)

Saves the mesh functions to a file (a numpy .npz)

Parameters:
  • filename – path at which to save

  • keys – if provided, restrict the saved keys to only these

submesh(zbounds, name='Temporary')

Returns a SubMesh viewing a range of this mesh.

The range is specified by desired \(z\) locations. If you want to specify exact indices instead, use the SubMesh constructor directly.

Parameters:

zbounds – two-element tuple of \(z\) locations to start and stop the submesh (inclusive)

Returns:

a SubMesh which views this mesh in the desired range

submesh_cover(znoints, names)

Returns a cover of the mesh split into submeshes at each point

Parameters:
  • znoints – list of locations (nearest point in node mesh will be used) where to divide the meshes

  • names – a list of names (length one greater than znoints)

Returns:

a list of submeshes

zeros_mid

A 1-D all-zeros mid function on this mesh

zeros_nod

A 1-D all-zeros node function on this mesh

property zm

the locations of the mid mesh as a numpy array

property zn

the locations of the node mesh as a numpy array

pynitride.core.mesh.MidFunction(mesh, value=nan, dtype='float', empty=False)

Returns a function defined on the mid mesh

This is a convenience equivalent to calling Function with pos='mid'. All other arguments are the same.

pynitride.core.mesh.NodFunction(mesh, value=nan, dtype='float', empty=False)

Returns a function defined on the node mesh

This is a convenience equivalent to calling Function() with pos='node'. All other arguments are the same.

class pynitride.core.mesh.SubMesh(mesh, name, start, stop)

Bases: Mesh

Represents a Mesh restricted to to particular segment of a larger mesh.

A submesh is essentially just a view of a mesh within that segment, ie it has all of the same functionality as the Mesh from which it is created, except that all operations on it (eg setting or getting mesh functions) will only affect those functions within the prescribed range. Vitally, the data is shared, not copied, between a mesh and its submeshes.

Note: the constructor for SubMesh takes exact indices as bounds of the submesh region. If you wish to instead specify \(z\)-positions, see the Mesh.submesh() function

Parameters:
  • mesh – the super Mesh within which this submesh will reside

  • start – The lower index (inclusive) of the submesh in the larger mesh

  • stop – The upper index (exclusive) of the submesh in the larger mesh

class pynitride.core.mesh.UniformLayer(name, thickness, **kwargs)

Bases: Layer

A uniform chunk of simulation domain which will be guaranteed to end on node-points

That is to say, the properties specified by kwargs will be uniform

Parameters:
  • name – an arbitrary name for the layer

  • thickness – the thickness of the layer

  • kwargs – any other properties specified uniformly in the region

place(mesh)

Places the layer onto the mesh (called by MaterialBlock.place, filling in uniform values.

pynitride.core.mesh.inner_product(a, b)

Takes the FEM inner product between two functions.

Parameters:
Returns:

the inner product with respect to the FEM metric