.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/b_grids/plot_nonuniform_grid_grad.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_b_grids_plot_nonuniform_grid_grad.py: ================================ Cartesian Gradient (Non-Uniform) ================================ Compute gradients in a Cartesian coordinate system on a non-uniform grid with higher resolution near the origin. .. GENERATED FROM PYTHON SOURCE LINES 10-31 This example demonstrates how to compute gradients in a Cartesian coordinate system using a **non-uniform grid** that provides higher resolution near the origin and sparser coverage near the domain boundaries. We use PyMetric's geometric grid abstractions to handle the complexities of computing numerical derivatives over irregularly spaced points. In particular, this example highlights: - The use of :class:`~grids.core.GenericGrid` for non-uniform grids, - Accurate gradient computation via :meth:`~grids.base.GridBase.dense_gradient`, - Comparison of numerical and analytical gradients in Cartesian coordinates. Such workflows are particularly useful in simulations where local resolution is needed around a feature of interest (e.g., boundary layers, shock fronts, or potential wells), without sacrificing performance over the full domain. ---------------------------- Coordinate Setup ---------------------------- The first thing to do is to create the coordinate system. For this example, we're going to use a cartesian coordinate system in 2D: :class:`~coordinates.coordinate_systems.CartesianCoordinateSystem2D`. .. GENERATED FROM PYTHON SOURCE LINES 31-44 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from matplotlib.colors import LogNorm # sphinx_gallery_thumbnail_number = 3 from pymetric import CartesianCoordinateSystem2D, GenericGrid # Create the coordinate system. We don't need # any parameters for this one. csys = CartesianCoordinateSystem2D() .. GENERATED FROM PYTHON SOURCE LINES 45-53 ---------------------------- Build a Non-Uniform Grid ---------------------------- For this operation, we'd like to have a grid with points clustered around the origin and with lower resolution near the outskirts. One simple prescription for this is the use of the :math:`\tanh` transformation, which will nicely produce this behavior. .. GENERATED FROM PYTHON SOURCE LINES 53-73 .. code-block:: Python # Define a tanh streching function. def tanh_scale(num_points, x0, x1, s=1): # Create linear spacing from -1 -> 1. u = np.linspace(-1, 1, num_points) u_stretched = np.sign(u) * (np.abs(u) ** s) return x0 + (x1 - x0) * (u_stretched + 1) / 2 # Generate 2D coordinates x = tanh_scale(128, -1, 1, s=3) y = tanh_scale(128, -1, 1, s=3) # Define the bounding box for the coordinate domain bbox = [[-1, -1], [1, 1]] # Create the grid grid = GenericGrid(csys, [x, y], bbox=bbox, center="cell") .. GENERATED FROM PYTHON SOURCE LINES 74-77 A nice feature of PyMetric grids is that you can easily visualize slices of them using the :func:`~grids.base.GridBase.plot_grid_lines` function. We can do that here to validate that we have achieved our intentions: .. GENERATED FROM PYTHON SOURCE LINES 77-81 .. code-block:: Python fig, ax = plt.subplots(1, 1) grid.plot_grid_lines(include_ghosts=True, ax=ax) plt.show() .. image-sg:: /auto_examples/b_grids/images/sphx_glr_plot_nonuniform_grid_grad_001.png :alt: plot nonuniform grid grad :srcset: /auto_examples/b_grids/images/sphx_glr_plot_nonuniform_grid_grad_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 82-99 ---------------------------- Define the Field ---------------------------- We'll now define a scalar field over this grid to test the gradient computation. Specifically, we define: .. math:: \Phi(x, y) = \sin\left[aR^2\right],\; R^2 = x^2 + y^2 where :math:`a` is a tunable frequency parameter. The analytical gradient is .. math:: \nabla_i \Phi = \begin{bmatrix}2ax \cos(a R^2)\\2ay\cos(aR^2)\end{bmatrix} .. GENERATED FROM PYTHON SOURCE LINES 99-115 .. code-block:: Python a = 5.0 # Frequency parameter # Generate meshgrid from the grid X, Y = grid.compute_domain_mesh(axes=["x", "y"]) R2 = X**2 + Y**2 Phi = np.sin(a * R2) # Plot the scalar field fig, ax = plt.subplots() c = ax.pcolormesh(X, Y, Phi, shading="auto", cmap="viridis") fig.colorbar(c, ax=ax, label=r"$\Phi(x, y)$") ax.set_aspect("equal") ax.set_title(r"Scalar Field $\Phi = \sin[a(x^2 + y^2)]$") plt.show() .. image-sg:: /auto_examples/b_grids/images/sphx_glr_plot_nonuniform_grid_grad_002.png :alt: Scalar Field $\Phi = \sin[a(x^2 + y^2)]$ :srcset: /auto_examples/b_grids/images/sphx_glr_plot_nonuniform_grid_grad_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 116-126 ---------------------------- Compute the Gradient ---------------------------- Now we'll compute the gradient of the field numerically using PyMetric's grid interface. This computes: .. math:: \nabla \Phi = \left[ \frac{\partial \Phi}{\partial x}, \frac{\partial \Phi}{\partial y} \right] .. GENERATED FROM PYTHON SOURCE LINES 126-145 .. code-block:: Python grad = grid.dense_gradient(Phi, ["x", "y"], edge_order=2) # Plot the gradient components fig, axes = plt.subplots(1, 2, figsize=(12, 5)) labels = [r"$\partial \Phi / \partial x$", r"$\partial \Phi / \partial y$"] for i, ax in enumerate(axes): c = ax.pcolormesh( X, Y, grad[..., i], shading="auto", cmap="seismic", vmin=-10, vmax=10 ) fig.colorbar(c, ax=ax, label=labels[i]) ax.set_title(labels[i]) ax.set_aspect("equal") plt.suptitle(r"Gradient Components of $\Phi$", fontsize=14) plt.tight_layout() plt.show() .. image-sg:: /auto_examples/b_grids/images/sphx_glr_plot_nonuniform_grid_grad_003.png :alt: Gradient Components of $\Phi$, $\partial \Phi / \partial x$, $\partial \Phi / \partial y$ :srcset: /auto_examples/b_grids/images/sphx_glr_plot_nonuniform_grid_grad_003.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 146-156 --------------------------------- Compare with Analytical Gradient --------------------------------- The analytical gradient is: .. math:: \nabla_i \Phi = \begin{bmatrix}2ax \cos(a R^2)\\2ay\cos(aR^2)\end{bmatrix} .. GENERATED FROM PYTHON SOURCE LINES 156-188 .. code-block:: Python dPhi_dx_exact = 2 * a * X * np.cos(a * R2) dPhi_dy_exact = 2 * a * Y * np.cos(a * R2) # Compute error err_x = np.abs((grad[..., 0] - dPhi_dx_exact) / dPhi_dx_exact) err_y = np.abs((grad[..., 1] - dPhi_dy_exact) / dPhi_dy_exact) print(f"Mean relative error: {np.mean(err_x)},{np.mean(err_y)}.") # Plot errors fig, axes = plt.subplots(1, 2, figsize=(12, 5)) titles = [r"$\partial \Phi / \partial x$ Error", r"$\partial \Phi / \partial y$ Error"] errors = [err_x, err_y] for i, ax in enumerate(axes): c = ax.pcolormesh( X, Y, errors[i], shading="auto", cmap="binary", norm=LogNorm(vmax=0.1, vmin=1e-7), ) fig.colorbar(c, ax=ax) ax.set_title(titles[i]) ax.set_aspect("equal") plt.suptitle( r"Gradient Relative Error (Numerical - Analytical)/Analytical", fontsize=14 ) plt.tight_layout() plt.show() .. image-sg:: /auto_examples/b_grids/images/sphx_glr_plot_nonuniform_grid_grad_004.png :alt: Gradient Relative Error (Numerical - Analytical)/Analytical, $\partial \Phi / \partial x$ Error, $\partial \Phi / \partial y$ Error :srcset: /auto_examples/b_grids/images/sphx_glr_plot_nonuniform_grid_grad_004.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Mean relative error: 0.014364471045282894,0.014364471045282892. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.922 seconds) .. _sphx_glr_download_auto_examples_b_grids_plot_nonuniform_grid_grad.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_nonuniform_grid_grad.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_nonuniform_grid_grad.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_nonuniform_grid_grad.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_