.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples/gallery_examples/010_harmonic_example.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note Click :ref:`here ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_examples_gallery_examples_010_harmonic_example.py: .. _harmonic_example: Postprocess a harmonic analysis ------------------------------- .. note:: When using a Workbench project, use the :func:`.composite_files_from_workbench_harmonic_analysis` method to obtain the input files. This example shows how to evaluate failure criteria for a harmonic simulation. It shows how to create a phase sweep to compute the maximum IRF in the frequency-phase space and shows how to identify the critical failure mode and the critical layer. .. GENERATED FROM PYTHON SOURCE LINES 43-49 Set up analysis ~~~~~~~~~~~~~~~ Setting up the analysis consists of loading the required modules, connecting to the DPF server, and retrieving the example files. Load Ansys libraries and matplotlib .. GENERATED FROM PYTHON SOURCE LINES 49-65 .. code-block:: default import ansys.dpf.core as dpf import matplotlib.pyplot as plt from ansys.dpf.composites.composite_model import CompositeModel from ansys.dpf.composites.constants import FailureOutput from ansys.dpf.composites.example_helper import get_continuous_fiber_example_files from ansys.dpf.composites.failure_criteria import ( CombinedFailureCriterion, FailureModeEnum, MaxStressCriterion, TsaiWuCriterion, ) from ansys.dpf.composites.layup_info.material_operators import get_material_operators from ansys.dpf.composites.server_helpers import connect_to_or_start_server from ansys.dpf.composites.unit_system import get_unit_system .. GENERATED FROM PYTHON SOURCE LINES 66-67 Start a DPF server and copy the example files into the current working directory. .. GENERATED FROM PYTHON SOURCE LINES 67-70 .. code-block:: default server = connect_to_or_start_server() composite_files_on_server = get_continuous_fiber_example_files(server, "harmonic") .. GENERATED FROM PYTHON SOURCE LINES 71-72 Create a composite model .. GENERATED FROM PYTHON SOURCE LINES 72-75 .. code-block:: default composite_model = CompositeModel(composite_files_on_server, server) .. GENERATED FROM PYTHON SOURCE LINES 76-77 Define a failure criterion .. GENERATED FROM PYTHON SOURCE LINES 77-85 .. code-block:: default combined_fc = CombinedFailureCriterion( name="My Failure Criteria", failure_criteria=[ MaxStressCriterion(), TsaiWuCriterion(), ], ) .. GENERATED FROM PYTHON SOURCE LINES 86-90 Obtain stresses and strains and compute max IRF over all phases and frequencies ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Get complex stresses and strains at all frequencies .. GENERATED FROM PYTHON SOURCE LINES 90-96 .. code-block:: default stress_operator = composite_model.core_model.results.stress.on_all_time_freqs() stress_operator.inputs.bool_rotate_to_global(False) strain_operator = composite_model.core_model.results.elastic_strain.on_all_time_freqs() strain_operator.inputs.bool_rotate_to_global(False) .. GENERATED FROM PYTHON SOURCE LINES 97-99 Get operators that provide material data .. GENERATED FROM PYTHON SOURCE LINES 99-105 .. code-block:: default material_operators = get_material_operators( composite_model.data_sources.rst, composite_model.data_sources.engineering_data, get_unit_system(composite_model.data_sources.rst), ) .. GENERATED FROM PYTHON SOURCE LINES 106-109 Define the frequency sweep. This is relatively coarse so the example does not take too much time. .. GENERATED FROM PYTHON SOURCE LINES 109-114 .. code-block:: default min_frequency = -180 max_frequency = 180 frequency_step = 60 sweep_phases = range(min_frequency, max_frequency, frequency_step) .. GENERATED FROM PYTHON SOURCE LINES 115-118 Initialize result containers. We create a result container for the failure value, the failure mode and the layer index in which the failure occurs. .. GENERATED FROM PYTHON SOURCE LINES 118-133 .. code-block:: default # This is a bit confusing, but DPF uses the same label for Frequency and Time FREQ_LABEL = "time" PHASE_LABEL = "phase" FAILURE_LABEL = "failure_label" all_phases_and_freqs_failure_value_fc = dpf.FieldsContainer() all_phases_and_freqs_failure_value_fc.labels = [FREQ_LABEL, PHASE_LABEL] all_phases_and_freqs_critical_layer_fc = dpf.FieldsContainer() all_phases_and_freqs_critical_layer_fc.labels = [FREQ_LABEL, PHASE_LABEL] all_phases_and_freqs_failure_mode_fc = dpf.FieldsContainer() all_phases_and_freqs_failure_mode_fc.labels = [FREQ_LABEL, PHASE_LABEL] .. GENERATED FROM PYTHON SOURCE LINES 134-139 Loop over all the phases and evaluate the failure criterion. The result is added to the field containers declared in the previous cell. In the end each container contains a field for each combination of frequency and phase .. GENERATED FROM PYTHON SOURCE LINES 139-189 .. code-block:: default for phase in sweep_phases: # Stress & strains at sweeping phase stress_at_phase = dpf.operators.math.sweeping_phase_fc( fields_container=stress_operator, angle=float(phase), unit_name="deg", abs_value=False ) strain_at_phase = dpf.operators.math.sweeping_phase_fc( fields_container=strain_operator, angle=float(phase), unit_name="deg", abs_value=False ) failure_evaluator = dpf.Operator("composite::multiple_failure_criteria_operator") failure_evaluator.inputs.configuration(combined_fc.to_json()) failure_evaluator.inputs.materials_container(material_operators.material_provider) failure_evaluator.inputs.stresses_container(stress_at_phase) failure_evaluator.inputs.strains_container(strain_at_phase) failure_evaluator.inputs.mesh(composite_model.get_mesh()) # Note: the min/max layer indices are 1-based starting with # Workbench 2024 R1 (DPF server 7.1) minmax_per_element = dpf.Operator("composite::minmax_per_element_operator") minmax_per_element.inputs.fields_container(failure_evaluator) minmax_per_element.inputs.mesh(composite_model.get_mesh()) minmax_per_element.inputs.material_support( material_operators.material_support_provider.outputs.abstract_field_support ) max_for_all_frequencies_at_phase = minmax_per_element.outputs.field_max() for frequency_id in max_for_all_frequencies_at_phase.get_time_scoping().ids: output_label = {FREQ_LABEL: frequency_id, PHASE_LABEL: phase} all_phases_and_freqs_failure_value_fc.add_field( output_label, max_for_all_frequencies_at_phase.get_field( {FAILURE_LABEL: FailureOutput.FAILURE_VALUE.value, FREQ_LABEL: frequency_id} ), ) all_phases_and_freqs_critical_layer_fc.add_field( output_label, max_for_all_frequencies_at_phase.get_field( {FAILURE_LABEL: FailureOutput.MAX_LAYER_INDEX.value, FREQ_LABEL: frequency_id} ), ) all_phases_and_freqs_failure_mode_fc.add_field( output_label, max_for_all_frequencies_at_phase.get_field( {FAILURE_LABEL: FailureOutput.FAILURE_MODE.value, FREQ_LABEL: frequency_id} ), ) .. GENERATED FROM PYTHON SOURCE LINES 190-193 Compute maximum over all the phases and frequencies for each element and plot the resulting IRF values .. GENERATED FROM PYTHON SOURCE LINES 193-199 .. code-block:: default min_max_over_all_op = dpf.operators.min_max.min_max_by_entity() min_max_over_all_op.inputs.fields_container.connect(all_phases_and_freqs_failure_value_fc) max_over_freq_and_phases_f = min_max_over_all_op.outputs.field_max() composite_model.core_model.metadata.meshed_region.plot(max_over_freq_and_phases_f) .. tab-set:: .. tab-item:: Static Scene .. image-sg:: /examples/gallery_examples/images/sphx_glr_010_harmonic_example_001.png :alt: 010 harmonic example :srcset: /examples/gallery_examples/images/sphx_glr_010_harmonic_example_001.png :class: sphx-glr-single-img .. tab-item:: Interactive Scene .. offlineviewer:: /home/runner/work/pydpf-composites/pydpf-composites/doc/source/examples/gallery_examples/images/sphx_glr_010_harmonic_example_001.vtksz .. GENERATED FROM PYTHON SOURCE LINES 200-204 Detailed analysis of the critical element ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Identify the element with the maximum IRF .. GENERATED FROM PYTHON SOURCE LINES 204-208 .. code-block:: default maximum_element_scoping = max_over_freq_and_phases_f.max().scoping max_element_id = maximum_element_scoping[0] print(f"The element with highest IRF is {max_element_id}.") .. rst-class:: sphx-glr-script-out .. code-block:: none The element with highest IRF is 3. .. GENERATED FROM PYTHON SOURCE LINES 209-212 Scope container with all frequencies and phases to critical element so we can plot the critical IRF over all the frequencies .. GENERATED FROM PYTHON SOURCE LINES 212-217 .. code-block:: default rescope_to_crit_element_op = dpf.operators.scoping.rescope_fc() rescope_to_crit_element_op.inputs.fields_container.connect(all_phases_and_freqs_failure_value_fc) rescope_to_crit_element_op.inputs.mesh_scoping.connect(maximum_element_scoping) all_phases_and_freqs_critical_element_fc = rescope_to_crit_element_op.outputs.fields_container() .. GENERATED FROM PYTHON SOURCE LINES 218-222 Compute the maximum IRF over all the phases for each frequency and plot the result for the critical element. Note: this can be different from maximum overall IRF at each frequency, because we look only at the element that has the highest IRF overall. .. GENERATED FROM PYTHON SOURCE LINES 222-235 .. code-block:: default min_max_over_phases_op = dpf.operators.min_max.min_max_over_label_fc() min_max_over_phases_op.inputs.fields_container.connect(all_phases_and_freqs_critical_element_fc) min_max_over_phases_op.inputs.label.connect(FREQ_LABEL) max_value_for_each_freq_crit_element = min_max_over_phases_op.outputs.field_max() fig, axs = plt.subplots(1) frequencies = composite_model.core_model.metadata.time_freq_support.time_frequencies.data axs.set_xlabel("Frequency (1/s)") axs.set_ylabel("Max IRF in critical element (-)") axs.plot(frequencies, max_value_for_each_freq_crit_element.data) .. image-sg:: /examples/gallery_examples/images/sphx_glr_010_harmonic_example_002.png :alt: 010 harmonic example :srcset: /examples/gallery_examples/images/sphx_glr_010_harmonic_example_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none [] .. GENERATED FROM PYTHON SOURCE LINES 236-238 Compute the critical phase .. GENERATED FROM PYTHON SOURCE LINES 238-245 .. code-block:: default freq_id_highest_IRF = max_value_for_each_freq_crit_element.max().scoping[0] index_highest_IRF = max_value_for_each_freq_crit_element.scoping.index(freq_id_highest_IRF) critical_phases_over_freqs = min_max_over_phases_op.outputs.domain_ids_max() critical_phase_at_critical_freq = critical_phases_over_freqs[index_highest_IRF] print(f"The phase with the highest IRF is {critical_phase_at_critical_freq}°.") .. rst-class:: sphx-glr-script-out .. code-block:: none The phase with the highest IRF is -120°. .. GENERATED FROM PYTHON SOURCE LINES 246-248 Compute critical layer and critical failure mode. .. GENERATED FROM PYTHON SOURCE LINES 248-263 .. code-block:: default max_layer_at_critical_phase_and_time_f = all_phases_and_freqs_critical_layer_fc.get_field( {FREQ_LABEL: freq_id_highest_IRF, PHASE_LABEL: critical_phase_at_critical_freq} ) max_layer_index = max_layer_at_critical_phase_and_time_f.get_entity_data_by_id(max_element_id)[0] all_analyis_plies = composite_model.get_analysis_plies(max_element_id) critical_ply_name = all_analyis_plies[int(max_layer_index)] mode_at_critical_phase_and_time_f = all_phases_and_freqs_failure_mode_fc.get_field( {FREQ_LABEL: freq_id_highest_IRF, PHASE_LABEL: critical_phase_at_critical_freq} ) critical_mode = mode_at_critical_phase_and_time_f.get_entity_data_by_id(max_element_id)[0] print(f"The critical ply is {critical_ply_name}.") print(f"The maximum IRF is {max_over_freq_and_phases_f.max().data[0]}.") print(f"The critical failure mode is {FailureModeEnum(int(critical_mode)).name}.") .. rst-class:: sphx-glr-script-out .. code-block:: none The critical ply is P1L1__ModelingPly.3. The maximum IRF is 0.17852210868866686. The critical failure mode is s1c. .. rst-class:: sphx-glr-timing **Total running time of the script:** ( 0 minutes 25.880 seconds) .. _sphx_glr_download_examples_gallery_examples_010_harmonic_example.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: 010_harmonic_example.py <010_harmonic_example.py>` .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: 010_harmonic_example.ipynb <010_harmonic_example.ipynb>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_