## Math for system designers

It is very common to start system design by first solving for key design parameters in an expression that describes the target system, inserting physical constants into that solution to find suitable design scales, select parameter values with unit and tolerance, and finally analyzing the stability of the solution using confidence intervals. Traditionally this requires usage of multiple tools with limited features and therefore is both time-consuming and risky. With quflow tools, it becomes much more easy – a few lines of Python code does it all.

Below is an example within nano-electronics: What charging energy margin does a 10% capacitor designed for >99% production yield have, when designed for tunneling blockade at room temperature?

[python]

>>> from quflow import System, Symbol, constants, K, F, eV, array, std, confidence

>>> charging = System(‘E == (n – C V/e)^2 e^2/(2 C)’); charging.E

-V*e*n + 0.5*C*V**2 + 0.5*e**2*n**2/C

>>> E = charging.E(V=0); E

0.5*e**2*n**2/C

>>> blockade = System( (E(n=1) – E(n=0)) – Symbol(‘dE’), constants )

>>> kT = constants.k*array([ 300, 600, 900 ])*K

>>> C = blockade.C(dE = kT).rescale(F); C

array([ 3.09874425e-18, 1.54937213e-18, 1.03291475e-18]) * F

>>> C0 = confidence( std( 1, .1 )*1e-18*F, 0.99 ); C0

array([ 7.42417069e-19, 1.25758293e-18]) * F

>>> blockade( C = C0.max(), dE = kT ).rescale(eV)

array([ 0.0378486 , 0.01199657, -0.01385546]) * eV

[/python]

Binning:

[python]

>>> decades = grid*10 – 10

>>> for n, i in decades(array([1, 3.14, 42])):

… print n, ‘in decade’, i, ‘%g..%g’% tuple(decades[i:i+2])

2 in decade 1 0..10

1 in decade 5 40..50

[/python]

Slicing – the Matlab/numpy way:

[python]

>>> tuple(grid[0:110:10])

(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)

[/python]

Slicing – by template:

[python]

>>> tuple(grid[0, 10, …, 100])

(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100)

[/python]

Combining with a unit:

[python]

>>> for x in (100 + grid[-10,-5,…,10])*units.nm: print x,

90.0 nm 95.0 nm 100.0 nm 105.0 nm 110.0 nm

[/python]

Conversion from symbolic to numeric units, with support for default units and formats.

[python]

>>> from quantities import nm, m, F, UnitQuantity

>>> aF = UnitQuantity( ‘attofarad’, 1e-18*F, symbol = ‘aF’ )

>>> default.set_units_and_formats(nm, aF, aF/nm, ‘%.2f’)

>>> (10*aF).simplified

array(1.0000000000000003e-35) * s**4*A**2/(kg*nm**2)

>>> default.rescale(_)

array(10.0) * aF

>>> print default.format(_), default.symquantity(_.units)

10.00 aF

[/python]

Sorting array result in increasing order, cut to a certain ‘range’ and/or ‘size’ if specified.

Example: First spin-degenerate states in a flat nanoelectron loop.

[python]

>>> from quantities.constants import e, m_e

>>> from quantities import nm, eV, UnitQuantity

>>> from statistics import independent

>>> default.set_units_and_formats( eV, ‘%.4f’ )

>>> Eml = Spectrum( ‘Em + El’, constants,

… Em = System(‘(m + 0.5)^2 h^2/(8 M w^2)’),

… El = System(‘((l – A B q/h)^2 + 1/4) h^2/(8 pi M A)’),

… q = -e, M = m_e, m = grid[0,1,…], l = grid[…,-1,0,1,…],

… s = (0.5,-0.5) )

>>> print Eml( w = 20*nm, A = 1000*nm**2, B = 0 )

Em El m l

# eV eV eV # #

0 0.0003 0.0002 0.0000 0 0

1 0.0004 0.0002 0.0001 0 -1

2 0.0004 0.0002 0.0001 0 1

3 0.0007 0.0002 0.0005 0 -2

4 0.0007 0.0002 0.0005 0 2

5 0.0013 0.0002 0.0011 0 -3

6 0.0013 0.0002 0.0011 0 3

7 0.0021 0.0021 0.0000 1 0

8 0.0022 0.0002 0.0019 0 -4

9 0.0022 0.0002 0.0019 0 4

>>> print array(zip( Eml.m, Eml.l ))

[[ 0 0]

[ 0 -1]

[ 0 1]

[ 0 -2]

[ 0 2]

[ 0 -3]

[ 0 3]

[ 1 0]

[ 0 -4]

[ 0 4]]

[/python]