Skip to content

Commit

Permalink
implement material_metadata instead of ply_type
Browse files Browse the repository at this point in the history
  • Loading branch information
roosre committed Jun 3, 2024
1 parent 9eb512e commit c020952
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 61 deletions.
72 changes: 46 additions & 26 deletions src/ansys/dpf/composites/_composite_model_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,7 @@
import numpy as np
from numpy.typing import NDArray

from ._composite_model_impl_helpers import (
_create_material_container_helper_op,
_deprecated_composite_definition_label,
_merge_containers,
)
from ._composite_model_impl_helpers import _deprecated_composite_definition_label, _merge_containers
from .composite_scope import CompositeScope
from .constants import REF_SURFACE_NAME
from .data_sources import (
Expand All @@ -59,7 +55,11 @@
_get_reference_surface_and_mapping_field,
)
from .layup_info.material_operators import MaterialOperators, get_material_operators
from .layup_info.material_properties import MaterialProperty, get_constant_property_dict
from .layup_info.material_properties import (
MaterialMetadata,
MaterialProperty,
get_constant_property_dict,
)
from .result_definition import FailureMeasureEnum
from .sampling_point import SamplingPointNew
from .server_helpers import (
Expand Down Expand Up @@ -198,7 +198,13 @@ def material_names(self) -> dict[str, int]:
This property can be used to filter analysis plies
or element layers by material name.
"""
helper_op = _create_material_container_helper_op(self._material_operators.material_provider)
helper_op = self._material_operators.material_container_helper_op
if helper_op is None:
raise RuntimeError(
"The used DPF server does not support the requested data. "
"Use version 2024 R1-pre0 or later."
)

string_field = helper_op.outputs.material_names()
material_ids = string_field.scoping.ids

Expand All @@ -209,32 +215,46 @@ def material_names(self) -> dict[str, int]:
return names

@property
def ply_types(self) -> dict[str, int]:
def material_metadata(self) -> dict[int, MaterialMetadata]:
"""
Ply type to DPF material ID map.
DPF material ID to metadata map of the materials.
This property can be used to filter analysis plies
or element layers by ply type. Ply type is one of
the following values ``regular``,
``woven``, ``honeycomb_core``,
``isotropic_homogeneous_core``, ``orthotropic_homogeneous_core``,
``isotropic``, ``adhesive``, ``undefined``. Regular stands for uni-directional.
This data can be used to filter analysis plies
or element layers by ply type, material name etc.
Note: ply type is only available in DPF server version 9.0 (2025 R1 pre0) and later.
"""
helper_op = _create_material_container_helper_op(self._material_operators.material_provider)
helper_op = self._material_operators.material_container_helper_op
if helper_op is None:
raise RuntimeError(
"The used DPF server does not support the requested data."
"Use version 2024 R1-pre0 or later."
)
material_name_field = helper_op.outputs.material_names()
solver_id_field = helper_op.outputs.solver_material_ids()
material_ids = material_name_field.scoping.ids
if hasattr(helper_op.outputs, "ply_types"):
string_field = helper_op.outputs.ply_types()
material_ids = string_field.scoping.ids
ply_types = {}
for dpf_mat_id in material_ids:
ply_types[string_field.data[string_field.scoping.index(dpf_mat_id)]] = dpf_mat_id

return ply_types
ply_type_field = helper_op.outputs.ply_types()
else:
raise RuntimeError(
"Ply types are not available in the current server version. "
"Use at least 9.0 (2025 R1 pre0)."
ply_type_field = None

metadata = {}
for dpf_mat_id in material_ids:
metadata[dpf_mat_id] = MaterialMetadata(
dpf_material_id=dpf_mat_id,
material_name=material_name_field.data[
material_name_field.scoping.index(dpf_mat_id)
],
ply_type=(
ply_type_field.data[ply_type_field.scoping.index(dpf_mat_id)]
if ply_type_field
else "unknown"
),
solver_material_id=solver_id_field.data[solver_id_field.scoping.index(dpf_mat_id)],
)

return metadata

@_deprecated_composite_definition_label
def get_mesh(self, composite_definition_label: Optional[str] = None) -> MeshedRegion:
"""Get the underlying DPF meshed region.
Expand Down
12 changes: 8 additions & 4 deletions src/ansys/dpf/composites/_composite_model_impl_2023r2.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@
get_element_info_provider,
)
from .layup_info.material_operators import MaterialOperators, get_material_operators
from .layup_info.material_properties import MaterialProperty, get_constant_property_dict
from .layup_info.material_properties import (
MaterialMetadata,
MaterialProperty,
get_constant_property_dict,
)
from .result_definition import FailureMeasureEnum, ResultDefinition, ResultDefinitionScope
from .sampling_point_2023r2 import SamplingPoint2023R2
from .sampling_point_types import SamplingPoint
Expand Down Expand Up @@ -227,10 +231,10 @@ def material_names(self) -> dict[str, int]:
)

