Week 1: Continuity, Plotting, and Partial Derivatives#
Demo by Christian Mikkelstrup, Hans Henrik Hermansen, Jakob Lemvig, Karl Johan Måstrup Kristensen og Magnus Troen
from sympy import *
from dtumathtools import *
init_printing()
Welcome back after Christmas and January, and welcome to spring in mat1. There will be a whole lot of new curriculum, and among other things a whole lot of 3D plots! For this we have developed dtumathtools
, which will accompany you during the spring. It contains dtuplot
which should be used for plotting, as well as several good helper functions. You should have dtumathtools installed from mat1a, if not, please run the command
pip install -U dtumathtools
in your terminal.
Functions (of One Variable)#
We can define the function \(f: \mathbb{R} \to \mathbb{R}\), \(f(x)=x \mathrm{e}^x\) as a python function using the familiar command:
def f(x):
return x * exp(x)
The function is evaluated in the point \(x = -2\) with the command:
f(-2)
![../_images/5143a366292d0b8d11a3379e75854f4443da9c761b4e42b6a74d180e08bc3d79.png](../_images/5143a366292d0b8d11a3379e75854f4443da9c761b4e42b6a74d180e08bc3d79.png)
Which has the nummerical value:
f(-2).evalf()
![../_images/0366f0d81388fb2f714c7ad32d87eaf184af7bf112e770b5656ef8bb2cd79bc5.png](../_images/0366f0d81388fb2f714c7ad32d87eaf184af7bf112e770b5656ef8bb2cd79bc5.png)
It is, however, rarely necessary to define functions with the def
-command, and we wil often work directly with the function expression:
x = symbols('x', real = True) # necessary to use x as a symbolic variable (note the real=True, since R -> R)
f_expr = x * exp(x)
f_expr
![../_images/bb59df58659ff15d76d3315db722c41be2564d1029f5061b6a15bbc2bc40d045.png](../_images/bb59df58659ff15d76d3315db722c41be2564d1029f5061b6a15bbc2bc40d045.png)
Which is evaluated by:
f_expr.subs(x, -2)
![../_images/5143a366292d0b8d11a3379e75854f4443da9c761b4e42b6a74d180e08bc3d79.png](../_images/5143a366292d0b8d11a3379e75854f4443da9c761b4e42b6a74d180e08bc3d79.png)
The function can be differentiated by:
f_maerke = f_expr.diff(x)
f_maerke
![../_images/196f67a172cde873c4d8ac79a56d769d3686a88d00f1b8e09d1e1851f0f389f5.png](../_images/196f67a172cde873c4d8ac79a56d769d3686a88d00f1b8e09d1e1851f0f389f5.png)
We can also investigate the limits for \(x \to -\infty\), \(x \to \infty\) and \(x \to -2\) with the commands:
f_expr.limit(x, -oo), f_expr.limit(x, oo), f_expr.limit(x, -2)
![../_images/06902cfb75e0c87555f02cb97e701e9b1b30fe56f3415444175816aa8df020a2.png](../_images/06902cfb75e0c87555f02cb97e701e9b1b30fe56f3415444175816aa8df020a2.png)
It should be no surprise that \(\lim_{x \to -2} f(x) = f(-2)\), since the function is continuous everywhere.
We can plot the function and its derivative by:
plot(f_expr, f_maerke, (x, -5, 1))
![../_images/b938880ec60078719c34ac467eaeab410bdc6a54935396179b0eb458a75df265.png](../_images/b938880ec60078719c34ac467eaeab410bdc6a54935396179b0eb458a75df265.png)
<sympy.plotting.backends.matplotlibbackend.matplotlib.MatplotlibBackend at 0x7f7dcaf240a0>
A little more complicated example could be the piecewise defined function \(g: \mathbb{R} \to \mathbb{R}\):
Which in pyhton would be defined by:
def g(x):
if x < 0:
return -x
else:
return exp(x)
Which again is preferable to define using Sympy:
g_expr = Piecewise((-x, x < 0), (exp(x), x >= 0))
g_expr
Which is evaluated as expected:
g_expr.subs(x, -2)
![../_images/b1fac8f1225f03d1681446e2a59ec935caa3f7b0c81185479a10e26dd6c63c3b.png](../_images/b1fac8f1225f03d1681446e2a59ec935caa3f7b0c81185479a10e26dd6c63c3b.png)
And plotted using:
plot(g_expr,(x,-5,2), ylabel='g(x)')
![../_images/b1ddf369032324f09860dcc79665036edc6447851e5dbf42b6720f334f9fff48.png](../_images/b1ddf369032324f09860dcc79665036edc6447851e5dbf42b6720f334f9fff48.png)
<sympy.plotting.backends.matplotlibbackend.matplotlib.MatplotlibBackend at 0x7f7dc8c92a30>
Notice the function is discontinuous in \(x = 0\). Note that Python/CAS cannot be used to prove discontinuity in \(x = 0\). This would require a so called epsilon-delta-argument, which Python/CAS cannot help us with. Sympy will, for example, differentiate the function without raising any suspicion of discontinuity.
g_expr.diff(x)
We should, however, note that the function isn’t differentiable in \(x = 0\), since it isn’t continuous in this point.
Partial Derivatives using diff
#
For functions of multiple variables we will introdue the partial derivative, aswell as how they can be used. To showcase the partial derivatives we will consider the function:
x, y = symbols('x y')
f = x*y**2+x
f
![../_images/1826ecb9e7061052d604b7e74e71fce0c2df70b654c6589cce14f54f8fa26712.png](../_images/1826ecb9e7061052d604b7e74e71fce0c2df70b654c6589cce14f54f8fa26712.png)
which can be differentiated using diff
f.diff(x), f.diff(y)
![../_images/d49ce783966f42544970fd731cfcc6fe6a24935bebcefd9ba2d3856e9ed8f0cd.png](../_images/d49ce783966f42544970fd731cfcc6fe6a24935bebcefd9ba2d3856e9ed8f0cd.png)
Each of these expression can be differentiated w.r.t \(x\) and \(y\). Which yields these four functions.
f.diff(x).diff(x), f.diff(x).diff(y), f.diff(y).diff(x), f.diff(y).diff(y)
![../_images/c6708f51a80726290ada31bf2c7ee4a8de4f64fdbe1e7f5eda8c7c500b226ad0.png](../_images/c6708f51a80726290ada31bf2c7ee4a8de4f64fdbe1e7f5eda8c7c500b226ad0.png)
These are called the second order derivatives and can be computed directly by:
f.diff(x,2), f.diff(y,2), f.diff(x,y), f.diff(y,x)
![../_images/a42d5e113dc13ab91ad57be2ecae884ef2e25f5f420bc7cb56e51ee8099ef1b9.png](../_images/a42d5e113dc13ab91ad57be2ecae884ef2e25f5f420bc7cb56e51ee8099ef1b9.png)
As last semester we can input values for x and y. For example \(\frac{\partial}{\partial x}f(x,y)\) evaluated in \((-2,3)\)
f.diff(x).subs({x:-2,y:3})
![../_images/ade62f20a7bcb96c8d3ed92debf0a75ef39435164d2934af8a560d7b030168c3.png](../_images/ade62f20a7bcb96c8d3ed92debf0a75ef39435164d2934af8a560d7b030168c3.png)
or \(\frac{\partial}{\partial x\partial y}f(x,y)\), evaluated in \((5,-13)\)
f.diff(x,y).subs({x:5,y:-13})
![../_images/970dc01d48cda10258dc783b17ed4b915b5add84cbc606c08feb206c1895dfb6.png](../_images/970dc01d48cda10258dc783b17ed4b915b5add84cbc606c08feb206c1895dfb6.png)
Plots#
Orienting Graphs#
We will now consider functions of multiple variables, hence plotting in 3D! This leaves us a decission to make, since we need to chose which angle we want to see the graphs from. If we don’t do anything dtuplot, will chose an angle for us, but if we wish to inspect the graph from a certain angle, then camera
can be used. Try changing the values for elev
and azim
.
f = 4-x**2-y**2
p=dtuplot.plot3d(f, (x,-3,3),(y,-3,3), camera = {"elev": 25, "azim": 45})
![../_images/9cac37f48acbd6a9724d0f1c1ca95affb4e9b35c2dc0ed14f37210a13d5bfaf8.png](../_images/9cac37f48acbd6a9724d0f1c1ca95affb4e9b35c2dc0ed14f37210a13d5bfaf8.png)
The plot above was generated as a static PNG-file, which is greate if you wish to print or export the Notebook as a PDF. All plots will be static if we don’t do anything or if we use the command %matplotlib inline
.
If we intead run the command %matplotlib qt
(which in the following block has been commented out, try running the block after removing #), then we enable interactive plots. All subsequent plots, will now “pop out” of VS Code, where we now can rotate the graph.
#%matplotlib qt
About Interactive Plots#
Note: %matplotlib qt
only works when running python on your own computer. It will, for instance, not work if you run Python on an online server like Google Colab. In such cases, widgets can be used instead %matplotlib ipympl
. This does, however, require you to intall the package ipympl
.
Overview of commands:
# %matplotlib inline # static plots
# %matplotlib qt # QT (cute) interactive pop-out plots
# %matplotlib ipympl # Widget/ipynpl interactive inline plots (not as stable as QT, may require a restart of the kernel)
# %matplotlib --list # list of all backends
Aesthetics#
When we wish to change the aesthetics of our plots, we’ll need to use redering_kw={...}
which may look intimidating. It just tells which rendering settings to use, for example color
, alpha
etc. In most cases it’s adequate to just write {...}
, which dtuplot will know means aesthetics.
dtuplot.plot3d(f, (x,-3,3),(y,-3,3), wireframe = True, rendering_kw = {"color": "red", "alpha": 0.5})
![../_images/8113b8a4f6737eec695e26c5b7ef61f6c19a2a3fcb4ddf54d5e9ef1a850d2f1c.png](../_images/8113b8a4f6737eec695e26c5b7ef61f6c19a2a3fcb4ddf54d5e9ef1a850d2f1c.png)
<spb.backends.matplotlib.matplotlib.MatplotlibBackend at 0x7f7dc8c2ae80>
Some aesthetic choices are special enough to be outside of redering_kw, for example wireframe
as seen above, or use_cm
which denotes each value with a color, as seen below.
p=dtuplot.plot3d(f, (x,-3,3),(y,-3,3), use_cm=True, legend=True)
![../_images/74560ab1df661a1a9f20c2a63cb64549f88667c76d7c5d87a0256ad6d9ffd6d5.png](../_images/74560ab1df661a1a9f20c2a63cb64549f88667c76d7c5d87a0256ad6d9ffd6d5.png)
Contours#
We can also plot contours, i.e. a 2D plot of a 3D structure by:
dtuplot.plot_contour(f, (x,-3,3),(y,-3,3), is_filled=False)
![../_images/767b6f873b6546d2a7542a9c2af9b3f990eb5cd4f8f7ace3b554c6ed8ddf4194.png](../_images/767b6f873b6546d2a7542a9c2af9b3f990eb5cd4f8f7ace3b554c6ed8ddf4194.png)
<spb.backends.matplotlib.matplotlib.MatplotlibBackend at 0x7f7dc8bd1730>
And if we wish to chose the exact values shown:
zvals = [-2,-1,0,1]
dtuplot.plot_contour(f, (x,-3,3),(y,-3,3), rendering_kw={"levels":zvals, "alpha":0.5}, is_filled=False)
![../_images/6363470bbb687ba92aaccbe6fe0c883f33a81c0e77a95de8604d9ab6f8a00984.png](../_images/6363470bbb687ba92aaccbe6fe0c883f33a81c0e77a95de8604d9ab6f8a00984.png)
<spb.backends.matplotlib.matplotlib.MatplotlibBackend at 0x7f7dc7f6dc40>
Gradient Vector Fields#
Consider the vector field
The gradient of \(f\) can be computed as:
f = cos(x)+sin(y)
nf = Matrix([f.diff(x), f.diff(y)])
nf
The gradient can also be computed using dtutools.gradient
. Note that this function doesn’t tell us in which order the variables are differentiated.
dtutools.gradient(f)
The gradient vector field can be plotted as shown:
dtuplot.plot_vector(nf, (x,-pi/2,3/2*pi),(y,0,2*pi),scalar=False)
![../_images/4d211a828c7cdc61665191e1c6b759201ccebb85487e4856210687a1be8351ac.png](../_images/4d211a828c7cdc61665191e1c6b759201ccebb85487e4856210687a1be8351ac.png)
<spb.backends.matplotlib.matplotlib.MatplotlibBackend at 0x7f7dc86c3f70>
Or if we want to get fancy (note that rendering_kw
has been split, such that the arrows and contours have their own list of aethetics).
dtuplot.plot_vector(nf, (x,-pi/2,3/2*pi),(y,0,2*pi),
quiver_kw={"color":"black"},
contour_kw={"cmap": "Blues_r", "levels": 20},
grid=False, xlabel="x", ylabel="y",n=15)
![../_images/8945a7c59f2c92eabbeb3bf9c054989725e4e572d2c4ea7e7f621e4e954ee5b4.png](../_images/8945a7c59f2c92eabbeb3bf9c054989725e4e572d2c4ea7e7f621e4e954ee5b4.png)
<spb.backends.matplotlib.matplotlib.MatplotlibBackend at 0x7f7dc8b6f3d0>
Which in 3D can be visualised as
p = dtuplot.plot3d(f, (x,-pi/2,3/2*pi),(y,0,2*pi),use_cm=True, camera={"elev":45, "azim":-65}, legend=True)
![../_images/237c3df74a3c6e0a854487607738c11a111828bfc6a9a511dec60b34ba86b709.png](../_images/237c3df74a3c6e0a854487607738c11a111828bfc6a9a511dec60b34ba86b709.png)