Skip to content

Commit 1f82dad

Browse files
authored
Add interface layer exposure (#609)
Add exposure for the `InterfaceLayer` object type.
1 parent fbbd5ff commit 1f82dad

File tree

7 files changed

+234
-2
lines changed

7 files changed

+234
-2
lines changed

doc/source/api/tree_objects.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ ACP objects
1616
ElementSet
1717
Fabric
1818
GeometricalSelectionRule
19+
InterfaceLayer
1920
LookUpTable1D
2021
LookUpTable1DColumn
2122
LookUpTable3D

doc/source/index.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,5 +78,4 @@ Limitations
7878

7979
* Only shell workflows are supported, solid models can not yet be defined using PyACP
8080
* FieldDefinitions for variable material properties are not supported
81-
* Butt joint sequences and interface layers are not supported
8281
* Section cuts are not supported

src/ansys/acp/core/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
GeometricalSelectionRuleElementalData,
7777
GeometricalSelectionRuleNodalData,
7878
IgnorableEntity,
79+
InterfaceLayer,
7980
Lamina,
8081
LinkedSelectionRule,
8182
LookUpTable1D,
@@ -189,6 +190,7 @@
189190
"get_dpf_unit_system",
190191
"get_model_tree",
191192
"IgnorableEntity",
193+
"InterfaceLayer",
192194
"Lamina",
193195
"launch_acp",
194196
"LaunchMode",

src/ansys/acp/core/_tree_objects/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
GeometricalSelectionRuleElementalData,
7777
GeometricalSelectionRuleNodalData,
7878
)
79+
from .interface_layer import InterfaceLayer
7980
from .linked_selection_rule import LinkedSelectionRule
8081
from .lookup_table_1d import LookUpTable1D
8182
from .lookup_table_1d_column import LookUpTable1DColumn
@@ -155,6 +156,7 @@
155156
"GeometricalSelectionRuleElementalData",
156157
"GeometricalSelectionRuleNodalData",
157158
"IgnorableEntity",
159+
"InterfaceLayer",
158160
"InterpolationOptions",
159161
"Lamina",
160162
"LinkedSelectionRule",
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# Copyright (C) 2022 - 2024 ANSYS, Inc. and/or its affiliates.
2+
# SPDX-License-Identifier: MIT
3+
#
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
from __future__ import annotations
24+
25+
from collections.abc import Iterable
26+
import dataclasses
27+
28+
from ansys.api.acp.v0 import interface_layer_pb2, interface_layer_pb2_grpc
29+
30+
from .._utils.property_protocols import ReadWriteProperty
31+
from ._grpc_helpers.linked_object_list import (
32+
define_linked_object_list,
33+
define_polymorphic_linked_object_list,
34+
)
35+
from ._grpc_helpers.property_helper import (
36+
grpc_data_property,
37+
grpc_data_property_read_only,
38+
mark_grpc_properties,
39+
)
40+
from ._mesh_data import (
41+
ElementalData,
42+
NodalData,
43+
VectorData,
44+
elemental_data_property,
45+
nodal_data_property,
46+
)
47+
from .base import CreatableTreeObject, IdTreeObject
48+
from .element_set import ElementSet
49+
from .enums import status_type_from_pb
50+
from .object_registry import register
51+
from .oriented_selection_set import OrientedSelectionSet
52+
53+
54+
@dataclasses.dataclass
55+
class InterfaceLayerElementalData(ElementalData):
56+
"""Represents elemental data for a Modeling Ply."""
57+
58+
normal: VectorData | None = None
59+
60+
61+
@dataclasses.dataclass
62+
class InterfaceLayerNodalData(NodalData):
63+
"""Represents nodal data for a Modeling Ply."""
64+
65+
ply_offset: VectorData | None = None
66+
67+
68+
@mark_grpc_properties
69+
@register
70+
class InterfaceLayer(CreatableTreeObject, IdTreeObject):
71+
"""Instantiate an interface layer.
72+
73+
The interface layer is a separation layer in the stacking sequence. It can be
74+
used to analyze the crack growth of existing cracks. They can also be used to
75+
define contacts zones between two layers.
76+
The topology is defined with an interface layer in ACP, while all other fracture
77+
settings need to be specified in the downstream analysis (MAPDL or Mechanical).
78+
79+
Parameters
80+
----------
81+
name :
82+
Name of the interface layer.
83+
global_ply_nr :
84+
Global ply number for the stacking sequence.
85+
active :
86+
Inactive interface layers are ignored in ACP and the downstream analysis.
87+
oriented_selection_sets :
88+
Oriented Selection Set for the expansion of the interface layer.
89+
open_area_sets :
90+
Defines the initial crack of a Virtual Crack Closure Technique (VCCT) layer.
91+
Can contain ``OrientedSelectionSet`` and ``ElementSet`` objects.
92+
"""
93+
94+
__slots__: Iterable[str] = tuple()
95+
_COLLECTION_LABEL = "interface_layers"
96+
_OBJECT_INFO_TYPE = interface_layer_pb2.ObjectInfo
97+
_CREATE_REQUEST_TYPE = interface_layer_pb2.CreateRequest
98+
_SUPPORTED_SINCE = "25.1"
99+
100+
def __init__(
101+
self,
102+
*,
103+
name: str = "InterfaceLayer",
104+
global_ply_nr: int = 0,
105+
active: bool = True,
106+
oriented_selection_sets: Iterable[OrientedSelectionSet] = (),
107+
open_area_sets: Iterable[ElementSet | OrientedSelectionSet] = (),
108+
):
109+
super().__init__(name=name)
110+
self.global_ply_nr = global_ply_nr
111+
self.active = active
112+
self.oriented_selection_sets = oriented_selection_sets
113+
self.open_area_sets = open_area_sets
114+
115+
def _create_stub(self) -> interface_layer_pb2_grpc.ObjectServiceStub:
116+
return interface_layer_pb2_grpc.ObjectServiceStub(self._channel)
117+
118+
status = grpc_data_property_read_only("properties.status", from_protobuf=status_type_from_pb)
119+
global_ply_nr: ReadWriteProperty[int, int] = grpc_data_property("properties.global_ply_nr")
120+
active: ReadWriteProperty[bool, bool] = grpc_data_property("properties.active")
121+
oriented_selection_sets = define_linked_object_list(
122+
"properties.oriented_selection_sets", OrientedSelectionSet
123+
)
124+
open_area_sets = define_polymorphic_linked_object_list(
125+
"properties.open_area_sets", allowed_types=(ElementSet, OrientedSelectionSet)
126+
)
127+
128+
elemental_data = elemental_data_property(InterfaceLayerElementalData)
129+
nodal_data = nodal_data_property(InterfaceLayerNodalData)

