Skip to content

Commit 4b27080

Browse files
committed
Implement ButtJointSequence objects
1 parent b1927c0 commit 4b27080

File tree

8 files changed

+376
-5
lines changed

8 files changed

+376
-5
lines changed

doc/source/api/linked_object_definitions.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ Linked object definitions
77
:toctree: _autosummary
88

99
FabricWithAngle
10+
Lamina
1011
LinkedSelectionRule
11-
TaperEdge
12+
PrimaryPly
1213
SubShape
13-
Lamina
14+
TaperEdge

doc/source/api/tree_objects.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ ACP objects
88

99
AnalysisPly
1010
BooleanSelectionRule
11+
ButtJointSequence
1112
CADComponent
1213
CADGeometry
1314
CutoffSelectionRule

src/ansys/acp/core/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
BooleanSelectionRule,
4949
BooleanSelectionRuleElementalData,
5050
BooleanSelectionRuleNodalData,
51+
ButtJointSequence,
5152
CADComponent,
5253
CADGeometry,
5354
CutoffMaterialType,
@@ -104,6 +105,7 @@
104105
PlyCutoffType,
105106
PlyGeometryExportFormat,
106107
PlyType,
108+
PrimaryPly,
107109
ProductionPly,
108110
ProductionPlyElementalData,
109111
ProductionPlyNodalData,
@@ -153,6 +155,7 @@
153155
"BooleanSelectionRule",
154156
"BooleanSelectionRuleElementalData",
155157
"BooleanSelectionRuleNodalData",
158+
"ButtJointSequence",
156159
"CADComponent",
157160
"CADGeometry",
158161
"ConnectLaunchConfig",
@@ -221,6 +224,7 @@
221224
"PlyCutoffType",
222225
"PlyGeometryExportFormat",
223226
"PlyType",
227+
"PrimaryPly",
224228
"print_model",
225229
"ProductionPly",
226230
"ProductionPlyElementalData",

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
BooleanSelectionRuleElementalData,
2828
BooleanSelectionRuleNodalData,
2929
)
30+
from .butt_joint_sequence import ButtJointSequence, PrimaryPly
3031
from .cad_component import CADComponent
3132
from .cad_geometry import CADGeometry, TriangleMesh
3233
from .cutoff_selection_rule import (
@@ -126,6 +127,7 @@
126127
"BooleanSelectionRule",
127128
"BooleanSelectionRuleElementalData",
128129
"BooleanSelectionRuleNodalData",
130+
"ButtJointSequence",
129131
"CADComponent",
130132
"CADGeometry",
131133
"CutoffMaterialType",
@@ -184,6 +186,7 @@
184186
"PlyCutoffType",
185187
"PlyGeometryExportFormat",
186188
"PlyType",
189+
"PrimaryPly",
187190
"ProductionPly",
188191
"ProductionPlyElementalData",
189192
"ProductionPlyNodalData",

src/ansys/acp/core/_tree_objects/_grpc_helpers/linked_object_list.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
ValueT = TypeVar("ValueT", bound=CreatableTreeObject)
4242

4343

44-
__all__ = ["LinkedObjectList", "define_linked_object_list"]
44+
__all__ = ["LinkedObjectList", "define_linked_object_list", "define_polymorphic_linked_object_list"]
4545

4646

4747
class LinkedObjectList(ObjectCacheMixin, MutableSequence[ValueT]):
@@ -302,11 +302,19 @@ def setter(self: ValueT, value: list[ChildT]) -> None:
302302

303303

304304
def define_polymorphic_linked_object_list(
305-
attribute_name: str, allowed_types: tuple[Any, ...]
305+
attribute_name: str,
306+
allowed_types: tuple[Any, ...] | None = None,
307+
allowed_types_getter: Callable[[], tuple[Any, ...]] | None = None,
306308
) -> Any:
307309
"""Define a list of linked tree objects with polymorphic types."""
310+
if allowed_types is None != allowed_types_getter is None:
311+
raise ValueError("Exactly one of allowed_types and allowed_types_getter must be provided.")
308312

309313
def getter(self: ValueT) -> LinkedObjectList[Any]:
314+
nonlocal allowed_types
315+
if allowed_types_getter is not None:
316+
allowed_types = allowed_types_getter()
317+
310318
return LinkedObjectList(
311319
_parent_object=self,
312320
_attribute_name=attribute_name,
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
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 Callable, Iterable, Sequence
26+
from typing import TYPE_CHECKING, Any, Union, cast
27+
28+
from typing_extensions import Self
29+
30+
from ansys.api.acp.v0 import butt_joint_sequence_pb2, butt_joint_sequence_pb2_grpc
31+
32+
from .._utils.property_protocols import ReadWriteProperty
33+
from ._grpc_helpers.edge_property_list import (
34+
GenericEdgePropertyType,
35+
define_add_method,
36+
define_edge_property_list,
37+
)
38+
from ._grpc_helpers.linked_object_list import define_polymorphic_linked_object_list
39+
from ._grpc_helpers.polymorphic_from_pb import tree_object_from_resource_path
40+
from ._grpc_helpers.property_helper import (
41+
_exposed_grpc_property,
42+
grpc_data_property,
43+
grpc_data_property_read_only,
44+
mark_grpc_properties,
45+
)
46+
from .base import CreatableTreeObject, IdTreeObject
47+
from .enums import status_type_from_pb
48+
from .modeling_ply import ModelingPly
49+
from .object_registry import register
50+
51+
if TYPE_CHECKING:
52+
# Creates a circular import if imported at the top-level, since the ButtJointSequence
53+
# is a direct child of the ModelingGroup.
54+
from .modeling_group import ModelingGroup
55+
56+
__all__ = ["ButtJointSequence", "PrimaryPly"]
57+
58+
59+
@mark_grpc_properties
60+
class PrimaryPly(GenericEdgePropertyType):
61+
"""Defines a primary ply of a butt joint sequence.
62+
63+
Parameters
64+
----------
65+
sequence :
66+
Modeling group or modeling ply defining the primary ply.
67+
level :
68+
Level of the primary ply. Plies with a higher level inherit the thickness
69+
from adjacent plies with a lower level.
70+
71+
"""
72+
73+
_SUPPORTED_SINCE = "25.1"
74+
75+
def __init__(self, sequence: ModelingGroup | ModelingPly, level: int = 1):
76+
self._callback_apply_changes: Callable[[], None] | None = None
77+
self.sequence = sequence
78+
self.level = level
79+
80+
@_exposed_grpc_property
81+
def sequence(self) -> ModelingGroup | ModelingPly:
82+
"""Linked sequence."""
83+
return self._sequence
84+
85+
@sequence.setter
86+
def sequence(self, value: ModelingGroup | ModelingPly) -> None:
87+
from .modeling_group import ModelingGroup
88+
89+
if not isinstance(value, (ModelingGroup, ModelingPly)):
90+
raise TypeError(f"Expected a ModelingGroup or ModelingPly, got {type(value)}")
91+
self._sequence = value
92+
if self._callback_apply_changes:
93+
self._callback_apply_changes()
94+
95+
@_exposed_grpc_property
96+
def level(self) -> int:
97+
"""Level of the primary ply.
98+
99+
Plies with a higher level inherit the thickness from adjacent plies with a lower level.
100+
"""
101+
return self._level
102+
103+
@level.setter
104+
def level(self, value: int) -> None:
105+
self._level = value
106+
if self._callback_apply_changes:
107+
self._callback_apply_changes()
108+
109+
def _set_callback_apply_changes(self, callback_apply_changes: Callable[[], None]) -> None:
110+
self._callback_apply_changes = callback_apply_changes
111+
112+
@classmethod
113+
def _from_pb_object(
114+
cls,
115+
parent_object: CreatableTreeObject,
116+
message: butt_joint_sequence_pb2.PrimaryPly,
117+
apply_changes: Callable[[], None],
118+
) -> Self:
119+
from .modeling_group import ModelingGroup # imported here to avoid circular import
120+
121+
new_obj = cls(
122+
sequence=cast(
123+
Union["ModelingGroup", ModelingPly],
124+
tree_object_from_resource_path(
125+
message.sequence,
126+
server_wrapper=parent_object._server_wrapper,
127+
allowed_types=(ModelingGroup, ModelingPly),
128+
),
129+
),
130+
level=message.level,
131+
)
132+
new_obj._set_callback_apply_changes(apply_changes)
133+
return new_obj
134+
135+
def _to_pb_object(self) -> butt_joint_sequence_pb2.PrimaryPly:
136+
return butt_joint_sequence_pb2.PrimaryPly(
137+
sequence=self.sequence._resource_path, level=self.level
138+
)
139+
140+
def _check(self) -> bool:
141+
# Check for empty resource paths
142+
return bool(self.sequence._resource_path.value)
143+
144+
def __eq__(self, other: Any) -> bool:
145+
if isinstance(other, self.__class__):
146+
return (
147+
self.sequence._resource_path == other.sequence._resource_path
148+
and self.level == other.level
149+
)
150+
151+
return False
152+
153+
def __repr__(self) -> str:
154+
return f"PrimaryPly(sequence={self.sequence.__repr__()}, level={self.level})"
155+
156+
def clone(self) -> Self:
157+
"""Create a new unstored PrimaryPly with the same properties."""
158+
return type(self)(sequence=self.sequence, level=self.level)
159+
160+
161+
def _get_allowed_secondary_ply_types() -> tuple[type, ...]:
162+
from .modeling_group import ModelingGroup
163+
164+
return (ModelingGroup, ModelingPly)
165+
166+
167+
@mark_grpc_properties
168+
@register
169+
class ButtJointSequence(CreatableTreeObject, IdTreeObject):
170+
"""Instantiate a ButtJointSequence.
171+
172+
Parameters
173+
----------
174+
name :
175+
Name of the butt joint sequence.
176+
primary_plies :
177+
Primary plies are the source of a butt joint and they pass the thickness to
178+
adjacent plies. Plies with a higher level inherit the thickness from those
179+
with a lower level.
180+
secondary_plies :
181+
Secondary plies are butt-joined to adjacent primary plies and they inherit
182+
the thickness.
183+
184+
"""
185+
186+
__slots__: Iterable[str] = tuple()
187+
188+
_COLLECTION_LABEL = "butt_joint_sequences"
189+
_OBJECT_INFO_TYPE = butt_joint_sequence_pb2.ObjectInfo
190+
_CREATE_REQUEST_TYPE = butt_joint_sequence_pb2.CreateRequest
191+
_SUPPORTED_SINCE = "25.1"
192+
193+
def __init__(
194+
self,
195+
*,
196+
name: str = "ButtJointSequence",
197+
active: bool = True,
198+
global_ply_nr: int = 0,
199+
primary_plies: Sequence[PrimaryPly] = (),
200+
secondary_plies: Sequence[ModelingGroup | ModelingPly] = (),
201+
):
202+
super().__init__(name=name)
203+
self.active = active
204+
self.global_ply_nr = global_ply_nr
205+
self.primary_plies = primary_plies
206+
self.secondary_plies = secondary_plies
207+
208+
def _create_stub(self) -> butt_joint_sequence_pb2_grpc.ObjectServiceStub:
209+
return butt_joint_sequence_pb2_grpc.ObjectServiceStub(self._channel)
210+
211+
status = grpc_data_property_read_only("properties.status", from_protobuf=status_type_from_pb)
212+
active: ReadWriteProperty[bool, bool] = grpc_data_property("properties.active")
213+
global_ply_nr: ReadWriteProperty[int, int] = grpc_data_property("properties.global_ply_nr")
214+
215+
primary_plies = define_edge_property_list("properties.primary_plies", PrimaryPly)
216+
add_primary_ply = define_add_method(
217+
PrimaryPly,
218+
attribute_name="primary_plies",
219+
func_name="add_primary_ply",
220+
parent_class_name="ButtJointSequence",
221+
module_name=__module__,
222+
)
223+
224+
secondary_plies = define_polymorphic_linked_object_list(
225+
"properties.secondary_plies", allowed_types_getter=_get_allowed_secondary_ply_types
226+
)

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

Lines changed: 17 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+
butt_joint_sequence_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 .butt_joint_sequence import ButtJointSequence
4046
from .modeling_ply import ModelingPly
4147
from .object_registry import register
4248

@@ -86,5 +92,15 @@ def _create_stub(self) -> modeling_group_pb2_grpc.ObjectServiceStub:
8692
)
8793
modeling_plies = define_mutable_mapping(ModelingPly, modeling_ply_pb2_grpc.ObjectServiceStub)
8894

95+
create_butt_joint_sequence = define_create_method(
96+
ButtJointSequence,
97+
func_name="create_butt_joint_sequence",
98+
parent_class_name="ModelingGroup",
99+
module_name=__module__,
100+
)
101+
butt_joint_sequences = define_mutable_mapping(
102+
ButtJointSequence, butt_joint_sequence_pb2_grpc.ObjectServiceStub
103+
)
104+
89105
elemental_data = elemental_data_property(ModelingGroupElementalData)
90106
nodal_data = nodal_data_property(ModelingGroupNodalData)

0 commit comments

Comments
 (0)