.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples\01-transient_analyses\00-basic_transient.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_examples_01-transient_analyses_00-basic_transient.py: .. _ref_basic_transient: Transient analysis result example ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This example shows how to postprocess a transient result and visualize the outputs. .. GENERATED FROM PYTHON SOURCE LINES 12-20 .. code-block:: Python # Import the necessary modules import matplotlib.pyplot as plt import numpy as np from ansys.dpf import core as dpf from ansys.dpf.core import examples from ansys.dpf.core import operators as ops .. GENERATED FROM PYTHON SOURCE LINES 21-27 Download the transient result example. This example is not included in DPF-Core by default to speed up the installation. Downloading this example should take only a few seconds. Next, create the model and display the state of the result. This transient result file contains several individual results, each at a different timestamp. .. GENERATED FROM PYTHON SOURCE LINES 27-32 .. code-block:: Python transient = examples.download_transient_result() model = dpf.Model(transient) 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: - displacement: Nodal Displacement - reaction_force: Nodal Force - elemental_summable_miscellaneous_data: Elemental Elemental Summable Miscellaneous Data - element_nodal_forces: ElementalNodal Element nodal Forces - stress: ElementalNodal Stress - elemental_volume: Elemental Volume - stiffness_matrix_energy: Elemental Energy-stiffness matrix - artificial_hourglass_energy: Elemental Hourglass Energy - thermal_dissipation_energy: Elemental thermal dissipation energy - kinetic_energy: Elemental Kinetic Energy - co_energy: Elemental co-energy - incremental_energy: Elemental incremental energy - elastic_strain: ElementalNodal Strain - thermal_strain: ElementalNodal Thermal Strains - thermal_strains_eqv: ElementalNodal Thermal Strains eqv - swelling_strains: ElementalNodal Swelling Strains - element_euler_angles: ElementalNodal Element Euler Angles - structural_temperature: ElementalNodal Structural temperature ------------------------------ DPF Meshed Region: 3820 nodes 789 elements Unit: m With solid (3D) elements, shell (2D) elements, shell (3D) elements ------------------------------ DPF Time/Freq Support: Number of sets: 35 Cumulative Time (s) LoadStep Substep 1 0.000000 1 1 2 0.019975 1 2 3 0.039975 1 3 4 0.059975 1 4 5 0.079975 1 5 6 0.099975 1 6 7 0.119975 1 7 8 0.139975 1 8 9 0.159975 1 9 10 0.179975 1 10 11 0.199975 1 11 12 0.218975 1 12 13 0.238975 1 13 14 0.258975 1 14 15 0.278975 1 15 16 0.298975 1 16 17 0.318975 1 17 18 0.338975 1 18 19 0.358975 1 19 20 0.378975 1 20 21 0.398975 1 21 22 0.417975 1 22 23 0.437975 1 23 24 0.457975 1 24 25 0.477975 1 25 26 0.497975 1 26 27 0.517975 1 27 28 0.537550 1 28 29 0.557253 1 29 30 0.577118 1 30 31 0.597021 1 31 32 0.616946 1 32 33 0.636833 1 33 34 0.656735 1 34 35 0.676628 1 35 .. GENERATED FROM PYTHON SOURCE LINES 33-34 Get the timestamps for each substep as a numpy array: .. GENERATED FROM PYTHON SOURCE LINES 34-37 .. code-block:: Python tf = model.metadata.time_freq_support print(tf.time_frequencies.data) .. rst-class:: sphx-glr-script-out .. code-block:: none [0. 0.019975 0.039975 0.059975 0.079975 0.099975 0.119975 0.139975 0.159975 0.179975 0.199975 0.218975 0.238975 0.258975 0.278975 0.298975 0.318975 0.338975 0.358975 0.378975 0.398975 0.417975 0.437975 0.457975 0.477975 0.497975 0.517975 0.53754972 0.55725277 0.57711786 0.59702054 0.61694639 0.63683347 0.65673452 0.67662783] .. GENERATED FROM PYTHON SOURCE LINES 38-42 Obtain minimum and maximum displacements for all results ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Create a displacement operator and set its time scoping request to the entire time frequency support: .. GENERATED FROM PYTHON SOURCE LINES 42-53 .. code-block:: Python disp = model.results.displacement() timeids = range(1, tf.n_sets + 1) # Must use 1-based indexing. disp.inputs.time_scoping(timeids) # Chain the displacement operator with ``norm`` and ``min_max`` operators. min_max_op = ops.min_max.min_max_fc(ops.math.norm_fc(disp)) min_disp = min_max_op.outputs.field_min() max_disp = min_max_op.outputs.field_max() print(max_disp.data) .. rst-class:: sphx-glr-script-out .. code-block:: none [0. 0.00062674 0.0025094 0.00564185 0.00999992 0.01552154 0.02207871 0.02944459 0.03725894 0.04499722 0.05195353 0.05703912 0.05982844 0.05897617 0.05358419 0.04310436 0.02759782 0.00798431 0.0137951 0.03478255 0.05130461 0.05942392 0.05715204 0.04272116 0.01787116 0.01244994 0.04062977 0.05913066 0.06042056 0.0418829 0.01201879 0.03526532 0.05950852 0.06077103 0.03733769] .. GENERATED FROM PYTHON SOURCE LINES 54-55 Plot the minimum and maximum displacements over time: .. GENERATED FROM PYTHON SOURCE LINES 55-64 .. code-block:: Python tdata = tf.time_frequencies.data plt.plot(tdata, max_disp.data, "r", label="Max") plt.plot(tdata, min_disp.data, "b", label="Min") plt.xlabel("Time (s)") plt.ylabel("Displacement (m)") plt.legend() plt.show() .. image-sg:: /examples/01-transient_analyses/images/sphx_glr_00-basic_transient_001.png :alt: 00 basic transient :srcset: /examples/01-transient_analyses/images/sphx_glr_00-basic_transient_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 65-67 Plot the minimum and maximum displacements over time for the X component. .. GENERATED FROM PYTHON SOURCE LINES 67-82 .. code-block:: Python disp_z = disp.Z() disp_z.inputs.time_scoping(timeids) min_max_op = ops.min_max.min_max_fc(ops.math.norm_fc(disp_z)) min_disp_z = min_max_op.outputs.field_min() max_disp_z = min_max_op.outputs.field_max() tdata = tf.time_frequencies.data plt.plot(tdata, max_disp_z.data, "r", label="Max") plt.plot(tdata, min_disp_z.data, "b", label="Min") plt.xlabel("Time (s)") plt.ylabel("X Displacement (m)") plt.legend() plt.show() .. image-sg:: /examples/01-transient_analyses/images/sphx_glr_00-basic_transient_002.png :alt: 00 basic transient :srcset: /examples/01-transient_analyses/images/sphx_glr_00-basic_transient_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 83-87 Postprocessing stress ~~~~~~~~~~~~~~~~~~~~~ Create an equivalent (von Mises) stress operator and set its time scoping to the entire time frequency support: .. GENERATED FROM PYTHON SOURCE LINES 87-103 .. code-block:: Python # Component stress operator (stress) stress = model.results.stress() # Equivalent stress operator eqv = stress.eqv() eqv.inputs.time_scoping(timeids) # Connect to the min_max operator and return the minimum and maximum # fields. min_max_eqv = ops.min_max.min_max_fc(eqv) eqv_min = min_max_eqv.outputs.field_min() eqv_max = min_max_eqv.outputs.field_max() print(eqv_min) .. rst-class:: sphx-glr-script-out .. code-block:: none DPF stress_0.s_eqv Field Location: Nodal Unit: Pa 35 entities Data: 1 components and 35 elementary data IDs data(Pa) ------------ ---------- 0 0.000000e+00 1 6.215362e+02 2 1.017913e+03 ... .. GENERATED FROM PYTHON SOURCE LINES 104-105 Plot the maximum stress over time: .. GENERATED FROM PYTHON SOURCE LINES 105-113 .. code-block:: Python plt.plot(tdata, eqv_min.data, "b", label="Minimum") plt.plot(tdata, eqv_max.data, "r", label="Maximum") plt.xlabel("Time (s)") plt.ylabel("Equivalent Stress (Pa)") plt.legend() plt.show() .. image-sg:: /examples/01-transient_analyses/images/sphx_glr_00-basic_transient_003.png :alt: 00 basic transient :srcset: /examples/01-transient_analyses/images/sphx_glr_00-basic_transient_003.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 114-118 Scoping and stress field coordinates ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The scoping of the stress field can be used to extract the coordinates used for each result: .. GENERATED FROM PYTHON SOURCE LINES 118-125 .. code-block:: Python # Extract a single field from the equivalent stress operator. field = eqv.outputs.fields_container()[28] # Print the first node IDs from the field. print(field.scoping.ids[:10]) .. rst-class:: sphx-glr-script-out .. code-block:: none [508 509 909 910 524 525 534 533 513 908] .. GENERATED FROM PYTHON SOURCE LINES 126-135 As you can see, these node IDs are not in order. Additionally, there may be fewer entries in the field than nodes in the model. For example, stresses are not computed at mid-side nodes. To extract the coordinates for these node IDs, load the mesh from the model and then extract a coordinate for each node index. Here is an inefficient way of getting the coordinates as each individual request must be sent to the DPF service: .. GENERATED FROM PYTHON SOURCE LINES 135-146 .. code-block:: Python # Load the mesh from the model. meshed_region = model.metadata.meshed_region # Print the first 10 coordinates for the field. node_ids = field.scoping.ids for node_id in node_ids[:10]: # Fetch each individual node by node ID. node_coord = meshed_region.nodes.node_by_id(node_id).coordinates print(f"Node ID {node_id} : %8.5f, %8.5f, %8.5f" % tuple(node_coord)) .. rst-class:: sphx-glr-script-out .. code-block:: none Node ID 508 : -0.01251, 0.01403, 0.02310 Node ID 509 : -0.01378, 0.00218, 0.02310 Node ID 909 : -0.03000, 0.00000, 0.02310 Node ID 910 : -0.02121, 0.02121, 0.02310 Node ID 524 : -0.01251, 0.01403, 0.00000 Node ID 525 : -0.01378, 0.00218, 0.00000 Node ID 534 : -0.03000, 0.00000, 0.00000 Node ID 533 : -0.02121, 0.02121, 0.00000 Node ID 513 : -0.00891, -0.00952, 0.02310 Node ID 908 : -0.02121, -0.02121, 0.02310 .. GENERATED FROM PYTHON SOURCE LINES 147-153 Rather than individually querying for each node coordinate of the field, you can use the :func:`map_scoping ` to remap the field data to match the order of the nodes in the meshed region. Obtain the indices needed to get the data from ``field.data`` to match the order of nodes in the mesh: .. GENERATED FROM PYTHON SOURCE LINES 153-167 .. code-block:: Python nodes = meshed_region.nodes ind, mask = nodes.map_scoping(field.scoping) # Show that the order of the remapped node scoping matches the field scoping. print("Scoping matches:", np.allclose(np.array(nodes.scoping.ids)[ind], field.scoping.ids)) # Now plot the von Mises stress relative to the Z coordinates. z_coord = nodes.coordinates_field.data[ind, 2] plt.plot(z_coord, field.data, ".") plt.xlabel("Z Coordinate (m)") plt.ylabel("Equivalent Stress (Pa)") plt.show() .. image-sg:: /examples/01-transient_analyses/images/sphx_glr_00-basic_transient_004.png :alt: 00 basic transient :srcset: /examples/01-transient_analyses/images/sphx_glr_00-basic_transient_004.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Scoping matches: True .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.532 seconds) .. _sphx_glr_download_examples_01-transient_analyses_00-basic_transient.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: 00-basic_transient.ipynb <00-basic_transient.ipynb>` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: 00-basic_transient.py <00-basic_transient.py>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_