.. 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 :ref:`Go to the end ` 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 ------------------------------- 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. .. note:: When using a Workbench project, use the :func:`.composite_files_from_workbench_harmonic_analysis` method to obtain the input files. .. 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:: Python 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 FAILURE_LABEL, 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:: Python 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:: Python 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:: Python 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:: Python 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:: Python 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:: Python 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-132 .. code-block:: Python # This is a bit confusing, but DPF uses the same label for Frequency and Time FREQ_LABEL = "time" PHASE_LABEL = "phase" 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 133-138 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 138-188 .. code-block:: Python 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 189-192 Compute maximum over all the phases and frequencies for each element and plot the resulting IRF values .. GENERATED FROM PYTHON SOURCE LINES 192-198 .. code-block:: Python 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 199-203 Detailed analysis of the critical element ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Identify the element with the maximum IRF .. GENERATED FROM PYTHON SOURCE LINES 203-207 .. code-block:: Python 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 208-211 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 211-216 .. code-block:: Python 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 217-221 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 221-234 .. code-block:: Python 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 235-237 Compute the critical phase .. GENERATED FROM PYTHON SOURCE LINES 237-244 .. code-block:: Python 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 245-247 Compute critical layer and critical failure mode. .. GENERATED FROM PYTHON SOURCE LINES 247-262 .. code-block:: Python 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 24.221 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-jupyter :download:`Download Jupyter notebook: 010_harmonic_example.ipynb <010_harmonic_example.ipynb>` .. 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-zip :download:`Download zipped: 010_harmonic_example.zip <010_harmonic_example.zip>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_