-
Notifications
You must be signed in to change notification settings - Fork 22
[Math][Doc] add a example of performing abitrary function mapping #1473
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| """ | ||
| Shamrock 3D unit vector generator | ||
| ======================================= | ||
|
|
||
| This example shows how to use the unit vector generator | ||
| """ | ||
|
|
||
| # %% | ||
|
|
||
| import matplotlib.pyplot as plt # plots | ||
| import numpy as np # sqrt & arctan2 | ||
|
|
||
| import shamrock | ||
| import sympy as sp | ||
| from scipy.special import erfinv, erf | ||
|
Comment on lines
+13
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
|
|
||
| #random set of points between 0 and 1 | ||
| np.random.seed(111) | ||
| points = np.random.rand(1000)[:] | ||
|
|
||
| range_start = (0,3) | ||
| range_end = (0,1) # must be between 0 and 1 because of the normalization | ||
|
|
||
| #define the function exp(-x^2) using sympy | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| x = sp.symbols('x') | ||
| f = sp.Abs(sp.sin(-x**2)) | ||
|
|
||
| # Numerical integration of f over range_start | ||
| primitive = [] | ||
| primitive_x = [] | ||
| accum = 0 | ||
| dx = (range_start[1] - range_start[0]) / 100 | ||
| for x_val in np.linspace(range_start[0], range_start[1], 100): | ||
| primitive.append(accum) | ||
| primitive_x.append(x_val) | ||
| accum += f.subs(x, x_val).evalf() * dx | ||
|
|
||
| primitive = np.array(primitive) | ||
| primitive_x = np.array(primitive_x) | ||
|
Comment on lines
+29
to
+40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The numerical integration is implemented with a Python # Lambdify the sympy function for faster evaluation with numpy
f_numpy = sp.lambdify(x, f, 'numpy')
# Numerical integration of f over range_start
# Use more points for a better approximation of the integral
num_points = 1001
primitive_x = np.linspace(range_start[0], range_start[1], num_points)
f_vals = f_numpy(primitive_x)
primitive = cumulative_trapezoid(f_vals, primitive_x, initial=0) |
||
|
|
||
| # normalize f so that primitive[-1] = 1 | ||
| norm = primitive[-1] | ||
| primitive = primitive / norm | ||
| f = f / norm | ||
|
|
||
| print(f"primitive = {primitive}") | ||
| print(f"primitive_x = {primitive_x}") | ||
|
Comment on lines
+47
to
+48
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| # plot f | ||
| plt.figure() | ||
| x_plot = np.linspace(range_start[0], range_start[1], 100) | ||
| f_plot = [f.subs(x, x_val).evalf() for x_val in x_plot] | ||
| plt.plot(x_plot, f_plot) | ||
| plt.xlabel("x") | ||
| plt.ylabel("f(x)") | ||
| plt.title("f(x) = exp(-x^2)") | ||
|
Comment on lines
+53
to
+57
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The plot title is incorrect and evaluation of the function inside a list comprehension is inefficient. The title should reflect the actual function being plotted, f_plot = f_numpy(x_plot)
plt.plot(x_plot, f_plot)
plt.xlabel("x")
plt.ylabel("f(x)")
plt.title("f(x) = |sin(-x^2)|") |
||
|
|
||
| # plot primitive | ||
| plt.figure() | ||
| plt.plot(primitive_x, primitive) | ||
| plt.xlabel("x") | ||
| plt.ylabel("primitive(x)") | ||
| plt.title("primitive(x) = integral(f(x))") | ||
|
|
||
| # plot finv | ||
| plt.figure() | ||
| plt.plot(primitive, primitive_x) | ||
| plt.xlabel("x") | ||
| plt.ylabel("finv(x)") | ||
| plt.title("finv(x) = inverse(primitive(x))") | ||
|
|
||
| #interpolate primitive using scipy.interpolate.interp1d | ||
| from scipy.interpolate import interp1d | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| mapping_interp = interp1d(primitive, primitive_x, kind='linear') | ||
|
|
||
| points_mapped = [mapping_interp(point) for point in points] | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| print(f"points = {points}") | ||
| print(f"points_mapped = {points_mapped}") | ||
|
Comment on lines
+79
to
+80
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| plt.figure() | ||
| hist_r, bins_r = np.histogram(points, bins=101, density=True, range=range_end) | ||
| r = np.linspace(bins_r[0], bins_r[-1], 101) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| plt.bar(bins_r[:-1], hist_r, np.diff(bins_r), alpha=0.5) | ||
| plt.xlabel("$r$") | ||
| plt.ylabel("$f(r)$") | ||
|
|
||
| plt.figure() | ||
| hist_r, bins_r = np.histogram(points_mapped, bins=101, density=True, range=range_start) | ||
| r = np.linspace(bins_r[0], bins_r[-1], 101) | ||
|
|
||
| plt.bar(bins_r[:-1], hist_r, np.diff(bins_r), alpha=0.5) | ||
| plt.plot(r, [f.subs(x, x_val).evalf() for x_val in r]) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| plt.xlabel("$r$") | ||
| plt.ylabel("$f(r)$") | ||
|
|
||
| plt.show() | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The docstring appears to be copied from another example and is not relevant to this script. It describes a "3D unit vector generator," whereas this example demonstrates arbitrary function mapping. Updating the docstring will make the example's purpose clear to users.