src/ansys/acp/core/_tree_objects/modeling_group.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,12 @@
2525
from collections.abc import Iterable
2626
import dataclasses
2727

28-
from ansys.api.acp.v0 import modeling_group_pb2, modeling_group_pb2_grpc, modeling_ply_pb2_grpc
28+
from ansys.api.acp.v0 import (
29+
interface_layer_pb2_grpc,
30+
modeling_group_pb2,
31+
modeling_group_pb2_grpc,
32+
modeling_ply_pb2_grpc,
33+
)
2934

3035
from ._grpc_helpers.mapping import define_create_method, define_mutable_mapping
3136
from ._grpc_helpers.property_helper import mark_grpc_properties
@@ -37,6 +42,7 @@
3742
nodal_data_property,
3843
)
3944
from .base import CreatableTreeObject, IdTreeObject
45+
from .interface_layer import InterfaceLayer
4046
from .modeling_ply import ModelingPly
4147
from .object_registry import register
4248

@@ -86,6 +92,15 @@ def _create_stub(self) -> modeling_group_pb2_grpc.ObjectServiceStub:
8692
module_name=__module__,
8793
)
8894
modeling_plies = define_mutable_mapping(ModelingPly, modeling_ply_pb2_grpc.ObjectServiceStub)
95+
interface_layers = define_mutable_mapping(
96+
InterfaceLayer, interface_layer_pb2_grpc.ObjectServiceStub
97+
)
98+
create_interface_layer = define_create_method(
99+
InterfaceLayer,
100+
func_name="create_interface_layer",
101+
parent_class_name="ModelingGroup",
102+
module_name=__module__,
103+
)
89104

90105
elemental_data = elemental_data_property(ModelingGroupElementalData)
91106
nodal_data = nodal_data_property(ModelingGroupNodalData)
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Copyright (C) 2022 - 2024 ANSYS, Inc. and/or its affiliates.
2+
# SPDX-License-Identifier: MIT
3+
#
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
from packaging.version import parse as parse_version
24+
import pytest
25+
26+
from ansys.acp.core import InterfaceLayer
27+
28+
from .common.tree_object_tester import NoLockedMixin, ObjectPropertiesToTest, TreeObjectTester
29+
30+
31+
@pytest.fixture(autouse=True)
32+
def skip_if_unsupported_version(acp_instance):
33+
if parse_version(acp_instance.server_version) < parse_version(InterfaceLayer._SUPPORTED_SINCE):
34+
pytest.skip("InterfaceLayer is not supported on this version of the server.")
35+
36+
37+
@pytest.fixture
38+
def model(load_model_from_tempfile):
39+
with load_model_from_tempfile() as model:
40+
yield model
41+
42+
43+
@pytest.fixture
44+
def parent_object(model):
45+
return list(model.modeling_groups.values())[0]
46+
47+
48+
@pytest.fixture
49+
def tree_object(parent_object):
50+
return parent_object.create_interface_layer()
51+
52+
53+
class TestInterfaceLayer(NoLockedMixin, TreeObjectTester):
54+
COLLECTION_NAME = "interface_layers"
55+
56+
@staticmethod
57+
@pytest.fixture
58+
def default_properties():
59+
return {
60+
"status": "NOTUPTODATE",
61+
"active": True,
62+
"oriented_selection_sets": [],
63+
"open_area_sets": [],
64+
}
65+
66+
CREATE_METHOD_NAME = "create_interface_layer"
67+
68+
@staticmethod
69+
@pytest.fixture
70+
def object_properties(model):
71+
oriented_selection_sets = [model.create_oriented_selection_set() for _ in range(3)]
72+
open_area_sets = [model.create_oriented_selection_set(), model.create_element_set()]
73+
return ObjectPropertiesToTest(
74+
read_write=[
75+
("name", "Interface layer name"),
76+
("oriented_selection_sets", oriented_selection_sets),
77+
("open_area_sets", open_area_sets),
78+
("active", False),
79+
],
80+
read_only=[
81+
("id", "some_id"),
82+
("status", "UPTODATE"),
83+
],
84+
)

0 commit comments

Comments
 (0)