@property
def ply_types(self) -> dict[str, int]:
"""Get ply types to DPF material ID map."""
def material_metadata(self) -> dict[int, MaterialMetadata]:
"""DPF Material ID to metadata map. Metadata are for example name and ply type."""
raise NotImplementedError(
"ply_types is not implemented"
"material_metadata is not implemented"
" for this version of DPF. DPF server 9.0 (2025 R1 pre0)"
" or later should be used instead."
)
Expand Down
16 changes: 1 addition & 15 deletions src/ansys/dpf/composites/_composite_model_impl_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,11 @@
from warnings import warn

import ansys.dpf.core as dpf
from ansys.dpf.core import FieldsContainer, Operator
from ansys.dpf.core import FieldsContainer

from .constants import FAILURE_LABEL, REF_SURFACE_NAME, TIME_LABEL, FailureOutput


def _create_material_container_helper_op(material_provider: Operator) -> Operator:
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(material_provider.outputs)
return helper_op


def _deprecated_composite_definition_label(func: Callable[..., Any]) -> Any:
"""Emit a warning when the deprecated ``composite_definition_label`` is used."""
function_arg = "composite_definition_label"
Expand Down
8 changes: 4 additions & 4 deletions src/ansys/dpf/composites/composite_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
from .failure_criteria import CombinedFailureCriterion
from .layup_info import ElementInfo, LayerProperty, LayupModelContextType
from .layup_info.material_operators import MaterialOperators
from .layup_info.material_properties import MaterialProperty
from .layup_info.material_properties import MaterialMetadata, MaterialProperty
from .result_definition import FailureMeasureEnum
from .sampling_point_types import SamplingPoint

Expand Down Expand Up @@ -135,9 +135,9 @@ def material_names(self) -> dict[str, int]:
return self._implementation.material_names

@property
def ply_types(self) -> dict[str, int]:
"""Get ply type to DPF material ID map."""
return self._implementation.ply_types
def material_metadata(self) -> dict[int, MaterialMetadata]:
"""PF material ID to metadata map."""
return self._implementation.material_metadata

