A current limitation of composite failure tool is that cannot be used in frequency-based analysis such as Random Vibrations.
As stated by our theory manual, in a random vibration analysis, the probability distribution of any combination of stress/strain components is neither Gaussian nor is the mean value zero, meaning that most of composite failure criterion cannot be used, since they are a combination of the stresses/strains. For the same reason, it is also relevant to highlight that stress tensor should not be rotated.
However, taking into account that results of spectrum analysis (including random) is given in layer coordinate system (see help), and that max stress or max strain failure criterion do not make any combination, this might be a way to evaluate our component.
Another point to take into account is that, although the solution provided by Mechanical is always positive, we must consider that stresses could be either positive or negative, which is important when dealing with orthotropic materials. So stresses must be negative scaled and compared to maximum compression strength.
With all these ingredients, we can proceed to evaluate the layered composite against 1sigma stresses/strains. Below the script:
## THIS IS JUST ALL INPUTS NEEDED import ansys.dpf.core as dpf from ansys.dpf.composites.composite_model import CompositeModel from ansys.dpf.composites.data_sources import composite_files_from_workbench_harmonic_analysis from ansys.dpf.composites.constants import FailureOutput from ansys.dpf.composites.failure_criteria import ( CombinedFailureCriterion, MaxStressCriterion, MaxStrainCriterion, ) combined_fc = CombinedFailureCriterion( name="Random Vibration", failure_criteria=[ MaxStrainCriterion(), MaxStressCriterion(), ], ) from ansys.dpf.composites.layup_info.material_properties import MaterialProperty from ansys.dpf.composites.server_helpers import connect_to_or_start_server # Start the server. By default this starts # a new local server and loads the composites plugin server = connect_to_or_start_server() # Read Workbench modal model result_folder_modal = r'here_your_modal_folder' result_folder_rv = r'here_your_rv_folder' composite_files = composite_files_from_workbench_harmonic_analysis(result_folder_modal,result_folder_rv) composite_model = CompositeModel(composite_files, server) # Generate data sources rst_data_source = dpf.DataSources(composite_files.rst[0]) eng_data_source = dpf.DataSources() eng_data_source.add_file_path(composite_files.engineering_data, "EngineeringData") # Read material data material_support_provider = dpf.Operator("support_provider") material_support_provider.inputs.property("mat") material_support_provider.inputs.data_sources(rst_data_source) result_info_provider = dpf.Operator("ResultInfoProvider") result_info_provider.inputs.data_sources(rst_data_source) material_provider = dpf.Operator("eng_data::ans_mat_material_provider") material_provider.inputs.data_sources = eng_data_source material_provider.inputs.unit_system_or_result_info(result_info_provider.outputs.result_info) material_provider.inputs.abstract_field_support( material_support_provider.outputs.abstract_field_support ) material_provider.inputs.Engineering_data_file(eng_data_source) # Read mesh mesh_provider = composite_model.core_model.metadata.mesh_provider # Set time scoping (3 for RV) timeScop = dpf.Scoping() timeScop.ids = [3] # Stress & strains at random vibrations model strain_operator = dpf.operators.result.elastic_strain() strain_operator.inputs.data_sources(rst_data_source) strain_operator.inputs.bool_rotate_to_global(False) strain_operator.inputs.time_scoping.connect(timeScop) strains = strain_operator.outputs.fields_container() stress_operator = dpf.operators.result.stress() stress_operator.inputs.data_sources(rst_data_source) stress_operator.inputs.bool_rotate_to_global(False) stress_operator.inputs.time_scoping.connect(timeScop) stresses = stress_operator.outputs.fields_container() failure_evaluator = dpf.Operator("composite::multiple_failure_criteria_operator") failure_evaluator.inputs.configuration(combined_fc.to_json()) failure_evaluator.inputs.materials_container(material_provider.outputs) failure_evaluator.inputs.stresses_container(stresses) failure_evaluator.inputs.strains_container(strains) failure_evaluator.inputs.mesh(composite_model.get_mesh()) minmax_per_element = dpf.Operator("composite::minmax_per_element_operator") minmax_per_element.inputs.fields_container(failure_evaluator.outputs.fields_container) minmax_per_element.inputs.mesh(mesh_provider.outputs.mesh) minmax_per_element.inputs.material_support(material_support_provider.outputs.abstract_field_support) output = minmax_per_element.outputs.field_max() op_sneg = dpf.operators.math.scale_fc(fields_container=stresses, ponderation=-1.0) stresses_neg = op_sneg.outputs.fields_container() op_eneg = dpf.operators.math.scale_fc(fields_container=strains, ponderation=-1.0) strains_neg = op_eneg.outputs.fields_container() failure_evaluator_neg = dpf.Operator("composite::multiple_failure_criteria_operator") failure_evaluator_neg.inputs.configuration(combined_fc.to_json()) failure_evaluator_neg.inputs.materials_container(material_provider.outputs) failure_evaluator_neg.inputs.stresses_container(stresses_neg) failure_evaluator_neg.inputs.strains_container(strains_neg) failure_evaluator_neg.inputs.mesh(composite_model.get_mesh()) minmax_per_element_neg = dpf.Operator("composite::minmax_per_element_operator") minmax_per_element_neg.inputs.fields_container(failure_evaluator_neg.outputs.fields_container) minmax_per_element_neg.inputs.mesh(mesh_provider.outputs.mesh) minmax_per_element_neg.inputs.material_support(material_support_provider.outputs.abstract_field_support) output_neg = minmax_per_element_neg.outputs.field_max() value_index = 1 op = dpf.operators.min_max.max_by_component() op.inputs.use_absolute_value.connect(False) op.inputs.field1.connect(output[value_index]) op.inputs.field2.connect(output_neg[value_index]) my_field = op.outputs.field() composite_model.core_model.metadata.meshed_region.plot(my_field)