diff --git a/examples/006_filter_composite_data_example.py b/examples/006_filter_composite_data_example.py index 32bef8815..fb832e296 100644 --- a/examples/006_filter_composite_data_example.py +++ b/examples/006_filter_composite_data_example.py @@ -27,7 +27,7 @@ from ansys.dpf.composites.layup_info import ( AnalysisPlyInfoProvider, get_all_analysis_ply_names, - get_dpf_material_id_by_analyis_ply_map, + get_dpf_material_id_by_analysis_ply_map, ) from ansys.dpf.composites.select_indices import ( get_selected_indices, @@ -123,7 +123,7 @@ # Note: It is not possible to get a DPF material ID for a # given material name. It is only possible to get a DPF material # ID from an analysis ply. -material_map = get_dpf_material_id_by_analyis_ply_map( +material_map = get_dpf_material_id_by_analysis_ply_map( composite_model.get_mesh(), data_source_or_streams_provider=composite_model.data_sources.rst ) ud_material_id = material_map["P1L1__ud_patch ns1"] diff --git a/src/ansys/dpf/composites/_composite_model_impl.py b/src/ansys/dpf/composites/_composite_model_impl.py index d10cc73fb..ddd6dc2cd 100644 --- a/src/ansys/dpf/composites/_composite_model_impl.py +++ b/src/ansys/dpf/composites/_composite_model_impl.py @@ -144,6 +144,34 @@ def material_operators(self) -> MaterialOperators: """Material operators.""" return self._material_operators + @property + def material_names(self) -> Dict[str, int]: + """ + Material name to DPF material ID map. + + This property can be used to filter analysis plies + or element layers. + """ + try: + helper_op = dpf.Operator("composite::materials_container_helper") + except Exception as exc: + raise RuntimeError( + f"Operator composite::materials_container_helper doesn't exist. " + f"This could be because the server version is 2024 R1-pre0. The " + f"latest preview or the unified installer can be used instead. " + f"Error: {exc}" + ) from exc + + helper_op.inputs.materials_container(self._material_operators.material_provider.outputs) + string_field = helper_op.outputs.material_names() + material_ids = string_field.scoping.ids + + names = {} + for mat_id in material_ids: + names[string_field.data[string_field.scoping.index(mat_id)]] = mat_id + + return names + @_deprecated_composite_definition_label def get_mesh(self, composite_definition_label: Optional[str] = None) -> MeshedRegion: """Get the underlying DPF meshed region. diff --git a/src/ansys/dpf/composites/_composite_model_impl_2023r2.py b/src/ansys/dpf/composites/_composite_model_impl_2023r2.py index bd5f3c4d4..244e14b22 100644 --- a/src/ansys/dpf/composites/_composite_model_impl_2023r2.py +++ b/src/ansys/dpf/composites/_composite_model_impl_2023r2.py @@ -143,7 +143,7 @@ def __init__( warn( "The post-processing of composite models with multiple lay-up" " definitions (assemblies) is deprecated with DPF servers older than 7.0" - " (2024 R1). Please use DPF server 7.0 or later.", + " (2024 R1). DPF server 7.0 or later should be used instead.", DeprecationWarning, stacklevel=2, ) @@ -193,6 +193,15 @@ def material_operators(self) -> MaterialOperators: """Material operators.""" return self._material_operators + @property + def material_names(self) -> Dict[str, int]: + """Get material name to DPF material ID map.""" + raise NotImplementedError( + "material_names is not implemented" + " for this version of DPF. DPF server 7.0 (2024 R1)" + " or later should be used instead." + ) + def get_layup_operator(self, composite_definition_label: Optional[str] = None) -> Operator: """Get the lay-up operator. @@ -550,8 +559,9 @@ def get_all_layered_element_ids(self) -> Sequence[int]: """Get all layered element IDs.""" raise NotImplementedError( "get_all_layered_element_ids is not implemented" - " for this version of DPF. Please upgrade to 7.0 (2024 R1)" - " or later. Use get_all_layered_element_ids_for_composite_definition_label" + " for this version of DPF. DPF server 7.0 (2024 R1)" + " or later should be used instead. Use " + "get_all_layered_element_ids_for_composite_definition_label" " instead." ) diff --git a/src/ansys/dpf/composites/composite_model.py b/src/ansys/dpf/composites/composite_model.py index 5e4bb49b1..b54bf27cf 100644 --- a/src/ansys/dpf/composites/composite_model.py +++ b/src/ansys/dpf/composites/composite_model.py @@ -106,6 +106,11 @@ def material_operators(self) -> MaterialOperators: """Material operators.""" return self._implementation.material_operators + @property + def material_names(self) -> Dict[str, int]: + """Get material name to DPF material ID map.""" + return self._implementation.material_names + def get_mesh(self, composite_definition_label: Optional[str] = None) -> MeshedRegion: """Get the underlying DPF meshed region. diff --git a/src/ansys/dpf/composites/layup_info/__init__.py b/src/ansys/dpf/composites/layup_info/__init__.py index f7cd49679..355e913c0 100644 --- a/src/ansys/dpf/composites/layup_info/__init__.py +++ b/src/ansys/dpf/composites/layup_info/__init__.py @@ -11,6 +11,7 @@ get_all_analysis_ply_names, get_analysis_ply_index_to_name_map, get_dpf_material_id_by_analyis_ply_map, + get_dpf_material_id_by_analysis_ply_map, get_element_info_provider, ) @@ -25,6 +26,7 @@ "get_all_analysis_ply_names", "get_analysis_ply_index_to_name_map", "get_dpf_material_id_by_analyis_ply_map", + "get_dpf_material_id_by_analysis_ply_map", "get_element_info_provider", "material_properties", "material_operators", diff --git a/src/ansys/dpf/composites/layup_info/_layup_info.py b/src/ansys/dpf/composites/layup_info/_layup_info.py index c76041d73..06969e553 100644 --- a/src/ansys/dpf/composites/layup_info/_layup_info.py +++ b/src/ansys/dpf/composites/layup_info/_layup_info.py @@ -2,6 +2,7 @@ from dataclasses import dataclass from typing import Any, Collection, Dict, List, Optional, Sequence, Union, cast +from warnings import warn import ansys.dpf.core as dpf from ansys.dpf.core import DataSources, MeshedRegion, Operator, PropertyField @@ -200,6 +201,38 @@ def get_dpf_material_id_by_analyis_ply_map( data_source_or_streams_provider: DPF data source with rst file or streams_provider. The streams provider is available from :attr:`.CompositeModel.core_model` (under metadata.streams_provider). + + Note + ---- + Cache the output because the computation can be performance-critical. + """ + warn( + "`get_dpf_material_id_by_analyis_ply_map` is deprecated. " + " and was replaced by `get_dpf_material_id_by_analysis_ply_map`.", + category=DeprecationWarning, + stacklevel=2, + ) + return get_dpf_material_id_by_analysis_ply_map(mesh, data_source_or_streams_provider) + + +def get_dpf_material_id_by_analysis_ply_map( + mesh: MeshedRegion, + data_source_or_streams_provider: Union[DataSources, Operator], +) -> Dict[str, np.int64]: + """Get the dictionary that maps analysis ply names to DPF material IDs. + + Parameters + ---------- + mesh + DPF Meshed region enriched with lay-up information + data_source_or_streams_provider: + DPF data source with RST file or streams provider. The streams provider is + available from the :attr:`.CompositeModel.core_model` attribute + (under ``metadata.streams_provider``). + + Note + ---- + Cache the output because the computation can be performance-critical. """ # Note: The stream_provider_or_data_source is not strictly needed for this workflow # We just need it because get_element_info_provider provider needs it (which needs diff --git a/src/ansys/dpf/composites/unit_system.py b/src/ansys/dpf/composites/unit_system.py index ec0377c65..3782fb87a 100644 --- a/src/ansys/dpf/composites/unit_system.py +++ b/src/ansys/dpf/composites/unit_system.py @@ -41,9 +41,8 @@ def get_unit_system( if default_unit_system is None: raise RuntimeError( "The result file does not specify a unit system." - " Please define a default unit system. " - "A default unit system can be passed when " - "creating a CompositeModel." + " A default unit system must be defined.. " + "It can be passed when creating a CompositeModel." ) return default_unit_system else: diff --git a/tests/composite_model_test.py b/tests/composite_model_test.py index 04b13aa89..76cba588b 100644 --- a/tests/composite_model_test.py +++ b/tests/composite_model_test.py @@ -14,7 +14,7 @@ from ansys.dpf.composites.layup_info import LayerProperty, get_analysis_ply_index_to_name_map from ansys.dpf.composites.layup_info.material_properties import MaterialProperty from ansys.dpf.composites.result_definition import FailureMeasureEnum -from ansys.dpf.composites.server_helpers import version_older_than +from ansys.dpf.composites.server_helpers import version_equal_or_later, version_older_than from .helper import Timer @@ -83,6 +83,18 @@ def test_basic_functionality_of_composite_model(dpf_server, data_files, distribu assert [ply["id"] for ply in sampling_point.analysis_plies] == analysis_ply_ids + if version_equal_or_later(dpf_server, "7.0"): + ref_material_names = [ + "Epoxy Carbon UD (230 GPa) Prepreg", + "Epoxy Carbon Woven (230 GPa) Wet", + "Honeycomb", + "Structural Steel", + ] + mat_names = composite_model.material_names + assert len(mat_names) == len(ref_material_names) + for mat_name in ref_material_names: + assert mat_name in mat_names.keys() + timer.add("After getting properties") timer.summary() diff --git a/tests/material_properties_test.py b/tests/material_properties_test.py index aa3b1896e..84ebea7fc 100644 --- a/tests/material_properties_test.py +++ b/tests/material_properties_test.py @@ -7,7 +7,7 @@ AnalysisPlyInfoProvider, get_all_analysis_ply_names, get_analysis_ply_index_to_name_map, - get_dpf_material_id_by_analyis_ply_map, + get_dpf_material_id_by_analysis_ply_map, get_element_info_provider, ) from ansys.dpf.composites.layup_info.material_operators import get_material_operators @@ -26,7 +26,7 @@ def test_get_analysis_ply_material_id_map(dpf_server): files = get_basic_shell_files() setup_result = setup_operators(dpf_server, files) - material_map = get_dpf_material_id_by_analyis_ply_map( + material_map = get_dpf_material_id_by_analysis_ply_map( setup_result.mesh, setup_result.streams_provider )