def get_mesh(self, composite_definition_label: Optional[str] = None) -> MeshedRegion:
"""Get the underlying DPF meshed region.
Expand Down
21 changes: 21 additions & 0 deletions src/ansys/dpf/composites/layup_info/material_operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

from ansys.dpf.core import DataSources, Operator

from ansys.dpf.composites.server_helpers import version_equal_or_later

__all__ = ("MaterialOperators", "get_material_operators")

from ansys.dpf.composites.unit_system import UnitSystemProvider
Expand Down Expand Up @@ -61,6 +63,14 @@ def __init__(
self._material_support_provider = material_support_provider
self._result_info_provider = result_info_provider

if version_equal_or_later(self._material_provider._server, "7.1"):
self._material_container_helper_op = Operator("composite::materials_container_helper")
self._material_container_helper_op.inputs.materials_container(
self._material_provider.outputs
)
else:
self._material_container_helper_op = None

@property
def result_info_provider(self) -> Operator:
"""Get result_info_provider."""
Expand All @@ -83,6 +93,17 @@ def material_provider(self) -> Operator:
"""Get material_provider."""
return self._material_provider

@property
def material_container_helper_op(self) -> Operator:
"""
Get material container helper operator.
This operator can be used to access metadata of the materials.
Return value is None if the server version does not support this operator.
The minimum version is 2024 R1-pre0 (7.1).
"""
return self._material_container_helper_op


def get_material_operators(
rst_data_source: DataSources,
Expand Down
28 changes: 28 additions & 0 deletions src/ansys/dpf/composites/layup_info/material_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@

"""Helpers to get material properties."""
from collections.abc import Collection
from dataclasses import dataclass
from enum import Enum
from typing import Union, cast

from ansys.dpf.core import DataSources, MeshedRegion, Operator, types
import numpy as np

__all__ = (
"MaterialMetadata",
"MaterialProperty",
"get_constant_property",
"get_all_dpf_material_ids",
Expand Down Expand Up @@ -209,3 +211,29 @@ def get_constant_property_dict(
)
properties[dpf_material_id][material_property] = constant_property
return properties


@dataclass(frozen=True)
class MaterialMetadata:
"""
Material metadata such as name and ply type.
Parameters
----------
dpf_material_id:
Material index in the DPF materials container.
material_name:
Name of the material. Is empty if the name is not available.
ply_type:
Ply type. One of regular, woven, honeycomb_core,
isotropic_homogeneous_core, orthotropic_homogeneous_core,
isotropic, adhesive, undefined. Regular stands for uni-directional.
`unknown` is used of the ply type is not available.
solver_material_id:
Material index of the solver.
"""

dpf_material_id: int = 0
material_name: str = ""
ply_type: str = "unknown"
solver_material_id: int = 0
73 changes: 61 additions & 12 deletions tests/composite_model_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
LayupModelContextType,
get_analysis_ply_index_to_name_map,
)
from ansys.dpf.composites.layup_info.material_properties import MaterialProperty
from ansys.dpf.composites.layup_info.material_properties import MaterialMetadata, MaterialProperty
from ansys.dpf.composites.result_definition import FailureMeasureEnum
from ansys.dpf.composites.server_helpers import version_equal_or_later, version_older_than

Expand Down Expand Up @@ -127,17 +127,66 @@ def test_basic_functionality_of_composite_model(dpf_server, data_files, distribu
for mat_name in ref_material_names:
assert mat_name in mat_names.keys()

if version_equal_or_later(dpf_server, "9.0"):
ref_ply_types = [
"regular",
"woven",
"honeycomb_core",
"undefined",
]
ply_types = composite_model.ply_types
assert len(ply_types) == len(ref_ply_types)
for p_type in ref_ply_types:
assert p_type in ply_types.keys()
metadata = composite_model.material_metadata

if version_equal_or_later(dpf_server, "9.0"):
ref_metadata = {
1: MaterialMetadata(
dpf_material_id=1,
material_name="Honeycomb",
ply_type="honeycomb_core",
solver_material_id=5,
),
2: MaterialMetadata(
dpf_material_id=2,
material_name="Epoxy Carbon UD (230 GPa) Prepreg",
ply_type="regular",
solver_material_id=4,
),
3: MaterialMetadata(
dpf_material_id=3,
material_name="Epoxy Carbon Woven (230 GPa) Wet",
ply_type="woven",
solver_material_id=3,
),
4: MaterialMetadata(
dpf_material_id=4,
material_name="Structural Steel",
ply_type="undefined",
solver_material_id=2,
),
}
else:
ref_metadata = {
1: MaterialMetadata(
dpf_material_id=1,
material_name="Honeycomb",
ply_type="unknown",
solver_material_id=5,
),
2: MaterialMetadata(
dpf_material_id=2,
material_name="Epoxy Carbon UD (230 GPa) Prepreg",
ply_type="unknown",
solver_material_id=4,
),
3: MaterialMetadata(
dpf_material_id=3,
material_name="Epoxy Carbon Woven (230 GPa) Wet",
ply_type="unknown",
solver_material_id=3,
),
4: MaterialMetadata(
dpf_material_id=4,
material_name="Structural Steel",
ply_type="unknown",
solver_material_id=2,
),
}

assert len(metadata) == len(ref_metadata)
for dpf_material_id, ref_data in ref_metadata.items():
assert metadata[dpf_material_id] == ref_data

timer.add("After getting properties")

Expand Down

0 comments on commit c020952

Please sign in to comment.