.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "tutorials\mapping\mapping_on_reduced_coordinates.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_tutorials_mapping_mapping_on_reduced_coordinates.py: .. _ref_tutorials_mapping_on_reduced_coordinates: Reduced coordinates mapping ============================= Perform high-precision interpolation using a two-step element-local coordinate approach. This tutorial demonstrates the ``find_reduced_coordinates`` / ``on_reduced_coordinates`` workflow for mapping field values. In the first step, :class:`find_reduced_coordinates` locates which element contains each target point and computes the element-local (reference) coordinates. In the second step, :class:`on_reduced_coordinates` uses those element-local coordinates to perform the interpolation. Compared to direct :ref:`ref_tutorials_mapping_on_coordinates` mapping, this approach gives explicit access to element-local positions, enables efficient reuse for multiple field types, and supports higher-accuracy quadratic element interpolation. Any target point outside the source mesh returns an empty value. .. GENERATED FROM PYTHON SOURCE LINES 48-51 Import modules and load the model ---------------------------------- Import the required modules and load a result file. .. GENERATED FROM PYTHON SOURCE LINES 51-64 .. code-block:: Python # Import the ``ansys.dpf.core`` module # Import NumPy for coordinate manipulation import matplotlib.pyplot as plt import numpy as np from ansys.dpf import core as dpf # Import the examples and operators modules from ansys.dpf.core import examples, operators as ops from ansys.dpf.core.geometry import Line from ansys.dpf.core.plotter import DpfPlotter .. GENERATED FROM PYTHON SOURCE LINES 65-69 Load model ---------- Download the crankshaft result file and create a :class:`Model` object. .. GENERATED FROM PYTHON SOURCE LINES 69-74 .. code-block:: Python result_file = examples.download_crankshaft() model = dpf.Model(data_sources=result_file) print(model) .. rst-class:: sphx-glr-script-out .. code-block:: none DPF Model ------------------------------ Static analysis Unit system: MKS: m, kg, N, s, V, A, degC Physics Type: Mechanical Available results: - node_orientations: Nodal Node Euler Angles - displacement: Nodal Displacement - velocity: Nodal Velocity - acceleration: Nodal Acceleration - reaction_force: Nodal Force - stress: ElementalNodal Stress - elemental_volume: Elemental Volume - stiffness_matrix_energy: Elemental Energy-stiffness matrix - artificial_hourglass_energy: Elemental Hourglass Energy - kinetic_energy: Elemental Kinetic Energy - co_energy: Elemental co-energy - incremental_energy: Elemental incremental energy - thermal_dissipation_energy: Elemental thermal dissipation energy - elastic_strain: ElementalNodal Strain - elastic_strain_eqv: ElementalNodal Strain eqv - element_orientations: ElementalNodal Element Euler Angles - structural_temperature: ElementalNodal Structural temperature ------------------------------ DPF Meshed Region: 69762 nodes 39315 elements Unit: m With solid (3D) elements ------------------------------ DPF Time/Freq Support: Number of sets: 3 Cumulative Time (s) LoadStep Substep 1 1.000000 1 1 2 2.000000 1 2 3 3.000000 1 3 .. GENERATED FROM PYTHON SOURCE LINES 75-81 Extract the mesh ---------------- The mesh is needed by both ``find_reduced_coordinates`` and ``on_reduced_coordinates``. Use :meth:`bounding_box` to confirm the spatial extent of the model before choosing probe points. .. GENERATED FROM PYTHON SOURCE LINES 81-90 .. code-block:: Python mesh = model.metadata.meshed_region bb_data = mesh.bounding_box.data[0] # [xmin, ymin, zmin, xmax, ymax, zmax] print( f"Bounding box: x=[{bb_data[0]:.4f}, {bb_data[3]:.4f}] " f"y=[{bb_data[1]:.4f}, {bb_data[4]:.4f}] " f"z=[{bb_data[2]:.4f}, {bb_data[5]:.4f}] m" ) .. rst-class:: sphx-glr-script-out .. code-block:: none Bounding box: x=[-0.0250, 0.0350] y=[-0.0250, 0.0250] z=[-0.0720, 0.0500] m .. GENERATED FROM PYTHON SOURCE LINES 91-100 Define target coordinates -------------------------- Create a :class:`Field` that holds the probe points at which field values should be interpolated. A line of 8 equally-spaced points is built along the crankshaft z-axis. The range deliberately extends 10 mm beyond each end of the bounding box so that the first and last points fall outside the model—demonstrating how the reduced-coordinates workflow handles coordinates with no containing element. .. GENERATED FROM PYTHON SOURCE LINES 100-112 .. code-block:: Python n_pts = 50 z_pts = np.linspace(bb_data[2] - 0.01, bb_data[5] + 0.01, n_pts) points = np.column_stack( [np.full(n_pts, 0.005), np.zeros(n_pts), z_pts] # fixed x=5 mm, y=0 ) coords_field = dpf.fields_factory.field_from_array(arr=points) print( f"Probe line: {n_pts} points, z from {z_pts[0]:.4f} to {z_pts[-1]:.4f} m " f"(bbox: [{bb_data[2]:.4f}, {bb_data[5]:.4f}])" ) .. rst-class:: sphx-glr-script-out .. code-block:: none Probe line: 50 points, z from -0.0820 to 0.0600 m (bbox: [-0.0720, 0.0500]) .. GENERATED FROM PYTHON SOURCE LINES 113-117 Visualize probe line on the crankshaft ---------------------------------------- Build a :class:`Line` from the two endpoints of the probe path and overlay it on a transparent crankshaft mesh. .. GENERATED FROM PYTHON SOURCE LINES 117-125 .. code-block:: Python probe_line = Line([points[0], points[-1]], n_points=n_pts) pl = DpfPlotter() pl.add_mesh(probe_line.mesh, color="red", line_width=4) pl.add_mesh(mesh, style="surface", show_edges=False, opacity=0.3) pl.show_figure(show_axes=True) .. image-sg:: /tutorials/mapping/images/sphx_glr_mapping_on_reduced_coordinates_001.png :alt: mapping on reduced coordinates :srcset: /tutorials/mapping/images/sphx_glr_mapping_on_reduced_coordinates_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none ([], ) .. GENERATED FROM PYTHON SOURCE LINES 126-130 Step 1: Find reduced coordinates and element IDs ------------------------------------------------- Use ``find_reduced_coordinates`` to determine which element contains each target point and the corresponding element-local (reference) coordinates. .. GENERATED FROM PYTHON SOURCE LINES 130-152 .. code-block:: Python find_op = ops.mapping.find_reduced_coordinates( coordinates=coords_field, mesh=mesh, ) reduced_coords_fc = find_op.outputs.reduced_coordinates() element_ids_sc = find_op.outputs.element_ids() print("Reduced coordinates:") print(reduced_coords_fc) print("Element IDs:") print(element_ids_sc) # The scoping of the reduced-coordinates field records which input probe # points were found inside an element; the rest fall outside the mesh. found_ids = reduced_coords_fc[0].scoping.ids # 1-based input-point indices in_mesh = np.zeros(n_pts, dtype=bool) for eid in found_ids: in_mesh[eid - 1] = True print(f"{in_mesh.sum()} of {n_pts} probe points are inside the mesh") x = z_pts # use z-coordinate as the x-axis .. rst-class:: sphx-glr-script-out .. code-block:: none Reduced coordinates: DPF Fields Container with 1 field(s) defined on labels: Unknown with: - field 0 {Unknown: 1} with Nodal location, 3 components and 24 entities. Element IDs: DPF Scopings Container with 1 scoping(s) defined on labels: Unknown with: - scoping 0 {Unknown: 1, } located on Elemental 24 entities. 24 of 50 probe points are inside the mesh .. GENERATED FROM PYTHON SOURCE LINES 153-157 Step 2: Map displacement to reduced coordinates ------------------------------------------------ Use ``on_reduced_coordinates`` to interpolate displacement values at the reduced coordinates found in step 1. .. GENERATED FROM PYTHON SOURCE LINES 157-169 .. code-block:: Python displacement_fc = model.results.displacement.eval() mesh.plot(field_or_fields_container=displacement_fc, title="Crankshaft displacement") mapping_op = ops.mapping.on_reduced_coordinates( fields_container=displacement_fc, reduced_coordinates=reduced_coords_fc, element_ids=element_ids_sc, mesh=mesh, ) mapped_displacement_fc = mapping_op.eval() .. image-sg:: /tutorials/mapping/images/sphx_glr_mapping_on_reduced_coordinates_002.png :alt: mapping on reduced coordinates :srcset: /tutorials/mapping/images/sphx_glr_mapping_on_reduced_coordinates_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 170-173 Access mapped results ---------------------- Extract and display the interpolated displacement values. .. GENERATED FROM PYTHON SOURCE LINES 173-203 .. code-block:: Python mapped_field = mapped_displacement_fc[0] mapped_data = mapped_field.data element_ids = element_ids_sc[0] # Build full arrays (NaN for outside-mesh points) full_disp = np.full((n_pts, 3), np.nan) for k, eid in enumerate(mapped_field.scoping.ids): full_disp[eid - 1] = mapped_data[k] # Line plot: displacement components along the probe line. # Gaps appear where probe points fall outside the mesh. components = ["ux", "uy", "uz"] fig, axes = plt.subplots(3, 1, figsize=(10, 8), sharex=True) for j, (ax, comp) in enumerate(zip(axes, components)): y_vals = np.where(in_mesh, full_disp[:, j], np.nan) ax.plot(x, y_vals, "o-", ms=3, label=comp) ax.axvspan( x[0], bb_data[2], color="lightgray", alpha=0.4, label="Outside mesh" if j == 0 else "" ) ax.axvspan(bb_data[5], x[-1], color="lightgray", alpha=0.4) ax.set_ylabel("Displacement (m)") ax.set_title(comp) ax.legend(loc="upper right") axes[-1].set_xlabel("z coordinate (m)") plt.suptitle("Interpolated displacement along probe line\n(gray = outside mesh, NaN gaps)") plt.tight_layout() plt.show() .. image-sg:: /tutorials/mapping/images/sphx_glr_mapping_on_reduced_coordinates_003.png :alt: Interpolated displacement along probe line (gray = outside mesh, NaN gaps), ux, uy, uz :srcset: /tutorials/mapping/images/sphx_glr_mapping_on_reduced_coordinates_003.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 204-208 Reuse reduced coordinates for stress -------------------------------------- Once the reduced coordinates and element IDs are available they can be reused to map additional result types efficiently without repeating the search step. .. GENERATED FROM PYTHON SOURCE LINES 208-238 .. code-block:: Python stress_fc = model.results.stress.eval() mapped_stress_fc = ops.mapping.on_reduced_coordinates( fields_container=stress_fc, reduced_coordinates=reduced_coords_fc, element_ids=element_ids_sc, mesh=mesh, ).eval() stress_data_out = mapped_stress_fc[0].data full_stress = np.full((n_pts, 6), np.nan) for k, eid in enumerate(mapped_stress_fc[0].scoping.ids): full_stress[eid - 1] = stress_data_out[k] # Line plot: stress components along the probe line. comp_names = ["s_xx", "s_yy", "s_zz", "s_xy", "s_yz", "s_xz"] fig, axes = plt.subplots(3, 2, figsize=(12, 9), sharex=True) for j, (ax, comp) in enumerate(zip(axes.flat, comp_names)): y_vals = np.where(in_mesh, full_stress[:, j], np.nan) ax.plot(x, y_vals, "o-", ms=3, label=comp) ax.axvspan(x[0], bb_data[2], color="lightgray", alpha=0.4) ax.axvspan(bb_data[5], x[-1], color="lightgray", alpha=0.4) ax.set_ylabel("Stress (Pa)") ax.set_title(comp) for ax in axes[-1]: ax.set_xlabel("z coordinate (m)") plt.suptitle("Interpolated stress along probe line\n(gray = outside mesh, NaN gaps)") plt.tight_layout() plt.show() .. image-sg:: /tutorials/mapping/images/sphx_glr_mapping_on_reduced_coordinates_004.png :alt: Interpolated stress along probe line (gray = outside mesh, NaN gaps), s_xx, s_yy, s_zz, s_xy, s_yz, s_xz :srcset: /tutorials/mapping/images/sphx_glr_mapping_on_reduced_coordinates_004.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 239-243 Use quadratic elements for higher precision ------------------------------------------- For meshes with quadratic elements, enable the ``use_quadratic_elements`` option in both operators for higher-order interpolation accuracy. .. GENERATED FROM PYTHON SOURCE LINES 243-283 .. code-block:: Python find_op_quad = ops.mapping.find_reduced_coordinates( coordinates=coords_field, mesh=mesh, use_quadratic_elements=True, ) reduced_coords_quad_fc = find_op_quad.outputs.reduced_coordinates() element_ids_quad_sc = find_op_quad.outputs.element_ids() mapped_disp_quad_fc = ops.mapping.on_reduced_coordinates( fields_container=displacement_fc, reduced_coordinates=reduced_coords_quad_fc, element_ids=element_ids_quad_sc, mesh=mesh, use_quadratic_elements=True, ).eval() quad_data_out = mapped_disp_quad_fc[0].data full_quad = np.full((n_pts, 3), np.nan) for k, eid in enumerate(mapped_disp_quad_fc[0].scoping.ids): full_quad[eid - 1] = quad_data_out[k] # Line plot comparison: linear vs quadratic interpolation fig, axes = plt.subplots(3, 1, figsize=(10, 8), sharex=True) for j, (ax, comp) in enumerate(zip(axes, components)): y_lin = np.where(in_mesh, full_disp[:, j], np.nan) y_quad = np.where(in_mesh, full_quad[:, j], np.nan) ax.plot(x, y_lin, "o-", ms=2, label="Linear") ax.plot(x, y_quad, "s--", ms=2, label="Quadratic") ax.axvspan( x[0], bb_data[2], color="lightgray", alpha=0.4, label="Outside mesh" if j == 0 else "" ) ax.axvspan(bb_data[5], x[-1], color="lightgray", alpha=0.4) ax.set_ylabel("Displacement (m)") ax.set_title(comp) ax.legend(loc="upper right") axes[-1].set_xlabel("z coordinate (m)") plt.suptitle("Displacement: linear vs quadratic interpolation along probe line") plt.tight_layout() plt.show() .. image-sg:: /tutorials/mapping/images/sphx_glr_mapping_on_reduced_coordinates_005.png :alt: Displacement: linear vs quadratic interpolation along probe line, ux, uy, uz :srcset: /tutorials/mapping/images/sphx_glr_mapping_on_reduced_coordinates_005.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 4.025 seconds) .. _sphx_glr_download_tutorials_mapping_mapping_on_reduced_coordinates.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: mapping_on_reduced_coordinates.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: mapping_on_reduced_coordinates.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: mapping_on_reduced_coordinates.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_