**What is a Derivative?**

**Definition 1:**

**Definition 2:**

**Definition 1**is known as a "first-order forward difference" method. Since these numerical methods are really just approximations, the "second-order" and "first-order" refer to the accuracy. Second-order means that the error in the approximation decreases with decreasing h proportional to

**h*h**, while first-order decreases only proportional to

**h**.

The **python_derivative_v1_1.mdl** IC-CAP model file attached at the bottom of this post includes several transforms to compute the derivative:

Using Python Numpy functions - gradient() and diff()

Using the PEL (Programming Extraction Language) derivative function explored in a transform named

**Test_PEL**

I will illustrate the use of IC-CAP's built-in derivative functions in **PEL** as follows.

########################################################################################

der =

**derivative2(x,y,1,34)**

print der

complex gm.M.11[size(der)]

i=0

while i < 34

gm.M.11[i] = der[i]

i = i + 1

end while

return gm

I wanted to implement the same derivative calculation using the IC-CAP Python environment. I've developed a new library for implementing some numerical methods including two different derivative functions that can be called from our transforms. This **ic_math.py** file is included as an attachment to this article. Download the file and copy it to your ICCAP_USER_PYTHON_PATH (typically "C:\Users\<username>\iccap\python").

In my first attempt, I used the **diff** function from the **Numpy** library as shown in the function **icm_derivative_npdiff** code listing from **ic_math.py**:

**icm_derivative_npdiff**(x,y):

Now that we have the function defined in our library we can import it from our **Test_npdiff** transform and call the function to compute the derivative of our sample I-V data set.

# Test_npdiff.py

# Computes the derivative of I-V data using Numpy Diff function

#############################################################################################

from iccap import set_return_array

import numpy as np

import ic_math as m

dydx = **m.icm_derivative_npdiff(x,y)**

if debug: print dydx

gm = [ dydx[i] for i in range(0,len(x)-1) ]

if debug: print "initial gm = {}".format(gm)

# insert dydx starting element to gm at index = 0

# dydx array has 1 less value due to diff function return

gm.insert(0,1E-10)

if debug: print "gm = {}".format(gm)

set_return_array("M", gm)

In my experience, this is usually adequate and the error is negligible when performing extractions of threshold voltage Vth from the Id vs. Vg characteristics of a MOSFET transistor. During this calculation, we compute the derivative of Id with respect to Vg and then find the maximum of the derivative (i.e. Gm_max). At that interpolated Vg, we define a linear function whose slope is equal to Gm_max to superimpose on the IdVg curves. This is illustrated in Ma Long's blog post entitled "Device Modeling 101 - How to Extract Threshold Voltage of MOSFETs." The error in performing these steps is usually greater than any round-off error that may have occurred in computing the derivative. In other words, the simple forward difference approximation for the derivative is usually close enough for this application.

After running the **Test_npdiff** transform and comparing the results to the built-in IC-CAP PEL function, I noticed that there was a * discrepancy* in the computed derivatives, especially in the first points of the I-V curve. The

**numpy**

**.diff()**function was slightly under-estimating the derivative even-though the overall slope of the line was pretty close. The maximum error was at the lower boundary of the curve. Furthermore, the vector returned was one point less in length. When plotting the derivative result against the original I-V data, I had to pad the first point to realign the data points.

Was there an error in my math? Looking at the PEL implementation of the derivative, I noticed that it was using a central difference approximation method which is often more accurate. The simple algorithm shown above using **numpy.diff()** uses the forward difference approximation method, which can be subject to round-off errors when the step size is small.

After some more investigation into the Numpy library functions, I discovered a function that will produce the same result of the Test_PEL transform - the **numpy.gradient()** function. This function uses the second order accurate central difference method for most of the vector. Furthermore, the vector length is preserved, by gracefully handling the lower and upper boundaries. To evaluate this method, I created an additional Python function in the **ic_math** library called **icm_derivative_npgrad **to implement the gradient method as shown below in the code listing:

**icm_derivative_npgrad**( x, y, e1, e2 ):

Now we can call the new **icm_derivative_npgrad** function from our transform named **Test_npgrad** which will uses the gradient function.

#############################################################################################

# Test_npgrad.py

# Computes the derivative of I-V data using Numpy Gradient function

#############################################################################################

from iccap import set_return_array

import numpy as np

import ic_math as m

dydx = **m.icm_derivative_npgrad(x,y,1,2)**

if debug: print dydx

gm = [ dydx[i] for i in range(0,len(x)-1) ]

if debug: print "initial gm = {}".format(gm)

set_return_array("M", gm)

You may notice that I've used a new function **set_return_array()** added to the IC-CAP 2018 Python API which returns a list from a temporary variable to the Transform dataset. This allows this data to be accessible for plotting and is analogous to the RETURN statement in PEL.

As you can see from the table below, the **icm_derivative_npgrad** function yields exactly the same results as the PEL **derivative2** function. Meanwhile, the numpy.diff function underestimates the derivative. I padded the numpy.diff() generated gm data so the first point is non-zero and of the same magnitude of the other data to allow easily plotting the results above. See that the blue and green traces in the graph above are right on top of each other.

### Conclusion

**numpy.gradient()**to perform the same derivative computation as the built-in libraries in IC-CAP. This kind of trade-off between accuracy is quite common with numerical methods for computing derivatives. There are some other 3rd Party libraries that support other methods for numerical differentiation but often require more compute time.