.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "tutorials\mapping\mapping_on_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_coordinates.py: .. _ref_tutorials_mapping_on_coordinates: Interpolation at coordinates ============================= Interpolate field values at arbitrary spatial coordinates using element shape functions. This tutorial demonstrates how to use the :class:`on_coordinates` operator to extract result values at specific locations in a model. The operator interpolates field values at arbitrary coordinates using the mesh shape functions, enabling you to extract results along paths, at sensor locations, or on custom grids. Any target point outside the source mesh returns an empty value. .. GENERATED FROM PYTHON SOURCE LINES 42-45 Import modules and load the model ---------------------------------- Import the required modules and load a result file. .. GENERATED FROM PYTHON SOURCE LINES 45-56 .. 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 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 57-61 Load model ---------- Download the crankshaft result file and create a :class:`Model` object. .. GENERATED FROM PYTHON SOURCE LINES 61-66 .. 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 67-71 Extract displacement results ---------------------------- Get the displacement results from the model as a :class:`FieldsContainer`. .. GENERATED FROM PYTHON SOURCE LINES 71-76 .. code-block:: Python displacement_fc = model.results.displacement.eval() mesh = model.metadata.meshed_region mesh.plot(field_or_fields_container=displacement_fc, title="Crankshaft displacement") .. image-sg:: /tutorials/mapping/images/sphx_glr_mapping_on_coordinates_001.png :alt: mapping on coordinates :srcset: /tutorials/mapping/images/sphx_glr_mapping_on_coordinates_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none (None, ) .. GENERATED FROM PYTHON SOURCE LINES 77-84 Define coordinates of interest -------------------------------- Define a line of 8 equally-spaced probe points 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 ``on_coordinates`` returns an empty value for coordinates with no containing element. .. GENERATED FROM PYTHON SOURCE LINES 84-103 .. code-block:: Python 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" ) 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 Bounding box: x=[-0.0250, 0.0350] y=[-0.0250, 0.0250] z=[-0.0720, 0.0500] m Probe line: 50 points, z from -0.0820 to 0.0600 m (bbox: [-0.0720, 0.0500]) .. GENERATED FROM PYTHON SOURCE LINES 104-109 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 so the spatial context is immediately visible. .. GENERATED FROM PYTHON SOURCE LINES 109-117 .. 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_coordinates_002.png :alt: mapping on coordinates :srcset: /tutorials/mapping/images/sphx_glr_mapping_on_coordinates_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none ([], ) .. GENERATED FROM PYTHON SOURCE LINES 118-122 Map displacement to coordinates -------------------------------- Use the ``on_coordinates`` operator to interpolate displacement values at the defined coordinates. .. GENERATED FROM PYTHON SOURCE LINES 122-129 .. code-block:: Python mapping_op = ops.mapping.on_coordinates( fields_container=displacement_fc, coordinates=coords_field, ) mapped_displacement_fc = mapping_op.eval() .. GENERATED FROM PYTHON SOURCE LINES 130-136 Access mapped results ---------------------- The output field only contains entities for probe points that were found inside an element. Build a full ``(n_pts, 3)`` array—filling ``NaN`` for coordinates outside the mesh—to keep a one-to-one correspondence with the input probe line. .. GENERATED FROM PYTHON SOURCE LINES 136-169 .. code-block:: Python mapped_field = mapped_displacement_fc[0] mapped_data = mapped_field.data found_ids = mapped_field.scoping.ids # 1-based indices of found probe points full_disp = np.full((n_pts, 3), np.nan) for k, eid in enumerate(found_ids): full_disp[eid - 1] = mapped_data[k] in_mesh = ~np.isnan(full_disp[:, 0]) print(f"{in_mesh.sum()} of {n_pts} probe points are inside the mesh") components = ["ux", "uy", "uz"] x = z_pts # use z-coordinate as the x-axis # Line plot: displacement components along the probe line. # Gaps appear where probe points fall outside the mesh. 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_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_coordinates_003.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none 24 of 50 probe points are inside the mesh .. GENERATED FROM PYTHON SOURCE LINES 170-174 Provide mesh explicitly ----------------------- If the input fields do not have a mesh in their support, you can provide the mesh explicitly via the ``mesh`` pin. .. GENERATED FROM PYTHON SOURCE LINES 174-182 .. code-block:: Python mapping_op_with_mesh = ops.mapping.on_coordinates( fields_container=displacement_fc, coordinates=coords_field, mesh=mesh, ) mapped_displacement_with_mesh = mapping_op_with_mesh.eval() .. GENERATED FROM PYTHON SOURCE LINES 183-187 Adjust tolerance for coordinate search ---------------------------------------- Control the tolerance used in the iterative algorithm that locates coordinates inside the mesh. The default value is ``5e-5``. .. GENERATED FROM PYTHON SOURCE LINES 187-195 .. code-block:: Python mapping_op_with_tol = ops.mapping.on_coordinates( fields_container=displacement_fc, coordinates=coords_field, tolerance=1e-4, ) mapped_displacement_with_tol = mapping_op_with_tol.eval() .. GENERATED FROM PYTHON SOURCE LINES 196-199 Map multiple result types -------------------------- The same coordinates can be reused to map different result types. .. GENERATED FROM PYTHON SOURCE LINES 199-227 .. code-block:: Python stress_fc = model.results.stress.eval() mapped_stress_fc = ops.mapping.on_coordinates( fields_container=stress_fc, coordinates=coords_field, ).eval() stress_data_out = mapped_stress_fc[0].data found_stress_ids = mapped_stress_fc[0].scoping.ids full_stress = np.full((n_pts, 6), np.nan) for k, eid in enumerate(found_stress_ids): full_stress[eid - 1] = stress_data_out[k] 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_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_coordinates_004.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 3.652 seconds) .. _sphx_glr_download_tutorials_mapping_mapping_on_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_coordinates.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: mapping_on_coordinates.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: mapping_on_coordinates.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_