{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Interpolation\n", "\n", "This notebook uses the [Interpolations](https://github.com/JuliaMath/Interpolations.jl) package. As an alternative, consider [Dierckx](https://github.com/kbarbary/Dierckx.jl)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Load Packages and Extra Functions" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "printyellow (generic function with 1 method)" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "using Printf, Interpolations\n", "\n", "include(\"jlFiles/printmat.jl\")" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "using Plots\n", "\n", "#pyplot(size=(600,400))\n", "gr(size=(480,320))\n", "default(fmt = :svg)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "# Interpolation of y = f(x)\n", "\n", "Interpolations are particularly useful when *(a)* we repeatedly want to evaluate a function $f(x)$ that is time consuming to calculate but we are willing to accept approximate results, or *(b)* when we only know $f(x)$ for a grid of $x$ values but we are willing to assume that the function is pretty smooth (perhaps even linear over short intervals).\n", "\n", "In either case, we do something like this:\n", "\n", "1. Calculate $f(x)$ values for a grid of $x$. This creates a \"look-up\" table.\n", "2. Replace the calculation of $f(x_i)$ by interpolating $f(x_i)$ from the \"look-up\" table." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Some Values to Be Interpolated\n", "\n", "As a simple illustration, we interpolate the sine function. (In practice, the interpolation technique is typically applied to more complicated functions.)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "xGrid = range(-pi,stop=pi,length=101) #uniformly spaced grid\n", "yGrid = sin.(xGrid) #y values at xGrid\n", "\n", "p1 = plot( xGrid,yGrid,\n", " linecolor = :red,\n", " linewidth = 2,\n", " legend = nothing,\n", " title = \"the sine function\",\n", " xlabel = \"x\",\n", " ylabel = \"y\" )\n", "display(p1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Interpolate\n", "\n", "The next cell calls on `CubicSplineInterpolation()` to create the \"look-up\" table (more precisely, create an interpolation object). \n", "\n", "To use a cubic spline it is required that the $x_i$ grid is *uniformly spaced* (for instance, 0.1,0.2,...). The case of a non-uniformly spaced $x$ grid is discussed later.\n", "\n", "The option `extrapolation_bc=...` determines how extrapolation beyond the range of the $x_i$ grid is done.\n", "\n", "The second cell interpolates and extrapolates $y$ at some specific $x$ values. " ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "itp = CubicSplineInterpolation(xGrid,yGrid,extrapolation_bc=Flat());" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " x interpolated y true y\n", " 0.250 0.247 0.247\n", " 0.750 0.682 0.682\n", "\n", " x2 extrapolated y\n", " 1.250 0.949\n", " 3.242 0.000\n", " 3.642 0.000\n", "\n" ] } ], "source": [ "x = [0.25,0.75] #to interpolate the y values at\n", "\n", "y_interpolated = itp(x)\n", "printmat([x y_interpolated sin.(x)],colNames=[\"x\",\"interpolated y\",\"true y\"],width=17)\n", "\n", "x2 = [1.25,pi+0.1,pi+0.5] #to extrapolate the y values at\n", "y_extrapolated = itp(x2) #\"extrapolation\" can be done\n", " #inside and outside the range xGrid\n", "printmat([x2 y_extrapolated],colNames=[\"x2\",\"extrapolated y\"],width=17)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Plotting the Results" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "p1 = plot( xGrid,yGrid,\n", " linecolor = :red,\n", " linewidth = 2,\n", " label = \"sine function\",\n", " title = \"the sine function\",\n", " xlabel = \"x\",\n", " ylabel = \"y\" )\n", "scatter!(x,y_interpolated,markercolor=:magenta,markersize=5,marker=:square,label=\"interpolated\")\n", "scatter!(x2,y_extrapolated,markercolor=:blue,markersize=8,label=\"extrapolated\")\n", "display(p1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Interpolation of y = f(x) for General Vectors\n", "\n", "That is, when we cannot guarantee that the look-up table of $y_i=f(x_i)$ is from uniformly spaced $x_i$ values (the grid is irregular). This is useful, for instance, when we have empirical data on $(x_i,y_i)$.\n", "\n", "The approach works similar to before, except that the `CubicSplineInterpolation` must be replaced by `LinearInterpolation`." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "xGrid2 = deleteat!(collect(xGrid),55:60) #non-uniformly spaced grid\n", "yGrid2 = sin.(xGrid2)\n", "\n", "p1 = scatter( xGrid2,yGrid2,\n", " linecolor = :red,\n", " legend = false,\n", " title = \"y\",\n", " xlabel = \"x\" )\n", "display(p1)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " x interpolated y true y\n", " 0.250 0.243 0.247\n", " 0.750 0.682 0.682\n", "\n", " x2 extrapolated y\n", " 1.250 0.949\n", " 3.242 0.000\n", " 3.642 0.000\n", "\n" ] } ], "source": [ "itp2 = LinearInterpolation(xGrid2,yGrid2,extrapolation_bc=Flat())\n", "\n", "y_interpolated = itp2(x)\n", "printmat([x y_interpolated sin.(x)],colNames=[\"x\",\"interpolated y\",\"true y\"],width=17)\n", "\n", "y_extrapolated = itp2(x2)\n", "printmat([x2 y_extrapolated],colNames=[\"x2\",\"extrapolated y\"],width=17)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "@webio": { "lastCommId": null, "lastKernelId": null }, "anaconda-cloud": {}, "kernelspec": { "display_name": "Julia 1.6.0", "language": "julia", "name": "julia-1.6" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", "version": "1.6.0" } }, "nbformat": 4, "nbformat_minor": 1 }