Skip to content

Commit 25d861a

Browse files
Merge pull request #699 from zwicker-group/fd_example
Add finite differences example with derivative plots
2 parents e4a01c2 + e692daf commit 25d861a

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
"""
2+
Finite differences approximation
3+
================================
4+
5+
This example displays various finite difference (FD) approximations of derivatives of
6+
simple harmonic function.
7+
"""
8+
9+
import matplotlib.pyplot as plt
10+
import numpy as np
11+
12+
from pde import CartesianGrid, ScalarField
13+
from pde.tools.expressions import evaluate
14+
15+
# create two grids with different resolution to emphasize finite difference approximation
16+
grid_fine = CartesianGrid([(0, 2 * np.pi)], 256, periodic=True)
17+
grid_coarse = CartesianGrid([(0, 2 * np.pi)], 10, periodic=True)
18+
19+
# create figure to present plots of the derivative
20+
fig, axes = plt.subplots(nrows=2, ncols=2, sharex=True, sharey=True)
21+
22+
# plot first derivatives of sin(x)
23+
f = ScalarField.from_expression(grid_coarse, "sin(x)")
24+
f_grad = f.gradient("periodic") # first derivative (from gradient vector field)
25+
ScalarField.from_expression(grid_fine, "cos(x)").plot(
26+
ax=axes[0, 0], label="Expected f'"
27+
)
28+
f_grad.plot(ax=axes[0, 0], label="FD grad(f)", ls="", marker="o")
29+
plt.legend(frameon=True)
30+
plt.ylabel("")
31+
plt.xlabel("")
32+
plt.title(r"First derivative of $f(x) = \sin(x)$")
33+
34+
# plot second derivatives of sin(x)
35+
f_laplace = f.laplace("periodic") # second derivative
36+
f_grad2 = f_grad.divergence("periodic") # second derivative using composition
37+
ScalarField.from_expression(grid_fine, "-sin(x)").plot(
38+
ax=axes[0, 1], label="Expected f''"
39+
)
40+
f_laplace.plot(ax=axes[0, 1], label="FD laplace(f)", ls="", marker="o")
41+
f_grad2.plot(ax=axes[0, 1], label="FD div(grad(f))", ls="", marker="o")
42+
plt.legend(frameon=True)
43+
plt.xlabel("")
44+
plt.title(r"Second derivative of $f(x) = \sin(x)$")
45+
46+
# plot first derivatives of sin(x)**2
47+
g_fine = ScalarField.from_expression(grid_fine, "sin(x)**2")
48+
g = g_fine.interpolate_to_grid(grid_coarse)
49+
expected = evaluate("2 * cos(x) * sin(x)", {"g": g_fine})
50+
fd_1 = evaluate("d_dx(g)", {"g": g}) # first derivative (from directional derivative)
51+
expected.plot(ax=axes[1, 0], label="Expected g'")
52+
fd_1.plot(ax=axes[1, 0], label="FD grad(g)", ls="", marker="o")
53+
plt.legend(frameon=True)
54+
plt.title(r"First derivative of $g(x) = \sin(x)^2$")
55+
56+
# plot second derivatives of sin(x)**2
57+
expected = evaluate("2 * cos(2 * x)", {"g": g_fine})
58+
fd_2 = evaluate("d2_dx2(g)", {"g": g}) # second derivative
59+
fd_11 = evaluate("d_dx(d_dx(g))", {"g": g}) # composition of first derivatives
60+
expected.plot(ax=axes[1, 1], label="Expected g''")
61+
fd_2.plot(ax=axes[1, 1], label="FD laplace(g)", ls="", marker="o")
62+
fd_11.plot(ax=axes[1, 1], label="FD div(grad(g))", ls="", marker="o")
63+
plt.legend(frameon=True)
64+
plt.title(r"Second derivative of $g(x) = \sin(x)^2$")
65+
66+
# finalize plot
67+
plt.tight_layout()
68+
plt.show()

0 commit comments

Comments
 (0)