{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Numerical Differentiation\n", "\n", "## Overview, Objectives, and Key Terms\n", " \n", "From [Lecture 1](L01_GettingStarted.ipynb) through the first half of the course, we used Python to assemble models, solve linear systems, check residuals, and interpret response quantities. We now shift toward numerical calculus: computing derivatives from formulas, black-box functions, or sampled data.\n", "\n", "In this lesson, we use Taylor series to derive **finite-difference** approximations for derivatives, then compare three practical derivative estimates: forward/backward differences, central differences, and the **complex-step** method. We finish by moving from a one-dimensional derivative to the **gradient** of a scalar field, which is the derivative object we need for many balance-law and transport applications.\n", "\n", "We will use the symbol $\\Delta$ in formulas and `Delta` in code for the finite-difference step.\n", "\n", "### Objectives\n", "\n", "By the end of this lesson, you should be able to\n", "\n", "- Derive first- and second-derivative finite-difference approximations using Taylor series.\n", "- Explain the difference between truncation error and floating-point roundoff error.\n", "- Compare forward, backward, central, and complex-step derivative estimates for a callable function.\n", "- Estimate a gradient from sampled two-dimensional data using `np.gradient`.\n", "- Use plots as evidence for accuracy, order of accuracy, and derivative direction.\n", "\n", "### Key Terms\n", "\n", "- finite difference\n", "- stencil\n", "- step size, $\\Delta$\n", "- forward difference\n", "- backward difference\n", "- central difference\n", "- truncation error\n", "- roundoff error\n", "- cancellation\n", "- absolute error\n", "- order of accuracy\n", "- first-order approximation\n", "- second-order approximation\n", "- complex-step derivative approximation\n", "- scalar field\n", "- partial derivative\n", "- gradient\n", "- sampled data\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## If, in the beginning, $\\Delta$ didn't go to 0...\n", "\n", "Recall that the derivative of $f(x)$ is\n", "\n", "$$\n", " \\frac{df}{dx} = \\lim_{\\Delta \\to 0} \\frac{f(x+\\Delta)-f(x)}{\\Delta} \\, .\n", "$$\n", "\n", "Here, $h$ (the ubiquitous \"step\" used in calculus books around the world) is swapped for $\\Delta$ (a better symbol that represents \"small change\"). What if that limit is not taken and, instead, a \"small\" value of $\\Delta$ is used? The result is our first **finite-difference** approximation, the **forward difference**:\n", "\n", "$$\n", " f'(x) \\approx \\frac{f(x+\\Delta)-f(x)}{\\Delta} \\, .\n", "$$\n", "\n", "This is called the *forward* difference approximation because $f'(x)$ depends on information (1) at point $x$ and (2) to the right (or forward) of $x$ at $x+\\Delta$. Intuition suggests that this approximation improves with smaller $\\Delta$. \n", "\n", "An equally valid approximation is the **backward difference**:\n", "$$\n", " f'(x) \\approx \\frac{f(x)-f(x-\\Delta)}{\\Delta} \\, .\n", "$$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "